ingo@147: package de.intevation.flys.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:
christian@3606: import de.intevation.artifactdatabase.Backend;
christian@3606: import de.intevation.artifactdatabase.Backend.PersistentArtifact;
christian@3606: import de.intevation.artifactdatabase.DefaultArtifactCollection;
bjoern@4499: import de.intevation.artifactdatabase.state.Facet;
christian@3606: import de.intevation.artifactdatabase.state.Output;
christian@3606: import de.intevation.artifactdatabase.state.Settings;
christian@3606: import de.intevation.artifactdatabase.state.StateEngine;
ingo@300: import de.intevation.artifacts.Artifact;
ingo@293: import de.intevation.artifacts.ArtifactDatabase;
ingo@293: import de.intevation.artifacts.ArtifactDatabaseException;
ingo@147: import de.intevation.artifacts.ArtifactNamespaceContext;
ingo@147: import de.intevation.artifacts.CallContext;
ingo@293: import de.intevation.artifacts.CallMeta;
ingo@147: import de.intevation.artifacts.common.utils.XMLUtils;
christian@3606: import de.intevation.flys.artifacts.FLYSArtifact;
ingo@300: import de.intevation.flys.artifacts.context.FLYSContext;
ingo@300: import de.intevation.flys.exports.OutGenerator;
christian@3606: import de.intevation.flys.exports.OutputHelper;
felix@1784: import de.intevation.flys.utils.FLYSUtils;
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: */
ingo@147: public class FLYSArtifactCollection extends DefaultArtifactCollection {
felix@1013: /** The logger used in this class. */
ingo@147: private static Logger log = Logger.getLogger(FLYSArtifactCollection.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:
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) {
ingo@147: log.debug("FLYSArtifactCollection.describe: " + identifier);
ingo@147:
ingo@1972: CollectionDescriptionHelper helper = new CollectionDescriptionHelper(
ingo@1972: getName(), identifier(), getCreationTime(), getTTL(),
ingo@1972: context);
ingo@147:
ingo@346: ArtifactDatabase db = context.getDatabase();
ingo@1976:
ingo@1976: Document oldAttrs = getAttribute();
ingo@1976: AttributeParser parser = new AttributeParser(oldAttrs);
ingo@293:
ingo@300: try {
sascha@3315: String[] aUUIDs = getArtifactUUIDs(context);
raimund@2585:
raimund@2585: oldAttrs = removeAttributes(oldAttrs, context);
raimund@2585: parser = new AttributeParser(oldAttrs);
raimund@2585:
ingo@1976: CollectionAttribute newAttr = mergeAttributes(
ingo@1976: db, context, parser, aUUIDs);
ingo@638:
ingo@1979: if (checkOutputSettings(newAttr, context)) {
ingo@1979: saveCollectionAttribute(db, context, 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@971: ArtifactDatabase db,
ingo@971: CallContext context,
ingo@1976: AttributeParser oldParser,
ingo@1976: String[] uuids
ingo@1976: ) {
ingo@1976: CollectionAttribute cAttribute =
ingo@1976: buildOutAttributes(db, context, 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:
ingo@1979: saveCollectionAttribute(db, context, cAttribute);
ingo@1979:
ingo@1979: return cAttribute;
ingo@1979: }
ingo@1979:
ingo@1979:
raimund@2585: protected Document removeAttributes(Document attrs, CallContext context) {
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);
raimund@2594: if(!outputExists(e.getAttribute("name"), context)) {
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: */
raimund@2594: protected boolean outputExists(String name, CallContext context) {
raimund@2585: FLYSArtifact master = getMasterArtifact(context);
raimund@2585: List