changeset 1071:9bb1979aabbe

Added a new output state and chart type for vertical profiles using vector data. gnv-artifacts/trunk@1168 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Mon, 07 Jun 2010 15:00:23 +0000
parents 7096a2e13676
children 6f35dcd81418
files gnv-artifacts/ChangeLog gnv-artifacts/doc/conf/queries.properties gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileVectorChart.java gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/vertical/VerticalProfileVectorOutputState.java gnv-artifacts/src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesVectorOutputState.java gnv-artifacts/src/main/java/de/intevation/gnv/utils/VectorDataProcessor.java
diffstat 6 files changed, 365 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/gnv-artifacts/ChangeLog	Mon Jun 07 14:42:42 2010 +0000
+++ b/gnv-artifacts/ChangeLog	Mon Jun 07 15:00:23 2010 +0000
@@ -1,3 +1,25 @@
+2010-06-07  Ingo Weinzierl <ingo.weinzierl@intevation.de>
+
+	* src/main/java/de/intevation/gnv/utils/VectorDataProcessor.java: The
+	  columns used for the final ResultDescriptor are no longer configured here
+	  - they need to be configured in the output states of each product. The
+	  VectorDataProcessor is called with the data collection and these columns
+	  now (so the method signature of process(.) changed).
+
+	* src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesVectorOutputState.java:
+	  Configured ResultDescriptor columns here and adapted method call of
+	  VectorDataProcessor.process(.).
+
+	* src/main/java/de/intevation/gnv/state/profile/vertical/VerticalProfileVectorOutputState.java:
+	  This output state is used while working vector data on verticalprofiles.
+	  Before a chart is generated by this state, the vector data are converted
+	  using VectorDataProcessor.
+
+	* src/main/java/de/intevation/gnv/chart/VerticalProfileVectorChart.java: A
+	  new chart type used for verticalprofiles with vector data.
+
+	* doc/conf/queries.properties: A parameter of an sql statement got a name.
+
 2010-06-07  Tim Englich  <tim.englich@intevation.de>
 
 	  Added functionality to publish the the mbr of the generated layer to
--- a/gnv-artifacts/doc/conf/queries.properties	Mon Jun 07 14:42:42 2010 +0000
+++ b/gnv-artifacts/doc/conf/queries.properties	Mon Jun 07 15:00:23 2010 +0000
@@ -607,7 +607,7 @@
 
 verticalprofile_chart_data_vector= SELECT M.ZLOCATION XORDINATE, \
            TS.PARAMETERID GROUP1, \
-           TVV.TIMEVALUE, \
+           TVV.TIMEVALUE GROUP2, \
            TVV.XCOMPONENT, \
            TVV.YCOMPONENT, \
            TVV.ZCOMPONENT, \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/chart/VerticalProfileVectorChart.java	Mon Jun 07 15:00:23 2010 +0000
@@ -0,0 +1,141 @@
+package de.intevation.gnv.chart;
+
+import de.intevation.gnv.geobackend.base.Result;
+import de.intevation.gnv.geobackend.base.ResultDescriptor;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Locale;
+
+import org.apache.log4j.Logger;
+
+import org.jfree.chart.ChartTheme;
+
+import org.jfree.chart.plot.XYPlot;
+
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+
+/**
+ * This class is used to create xy charts of vertical profiles.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class VerticalProfileVectorChart
+extends      VerticalProfileChart
+{
+    private static Logger logger =
+        Logger.getLogger(VerticalProfileVectorChart.class);
+
+    public VerticalProfileVectorChart(
+        ChartLabels labels,
+        ChartTheme  theme,
+        Collection  parameters,
+        Collection  measurements,
+        Collection  dates,
+        Collection  result,
+        Collection  timeGaps,
+        Locale      locale,
+        boolean     linesVisible,
+        boolean     shapesVisible
+    ) {
+        super(labels, theme, parameters, measurements, dates, result,
+              timeGaps, locale, linesVisible, shapesVisible);
+    }
+
+
+    @Override
+    protected void initData() {
+        logger.debug("init data for verticalprofile chart with vector data.");
+
+        Iterator iter         = resultSet.iterator();
+        Result     row        = null;
+        String     seriesName = null;
+        XYSeries   series     = null;
+
+        int  idx       = 0;
+        int  startPos  = 0;
+        int  endPos    = 0;
+
+        double startValue = 0;
+        double endValue   = 0;
+
+        ResultDescriptor rd = null;
+        int idxSeries       = -1;
+        int idxX            = -1;
+        int idxY            = -1;
+
+        Result[] results =
+            (Result[]) resultSet.toArray(new Result[resultSet.size()]);
+
+        while (iter.hasNext()) {
+            row = (Result) iter.next();
+
+            if (rd == null) {
+                rd        = row.getResultDescriptor();
+                idxSeries = rd.getColumnIndex("SERIES");
+                idxX      = rd.getColumnIndex("XORDINATE");
+                idxY      = rd.getColumnIndex("YORDINATE");
+            }
+
+            if (!row.getString(idxSeries).equals(seriesName)) {
+                logger.debug("prepare data/plot for next dataset.");
+
+                if (series != null) {
+                    gapDetection(results, series, startPos, endPos);
+                    addSeries(series, seriesName, idx);
+
+                    startPos = endPos + 1;
+                }
+
+                seriesName = row.getString(idxSeries);
+
+                logger.debug("next data is '" + seriesName + "'");
+                series = new XYSeries(seriesName);
+            }
+
+            addValue(row, series);
+            Object x = getValue(row);
+            Double y = row.getDouble(idxY);
+            if (x != null && y != null) {
+                storeMaxRange(ranges, y, seriesName);
+                storeMaxValue(values, x, seriesName);
+            }
+
+            endPos++;
+        }
+
+        if (results.length == 0)
+            return;
+
+        gapDetection(results, series, startPos, endPos);
+        addSeries(series, seriesName, idx);
+
+        addDatasets();
+    }
+
+
+    @Override
+    protected void addDatasets() {
+        XYPlot     plot = chart.getXYPlot();
+        int        idx  = 0;
+
+        XYSeriesCollection sc  = null;
+        Iterator           iter = datasets.keySet().iterator();
+
+        while (iter.hasNext()) {
+            String key = (String) iter.next();
+            sc  = (XYSeriesCollection)datasets.get(key);
+            plot.setDataset(idx, sc );
+            logger.debug("Added " + key + " parameter to plot.");
+            prepareAxis(key, idx);
+            adjustRenderer(
+                idx++,
+                sc.getSeriesCount(),
+                linesVisible,
+                shapesVisible
+            );
+        }
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/profile/vertical/VerticalProfileVectorOutputState.java	Mon Jun 07 15:00:23 2010 +0000
@@ -0,0 +1,186 @@
+package de.intevation.gnv.state.profile.vertical;
+
+import au.com.bytecode.opencsv.CSVWriter;
+
+import de.intevation.artifacts.CallContext;
+
+import de.intevation.gnv.artifacts.cache.CacheFactory;
+
+import de.intevation.gnv.chart.Chart;
+import de.intevation.gnv.chart.ChartLabels;
+import de.intevation.gnv.chart.VerticalProfileVectorChart;
+
+import de.intevation.gnv.exports.DefaultExport;
+import de.intevation.gnv.exports.DefaultProfile;
+import de.intevation.gnv.exports.Export;
+import de.intevation.gnv.exports.Export.Profile;
+import de.intevation.gnv.exports.SimpleOdvDataCollector;
+
+import de.intevation.gnv.geobackend.base.Result;
+
+import de.intevation.gnv.utils.VectorDataProcessor;
+
+import de.intevation.gnv.state.exception.StateException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.util.Collection;
+import java.util.Locale;
+
+import net.sf.ehcache.Cache;
+
+import org.apache.log4j.Logger;
+
+import org.jfree.chart.ChartTheme;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class VerticalProfileVectorOutputState
+extends      VerticalProfileOutputState
+{
+    private static Logger logger =
+        Logger.getLogger(VerticalProfileVectorOutputState.class);
+
+    public static final String[] RESULT_COLUMNS = {
+        "YORDINATE", "XORDINATE",
+        "GROUP1",    "GROUP2",     "GROUP3",
+        "DATAID",    "FEATUREID",  "TIMESERIESID",
+        "SERIES"
+    };
+
+
+    public static final String[] ODV_COLUMN_HEADERS = {
+        "Cruise",
+        "Station",
+        "Type",
+        "yyyy-mm-dd hh:mm",
+        "Lon (°E)",
+        "Lat (°N)",
+        "Bot. Depth [m]",
+        "Depth [m]",
+        "QF",
+        "XComponent",
+        "QF",
+        "YComponent",
+        "QF",
+        "ZComponent",
+        "QF",
+        "Speed",
+        "QF",
+        "Direction",
+        "QF"
+    };
+
+    public static final String[] ODV_PROFILE_NAMES = {
+        "CRUISE",
+        "STATION",
+        "TYPE",
+        "TIMEVALUE",
+        "SHAPE",
+        "BOTDEPTH",
+        "DEPTH",
+        "QF",
+        "XCOMPONENT",
+        "QF",
+        "YCOMPONENT",
+        "QF",
+        "ZCOMPONENT",
+        "QF",
+        "SPEED",
+        "QF",
+        "DIRECTION",
+        "QF"};
+
+
+    @Override
+    protected Object getChartResult(String uuid, CallContext callContext) {
+        logger.debug("Fetch chart data for vertical profile with vector data.");
+        CacheFactory factory = CacheFactory.getInstance();
+
+        if (factory.isInitialized()) {
+            // we use a cache
+            logger.info("Using cache.");
+            Cache cache = factory.getCache();
+            String key  = "chart_" + getHash();
+
+            net.sf.ehcache.Element value = cache.get(key);
+            if (value != null) {
+                logger.debug("Found element in cache.");
+                return value.getObjectValue();
+            }
+            else {
+                logger.debug("Element not in cache, we ask the database");
+                Collection<Result> res = (Collection<Result>)getData(queryID);
+                logger.debug("Got " + res.size() + " elements from db.");
+
+                res = VectorDataProcessor.process(res, RESULT_COLUMNS);
+                cache.put(new net.sf.ehcache.Element(key, res));
+
+                return res;
+            }
+        }
+        else {
+            // we don't use a cache, so we have to query the database every
+            // single time
+            logger.info("Not using a cache.");
+            return VectorDataProcessor.process(
+                getData(queryID), RESULT_COLUMNS);
+        }
+    }
+
+
+    @Override
+    protected Chart getChart(
+        ChartLabels  chartLables,
+        ChartTheme   theme,
+        Collection   parameters,
+        Collection   measurements,
+        Collection   dates,
+        Object       result,
+        Locale       locale,
+        String       uuid,
+        boolean      linesVisible,
+        boolean      shapesVisible,
+        CallContext  callContext
+    ) {
+        Chart chart = new VerticalProfileVectorChart(
+            chartLables,
+            theme,
+            parameters,
+            measurements,
+            dates,
+            (Collection)result,
+            timeGapDefinitions,
+            locale,
+            linesVisible,
+            shapesVisible
+        );
+        chart.generateChart();
+
+        return chart;
+    }
+
+
+    @Override
+    protected void createODV(
+        OutputStream outputStream, Collection result, String uuid)
+    throws IOException, StateException
+    {
+        logger.info("Start exporting " + result.size() + " items to odv.");
+        Export export = new DefaultExport(
+            new SimpleOdvDataCollector(ODV_PROFILE_NAMES));
+
+        Profile profile = new DefaultProfile(
+            ODV_COLUMN_HEADERS,
+            '\t',
+            CSVWriter.NO_QUOTE_CHARACTER,
+            CSVWriter.NO_ESCAPE_CHARACTER,
+            "ODV",
+            "ISO-8859-1");
+
+        export.create(profile, outputStream, result);
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesVectorOutputState.java	Mon Jun 07 14:42:42 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesVectorOutputState.java	Mon Jun 07 15:00:23 2010 +0000
@@ -42,6 +42,10 @@
     private static Logger logger =
         Logger.getLogger(TimeSeriesVectorOutputState.class);
 
+    public static final String[] RESULT_COLUMNS = {
+       "YORDINATE", "XORDINATE", "GROUP1", "GROUP2", "GROUP3", "GAPID", "SERIES"
+    };
+
     public static final String[] ODV_COLUMN_HEADERS = {
         "Cruise",
         "Station",
@@ -107,7 +111,7 @@
             else {
                 logger.debug("Element not in cache, we ask the database");
                 Collection<Result> res = (Collection<Result>)getData(queryID);
-                res                    = VectorDataProcessor.process(res);
+                res = VectorDataProcessor.process(res, RESULT_COLUMNS);
                 cache.put(new net.sf.ehcache.Element(key, res));
 
                 return res;
@@ -117,7 +121,8 @@
             // we don't use a cache, so we have to query the database every
             // single time
             logger.info("Not using a cache.");
-            return VectorDataProcessor.process(getData(queryID));
+            return VectorDataProcessor.process(
+                getData(queryID), RESULT_COLUMNS);
         }
     }
 
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/utils/VectorDataProcessor.java	Mon Jun 07 14:42:42 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/utils/VectorDataProcessor.java	Mon Jun 07 15:00:23 2010 +0000
@@ -21,14 +21,12 @@
 
     private static Logger logger = Logger.getLogger(VectorDataProcessor.class);
 
-    public static final String[] COLUMNS = {
-       "YORDINATE", "XORDINATE", "GROUP1", "GROUP2", "GROUP3", "GAPID", "SERIES"
-    };
-
-    public static Collection<Result> process(Collection<Result> input) {
+    public static Collection<Result> process(
+        Collection<Result> input, String[] columnNames)
+    {
         logger.info("Process vector data (" + input.size() + " items)");
 
-        ResultDescriptor outDescriptor = initResultDescriptor();
+        ResultDescriptor outDescriptor = initResultDescriptor(columnNames);
         ResultDescriptor inDescriptor  = null;
         int[]            inIndices     = null;
         int              columns       = -1;
@@ -39,7 +37,7 @@
         for (Result result: input) {
             if (inDescriptor == null || inIndices == null) {
                 inDescriptor = result.getResultDescriptor();
-                inIndices    = inDescriptor.getColumnIndices(COLUMNS);
+                inIndices    = inDescriptor.getColumnIndices(columnNames);
                 columns      = inDescriptor.getColumnCount();
             }
 
@@ -47,7 +45,7 @@
             for (int i = 0; i < columns; i++) {
                 String name = inDescriptor.getColumnName(i);
 
-                if (!StringUtils.contains(COLUMNS, name)) {
+                if (!StringUtils.contains(columnNames, name)) {
                     List list = (List) series.get(name);
                     if (list == null)
                         list = new ArrayList();
@@ -90,12 +88,12 @@
     }
 
 
-    public static ResultDescriptor initResultDescriptor() {
+    public static ResultDescriptor initResultDescriptor(String[] columnNames) {
         logger.debug("Init ResultDescriptor for outgoing results.");
 
         ResultDescriptor desc = new DefaultResultDescriptor();
 
-        for (String name: COLUMNS) {
+        for (String name: columnNames) {
             desc.addColumn(name, "java.lang.String");
         }
 

http://dive4elements.wald.intevation.org