teichmann@7040: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@7040: * Software engineering by Intevation GmbH teichmann@7040: * teichmann@7040: * This file is Free Software under the GNU AGPL (>=v3) teichmann@7040: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@7040: * documentation coming with Dive4Elements River for details. teichmann@7040: */ teichmann@7040: teichmann@7040: package org.dive4elements.river.exports; teichmann@7040: teichmann@7040: import java.util.ArrayList; teichmann@7040: import java.util.List; teichmann@7040: teichmann@7040: import org.w3c.dom.Element; teichmann@7040: import org.w3c.dom.NodeList; teichmann@7040: teichmann@7040: import org.dive4elements.river.exports.process.Processor; teichmann@7040: teichmann@7040: import org.apache.log4j.Logger; teichmann@7040: teichmann@7048: import org.dive4elements.artifacts.CallContext; teichmann@7048: teichmann@7048: import org.dive4elements.river.artifacts.resources.Resources; teichmann@7048: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@7048: teichmann@7099: import org.dive4elements.artifacts.common.utils.ElementConverter; teichmann@7099: teichmann@7040: public class DiagramAttributes teichmann@7099: implements ElementConverter teichmann@7040: { teichmann@7040: private static Logger log = Logger.getLogger(DiagramAttributes.class); teichmann@7040: teichmann@7143: public interface Evaluator { teichmann@7143: Object evaluate(D4EArtifact artifact, CallContext context); teichmann@7143: } // interface Evaluator teichmann@7143: teichmann@7143: public static final Evaluator TRUE = new Evaluator() { teichmann@7143: @Override teichmann@7143: public Object evaluate(D4EArtifact artifact, CallContext context) { teichmann@7143: return Boolean.TRUE; teichmann@7143: } teichmann@7143: }; teichmann@7143: teichmann@7143: public static final Evaluator FALSE = new Evaluator() { teichmann@7143: @Override teichmann@7143: public Object evaluate(D4EArtifact artifact, CallContext context) { teichmann@7143: return Boolean.TRUE; teichmann@7143: } teichmann@7143: }; teichmann@7143: teichmann@7099: public class Instance { teichmann@7099: teichmann@7099: private List processors; teichmann@7099: teichmann@7099: public Instance() { teichmann@7099: processors = createProcessors(); teichmann@7099: } teichmann@7099: teichmann@7099: private List createProcessors() { teichmann@7099: List processors = teichmann@7099: new ArrayList(axesProcessors.size()); teichmann@7099: for (AxisProcessor ap: axesProcessors) { teichmann@7099: Processor pr = ap.createProcessor(); teichmann@7099: if (pr != null) { teichmann@7099: processors.add(pr); teichmann@7099: } teichmann@7099: } teichmann@7099: return processors; teichmann@7099: } teichmann@7099: aheinecke@7122: public List getProcessorsForAxisName(String axisName) { aheinecke@7122: List retval = new ArrayList(5); teichmann@7099: for (Processor pr: processors) { teichmann@7099: String aName = pr.getAxisName(); teichmann@7099: if (aName != null && axisName.equals(aName)) { aheinecke@7122: retval.add(pr); teichmann@7099: } teichmann@7099: } aheinecke@7122: return retval; teichmann@7099: } teichmann@7099: teichmann@7099: public List getProcessors() { teichmann@7099: return processors; teichmann@7099: } teichmann@7099: teichmann@7099: public Title getTitle() { teichmann@7099: return DiagramAttributes.this.getTitle(); teichmann@7099: } teichmann@7099: teichmann@7099: public Title getSubtitle() { teichmann@7099: return DiagramAttributes.this.getSubtitle(); teichmann@7099: } teichmann@7099: teichmann@7143: public DomainAxisAttributes getDomainAxis() { teichmann@7143: return DiagramAttributes.this.getDomainAxis(); teichmann@7099: } teichmann@7099: teichmann@7099: public int getAxisIndex(String axisName) { teichmann@7099: return DiagramAttributes.this.getAxisIndex(axisName); teichmann@7099: } teichmann@7099: teichmann@7099: public String getAxisName(int index) { teichmann@7099: return DiagramAttributes.this.getAxisName(index); teichmann@7099: } teichmann@7099: teichmann@7099: public List getAxesAttributes() { teichmann@7099: return DiagramAttributes.this.getAxesAttributes(); teichmann@7099: } teichmann@7099: } // class Instance teichmann@7099: teichmann@7048: public static class AxisAttributes { teichmann@7049: private String name; teichmann@7049: private boolean isLeftAlign; teichmann@7049: private boolean forceAlign; teichmann@7062: private boolean includeZero; teichmann@7040: teichmann@7143: private Evaluator isInverted; teichmann@7143: teichmann@7040: public AxisAttributes() { teichmann@7040: } teichmann@7040: teichmann@7049: public AxisAttributes( teichmann@7143: String name, teichmann@7143: boolean isLeftAlign, teichmann@7143: boolean forceAlign, teichmann@7143: boolean includeZero, teichmann@7143: Evaluator isInverted teichmann@7049: ) { teichmann@7049: this.name = name; teichmann@7049: this.isLeftAlign = isLeftAlign; teichmann@7049: this.forceAlign = forceAlign; teichmann@7062: this.includeZero = includeZero; teichmann@7143: this.isInverted = isInverted; teichmann@7040: } teichmann@7040: teichmann@7040: public String getName() { teichmann@7040: return name; teichmann@7040: } teichmann@7049: teichmann@7049: public boolean isLeftAlign() { teichmann@7049: return isLeftAlign; teichmann@7049: } teichmann@7049: teichmann@7049: public boolean forceAlign() { teichmann@7049: return forceAlign; teichmann@7049: } teichmann@7062: teichmann@7062: public boolean includeZero() { teichmann@7062: return includeZero; teichmann@7062: } teichmann@7143: teichmann@7143: public Evaluator isInverted() { teichmann@7143: return isInverted; teichmann@7143: } teichmann@7040: } // class AxisAttributes teichmann@7040: teichmann@7143: public class DomainAxisAttributes extends AxisAttributes { teichmann@7143: teichmann@7143: private Title title; teichmann@7143: teichmann@7143: public DomainAxisAttributes() { teichmann@7143: } teichmann@7143: teichmann@7143: public DomainAxisAttributes( teichmann@7143: String name, teichmann@7143: boolean isLeftAlign, teichmann@7143: boolean forceAlign, teichmann@7143: boolean includeZero, teichmann@7143: Evaluator isInverted, teichmann@7143: Title title teichmann@7143: ) { teichmann@7143: super(name, isLeftAlign, forceAlign, includeZero, isInverted); teichmann@7143: this.title = title; teichmann@7143: } teichmann@7143: teichmann@7143: public Title getTitle() { teichmann@7143: return title; teichmann@7143: } teichmann@7143: } // class DomainAxisAttributes teichmann@7143: teichmann@7099: public static class AxisProcessor { teichmann@7099: teichmann@7099: private Class processorClass; teichmann@7099: private String axisName; teichmann@7099: teichmann@7099: public AxisProcessor(Class processorClass, String axisName) { teichmann@7099: this.processorClass = processorClass; teichmann@7099: this.axisName = axisName; teichmann@7099: } teichmann@7099: teichmann@7099: public Processor createProcessor() { teichmann@7099: try { teichmann@7099: Processor pr = processorClass.newInstance(); teichmann@7099: pr.setAxisName(axisName); teichmann@7099: return pr; teichmann@7099: } teichmann@7099: catch (InstantiationException ie) { teichmann@7099: log.error(ie, ie); teichmann@7099: } teichmann@7099: catch (IllegalAccessException iae) { teichmann@7099: log.error(iae, iae); teichmann@7099: } teichmann@7099: return null; teichmann@7099: } teichmann@7099: teichmann@7099: } // class AxisProcessor teichmann@7099: teichmann@7048: public static class Argument { teichmann@7048: private String expression; teichmann@7048: private String type; teichmann@7048: teichmann@7048: public Argument() { teichmann@7048: } teichmann@7048: teichmann@7048: public Argument(String expression, String type) { teichmann@7048: this.expression = expression; teichmann@7048: this.type = type; teichmann@7048: } teichmann@7048: teichmann@7048: public Object evaluate(D4EArtifact artifact, CallContext context) { teichmann@7048: if (expression.startsWith("artifact.")) { teichmann@7048: String value = artifact.getDataAsString( teichmann@7048: expression.substring("artifact.".length())); teichmann@7048: return convert(value); teichmann@7048: } teichmann@7048: if (expression.startsWith("context.")) { teichmann@7048: return context.getContextValue( teichmann@7048: expression.substring("context.".length())); teichmann@7048: } teichmann@7048: return expression; teichmann@7048: } teichmann@7048: teichmann@7048: private Object convert(String value) { teichmann@7048: if (value == null || type == null) { teichmann@7048: return value; teichmann@7048: } teichmann@7048: if ("double".equals(type)) { teichmann@7048: return Double.valueOf(value); teichmann@7048: } teichmann@7048: if ("int".equals(type)) { teichmann@7048: return Integer.valueOf(value); teichmann@7048: } teichmann@7048: // TODO: more types teichmann@7048: return value; teichmann@7048: } teichmann@7048: } // class Argument teichmann@7048: teichmann@7048: public static class Title { teichmann@7048: teichmann@7048: private String key; teichmann@7048: private String def; teichmann@7048: private List arguments; teichmann@7048: teichmann@7048: public Title() { teichmann@7048: arguments = new ArrayList(5); teichmann@7048: } teichmann@7048: teichmann@7048: public Title(String key) { teichmann@7048: this(key, key); teichmann@7048: } teichmann@7048: teichmann@7048: public Title(String key, String def) { teichmann@7048: this(); teichmann@7048: this.key = key; teichmann@7048: this.def = def; teichmann@7048: } teichmann@7048: teichmann@7048: public String getKey() { teichmann@7048: return key; teichmann@7048: } teichmann@7048: teichmann@7048: public void addArgument(Argument argument) { teichmann@7048: arguments.add(argument); teichmann@7048: } teichmann@7048: aheinecke@7060: public String evaluate(D4EArtifact artifact, CallContext context) { teichmann@7048: if (key == null || key.isEmpty()) { teichmann@7048: return def; teichmann@7048: } teichmann@7048: Object [] args = new Object[arguments.size()]; teichmann@7048: for (int i = 0; i < args.length; ++i) { teichmann@7048: args[i] = arguments.get(i).evaluate(artifact, context); teichmann@7048: } teichmann@7048: return Resources.getMsg(context.getMeta(), key, def, args); teichmann@7048: } teichmann@7048: } // class Title teichmann@7048: teichmann@7040: private List axesAttrs; teichmann@7099: private List axesProcessors; teichmann@7040: teichmann@7048: private Title title; teichmann@7048: private Title subtitle; teichmann@7143: teichmann@7143: private DomainAxisAttributes domainAxis; teichmann@7048: teichmann@7040: public DiagramAttributes() { teichmann@7040: axesAttrs = new ArrayList(5); teichmann@7099: axesProcessors = new ArrayList(5); teichmann@7040: } teichmann@7040: teichmann@7099: @Override teichmann@7099: public Object convert(Element config) { teichmann@7040: parseAxis(config); teichmann@7040: parseProcessors(config); teichmann@7048: parseTitle(config); teichmann@7049: parseSubtitle(config); teichmann@7143: parseDomainAxis(config); teichmann@7099: return this; teichmann@7040: } teichmann@7040: aheinecke@7060: public List getAxesAttributes() { aheinecke@7060: return axesAttrs; aheinecke@7060: } aheinecke@7060: teichmann@7040: private void parseAxis(Element config) { teichmann@7040: NodeList axisNodes = config.getElementsByTagName("axis"); teichmann@7040: teichmann@7040: for (int i = 0, N = axisNodes.getLength(); i < N; ++i) { teichmann@7040: Element axisElement = (Element)axisNodes.item(i); teichmann@7040: String name = axisElement.getAttribute("name").trim(); teichmann@7049: String align = axisElement.getAttribute("align").trim(); teichmann@7062: String includeZero = teichmann@7062: axisElement.getAttribute("include-zero").trim(); teichmann@7143: teichmann@7143: String isInverted = axisElement.getAttribute("inverted"); teichmann@7143: teichmann@7049: if (name.isEmpty()) { teichmann@7049: continue; teichmann@7040: } teichmann@7049: boolean isleftAlign = false; teichmann@7049: boolean forceAlign = false; teichmann@7049: for (String part: align.split("[\\s,]")) { teichmann@7049: part = part.trim(); teichmann@7049: if ("left" .equals(part)) isleftAlign = true; teichmann@7049: else if ("right".equals(part)) isleftAlign = false; teichmann@7049: else if ("force".equals(part)) forceAlign = true; teichmann@7049: } teichmann@7062: teichmann@7143: Evaluator isInvertedE = parseEvaluator(isInverted, FALSE); teichmann@7143: teichmann@7062: axesAttrs.add(new AxisAttributes( teichmann@7062: name, isleftAlign, forceAlign, teichmann@7143: includeZero.equals("true"), teichmann@7143: isInvertedE)); teichmann@7040: } teichmann@7040: } teichmann@7040: teichmann@7143: private Evaluator parseEvaluator(String s, Evaluator def) { teichmann@7143: if ((s = s.trim()).isEmpty()) return def; teichmann@7143: if ("true".equals(s)) return TRUE; teichmann@7143: if ("false".equals(s)) return FALSE; teichmann@7143: if (s.endsWith("()")) { teichmann@7143: s = s.substring(0, s.length()-2).trim(); teichmann@7143: try { teichmann@7143: Class clazz = (Class)Class.forName(s); teichmann@7143: return clazz.newInstance(); teichmann@7143: } teichmann@7143: catch (ClassNotFoundException cnfe) { teichmann@7143: log.error(cnfe, cnfe); teichmann@7143: } teichmann@7143: catch (InstantiationException ie) { teichmann@7143: log.error(ie, ie); teichmann@7143: } teichmann@7143: catch (IllegalAccessException iae) { teichmann@7143: log.error(iae, iae); teichmann@7143: } teichmann@7143: } teichmann@7143: return def; teichmann@7143: } teichmann@7143: teichmann@7099: public List getAxesProcessors() { teichmann@7099: return axesProcessors; teichmann@7040: } teichmann@7040: teichmann@7048: public Title getTitle() { teichmann@7048: return title; teichmann@7048: } teichmann@7048: teichmann@7048: public Title getSubtitle() { teichmann@7048: return subtitle; teichmann@7048: } teichmann@7048: teichmann@7143: public DomainAxisAttributes getDomainAxis() { teichmann@7143: return domainAxis; teichmann@7061: } teichmann@7061: teichmann@7040: private void parseProcessors(Element config) { teichmann@7040: NodeList processorNodes = config.getElementsByTagName("processor"); teichmann@7040: teichmann@7040: for (int i = 0, N = processorNodes.getLength(); i < N; ++i) { teichmann@7040: Element processorElement = (Element)processorNodes.item(i); teichmann@7040: String className = processorElement.getAttribute("class").trim(); teichmann@7040: String axisName = processorElement.getAttribute("axis").trim(); teichmann@7040: if (className.isEmpty() || axisName.isEmpty()) { teichmann@7040: continue; teichmann@7040: } teichmann@7040: teichmann@7040: try { teichmann@7099: Class processorClass = teichmann@7099: (Class)Class.forName(className); teichmann@7099: axesProcessors.add(new AxisProcessor(processorClass, axisName)); teichmann@7040: } teichmann@7040: catch (ClassNotFoundException cnfe) { teichmann@7040: log.error(cnfe, cnfe); teichmann@7040: } teichmann@7040: } teichmann@7040: } teichmann@7048: teichmann@7048: private void parseTitle(Element config) { teichmann@7048: title = extractTitle(config, "title"); teichmann@7048: } teichmann@7048: teichmann@7048: private void parseSubtitle(Element config) { teichmann@7048: subtitle = extractTitle(config, "subtitle"); teichmann@7048: } teichmann@7048: teichmann@7143: private void parseDomainAxis(Element config) { teichmann@7143: Title title = extractTitle(config, "domain-axis"); teichmann@7143: String includeZero = config.getAttribute("include-zero"); teichmann@7143: String isInverted = config.getAttribute("inverted"); teichmann@7143: teichmann@7143: domainAxis = new DomainAxisAttributes( teichmann@7143: "X", teichmann@7143: false, teichmann@7143: false, teichmann@7143: false, teichmann@7143: parseEvaluator(isInverted, FALSE), teichmann@7143: title); teichmann@7061: } teichmann@7061: teichmann@7048: private static Title extractTitle(Element config, String tagName) { teichmann@7048: NodeList titleNodes = config.getElementsByTagName(tagName); teichmann@7048: if (titleNodes.getLength() < 1) { teichmann@7048: return null; teichmann@7048: } teichmann@7048: Element titleElement = (Element)titleNodes.item(0); teichmann@7048: String key = titleElement.getAttribute("key"); teichmann@7048: String def = titleElement.getAttribute("default"); teichmann@7048: Title title = new Title(key, def); teichmann@7048: NodeList argumentNodes = titleElement.getElementsByTagName("arg"); teichmann@7048: for (int i = 0, N = argumentNodes.getLength(); i < N; ++i) { teichmann@7048: Element argumentElement = (Element)argumentNodes.item(i); teichmann@7048: String expression = argumentElement.getAttribute("expr"); teichmann@7048: String type = argumentElement.getAttribute("type"); teichmann@7048: title.addArgument(new Argument(expression, type)); teichmann@7048: } teichmann@7048: return title; teichmann@7048: } aheinecke@7060: aheinecke@7060: public int getAxisIndex(String axisName) { teichmann@7061: for (int i = axesAttrs.size()-1; i >= 0; --i) { aheinecke@7060: if (axesAttrs.get(i).getName().equals(axisName)) { aheinecke@7060: return i; aheinecke@7060: } aheinecke@7060: } aheinecke@7060: return -1; aheinecke@7060: } aheinecke@7068: aheinecke@7068: public String getAxisName(int index) { teichmann@7099: return index < 0 || index >= axesAttrs.size() teichmann@7099: ? "" // null? teichmann@7099: : axesAttrs.get(index).getName(); aheinecke@7068: } teichmann@7040: } teichmann@7040: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :