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:

http://dive4elements.wald.intevation.org