sascha@13: package de.intevation.artifactdatabase; sascha@13: sascha@13: import java.util.HashMap; sascha@32: import java.util.HashSet; sascha@32: import java.util.ArrayList; sascha@32: import java.util.List; sascha@13: sascha@32: import de.intevation.artifacts.ArtifactDatabaseException; sascha@13: import de.intevation.artifacts.ArtifactDatabase; sascha@13: import de.intevation.artifacts.ArtifactFactory; sascha@13: import de.intevation.artifacts.Artifact; sascha@32: import de.intevation.artifacts.CallContext; sascha@48: import de.intevation.artifacts.CallMeta; sascha@32: sascha@32: import de.intevation.artifactdatabase.Backend.PersistentArtifact; sascha@32: sascha@32: import org.apache.log4j.Logger; sascha@32: sascha@32: import org.w3c.dom.Document; sascha@32: sascha@32: import java.io.OutputStream; sascha@32: import java.io.IOException; sascha@13: sascha@13: /** sascha@13: * @author Sascha L. Teichmann sascha@13: */ sascha@13: public class ArtifactDatabaseImpl sascha@41: implements ArtifactDatabase, Id.Filter, Backend.FactoryLookup sascha@13: { sascha@32: private static Logger logger = sascha@32: Logger.getLogger(ArtifactDatabaseImpl.class); sascha@13: sascha@32: public static final String NO_SUCH_FACTORY = sascha@32: "No such factory"; sascha@32: sascha@32: public static final String NO_SUCH_ARTIFACT = sascha@32: "No such artifact"; sascha@32: sascha@32: public static final String NOT_IN_BACKGROUND = sascha@32: "Not in background"; sascha@32: sascha@32: public static final String INVALID_CALL_STATE = sascha@32: "Invalid after call state"; sascha@32: sascha@32: public static final String CREATION_FAILED = sascha@32: "Creation of artifact failed"; sascha@32: sascha@32: public static final String INTERNAL_ERROR = sascha@32: "Creation of artifact failed"; sascha@32: sascha@32: public class CallContextImpl sascha@32: implements CallContext sascha@32: { sascha@32: protected PersistentArtifact artifact; sascha@32: protected int action; sascha@48: protected CallMeta callMeta; sascha@32: sascha@48: public CallContextImpl( sascha@48: PersistentArtifact artifact, sascha@48: int action, sascha@48: CallMeta callMeta sascha@48: ) { sascha@32: this.artifact = artifact; sascha@32: this.action = action; sascha@48: this.callMeta = callMeta; sascha@32: } sascha@32: sascha@32: public void afterCall(int action) { sascha@32: this.action = action; sascha@32: if (action == BACKGROUND) { sascha@32: addIdToBackground(artifact.getId()); sascha@32: } sascha@32: } sascha@32: sascha@32: public void afterBackground(int action) { sascha@32: if (this.action != BACKGROUND) { sascha@32: throw new IllegalStateException(NOT_IN_BACKGROUND); sascha@32: } sascha@32: fromBackground(artifact, action); sascha@32: } sascha@32: sascha@32: public Object globalContext() { sascha@32: return context; sascha@32: } sascha@32: sascha@48: public CallMeta getMeta() { sascha@48: return callMeta; sascha@48: } sascha@48: sascha@32: public void postCall() { sascha@32: switch (action) { sascha@32: case NOTHING: sascha@32: break; sascha@32: case TOUCH: sascha@32: artifact.touch(); sascha@32: break; sascha@32: case STORE: sascha@32: artifact.store(); sascha@32: break; sascha@32: case BACKGROUND: sascha@32: logger.warn("BACKGROUND processing is not fully implemented, yet!"); sascha@32: artifact.store(); sascha@32: break; sascha@32: default: sascha@32: logger.error(INVALID_CALL_STATE + ": " + action); sascha@32: throw new IllegalStateException(INVALID_CALL_STATE); sascha@32: } sascha@32: } sascha@32: } // class CallContextImpl sascha@32: sascha@32: public class DeferredOutputImpl sascha@32: implements DeferredOutput sascha@32: { sascha@32: protected PersistentArtifact artifact; sascha@32: protected Document format; sascha@48: protected CallMeta callMeta; sascha@32: sascha@32: public DeferredOutputImpl() { sascha@32: } sascha@32: sascha@32: public DeferredOutputImpl( sascha@47: PersistentArtifact artifact, sascha@48: Document format, sascha@48: CallMeta callMeta sascha@32: ) { sascha@32: this.artifact = artifact; sascha@32: this.format = format; sascha@48: this.callMeta = callMeta; sascha@32: } sascha@32: sascha@32: public void write(OutputStream output) throws IOException { sascha@32: sascha@32: CallContextImpl cc = new CallContextImpl( sascha@48: artifact, CallContext.TOUCH, callMeta); sascha@32: sascha@32: try { sascha@32: artifact.getArtifact().out(format, output, cc); sascha@32: } sascha@32: finally { sascha@32: cc.postCall(); sascha@32: } sascha@32: } sascha@32: } // class DeferredOutputImpl sascha@32: sascha@32: protected String [][] factoryNamesAndDescription; sascha@32: protected HashMap name2factory; sascha@32: sascha@32: protected Backend backend; sascha@32: protected Object context; sascha@32: sascha@32: protected HashSet backgroundIds; sascha@13: sascha@13: public ArtifactDatabaseImpl() { sascha@13: } sascha@13: sascha@41: public ArtifactDatabaseImpl(FactoryBootstrap bootstrap) { sascha@41: this(bootstrap, null); sascha@41: } sascha@41: sascha@13: public ArtifactDatabaseImpl(FactoryBootstrap bootstrap, Backend backend) { sascha@32: sascha@32: backgroundIds = new HashSet(); sascha@32: name2factory = new HashMap(); sascha@13: sascha@13: ArtifactFactory [] factories = bootstrap.getArtifactFactories(); sascha@32: factoryNamesAndDescription = new String[factories.length][]; sascha@13: sascha@13: for (int i = 0; i < factories.length; ++i) { sascha@32: sascha@13: ArtifactFactory factory = factories[i]; sascha@32: sascha@32: String name = factory.getName(); sascha@32: String description = factory.getDescription(); sascha@32: sascha@32: factoryNamesAndDescription[i] = sascha@32: new String [] { name, description }; sascha@32: sascha@32: name2factory.put(name, factory); sascha@13: } sascha@13: sascha@13: context = bootstrap.getContext(); sascha@26: sascha@41: wireWithBackend(backend); sascha@41: } sascha@41: sascha@41: public void wireWithBackend(Backend backend) { sascha@41: if (backend != null) { sascha@41: this.backend = backend; sascha@41: backend.setFactoryLookup(this); sascha@41: } sascha@13: } sascha@13: sascha@32: protected void fromBackground(PersistentArtifact artifact, int action) { sascha@32: logger.warn("BACKGROUND processing is not fully implemented, yet!"); sascha@32: switch (action) { sascha@32: case CallContext.NOTHING: sascha@32: break; sascha@32: case CallContext.TOUCH: sascha@32: artifact.touch(); sascha@32: break; sascha@32: case CallContext.STORE: sascha@32: artifact.store(); sascha@32: break; sascha@32: default: sascha@32: logger.warn("operation not allowed in fromBackground"); sascha@32: } sascha@32: removeIdFromBackground(artifact.getId()); sascha@13: } sascha@13: sascha@32: protected void removeIdFromBackground(int id) { sascha@32: synchronized (backgroundIds) { sascha@32: backgroundIds.remove(Integer.valueOf(id)); sascha@32: } sascha@13: } sascha@13: sascha@32: protected void addIdToBackground(int id) { sascha@32: synchronized (backgroundIds) { sascha@32: backgroundIds.add(Integer.valueOf(id)); sascha@32: } sascha@32: } sascha@32: sascha@32: public List filterIds(List ids) { sascha@32: int N = ids.size(); sascha@32: ArrayList out = new ArrayList(N); sascha@32: synchronized (backgroundIds) { sascha@32: for (int i = 0; i < N; ++i) { sascha@32: Id id = (Id)ids.get(i); sascha@32: if (!backgroundIds.contains(Integer.valueOf(id.getId()))) { sascha@32: out.add(id); sascha@32: } sascha@32: } sascha@32: } sascha@32: return out; sascha@32: } sascha@32: sascha@32: public String [][] artifactFactoryNamesAndDescriptions() { sascha@32: return factoryNamesAndDescription; sascha@32: } sascha@32: sascha@41: public ArtifactFactory getArtifactFactory(String factoryName) { sascha@41: return (ArtifactFactory)name2factory.get(factoryName); sascha@41: } sascha@41: sascha@48: public Document createArtifactWithFactory( sascha@48: String factoryName, sascha@48: CallMeta callMeta sascha@48: ) sascha@48: throws ArtifactDatabaseException sascha@32: { sascha@41: ArtifactFactory factory = getArtifactFactory(factoryName); sascha@32: sascha@32: if (factory == null) { sascha@32: throw new ArtifactDatabaseException(NO_SUCH_FACTORY); sascha@32: } sascha@32: sascha@32: Artifact artifact = factory.createArtifact( sascha@32: backend.newIdentifier(), sascha@32: context); sascha@32: sascha@32: if (artifact == null) { sascha@32: throw new ArtifactDatabaseException(CREATION_FAILED); sascha@32: } sascha@32: sascha@32: PersistentArtifact persistentArtifact; sascha@32: sascha@32: try { sascha@32: persistentArtifact = backend.storeInitially( sascha@32: artifact, sascha@41: factory, sascha@32: factory.timeToLiveUntouched(artifact, context)); sascha@32: } sascha@32: catch (Exception e) { sascha@32: logger.error(e.getLocalizedMessage(), e); sascha@32: throw new ArtifactDatabaseException(CREATION_FAILED); sascha@32: } sascha@32: sascha@32: CallContextImpl cc = new CallContextImpl( sascha@48: persistentArtifact, CallContext.NOTHING, callMeta); sascha@32: sascha@32: try { sascha@55: return artifact.describe(null, cc); sascha@32: } sascha@32: finally { sascha@32: cc.postCall(); sascha@32: } sascha@32: } sascha@32: sascha@55: public Document describe(String identifier, Document data, CallMeta callMeta) sascha@32: throws ArtifactDatabaseException sascha@32: { sascha@32: // TODO: Handle background tasks sascha@32: PersistentArtifact artifact = backend.getArtifact(identifier); sascha@32: sascha@32: if (artifact == null) { sascha@32: throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); sascha@32: } sascha@32: sascha@32: CallContextImpl cc = new CallContextImpl( sascha@48: artifact, CallContext.TOUCH, callMeta); sascha@32: sascha@32: try { sascha@55: return artifact.getArtifact().describe(data, cc); sascha@32: } sascha@32: finally { sascha@32: cc.postCall(); sascha@32: } sascha@32: } sascha@32: sascha@48: public Document advance(String identifier, Document target, CallMeta callMeta) sascha@32: throws ArtifactDatabaseException sascha@32: { sascha@32: // TODO: Handle background tasks sascha@32: PersistentArtifact artifact = backend.getArtifact(identifier); sascha@32: sascha@32: if (artifact == null) { sascha@32: throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); sascha@32: } sascha@32: sascha@32: CallContextImpl cc = new CallContextImpl( sascha@48: artifact, CallContext.STORE, callMeta); sascha@48: sascha@48: try { sascha@48: return artifact.getArtifact().advance(target, cc); sascha@48: } sascha@48: finally { sascha@48: cc.postCall(); sascha@48: } sascha@48: } sascha@48: sascha@48: public Document feed(String identifier, Document data, CallMeta callMeta) sascha@48: throws ArtifactDatabaseException sascha@48: { sascha@48: // TODO: Handle background tasks sascha@48: PersistentArtifact artifact = backend.getArtifact(identifier); sascha@48: sascha@48: if (artifact == null) { sascha@48: throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); sascha@48: } sascha@48: sascha@48: CallContextImpl cc = new CallContextImpl( sascha@48: artifact, CallContext.STORE, callMeta); sascha@32: sascha@32: try { tim@36: return artifact.getArtifact().feed(data, cc); sascha@32: } sascha@32: finally { sascha@32: cc.postCall(); sascha@32: } sascha@32: } sascha@32: sascha@48: public DeferredOutput out(String identifier, Document format, CallMeta callMeta) sascha@32: throws ArtifactDatabaseException sascha@32: { sascha@32: // TODO: Handle background tasks sascha@32: PersistentArtifact artifact = backend.getArtifact(identifier); sascha@32: sascha@32: if (artifact == null) { sascha@32: throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); sascha@32: } sascha@32: sascha@48: return new DeferredOutputImpl(artifact, format, callMeta); sascha@13: } sascha@13: } sascha@13: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: