view flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Recommendations.java @ 5627:2d9eb188fa51

Flys Issue 759 write longer strings and explicitly break the lines This makes the dem hover item layout more robust as it works with different string lengths
author Andre Heinecke <aheinecke@intevation.de>
date Wed, 10 Apr 2013 10:25:33 +0200
parents cf4cc385e7c6
children ebec12def170
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 org.apache.log4j.Logger;

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

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import org.hibernate.jdbc.Work;

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

import de.intevation.flys.artifacts.FLYSArtifact;

import de.intevation.flys.backend.SessionFactoryProvider;
import de.intevation.flys.backend.SessionHolder;

import de.intevation.artifactdatabase.data.StateData;

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


/**
 * Also accessible as Singleton with getInstance().
 */
public class Recommendations
{
    public static final String CONNECTION_USER   = "user";
    public static final String CONNECTION_SYSTEM = "system";
    public static final String CONNECTION_SEDDB  = "seddb";

    public static final String DEFAULT_CONNECTION_NAME = CONNECTION_SYSTEM;

    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_TEMPLATE =
        "/artifact-database/metadata/template/text()";

    public static final String DEFAULT_TEMPLATE_PATH =
        "${artifacts.config.dir}/meta-data.xml";

    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 builderProvider;

    public Recommendations() {
    }

    public Recommendations(BuilderProvider builderProvider) {
        this.builderProvider = builderProvider;
    }

    public Builder getBuilder() {
        return builderProvider.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('.', '-').toUpperCase();
            parameters.put(key, value);
        }
    }


    /**
     * Put Key/Values from \param src to \param dst, but uppercase
     * both Keys and Values.
     */
    public static void convertKeysToUpperCase(
        Map<String, Object> src,
        Map<String, Object> dst
    ) {
        for (Map.Entry<String, Object> entry: src.entrySet()) {
            dst.put(entry.getKey().toUpperCase(), entry.getValue());
        }
    }


    /**
     * Append recommendations to \param result.
     * @param extraParameters parameters (typicall example: 'recommended')
     */
    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) {
            convertKeysToUpperCase(extraParameters, parameters);
        }

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

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

        parameters.put("ARTIFACT-OUTS", StringUtils.toUpperCase(outs));

        parameters.put("PARAMETERS", parameters);

        recommend(parameters, userId, result);
    }


    /**
     * Append recommendations to \param 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                   systemSession
    ) {
        systemSession.doWork(new Work() {
            @Override
            public void execute(final Connection systemConnection)
            throws SQLException
            {
                SessionFactory sedDBFactory =
                    SessionFactoryProvider.getSedDBSessionFactory();

                Session sedDBSession = sedDBFactory.openSession();
                try {
                    sedDBSession.doWork(new Work() {
                        @Override
                        public void execute(Connection sedDBConnection)
                        throws SQLException
                        {
                            recommend(
                                parameters, userId, result,
                                systemConnection,
                                sedDBConnection);
                        }
                    });
                }
                finally {
                    sedDBSession.close();
                }
            }
        });
    }

    public void recommend(
        Map<String, Object> parameters,
        String              userId,
        Node                result,
        Connection          systemConnection,
        Connection          seddbConnection
    ) throws SQLException
    {
        List<Builder.NamedConnection> connections =
            new ArrayList<Builder.NamedConnection>(3);

        Connection userConnection = userId != null
            ? DBConfig
                .getInstance()
                .getDBConnection()
                .getDataSource()
                .getConnection()
            : null;

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

            if (seddbConnection != null) {
                connections.add(new Builder.NamedConnection(
                    CONNECTION_SEDDB, seddbConnection, true));
            }

            if (userConnection != null) {
                connections.add(new Builder.NamedConnection(
                    CONNECTION_USER, userConnection, false));
            }


            getBuilder().build(connections, result, parameters);
        }
        finally {
            if (userConnection != null) {
                userConnection.close();
            }
        }
    }

    /** Get singleton instance. */
    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 file) {
        log.debug("Recommendations.createBuilder");

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

        FileBuilderProvider fbp = new FileBuilderProvider(file);

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

        BuilderProvider bp = DEVELOPMENT_MODE
            ? fbp
            : fbp.toStaticProvider();

        return new Recommendations(bp);
    }

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

        String path = Config.getStringXPath(XPATH_TEMPLATE);

        if (path == null) {
            path = DEFAULT_TEMPLATE_PATH;
        }

        path = Config.replaceConfigDir(path);

        log.info("Meta data template: " + path);

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

http://dive4elements.wald.intevation.org