teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
teichmann@5863: * Software engineering by Intevation GmbH
teichmann@5863: *
teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3)
teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the
teichmann@5994: * documentation coming with Dive4Elements River for details.
teichmann@5863: */
teichmann@5863:
teichmann@5831: package org.dive4elements.river.collections;
ingo@147:
ingo@300: import java.io.IOException;
ingo@300: import java.io.OutputStream;
ingo@300: import java.util.ArrayList;
ingo@638: import java.util.HashMap;
ingo@300: import java.util.List;
ingo@300: import java.util.Map;
ingo@147:
ingo@147: import javax.xml.xpath.XPathConstants;
ingo@147:
ingo@147: import org.apache.log4j.Logger;
ingo@147: import org.w3c.dom.Document;
ingo@147: import org.w3c.dom.Element;
ingo@147: import org.w3c.dom.Node;
ingo@293: import org.w3c.dom.NodeList;
ingo@147:
teichmann@5831: import org.dive4elements.artifactdatabase.Backend;
teichmann@5831: import org.dive4elements.artifactdatabase.Backend.PersistentArtifact;
teichmann@5831: import org.dive4elements.artifactdatabase.DefaultArtifactCollection;
teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet;
teichmann@5831: import org.dive4elements.artifactdatabase.state.Output;
teichmann@5831: import org.dive4elements.artifactdatabase.state.Settings;
teichmann@5831: import org.dive4elements.artifactdatabase.state.StateEngine;
teichmann@5831: import org.dive4elements.artifacts.Artifact;
teichmann@5831: import org.dive4elements.artifacts.ArtifactDatabase;
teichmann@5831: import org.dive4elements.artifacts.ArtifactDatabaseException;
teichmann@5831: import org.dive4elements.artifacts.ArtifactNamespaceContext;
teichmann@5831: import org.dive4elements.artifacts.CallContext;
teichmann@5831: import org.dive4elements.artifacts.CallMeta;
teichmann@5831: import org.dive4elements.artifacts.common.utils.XMLUtils;
teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact;
teichmann@5866: import org.dive4elements.river.artifacts.context.RiverContext;
teichmann@5831: import org.dive4elements.river.exports.OutGenerator;
teichmann@5831: import org.dive4elements.river.exports.OutputHelper;
teichmann@5865: import org.dive4elements.river.utils.RiverUtils;
ingo@147:
ingo@147: /**
felix@4966: * Collection of artifacts, can do outs, describe.
felix@4966: * Lots of stuff done in AttributeParser and AttributeWriter.
felix@4966: * Critical out and facet merging.
ingo@147: * @author Ingo Weinzierl
ingo@147: */
teichmann@5867: public class D4EArtifactCollection extends DefaultArtifactCollection {
teichmann@8202: /** The log used in this class. */
teichmann@5867: private static Logger log = Logger.getLogger(D4EArtifactCollection.class);
ingo@147:
felix@1013: /** Constant XPath that points to the outputmodes of an artifact. */
ingo@147: public static final String XPATH_ARTIFACT_OUTPUTMODES =
ingo@147: "/art:result/art:outputmodes";
ingo@147:
felix@1950: public static final String XPATH_ARTIFACT_STATE_DATA =
felix@1950: "/art:result/art:ui/art:static/art:state/art:data";
felix@1950:
ingo@293: public static final String XPATH_COLLECTION_ITEMS =
ingo@293: "/art:result/art:artifact-collection/art:collection-item";
ingo@293:
ingo@300: public static final String XPATH_OUT_NAME = "/art:action/@art:name";
ingo@300:
ingo@300: public static final String XPATH_OUT_TYPE = "/art:action/@art:type";
ingo@300:
felix@1780: /** Xpath to master artifacts uuid. */
felix@1780: public static final String XPATH_MASTER_UUID =
felix@1780: "/art:artifact-collection/art:artifact/@art:uuid";
felix@1744:
ingo@971: public static final String XPATH_LOADED_RECOMMENDATIONS =
ingo@971: "/art:attribute/art:loaded-recommendations";
ingo@971:
felix@6976: private CallContext context;
felix@6976:
felix@6976: private ArtifactDatabase db;
felix@6976:
felix@6976: protected CallContext getContext() {
felix@6976: return this.context;
felix@6976: }
felix@6976:
felix@6976: protected ArtifactDatabase getArtifactDB() {
felix@6976: return this.db;
felix@6976: }
felix@6976:
felix@6976: protected void setContext(CallContext context) {
felix@6976: this.context = context;
felix@6976: this.db = context.getDatabase();
felix@6976: }
ingo@300:
felix@1628: /**
felix@4966: * Create and return description Document for this collection.
felix@1628: */
ingo@147: @Override
ingo@147: public Document describe(CallContext context) {
teichmann@5867: log.debug("D4EArtifactCollection.describe: " + identifier);
ingo@147:
felix@6976: setContext(context);
felix@6976:
ingo@1972: CollectionDescriptionHelper helper = new CollectionDescriptionHelper(
ingo@1972: getName(), identifier(), getCreationTime(), getTTL(),
ingo@1972: context);
ingo@147:
ingo@1976:
ingo@1976: Document oldAttrs = getAttribute();
ingo@1976: AttributeParser parser = new AttributeParser(oldAttrs);
ingo@293:
ingo@300: try {
felix@6976: String[] aUUIDs = getArtifactUUIDs();
raimund@2585:
felix@6976: oldAttrs = removeAttributes(oldAttrs);
raimund@2585: parser = new AttributeParser(oldAttrs);
raimund@2585:
felix@6976: CollectionAttribute newAttr = mergeAttributes(parser, aUUIDs);
ingo@638:
felix@6976: if (checkOutputSettings(newAttr)) {
felix@6976: saveCollectionAttribute(newAttr);
ingo@1979: }
ingo@1979:
ingo@1972: helper.setAttribute(newAttr);
ingo@346:
sascha@3315: if (aUUIDs != null) {
sascha@3315: for (String uuid: aUUIDs) {
sascha@3315: helper.addArtifact(uuid);
sascha@3315: }
ingo@293: }
ingo@293: }
ingo@293: catch (ArtifactDatabaseException ade) {
ingo@1972: log.error("Error while merging attribute documents.", ade);
ingo@971:
ingo@1976: helper.setAttribute(parser.getCollectionAttribute());
ingo@147: }
ingo@147:
ingo@1976: return helper.toXML();
ingo@147: }
ingo@147:
ingo@147:
ingo@971: /**
ingo@971: * Merge the current art:outputs nodes with the the outputs provided by the
ingo@971: * artifacts in the Collection.
felix@1784: *
felix@1709: * @param uuids Artifact uuids.
ingo@971: */
ingo@1976: protected CollectionAttribute mergeAttributes(
ingo@1976: AttributeParser oldParser,
ingo@1976: String[] uuids
ingo@1976: ) {
ingo@1976: CollectionAttribute cAttribute =
felix@6976: buildOutAttributes(oldParser, uuids);
ingo@971:
ingo@3785: if (cAttribute == null) {
ingo@3785: log.warn("mergeAttributes: cAttribute == null");
ingo@3785: return null;
ingo@3785: }
ingo@3785:
ingo@1976: cAttribute.setLoadedRecommendations(
ingo@1976: getLoadedRecommendations(oldParser.getAttributeDocument()));
ingo@1976:
felix@6976: saveCollectionAttribute(cAttribute);
ingo@1979:
ingo@1979: return cAttribute;
ingo@1979: }
ingo@1979:
ingo@1979:
felix@6976: /**
felix@6976: * Remove those output-elements which have a name that does
felix@6976: * not appear in master artifacts out-list.
felix@6976: * @param attr[in,out] Document to clean and return.
felix@6976: * @return param attr.
felix@6976: */
felix@6976: protected Document removeAttributes(Document attrs) {
raimund@2594: Node outs = (Node) XMLUtils.xpath(
raimund@2594: attrs,
raimund@2594: "/art:attribute/art:outputs",
raimund@2594: XPathConstants.NODE,
raimund@2594: ArtifactNamespaceContext.INSTANCE);
raimund@2594:
raimund@2594: NodeList nodes = (NodeList) XMLUtils.xpath(
raimund@2594: attrs,
raimund@2594: "/art:attribute/art:outputs/art:output",
raimund@2594: XPathConstants.NODESET,
raimund@2594: ArtifactNamespaceContext.INSTANCE);
raimund@2594:
raimund@2594: if (nodes != null) {
raimund@2594: for (int i = 0; i < nodes.getLength(); i++) {
raimund@2594: Element e = (Element)nodes.item(i);
felix@6976: if(!outputExists(e.getAttribute("name"))) {
raimund@2594: outs.removeChild(e);
raimund@2594: }
raimund@2594: }
raimund@2594: }
raimund@2594: return attrs;
raimund@2594: }
raimund@2594:
raimund@2594:
felix@2728: /**
felix@2728: * True if current MasterArtifact has given output.
felix@2728: * @param name Name of the output of interest.
felix@2728: * @param context current context
christian@3081: * @return true if current master artifact has given output.
felix@2728: */
felix@6976: protected boolean outputExists(String name) {
felix@6976: D4EArtifact master = getMasterArtifact();
felix@6976: List