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 <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
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<Output> outList = master.getOutputs(context);
raimund@2585: 
raimund@2594:         for (Output o : outList) {
raimund@2594:             if (name.equals(o.getName())) {
raimund@2594:                 return true;
raimund@2585:             }
raimund@2585:         }
raimund@2594:         return false;
raimund@2585:     }
raimund@2585: 
ingo@1979:     /**
ingo@1979:      * @param db The ArtifactDatabase which is required to save the attribute
ingo@1979:      * into.
ingo@1979:      * @param attribute The CollectionAttribute that should be stored in the
ingo@1979:      * database.
ingo@1979:      *
ingo@1979:      * @return true, if the transaction was successful, otherwise false.
ingo@1979:      */
ingo@1979:     protected boolean saveCollectionAttribute(
ingo@1979:         ArtifactDatabase    db,
ingo@1979:         CallContext         context,
ingo@1979:         CollectionAttribute attribute
ingo@1979:     ) {
ingo@1979:         log.info("Save new CollectionAttribute into database.");
ingo@1979: 
ingo@1979:         Document doc = attribute.toXML();
ingo@971: 
ingo@971:         try {
felix@1013:             // Save the merged document into database.
ingo@971:             db.setCollectionAttribute(identifier(), context.getMeta(), doc);
ingo@1979: 
ingo@1979:             log.info("Saving CollectionAttribute was successful.");
ingo@1979: 
ingo@1979:             return true;
ingo@971:         }
ingo@971:         catch (ArtifactDatabaseException adb) {
ingo@971:             log.error(adb, adb);
ingo@971:         }
ingo@971: 
ingo@1979:         return false;
ingo@971:     }
ingo@971: 
ingo@971: 
ingo@971:     /**
ingo@971:      * Merge the recommendations which have already been loaded from the old
ingo@971:      * attribute document into the new attribute document. This is necessary,
ingo@971:      * because mergeAttributes() only merges the art:outputs nodes - all
felix@3442:      * other nodes are skipped.
ingo@971:      */
ingo@1976:     protected Node getLoadedRecommendations(Document oldAttrs) {
ingo@971:         Element loadedRecoms = (Element) XMLUtils.xpath(
ingo@971:             oldAttrs,
ingo@971:             XPATH_LOADED_RECOMMENDATIONS,
ingo@971:             XPathConstants.NODE,
ingo@971:             ArtifactNamespaceContext.INSTANCE);
ingo@971: 
ingo@1976:         return loadedRecoms;
ingo@971:     }
ingo@971: 
ingo@971: 
ingo@1979:     /**
ingo@1979:      * Evaluates the Output settings. If an Output has no Settings set, the
ingo@1979:      * relevant OutGenerator is used to initialize a default Settings object.
ingo@1979:      *
ingo@1979:      * @param attribute The CollectionAttribute.
ingo@1979:      * @param cc The CallContext.
ingo@1979:      *
ingo@1979:      * @return true, if the CollectionAttribute was modified, otherwise false.
ingo@1979:      */
ingo@1979:     protected boolean checkOutputSettings(
ingo@1979:         CollectionAttribute attribute,
ingo@1979:         CallContext         cc
ingo@1979:     ) {
ingo@1979:         boolean modified = false;
ingo@1979: 
ingo@1979:         Map<String, Output> outputMap = attribute != null
ingo@1979:             ? attribute.getOutputs()
ingo@1979:             : null;
ingo@1979: 
sascha@3555:         if (outputMap == null || outputMap.isEmpty()) {
ingo@1979:             log.debug("No Output Settings check necessary.");
ingo@1979:             return modified;
ingo@1979:         }
ingo@1979: 
ingo@1979: 
teichmann@4050:         for (Map.Entry<String, Output> entry: outputMap.entrySet()) {
ingo@1979:             String outName = entry.getKey();
ingo@1979:             Output output  = entry.getValue();
ingo@1979: 
raimund@3295:             if (outName.equals("sq_overview")) {
raimund@3295:                 continue;
raimund@3295:             }
ingo@1979:             Settings settings = output.getSettings();
ingo@1979: 
ingo@1979:             if (settings == null) {
ingo@1979:                 log.debug("No Settings set for Output '" + outName + "'.");
ingo@1999:                 output.setSettings(
ingo@1999:                     createInitialOutputSettings(cc, attribute, outName));
ingo@1979: 
ingo@1979:                 modified = true;
ingo@1979:             }
ingo@1979:         }
ingo@1979: 
ingo@1979:         return modified;
ingo@1979:     }
ingo@1979: 
ingo@1979: 
ingo@1979:     /**
ingo@1979:      * This method uses the the OutGenerator for the specified Output
ingo@1979:      * <i>out</i> to create an initial Settings object.
ingo@1999:      *
ingo@1999:      * @param cc The CallContext object.
ingo@1999:      * @param attr The CollectionAttribute.
ingo@1999:      * @param out The name of the output.
ingo@1999:      *
ingo@1999:      * @return a default Settings object for the specified Output.
ingo@1979:      */
ingo@1999:     protected Settings createInitialOutputSettings(
ingo@1999:         CallContext         cc,
ingo@1999:         CollectionAttribute attr,
ingo@1999:         String              out
ingo@1999:     ) {
raimund@3295:         OutGenerator outGen = FLYSContext.getOutGenerator(cc, out, null);
ingo@1979: 
ingo@1999:         if (outGen == null) {
ingo@1999:             return null;
ingo@1999:         }
ingo@1999: 
ingo@1988:         // XXX NOTE: the outGen is not able to process its generate() operation,
ingo@1988:         // because it has no OutputStream set!
ingo@1988:         outGen.init(XMLUtils.newDocument(), null, cc);
ingo@1988:         prepareMasterArtifact(outGen, cc);
ingo@1988: 
ingo@1988:         try {
ingo@1999:             Document outAttr = getAttribute(cc, attr, out);
raimund@3295:             OutputHelper helper = new OutputHelper(identifier());
raimund@3295:             helper.doOut(outGen, out, out, outAttr, cc);
ingo@1988:         }
ingo@1988:         catch (ArtifactDatabaseException adbe) {
ingo@1988:             log.error(adbe, adbe);
ingo@1988:         }
ingo@1988:         catch (IOException ioe) {
ingo@1988:             log.error(ioe, ioe);
ingo@1988:         }
ingo@1979: 
ingo@1979:         return outGen.getSettings();
ingo@1979:     }
ingo@1979: 
ingo@1979: 
ingo@300:     @Override
ingo@646:     public void out(
ingo@646:         String       type,
ingo@646:         Document     format,
ingo@646:         OutputStream out,
ingo@646:         CallContext  context)
ingo@300:     throws IOException
ingo@300:     {
sascha@3315:         boolean debug = log.isDebugEnabled();
sascha@3315: 
ingo@1998:         long reqBegin = System.currentTimeMillis();
ingo@1998: 
sascha@3315:         if (debug) {
bjoern@4499:             log.debug(XMLUtils.toString(format));
sascha@3315:             log.debug("FLYSArtifactCollection.out");
sascha@3315:         }
ingo@300: 
ingo@300:         String name = XMLUtils.xpathString(
ingo@300:             format, XPATH_OUT_NAME, ArtifactNamespaceContext.INSTANCE);
ingo@300: 
ingo@646:         String subtype = XMLUtils.xpathString(
ingo@300:             format, XPATH_OUT_TYPE, ArtifactNamespaceContext.INSTANCE);
ingo@300: 
sascha@3315:         if (debug) {
sascha@3315:             log.debug("-> Output name = " + name);
sascha@3315:             log.debug("-> Output type = " + type);
sascha@3315:             log.debug("-> Output subtype = " + subtype);
sascha@3315:         }
ingo@388: 
ingo@646:         OutGenerator generator = null;
felix@1780:         if (type != null
felix@1780:              && type.length() > 0
felix@1780:              && type.indexOf("chartinfo") > 0)
felix@1780:         {
raimund@3295:             generator = FLYSContext.getOutGenerator(context, type, subtype);
ingo@646:         }
ingo@646:         else {
raimund@3295:             generator = FLYSContext.getOutGenerator(context, name, subtype);
ingo@646:         }
ingo@646: 
ingo@300:         if (generator == null) {
ingo@390:             log.error("There is no generator specified for output: " + name);
felix@1013:             // TODO Throw an exception.
ingo@300: 
ingo@300:             return;
ingo@300:         }
ingo@300: 
ingo@1999:         Document        oldAttrs  = getAttribute();
ingo@1999:         AttributeParser parser    = new AttributeParser(oldAttrs);
ingo@1999:         CollectionAttribute cAttr = parser.getCollectionAttribute();
ingo@1999: 
felix@5046:         Output output = cAttr.getOutput(name);
bjoern@4024:         Settings settings = null;
bjoern@4024:         if (output != null) {
bjoern@4024:             settings = output.getSettings();
bjoern@4499: 
bjoern@4499:             if (debug) {
bjoern@4499:                 List<Facet> facets = output.getFacets();
bjoern@4499:                 for(Facet facet: facets) {
bjoern@4499:                     log.debug("  -- Facet " + facet.getName());
bjoern@4499:                 }
bjoern@4499:             }
bjoern@4024:         }
ingo@1999: 
ingo@300:         generator.init(format, out, context);
ingo@2047:         generator.setSettings(settings);
ingo@3422:         generator.setCollection(this);
ingo@1988:         prepareMasterArtifact(generator, context);
ingo@300: 
ingo@1988:         try {
ingo@1999:             Document attr = getAttribute(context, cAttr, name);
raimund@3295:             OutputHelper helper = new OutputHelper(identifier());
raimund@3295:             if (name.equals("sq_overview")) {
raimund@3295:                 helper.doOut(generator, name, subtype, format, context);
raimund@3295:             }
raimund@3295:             helper.doOut(generator, name, subtype, attr, context);
ingo@1988:             generator.generate();
ingo@1988:         }
ingo@1988:         catch (ArtifactDatabaseException adbe) {
ingo@1988:             log.error(adbe, adbe);
ingo@1988:         }
ingo@1998: 
sascha@3316:         if (debug) {
sascha@3316:             long duration = System.currentTimeMillis() -reqBegin;
sascha@3316:             log.info("Processing out(" + name + ") took " + duration + " ms.");
sascha@3316:         }
ingo@1988:     }
ingo@1988: 
ingo@1988: 
ingo@1988:     /**
ingo@1988:      * Sets the master Artifact at the given <i>generator</i>.
ingo@1988:      *
ingo@1988:      * @param generator The generator that gets a master Artifact.
ingo@1988:      * @param cc The CallContext.
ingo@1988:      */
ingo@1988:     protected void prepareMasterArtifact(OutGenerator generator, CallContext cc
ingo@1988:     ) {
felix@1744:         // Get master artifact.
ingo@1988:         FLYSArtifact master = getMasterArtifact(cc);
felix@1784:         if (master != null) {
ingo@1988:             log.debug("Set master Artifact to uuid: " + master.identifier());
felix@1784:             generator.setMasterArtifact(master);
felix@1780:         }
felix@1784:         else {
felix@1784:             log.warn("Could not set master artifact.");
felix@1744:         }
ingo@347:     }
ingo@300: 
ingo@347: 
ingo@347:     /**
felix@1784:      * @return masterartifact or null if exception/not found.
felix@1784:      */
felix@1784:     protected FLYSArtifact getMasterArtifact(CallContext context)
felix@1784:     {
felix@1784:         try {
felix@1784:             ArtifactDatabase db = context.getDatabase();
felix@1784:             CallMeta callMeta   = context.getMeta();
felix@1784:             Document document   = db.getCollectionsMasterArtifact(
felix@1784:                 identifier(), callMeta);
ingo@1972: 
felix@1784:             String masterUUID   = XMLUtils.xpathString(
felix@1784:                 document, XPATH_MASTER_UUID, ArtifactNamespaceContext.INSTANCE);
felix@1784:             FLYSArtifact masterArtifact =
felix@1784:                 (FLYSArtifact) getArtifact(masterUUID, context);
felix@1784:             return masterArtifact;
felix@1784:         }
felix@1784:         catch (ArtifactDatabaseException ade) {
felix@1784:             log.error(ade, ade);
felix@1784:         }
felix@1784:         return null;
felix@1784:     }
felix@1784: 
felix@1784: 
felix@1784:     /**
felix@1628:      * Return merged output document.
felix@1709:      * @param uuids List of artifact uuids.
felix@1628:      */
ingo@1976:     protected CollectionAttribute buildOutAttributes(
ingo@346:         ArtifactDatabase db,
ingo@346:         CallContext      context,
ingo@1976:         AttributeParser  aParser,
felix@1709:         String[]         uuids)
ingo@346:     {
felix@1785:         FLYSContext flysContext = FLYSUtils.getFlysContext(context);
felix@1785:         StateEngine engine = (StateEngine) flysContext.get(
sascha@3608:             FLYSContext.STATE_ENGINE_KEY);
sascha@3608: 
sascha@3608:         if (engine == null) {
sascha@3608:             log.error("buildOutAttributes: engine == null");
sascha@3608:             return null;
sascha@3608:         }
felix@1785: 
felix@1785:         FLYSArtifact masterArtifact = getMasterArtifact(context);
ingo@1972: 
sascha@3608:         if (masterArtifact == null) {
christian@3606:             log.debug("buildOutAttributes: masterArtifact == null");
christian@3606:             return null;
christian@3606:         }
ingo@1972: 
ingo@1976:         OutputParser oParser = new OutputParser(db, context);
ingo@1972: 
felix@1709:         if (uuids != null) {
felix@1709:             for (String uuid: uuids) {
ingo@1175:                 try {
ingo@1175:                     oParser.parse(uuid);
ingo@1175:                 }
ingo@1175:                 catch (ArtifactDatabaseException ade) {
ingo@1175:                     log.warn(ade, ade);
ingo@1175:                 }
ingo@346:             }
ingo@346:         }
ingo@1976: 
ingo@1976:         aParser.parse();
felix@1950: 
christian@3606:         AttributeWriter aWriter = new AttributeWriter(
felix@1709:             db,
ingo@1993:             aParser.getCollectionAttribute(),
felix@1709:             aParser.getOuts(),
felix@1785:             aParser.getFacets(),
felix@1785:             oParser.getOuts(),
felix@1785:             oParser.getFacets(),
felix@1785:             engine.getCompatibleFacets(masterArtifact.getStateHistoryIds())
christian@3606:             );
christian@3606:         return aWriter.write();
ingo@346:     }
ingo@346: 
ingo@346: 
ingo@300:     /**
felix@1780:      * Returns the "attribute" (part of description document) for a specific
felix@1780:      * output type.
ingo@347:      *
ingo@1999:      * @param context The CallContext object.
ingo@1999:      * @param cAttr The CollectionAttribute.
ingo@347:      * @param output The name of the desired output type.
ingo@347:      *
ingo@347:      * @return the attribute for the desired output type.
ingo@347:      */
ingo@1999:     protected Document getAttribute(
ingo@1999:         CallContext         context,
ingo@1999:         CollectionAttribute cAttr,
ingo@1999:         String              output)
ingo@347:     throws    ArtifactDatabaseException
ingo@347:     {
ingo@1976:         Document attr = cAttr.toXML();
ingo@1976: 
sascha@3263:         Map<String, String> vars = new HashMap<String, String>();
sascha@3263:         vars.put("output", output);
sascha@3263: 
ingo@347:         Node out = (Node) XMLUtils.xpath(
ingo@347:             attr,
sascha@3263:             "art:attribute/art:outputs/art:output[@name=$output]",
ingo@347:             XPathConstants.NODE,
sascha@3263:             ArtifactNamespaceContext.INSTANCE,
sascha@3263:             vars);
ingo@347: 
ingo@347: 
ingo@347:         if (out != null) {
ingo@347:             Document o = XMLUtils.newDocument();
ingo@347: 
ingo@347:             o.appendChild(o.importNode(out, true));
ingo@347: 
ingo@347:             return o;
ingo@347:         }
ingo@347: 
ingo@347:         return null;
ingo@347:     }
ingo@347: 
ingo@347: 
ingo@347:     /**
ingo@300:      * This method returns the list of artifact UUIDs that this collections
ingo@300:      * contains.
ingo@300:      *
ingo@300:      * @param context The CallContext that is necessary to get information about
ingo@300:      * the ArtifactDatabase.
ingo@300:      *
ingo@300:      * @return a list of uuids.
ingo@300:      */
ingo@300:     protected String[] getArtifactUUIDs(CallContext context)
ingo@300:     throws    ArtifactDatabaseException
ingo@300:     {
ingo@300:         log.debug("FLYSArtifactCollection.getArtifactUUIDs");
ingo@300: 
ingo@300:         ArtifactDatabase db = context.getDatabase();
ingo@300:         CallMeta meta       = context.getMeta();
ingo@300: 
ingo@300:         Document itemList = db.listCollectionArtifacts(identifier(), meta);
ingo@300:         NodeList items    = (NodeList) XMLUtils.xpath(
ingo@300:             itemList,
ingo@300:             XPATH_COLLECTION_ITEMS,
ingo@300:             XPathConstants.NODESET,
ingo@300:             ArtifactNamespaceContext.INSTANCE);
ingo@300: 
ingo@300:         if (items == null || items.getLength() == 0) {
ingo@300:             log.debug("No artifacts found in this collection.");
ingo@300:             return null;
ingo@300:         }
ingo@300: 
ingo@300:         int num = items.getLength();
ingo@300: 
ingo@300:         List<String> uuids = new ArrayList<String>(num);
ingo@300: 
ingo@300:         for (int i = 0; i < num; i++) {
ingo@300:             String uuid = XMLUtils.xpathString(
ingo@300:                 items.item(i),
ingo@300:                 "@art:uuid",
ingo@300:                 ArtifactNamespaceContext.INSTANCE);
ingo@300: 
ingo@300:             if (uuid != null && uuid.trim().length() != 0) {
ingo@300:                 uuids.add(uuid);
ingo@300:             }
ingo@300:         }
ingo@300: 
sascha@3452:         return uuids.toArray(new String[uuids.size()]);
ingo@300:     }
ingo@300: 
ingo@300: 
ingo@300:     /**
ingo@300:      * Returns a concrete Artifact of this collection specified by its uuid.
ingo@300:      *
ingo@300:      * @param uuid The Artifact's uuid.
ingo@300:      * @param context The CallContext.
ingo@300:      *
ingo@300:      * @return an Artifact.
ingo@300:      */
ingo@300:     protected Artifact getArtifact(String uuid, CallContext context)
ingo@300:     throws    ArtifactDatabaseException
ingo@300:     {
ingo@300:         log.debug("FLYSArtifactCollection.getArtifact");
ingo@300: 
ingo@300:         Backend backend               = Backend.getInstance();
ingo@300:         PersistentArtifact persistent = backend.getArtifact(uuid);
ingo@300: 
ingo@300:         return persistent != null ? persistent.getArtifact() : null;
ingo@300:     }
ingo@300: 
ingo@300: 
ingo@147: }
ingo@147: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :