Mercurial > dive4elements > river
diff flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Recommendations.java @ 3468:f37e7e8907cb
merged flys-artifacts/2.8.1
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:39 +0200 |
parents | 2b3c4abe034f |
children | cbd0fafcb26b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/datacage/Recommendations.java Fri Sep 28 12:14:39 2012 +0200 @@ -0,0 +1,306 @@ +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.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.SessionHolder; + +import de.intevation.artifactdatabase.data.StateData; + +import de.intevation.flys.artifacts.datacage.templating.Builder; + + +/** + * Also accessible as Singleton with getInstance(). + */ +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_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); + } + } + + 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. + */ + 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 session + ) { + session.doWork(new Work() { + @Override + public void execute(Connection systemConnection) + throws SQLException + { + List<Builder.NamedConnection> connections = + new ArrayList<Builder.NamedConnection>(2); + + Connection userConnection = userId != null + ? DBConfig + .getInstance() + .getDBConnection() + .getDataSource() + .getConnection() + : null; + + try { + if (userConnection != null) { + connections.add(new Builder.NamedConnection( + Builder.CONNECTION_USER, userConnection, false)); + } + + connections.add(new Builder.NamedConnection( + Builder.CONNECTION_SYSTEM, systemConnection, true)); + + 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 :