changeset 346:16161de47662

The Attributes of a collection are written into its DESCRIBE now. flys-artifacts/trunk@1748 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Tue, 26 Apr 2011 13:29:18 +0000
parents 88a669785863
children a63d8bdb2d79
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedFacet.java 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/FLYSArtifactCollection.java flys-artifacts/src/main/java/de/intevation/flys/collections/OutputParser.java
diffstat 6 files changed, 553 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Tue Apr 26 13:17:08 2011 +0000
+++ b/flys-artifacts/ChangeLog	Tue Apr 26 13:29:18 2011 +0000
@@ -1,3 +1,27 @@
+2011-04-26  Ingo Weinzierl <ingo@intevation.de>
+
+	* src/main/java/de/intevation/flys/artifacts/model/ManagedFacet.java: New.
+	  a specialized facet that stores information about its position and its
+	  state (active/inactive) in an output of a collection.
+
+	* src/main/java/de/intevation/flys/collections/AttributeParser.java: New.
+	  This parser takes the attributes (XML) of a collection and extracts the
+	  contained outputs with its facets. The result is a Map<String, Output>.
+
+	* src/main/java/de/intevation/flys/collections/OutputParser.java: New.
+	  This parser is used to query the artifact's DESCRIBE and to extract the
+	  supported outputs. The result is a Map<String, Output>.
+
+	* src/main/java/de/intevation/flys/collections/AttributeWriter.java: New.
+	  This writer merges the outputs contained in an attribute of a collection
+	  with the outputs of a collection's artifacts.
+
+	* src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java:
+	  The attributes of a collection are written into its DESCRIBE document
+	  now. The OutputParser and AttributeParser are used to read the supported
+	  attributes by the collection and its artifacts - the AttributeWriter is
+	  used to merge both attributes and create a final attribute document.
+
 2011-04-26  Ingo Weinzierl <ingo@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/context/FLYSContext.java,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedFacet.java	Tue Apr 26 13:29:18 2011 +0000
@@ -0,0 +1,57 @@
+package de.intevation.flys.artifacts.model;
+
+import de.intevation.artifactdatabase.state.DefaultFacet;
+
+
+public class ManagedFacet extends DefaultFacet {
+
+    /** The uuid of the owner artifact.*/
+    protected String uuid;
+
+    /** A property that determines the position of this facet.*/
+    protected int position;
+
+    /** A property that determines if this facet is active or not.*/
+    protected int active;
+
+
+    public ManagedFacet(
+        String  name,
+        String  desc,
+        String  uuid,
+        int     pos,
+        int     active)
+    {
+        super(name, desc);
+
+        this.uuid     = uuid;
+        this.position = pos;
+        this.active   = active;
+    }
+
+
+    public void setPosition(int pos) {
+        this.position = pos;
+    }
+
+
+    public int getPosition() {
+        return position;
+    }
+
+
+    public void setActive(int active) {
+        this.active = active;
+    }
+
+
+    public int getActive() {
+        return active;
+    }
+
+
+    public String getArtifact() {
+        return uuid;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeParser.java	Tue Apr 26 13:29:18 2011 +0000
@@ -0,0 +1,133 @@
+package de.intevation.flys.collections;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.xpath.XPathConstants;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import de.intevation.artifacts.ArtifactDatabase;
+import de.intevation.artifacts.ArtifactDatabaseException;
+import de.intevation.artifacts.ArtifactNamespaceContext;
+import de.intevation.artifacts.CallMeta;
+
+import de.intevation.artifactdatabase.state.DefaultOutput;
+import de.intevation.artifactdatabase.state.Facet;
+import de.intevation.artifactdatabase.state.Output;
+
+import de.intevation.artifacts.common.utils.XMLUtils;
+
+import de.intevation.flys.artifacts.model.ManagedFacet;
+
+
+public class AttributeParser {
+
+    /** Constant XPath that points to the outputmodes of an artifact.*/
+    public static final String XPATH_ARTIFACT_OUTPUTMODES =
+        "/art:output";
+
+
+    private static Logger logger = Logger.getLogger(AttributeParser.class);
+
+
+    protected Map<String, Output> outs;
+
+
+    public AttributeParser() {
+        this.outs = new HashMap<String, Output>();
+    }
+
+
+    public void parse(Document doc) {
+        logger.debug("AttributeParser.parse");
+
+        NodeList outs = (NodeList) XMLUtils.xpath(
+            doc,
+            XPATH_ARTIFACT_OUTPUTMODES,
+            XPathConstants.NODESET,
+            ArtifactNamespaceContext.INSTANCE);
+
+        int num = outs != null ? outs.getLength() : 0;
+
+        logger.debug("Attribute has " + num + " outputs.");
+
+        for (int i = 0; i < num; i++) {
+            Node out = outs.item(i);
+
+            parseOutput(out);
+        }
+    }
+
+
+    public Map<String, Output> getOuts() {
+        return outs;
+    }
+
+
+    protected void addItem(String out, ManagedFacet item) {
+        Output o = outs.get(out);
+
+        if (o != null) {
+            o.addFacet(item);
+        }
+    }
+
+
+    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);
+    }
+
+
+    protected void parseItems(Node out, String outname) {
+        NodeList themes = (NodeList) XMLUtils.xpath(
+            out, "art:theme",
+            XPathConstants.NODESET,
+            ArtifactNamespaceContext.INSTANCE);
+
+        int num = themes != null ? themes.getLength() : 0;
+
+        logger.debug("Output has " + num + " themes.");
+
+        for (int i = 0; i < num; i++) {
+            Node theme = themes.item(i);
+
+            String name = XMLUtils.xpathString(
+                theme, "@facet", ArtifactNamespaceContext.INSTANCE);
+
+            String uuid = XMLUtils.xpathString(
+                theme, "@artifact", ArtifactNamespaceContext.INSTANCE);
+
+            String pos = XMLUtils.xpathString(
+                theme, "@pos", ArtifactNamespaceContext.INSTANCE);
+
+            String active = XMLUtils.xpathString(
+                theme, "@active", ArtifactNamespaceContext.INSTANCE);
+
+            ManagedFacet item = new ManagedFacet(
+                name, "", uuid,
+                Integer.parseInt(pos),
+                Integer.parseInt(active));
+
+            addItem(outname, item);
+        }
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java	Tue Apr 26 13:29:18 2011 +0000
@@ -0,0 +1,144 @@
+package de.intevation.flys.collections;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+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.model.ManagedFacet;
+
+
+public class AttributeWriter {
+
+    protected Map<String, Output> oldAttr;
+    protected Map<String, Output> newAttr;
+
+    private static Logger logger = Logger.getLogger(AttributeWriter.class);
+
+
+    public AttributeWriter(
+        Map<String, Output> oldAttr,
+        Map<String, Output> newAttr)
+    {
+        this.oldAttr = oldAttr;
+        this.newAttr = newAttr;
+    }
+
+
+    protected Document write() {
+        Document doc = XMLUtils.newDocument();
+
+        ElementCreator cr = new ElementCreator(
+            doc,
+            ArtifactNamespaceContext.NAMESPACE_URI,
+            ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+        Iterator<String> iter = newAttr.keySet().iterator();
+
+        while (iter.hasNext()) {
+            String outName = iter.next();
+
+            Output a = newAttr.get(outName);
+            Output b = oldAttr.get(outName);
+
+            writeOutput(doc, cr, a, b);
+        }
+
+        return doc;
+    }
+
+
+    protected void writeOutput(
+        Document       doc,
+        ElementCreator cr,
+        Output         a,
+        Output         b)
+    {
+        Element output = cr.create("output");
+        cr.addAttr(output, "name", a.getName());
+
+        doc.appendChild(output);
+
+        List<Facet> facetsA = a.getFacets();
+        List<Facet> facetsB = null;
+
+        if (b != null) {
+            facetsB = b.getFacets();
+        }
+
+        writeFacets(doc, cr, output, facetsA, facetsB);
+    }
+
+
+    protected void writeFacets(
+        Document       doc,
+        ElementCreator cr,
+        Element        output,
+        List<Facet>    a,
+        List<Facet>    b)
+    {
+        int num = a.size();
+
+        for (int i = 0; i < num; i++) {
+            ManagedFacet fA = (ManagedFacet) a.get(i);
+
+            if (!mergeFacets(doc, cr, output, fA, b)) {
+                writeFacet(doc, cr, output, fA);
+            }
+        }
+    }
+
+
+    protected boolean mergeFacets(
+        Document       doc,
+        ElementCreator cr,
+        Element        output,
+        ManagedFacet   a,
+        List<Facet>    list)
+    {
+        String name = a.getName();
+
+        if (list == null) {
+            return false;
+        }
+
+        for (Facet facet: list) {
+            if (name.equals(facet.getName())) {
+                writeFacet(doc, cr, output, (ManagedFacet) facet);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+    protected void writeFacet(
+        Document       doc,
+        ElementCreator cr,
+        Node           output,
+        ManagedFacet   f)
+    {
+        Element theme = cr.create("theme");
+        cr.addAttr(theme, "artifact", f.getArtifact(), true);
+        cr.addAttr(theme, "facet", f.getName(), true);
+        cr.addAttr(theme, "pos", Integer.toString(f.getPosition()), true);
+        cr.addAttr(theme, "active", Integer.toString(f.getActive()), true);
+
+        output.appendChild(theme);
+    }
+}
+
--- a/flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java	Tue Apr 26 13:17:08 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java	Tue Apr 26 13:29:18 2011 +0000
@@ -73,25 +73,32 @@
 
         Element collection = ec.create("artifact-collection");
         Element artifacts  = ec.create("artifacts");
+        Element attributes = ec.create("attribute");
 
         ec.addAttr(collection, "name", getName(), true);
         ec.addAttr(collection, "uuid", identifier(), true);
         ec.addAttr(collection, "creation", creation,  true);
 
         collection.appendChild(artifacts);
+        collection.appendChild(attributes);
         doc.appendChild(collection);
 
-        Document attribute = getAttribute();
-        if (attribute != null) {
-            Node child = attribute.getFirstChild();
-            collection.appendChild(doc.importNode(child, true));
-        }
-
-        ArtifactDatabase db    = context.getDatabase();
+        ArtifactDatabase db = context.getDatabase();
 
         try {
             String[] artifactUUIDs = getArtifactUUIDs(context);
 
+            Document oldAttrs = getAttribute();
+            Document attrs    = buildAttributes(
+                db, context,
+                oldAttrs,
+                artifactUUIDs);
+
+            db.setCollectionAttribute(identifier(), context.getMeta(), attrs);
+
+            Node child = attrs.getFirstChild();
+            attributes.appendChild(doc.importNode(child, true));
+
             for (String uuid: artifactUUIDs) {
                 try {
                     artifacts.appendChild(
@@ -147,6 +154,37 @@
     }
 
 
+    protected Document buildAttributes(
+        ArtifactDatabase db,
+        CallContext      context,
+        Document         oldAttr,
+        String[]         items)
+    {
+        Document doc = XMLUtils.newDocument();
+
+        XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
+            doc,
+            ArtifactNamespaceContext.NAMESPACE_URI,
+            ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+        AttributeParser aParser = new AttributeParser();
+        OutputParser    oParser = new OutputParser(db, context.getMeta());
+
+        for (String uuid: items) {
+            try {
+                oParser.parse(uuid);
+            }
+            catch (ArtifactDatabaseException ade) {
+                log.warn(ade, ade);
+            }
+        }
+
+        aParser.parse(oldAttr);
+
+        return new AttributeWriter(aParser.getOuts(), oParser.getOuts()).write();
+    }
+
+
     /**
      * This method returns the list of artifact UUIDs that this collections
      * contains.
@@ -324,17 +362,17 @@
     {
         log.debug("Append artifact '" + uuid + "' to collection description");
 
-        // XXX I am not sure if it works well every time with an empty document
-        // in the describe operation of an artifact.
-        Document description = database.describe(uuid, null, context.getMeta());
-
+        // TODO
         String hash = "MYHASH";
-        // TODO
 
         Element ci   = ec.create("artifact");
         ec.addAttr(ci, "uuid", uuid, true);
         ec.addAttr(ci, "hash", hash, true);
 
+        // XXX I am not sure if it works well every time with an empty document
+        // in the describe operation of an artifact.
+        Document description = database.describe(uuid, null, context.getMeta());
+
         Node outputModes = (Node) XMLUtils.xpath(
             description,
             XPATH_ARTIFACT_OUTPUTMODES,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/OutputParser.java	Tue Apr 26 13:29:18 2011 +0000
@@ -0,0 +1,145 @@
+package de.intevation.flys.collections;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.xpath.XPathConstants;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import de.intevation.artifacts.ArtifactDatabase;
+import de.intevation.artifacts.ArtifactDatabaseException;
+import de.intevation.artifacts.ArtifactNamespaceContext;
+import de.intevation.artifacts.CallMeta;
+
+import de.intevation.artifactdatabase.state.DefaultOutput;
+import de.intevation.artifactdatabase.state.Facet;
+import de.intevation.artifactdatabase.state.Output;
+
+import de.intevation.artifacts.common.utils.XMLUtils;
+
+import de.intevation.flys.artifacts.model.ManagedFacet;
+
+
+public class OutputParser {
+
+    /** Constant XPath that points to the outputmodes of an artifact.*/
+    public static final String XPATH_ARTIFACT_OUTPUTMODES =
+        "/art:result/art:outputmodes/art:output";
+
+
+    private static Logger logger = Logger.getLogger(OutputParser.class);
+
+    protected ArtifactDatabase db;
+    protected CallMeta         meta;
+
+    protected Map<String, Output> outs;
+
+
+    public OutputParser(ArtifactDatabase db, CallMeta meta) {
+        this.db   = db;
+        this.meta = meta;
+        this.outs = new HashMap<String, Output>();
+    }
+
+
+    public void parse(String uuid)
+    throws ArtifactDatabaseException
+    {
+        logger.debug("OutputParser.parse: " + uuid);
+
+        // XXX I am not sure if it works well every time with an empty
+        // document in the describe operation of an artifact.
+        Document description = db.describe(uuid, null, meta);
+
+        NodeList outs = (NodeList) XMLUtils.xpath(
+            description,
+            XPATH_ARTIFACT_OUTPUTMODES,
+            XPathConstants.NODESET,
+            ArtifactNamespaceContext.INSTANCE);
+
+        int num = outs != null ? outs.getLength() : 0;
+
+        logger.debug("Artifact has " + num + " outputs.");
+
+        for (int i = 0; i < num; i++) {
+            Node out = outs.item(i);
+
+            parseOutput(uuid, out);
+        }
+    }
+
+
+    public Map<String, Output> getOuts() {
+        return outs;
+    }
+
+
+    protected void addItem(String out, ManagedFacet item) {
+        Output o = outs.get(out);
+
+        if (o != null) {
+            int num = o.getFacets().size();
+            item.setPosition(num+1);
+
+            o.addFacet(item);
+        }
+    }
+
+
+    protected void parseOutput(String uuid, Node out) {
+        String name = XMLUtils.xpathString(
+            out, "@art:name", ArtifactNamespaceContext.INSTANCE);
+
+        if (outs.get(name) == null) {
+            logger.debug("Create new output: " + name);
+            newOutput(out, name);
+        }
+
+        parseItems(uuid, out, name);
+    }
+
+
+    protected void newOutput(Node out, String name) {
+        String desc = XMLUtils.xpathString(
+            out, "@art:description", ArtifactNamespaceContext.INSTANCE);
+
+        String mimetype = XMLUtils.xpathString(
+            out, "@art:mime-type", ArtifactNamespaceContext.INSTANCE);
+
+        Output o = new DefaultOutput(name, desc, mimetype);
+
+        outs.put(name, o);
+    }
+
+
+    protected void parseItems(String uuid, Node out, String outname) {
+        NodeList facets = (NodeList) XMLUtils.xpath(
+            out, "art:facets/art:facet",
+            XPathConstants.NODESET,
+            ArtifactNamespaceContext.INSTANCE);
+
+        int num = facets != null ? facets.getLength() : 0;
+
+        logger.debug("Output has " + num + " facets.");
+
+        for (int i = 0; i < num; i++) {
+            Node facet = facets.item(i);
+
+            String name = XMLUtils.xpathString(
+                facet, "@art:name", ArtifactNamespaceContext.INSTANCE);
+
+            ManagedFacet item = new ManagedFacet(name, null, uuid, 1, 1);
+
+            addItem(outname, item);
+        }
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org