view artifacts/src/main/java/org/dive4elements/river/exports/DiagramAttributes.java @ 7122:038a04e001d7

Handle multiple processors for axis labeling. It now looks for the first processor that provides a label != null
author Andre Heinecke <aheinecke@intevation.de>
date Tue, 24 Sep 2013 18:35:21 +0200
parents 24f153ad1f40
children 053e39436ba3
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.exports;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import org.dive4elements.river.exports.process.Processor;

import org.apache.log4j.Logger;

import org.dive4elements.artifacts.CallContext;

import org.dive4elements.river.artifacts.resources.Resources;
import org.dive4elements.river.artifacts.D4EArtifact;

import org.dive4elements.artifacts.common.utils.ElementConverter;

public class DiagramAttributes
implements   ElementConverter
{
    private static Logger log = Logger.getLogger(DiagramAttributes.class);

    public class Instance {

        private List<Processor> processors;

        public Instance() {
            processors = createProcessors();
        }

        private List<Processor> createProcessors() {
            List<Processor> processors =
                new ArrayList<Processor>(axesProcessors.size());
            for (AxisProcessor ap: axesProcessors) {
                Processor pr = ap.createProcessor();
                if (pr != null) {
                    processors.add(pr);
                }
            }
            return processors;
        }

        public List<Processor> getProcessorsForAxisName(String axisName) {
            List<Processor> retval = new ArrayList<Processor>(5);
            for (Processor pr: processors) {
                String aName = pr.getAxisName();
                if (aName != null && axisName.equals(aName)) {
                    retval.add(pr);
                }
            }
            return retval;
        }

        public List<Processor> getProcessors() {
            return processors;
        }

        public Title getTitle() {
            return DiagramAttributes.this.getTitle();
        }

        public Title getSubtitle() {
            return DiagramAttributes.this.getSubtitle();
        }

        public Title getDomainAxisTitle() {
            return DiagramAttributes.this.getDomainAxisTitle();
        }

        public int getAxisIndex(String axisName) {
            return DiagramAttributes.this.getAxisIndex(axisName);
        }

        public String getAxisName(int index) {
            return DiagramAttributes.this.getAxisName(index);
        }

        public List<AxisAttributes> getAxesAttributes() {
            return DiagramAttributes.this.getAxesAttributes();
        }
    } // class Instance

    public static class AxisAttributes {
        private String  name;
        private boolean isLeftAlign;
        private boolean forceAlign;
        private boolean includeZero;

        public AxisAttributes() {
        }

        public AxisAttributes(
            String  name,
            boolean isLeftAlign,
            boolean forceAlign,
            boolean includeZero
        ) {
            this.name        = name;
            this.isLeftAlign = isLeftAlign;
            this.forceAlign  = forceAlign;
            this.includeZero = includeZero;
        }

        public String getName() {
            return name;
        }

        public boolean isLeftAlign() {
            return isLeftAlign;
        }

        public boolean forceAlign() {
            return forceAlign;
        }

        public boolean includeZero() {
            return includeZero;
        }
    } // class AxisAttributes

    public static class AxisProcessor {

        private Class<Processor> processorClass;
        private String axisName;

        public AxisProcessor(Class<Processor> processorClass, String axisName) {
            this.processorClass = processorClass;
            this.axisName = axisName;
        }

        public Processor createProcessor() {
            try {
                Processor pr = processorClass.newInstance();
                pr.setAxisName(axisName);
                return pr;
            }
            catch (InstantiationException ie) {
                log.error(ie, ie);
            }
            catch (IllegalAccessException iae) {
                log.error(iae, iae);
            }
            return null;
        }

    } // class AxisProcessor

    public static class Argument {
        private String expression;
        private String type;

        public Argument() {
        }

        public Argument(String expression, String type) {
            this.expression = expression;
            this.type = type;
        }

        public Object evaluate(D4EArtifact artifact, CallContext context) {
            if (expression.startsWith("artifact.")) {
                String value = artifact.getDataAsString(
                    expression.substring("artifact.".length()));
                return convert(value);
            }
            if (expression.startsWith("context.")) {
                return context.getContextValue(
                    expression.substring("context.".length()));
            }
            return expression;
        }

        private Object convert(String value) {
            if (value == null || type == null) {
                return value;
            }
            if ("double".equals(type)) {
                return Double.valueOf(value);
            }
            if ("int".equals(type)) {
                return Integer.valueOf(value);
            }
            // TODO: more types
            return value;
        }
    } // class Argument

    public static class Title {

        private String key;
        private String def;
        private List<Argument> arguments;

        public Title() {
            arguments = new ArrayList<Argument>(5);
        }

        public Title(String key) {
            this(key, key);
        }

        public Title(String key, String def) {
            this();
            this.key = key;
            this.def = def;
        }

        public String getKey() {
            return key;
        }

        public void addArgument(Argument argument) {
            arguments.add(argument);
        }

        public String evaluate(D4EArtifact artifact, CallContext context) {
            if (key == null || key.isEmpty()) {
                return def;
            }
            Object [] args = new Object[arguments.size()];
            for (int i = 0; i < args.length; ++i) {
                args[i] = arguments.get(i).evaluate(artifact, context);
            }
            return Resources.getMsg(context.getMeta(), key, def, args);
        }
    } // class Title

    private List<AxisAttributes> axesAttrs;
    private List<AxisProcessor>  axesProcessors;

    private Title title;
    private Title subtitle;
    private Title domainAxisTitle;

    public DiagramAttributes() {
        axesAttrs      = new ArrayList<AxisAttributes>(5);
        axesProcessors = new ArrayList<AxisProcessor>(5);
    }

    @Override
    public Object convert(Element config) {
        parseAxis(config);
        parseProcessors(config);
        parseTitle(config);
        parseSubtitle(config);
        parseDomainAxisTitle(config);
        return this;
    }

    public List<AxisAttributes> getAxesAttributes() {
        return axesAttrs;
    }

    private void parseAxis(Element config) {
        NodeList axisNodes = config.getElementsByTagName("axis");

        for (int i = 0, N = axisNodes.getLength(); i < N; ++i) {
            Element axisElement = (Element)axisNodes.item(i);
            String name = axisElement.getAttribute("name").trim();
            String align = axisElement.getAttribute("align").trim();
            String includeZero =
                axisElement.getAttribute("include-zero").trim();
            if (name.isEmpty()) {
                continue;
            }
            boolean isleftAlign = false;
            boolean forceAlign = false;
            for (String part: align.split("[\\s,]")) {
                part = part.trim();
                     if ("left" .equals(part)) isleftAlign = true;
                else if ("right".equals(part)) isleftAlign = false;
                else if ("force".equals(part)) forceAlign  = true;
            }

            axesAttrs.add(new AxisAttributes(
                name, isleftAlign, forceAlign,
                includeZero.equals("true")));
        }
    }

    public List<AxisProcessor> getAxesProcessors() {
        return axesProcessors;
    }

    public Title getTitle() {
        return title;
    }

    public Title getSubtitle() {
        return subtitle;
    }

    public Title getDomainAxisTitle() {
        return domainAxisTitle;
    }

    private void parseProcessors(Element config) {
        NodeList processorNodes = config.getElementsByTagName("processor");

        for (int i = 0, N = processorNodes.getLength(); i < N; ++i) {
            Element processorElement = (Element)processorNodes.item(i);
            String className = processorElement.getAttribute("class").trim();
            String axisName = processorElement.getAttribute("axis").trim();
            if (className.isEmpty() || axisName.isEmpty()) {
                continue;
            }

            try {
                Class<Processor> processorClass =
                    (Class<Processor>)Class.forName(className);
                axesProcessors.add(new AxisProcessor(processorClass, axisName));
            }
            catch (ClassNotFoundException cnfe) {
                log.error(cnfe, cnfe);
            }
        }
    }

    private void parseTitle(Element config) {
        title = extractTitle(config, "title");
    }

    private void parseSubtitle(Element config) {
        subtitle = extractTitle(config, "subtitle");
    }

    private void parseDomainAxisTitle(Element config) {
        domainAxisTitle = extractTitle(config, "domain-axis");
    }

    private static Title extractTitle(Element config, String tagName) {
        NodeList titleNodes = config.getElementsByTagName(tagName);
        if (titleNodes.getLength() < 1) {
            return null;
        }
        Element titleElement = (Element)titleNodes.item(0);
        String key = titleElement.getAttribute("key");
        String def = titleElement.getAttribute("default");
        Title title = new Title(key, def);
        NodeList argumentNodes = titleElement.getElementsByTagName("arg");
        for (int i = 0, N = argumentNodes.getLength(); i < N; ++i) {
            Element argumentElement = (Element)argumentNodes.item(i);
            String expression = argumentElement.getAttribute("expr");
            String type = argumentElement.getAttribute("type");
            title.addArgument(new Argument(expression, type));
        }
        return title;
    }

    public int getAxisIndex(String axisName) {
        for (int i = axesAttrs.size()-1; i >= 0; --i) {
            if (axesAttrs.get(i).getName().equals(axisName)) {
                return i;
            }
        }
        return -1;
    }

    public String getAxisName(int index) {
        return index < 0 || index >= axesAttrs.size()
            ? "" // null?
            : axesAttrs.get(index).getName();
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org