view flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Recommendations.java @ 1043:9c0f981cd22d

Datacage user template: Removed state filter because it was broken. Simplified by joining two contexts. flys-artifacts/trunk@2504 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Thu, 18 Aug 2011 14:13:35 +0000
parents c586b6220f35
children 0a5eff5511b1
line wrap: on
line source
package de.intevation.flys.artifacts.datacage;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

import java.io.InputStream;
import java.io.IOException;
import java.io.File;

import java.io.FileInputStream;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.log4j.Logger;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import org.hibernate.Session;

import org.hibernate.jdbc.Work;

import de.intevation.artifacts.common.utils.Config;
import de.intevation.artifacts.common.utils.XMLUtils;

import de.intevation.flys.artifacts.FLYSArtifact;

import de.intevation.flys.backend.SessionHolder;

import de.intevation.artifactdatabase.data.StateData;

import de.intevation.flys.artifacts.datacage.templating.Builder;

public class Recommendations
{
    private static Logger log = Logger.getLogger(Recommendations.class);

    private static final boolean DEVELOPMENT_MODE =
        Boolean.getBoolean("flys.datacage.recommendations.development");

    public static final String XPATH_SYSTEM_TEMPLATE =
        "/artifact-database/metadata/system/@template";

    public static final String XPATH_USER_TEMPLATE =
        "/artifact-database/metadata/user/@template";

    private static Recommendations INSTANCE;

    public static class BuilderProvider
    {
        protected Builder builder;

        public BuilderProvider() {
        }

        public BuilderProvider(Builder builder) {
            this.builder = builder;
        }

        public Builder getBuilder() {
            return builder;
        }
    } // class BuilderProvider

    public static class FileBuilderProvider
    extends             BuilderProvider
    {
        protected File file;
        protected long lastModified;

        public FileBuilderProvider() {
        }

        public FileBuilderProvider(File file) {
            this.file    = file;
            lastModified = Long.MIN_VALUE;
        }

        @Override
        public synchronized Builder getBuilder() {
            long modified = file.lastModified();
            if (modified > lastModified) {
                lastModified = modified;
                try {
                    Document template = loadTemplate(file);
                    builder = new Builder(template);
                }
                catch (IOException ioe) {
                    log.error(ioe);
                }
            }
            return builder;
        }

        public BuilderProvider toStaticProvider() {
            return new BuilderProvider(builder);
        }
    } // class BuilderProvider

    protected BuilderProvider systemBuilderProvider;
    protected BuilderProvider userBuilderProvider;

    public Recommendations() {
    }

    public Recommendations(
        BuilderProvider systemBuilderProvider,
        BuilderProvider userBuilderProvider) {
        this.systemBuilderProvider = systemBuilderProvider;
        this.userBuilderProvider   = userBuilderProvider;
    }

    public Builder getUserBuilder() {
        return userBuilderProvider.getBuilder();
    }

    public Builder getSystemBuilder() {
        return systemBuilderProvider.getBuilder();
    }

    protected static void artifactToParameters(
        FLYSArtifact        artifact, 
        Map<String, Object> parameters
    ) {
        parameters.put("current-state-id", artifact.getCurrentStateId());
        parameters.put("artifact-id",      artifact.identifier());

        for (StateData sd: artifact.getAllData()) {
            Object value = sd.getValue();
            if (value == null) {
                continue;
            }
            String key = sd.getName().replace('.', '-');
            parameters.put(key, value);
        }
    }

    public void  recommend(
        FLYSArtifact        artifact,
        String              userId,
        String []           outs,
        Map<String, Object> extraParameters,
        Node                result
    ) {
        Map<String, Object> parameters = new HashMap<String, Object>();

        if (extraParameters != null) {
            parameters.putAll(extraParameters);
        }

        if (userId != null) {
            parameters.put("user-id", userId);
        }

        if (artifact != null) {
            artifactToParameters(artifact, parameters);
        }

        parameters.put("artifact-outs", outs);

        parameters.put("parameters", parameters);

        recommend(parameters, userId, result);
    }

    public void recommend(
        Map<String, Object> parameters,
        String              userId,
        Node                result
    ) {
        recommend(parameters, userId, result, SessionHolder.HOLDER.get());
    }

    public void recommend(
        final Map<String, Object> parameters,
        final String              userId,
        final Node                result,
        Session                   session
    ) {
        session.doWork(new Work() {
            @Override
            public void execute(Connection systemConnection)
            throws SQLException
            {
                List<Builder.NamedConnection> connections =
                    new ArrayList<Builder.NamedConnection>(2);

                if (userId != null) { // Use system and user templates.
                    // Get connection to datacage db.
                    DataSource dataSource = DBConfig
                        .getInstance()
                        .getDBConnection()
                        .getDataSource();

                    Connection userConnection = dataSource.getConnection();
                    try {
                        connections.add(new Builder.NamedConnection(
                            Builder.CONNECTION_USER, userConnection, false));

                        connections.add(new Builder.NamedConnection(
                            Builder.CONNECTION_SYSTEM, systemConnection, true));

                        getUserBuilder().build(connections, result, parameters);
                    }
                    finally {
                        userConnection.close();
                    }
                }
                else { // Use system template only.
                    connections.add(new Builder.NamedConnection(
                        Builder.CONNECTION_SYSTEM, systemConnection, true));

                    getSystemBuilder().build(connections, result, parameters);
                }
            }
        });
    }

    public static synchronized Recommendations getInstance() {
        if (INSTANCE == null) {
            INSTANCE = createRecommendations();
        }
        return INSTANCE;
    }

    protected static Document loadTemplate(File file) throws IOException {
        InputStream in = null;

        try {
            in = new FileInputStream(file);

            Document template = XMLUtils.parseDocument(in);

            if (template == null) {
                throw new IOException("cannot load template");
            }
            return template;
        }
        finally {
            if (in != null) {
                try {
                    in.close();
                }
                catch (IOException ioe) {
                    log.error(ioe);
                }
            }
        }
    }

    public static Recommendations createRecommendations(
        File systemFile,
        File userFile
    ) {
        log.debug("Recommendations.createBuilder");

        if (!systemFile.isFile() || !systemFile.canRead()) {
            log.error("Cannot open template file '" + systemFile + "'");
            return null;
        }

        if (!userFile.isFile() || !userFile.canRead()) {
            log.error("Cannot open template file '" + userFile + "'");
            return null;
        }

        FileBuilderProvider ufbp = new FileBuilderProvider(userFile);
        FileBuilderProvider sfbp = new FileBuilderProvider(systemFile);

        if (ufbp.getBuilder() == null || sfbp.getBuilder() == null) {
            log.error("failed loading builder");
            return null;
        }

        BuilderProvider ubp;
        BuilderProvider sbp;

        if (DEVELOPMENT_MODE) {
            ubp = ufbp;
            sbp = sfbp;
        }
        else {
            ubp = ufbp.toStaticProvider();
            sbp = sfbp.toStaticProvider();
        }

        return new Recommendations(sbp, ubp);
    }

    protected static Recommendations createRecommendations() {
        log.debug("Recommendations.createRecommendations");

        String systemPath = Config.getStringXPath(XPATH_SYSTEM_TEMPLATE);
        String userPath   = Config.getStringXPath(XPATH_USER_TEMPLATE);

        if (systemPath == null || userPath == null) {
            log.error("no path to template file given");
            return null;
        }

        systemPath = Config.replaceConfigDir(systemPath);
        userPath   = Config.replaceConfigDir(userPath);

        return createRecommendations(
            new File(systemPath),
            new File(userPath));
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org