view flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java @ 322:448d0dc64357

The inserted ranges (distance and WQ ranges) are validated in the feed() operation. flys-artifacts/trunk@1716 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Mon, 18 Apr 2011 12:36:08 +0000
parents 9a0e1289bab6
children 16161de47662
line wrap: on
line source
package de.intevation.flys.collections;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
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.Artifact;
import de.intevation.artifacts.ArtifactDatabase;
import de.intevation.artifacts.ArtifactDatabaseException;
import de.intevation.artifacts.ArtifactNamespaceContext;
import de.intevation.artifacts.CallContext;
import de.intevation.artifacts.CallMeta;

import de.intevation.artifacts.common.utils.XMLUtils;

import de.intevation.artifactdatabase.Backend;
import de.intevation.artifactdatabase.Backend.PersistentArtifact;
import de.intevation.artifactdatabase.DefaultArtifactCollection;

import de.intevation.flys.artifacts.context.FLYSContext;
import de.intevation.flys.exports.OutGenerator;


/**
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class FLYSArtifactCollection extends DefaultArtifactCollection {

    /** The logger used in this class.*/
    private static Logger log = Logger.getLogger(FLYSArtifactCollection.class);


    /** Constant XPath that points to the outputmodes of an artifact.*/
    public static final String XPATH_ARTIFACT_OUTPUTMODES =
        "/art:result/art:outputmodes";

    public static final String XPATH_COLLECTION_ITEMS =
        "/art:result/art:artifact-collection/art:collection-item";

    public static final String XPATH_OUT_NAME = "/art:action/@art:name";

    public static final String XPATH_OUT_TYPE = "/art:action/@art:type";



    @Override
    public Document describe(CallContext context) {
        log.debug("FLYSArtifactCollection.describe: " + identifier);

        Document doc = XMLUtils.newDocument();

        XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
            doc,
            ArtifactNamespaceContext.NAMESPACE_URI,
            ArtifactNamespaceContext.NAMESPACE_PREFIX);

        Date creationTime = getCreationTime();
        String creation   = creationTime != null
            ? Long.toString(creationTime.getTime())
            : "";

        Element collection = ec.create("artifact-collection");
        Element artifacts  = ec.create("artifacts");

        ec.addAttr(collection, "name", getName(), true);
        ec.addAttr(collection, "uuid", identifier(), true);
        ec.addAttr(collection, "creation", creation,  true);

        collection.appendChild(artifacts);
        doc.appendChild(collection);

        Document attribute = getAttribute();
        if (attribute != null) {
            Node child = attribute.getFirstChild();
            collection.appendChild(doc.importNode(child, true));
        }

        ArtifactDatabase db    = context.getDatabase();

        try {
            String[] artifactUUIDs = getArtifactUUIDs(context);

            for (String uuid: artifactUUIDs) {
                try {
                    artifacts.appendChild(
                        buildArtifactNode(db, uuid, context, ec));
                }
                catch (ArtifactDatabaseException dbe) {
                    log.warn(dbe, dbe);
                }
            }
        }
        catch (ArtifactDatabaseException ade) {
            log.error(ade, ade);
        }

        return doc;
    }


    @Override
    public void out(Document format, OutputStream out, CallContext context)
    throws IOException
    {
        log.info("FLYSArtifactCollection.out");

        String name = XMLUtils.xpathString(
            format, XPATH_OUT_NAME, ArtifactNamespaceContext.INSTANCE);

        String type = XMLUtils.xpathString(
            format, XPATH_OUT_TYPE, ArtifactNamespaceContext.INSTANCE);

        OutGenerator generator = getOutGenerator(context, name, type);
        if (generator == null) {
            log.error("There is no generator specified for output: " + type);
            // TODO throw an exception.

            return;
        }

        generator.init(format, out, context);

        try {
            Object[][] container = getArtifactsWithAttribute(context);

            for (Object[] obj: container) {
                generator.doOut((Artifact) obj[0], (Document) obj[1]);
            }
        }
        catch (ArtifactDatabaseException ade) {
            log.error(ade, ade);
        }

        generator.generate();
    }


    /**
     * This method returns the list of artifact UUIDs that this collections
     * contains.
     *
     * @param context The CallContext that is necessary to get information about
     * the ArtifactDatabase.
     *
     * @return a list of uuids.
     */
    protected String[] getArtifactUUIDs(CallContext context)
    throws    ArtifactDatabaseException
    {
        log.debug("FLYSArtifactCollection.getArtifactUUIDs");

        ArtifactDatabase db = context.getDatabase();
        CallMeta meta       = context.getMeta();

        Document itemList = db.listCollectionArtifacts(identifier(), meta);
        NodeList items    = (NodeList) XMLUtils.xpath(
            itemList,
            XPATH_COLLECTION_ITEMS,
            XPathConstants.NODESET,
            ArtifactNamespaceContext.INSTANCE);

        if (items == null || items.getLength() == 0) {
            log.debug("No artifacts found in this collection.");
            return null;
        }

        int num = items.getLength();

        List<String> uuids = new ArrayList<String>(num);

        for (int i = 0; i < num; i++) {
            String uuid = XMLUtils.xpathString(
                items.item(i),
                "@art:uuid",
                ArtifactNamespaceContext.INSTANCE);

            if (uuid != null && uuid.trim().length() != 0) {
                uuids.add(uuid);
            }
        }

        return (String[]) uuids.toArray(new String[uuids.size()]);
    }


    /**
     * Returns a concrete Artifact of this collection specified by its uuid.
     *
     * @param uuid The Artifact's uuid.
     * @param context The CallContext.
     *
     * @return an Artifact.
     */
    protected Artifact getArtifact(String uuid, CallContext context)
    throws    ArtifactDatabaseException
    {
        log.debug("FLYSArtifactCollection.getArtifact");

        Backend backend               = Backend.getInstance();
        PersistentArtifact persistent = backend.getArtifact(uuid);

        return persistent != null ? persistent.getArtifact() : null;
    }


    /**
     * Returns the attribute that belongs to an artifact stored in this
     * collection.
     *
     * @param uuid The Artifact's uuid.
     * @param context The CallContext.
     *
     * @return an attribute in form of a document.
     */
    protected Document getArtifactAttribute(String uuid, CallContext context)
    throws    ArtifactDatabaseException
    {
        log.debug("FLYSArtifactCollection.getArtifactAttribute");

        // TODO FILL ME
        return null;
    }


    /**
     * Returns a list of Artifact/Attribute pairs.
     *
     * @param context The CallContext.
     *
     * @return a list of Artifact/Attribute pairs.
     */
    protected Object[][] getArtifactsWithAttribute(CallContext context)
    throws    ArtifactDatabaseException
    {
        log.debug("FLYSArtifactCollection.getArtifactWithAttribute");

        ArtifactDatabase db = context.getDatabase();
        CallMeta meta       = context.getMeta();

        String[] uuids = getArtifactUUIDs(context);
        Object[][] awa = new Object[uuids.length][2];

        for (int i = 0; i < uuids.length; i++) {
            try {
                Artifact artifact  = getArtifact(uuids[i], context);
                Document attribute = getArtifactAttribute(uuids[i], context);

                if (artifact == null) {
                    log.warn("Artifact '" + uuids[i] + "' is not existing.");
                    continue;
                }

                awa[i][0] = artifact;
                awa[i][1] = attribute;
            }
            catch (ArtifactDatabaseException ade) {
                log.warn(ade, ade);
            }
        }

        return awa;
    }


    /**
     * Returns the OutGenerator for a specified <i>type</i>.
     *
     * @param name The name of the output type.
     * @param type Defines the type of the desired OutGenerator.
     *
     * @return The OutGenerator specified by <i>type</i>.
     */
    protected OutGenerator getOutGenerator(
        CallContext context,
        String      name,
        String      type)
    {
        FLYSContext flysContext = context instanceof FLYSContext
            ? (FLYSContext) context
            : (FLYSContext) context.globalContext();

        Map<String, Class> generators = (Map<String, Class>)
            flysContext.get(FLYSContext.OUTGENERATORS_KEY);

        if (generators == null) {
            log.error("No output generators found in the running application!");
            return null;
        }

        Class clazz = generators.get(type);

        try {
            return clazz != null ? (OutGenerator) clazz.newInstance() : null;
        }
        catch (InstantiationException ie) {
            log.error(ie, ie);
        }
        catch (IllegalAccessException iae) {
            log.error(iae, iae);
        }

        return null;
    }


    protected Element buildArtifactNode(
        ArtifactDatabase        database,
        String                  uuid,
        CallContext             context,
        XMLUtils.ElementCreator ec)
    throws ArtifactDatabaseException
    {
        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());

        String hash = "MYHASH";
        // TODO

        Element ci   = ec.create("artifact");
        ec.addAttr(ci, "uuid", uuid, true);
        ec.addAttr(ci, "hash", hash, true);

        Node outputModes = (Node) XMLUtils.xpath(
            description,
            XPATH_ARTIFACT_OUTPUTMODES,
            XPathConstants.NODE,
            ArtifactNamespaceContext.INSTANCE);

        if (outputModes != null) {
            Document doc = ci.getOwnerDocument();
            ci.appendChild(doc.importNode(outputModes, true));
        }

        return ci;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org