tim@64: /**
tim@64:  *
tim@64:  */
tim@64: package de.intevation.gnv.transition.timeseries;
tim@64: 
tim@68: import java.io.IOException;
ingo@304: import java.io.File;
tim@73: import java.io.OutputStream;
ingo@321: import java.io.FileOutputStream;
tim@177: import java.io.UnsupportedEncodingException;
tim@217: import java.util.ArrayList;
tim@68: import java.util.Collection;
tim@68: import java.util.Iterator;
tim@217: import java.util.List;
ingo@300: import java.util.Locale;
tim@68: 
tim@95: import javax.xml.transform.Transformer;
tim@95: import javax.xml.transform.TransformerConfigurationException;
tim@95: import javax.xml.transform.TransformerException;
tim@95: import javax.xml.transform.TransformerFactory;
tim@95: import javax.xml.transform.TransformerFactoryConfigurationError;
tim@95: import javax.xml.transform.dom.DOMSource;
tim@95: import javax.xml.transform.stream.StreamResult;
tim@95: 
tim@68: import org.apache.log4j.Logger;
tim@95: import org.w3c.dom.Document;
tim@95: import org.w3c.dom.Element;
tim@95: import org.w3c.dom.Node;
tim@217: import org.w3c.dom.NodeList;
tim@68: 
ingo@300: import org.jfree.chart.ChartTheme;
ingo@300: 
tim@90: import au.com.bytecode.opencsv.CSVWriter;
tim@119: import de.intevation.artifactdatabase.Config;
tim@95: import de.intevation.artifactdatabase.XMLUtils;
tim@117: import de.intevation.artifacts.CallMeta;
tim@178: import de.intevation.artifacts.PreferredLocale;
tim@178: import de.intevation.gnv.artifacts.ressource.RessourceFactory;
ingo@300: import de.intevation.gnv.chart.Chart;
tim@68: import de.intevation.gnv.chart.ChartLabels;
ingo@299: import de.intevation.gnv.chart.TimeSeriesChart;
ingo@304: import de.intevation.gnv.chart.XMLChartTheme;
tim@68: import de.intevation.gnv.chart.exception.TechnicalChartException;
ingo@318: import de.intevation.gnv.exports.ChartExportHelper;
tim@232: import de.intevation.gnv.exports.DefaultExport;
ingo@301: import de.intevation.gnv.exports.DefaultDataCollector;
ingo@301: import de.intevation.gnv.exports.SimpleOdvDataCollector;
tim@232: import de.intevation.gnv.exports.DefaultProfile;
tim@232: import de.intevation.gnv.exports.Export.Profile;
tim@68: import de.intevation.gnv.geobackend.base.Result;
tim@95: import de.intevation.gnv.statistics.Statistic;
tim@253: import de.intevation.gnv.statistics.StatisticSet;
tim@98: import de.intevation.gnv.statistics.Statistics;
tim@95: import de.intevation.gnv.statistics.TimeseriesStatistics;
tim@95: import de.intevation.gnv.statistics.exception.StatisticsException;
tim@217: import de.intevation.gnv.timeseries.gap.DefaultTimeGap;
tim@217: import de.intevation.gnv.timeseries.gap.TimeGap;
tim@91: import de.intevation.gnv.transition.InputData;
tim@64: import de.intevation.gnv.transition.OutputTransitionBase;
tim@68: import de.intevation.gnv.transition.describedata.KeyValueDescibeData;
tim@81: import de.intevation.gnv.transition.describedata.NamedCollection;
tim@68: import de.intevation.gnv.transition.exception.TransitionException;
tim@95: import de.intevation.gnv.utils.ArtifactXMLUtilities;
tim@64: 
ingo@230: 
tim@64: /**
tim@64:  * @author Tim Englich <tim.englich@intevation.de>
tim@117:  * 
tim@64:  */
tim@117: public class TimeSeriesOutputTransition extends OutputTransitionBase {
tim@86: 
ingo@320:     protected static final boolean CACHE_CHART =
ingo@300:         Boolean.parseBoolean(System.getProperty("cache.chart", "false"));
ingo@300: 
ingo@320:     protected static final boolean PDF_FORMAT_LANDSCAPE =
ingo@320:         Boolean.parseBoolean(System.getProperty("export.pdf.landscape","true"));
ingo@320: 
ingo@303:     protected static final String[] IMG_EXPORT_FORMAT = {
ingo@303:         "PNG", "JPEG", "GIF"
ingo@303:     };
ingo@303: 
tim@86:     /**
tim@86:      * The UID of this Class
tim@86:      */
tim@86:     private static final long serialVersionUID = 4178407570503098858L;
tim@117: 
tim@68:     /**
tim@68:      * the logger, used to log exceptions and additonaly information
tim@68:      */
tim@117:     private static Logger log = Logger
tim@117:             .getLogger(TimeSeriesOutputTransition.class);
ingo@300: 
tim@217:     private static List<TimeGap> timeGapDefinitions = null;
tim@117: 
tim@117:     protected String domainLable = "Zeit [UTC]";
tim@171: 
tim@119:     protected String featureValuesName = "featureid";
tim@119:     protected String parameterValuesName = "parameterid";
tim@119:     protected String measuremenValueName = "measurementid";
tim@179:     protected String dateValueName = "dateid";
ingo@230:     
ingo@230:     public static final String [] TIMESERIES_CSV_PROFILE_NAMES = {
ingo@230:         "XORDINATE",
ingo@230:         "YORDINATE",
ingo@230:         "GROUP1",
ingo@230:         "GROUP2",
ingo@230:         "GROUP3"
ingo@230:     };
tim@232:     
tim@232:     public static final String [] TIMESERIES_ODV_PROFILE_NAMES = {
tim@232:           "CRUISE",
tim@232:           "STATION",
tim@232:           "TYPE",
ingo@238:           "SHAPE",
tim@232:           "BOTDEPTH",
tim@247:           "DEPTH",
tim@247:           "TIMEVALUE",
tim@247:           "DATAVALUE",
tim@247:           "PARAMETER"
ingo@239:     };
ingo@239: 
ingo@239: 
ingo@239:     public static final String [] ODV_COLUMN_HEADER = {
ingo@239:         "Cruise",
ingo@239:         "Station",
ingo@239:         "Type",
ingo@239:         "Longitude [deegrees_east]",
ingo@239:         "Latitude [deegrees_north]",
tim@241:         "Bot. Depth [m]",
tim@247:         "Depth [m]",
tim@247:         "Date/Time",
tim@247:         "Value",
tim@247:         "Parameterid"
ingo@239:     };
ingo@230: 
ingo@230:     /**
ingo@230:      * Profile for exporting data to cvs
ingo@230:      */
ingo@230:     public static final Profile TIMESERIES_CSV_PROFILE =
ingo@230:         new DefaultProfile(
ingo@239:             null,
ingo@230:             ',',
ingo@230:             '"',
ingo@230:             '"',
ingo@230:             "CSV",
ingo@230:             "ISO-8859-1");
ingo@230: 
ingo@230:     /**
ingo@230:      * Profile for exporting data to odv
ingo@230:      * TODO Change TIMESERIES_PROFILE_NAMES, which belong to CSV exports
ingo@230:      */
ingo@230:     public static final Profile TIMESERIES_ODV_PROFILE =
ingo@230:         new DefaultProfile(
ingo@239:             ODV_COLUMN_HEADER,
ingo@230:             '\t',
ingo@230:             CSVWriter.NO_QUOTE_CHARACTER,
ingo@230:             CSVWriter.NO_ESCAPE_CHARACTER,
ingo@230:             "ODV",
ingo@230:             "ISO-8859-1");
tim@117: 
tim@64:     /**
tim@64:      * Constructor
tim@64:      */
tim@64:     public TimeSeriesOutputTransition() {
tim@64:         super();
tim@64:     }
tim@64: 
tim@64:     /**
tim@117:      * @see de.intevation.gnv.transition.OutputTransition#out(java.lang.String,
tim@117:      *      java.util.Collection, java.io.OutputStream, java.lang.String,
tim@117:      *      de.intevation.artifacts.CallMeta)
tim@117:      */
ingo@303:     public void out(
ingo@303:         Document format,
ingo@303:         Collection<InputData> inputData,
ingo@303:         OutputStream outputStream,
ingo@303:         String uuid,
ingo@303:         CallMeta callMeta
ingo@303:     ) throws TransitionException
ingo@303:     {
tim@90:         log.debug("TimeSeriesOutputTransition.out");
ingo@303: 
ingo@303:         String outputMode = Config.getStringXPath(
ingo@303:             format,
ingo@303:             "action/out/@name"
ingo@303:         );
ingo@303:         String mimeType   = Config.getStringXPath(
ingo@303:             format,
ingo@303:             "action/out/mime-type/@value"
ingo@303:         );
ingo@303: 
tim@68:         try {
tim@117:             if (outputMode.equalsIgnoreCase("chart")) {
tim@90:                 log.debug("Chart will be generated.");
tim@91:                 int chartWidth = 600;
tim@91:                 int chartHeight = 400;
tim@91:                 try {
tim@117:                     if (inputData != null) {
tim@91:                         Iterator<InputData> it = inputData.iterator();
tim@117:                         while (it.hasNext()) {
tim@91:                             InputData ip = it.next();
tim@117:                             if (ip.getName().equalsIgnoreCase("width")) {
tim@91:                                 chartWidth = Integer.parseInt(ip.getValue());
tim@117:                             } else if (ip.getName().equalsIgnoreCase("height")) {
tim@91:                                 chartHeight = Integer.parseInt(ip.getValue());
tim@91:                             }
tim@91:                         }
tim@91:                     }
tim@91:                 } catch (NumberFormatException e) {
tim@117:                     log.error(e, e);
tim@91:                     throw new TransitionException(e);
tim@91:                 }
ingo@327: 
ingo@315:                 PreferredLocale[] locales = callMeta.getLanguages();
ingo@315:                 Locale[] serverLocales    =
ingo@315:                     RessourceFactory.getInstance().getLocales();
ingo@315:                 Locale locale             =
ingo@315:                     callMeta.getPreferredLocale(serverLocales);
ingo@315: 
ingo@315:                 log.debug(
ingo@315:                     "Best locale - regarding intersection of server and " +
ingo@315:                     "browser locales -  is " + locale.toString()
ingo@315:                 );
ingo@303: 
ingo@331:                 Collection parameters   = this.getParameters(uuid);
ingo@331:                 Collection measurements = this.getMeasurements(uuid);
ingo@331:                 Collection dates        = this.getDates(uuid);
ingo@331: 
ingo@331:                 ChartLabels chartLables = new ChartLabels(
ingo@331:                     createChartTitle(locale, uuid),
ingo@331:                     createChartSubtitle(locale, uuid),
ingo@331:                     domainLable
ingo@331:                 );
ingo@331: 
ingo@331:                 String exportFormat = getExportFormat(mimeType);
ingo@331: 
ingo@331:                 // TODO Remove this and parse input data
ingo@331:                 boolean linesVisible = true;
ingo@331:                 boolean shapesVisible = true;
ingo@331: 
ingo@303:                 this.createChart(
ingo@303:                     outputStream,
ingo@303:                     parameters,
ingo@303:                     measurements,
ingo@303:                     dates,
ingo@303:                     chartLables,
ingo@303:                     uuid,
ingo@304:                     exportFormat,
ingo@315:                     locale,
ingo@304:                     chartWidth,
ingo@327:                     chartHeight,
ingo@327:                     linesVisible,
ingo@327:                     shapesVisible
ingo@303:                 );
ingo@318:             }
ingo@320:             else if (outputMode.equalsIgnoreCase("pdf")) {
ingo@320:                 log.debug("Output mode == pdf");
ingo@320: 
ingo@320:                 Locale[] serverLocales    =
ingo@320:                     RessourceFactory.getInstance().getLocales();
ingo@320:                 Locale locale             =
ingo@320:                     callMeta.getPreferredLocale(serverLocales);
ingo@320: 
ingo@327:                 // TODO Remove this and parse input data
ingo@327:                 boolean linesVisible = true;
ingo@327:                 boolean shapesVisible = true;
ingo@327: 
ingo@320:                 log.debug(
ingo@320:                     "Best locale - regarding intersection of server and " +
ingo@320:                     "browser locales -  is " + locale.toString()
ingo@320:                 );
ingo@320: 
ingo@320:                 createPDF(
ingo@320:                     outputStream,
ingo@320:                     getParameters(uuid),
ingo@320:                     getMeasurements(uuid),
ingo@320:                     getDates(uuid),
ingo@320:                     new ChartLabels(
ingo@331:                         createChartTitle(locale, uuid),
ingo@331:                         createChartSubtitle(locale, uuid),
ingo@331:                         domainLable),
ingo@320:                     uuid,
ingo@320:                     "A4",
ingo@320:                     true,
ingo@327:                     locale,
ingo@327:                     linesVisible,
ingo@327:                     shapesVisible
ingo@320:                 );
ingo@320:             }
ingo@321:             else if (outputMode.equalsIgnoreCase("svg")) {
ingo@321:                 log.debug("Output mode == svg");
ingo@321:                 int width  = 600;
ingo@321:                 int height = 400;
ingo@321: 
ingo@327:                 // TODO Remove this and parse input data
ingo@327:                 boolean linesVisible = true;
ingo@327:                 boolean shapesVisible = true;
ingo@327: 
ingo@321:                 Locale[] serverLocales    =
ingo@321:                     RessourceFactory.getInstance().getLocales();
ingo@321:                 Locale locale             =
ingo@321:                     callMeta.getPreferredLocale(serverLocales);
ingo@321: 
ingo@321:                 log.debug(
ingo@321:                     "Best locale - regarding intersection of server and " +
ingo@321:                     "browser locales -  is " + locale.toString()
ingo@321:                 );
ingo@321: 
ingo@321:                 createSVG(
ingo@321:                     outputStream,
ingo@321:                     getParameters(uuid),
ingo@321:                     getMeasurements(uuid),
ingo@321:                     getDates(uuid),
ingo@321:                     new ChartLabels(
ingo@331:                         createChartTitle(locale, uuid),
ingo@331:                         createChartSubtitle(locale, uuid),
ingo@331:                         domainLable
ingo@331:                     ),
ingo@321:                     uuid,
ingo@321:                     locale,
ingo@321:                     width,
ingo@327:                     height,
ingo@327:                     linesVisible,
ingo@327:                     shapesVisible
ingo@321:                 );
ingo@321:             }
ingo@318:             else if (outputMode.equalsIgnoreCase("csv")) {
tim@90:                 log.debug("CSV-File will be generated.");
tim@232:                 Collection<Result> chartResult = this.getChartResult(uuid);
tim@177:                 this.createCSV(outputStream, chartResult);
tim@117:             } else if (outputMode.equalsIgnoreCase("statistics")) {
tim@95:                 log.debug("Statistics will be generated.");
tim@98:                 Statistics s = getStatisticsGenerator();
tim@232:                 Collection<Result> chartResult = this.getChartResult(uuid);
tim@253:                 Collection<KeyValueDescibeData> parameters = 
tim@253:                                                 this.getParameters(uuid);
tim@253:                 Collection<KeyValueDescibeData> measurements = 
tim@253:                                                 this.getMeasurements(uuid);
tim@253:                 Collection<KeyValueDescibeData> dates = 
tim@253:                                                 this.getDates(uuid);
tim@253:                 Collection<StatisticSet> statistics = 
tim@253:                                       s.calculateStatistics(chartResult,
tim@253:                                                             parameters,
tim@253:                                                             measurements,
tim@253:                                                             dates);
tim@95:                 Document doc = this.writeStatistics2XML(statistics);
tim@95:                 this.writeDocument2OutputStream(doc, outputStream);
ingo@230:             } else if (outputMode.equalsIgnoreCase("odv")) {
tim@232:                 
tim@232:                 Collection<Result> odvResult = this.getODVResult(uuid);
tim@232:                 this.createODV(outputStream, odvResult);
tim@90:             }
tim@68:         } catch (IOException e) {
tim@117:             log.error(e, e);
tim@68:             throw new TransitionException(e);
tim@68:         } catch (TechnicalChartException e) {
tim@117:             log.error(e, e);
tim@68:             throw new TransitionException(e);
tim@117:         } catch (StatisticsException e) {
tim@117:             log.error(e, e);
tim@95:             throw new TransitionException(e);
tim@68:         }
tim@68:     }
tim@98: 
ingo@303: 
ingo@303:     protected String getExportFormat(String mime) {
ingo@303:         for(int i = 0; i < IMG_EXPORT_FORMAT.length; i++) {
ingo@303:             if (mime.trim().toUpperCase().indexOf(IMG_EXPORT_FORMAT[i]) > 0)
ingo@303:                 return IMG_EXPORT_FORMAT[i];
ingo@303:         }
ingo@303: 
ingo@303:         // no format found relating to mimeType, default export as PNG
ingo@303:         return IMG_EXPORT_FORMAT[0];
ingo@303:     }
ingo@303: 
ingo@303: 
tim@98:     /**
tim@177:      * @param outputStream
tim@177:      * @param chartResult
tim@177:      * @throws UnsupportedEncodingException
tim@177:      * @throws IOException
tim@177:      * @throws TransitionException
tim@177:      */
tim@177:     protected void createCSV(OutputStream outputStream,
tim@177:                             Collection<Result> chartResult)
tim@177:                                                           throws UnsupportedEncodingException,
tim@177:                                                           IOException,
tim@177:                                                           TransitionException {
ingo@233:         DefaultExport export = new DefaultExport(new DefaultDataCollector(
ingo@233:             TIMESERIES_CSV_PROFILE_NAMES));
ingo@230: 
ingo@230:         export.create(TIMESERIES_CSV_PROFILE, outputStream, chartResult);
ingo@230:     }
ingo@230: 
ingo@230:     /**
ingo@230:      * TODO Result is not used at the moment. Change result with correct data.
ingo@230:      */
ingo@230:     protected void createODV(OutputStream outputStream, Collection result)
ingo@230:     throws IOException, TransitionException {
ingo@230: 
ingo@238:         DefaultExport export = new DefaultExport(new SimpleOdvDataCollector(
ingo@238:             TIMESERIES_ODV_PROFILE_NAMES));
ingo@230: 
ingo@238:         if (result == null)
ingo@238:             log.error("#################### RESULT == NULL #################");
ingo@230:         export.create(TIMESERIES_ODV_PROFILE, outputStream, result);
tim@177:     }
tim@177: 
tim@177:     /**
tim@98:      * @return
tim@98:      */
tim@98:     protected Statistics getStatisticsGenerator() {
tim@98:         Statistics s = new TimeseriesStatistics();
tim@98:         return s;
tim@98:     }
tim@117: 
tim@117:     protected void writeDocument2OutputStream(Document document, OutputStream os) {
tim@117: 
tim@95:         try {
tim@117:             TransformerFactory transformerFactory = TransformerFactory
tim@117:                     .newInstance();
tim@95:             Transformer transformer = transformerFactory.newTransformer();
tim@95:             DOMSource source = new DOMSource(document);
tim@117:             StreamResult result = new StreamResult(os);
tim@95:             transformer.transform(source, result);
tim@95:         } catch (TransformerConfigurationException e) {
tim@117:             log.error(e, e);
tim@95:         } catch (TransformerFactoryConfigurationError e) {
tim@117:             log.error(e, e);
tim@117:         } catch (TransformerException e) {
tim@117:             log.error(e, e);
tim@95:         }
tim@95:     }
tim@117: 
tim@253:     protected Document writeStatistics2XML( Collection<StatisticSet> statistic) {
tim@95:         ArtifactXMLUtilities xmlUtilities = new ArtifactXMLUtilities();
tim@95:         Document doc = XMLUtils.newDocument();
tim@117:         if (statistic != null) {
tim@117:             Node statisticResults = xmlUtilities.createArtifactElement(doc,
tim@253:                     "statistics");
tim@95:             doc.appendChild(statisticResults);
tim@253:             Iterator<StatisticSet> it = statistic.iterator();
tim@117:             while (it.hasNext()) {
tim@253:                 StatisticSet set = it.next();
tim@253:                 Element setElement = xmlUtilities.createArtifactElement(doc,
tim@253:                                                                        "statistic");
tim@253:                 setElement.setAttribute("name", set.getName());
tim@253:                 
tim@253:                 Iterator<Statistic> sit = set.getStatistics().iterator();
tim@253:                 while (sit.hasNext()){
tim@253:                     Statistic s = sit.next();
tim@253:                     Element result = xmlUtilities.createArtifactElement(doc,
tim@253:                     "statistic-value");
tim@253:                     result.setAttribute("name", s.getKey());
tim@253:                     result.setAttribute("value", s.getStringValue());
tim@253:                     setElement.appendChild(result);
tim@253:                 }
tim@253:                 statisticResults.appendChild(setElement);
tim@95:             }
tim@117: 
tim@95:         }
tim@95:         return doc;
tim@95:     }
tim@68: 
ingo@331: 
tim@207:     protected String getSelectedFeatureName(String uuid) {
ingo@331:         Collection values = getCollection(featureValuesName, uuid);
ingo@331: 
tim@117:         if (values != null) {
ingo@331:             Iterator it = values.iterator();
ingo@331: 
tim@117:             while (it.hasNext()) {
ingo@331:                 KeyValueDescibeData data = (KeyValueDescibeData) it.next();
ingo@331: 
tim@117:                 if (data.isSelected()) {
tim@86:                     return data.getValue();
tim@86:                 }
tim@86:             }
tim@86:         }
tim@86:         return null;
tim@86:     }
tim@117: 
ingo@331: 
tim@86:     /**
tim@86:      * @param outputStream
tim@86:      * @param parameters
tim@86:      * @param measurements
tim@86:      * @param timeSeriesName
tim@86:      * @param chartStyle
tim@86:      * @param chartLables
tim@86:      * @throws IOException
tim@86:      * @throws TechnicalChartException
tim@86:      */
ingo@300:     protected void createChart(
ingo@300:         OutputStream outputStream,
ingo@300:         Collection   parameters,
ingo@300:         Collection   measurements,
ingo@300:         Collection   dates,
ingo@300:         ChartLabels  chartLables,
ingo@303:         String       uuid,
ingo@304:         String       exportFormat,
ingo@315:         Locale       locale,
ingo@304:         int          width,
ingo@327:         int          height,
ingo@327:         boolean      linesVisible,
ingo@327:         boolean      shapesVisible
ingo@300:     )
ingo@300:     throws IOException, TechnicalChartException
ingo@300:     {
ingo@300:         log.debug("Create chart.");
ingo@300:         Chart chart = getChart(
ingo@300:             chartLables,
ingo@300:             parameters,
ingo@300:             measurements,
ingo@310:             dates,
ingo@300:             getChartResult(uuid),
ingo@315:             locale, // Locale
ingo@327:             uuid,
ingo@327:             linesVisible,
ingo@327:             shapesVisible
ingo@300:         );
ingo@300: 
ingo@300:         if (chart == null) {
ingo@300:             log.error("Could not initialize chart.");
ingo@300:             return;
ingo@300:         }
ingo@300: 
ingo@303:         log.debug(
ingo@303:             "export chart as " + exportFormat +
ingo@303:             " in " + width + "x" + height
ingo@303:         );
ingo@303: 
ingo@318:         ChartExportHelper.exportImage(
ingo@318:             outputStream,
ingo@318:             chart.generateChart(),
ingo@303:             exportFormat,
ingo@318:             width,
ingo@318:             height
ingo@303:         );
ingo@300:     }
ingo@300: 
ingo@310: 
ingo@320:     protected void createPDF(
ingo@320:         OutputStream outputStream,
ingo@320:         Collection   parameters,
ingo@320:         Collection   measurements,
ingo@320:         Collection   dates,
ingo@320:         ChartLabels  chartLables,
ingo@320:         String       uuid,
ingo@320:         String       exportFormat,
ingo@320:         boolean      landscape,
ingo@327:         Locale       locale,
ingo@327:         boolean      linesVisible,
ingo@327:         boolean      shapesVisible
ingo@320:     ) {
ingo@320:         Chart chart = getChart(
ingo@320:             chartLables,
ingo@320:             parameters,
ingo@320:             measurements,
ingo@320:             dates,
ingo@320:             getChartResult(uuid),
ingo@320:             locale,
ingo@327:             uuid,
ingo@327:             linesVisible,
ingo@327:             shapesVisible
ingo@320:         );
ingo@320: 
ingo@320:         if (chart == null) {
ingo@320:             log.error("Could not initialize chart.");
ingo@320:             return;
ingo@320:         }
ingo@320: 
ingo@320:         ChartExportHelper.exportPDF(
ingo@320:             outputStream,
ingo@320:             chart.generateChart(),
ingo@320:             "A4",
ingo@320:             PDF_FORMAT_LANDSCAPE,
ingo@320:             50F, 50F, 50F, 50F
ingo@320:         );
ingo@321: 
ingo@321:         try {
ingo@321:             OutputStream toFile = new FileOutputStream("/vol1/home/iweinzierl/tmp/test.svg");
ingo@321:             ChartExportHelper.exportSVG(
ingo@321:                 toFile,
ingo@321:                 chart.generateChart(),
ingo@321:                 null,
ingo@321:                 600, 400
ingo@321:             );
ingo@321:             toFile.flush();
ingo@321:             toFile.close();
ingo@321:         }
ingo@321:         catch(Exception e) { log.debug("ERROR WHLILE TEST."); }
ingo@321:     }
ingo@321: 
ingo@321: 
ingo@321:     protected void createSVG(
ingo@321:         OutputStream outputStream,
ingo@321:         Collection   parameters,
ingo@321:         Collection   measurements,
ingo@321:         Collection   dates,
ingo@321:         ChartLabels  chartLables,
ingo@321:         String       uuid,
ingo@321:         Locale       locale,
ingo@321:         int          width,
ingo@327:         int          height,
ingo@327:         boolean      linesVisible,
ingo@327:         boolean      shapesVisible
ingo@321:     ) {
ingo@321:         Chart chart = getChart(
ingo@321:             chartLables,
ingo@321:             parameters,
ingo@321:             measurements,
ingo@321:             dates,
ingo@321:             getChartResult(uuid),
ingo@321:             locale,
ingo@327:             uuid,
ingo@327:             linesVisible,
ingo@327:             shapesVisible
ingo@321:         );
ingo@321: 
ingo@321:         if (chart == null) {
ingo@321:             log.error("Could not initialize chart.");
ingo@321:             return;
ingo@321:         }
ingo@321: 
ingo@321:         ChartExportHelper.exportSVG(
ingo@321:             outputStream,
ingo@321:             chart.generateChart(),
ingo@321:             null,
ingo@321:             600, 400
ingo@321:         );
ingo@321: 
ingo@321:         log.debug("svg export finished.");
ingo@320:     }
ingo@320: 
ingo@320: 
ingo@300:     protected Chart getChart(
ingo@300:         ChartLabels  chartLables,
ingo@300:         Collection   parameters,
ingo@300:         Collection   measurements,
ingo@310:         Collection   dates,
ingo@300:         Collection   result,
ingo@300:         Locale       locale,
ingo@327:         String       uuid,
ingo@327:         boolean      linesVisible,
ingo@327:         boolean      shapesVisible
ingo@300:     ) {
ingo@300:         Chart chart = null;
ingo@300: 
ingo@300:         if (CACHE_CHART) {
ingo@300:             log.info("Try to get timeseries chart from cache.");
ingo@300:             chart = (Chart) getChartFromCache(uuid);
ingo@300:         }
ingo@300: 
ingo@300:         if (chart != null)
ingo@300:             return chart;
ingo@300: 
ingo@300:         log.info("Chart not in cache yet.");
ingo@300:         chart = new TimeSeriesChart(
ingo@300:             chartLables,
ingo@304:             createStyle(),
ingo@300:             parameters,
ingo@300:             measurements,
ingo@310:             dates,
ingo@300:             result,
ingo@310:             timeGapDefinitions,
ingo@327:             locale,
ingo@327:             linesVisible,
ingo@327:             shapesVisible
ingo@300:         );
ingo@300:         chart.generateChart();
ingo@300: 
ingo@300:         if (CACHE_CHART) {
ingo@300:             log.info("Put chart into cache.");
ingo@300:             purifyChart(chart, uuid);
ingo@300:         }
ingo@300: 
ingo@300:         return chart;
tim@68:     }
tim@117: 
ingo@304:     protected ChartTheme createStyle() {
ingo@304:         XMLChartTheme theme = null;
ingo@304: 
ingo@304:         Document template = Config.getChartTemplate();
ingo@304:         String   name     = Config.getStringXPath(
ingo@304:             template,
ingo@304:             "theme/name/@value"
ingo@304:         );
ingo@304: 
ingo@304:         theme  = new XMLChartTheme(name);
ingo@304:         theme.applyXMLConfiguration(template);
ingo@304: 
ingo@304:         return theme;
tim@68:     }
ingo@304: 
ingo@331: 
ingo@331:     protected String createChartTitle(Locale locale, String uuid) {
ingo@331:         return getFisName(locale);
ingo@331: 
ingo@331:     }
ingo@331: 
ingo@331: 
ingo@331:     protected String createChartSubtitle(Locale locale, String uuid) {
ingo@331:         return getSelectedFeatureName(uuid);
ingo@331:     }
ingo@331: 
ingo@331: 
ingo@331:     protected String getFisName(Locale locale) {
ingo@331:         String    returnValue = "";
ingo@331:         InputData input       = inputData.get("fisname");
ingo@331: 
ingo@331:         if (input != null) {
ingo@331:             String value = input.getValue();
ingo@331: 
ingo@331:             returnValue = RessourceFactory.getInstance().getRessource(
ingo@331:                 locale,
ingo@331:                 value,
ingo@331:                 value
ingo@331:             );
tim@178:         }
tim@178:         return returnValue;
tim@178:     }
tim@117: 
ingo@331: 
tim@207:     protected Collection<KeyValueDescibeData> getParameters(String uuid) {
tim@207:         return this.getCollection(parameterValuesName, uuid);
tim@64:     }
tim@117: 
tim@207:     protected Collection<KeyValueDescibeData> getMeasurements(String uuid) {
tim@207:         return this.getCollection(measuremenValueName, uuid);
tim@119:     }
tim@207:     protected Collection<KeyValueDescibeData> getDates(String uuid) {
tim@207:         return this.getCollection(dateValueName,uuid);
tim@179:     }
tim@119: 
tim@119:     @Override
tim@119:     public void setup(Node configuration) {
tim@119:         super.setup(configuration);
tim@171:         String featureNameValue = Config.getStringXPath(configuration,
tim@171:                 "value-names/value-name[@name='feature']/@value");
tim@171:         if (featureNameValue != null) {
tim@119:             this.featureValuesName = featureNameValue;
tim@119:         }
tim@171:         String parameterNameValue = Config.getStringXPath(configuration,
tim@171:                 "value-names/value-name[@name='parameter']/@value");
tim@171:         if (parameterNameValue != null) {
tim@119:             this.parameterValuesName = parameterNameValue;
tim@119:         }
tim@171:         String measurementNameValue = Config.getStringXPath(configuration,
tim@171:                 "value-names/value-name[@name='measurement']/@value");
tim@171:         if (measurementNameValue != null) {
tim@119:             this.measuremenValueName = measurementNameValue;
tim@119:         }
tim@179:         
tim@179:         String dateNameValue = Config.getStringXPath(configuration,
tim@179:         "value-names/value-name[@name='date']/@value");
tim@179:         if (dateNameValue != null) {
tim@179:             this.dateValueName = dateNameValue;
tim@179:         }
tim@217:         if (timeGapDefinitions == null){
tim@217:             Element gapDefinition =  (Element)Config.getNodeXPath(configuration,
tim@217:                                                                  "time-gap-definition");
tim@217:             synchronized (this.getClass()) {
tim@217:                 if (gapDefinition != null){
tim@217:                     String link = gapDefinition.getAttribute("xlink:href");
tim@217:                     if (link != null ){
tim@217:                         String absolutFileName = Config.replaceConfigDir(link);
tim@217:                         gapDefinition = (Element)new ArtifactXMLUtilities().
tim@217:                                                      readConfiguration(absolutFileName);
tim@217:                     }
tim@217:                     
tim@217:                     NodeList gapDefinitions = Config.getNodeSetXPath(gapDefinition, 
tim@217:                                                                     "/time-gaps/time-gap");
tim@217:                     if (gapDefinition != null){
tim@217:                         timeGapDefinitions = new ArrayList<TimeGap>(gapDefinitions.
tim@217:                                                                     getLength());
tim@217:                         for (int i = 0; i < gapDefinitions.getLength(); i++){
tim@217:                             Element gapNode = (Element)gapDefinitions.item(i);
tim@217:                             String unit = gapNode.getAttribute("unit");
tim@217:                             int key = Integer.parseInt(gapNode.getAttribute("key"));
tim@217:                             int value = Integer.parseInt(gapNode.getAttribute("gap"));
tim@217:                             log.info("Add new Timegap: "+key+" "+value+" "+ unit);
tim@217:                             timeGapDefinitions.add(new DefaultTimeGap(unit, 
tim@217:                                                                       key, 
tim@217:                                                                       value));
tim@217:                         }
tim@217:                     }
tim@217:                     
tim@217:                 }
tim@217:             }
tim@217:         }
tim@82:     }
tim@217:     
tim@82:     /**
tim@82:      * @param collectionName
tim@82:      * @return
tim@82:      */
tim@82:     protected Collection<KeyValueDescibeData> getCollection(
tim@207:                                                             String collectionName, 
tim@207:                                                             String uuid) {
tim@207:         Iterator<Object> it = this.getDescibeData(uuid).iterator();
tim@117:         while (it.hasNext()) {
tim@117: 
tim@117:             Object o = it.next();
tim@117: 
tim@117:             if (o instanceof NamedCollection<?>) {
tim@117:                 NamedCollection<KeyValueDescibeData> nc = (NamedCollection<KeyValueDescibeData>) o;
tim@117:                 if (nc.getName().equals(collectionName)) {
tim@117:                     return nc;
tim@117:                 }
tim@117:             }
tim@68:         }
tim@68:         return null;
tim@68:     }
tim@64: }
ingo@320: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :