# HG changeset patch # User Ingo Weinzierl # Date 1303824558 0 # Node ID 16161de47662bb5a947c03ae17a49e2e6daabd60 # Parent 88a669785863ed66143b778ce2f13c6bff2909a1 The Attributes of a collection are written into its DESCRIBE now. flys-artifacts/trunk@1748 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 88a669785863 -r 16161de47662 flys-artifacts/ChangeLog --- 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 + + * 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. + + * 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. + + * 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 * src/main/java/de/intevation/flys/artifacts/context/FLYSContext.java, diff -r 88a669785863 -r 16161de47662 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/ManagedFacet.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 : diff -r 88a669785863 -r 16161de47662 flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeParser.java --- /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 outs; + + + public AttributeParser() { + this.outs = new HashMap(); + } + + + 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 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 : diff -r 88a669785863 -r 16161de47662 flys-artifacts/src/main/java/de/intevation/flys/collections/AttributeWriter.java --- /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 oldAttr; + protected Map newAttr; + + private static Logger logger = Logger.getLogger(AttributeWriter.class); + + + public AttributeWriter( + Map oldAttr, + Map 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 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 facetsA = a.getFacets(); + List facetsB = null; + + if (b != null) { + facetsB = b.getFacets(); + } + + writeFacets(doc, cr, output, facetsA, facetsB); + } + + + protected void writeFacets( + Document doc, + ElementCreator cr, + Element output, + List a, + List 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 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); + } +} + diff -r 88a669785863 -r 16161de47662 flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java --- 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, diff -r 88a669785863 -r 16161de47662 flys-artifacts/src/main/java/de/intevation/flys/collections/OutputParser.java --- /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 outs; + + + public OutputParser(ArtifactDatabase db, CallMeta meta) { + this.db = db; + this.meta = meta; + this.outs = new HashMap(); + } + + + 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 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 :