sascha@982: package de.intevation.flys.artifacts.datacage; sascha@982: sascha@990: import java.util.Collection; sascha@991: import java.util.List; sascha@990: sascha@984: import java.sql.SQLException; sascha@991: import java.sql.PreparedStatement; sascha@990: import java.sql.Types; sascha@984: sascha@982: import de.intevation.artifacts.GlobalContext; sascha@982: sascha@983: import de.intevation.artifactdatabase.db.SQL; sascha@983: import de.intevation.artifactdatabase.db.SQLExecutor; sascha@983: sascha@982: import de.intevation.artifactdatabase.LifetimeListener; sascha@982: sascha@990: import de.intevation.artifactdatabase.data.StateData; sascha@990: sascha@991: import de.intevation.artifactdatabase.state.Output; sascha@992: import de.intevation.artifactdatabase.state.Facet; sascha@991: sascha@984: import de.intevation.artifacts.Artifact; sascha@984: import de.intevation.artifacts.ArtifactDatabase; sascha@984: import de.intevation.artifacts.ArtifactDatabaseException; sascha@984: sascha@984: import de.intevation.flys.artifacts.FLYSArtifact; sascha@984: sascha@984: import de.intevation.artifacts.common.utils.LRUCache; sascha@984: sascha@982: import org.apache.log4j.Logger; sascha@982: sascha@982: import org.w3c.dom.Document; sascha@982: sascha@982: public class Datacage sascha@982: implements LifetimeListener sascha@982: { sascha@982: private static Logger log = Logger.getLogger(Datacage.class); sascha@982: sascha@984: public static final String ARTEFACT_DATABASE_KEY = sascha@984: "global.artifact.database"; sascha@984: sascha@987: private String SQL_DELETE_ALL_USERS = "delete.all.users"; sascha@987: private String SQL_USER_ID_NEXTVAL = "user.id.nextval"; sascha@987: private String SQL_USER_BY_GID = "user.by.gid"; sascha@987: private String SQL_INSERT_USER = "insert.user"; sascha@987: private String SQL_COLLECTION_BY_GID = "collection.by.gid"; sascha@987: private String SQL_COLLECTION_ID_NEXTVAL = "collection.id.nextval"; sascha@987: private String SQL_INSERT_COLLECTION = "insert.collection"; sascha@988: private String SQL_ARTIFACT_BY_GID = "artifact.by.gid"; sascha@988: private String SQL_COLLECTION_ITEM_ID_NEXTVAL = sascha@988: "collection.item.id.nextval"; sascha@988: private String SQL_INSERT_COLLECTION_ITEM = "insert.collection.item"; sascha@989: private String SQL_ARTIFACT_ID_NEXTVAL = "artifact.id.nextval"; sascha@989: private String SQL_INSERT_ARTIFACT = "insert.artifact"; sascha@991: private String SQL_ARTIFACT_DATA_ID_NEXTVAL = "artifact.data.id.nextval"; sascha@990: private String SQL_INSERT_ARTIFACT_DATA = "insert.artifact.data"; sascha@991: private String SQL_OUT_ID_NEXTVALUE = "out.id.nextval"; sascha@991: private String SQL_INSERT_OUT = "insert.out"; sascha@992: private String SQL_FACET_ID_NEXTVAL = "facet.id.nextval"; sascha@992: private String SQL_INSERT_FACET = "insert.facet"; sascha@984: sascha@983: protected SQLExecutor sqlExecutor; sascha@983: sascha@984: public class InitialScan sascha@984: implements ArtifactDatabase.ArtifactLoadedCallback sascha@984: { sascha@984: protected LRUCache users; sascha@986: protected LRUCache collections; sascha@988: protected LRUCache artifacts; sascha@984: sascha@991: protected GlobalContext context; sascha@991: sascha@984: public InitialScan() { sascha@986: users = new LRUCache(); sascha@986: collections = new LRUCache(); sascha@988: artifacts = new LRUCache(); sascha@984: } sascha@984: sascha@991: public InitialScan(GlobalContext context) { sascha@991: this(); sascha@991: this.context = context; sascha@991: } sascha@991: sascha@984: @Override sascha@984: public void artifactLoaded( sascha@984: String userId, sascha@984: String collectionId, sascha@984: String artifactId, sascha@984: Artifact artifact sascha@984: ) { sascha@984: if (!(artifact instanceof FLYSArtifact)) { sascha@984: log.warn("ignoring none FLYS artifacts"); sascha@984: return; sascha@984: } sascha@984: sascha@984: FLYSArtifact flysArtifact = (FLYSArtifact)artifact; sascha@986: sascha@986: Integer uId = getUserId(userId); sascha@987: // TODO: We need the name of the collection sascha@987: Integer cId = getCollectionId(collectionId, uId, "XXX"); sascha@987: sascha@988: storeArtifact(artifactId, cId, flysArtifact); sascha@984: } sascha@984: sascha@987: protected Integer getId( sascha@987: LRUCache cache, sascha@987: final String idString, sascha@987: final String selectById sascha@987: ) { sascha@987: Integer id = cache.get(idString); sascha@987: if (id != null) { sascha@987: return id; sascha@986: } sascha@986: sascha@986: final Integer [] res = new Integer[1]; sascha@986: sascha@986: SQLExecutor.Instance exec = sqlExecutor.new Instance() { sascha@986: @Override sascha@986: public boolean doIt() throws SQLException { sascha@987: prepareStatement(selectById); sascha@987: stmnt.setString(1, idString); sascha@986: result = stmnt.executeQuery(); sascha@986: if (!result.next()) { sascha@986: return false; sascha@986: } sascha@986: res[0] = result.getInt(1); sascha@986: return true; sascha@986: } sascha@986: }; sascha@986: sascha@986: if (exec.runRead()) { sascha@987: cache.put(idString, res[0]); sascha@986: return res[0]; sascha@986: } sascha@986: sascha@987: return null; sascha@987: } sascha@987: sascha@988: protected void storeArtifact( sascha@989: final String artifactId, sascha@989: Integer collectionId, sascha@989: final FLYSArtifact artifact sascha@988: ) { sascha@988: Integer aId = getId(artifacts, artifactId, SQL_ARTIFACT_BY_GID); sascha@988: sascha@988: if (aId != null) { sascha@988: // We've already stored it. Just create the collection item. sascha@988: storeCollectionItem(collectionId, aId); sascha@988: return; sascha@988: } sascha@988: // We need to write it to database sascha@989: sascha@989: final Integer [] res = new Integer[1]; sascha@989: sascha@989: SQLExecutor.Instance exec = sqlExecutor.new Instance() { sascha@989: @Override sascha@989: public boolean doIt() throws SQLException { sascha@989: prepareStatement(SQL_ARTIFACT_ID_NEXTVAL); sascha@989: result = stmnt.executeQuery(); sascha@989: if (!result.next()) { sascha@989: return false; sascha@989: } sascha@989: res[0] = result.getInt(1); sascha@989: reset(); sascha@989: prepareStatement(SQL_INSERT_ARTIFACT); sascha@989: stmnt.setInt (1, res[0]); sascha@989: stmnt.setString(2, artifactId); sascha@989: stmnt.setString(3, artifact.getCurrentStateId()); sascha@989: stmnt.execute(); sascha@990: conn.commit(); sascha@989: return true; sascha@989: } sascha@989: }; sascha@989: sascha@989: if (!exec.runWrite()) { sascha@989: log.error("storing of artifact failed."); sascha@989: return; sascha@989: } sascha@989: sascha@989: artifacts.put(artifactId, aId = res[0]); sascha@989: sascha@989: storeCollectionItem(collectionId, aId); sascha@989: sascha@990: storeData(aId, artifact); sascha@990: sascha@991: storeOuts(aId, artifact); sascha@991: } sascha@991: sascha@991: protected void storeOuts( sascha@991: final int artifactId, sascha@991: final FLYSArtifact artifact sascha@991: ) { sascha@991: final List outs = artifact.getCurrentOutputs(context); sascha@991: sascha@991: if (outs.isEmpty()) { sascha@991: return; sascha@991: } sascha@991: sascha@992: final int [] outIds = new int[outs.size()]; sascha@991: sascha@991: SQLExecutor.Instance exec = sqlExecutor.new Instance() { sascha@991: @Override sascha@991: public boolean doIt() throws SQLException { sascha@991: prepareStatement(SQL_OUT_ID_NEXTVALUE); sascha@992: for (int i = 0; i < outIds.length; ++i) { sascha@991: result = stmnt.executeQuery(); sascha@991: if (!result.next()) { sascha@991: log.error("generation of out ids failed"); sascha@991: return false; sascha@991: } sascha@992: outIds[i] = result.getInt(1); sascha@991: result.close(); result = null; sascha@991: } sascha@991: reset(); sascha@991: prepareStatement(SQL_INSERT_OUT); sascha@992: for (int i = 0; i < outIds.length; ++i) { sascha@991: Output out = outs.get(i); sascha@992: stmnt.setInt(1, outIds[i]); sascha@991: stmnt.setInt(2, artifactId); sascha@991: stmnt.setString(3, out.getName()); sascha@991: setString(stmnt, 4, out.getDescription()); sascha@991: setString(stmnt, 5, out.getType()); sascha@991: stmnt.execute(); sascha@991: } sascha@991: conn.commit(); sascha@991: return true; sascha@991: } sascha@991: }; sascha@991: sascha@991: if (!exec.runWrite()) { sascha@992: log.error("storing artifact outs failed"); sascha@992: return; sascha@991: } sascha@991: sascha@992: final int FACETS = numFacets(outs); sascha@992: sascha@992: if (FACETS == 0) { sascha@992: return; sascha@992: } sascha@992: sascha@992: exec = sqlExecutor.new Instance() { sascha@992: @Override sascha@992: public boolean doIt() throws SQLException { sascha@992: int [] facetIds = new int[FACETS]; sascha@992: prepareStatement(SQL_FACET_ID_NEXTVAL); sascha@992: for (int i = 0; i < facetIds.length; ++i) { sascha@992: result = stmnt.executeQuery(); sascha@992: if (!result.next()) { sascha@992: log.error("generation of facet ids failed"); sascha@992: return false; sascha@992: } sascha@992: facetIds[i] = result.getInt(1); sascha@992: result.close(); result = null; sascha@992: } sascha@992: reset(); sascha@992: prepareStatement(SQL_INSERT_FACET); sascha@992: int index = 0; sascha@992: for (int i = 0, N = outs.size(); i < N; ++i) { sascha@992: Output out = outs.get(i); sascha@992: int outId = outIds[i]; sascha@992: for (Facet facet: out.getFacets()) { sascha@992: stmnt.setInt(1, facetIds[index]); sascha@992: stmnt.setInt(2, outId); sascha@992: stmnt.setString(3, facet.getName()); sascha@992: stmnt.setInt(4, facet.getIndex()); sascha@992: stmnt.setString(5, "XXX"); // TODO: handle states sascha@992: setString(stmnt, 6, facet.getDescription()); sascha@992: stmnt.execute(); sascha@992: ++index; sascha@992: } sascha@992: } sascha@992: conn.commit(); sascha@992: return true; sascha@992: } sascha@992: }; sascha@992: sascha@992: if (!exec.runWrite()) { sascha@992: log.error("storing facets failed"); sascha@992: } sascha@988: } sascha@988: sascha@990: protected void storeData( sascha@990: final int artifactId, sascha@990: FLYSArtifact artifact sascha@990: ) { sascha@990: final Collection data = artifact.getAllData(); sascha@990: sascha@990: if (data.isEmpty()) { sascha@990: return; sascha@990: } sascha@990: sascha@990: SQLExecutor.Instance exec = sqlExecutor.new Instance() { sascha@990: @Override sascha@990: public boolean doIt() throws SQLException { sascha@990: int [] ids = new int[data.size()]; sascha@991: prepareStatement(SQL_ARTIFACT_DATA_ID_NEXTVAL); sascha@990: sascha@990: for (int i = 0; i < ids.length; ++i) { sascha@990: result = stmnt.executeQuery(); sascha@990: if (!result.next()) { sascha@990: log.error("generating id for artifact data failed"); sascha@990: return false; sascha@990: } sascha@990: ids[i] = result.getInt(1); sascha@990: result.close(); result = null; sascha@990: } sascha@990: reset(); sascha@990: prepareStatement(SQL_INSERT_ARTIFACT_DATA); sascha@990: sascha@990: int i = 0; sascha@990: for (StateData sd: data) { sascha@990: int id = ids[i++]; sascha@990: stmnt.setInt(1, id); sascha@990: stmnt.setInt(2, artifactId); sascha@995: // XXX: Where come the nulls from? sascha@995: String type = sd.getType(); sascha@995: if (type == null) type = "String"; sascha@995: stmnt.setString(3, type); sascha@990: stmnt.setString(4, sd.getName()); sascha@991: setString(stmnt, 5, sd); sascha@990: stmnt.execute(); sascha@990: } sascha@990: sascha@990: conn.commit(); sascha@990: return true; sascha@990: } sascha@990: }; sascha@990: sascha@990: if (!exec.runWrite()) { sascha@990: log.error("storing artifact data failed"); sascha@990: } sascha@990: } sascha@990: sascha@988: protected void storeCollectionItem( sascha@988: final Integer collectionId, sascha@988: final Integer artifactId sascha@988: ) { sascha@988: SQLExecutor.Instance exec = sqlExecutor.new Instance() { sascha@988: @Override sascha@988: public boolean doIt() throws SQLException { sascha@988: prepareStatement(SQL_COLLECTION_ITEM_ID_NEXTVAL); sascha@988: result = stmnt.executeQuery(); sascha@988: if (!result.next()) { sascha@988: return false; sascha@988: } sascha@988: int ciId = result.getInt(1); sascha@988: reset(); sascha@988: prepareStatement(SQL_INSERT_COLLECTION_ITEM); sascha@988: stmnt.setInt(1, ciId); sascha@988: stmnt.setInt(2, collectionId); sascha@988: stmnt.setInt(3, artifactId); sascha@988: stmnt.execute(); sascha@990: conn.commit(); sascha@988: return true; sascha@988: } sascha@988: }; sascha@988: sascha@988: if (!exec.runWrite()) { sascha@988: log.error("storing of collection item failed."); sascha@988: } sascha@988: } sascha@987: sascha@987: protected Integer getCollectionId( sascha@987: final String collectionId, sascha@987: final Integer ownerId, sascha@987: final String collectionName sascha@987: ) { sascha@987: Integer c = getId(collections, collectionId, SQL_COLLECTION_BY_GID); sascha@987: sascha@987: if (c != null) { sascha@987: return c; sascha@987: } sascha@987: sascha@987: final Integer [] res = new Integer[1]; sascha@987: sascha@987: SQLExecutor.Instance exec = sqlExecutor.new Instance() { sascha@987: @Override sascha@987: public boolean doIt() throws SQLException { sascha@987: prepareStatement(SQL_COLLECTION_ID_NEXTVAL); sascha@987: result = stmnt.executeQuery(); sascha@987: if (!result.next()) { sascha@987: return false; sascha@987: } sascha@987: res[0] = result.getInt(1); sascha@987: reset(); sascha@987: prepareStatement(SQL_INSERT_COLLECTION); sascha@987: stmnt.setInt (1, res[0]); sascha@987: stmnt.setString(2, collectionId); sascha@987: stmnt.setInt (3, ownerId); sascha@987: stmnt.setString(4, collectionName); sascha@987: stmnt.execute(); sascha@990: conn.commit(); sascha@987: return true; sascha@987: } sascha@987: }; sascha@987: sascha@987: if (exec.runWrite()) { sascha@987: collections.put(collectionId, res[0]); sascha@987: return res[0]; sascha@987: } sascha@987: sascha@987: return null; sascha@987: } sascha@987: sascha@987: protected Integer getUserId(final String userId) { sascha@987: sascha@987: Integer u = getId(users, userId, SQL_USER_BY_GID); sascha@987: sascha@987: if (u != null) { sascha@987: return u; sascha@987: } sascha@987: sascha@987: final Integer [] res = new Integer[1]; sascha@987: sascha@987: SQLExecutor.Instance exec = sqlExecutor.new Instance() { sascha@986: @Override sascha@986: public boolean doIt() throws SQLException { sascha@986: prepareStatement(SQL_USER_ID_NEXTVAL); sascha@986: result = stmnt.executeQuery(); sascha@986: if (!result.next()) { sascha@986: return false; sascha@986: } sascha@986: res[0] = result.getInt(1); sascha@986: reset(); sascha@986: prepareStatement(SQL_INSERT_USER); sascha@986: stmnt.setInt (1, res[0]); sascha@986: stmnt.setString(2, userId); sascha@986: stmnt.execute(); sascha@990: conn.commit(); sascha@986: return true; sascha@986: } sascha@986: }; sascha@986: sascha@986: if (exec.runWrite()) { sascha@986: users.put(userId, res[0]); sascha@986: return res[0]; sascha@986: } sascha@986: sascha@986: return null; sascha@986: } sascha@986: sascha@984: public boolean scan(ArtifactDatabase adb) { sascha@993: log.debug("scan"); sascha@984: try { sascha@984: adb.loadAllArtifacts(this); sascha@984: } sascha@984: catch (ArtifactDatabaseException ade) { sascha@984: log.error(ade); sascha@984: return false; sascha@984: } sascha@984: return true; sascha@984: } sascha@984: } // class InitialScan sascha@984: sascha@984: sascha@982: public Datacage() { sascha@982: } sascha@982: sascha@982: @Override sascha@982: public void setup(Document document) { sascha@982: log.debug("setup"); sascha@983: DBConfig config = DBConfig.getInstance(); sascha@983: setupSQL(config.getSQL()); sascha@983: sqlExecutor = new SQLExecutor(config.getDBConnection()); sascha@983: } sascha@983: sascha@983: protected void setupSQL(SQL sql) { sascha@987: SQL_DELETE_ALL_USERS = sql.get(SQL_DELETE_ALL_USERS); sascha@987: SQL_USER_ID_NEXTVAL = sql.get(SQL_USER_ID_NEXTVAL); sascha@987: SQL_USER_BY_GID = sql.get(SQL_USER_BY_GID); sascha@987: SQL_INSERT_USER = sql.get(SQL_INSERT_USER); sascha@987: SQL_COLLECTION_BY_GID = sql.get(SQL_COLLECTION_BY_GID); sascha@987: SQL_COLLECTION_ID_NEXTVAL = sql.get(SQL_COLLECTION_ID_NEXTVAL); sascha@987: SQL_INSERT_COLLECTION = sql.get(SQL_INSERT_COLLECTION); sascha@988: SQL_ARTIFACT_BY_GID = sql.get(SQL_ARTIFACT_BY_GID); sascha@988: SQL_COLLECTION_ITEM_ID_NEXTVAL = sascha@988: sql.get(SQL_COLLECTION_ITEM_ID_NEXTVAL); sascha@988: SQL_INSERT_COLLECTION_ITEM = sascha@988: sql.get(SQL_INSERT_COLLECTION_ITEM); sascha@989: SQL_ARTIFACT_ID_NEXTVAL = sql.get(SQL_ARTIFACT_ID_NEXTVAL); sascha@989: SQL_INSERT_ARTIFACT = sql.get(SQL_INSERT_ARTIFACT); sascha@991: SQL_ARTIFACT_DATA_ID_NEXTVAL = sql.get(SQL_ARTIFACT_DATA_ID_NEXTVAL); sascha@990: SQL_INSERT_ARTIFACT_DATA = sql.get(SQL_INSERT_ARTIFACT_DATA); sascha@991: SQL_OUT_ID_NEXTVALUE = sql.get(SQL_OUT_ID_NEXTVALUE); sascha@991: SQL_INSERT_OUT = sql.get(SQL_INSERT_OUT); sascha@992: SQL_FACET_ID_NEXTVAL = sql.get(SQL_FACET_ID_NEXTVAL); sascha@992: SQL_INSERT_FACET = sql.get(SQL_INSERT_FACET); sascha@991: } sascha@991: sascha@992: protected static final int numFacets(List outs) { sascha@992: int sum = 0; sascha@992: for (Output out: outs) { sascha@992: sum += out.getFacets().size(); sascha@992: } sascha@992: return sum; sascha@992: } sascha@992: sascha@992: protected static final void setString( sascha@991: PreparedStatement stmnt, sascha@991: int index, sascha@991: Object value sascha@991: ) sascha@991: throws SQLException sascha@991: { sascha@991: if (value == null) { sascha@991: stmnt.setNull(index, Types.VARCHAR); sascha@991: } sascha@991: else { sascha@991: stmnt.setString(index, value.toString()); sascha@991: } sascha@982: } sascha@982: sascha@982: @Override sascha@982: public void systemUp(GlobalContext context) { sascha@993: log.debug("systemUp entered"); sascha@984: initialScan(context); sascha@993: log.debug("systemUp leaved"); sascha@982: } sascha@982: sascha@984: protected void initialScan(GlobalContext context) { sascha@984: log.debug("initialScan"); sascha@984: sascha@984: Object adbObject = context.get(ARTEFACT_DATABASE_KEY); sascha@984: sascha@984: if (!(adbObject instanceof ArtifactDatabase)) { sascha@984: log.error("missing artefact database. Cannot scan"); sascha@984: return; sascha@984: } sascha@984: sascha@984: ArtifactDatabase adb = (ArtifactDatabase)adbObject; sascha@984: sascha@984: if (!cleanDatabase()) { sascha@984: log.error("cleaning database failed"); sascha@984: return; sascha@984: } sascha@984: sascha@991: InitialScan is = new InitialScan(context); sascha@984: sascha@984: if (!is.scan(adb)) { sascha@984: log.error("initial scan failed"); sascha@984: return; sascha@984: } sascha@984: sascha@984: } sascha@984: sascha@984: protected boolean cleanDatabase() { sascha@984: sascha@993: log.debug("cleanDatabase"); sascha@993: sascha@993: boolean success = sqlExecutor.new Instance() { sascha@984: @Override sascha@984: public boolean doIt() throws SQLException { sascha@993: log.debug("doIt"); sascha@984: prepareStatement(SQL_DELETE_ALL_USERS); sascha@993: log.debug("prepareStatement"); sascha@984: stmnt.execute(); sascha@993: log.debug("execute"); sascha@990: conn.commit(); sascha@993: log.debug("commit"); sascha@984: return true; sascha@984: } sascha@984: }.runWrite(); sascha@993: sascha@993: log.debug("after runWrite(): " + success); sascha@993: sascha@993: return success; sascha@984: } sascha@984: sascha@984: sascha@982: @Override sascha@982: public void systemDown(GlobalContext context) { sascha@982: log.debug("systemDown"); sascha@982: } sascha@982: } sascha@982: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :