changeset 8892:87a242425467

Introduced ChartExtender that allows to tweak the charts for very specific use cases.
author gernotbelger
date Thu, 15 Feb 2018 13:46:35 +0100
parents f431aec10d2c
children ffebc94cf679
files artifacts/src/main/java/org/dive4elements/river/exports/ChartExtender.java artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java artifacts/src/main/java/org/dive4elements/river/exports/DiagramAttributes.java artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java
diffstat 4 files changed, 106 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartExtender.java	Thu Feb 15 13:46:35 2018 +0100
@@ -0,0 +1,34 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * 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 org.jfree.chart.plot.XYPlot;
+
+/**
+ * Implementors of this class can be used to tweak some very application specific behaviour within the charts.<br/>
+ * Implementations should not have a state, because they are instantiated only once.
+ *
+ * @author Gernot Belger
+ */
+public interface ChartExtender {
+
+    /**
+     * Called after {@link DiagramGenerator#autoZoom(org.jfree.chart.plot.XYPlot)} was called, allows to tweak auto zoom
+     * behavior.
+     */
+    void afterAutoZoom(DiagramGenerator generator);
+
+    /**
+     * Called after the complete chart is generated.
+     * 
+     * @param plot
+     */
+    void afterGenerateChart(DiagramGenerator generator, XYPlot plot);
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java	Wed Feb 14 19:06:21 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java	Thu Feb 15 13:46:35 2018 +0100
@@ -22,6 +22,7 @@
 import java.io.OutputStream;
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -139,6 +140,8 @@
 
     protected String outName;
 
+    private Map<String, IdentifiableNumberAxis> axisNameToAxis = new HashMap<>();
+
     /**
      * Default constructor that initializes internal data structures.
      */
@@ -1479,8 +1482,7 @@
 
         String axisName = axisIndexToName(index);
 
-        IdentifiableNumberAxis axis = new IdentifiableNumberAxis(
-            axisName, getYAxisLabel(axisName));
+        IdentifiableNumberAxis axis = new IdentifiableNumberAxis(axisName, getYAxisLabel(axisName));
 
         axis.setAutoRangeIncludesZero(false);
         axis.setLabelFont(labelFont);
@@ -1489,6 +1491,9 @@
         axis.setLowerMargin(0);
         axis.setUpperMargin(0);
 
+        /* remember axis for lookup */
+        axisNameToAxis.put( axisName, axis );
+        
         return axis;
     }
 
@@ -1599,4 +1604,8 @@
     public CallContext getCallContext() {
         return context;
     }
-}
+    
+    public final IdentifiableNumberAxis getAxis(final String axisName) {
+        return axisNameToAxis.get(axisName);
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DiagramAttributes.java	Wed Feb 14 19:06:21 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DiagramAttributes.java	Thu Feb 15 13:46:35 2018 +0100
@@ -9,6 +9,8 @@
 package org.dive4elements.river.exports;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 import org.w3c.dom.Element;
@@ -82,6 +84,10 @@
         public List<Processor> getProcessors() {
             return processors;
         }
+        
+        public Collection<ChartExtender> getExtenders() {
+            return DiagramAttributes.this.getExtenders();
+        }
 
         public Title getTitle() {
             return DiagramAttributes.this.getTitle();
@@ -345,6 +351,7 @@
 
     private List<AxisAttributes> axesAttrs;
     private List<AxisProcessor>  axesProcessors;
+    private List<ChartExtender> extenders = new ArrayList<>();
 
     private Title title;
     private Title subtitle;
@@ -363,6 +370,7 @@
         parseTitle(config);
         parseSubtitle(config);
         parseDomainAxis(config);
+        parseExtenders(config);
         return this;
     }
 
@@ -459,6 +467,10 @@
     public List<AxisProcessor> getAxesProcessors() {
         return axesProcessors;
     }
+    
+    public Collection<ChartExtender> getExtenders() {
+        return Collections.unmodifiableCollection(extenders);
+    }
 
     public Title getTitle() {
         return title;
@@ -493,6 +505,33 @@
             }
         }
     }
+    
+    private void parseExtenders(final Element config) {
+        final NodeList processorNodes = config.getElementsByTagName("chartextender");
+
+        for (int i = 0, N = processorNodes.getLength(); i < N; ++i) {
+            final Element extenderElement = (Element)processorNodes.item(i);
+            final String className = extenderElement.getAttribute("class").trim();
+            if (className.isEmpty() ) {
+                log.error("chartextender missing 'class' attribute");
+                continue;
+            }
+
+            try {
+                final Class<?> protoclass = Class.forName(className);
+                if( !ChartExtender.class.isAssignableFrom(protoclass) ) {
+                    log.error(String.format( "Chart extender must implement interface ChartExtender: %s", className) );
+                    continue;
+                }
+                
+                final ChartExtender extender = (ChartExtender) protoclass.newInstance();
+                extenders.add(extender);
+            }
+            catch (ClassNotFoundException | InstantiationException | IllegalAccessException cnfe) {
+                log.error(String.format( "Failed to load or create chartextender class: %s", className ), cnfe);
+            }
+        }
+    }
 
     private void parseTitle(Element config) {
         title = extractTitle(config, "title");
--- a/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java	Wed Feb 14 19:06:21 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/DiagramGenerator.java	Thu Feb 15 13:46:35 2018 +0100
@@ -14,6 +14,7 @@
 import java.text.NumberFormat;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -238,6 +239,12 @@
 
         aggregateLegendEntries(plot);
 
+        /* allow extenders to do some work */
+        final Collection<ChartExtender> extenders = this.diagramAttributes.getExtenders();
+        for (final ChartExtender extender : extenders) {
+            extender.afterGenerateChart(this, plot);
+        }
+        
         return chart;
     }
 
@@ -390,12 +397,19 @@
             isLog().evaluate((D4EArtifact)getMaster(), context);
 
         if (logarithmic) {
-            return new LogarithmicAxis(label);
+            final LogarithmicAxis axis = new LogarithmicAxis(label);
+            // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+            axis.setLowerMargin(0);
+            axis.setUpperMargin(0);
+            return axis;
         }
         final NumberAxis axis = new NumberAxis(label);
         // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
         axis.setLowerMargin(0);
         axis.setUpperMargin(0);
+        // REMARK: we overwrite the default values to 0.0, because in earlier version margins were never applied.
+        axis.setLowerMargin(0);
+        axis.setUpperMargin(0);
         return axis;
     }
 
@@ -739,9 +753,14 @@
             log.debug("Prepare zoom settings for y axis at index: " + i);
             zoom(plot, yaxis, getYBounds(Integer.valueOf(i)), yrange);
         }
+        
+        /* allow chart extenders to tweak zoom behaviour */
+        final Collection<ChartExtender> extenders = this.diagramAttributes.getExtenders();
+        for (final ChartExtender extender : extenders) {
+            extender.afterAutoZoom(this);
+        }
     }
 
-
     protected Range getDomainAxisRange() {
         String[] ranges = getDomainAxisRangeFromRequest();
 

http://dive4elements.wald.intevation.org