view flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java @ 295:53c155bfde07

Added code to parse the configured OutGenerators in the global configuration and to save a map of such in the FLYSContext. flys-artifacts/trunk@1633 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Thu, 31 Mar 2011 10:56:08 +0000
parents 1fa38d60a702
children eca7892bf8ff
line wrap: on
line source
package de.intevation.flys.artifacts.context;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
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.ArtifactContextFactory;

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

import de.intevation.artifactdatabase.state.State;
import de.intevation.artifactdatabase.state.StateEngine;
import de.intevation.artifactdatabase.transition.Transition;
import de.intevation.artifactdatabase.transition.TransitionEngine;

import de.intevation.flys.artifacts.states.StateFactory;
import de.intevation.flys.artifacts.transitions.TransitionFactory;


/**
 * The ArtifactContextFactory is used to initialize basic components and put
 * them into the global context of the application.
 *
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class FLYSContextFactory implements ArtifactContextFactory {

    /** The logger that is used in this class */
    private static Logger logger = Logger.getLogger(FLYSContextFactory.class);

    /** The XPath to the artifacts configured in the configuration. */
    public static final String XPATH_ARTIFACTS =
        "/artifact-database/artifacts/artifact";

    /** The XPath to the name of the artifact. */
    public static final String XPATH_ARTIFACT_NAME = "/artifact/@name";

    /** The XPath to the xlink ref in an artifact configuration. */
    public static final String XPATH_XLINK = "xlink:href";

    /** The XPath to the transitions configured in the artifact config. */
    public static final String XPATH_TRANSITIONS =
        "/artifact/states/transition";

    /** The XPath to the states configured in the artifact config. */
    public static final String XPATH_STATES =
        "/artifact/states/state";

    public static final String XPATH_OUTPUT_GENERATORS =
        "/artifact-database/output-generators/output-generator";

    /**
     * Creates a new FLYSArtifactContext object and initialize all
     * components required by the application.
     *
     * @param config The artifact server configuration.
     * @return a FLYSArtifactContext.
     */
    public Object createArtifactContext(Document config) {
        FLYSContext context = new FLYSContext(config);

        configureTransitions(config, context);
        configureStates(config, context);
        configureOutGenerators(config, context);

        return context;
    }


    /**
     * This method initializes the transition configuration.
     *
     * @param config the config document.
     * @param context the FLYSContext.
     */
    protected void configureTransitions(Document config, FLYSContext context) {
        TransitionEngine engine = new TransitionEngine();

        Document[] artifacts = getArtifactConfigurations(config);
        logger.info("Found " + artifacts.length + " artifacts in the config.");

        for (Document doc: artifacts) {
            List<Transition> transitions = new ArrayList<Transition>();

            String artName = (String) XMLUtils.xpath(
                doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING);

            NodeList list = (NodeList) XMLUtils.xpath(
                doc, XPATH_TRANSITIONS, XPathConstants.NODESET);

            if (list == null) {
                logger.warn("The artifact has no transitions configured.");
                continue;
            }

            int trans = list.getLength();

            logger.info(
                "Artifact '" + artName + "' has " + trans + " transitions.");

            for (int i = 0; i < trans; i++) {
                Transition t = TransitionFactory.createTransition(list.item(i));
                String     s = t.getFrom();
                engine.addTransition(s, t);
            }
        }

        context.put(FLYSContext.TRANSITION_ENGINE_KEY, engine);
    }


    /**
     * This method returns all artifact documents defined in
     * <code>config</code>. <br>NOTE: The artifact configurations need to be
     * stored in own files referenced by an xlink.
     *
     * @param config The global configuration.
     *
     * @return an array of Artifact configurations.
     */
    protected Document[] getArtifactConfigurations(Document config) {
        NodeList artifacts = (NodeList) XMLUtils.xpath(
            config, XPATH_ARTIFACTS, XPathConstants.NODESET);

        int count = artifacts.getLength();

        Document[] artifactDocs = new Document[count];

        for (int i = 0; i < count; i++) {
            Element tmp = (Element) artifacts.item(i);

            String xlink = tmp.getAttribute(XPATH_XLINK);
            xlink        = Config.replaceConfigDir(xlink);

            File artifactFile = new File(xlink);
            artifactDocs[i]   = XMLUtils.parseDocument(artifactFile);
        }

        return artifactDocs;
    }


    /**
     * This method initializes the transition configuration.
     *
     * @param config the config document.
     * @param context the FLYSContext.
     */
    protected void configureStates(Document config, FLYSContext context) {
        StateEngine engine = new StateEngine();

        Document[] artifacts = getArtifactConfigurations(config);
        logger.info("Found " + artifacts.length + " artifacts in the config.");

        for (Document doc: artifacts) {
            List<State> states = new ArrayList<State>();

            String artName = (String) XMLUtils.xpath(
                doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING);

            NodeList stateList = (NodeList) XMLUtils.xpath(
                doc, XPATH_STATES, XPathConstants.NODESET);

            if (stateList == null) {
                logger.warn("The artifact has no states configured.");
                continue;
            }

            int count = stateList.getLength();

            logger.info(
                "Artifact '" + artName + "' has " + count + " states.");

            for (int i = 0; i < count; i++) {
                states.add(StateFactory.createState(
                    stateList.item(i)));
            }

            engine.addStates(artName, states);
        }

        context.put(FLYSContext.STATE_ENGINE_KEY, engine);
    }


    /**
     * This method intializes the provided output generators.
     *
     * @param config the config document.
     * @param context the FLYSContext.
     */
    protected void configureOutGenerators(Document config, FLYSContext context){
        Map<String, Class> generators = new HashMap<String, Class>();

        NodeList outGenerators = (NodeList) XMLUtils.xpath(
            config,
            XPATH_OUTPUT_GENERATORS,
            XPathConstants.NODESET);

        int num = outGenerators == null ? 0 : outGenerators.getLength();

        if (num == 0) {
            logger.warn("No output generators configured in this application.");
            return;
        }

        logger.info("Found " + num + " configured output generators.");

        int idx = 0;

        for (int i = 0; i < num; i++) {
            Node item = outGenerators.item(i);

            String name = (String) XMLUtils.xpath(
                item, "@name", XPathConstants.STRING);

            String clazz = (String) XMLUtils.xpath(
                item, "text()", XPathConstants.STRING);

            if (name == null || clazz == null) {
                continue;
            }

            try {
                generators.put(name, Class.forName(clazz));

                idx++;
            }
            catch (ClassNotFoundException cnfe) {
                logger.warn(cnfe, cnfe);
            }
        }

        logger.info("Successfully loaded " + idx + " output generators.");
        context.put(FLYSContext.OUTGENERATORS_KEY, generators);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org