view gnv-artifacts/src/main/java/de/intevation/gnv/artifacts/fis/FISArtifact.java @ 193:34f233123a6f

Adding empty Series into Chart to prevent NPE issue 19 gnv-artifacts/trunk@243 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Mon, 19 Oct 2009 12:06:48 +0000
parents 7fb9441dd8af
children 734ac082c8d1
line wrap: on
line source
/**
 *
 */
package de.intevation.gnv.artifacts.fis;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
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 org.w3c.dom.NodeList;

import de.intevation.artifactdatabase.Config;
import de.intevation.artifactdatabase.DefaultArtifact;
import de.intevation.artifactdatabase.XMLUtils;
import de.intevation.artifacts.Artifact;
import de.intevation.artifacts.ArtifactFactory;
import de.intevation.artifacts.CallContext;
import de.intevation.artifacts.CallMeta;
import de.intevation.gnv.artifacts.GNVArtifactBase;
import de.intevation.gnv.artifacts.context.GNVArtifactContext;
import de.intevation.gnv.artifacts.fis.product.DefaultProduct;
import de.intevation.gnv.artifacts.fis.product.Product;
import de.intevation.gnv.artifacts.ressource.RessourceFactory;
import de.intevation.gnv.transition.DefaultInputData;
import de.intevation.gnv.transition.InputData;
import de.intevation.gnv.utils.ArtifactFactoryUtilities;
import de.intevation.gnv.utils.ArtifactXMLUtilities;

/**
 * @author Tim Englich <tim.englich@intevation.de>
 * 
 */
public class FISArtifact extends DefaultArtifact {

    /**
     * the logger, used to log exceptions and additonaly information
     */
    private static Logger log = Logger.getLogger(GNVArtifactBase.class);
    /**
     * The UID of this Class
     */
    private static final long serialVersionUID = 2874044542701727083L;

    /**
     * The Identifier for the Replacement of the Artifactname
     */
    public static final String XPATH_IDENTIFIER_REPLACE = "IDENTIFIER";

    /**
     * The XPATH to the XML-Fragment that should be used for the Configuration
     */
    public static final String XPATH_ARTIFACT_CONFIGURATION = "/artifact-database/artifacts/artifact[@name='"
                                                              + XPATH_IDENTIFIER_REPLACE
                                                              + "']";

    /**
     * The Name of the Artifact
     */
    private String name = null;

    private Map<String, Product> products = null;

    private Artifact productArtifact = null;

    private Product current = null;

    private ArtifactXMLUtilities xmlUtilities = new ArtifactXMLUtilities();

    /**
     * @see de.intevation.artifactdatabase.DefaultArtifact#advance(org.w3c.dom.Document,
     *      de.intevation.artifacts.CallContext)
     */
    @Override
    public Document advance(Document target, CallContext context) {

        Document result = null;
        if (this.productArtifact == null) {
            if (this.current != null) {

                String uuid = Config.getStringXPath(target,
                        "action/uuid/@value");
                String hash = Config.getStringXPath(target,
                        "action/hash/@value");
                this.productArtifact = this.current.getArtifactFactory()
                        .createArtifact(uuid, context);
                Document feedDocument = xmlUtilities.reInitDocument(this
                        .createFeedProductArtifactDocument(uuid, hash));
                log.debug("Feed ==> "
                          + this.xmlUtilities
                                  .writeDocument2String(feedDocument));
                Document descibeDocument = xmlUtilities
                        .reInitDocument(this.productArtifact.describe(context));
                log.debug("Descibe ==> "
                          + this.xmlUtilities
                                  .writeDocument2String(descibeDocument));
                this.productArtifact.feed(feedDocument, context);
                String targetName = Config.getStringXPath(descibeDocument,
                        "result/reachable-states/state/@name");
                Document advanceDocument = xmlUtilities.reInitDocument(this
                        .createAdvanceProductArtifactDocument(uuid, hash,
                                targetName));
                log.debug("Advance ==> "
                          + this.xmlUtilities
                                  .writeDocument2String(advanceDocument));
                result = this.productArtifact.advance(advanceDocument, context);
            } else {
                String msg = "Artifact is not configured properly. Call feed first.";
                log.error(msg);
                result = new ArtifactXMLUtilities().createExceptionReport(msg,
                        XMLUtils.newDocument());
            }
        } else {
            result = this.productArtifact.advance(target, context);
        }
        return result;
    }

    private Document createAdvanceProductArtifactDocument(String uuid,
                                                          String hash,
                                                          String targetName) {
        Document document = XMLUtils.newDocument();
        Element rootNode = xmlUtilities.createArtifactElement(document,
                "action");

        Element typeNode = xmlUtilities.createArtifactElement(document, "type");
        typeNode.setAttribute("name", "advanve");
        rootNode.appendChild(typeNode);

        Element uuidNode = xmlUtilities.createArtifactElement(document, "uuid");
        uuidNode.setAttribute("value", uuid);
        rootNode.appendChild(uuidNode);

        Element hashNode = xmlUtilities.createArtifactElement(document, "hash");
        hashNode.setAttribute("value", hash);
        rootNode.appendChild(hashNode);
        Element targetNode = xmlUtilities.createArtifactElement(document,
                "target");
        targetNode.setAttribute("name", targetName);
        rootNode.appendChild(targetNode);

        document.appendChild(rootNode);
        return document;
    }

    private Document createFeedProductArtifactDocument(String uuid, String hash) {
        Document document = XMLUtils.newDocument();
        Element rootNode = xmlUtilities.createArtifactElement(document,
                "action");

        Element typeNode = xmlUtilities.createArtifactElement(document, "type");
        typeNode.setAttribute("name", "feed");
        rootNode.appendChild(typeNode);

        Element uuidNode = xmlUtilities.createArtifactElement(document, "uuid");
        uuidNode.setAttribute("value", uuid);
        rootNode.appendChild(uuidNode);

        Element hashNode = xmlUtilities.createArtifactElement(document, "hash");
        hashNode.setAttribute("value", hash);
        rootNode.appendChild(hashNode);

        Element dataNode = xmlUtilities.createArtifactElement(document, "data");
        rootNode.appendChild(dataNode);

        Collection<InputData> parameter = this.current.getParameter();
        if (parameter != null) {
            Iterator<InputData> parameterIt = parameter.iterator();
            while (parameterIt.hasNext()) {
                InputData inputData = parameterIt.next();
                Element inputNode = xmlUtilities.createArtifactElement(
                        document, "input");
                inputNode.setAttribute("name", inputData.getName());
                inputNode.setAttribute("value", inputData.getValue());
                dataNode.appendChild(inputNode);
            }
        }
        document.appendChild(rootNode);
        return document;

    }

    /**
     * @see de.intevation.artifactdatabase.DefaultArtifact#describe(java.lang.Object)
     */
    @Override
    public Document describe(CallContext context) {
        if (this.productArtifact == null) {
            return this.createDescibeOutput(context.getMeta());
        } else {
            Document document = this.productArtifact.describe(context);
            document = new ArtifactXMLUtilities().reInitDocument(document);
            Node staticNode = Config
                    .getNodeXPath(document, "/result/ui/static");
            if (staticNode != null) {
                Node staticUI = this.createSelectBox(document, context
                        .getMeta());
                staticNode.insertBefore(staticUI, staticNode.getFirstChild());
            }
            return document;
        }
    }

    /**
     * @see de.intevation.artifactdatabase.DefaultArtifact#feed(org.w3c.dom.Document,
     *      java.lang.Object)
     */
    @Override
    public Document feed(Document target, CallContext context) {
        log.debug("FISArtifact.feed");
        Document result = null;
        if (this.productArtifact == null) {
            String productName = Config.getStringXPath(target,
                    "action/data/input[@name='product']/@value");
            log.debug("Looking for ProductArtifact " + productName);
            if (this.products.containsKey(productName)) {
                this.current = this.products.get(productName);
                result = new ArtifactXMLUtilities().createSuccessReport(
                        "Feed success New ProductArtifact created", XMLUtils
                                .newDocument());
            } else {
                String msg = "Product does not exists for " + productName;
                log.error(msg);
                result = new ArtifactXMLUtilities().createExceptionReport(msg,
                        XMLUtils.newDocument());
            }
        } else {
            log.debug("Feed a Productartifact");
            result = this.productArtifact.feed(target, context);
        }
        return result;
    }

    /**
     * @see de.intevation.artifactdatabase.DefaultArtifact#out(org.w3c.dom.Document,
     *      java.lang.Object)
     */
    @Override
    public void out(Document format, OutputStream outputStream,
                    CallContext context) throws IOException {
        if (this.productArtifact != null) {
            this.productArtifact.out(format, outputStream, context);
        }
    }

    /**
     * Constructor
     */
    public FISArtifact() {
        super();
    }

    /**
     * @see de.intevation.artifactdatabase.DefaultArtifact#setup(java.lang.String,
     *      de.intevation.artifacts.ArtifactFactory, java.lang.Object)
     */
    @Override
    public void setup(String identifier, ArtifactFactory factory, Object context) {
        log.debug("FISArtifact.setup");
        this.name = factory.getName();
        super.setup(identifier, factory, context);
        if (context instanceof GNVArtifactContext) {
            GNVArtifactContext gnvContext = (GNVArtifactContext) context;
            Document doc = gnvContext.getConfig();
            Node artifactNode = this.getConfigurationFragment(doc);

            NodeList products = Config.getNodeSetXPath(artifactNode,
                    "products/product");
            if (products != null) {
                this.products = new HashMap<String, Product>(products
                        .getLength());
                for (int i = 0; i < products.getLength(); i++) {
                    Node productNode = products.item(i);
                    String productName = Config.getStringXPath(productNode,
                            "@name");
                    NodeList parameterNodes = Config.getNodeSetXPath(
                            productNode, "parameters/parameter");
                    Collection<InputData> parameter = null;
                    if (parameterNodes != null) {
                        parameter = new ArrayList<InputData>(parameterNodes
                                .getLength());
                        for (int j = 0; j < parameterNodes.getLength(); j++) {
                            Node parameterNode = parameterNodes.item(j);
                            String name = Config.getStringXPath(parameterNode,
                                    "@name");
                            String value = Config.getStringXPath(parameterNode,
                                    "@value");
                            parameter.add(new DefaultInputData(name, value));
                        }
                    }
                    Node artifactFactoryNode = Config.getNodeXPath(productNode,
                            "artifact-factory");
                    ArtifactFactory artifactFactory = new ArtifactFactoryUtilities()
                            .createArtitfactFactor(doc, artifactFactoryNode);
                    this.products.put(productName, new DefaultProduct(
                            productName, parameter, artifactFactory));
                }
            }
        }
    }

    protected Node getConfigurationFragment(Document document) {
        log.debug("GNVArtifactBase.getConfigurationFragment");
        String xpathQuery = XPATH_ARTIFACT_CONFIGURATION.replaceAll(
                XPATH_IDENTIFIER_REPLACE, this.name);
        log.debug(xpathQuery);
        return Config.getNodeXPath(document, xpathQuery);
    }

    protected Document createDescibeOutput(CallMeta callMeta) {
        log.debug("GNVArtifactBase.createDescibeOutput");
        Document document = XMLUtils.newDocument();
        Element rootNode = this.createRootNode(document);
        this.createHeader(rootNode, document, "describe");
        this.createOutputs(rootNode, document);
        this.createCurrentState(rootNode, document);
        this.createReachableStates(rootNode, document);
        this.createModel(rootNode, document);
        this.createUserInterface(rootNode, document, callMeta);

        return document;
    }

    protected Element createRootNode(Document document) {
        Element rootNode = xmlUtilities.createArtifactElement(document,
                "result");
        document.appendChild(rootNode);
        return rootNode;
    }

    protected void createHeader(Element parent, Document document,
                                String documentType) {
        Element typeNode = xmlUtilities.createArtifactElement(document, "type");
        typeNode.setAttribute("name", documentType);
        parent.appendChild(typeNode);

        Element uuidNode = xmlUtilities.createArtifactElement(document, "uuid");
        uuidNode.setAttribute("value", super.identifier);
        parent.appendChild(uuidNode);

        Element hashNode = xmlUtilities.createArtifactElement(document, "hash");
        hashNode.setAttribute("value", this.hash());
        parent.appendChild(hashNode);

    }

    protected void createReachableStates(Element parent, Document document) {
        Element stateNode = xmlUtilities.createArtifactElement(document,
                "reachable-states");
        if (this.products != null) {
            Iterator<Product> products = this.products.values().iterator();
            while (products.hasNext()) {
                Product product = products.next();
                Element currentNode = xmlUtilities.createArtifactElement(
                        document, "state");
                currentNode.setAttribute("name", product.getName());
                currentNode.setAttribute("description", product.getName());
                stateNode.appendChild(currentNode);
            }
        }
        parent.appendChild(stateNode);
    }

    protected void createCurrentState(Element parent, Document document) {
        Element stateNode = xmlUtilities.createArtifactElement(document,
                "state");
        stateNode.setAttribute("name", "choose-product");
        stateNode.setAttribute("description",
                "Initialer Stand Auswahl des products");
        parent.appendChild(stateNode);
    }

    protected void createModel(Element parent, Document document) {
        Element modelNode = xmlUtilities.createArtifactElement(document,
                "model");

        Element inputNode = xmlUtilities.createArtifactElement(document,
                "input");
        inputNode.setAttribute("name", "product");
        inputNode.setAttribute("type", "String");
        modelNode.appendChild(inputNode);

        parent.appendChild(modelNode);
    }

    protected void createUserInterface(Element parent, Document document,
                                       CallMeta callMeta) {
        Element uiNode = xmlUtilities.createArtifactElement(document, "ui");
        ArtifactXMLUtilities xmlUtilities = new ArtifactXMLUtilities();
        Node dynamic = xmlUtilities.createArtifactElement(document, "dynamic");
        uiNode.appendChild(dynamic);
        if (this.products != null && !this.products.isEmpty()) {
            Element selectNode = createSelectBox(document, callMeta);

            dynamic.appendChild(selectNode);
        }

        parent.appendChild(uiNode);
    }

    /**
     * @param document
     * @param xmlUtilities
     * @return
     */
    private Element createSelectBox(Document document, CallMeta callMeta) {

        ArtifactXMLUtilities xmlUtilities = new ArtifactXMLUtilities();
        String selectboxName = "product";
        Iterator<Product> it = this.products.values().iterator();
        Element selectNode = xmlUtilities.createXFormElement(document,
                "select1");
        selectNode.setAttribute("ref", selectboxName);

        Element lableNode = xmlUtilities.createXFormElement(document, "label");
        lableNode.setTextContent(RessourceFactory.getInstance().getRessource(
                callMeta.getLanguages(), selectboxName, selectboxName));
        selectNode.appendChild(lableNode);
        Element choiceNode = xmlUtilities.createXFormElement(document,
                "choices");
        selectNode.appendChild(choiceNode);
        while (it.hasNext()) {
            Product p = it.next();
            Element itemNode = xmlUtilities
                    .createXFormElement(document, "item");

            if (this.current != null
                && this.current.getName().equals(p.getName())) {
                itemNode.setAttribute("selected", "true");
            }

            Element choiceLableNode = xmlUtilities.createXFormElement(document,
                    "label");
            choiceLableNode.setTextContent(RessourceFactory.getInstance()
                    .getRessource(callMeta.getLanguages(), p.getName(),
                            p.getName()));
            itemNode.appendChild(choiceLableNode);

            Element choicValueNode = xmlUtilities.createXFormElement(document,
                    "value");
            choicValueNode.setTextContent(p.getName());
            itemNode.appendChild(choicValueNode);

            choiceNode.appendChild(itemNode);

        }
        return selectNode;
    }

    protected void createOutputs(Element parent, Document document) {
        log.debug("GNVArtifactBase.createOutputs");
        Element outputsNode = xmlUtilities.createArtifactElement(document,
                "outputs");
        parent.appendChild(outputsNode);
    }

}

http://dive4elements.wald.intevation.org