view flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java @ 4282:8b4988815974

Added marker for Ws and Qs in Historical Discharge WQ charts. Therefore, the XYChartGenerator got two new methods addDomainMarker(Marker, boolean) and addValueMarker(Marker, boolean). The boolean parameters determine, if the marker should be visible or not. This is analogous to addAxisSeries(XYSeries, int, boolean).
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Mon, 29 Oct 2012 05:59:27 +0100
parents 58bdf95df5e4
children 05c9902c761d
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.GlobalContext;

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.model.Module;
import de.intevation.flys.artifacts.states.StateFactory;
import de.intevation.flys.artifacts.transitions.TransitionFactory;
import de.intevation.flys.themes.Theme;
import de.intevation.flys.themes.ThemeGroup;
import de.intevation.flys.themes.ThemeFactory;
import de.intevation.flys.themes.ThemeMapping;


/**
 * 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";

    public static final String XPATH_THEME_CONFIG =
        "/artifact-database/flys/themes/configuration/text()";

    public static final String XPATH_THEMES =
        "theme";

    public static final String XPATH_THEME_GROUPS =
        "/themes/themegroup";

    public static final String XPATH_THEME_MAPPINGS =
        "/themes/mappings/mapping";

    public static final String XPATH_RIVER_WMS =
        "/artifact-database/floodmap/river";

    public static final String XPATH_MODULES = "/artifact-database/modules/module";

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

        configureTransitions(config, context);
        configureStates(config, context);
        configureOutGenerators(config, context);
        configureThemes(config, context);
        configureThemesMappings(config, context);
        configureRiverWMS(config, context);
        configureModules(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) {

            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 " + artName +
                    " 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 " + artName +
                    " 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);
    }


    /**
     * This methods reads the configured themes and puts them into the
     * FLYSContext.
     *
     * @param config The global configuration.
     * @param context The FLYSContext.
     */
    protected void configureThemes(Document config, FLYSContext context) {
        logger.debug("FLYSContextFactory.configureThemes");

        Document cfg = getThemeConfig(config);

        NodeList themeGroups = (NodeList) XMLUtils.xpath(
            cfg, XPATH_THEME_GROUPS, XPathConstants.NODESET);

        int groupNum = themeGroups != null ? themeGroups.getLength() : 0;

        if (groupNum == 0) {
            logger.warn("There are no theme groups configured!");
        }

        logger.info("Found " + groupNum + " theme groups in configuration");

        List<ThemeGroup> groups = new ArrayList<ThemeGroup>();

        for (int g = 0; g < groupNum; g++) {
            Element themeGroup = (Element) themeGroups.item(g);
            NodeList themes = (NodeList) XMLUtils.xpath(
                themeGroup, XPATH_THEMES, XPathConstants.NODESET);

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

            if (num == 0) {
                logger.warn("There are no themes configured!");
                return;
            }

            logger.info("Theme group has " + num + " themes.");

            Map<String, Theme> theThemes = new HashMap<String, Theme>();

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

                Theme theTheme = ThemeFactory.createTheme(cfg, theme);

                if (theme != null) {
                    theThemes.put(theTheme.getName(), theTheme);
                }
            }
            String gName = themeGroup.getAttribute("name");
            groups.add(new ThemeGroup(gName, theThemes));

            logger.info(
                "Initialized " + theThemes.size() + "/" + num + " themes " +
                "of theme-group '" + gName + "'");
        }
        context.put(FLYSContext.THEMES, groups);
    }

    /**
     * This method is used to retrieve the theme configuration document.
     *
     * @param config The global configuration.
     *
     * @return the theme configuration.
     */
    protected Document getThemeConfig(Document config) {
        String themeConfig = (String) XMLUtils.xpath(
            config,
            XPATH_THEME_CONFIG,
            XPathConstants.STRING);

        themeConfig = Config.replaceConfigDir(themeConfig);

        logger.debug("Parse theme cfg: " + themeConfig);

        return XMLUtils.parseDocument(new File(themeConfig));
    }


    protected void configureThemesMappings(Document cfg, FLYSContext context) {
        logger.debug("FLYSContextFactory.configureThemesMappings");

        Document config = getThemeConfig(cfg);

        NodeList mappings = (NodeList) XMLUtils.xpath(
            config, XPATH_THEME_MAPPINGS, XPathConstants.NODESET);

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

        if (num == 0) {
            logger.warn("No theme <--> facet mappins found!");
            return;
        }

        Map<String, List<ThemeMapping>> mapping =
            new HashMap<String, List<ThemeMapping>>();

        for (int i = 0; i < num; i++) {
            Element node = (Element)mappings.item(i);

            String from              = node.getAttribute("from");
            String to                = node.getAttribute("to");
            String pattern           = node.getAttribute("pattern");
            String masterAttrPattern = node.getAttribute("masterAttr");
            String outputPattern     = node.getAttribute("output");

            if (from.length() > 0 && to.length() > 0) {
                List<ThemeMapping> tm = mapping.get(from);

                if (tm == null) {
                    tm = new ArrayList<ThemeMapping>();
                    mapping.put(from, tm);
                }

                tm.add(new ThemeMapping(
                    from, to, pattern, masterAttrPattern, outputPattern));
            }
        }

        logger.debug("Found " + mapping.size() + " theme mappings.");

        context.put(FLYSContext.THEME_MAPPING, mapping);
    }


    protected void configureRiverWMS(Document cfg, FLYSContext context) {
        Map<String, String> riverWMS = new HashMap<String, String>();

        NodeList rivers = (NodeList) XMLUtils.xpath(
            cfg, XPATH_RIVER_WMS, XPathConstants.NODESET);

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

        for (int i = 0; i < num; i++) {
            Element e = (Element) rivers.item(i);

            String river = e.getAttribute("name");
            String url   = XMLUtils.xpathString(e, "river-wms/@url", null);

            if (river != null && url != null) {
                riverWMS.put(river, url);
            }
        }

        logger.debug("Found " + riverWMS.size() + " river WMS.");

        context.put(FLYSContext.RIVER_WMS, riverWMS);
    }


    /**
     * This method initializes the modules configuration.
     *
     * @param config the config document.
     * @param context the FLYSContext.
     */
    protected void configureModules(Document cfg, FLYSContext context) {
        NodeList modulenodes = (NodeList) XMLUtils.xpath(
            cfg, XPATH_MODULES, XPathConstants.NODESET);

        int num = modulenodes != null ? modulenodes.getLength() : 0;
        ArrayList<Module> modules = new ArrayList<Module>(num);

        for (int i = 0; i < num; i++) {
            Element e = (Element) modulenodes.item(i);
            String modulename = e.getAttribute("name");
            String attrselected = e.getAttribute("selected");
            boolean selected = attrselected == null ? false :
                attrselected.equalsIgnoreCase("true");
            logger.debug("Loaded module " + modulename);
            modules.add(new Module(modulename, selected));
        }
        context.put(FLYSContext.MODULES, modules);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org