sascha@1015: package de.intevation.flys.artifacts.datacage; sascha@1015: sascha@1015: import java.util.Map; sascha@1015: import java.util.HashMap; sascha@1015: import java.util.List; sascha@1015: import java.util.ArrayList; sascha@1015: sascha@1015: import java.io.InputStream; sascha@1015: import java.io.IOException; sascha@1015: import java.io.File; sascha@1015: sascha@1015: import java.io.FileInputStream; sascha@1015: sascha@1015: import java.sql.Connection; sascha@1015: import java.sql.SQLException; sascha@1015: sascha@1015: import org.apache.log4j.Logger; sascha@1015: sascha@1015: import org.w3c.dom.Document; sascha@1015: import org.w3c.dom.Node; sascha@1015: sascha@1015: import org.hibernate.Session; sascha@1015: sascha@1015: import org.hibernate.jdbc.Work; sascha@1015: sascha@1015: import de.intevation.artifacts.common.utils.Config; sascha@1015: import de.intevation.artifacts.common.utils.XMLUtils; sascha@1716: import de.intevation.artifacts.common.utils.StringUtils; sascha@1015: sascha@1015: import de.intevation.flys.artifacts.FLYSArtifact; sascha@1015: teichmann@5531: import de.intevation.flys.backend.SedDBSessionHolder; sascha@1015: import de.intevation.flys.backend.SessionHolder; sascha@1015: sascha@1015: import de.intevation.artifactdatabase.data.StateData; sascha@1015: sascha@1015: import de.intevation.flys.artifacts.datacage.templating.Builder; sascha@1015: felix@3391: felix@3391: /** felix@3391: * Also accessible as Singleton with getInstance(). felix@3391: */ sascha@1015: public class Recommendations sascha@1015: { teichmann@5531: public static final String CONNECTION_USER = "user"; teichmann@5531: public static final String CONNECTION_SYSTEM = "system"; teichmann@5531: public static final String CONNECTION_SEDDB = "seddb"; teichmann@5531: teichmann@5531: public static final String DEFAULT_CONNECTION_NAME = CONNECTION_SYSTEM; teichmann@5531: sascha@1015: private static Logger log = Logger.getLogger(Recommendations.class); sascha@1015: sascha@1030: private static final boolean DEVELOPMENT_MODE = sascha@1030: Boolean.getBoolean("flys.datacage.recommendations.development"); sascha@1030: sascha@1046: public static final String XPATH_TEMPLATE = sascha@1046: "/artifact-database/metadata/template/text()"; sascha@1015: sascha@1046: public static final String DEFAULT_TEMPLATE_PATH = sascha@1046: "${artifacts.config.dir}/meta-data.xml"; sascha@1015: sascha@1015: private static Recommendations INSTANCE; sascha@1015: sascha@1030: public static class BuilderProvider sascha@1030: { sascha@1030: protected Builder builder; sascha@1030: sascha@1030: public BuilderProvider() { sascha@1030: } sascha@1030: sascha@1030: public BuilderProvider(Builder builder) { sascha@1030: this.builder = builder; sascha@1030: } sascha@1030: sascha@1030: public Builder getBuilder() { sascha@1030: return builder; sascha@1030: } sascha@1030: } // class BuilderProvider sascha@1030: sascha@1030: public static class FileBuilderProvider sascha@1030: extends BuilderProvider sascha@1030: { sascha@1030: protected File file; sascha@1030: protected long lastModified; sascha@1030: sascha@1030: public FileBuilderProvider() { sascha@1030: } sascha@1030: sascha@1030: public FileBuilderProvider(File file) { sascha@1030: this.file = file; sascha@1030: lastModified = Long.MIN_VALUE; sascha@1030: } sascha@1030: sascha@1030: @Override sascha@1030: public synchronized Builder getBuilder() { sascha@1030: long modified = file.lastModified(); sascha@1030: if (modified > lastModified) { sascha@1030: lastModified = modified; sascha@1030: try { sascha@1030: Document template = loadTemplate(file); sascha@1030: builder = new Builder(template); sascha@1030: } sascha@1030: catch (IOException ioe) { sascha@1030: log.error(ioe); sascha@1030: } sascha@1030: } sascha@1030: return builder; sascha@1030: } sascha@1030: sascha@1030: public BuilderProvider toStaticProvider() { sascha@1030: return new BuilderProvider(builder); sascha@1030: } sascha@1030: } // class BuilderProvider sascha@1030: sascha@1046: protected BuilderProvider builderProvider; sascha@1015: sascha@1015: public Recommendations() { sascha@1015: } sascha@1015: sascha@1046: public Recommendations(BuilderProvider builderProvider) { sascha@1046: this.builderProvider = builderProvider; sascha@1015: } sascha@1015: sascha@1046: public Builder getBuilder() { sascha@1046: return builderProvider.getBuilder(); sascha@1015: } sascha@1015: sascha@1015: protected static void artifactToParameters( sascha@3076: FLYSArtifact artifact, sascha@1015: Map parameters sascha@1015: ) { sascha@1716: parameters.put("CURRENT-STATE-ID", artifact.getCurrentStateId()); sascha@1716: parameters.put("ARTIFACT-ID", artifact.identifier()); sascha@1015: sascha@1015: for (StateData sd: artifact.getAllData()) { sascha@1015: Object value = sd.getValue(); sascha@1015: if (value == null) { sascha@1015: continue; sascha@1015: } sascha@1716: String key = sd.getName().replace('.', '-').toUpperCase(); sascha@1015: parameters.put(key, value); sascha@1015: } sascha@1015: } sascha@1015: felix@4528: felix@4528: /** felix@4528: * Put Key/Values from \param src to \param dst, but uppercase felix@4528: * both Keys and Values. felix@4528: */ sascha@1716: public static void convertKeysToUpperCase( sascha@1716: Map src, sascha@1716: Map dst sascha@1716: ) { sascha@1716: for (Map.Entry entry: src.entrySet()) { sascha@1716: dst.put(entry.getKey().toUpperCase(), entry.getValue()); sascha@1716: } sascha@1716: } sascha@1716: felix@3391: felix@3391: /** felix@3391: * Append recommendations to \param result. felix@4528: * @param extraParameters parameters (typicall example: 'recommended') felix@3391: */ sascha@1015: public void recommend( sascha@1015: FLYSArtifact artifact, sascha@1015: String userId, sascha@1015: String [] outs, sascha@1015: Map extraParameters, sascha@1015: Node result sascha@1015: ) { sascha@1015: Map parameters = new HashMap(); sascha@1015: sascha@1015: if (extraParameters != null) { sascha@1716: convertKeysToUpperCase(extraParameters, parameters); sascha@1015: } sascha@1015: sascha@1015: if (userId != null) { sascha@1716: parameters.put("USER-ID", userId); sascha@1015: } sascha@1015: sascha@1015: if (artifact != null) { sascha@1015: artifactToParameters(artifact, parameters); sascha@1015: } sascha@1015: sascha@1716: parameters.put("ARTIFACT-OUTS", StringUtils.toUpperCase(outs)); sascha@1015: sascha@1716: parameters.put("PARAMETERS", parameters); sascha@1015: sascha@1015: recommend(parameters, userId, result); sascha@1015: } sascha@1015: felix@3391: felix@3391: /** felix@3391: * Append recommendations to \param result. felix@3391: */ sascha@1015: public void recommend( sascha@1015: Map parameters, sascha@1015: String userId, sascha@1015: Node result sascha@1015: ) { sascha@1015: recommend(parameters, userId, result, SessionHolder.HOLDER.get()); sascha@1015: } sascha@1015: sascha@1015: public void recommend( sascha@1015: final Map parameters, sascha@1015: final String userId, sascha@1015: final Node result, teichmann@5531: Session systemSession sascha@1015: ) { teichmann@5531: systemSession.doWork(new Work() { sascha@1015: @Override teichmann@5531: public void execute(final Connection systemConnection) sascha@1015: throws SQLException sascha@1015: { teichmann@5531: SedDBSessionHolder.HOLDER.get().doWork(new Work() { teichmann@5531: @Override teichmann@5531: public void execute(Connection sedDBConnection) teichmann@5531: throws SQLException teichmann@5531: { teichmann@5531: recommend( teichmann@5531: parameters, userId, result, teichmann@5531: systemConnection, teichmann@5531: sedDBConnection); sascha@1046: } teichmann@5531: }); sascha@1015: } sascha@1015: }); sascha@1015: } sascha@1015: teichmann@5531: public void recommend( teichmann@5531: Map parameters, teichmann@5531: String userId, teichmann@5531: Node result, teichmann@5531: Connection systemConnection, teichmann@5531: Connection seddbConnection teichmann@5531: ) throws SQLException teichmann@5531: { teichmann@5531: List connections = teichmann@5531: new ArrayList(3); teichmann@5531: teichmann@5531: Connection userConnection = userId != null teichmann@5531: ? DBConfig teichmann@5531: .getInstance() teichmann@5531: .getDBConnection() teichmann@5531: .getDataSource() teichmann@5531: .getConnection() teichmann@5531: : null; teichmann@5531: teichmann@5531: try { teichmann@5531: connections.add(new Builder.NamedConnection( teichmann@5531: CONNECTION_SYSTEM, systemConnection, true)); teichmann@5531: teichmann@5531: connections.add(new Builder.NamedConnection( teichmann@5531: CONNECTION_SEDDB, seddbConnection, true)); teichmann@5531: teichmann@5531: if (userConnection != null) { teichmann@5531: connections.add(new Builder.NamedConnection( teichmann@5531: CONNECTION_USER, userConnection, false)); teichmann@5531: } teichmann@5531: teichmann@5531: teichmann@5531: getBuilder().build(connections, result, parameters); teichmann@5531: } teichmann@5531: finally { teichmann@5531: if (userConnection != null) { teichmann@5531: userConnection.close(); teichmann@5531: } teichmann@5531: } teichmann@5531: } felix@3391: felix@3391: /** Get singleton instance. */ sascha@1015: public static synchronized Recommendations getInstance() { sascha@1015: if (INSTANCE == null) { sascha@1015: INSTANCE = createRecommendations(); sascha@1015: } sascha@1015: return INSTANCE; sascha@1015: } sascha@1015: felix@3391: sascha@1015: protected static Document loadTemplate(File file) throws IOException { sascha@1015: InputStream in = null; sascha@1015: sascha@1015: try { sascha@1015: in = new FileInputStream(file); sascha@1015: sascha@1015: Document template = XMLUtils.parseDocument(in); sascha@1015: sascha@1015: if (template == null) { sascha@1015: throw new IOException("cannot load template"); sascha@1015: } sascha@1015: return template; sascha@1015: } sascha@1015: finally { sascha@1015: if (in != null) { sascha@1015: try { sascha@1015: in.close(); sascha@1015: } sascha@1015: catch (IOException ioe) { sascha@1015: log.error(ioe); sascha@1015: } sascha@1015: } sascha@1015: } sascha@1015: } sascha@1015: sascha@1046: public static Recommendations createRecommendations(File file) { sascha@1015: log.debug("Recommendations.createBuilder"); sascha@1015: sascha@1046: if (!file.isFile() || !file.canRead()) { sascha@1046: log.error("Cannot open template file '" + file + "'"); sascha@1015: return null; sascha@1015: } sascha@1015: sascha@1046: FileBuilderProvider fbp = new FileBuilderProvider(file); sascha@1015: sascha@1046: if (fbp.getBuilder() == null) { sascha@1030: log.error("failed loading builder"); sascha@1015: return null; sascha@1015: } sascha@1030: sascha@1046: BuilderProvider bp = DEVELOPMENT_MODE sascha@1046: ? fbp sascha@1046: : fbp.toStaticProvider(); sascha@1030: sascha@1046: return new Recommendations(bp); sascha@1015: } sascha@1015: sascha@1015: protected static Recommendations createRecommendations() { sascha@1015: log.debug("Recommendations.createRecommendations"); sascha@1015: sascha@1046: String path = Config.getStringXPath(XPATH_TEMPLATE); sascha@1015: sascha@1046: if (path == null) { sascha@1046: path = DEFAULT_TEMPLATE_PATH; sascha@1015: } sascha@1015: sascha@1046: path = Config.replaceConfigDir(path); sascha@1015: sascha@1046: log.info("Meta data template: " + path); sascha@1046: sascha@1046: return createRecommendations(new File(path)); sascha@1015: } sascha@1015: } sascha@1015: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :