view flys-artifacts/src/main/java/de/intevation/flys/themes/ThemeFactory.java @ 5818:a4ff4167be1e

Request feature info on all layers and show it as html if the server does not return valid gml. Non queryable layers produce an error message when the request fails. This is good enough
author Andre Heinecke <aheinecke@intevation.de>
date Wed, 24 Apr 2013 17:33:27 +0200
parents a5f65e8983be
children
line wrap: on
line source
package de.intevation.flys.themes;

import de.intevation.artifacts.common.utils.XMLUtils;
import de.intevation.flys.artifacts.FLYSArtifact;
import de.intevation.flys.artifacts.context.FLYSContext;

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

/**
 * @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,
        String groupName)
    {
        if (logger.isDebugEnabled()) {
            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.
        @SuppressWarnings("unchecked")
        Map<String, List<ThemeMapping>> map = (Map<String, List<ThemeMapping>>)
            c.get(FLYSContext.THEME_MAPPING);

        @SuppressWarnings("unchecked")
        List<ThemeGroup> tgs = (List<ThemeGroup>)
            c.get(FLYSContext.THEMES);

        ThemeGroup group = null;
        for (ThemeGroup tg: tgs) {
            if (tg.getName().equals(groupName)) {
                group = tg;
                break;
            }
        }

        if (group == null) {
            logger.warn("No theme group found: '" + groupName + "'");
            return null;
        }

        Map<String, Theme> t = group.getThemes();

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

        if (map == null || map.isEmpty() || t == null || t.isEmpty()) {
            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))
            {
                String target = tm.getTo();

                logger.debug("Found theme '" + target + "'");
                return t.get(target);
            }
        }

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

        logger.warn(msg);

        return null;
    }


    @SuppressWarnings("unchecked")
    public static List<ThemeGroup> getThemeGroups(FLYSContext c) {
        List<ThemeGroup> tgs = (List<ThemeGroup>)
            c.get(FLYSContext.THEMES);
        return tgs;
    }


    @SuppressWarnings("unchecked")
    public static List<Theme> getThemes (FLYSContext c, String name) {
        List<ThemeGroup> tgs = (List<ThemeGroup>)
            c.get(FLYSContext.THEMES);
        if (tgs == null) {
            return null;
        }

        List<Theme> themes = new ArrayList<Theme>();
        for (ThemeGroup tg: tgs) {
            themes.add(tg.getThemeByName(name));
        }
        return themes;
    }

    protected static String getName(Node config) {
        return ((Element)config).getAttribute("name");
    }


    protected static String getDescription(Node config) {
        return ((Element)config).getAttribute("desc");
    }


    protected static void parseInherits(Document themeCfg, Node cfg, Theme t) {
        parseInherits(themeCfg, cfg, t, null);
    }

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

        NodeList inherits = ((Element)cfg).getElementsByTagName("inherit");

        int num = inherits.getLength();

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

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

        if (themes == null) {
            themes = buildThemeMap(themeCfg);
        }

        for (int i = 0; i < num; i++) {
            Node inherit = inherits.item(i);
            String from = ((Element)inherit).getAttribute("from");

            Node tmp = themes.get(from);

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

    protected static Map<String, Node> buildThemeMap(Document themeCfg) {
        Map<String, Node> map = new HashMap<String, Node>();
        String xpath = "/themes/themegroup/theme";

        NodeList nodes = (NodeList)XMLUtils.xpath(
            themeCfg, xpath, XPathConstants.NODESET);

        if (nodes != null) {
            for (int i = 0, N = nodes.getLength(); i < N; ++i) {
                Node node = nodes.item(i);
                String name = ((Element)node).getAttribute("name");
                map.put(name, node);
            }
        }
        return map;
    }


    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 = ((Element)config).getElementsByTagName("field");

        int num = fields.getLength();

        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 = ((Element)field).getAttribute("name");

        logger.debug("Add field " + name + " to theme " + theme.getName());

        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