changeset 1976:0b466bd4ab24

Introduced a CollectionAttribute class that stores the information provided by the Collection's attribute document. flys-artifacts/trunk@3400 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Tue, 13 Dec 2011 11:55:47 +0000
parents b30e1710df1d
children 9dc399718335
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeParser.java flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionAttribute.java flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionDescriptionHelper.java flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java
diffstat 6 files changed, 364 insertions(+), 129 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Tue Dec 13 09:10:48 2011 +0000
+++ b/flys-artifacts/ChangeLog	Tue Dec 13 11:55:47 2011 +0000
@@ -1,3 +1,29 @@
+2011-12-13  Ingo Weinzierl <ingo@intevation.de>
+
+	* src/main/java/de/intevation/flys/collections/CollectionAttribute.java:
+	  New. This class will store the information provided in the Collection's
+	  attribute (which is a DOM document).
+
+	* src/main/java/de/intevation/flys/collections/CollectionDescriptionHelper.java:
+	  Store an instance of CollectionAttribute and append its XML representation
+	  to the DESCRIBE document.
+
+	* src/main/java/de/intevation/flys/collections/AttributeWriter.java: Removed
+	  all DOM operations from this writer. Its new task is to create a new
+	  CollectionAttribute object which represents a merged version of the old
+	  CollectionAttribute and the information provided by the Collection's child
+	  Artifacts.
+
+	* src/main/java/de/intevation/flys/collections/AttributeParser.java: The
+	  result of AttributeParser's parse() operation is a CollectionAttribute
+	  object now. The methods getOuts() and getFacets() are as of now proxy
+	  methods that call the relevant methods of CollectionAttribute.
+
+	* src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java:
+	  Some structural changes in the process to build the attribute Document of
+	  the Collection's DESCRIBE. We will no longer work with Document during
+	  this process but with instances of CollectionAttribute.
+
 2011-12-13	Felix Wolfsteller	<felix.wolfsteller@intevation.de>
 
 	Server-side of newer Cross-Section diagram construction architecture.
--- a/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeParser.java	Tue Dec 13 09:10:48 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeParser.java	Tue Dec 13 11:55:47 2011 +0000
@@ -1,7 +1,5 @@
 package de.intevation.flys.collections;
 
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -22,7 +20,6 @@
 
 import de.intevation.artifacts.common.utils.XMLUtils;
 
-import de.intevation.flys.artifacts.model.ManagedFacet;
 import de.intevation.flys.artifacts.model.ManagedDomFacet;
 
 /**
@@ -35,25 +32,27 @@
     public static final String XPATH_ARTIFACT_OUTPUTMODES =
         "/art:attribute/art:outputs/art:output";
 
+
     private static Logger logger = Logger.getLogger(AttributeParser.class);
 
-    protected Map<String, Output> outs;
 
-    /** List of facets. */
-    protected List<Facet> facets;
+    protected Document attributeDocument;
+
+    protected CollectionAttribute attribute;
 
 
-    public AttributeParser() {
-        this.outs   = new HashMap<String, Output>();
-        this.facets = new ArrayList<Facet>();
+    public AttributeParser(Document attributeDocument) {
+        this.attributeDocument = attributeDocument;
     }
 
 
-    public void parse(Document doc) {
+    public void parse() {
         logger.debug("AttributeParser.parse");
 
+        attribute = new CollectionAttribute();
+
         NodeList outs = (NodeList) XMLUtils.xpath(
-            doc,
+            attributeDocument,
             XPATH_ARTIFACT_OUTPUTMODES,
             XPathConstants.NODESET,
             ArtifactNamespaceContext.INSTANCE);
@@ -70,36 +69,22 @@
     }
 
 
-    public Map<String, Output> getOuts() {
-        return outs;
+    public CollectionAttribute getCollectionAttribute() {
+        if (attribute == null) {
+            parse();
+        }
+
+        return attribute;
     }
 
 
-    /**
-     * Adds item (a ManagedFacet) to an out.
-     */
-    protected void addItem(String out, ManagedFacet item) {
-        this.facets.add(item);
-        Output o = outs.get(out);
-
-        if (o != null) {
-            o.addFacet(item);
-        }
+    public Document getAttributeDocument() {
+        return attributeDocument;
     }
 
 
-    protected void parseOutput(Node out) {
-        String name = XMLUtils.xpathString(
-            out, "@name", ArtifactNamespaceContext.INSTANCE);
-
-        if (outs.get(name) == null) {
-            logger.debug("Create new output: " + name);
-
-            Output o = new DefaultOutput(name, null, null);
-            outs.put(name, o);
-        }
-
-        parseItems(out, name);
+    public Map<String, Output> getOuts() {
+        return attribute.getOutputs();
     }
 
 
@@ -108,7 +93,29 @@
      * @return list of all facets.
      */
     public List<Facet> getFacets() {
-        return this.facets;
+        return attribute.getFacets();
+    }
+
+
+    protected void parseOutput(Node out) {
+        String name = XMLUtils.xpathString(
+            out, "@name", ArtifactNamespaceContext.INSTANCE);
+
+        if (name == null || name.length() == 0) {
+            logger.warn("No Output name specified. Cancel parsing!");
+            return;
+        }
+
+        Output o = attribute.getOutput(name);
+
+        if (o == null) {
+            logger.debug("Create new output: " + name);
+
+            o = new DefaultOutput(name, null, null);
+            attribute.addOutput(name, o);
+        }
+
+        parseItems(out, name);
     }
 
 
@@ -127,7 +134,7 @@
         for (int i = 0; i < num; i++) {
             Element theme = (Element) themes.item(i);
 
-            addItem(outname, new ManagedDomFacet(theme));
+            attribute.addFacet(outname, new ManagedDomFacet(theme));
         }
     }
 }
--- a/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java	Tue Dec 13 09:10:48 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java	Tue Dec 13 11:55:47 2011 +0000
@@ -13,14 +13,10 @@
 
 import de.intevation.artifacts.ArtifactDatabase;
 import de.intevation.artifacts.ArtifactDatabaseException;
-import de.intevation.artifacts.ArtifactNamespaceContext;
 
 import de.intevation.artifactdatabase.state.Facet;
 import de.intevation.artifactdatabase.state.Output;
 
-import de.intevation.artifacts.common.utils.XMLUtils;
-import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator;
-
 import de.intevation.flys.artifacts.FLYSArtifact;
 import de.intevation.flys.artifacts.model.ManagedFacet;
 
@@ -51,6 +47,11 @@
      */
     protected Map<String, List<String>> compatibilities;
 
+
+    /** The result of the <i>write()</i> operation.*/
+    protected CollectionAttribute attribute;
+
+
     private static Logger logger = Logger.getLogger(AttributeWriter.class);
 
 
@@ -90,60 +91,34 @@
      *
      * @return document with merged outputs as described.
      */
-    protected Document write() {
-        Document doc = XMLUtils.newDocument();
-
-        ElementCreator cr = new ElementCreator(
-            doc,
-            ArtifactNamespaceContext.NAMESPACE_URI,
-            ArtifactNamespaceContext.NAMESPACE_PREFIX);
-
-        Element attribute = cr.create("attribute");
-        Element outs      = cr.create("outputs");
-
-        attribute.appendChild(outs);
-        doc.appendChild(attribute);
+    protected CollectionAttribute write() {
+        attribute = new CollectionAttribute();
 
         for (String outName: newAttr.keySet()) {
             Output a = newAttr.get(outName);
-            Output b = oldAttr.get(outName);
 
-            writeOutput(doc, outs, cr, a.getName(), newFacets, oldFacets);
+            attribute.addOutput(a.getName(), a);
+
+            writeOutput(a.getName(), newFacets, oldFacets);
         }
 
-        return doc;
+        return attribute;
     }
 
 
     /**
-     * @param doc  Document to add output nodes to
-     * @param outs Node in Document to add output nodes to
-     * @param cr   ElementCreator in use to modify doc/outs
      * @param outputName the "new" outputs name
      * @param newOutFacets Facets of the new outputs
      * @param oldOutFacets Facets of the old outputs (can be null)
      */
     protected void writeOutput(
-        Document       doc,
-        Node           outs,
-        ElementCreator cr,
-        String         outputName,
-        List<Facet>    newOutFacets,
-        List<Facet>    oldOutFacets)
-    {
-        Element output = cr.create("output");
-        cr.addAttr(output, "name", outputName);
-
-
-        List<String> compatibleFacets = this.compatibilities.get(outputName);
+        String      outputName,
+        List<Facet> newOutFacets,
+        List<Facet> oldOutFacets
+    ) {
+        List<String> compatFacets = this.compatibilities.get(outputName);
         try {
-            if (writeFacets(
-                    doc, cr, output, newOutFacets, oldOutFacets,
-                    compatibleFacets))
-            {
-                // Add output element only if it contains facets.
-                outs.appendChild(output);
-            }
+            writeFacets(outputName, newOutFacets, oldOutFacets, compatFacets);
         }
         catch (ArtifactDatabaseException ade) {
             logger.error(ade, ade);
@@ -152,18 +127,13 @@
 
 
     /**
-     * @param doc    Document to add facet nodes to
-     * @param cr     ElementCreator to use with output/doc
-     * @param output Node in Document to add facet nodes to
      * @param newFacets the new facets
      * @param oldFacets the old facets
      * @param compatibleFacets List of facets to accept
      * @return true if any facets are written to the out.
      */
     protected boolean writeFacets(
-        Document       doc,
-        ElementCreator cr,
-        Element        output,
+        String         outputName,
         List<Facet>    newFacets,
         List<Facet>    oldFacets,
         List<String>   compatibleFacets)
@@ -204,11 +174,11 @@
         for (ManagedFacet newMF: genuinelyNewFacets) {
             FLYSArtifact flys = (FLYSArtifact) db.getRawArtifact(newMF.getArtifact());
             newMF.setActive(flys.getInitialFacetActivity(
-                output.getAttribute("name"),
+                outputName,
                 newMF.getName(),
                 newMF.getIndex()));
         }
-        
+
         // For each genuinely new Facet check positional conflicts.
         for (ManagedFacet newMF: genuinelyNewFacets) {
             boolean conflicts = true;
@@ -254,10 +224,7 @@
 
         // Now add all facets.
         for (ManagedFacet oldMF: currentFacets) {
-            Node node = oldMF.toXML(doc);
-            if (node != null) {
-                output.appendChild(node);
-            }
+            attribute.addFacet(outputName, oldMF);
         }
 
         return currentFacets.size() > 0;
@@ -274,14 +241,13 @@
      *                  these.
      * @return facet if genuinely new, matching old facet otherwise.
      */
-    protected ManagedFacet pickFacet(ManagedFacet facet,
-        List<Facet> oldFacets)
+    protected ManagedFacet pickFacet(ManagedFacet facet, List<Facet> oldFacets)
     {
         if (oldFacets == null) {
             logger.debug("No old facets to compare a new to found.");
             return facet;
         }
-       
+
         String hash = facet.getName() + facet.getIndex() + facet.getArtifact();
 
         // Compare "new" facet with all old facets.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionAttribute.java	Tue Dec 13 11:55:47 2011 +0000
@@ -0,0 +1,236 @@
+package de.intevation.flys.collections;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import org.apache.log4j.Logger;
+
+import de.intevation.artifacts.ArtifactNamespaceContext;
+
+import de.intevation.artifacts.common.utils.XMLUtils;
+import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator;
+
+import de.intevation.artifactdatabase.state.DefaultOutput;
+import de.intevation.artifactdatabase.state.Facet;
+import de.intevation.artifactdatabase.state.Output;
+
+
+public class CollectionAttribute {
+
+    private static final Logger logger =
+        Logger.getLogger(CollectionAttribute.class);
+
+
+    protected ElementCreator ec;
+
+    protected Map<String, Output> outputMap;
+
+    protected Node loadedRecommendations;
+
+
+    public CollectionAttribute() {
+    }
+
+
+    public void addOutput(String key, Output output) {
+        if (outputMap == null) {
+            outputMap = new HashMap<String, Output>();
+        }
+
+        if (key != null && key.length() > 0 && output != null) {
+            outputMap.put(
+                key,
+                new DefaultOutput(
+                    output.getName(),
+                    output.getDescription(),
+                    output.getMimeType(),
+                    new ArrayList<Facet>(),
+                    output.getType()));
+        }
+    }
+
+
+    public void addFacet(String outputKey, Facet facet) {
+        if (facet == null) {
+            logger.warn("Tried to add empty facet.");
+            return;
+        }
+
+        if (outputMap == null) {
+            logger.warn("Tried to add facet but no Outputs are existing yet.");
+            return;
+        }
+
+        Output output = outputMap.get(outputKey);
+
+        if (output == null) {
+            logger.warn("Tried to add facet for unknown Output: " + outputKey);
+            return;
+        }
+
+        logger.debug("Add facet for '" + outputKey + "': " + facet.getName());
+        output.addFacet(facet);
+    }
+
+
+    public void setLoadedRecommendations(Node loadedRecommendations) {
+        // TODO Replace this Node with a Java class object.
+        this.loadedRecommendations = loadedRecommendations;
+    }
+
+
+    public Document toXML() {
+        Document doc = XMLUtils.newDocument();
+
+        ec = new ElementCreator(
+            doc,
+            ArtifactNamespaceContext.NAMESPACE_URI,
+            ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+        Element root = ec.create("attribute");
+
+        appendOutputs(root);
+        appendLoadedRecommendations(root);
+
+        doc.appendChild(root);
+
+        return doc;
+    }
+
+
+    public Map<String, Output> getOutputs() {
+        return outputMap;
+    }
+
+
+    public Output getOutput(String name) {
+        if (name == null || name.length() == 0) {
+            logger.warn("No Output name specified.");
+            return null;
+        }
+
+        if (outputMap == null || outputMap.size() == 0) {
+            logger.warn("Tried to retrieve Output, but no Outputs existing.");
+            return null;
+        }
+
+        return outputMap.get(name);
+    }
+
+
+    public List<Facet> getFacets(String output) {
+        if (output == null || output.length() == 0) {
+            logger.warn("No Output name specified.");
+            return new ArrayList<Facet>();
+        }
+
+        if (outputMap == null) {
+            logger.warn("Tried to retrieve facets, but no Outputs existing.");
+            return new ArrayList<Facet>();
+        }
+
+        Output o = outputMap.get(output);
+
+        if (o == null) {
+            logger.warn("No Output '" + output + "' existing.");
+            return new ArrayList<Facet>();
+        }
+
+        return o.getFacets();
+    }
+
+
+    public List<Facet> getFacets() {
+        List<Facet> allFacets = new ArrayList<Facet>();
+
+        if (outputMap == null || outputMap.size() == 0) {
+            logger.warn("No Outputs existing.");
+            return allFacets;
+        }
+
+        Set<String> outputNames = outputMap.keySet();
+
+        for (String outputName: outputNames) {
+            allFacets.addAll(getFacets(outputName));
+        }
+
+        return allFacets;
+    }
+
+
+    protected void appendOutputs(Element root) {
+        if (outputMap == null || outputMap.size() == 0) {
+            logger.warn("No outputs to append.");
+            return;
+        }
+
+        logger.debug("Append " + outputMap.size() + " Output Elements.");
+
+        Element outputsEl = ec.create("outputs");
+
+        Set<Map.Entry<String, Output>> entrySet = outputMap.entrySet();
+
+        for (Map.Entry<String, Output> entry: entrySet) {
+            appendOutput(outputsEl, entry.getKey(), entry.getValue());
+        }
+
+        root.appendChild(outputsEl);
+    }
+
+
+    protected void appendOutput(Element root, String name, Output output) {
+        if (name == null || name.length() == 0 || output == null) {
+            logger.warn("Tried to appendOutput, but Output is invalid.");
+            return;
+        }
+
+        logger.debug("Append Output Element for '" + name + "'");
+
+        Element outputEl = ec.create("output");
+        ec.addAttr(outputEl, "name", name);
+
+        appendFacets(outputEl, output.getFacets());
+
+        root.appendChild(outputEl);
+    }
+
+
+    protected void appendFacets(Element root, List<Facet> facets) {
+        if (facets == null || facets.size() == 0) {
+            logger.warn("Tried to append 0 Facets.");
+            return;
+        }
+
+        Document owner = root.getOwnerDocument();
+
+        logger.debug("Append " + facets.size() + " facets.");
+
+        for (Facet facet: facets) {
+            Node facetNode = facet.toXML(owner);
+
+            if (facetNode != null) {
+                root.appendChild(facetNode);
+            }
+        }
+    }
+
+
+    protected void appendLoadedRecommendations(Element root) {
+        if (loadedRecommendations == null) {
+            logger.debug("No loaded recommendations existing yet.");
+            return;
+        }
+
+        Document owner = root.getOwnerDocument();
+
+        root.appendChild(owner.importNode(loadedRecommendations, true));
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionDescriptionHelper.java	Tue Dec 13 09:10:48 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/CollectionDescriptionHelper.java	Tue Dec 13 11:55:47 2011 +0000
@@ -46,8 +46,8 @@
     protected Date   creation;
     protected long   ttl;
 
-    protected List<String> artifacts;
-    protected Node         attribute;
+    protected List<String>        artifacts;
+    protected CollectionAttribute attribute;
 
 
     /**
@@ -83,7 +83,7 @@
     }
 
 
-    public void setAttribute(Node attribute) {
+    public void setAttribute(CollectionAttribute attribute) {
         if (attribute != null) {
             this.attribute = attribute;
         }
@@ -198,7 +198,8 @@
 
     protected void appendAttribute(Element root) {
         Document owner = root.getOwnerDocument();
+        Document attr  = attribute.toXML();
 
-        root.appendChild(owner.importNode(attribute, true));
+        root.appendChild(owner.importNode(attr.getFirstChild(), true));
     }
 }
--- a/flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java	Tue Dec 13 09:10:48 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java	Tue Dec 13 11:55:47 2011 +0000
@@ -83,11 +83,14 @@
             context);
 
         ArtifactDatabase db = context.getDatabase();
-        Document oldAttrs   = getAttribute();
+
+        Document        oldAttrs = getAttribute();
+        AttributeParser parser   = new AttributeParser(oldAttrs);
 
         try {
-            String[] aUUIDs = getArtifactUUIDs(context);
-            Node newAttr    = mergeAttributes(db, context, oldAttrs, aUUIDs);
+            String[]            aUUIDs  = getArtifactUUIDs(context);
+            CollectionAttribute newAttr = mergeAttributes(
+                db, context, parser, aUUIDs);
 
             helper.setAttribute(newAttr);
 
@@ -103,13 +106,10 @@
         catch (ArtifactDatabaseException ade) {
             log.error("Error while merging attribute documents.", ade);
 
-            helper.setAttribute(oldAttrs);
+            helper.setAttribute(parser.getCollectionAttribute());
         }
 
-        Document doc = helper.toXML();
-        log.debug("HELPER DOC: " + XMLUtils.toString(doc));
-
-        return doc;
+        return helper.toXML();
     }
 
 
@@ -119,16 +119,19 @@
      *
      * @param uuids Artifact uuids.
      */
-    protected Node mergeAttributes(
+    protected CollectionAttribute mergeAttributes(
         ArtifactDatabase db,
         CallContext      context,
-        Document         oldAttrs,
-        String[]         uuids)
-    {
-        Document doc = buildOutAttributes(db, context, oldAttrs, uuids);
-        Node newAttr = doc.getFirstChild();
+        AttributeParser  oldParser,
+        String[]         uuids
+    ) {
+        CollectionAttribute cAttribute =
+            buildOutAttributes(db, context, oldParser, uuids);
 
-        newAttr = mergeLoadedRecommendations(oldAttrs, newAttr);
+        cAttribute.setLoadedRecommendations(
+            getLoadedRecommendations(oldParser.getAttributeDocument()));
+
+        Document doc = cAttribute.toXML();
 
         try {
             // Save the merged document into database.
@@ -138,7 +141,7 @@
             log.error(adb, adb);
         }
 
-        return newAttr;
+        return cAttribute;
     }
 
 
@@ -148,19 +151,14 @@
      * because mergeAttributes() only merges the art:outputs nodes - all
      * other nodes are skiped.
      */
-    protected Node mergeLoadedRecommendations(Document oldAttrs, Node newAttrs){
+    protected Node getLoadedRecommendations(Document oldAttrs) {
         Element loadedRecoms = (Element) XMLUtils.xpath(
             oldAttrs,
             XPATH_LOADED_RECOMMENDATIONS,
             XPathConstants.NODE,
             ArtifactNamespaceContext.INSTANCE);
 
-        if (loadedRecoms != null) {
-            Document doc = newAttrs.getOwnerDocument();
-            newAttrs.appendChild(doc.importNode(loadedRecoms, true));
-        }
-
-        return newAttrs;
+        return loadedRecoms;
     }
 
 
@@ -360,10 +358,10 @@
      * Return merged output document.
      * @param uuids List of artifact uuids.
      */
-    protected Document buildOutAttributes(
+    protected CollectionAttribute buildOutAttributes(
         ArtifactDatabase db,
         CallContext      context,
-        Document         oldAttr,
+        AttributeParser  aParser,
         String[]         uuids)
     {
         Document doc = XMLUtils.newDocument();
@@ -379,8 +377,7 @@
             ArtifactNamespaceContext.NAMESPACE_URI,
             ArtifactNamespaceContext.NAMESPACE_PREFIX);
 
-        AttributeParser aParser = new AttributeParser();
-        OutputParser    oParser = new OutputParser(db, context);
+        OutputParser oParser = new OutputParser(db, context);
 
         if (uuids != null) {
             for (String uuid: uuids) {
@@ -392,8 +389,8 @@
                 }
             }
         }
-    
-        aParser.parse(oldAttr);
+
+        aParser.parse();
 
         return new AttributeWriter(
             db,
@@ -417,12 +414,14 @@
     protected Document getAttribute(CallContext context, String output)
     throws    ArtifactDatabaseException
     {
-        Document attr = buildOutAttributes(
+        CollectionAttribute cAttr = buildOutAttributes(
             context.getDatabase(),
             context,
-            getAttribute(),
+            new AttributeParser(getAttribute()),
             getArtifactUUIDs(context));
 
+        Document attr = cAttr.toXML();
+
         Node out = (Node) XMLUtils.xpath(
             attr,
             "art:attribute/art:outputs/art:output[@name='" + output + "']",

http://dive4elements.wald.intevation.org