Mercurial > dive4elements > framework
diff artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java @ 32:c2d53bd30ab8
Re-factored artifact API for better integration of background processing.
artifacts/trunk@78 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 13 Sep 2009 14:50:53 +0000 |
parents | 83a059c204f8 |
children | f7d2cd59a0d5 |
line wrap: on
line diff
--- a/artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java Sat Sep 12 10:45:28 2009 +0000 +++ b/artifact-database/src/main/java/de/intevation/artifactdatabase/ArtifactDatabaseImpl.java Sun Sep 13 14:50:53 2009 +0000 @@ -1,35 +1,163 @@ package de.intevation.artifactdatabase; import java.util.HashMap; +import java.util.HashSet; +import java.util.ArrayList; +import java.util.List; +import de.intevation.artifacts.ArtifactDatabaseException; import de.intevation.artifacts.ArtifactDatabase; import de.intevation.artifacts.ArtifactFactory; import de.intevation.artifacts.Artifact; +import de.intevation.artifacts.CallContext; + +import de.intevation.artifactdatabase.Backend.PersistentArtifact; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import java.io.OutputStream; +import java.io.IOException; /** * @author Sascha L. Teichmann */ public class ArtifactDatabaseImpl -implements ArtifactDatabase +implements ArtifactDatabase, Id.Filter { - protected String [] factoryNames; - protected HashMap name2factory; + private static Logger logger = + Logger.getLogger(ArtifactDatabaseImpl.class); - protected Backend backend; - protected Object context; + public static final String NO_SUCH_FACTORY = + "No such factory"; + + public static final String NO_SUCH_ARTIFACT = + "No such artifact"; + + public static final String NOT_IN_BACKGROUND = + "Not in background"; + + public static final String INVALID_CALL_STATE = + "Invalid after call state"; + + public static final String CREATION_FAILED = + "Creation of artifact failed"; + + public static final String INTERNAL_ERROR = + "Creation of artifact failed"; + + public class CallContextImpl + implements CallContext + { + protected PersistentArtifact artifact; + protected int action; + + public CallContextImpl(PersistentArtifact artifact, int action) { + this.artifact = artifact; + this.action = action; + } + + public void afterCall(int action) { + this.action = action; + if (action == BACKGROUND) { + addIdToBackground(artifact.getId()); + } + } + + public void afterBackground(int action) { + if (this.action != BACKGROUND) { + throw new IllegalStateException(NOT_IN_BACKGROUND); + } + fromBackground(artifact, action); + } + + public Object globalContext() { + return context; + } + + public void postCall() { + switch (action) { + case NOTHING: + break; + case TOUCH: + artifact.touch(); + break; + case STORE: + artifact.store(); + break; + case BACKGROUND: + logger.warn("BACKGROUND processing is not fully implemented, yet!"); + artifact.store(); + break; + default: + logger.error(INVALID_CALL_STATE + ": " + action); + throw new IllegalStateException(INVALID_CALL_STATE); + } + } + } // class CallContextImpl + + public class DeferredOutputImpl + implements DeferredOutput + { + protected PersistentArtifact artifact; + protected Document format; + + public DeferredOutputImpl() { + } + + public DeferredOutputImpl( + PersistentArtifact artifact, + Document format + ) { + this.artifact = artifact; + this.format = format; + } + + public void write(OutputStream output) throws IOException { + + CallContextImpl cc = new CallContextImpl( + artifact, CallContext.TOUCH); + + try { + artifact.getArtifact().out(format, output, cc); + } + finally { + cc.postCall(); + } + } + } // class DeferredOutputImpl + + protected String [][] factoryNamesAndDescription; + protected HashMap name2factory; + + protected Backend backend; + protected Object context; + + protected HashSet backgroundIds; public ArtifactDatabaseImpl() { } public ArtifactDatabaseImpl(FactoryBootstrap bootstrap, Backend backend) { - name2factory = new HashMap(); + + backgroundIds = new HashSet(); + name2factory = new HashMap(); ArtifactFactory [] factories = bootstrap.getArtifactFactories(); - factoryNames = new String[factories.length]; + factoryNamesAndDescription = new String[factories.length][]; for (int i = 0; i < factories.length; ++i) { + ArtifactFactory factory = factories[i]; - name2factory.put(factoryNames[i] = factory.getName(), factory); + + String name = factory.getName(); + String description = factory.getDescription(); + + factoryNamesAndDescription[i] = + new String [] { name, description }; + + name2factory.put(name, factory); } context = bootstrap.getContext(); @@ -37,23 +165,168 @@ this.backend = backend; } - public String [] getArtifactFactoryNames() { - return factoryNames; - } - - public Artifact getArtifact(String identifier) { - return backend.getArtifact(identifier); + protected void fromBackground(PersistentArtifact artifact, int action) { + logger.warn("BACKGROUND processing is not fully implemented, yet!"); + switch (action) { + case CallContext.NOTHING: + break; + case CallContext.TOUCH: + artifact.touch(); + break; + case CallContext.STORE: + artifact.store(); + break; + default: + logger.warn("operation not allowed in fromBackground"); + } + removeIdFromBackground(artifact.getId()); } - public Artifact createArtifactWithFactory(String factoryName) { - ArtifactFactory factory = (ArtifactFactory)name2factory.get(factoryName); - return factory == null - ? null - : backend.createArtifactWithFactory(factory, context); + protected void removeIdFromBackground(int id) { + synchronized (backgroundIds) { + backgroundIds.remove(Integer.valueOf(id)); + } } - public Object getArtifactContext() { - return context; + protected void addIdToBackground(int id) { + synchronized (backgroundIds) { + backgroundIds.add(Integer.valueOf(id)); + } + } + + public List filterIds(List ids) { + int N = ids.size(); + ArrayList out = new ArrayList(N); + synchronized (backgroundIds) { + for (int i = 0; i < N; ++i) { + Id id = (Id)ids.get(i); + if (!backgroundIds.contains(Integer.valueOf(id.getId()))) { + out.add(id); + } + } + } + return out; + } + + public String [][] artifactFactoryNamesAndDescriptions() { + return factoryNamesAndDescription; + } + + public Document createArtifactWithFactory(String factoryName) + throws ArtifactDatabaseException + { + ArtifactFactory factory = (ArtifactFactory)name2factory.get( + factoryName); + + if (factory == null) { + throw new ArtifactDatabaseException(NO_SUCH_FACTORY); + } + + Artifact artifact = factory.createArtifact( + backend.newIdentifier(), + context); + + if (artifact == null) { + throw new ArtifactDatabaseException(CREATION_FAILED); + } + + PersistentArtifact persistentArtifact; + + try { + persistentArtifact = backend.storeInitially( + artifact, + factory.timeToLiveUntouched(artifact, context)); + } + catch (Exception e) { + logger.error(e.getLocalizedMessage(), e); + throw new ArtifactDatabaseException(CREATION_FAILED); + } + + CallContextImpl cc = new CallContextImpl( + persistentArtifact, CallContext.NOTHING); + + try { + return artifact.describe(cc); + } + finally { + cc.postCall(); + } + } + + public Document describe(String identifier) + throws ArtifactDatabaseException + { + // TODO: Handle background tasks + PersistentArtifact artifact = backend.getArtifact(identifier); + + if (artifact == null) { + throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); + } + + CallContextImpl cc = new CallContextImpl( + artifact, CallContext.TOUCH); + + try { + return artifact.getArtifact().describe(cc); + } + finally { + cc.postCall(); + } + } + + public Document advance(String identifier, Document target) + throws ArtifactDatabaseException + { + // TODO: Handle background tasks + PersistentArtifact artifact = backend.getArtifact(identifier); + + if (artifact == null) { + throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); + } + + CallContextImpl cc = new CallContextImpl( + artifact, CallContext.STORE); + + try { + return artifact.getArtifact().advance(target, cc); + } + finally { + cc.postCall(); + } + } + + public Document feed(String identifier, Document data) + throws ArtifactDatabaseException + { + // TODO: Handle background tasks + PersistentArtifact artifact = backend.getArtifact(identifier); + + if (artifact == null) { + throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); + } + + CallContextImpl cc = new CallContextImpl( + artifact, CallContext.STORE); + + try { + return artifact.getArtifact().advance(data, cc); + } + finally { + cc.postCall(); + } + } + + public DeferredOutput out(String identifier, Document format) + throws ArtifactDatabaseException + { + // TODO: Handle background tasks + PersistentArtifact artifact = backend.getArtifact(identifier); + + if (artifact == null) { + throw new ArtifactDatabaseException(NO_SUCH_ARTIFACT); + } + + return new DeferredOutputImpl(artifact, format); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: