view flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeFactory.java @ 2089:0da8874bd378

Added initial state to map artifact to be able to advance and step back. The map artifact overrides describe() to have the complete UI information in the describe response document. flys-artifacts/trunk@3613 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Raimund Renkert <raimund.renkert@intevation.de>
date Fri, 06 Jan 2012 12:02:10 +0000
parents 6f047a407f84
children 83b22ccf48da
line wrap: on
line source
package de.intevation.flys.themes;

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.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

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

import de.intevation.flys.artifacts.context.FLYSContext;
import de.intevation.flys.artifacts.FLYSArtifact;

/**
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 *
 * Mapping-matching rules:
 *
 */
public class ThemeFactory {

    private static Logger logger = Logger.getLogger(ThemeFactory.class);

    /** Trivial, hidden constructor. */
    private ThemeFactory() {
    }


    /**
     * Creates a new theme from <i>config</i>.
     *
     * @param themeCfg The theme config document that is used to fetch parent
     * themes.
     * @param config The theme config node.
     *
     * @return a new theme.
     */
    public static Theme createTheme(Document themeCfg, Node config) {
        String name = getName(config);
        String desc = getDescription(config);

        logger.debug("Create new theme: " + name);

        Theme theme = new DefaultTheme(name, desc);

        parseInherits(themeCfg, config, theme);
        parseFields(config, theme);
        parseAttrs(config, theme);

        return theme;
    }


    /**
     * Get first matching theme for facet.
     *
     * @param name    Name to match "from" of theme mapping.
     * @param pattern String to 'compare' to pattern in mapping.
     * @param output  Name of the current output
     *
     * @return First matching theme.
     */
    public static Theme getTheme(
        FLYSContext c,
        String name,
        String pattern,
        String output)
    {
        logger.debug("Search theme for: " + name + " - pattern: " + pattern);

        if (c == null || name == null) {
            logger.warn("Cannot search for theme.");
            return null;
        }

        // Fetch mapping and themes.
        Map<String, List<ThemeMapping>> map = (Map<String, List<ThemeMapping>>)
            c.get(FLYSContext.THEME_MAPPING);

        Map<String, Theme> t = (Map<String, Theme>)
            c.get(FLYSContext.THEMES);

        FLYSArtifact artifact = (FLYSArtifact) c.get(FLYSContext.ARTIFACT_KEY);

        if (map == null || map.size() == 0 || t == null || t.size() == 0) {
            logger.warn("No mappings or themes found. Cannot retrieve theme!");
            return null;
        }

        List<ThemeMapping> mapping = map.get(name);

        if (mapping == null) {
            logger.warn("No theme found for mapping: " + name);
            return null;
        }

        // Take first mapping of which all conditions are satisfied.
        for (ThemeMapping tm: mapping) {
            if (name.equals(tm.getFrom())
                && tm.applyPattern(pattern)
                && tm.masterAttrMatches(artifact)
                && tm.outputMatches(output))
            {
                return t.get(tm.getTo());
            }
        }

        String msg =
            "No theme found for '" + name +
            "' with pattern '" + pattern + "' and output " + output + ".";

        logger.warn(msg);

        return null;
    }


    protected static String getName(Node config) {
        return (String) XMLUtils.xpath(config, "@name", XPathConstants.STRING);
    }


    protected static String getDescription(Node config) {
        return (String) XMLUtils.xpath(config, "@desc", XPathConstants.STRING);
    }


    protected static void parseInherits(Document themeCfg, Node cfg, Theme t) {
        logger.debug("ThemeFactory.parseInherits");

        NodeList inherits = (NodeList) XMLUtils.xpath(
            cfg, "inherits/inherit", XPathConstants.NODESET);

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

        if (num == 0) {
            logger.debug("Theme does not inherit from other themes.");
            return;
        }

        logger.debug("Theme inherits from " + num + " other themes.");

        for (int i = 0; i < num; i++) {
            Node inherit = inherits.item(i);
            String from  = (String) XMLUtils.xpath(
                inherit, "@from", XPathConstants.STRING);

            Node tmp = getThemeNode(themeCfg, from);

            parseInherits(themeCfg, tmp, t);
            parseFields(tmp, t);
        }
    }


    protected static Node getThemeNode(Document themeCfg, String name) {
        if (name == null) {
            logger.warn("Cannot search theme config without name!");
            return null;
        }

        logger.debug("Search for theme: " + name);

        String xpath = "/themes/theme[@name='" + name + "']";

        return (Node) XMLUtils.xpath(themeCfg, xpath, XPathConstants.NODE);
    }


    protected static void parseFields(Node config, Theme theme) {
        if (config == null || theme == null) {
            logger.warn("Parsing fields without node or theme is senseless!");
            return;
        }

        NodeList fields = (NodeList) XMLUtils.xpath(
            config, "fields/field", XPathConstants.NODESET);

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

        logger.debug("Found " + num + " own fields in this theme.");

        if (num == 0) {
            logger.debug("Theme has no own fields.");
            return;
        }

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

            addField(theme, field);
        }
    }


    protected static void addField(Theme theme, Node field) {
        String name = (String) XMLUtils.xpath(
            field, "@name", XPathConstants.STRING);

        logger.debug("Add field: " + name);

        NamedNodeMap attrs = field.getAttributes();

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

        if (num == 0) {
            logger.warn("This field has no attributes.");
            return;
        }

        ThemeField theField = new DefaultThemeField(name);

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

            String key   = attr.getNodeName();
            String value = attr.getNodeValue();

            theField.setAttribute(key, value);
        }

        theme.addField(name, theField);
    }


    protected static void parseAttrs(Node config, Theme theme) {
        NamedNodeMap attrs = config.getAttributes();

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

        if (num == 0) {
            logger.debug("Theme has no attributes set.");
            return;
        }

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

            String name  = attr.getNodeName();
            String value = attr.getNodeValue();

            theme.addAttribute(name, value);
        }
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org