teichmann@5831: package org.dive4elements.river.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; teichmann@5590: import org.hibernate.SessionFactory; sascha@1015: sascha@1015: import org.hibernate.jdbc.Work; sascha@1015: teichmann@5831: import org.dive4elements.artifacts.common.utils.Config; teichmann@5831: import org.dive4elements.artifacts.common.utils.XMLUtils; teichmann@5831: import org.dive4elements.artifacts.common.utils.StringUtils; sascha@1015: teichmann@5831: import org.dive4elements.river.artifacts.FLYSArtifact; sascha@1015: teichmann@5831: import org.dive4elements.river.backend.SessionFactoryProvider; teichmann@5831: import org.dive4elements.river.backend.SessionHolder; sascha@1015: teichmann@5831: import org.dive4elements.artifactdatabase.data.StateData; teichmann@5831: teichmann@5831: import org.dive4elements.river.artifacts.datacage.templating.Builder; teichmann@5831: import org.dive4elements.river.artifacts.datacage.templating.BuilderPool; 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: teichmann@5779: public static class BuilderPoolProvider sascha@1030: { teichmann@5779: protected BuilderPool builderPool; sascha@1030: teichmann@5779: public BuilderPoolProvider() { sascha@1030: } sascha@1030: teichmann@5779: public BuilderPoolProvider(BuilderPool builderPool) { teichmann@5779: this.builderPool = builderPool; sascha@1030: } sascha@1030: teichmann@5779: public BuilderPool getBuilderPool() { teichmann@5779: return builderPool; sascha@1030: } sascha@1030: } // class BuilderProvider sascha@1030: teichmann@5779: public static class FileBuilderPoolProvider teichmann@5779: extends BuilderPoolProvider sascha@1030: { sascha@1030: protected File file; sascha@1030: protected long lastModified; sascha@1030: teichmann@5779: public FileBuilderPoolProvider() { sascha@1030: } sascha@1030: teichmann@5779: public FileBuilderPoolProvider(File file) { sascha@1030: this.file = file; sascha@1030: lastModified = Long.MIN_VALUE; sascha@1030: } sascha@1030: sascha@1030: @Override teichmann@5779: public synchronized BuilderPool getBuilderPool() { sascha@1030: long modified = file.lastModified(); sascha@1030: if (modified > lastModified) { sascha@1030: lastModified = modified; sascha@1030: try { sascha@1030: Document template = loadTemplate(file); teichmann@5779: builderPool = new BuilderPool(template); sascha@1030: } sascha@1030: catch (IOException ioe) { sascha@1030: log.error(ioe); sascha@1030: } sascha@1030: } teichmann@5779: return builderPool; sascha@1030: } sascha@1030: teichmann@5779: public BuilderPoolProvider toStaticProvider() { teichmann@5779: return new BuilderPoolProvider(builderPool); sascha@1030: } sascha@1030: } // class BuilderProvider sascha@1030: teichmann@5779: protected BuilderPoolProvider builderPoolProvider; sascha@1015: sascha@1015: public Recommendations() { sascha@1015: } sascha@1015: teichmann@5779: public Recommendations(BuilderPoolProvider builderPoolProvider) { teichmann@5779: this.builderPoolProvider = builderPoolProvider; sascha@1015: } sascha@1015: teichmann@5779: public BuilderPool getBuilderPool() { teichmann@5779: return builderPoolProvider.getBuilderPool(); 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: * 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@5590: SessionFactory sedDBFactory = teichmann@5590: SessionFactoryProvider.getSedDBSessionFactory(); teichmann@5590: teichmann@5590: Session sedDBSession = sedDBFactory.openSession(); teichmann@5590: try { teichmann@5590: sedDBSession.doWork(new Work() { teichmann@5590: @Override teichmann@5590: public void execute(Connection sedDBConnection) teichmann@5590: throws SQLException teichmann@5590: { teichmann@5590: recommend( teichmann@5590: parameters, userId, result, teichmann@5590: systemConnection, teichmann@5590: sedDBConnection); teichmann@5590: } teichmann@5590: }); teichmann@5590: } teichmann@5590: finally { teichmann@5590: sedDBSession.close(); teichmann@5590: } 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@5588: if (seddbConnection != null) { teichmann@5588: connections.add(new Builder.NamedConnection( teichmann@5588: CONNECTION_SEDDB, seddbConnection, true)); teichmann@5588: } 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@5779: getBuilderPool().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 { teichmann@5779: InputStream in = new FileInputStream(file); sascha@1015: sascha@1015: try { sascha@1015: Document template = XMLUtils.parseDocument(in); sascha@1015: if (template == null) { sascha@1015: throw new IOException("cannot load template"); sascha@1015: } sascha@1015: return template; sascha@1015: } sascha@1015: finally { teichmann@5779: in.close(); 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: teichmann@5779: FileBuilderPoolProvider fbp = new FileBuilderPoolProvider(file); sascha@1015: teichmann@5779: if (fbp.getBuilderPool() == null) { sascha@1030: log.error("failed loading builder"); sascha@1015: return null; sascha@1015: } sascha@1030: teichmann@5779: BuilderPoolProvider 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 :