tim@64: /**
tim@64:  *
tim@64:  */
tim@64: package de.intevation.gnv.transition.timeseries;
tim@64: 
tim@68: import java.awt.Color;
tim@68: import java.awt.Dimension;
tim@68: import java.io.IOException;
tim@73: import java.io.OutputStream;
tim@90: import java.io.OutputStreamWriter;
tim@68: import java.util.Collection;
tim@68: import java.util.Iterator;
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@68: 
tim@90: import au.com.bytecode.opencsv.CSVWriter;
tim@95: import de.intevation.artifactdatabase.XMLUtils;
tim@68: import de.intevation.gnv.chart.ChartFactory;
tim@68: import de.intevation.gnv.chart.ChartLabels;
tim@68: import de.intevation.gnv.chart.ChartStyle;
tim@68: import de.intevation.gnv.chart.exception.TechnicalChartException;
tim@68: import de.intevation.gnv.geobackend.base.Result;
tim@95: import de.intevation.gnv.statistics.Statistic;
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@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: 
tim@64: /**
tim@64:  * @author Tim Englich <tim.englich@intevation.de>
tim@64:  *
tim@64:  */
tim@64: public class TimeSeriesOutputTransition extends OutputTransitionBase{
tim@86: 
tim@86:     /**
tim@86:      * The UID of this Class
tim@86:      */
tim@86:     private static final long serialVersionUID = 4178407570503098858L;
tim@68:     
tim@68:     /**
tim@68:      * the logger, used to log exceptions and additonaly information
tim@68:      */
tim@68:     private static Logger log = Logger.getLogger(TimeSeriesOutputTransition.class);
tim@86:     
tim@86:     protected String domainLable = "Zeit [UTC]"; 
tim@86:     
tim@64:     /**
tim@64:      * Constructor
tim@64:      */
tim@64:     public TimeSeriesOutputTransition() {
tim@64:         super();
tim@64:     }
tim@64: 
tim@64:     /**
tim@64:      * @see de.intevation.gnv.transition.Transition#validate()
tim@64:      */
tim@64:     public boolean validate() {
tim@64:         return true;
tim@64:     }
tim@64: 
tim@73:    /**
tim@91:     * @see de.intevation.gnv.transition.OutputTransition#out(java.lang.String, java.util.Collection, java.io.OutputStream)
tim@73:     */
tim@99:     public void out(String outputMode, Collection<InputData> inputData, OutputStream outputStream, String uuid) throws TransitionException {
tim@90:         log.debug("TimeSeriesOutputTransition.out");
tim@68:         try {
tim@99:        
tim@99:             this.advance(uuid);
tim@99:             Collection<Result> chartResult = this.getChartResult(uuid); 
tim@90:             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@91:                     if (inputData != null){
tim@91:                         Iterator<InputData> it = inputData.iterator();
tim@91:                         while (it.hasNext()){
tim@91:                             InputData ip = it.next();
tim@91:                             if (ip.getName().equalsIgnoreCase("width")){
tim@91:                                 chartWidth = Integer.parseInt(ip.getValue());
tim@91:                             }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@91:                     log.error(e,e);
tim@91:                     throw new TransitionException(e);
tim@91:                 }
tim@90:                 Collection<KeyValueDescibeData> parameters = this.getParameters();
tim@90:                 Collection<KeyValueDescibeData> measurements = this.getMeasurements();
tim@91:                 ChartStyle chartStyle = this.creatStyle(chartWidth,chartHeight);
tim@90:                 ChartLabels chartLables = new ChartLabels(this.getSelectedFeatureName(),this.domainLable);
tim@90:                 this.createChart(outputStream, parameters, measurements,
tim@99:                         chartStyle, chartLables,uuid);
tim@90:             }else if (outputMode.equalsIgnoreCase("csv")){
tim@90:                 log.debug("CSV-File will be generated.");
tim@99:                 if(chartResult != null){
tim@90:                     CSVWriter writer = new CSVWriter(new OutputStreamWriter(outputStream,"ISO-8859-1"), ','); // USE THIS ENCODING BECAUSE OF PROBLEMS WITH EXCEL AND UTF-8
tim@99:                     Iterator<Result>it = chartResult.iterator();
tim@90:                     while (it.hasNext()){
tim@90:                         Result result = it.next();
tim@90:                         int i = 0;
tim@90:                         String[] entries = new String[5];
tim@90:                         entries[i++] = result.getString("XORDINATE");
tim@90:                         entries[i++] = result.getString("YORDINATE");
tim@90:                         entries[i++] = result.getString("GROUP1");
tim@90:                         entries[i++] = result.getString("GROUP2");
tim@90:                         entries[i++] = result.getString("GROUP3");
tim@90:                         writer.writeNext(entries);
tim@90:                     }
tim@90:                     writer.close();
tim@90:                 }else{
tim@90:                     log.error("No Data given for generation an CSV-File.");
tim@90:                     throw new TransitionException("No Data given for generation an CSV-File.");
tim@90:                 }
tim@95:             }else if (outputMode.equalsIgnoreCase("statistics")){
tim@95:                 log.debug("Statistics will be generated.");
tim@98:                 Statistics s = getStatisticsGenerator();
tim@99:                 Collection<Statistic> statistics = s.calculateStatistics(chartResult);
tim@95:                 Document doc = this.writeStatistics2XML(statistics);
tim@95:                 this.writeDocument2OutputStream(doc, outputStream);
tim@90:             }
tim@68:         } catch (IOException e) {
tim@68:             log.error(e,e);
tim@68:             throw new TransitionException(e);
tim@68:         } catch (TechnicalChartException e) {
tim@68:             log.error(e,e);
tim@68:             throw new TransitionException(e);
tim@95:         }catch (StatisticsException e) {
tim@95:             log.error(e,e);
tim@95:             throw new TransitionException(e);
tim@68:         }
tim@68:     }
tim@98: 
tim@98:     /**
tim@98:      * @return
tim@98:      */
tim@98:     protected Statistics getStatisticsGenerator() {
tim@98:         Statistics s = new TimeseriesStatistics();
tim@98:         return s;
tim@98:     }
tim@95:     
tim@95:     protected void writeDocument2OutputStream(Document document, OutputStream os){
tim@95:         
tim@95:         try {
tim@95:             TransformerFactory transformerFactory = TransformerFactory.newInstance();
tim@95:             Transformer transformer = transformerFactory.newTransformer();
tim@95:             DOMSource source = new DOMSource(document);
tim@95:             StreamResult result =  new StreamResult(os);
tim@95:             transformer.transform(source, result);
tim@95:         } catch (TransformerConfigurationException e) {
tim@95:             log.error(e,e);
tim@95:         } catch (TransformerFactoryConfigurationError e) {
tim@95:             log.error(e,e);
tim@95:         }catch (TransformerException e) {
tim@95:             log.error(e,e);
tim@95:         }
tim@95:     }
tim@95:     
tim@95:     protected Document writeStatistics2XML(Collection<Statistic> statistic){
tim@95:         ArtifactXMLUtilities xmlUtilities = new ArtifactXMLUtilities();
tim@95:         Document doc = XMLUtils.newDocument();
tim@95:         if (statistic != null){
tim@95:             Node statisticResults = xmlUtilities.createArtifactElement(doc, "statistic-values");
tim@95:             doc.appendChild(statisticResults);
tim@95:             Iterator<Statistic> it = statistic.iterator();
tim@95:             while (it.hasNext()){
tim@95:                 Statistic s = it.next();
tim@95:                 Element result = xmlUtilities.createArtifactElement(doc, "statistic");
tim@95:                 result.setAttribute("name", s.getKey());
tim@95:                 result.setAttribute("value", s.getStringValue());
tim@95:                 statisticResults.appendChild(result);
tim@95:             }
tim@95:         
tim@95:         }
tim@95:         return doc;
tim@95:     }
tim@68: 
tim@86:     
tim@86:     protected String getSelectedFeatureName(){
tim@86:         String collectionName = "featureid"; // TODO: Konfigurierbar machen
tim@86:         Collection<KeyValueDescibeData> values =  this.getCollection(collectionName);
tim@86:         if (values != null){
tim@86:             Iterator<KeyValueDescibeData> it = values.iterator();
tim@86:             while(it.hasNext()){
tim@86:                 KeyValueDescibeData data = it.next();
tim@86:                 if (data.isSelected()){
tim@86:                     return data.getValue();
tim@86:                 }
tim@86:             }
tim@86:         }
tim@86:         return null;
tim@86:     }
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:      */
tim@86:     protected void createChart(OutputStream outputStream,
tim@86:             Collection<KeyValueDescibeData> parameters,
tim@86:             Collection<KeyValueDescibeData> measurements,
tim@99:             ChartStyle chartStyle, ChartLabels chartLables, String uuid) throws IOException,
tim@86:             TechnicalChartException {
tim@86:         ChartFactory chartFactory = new ChartFactory();
tim@86:         chartFactory.createSimpleTimeSeriesChart(chartLables, chartStyle,
tim@86:                                                  parameters, measurements, 
tim@99:                                                  outputStream, this.getChartResult(uuid));
tim@68:     }
tim@68:     
tim@68:     protected ChartStyle creatStyle(int witdh, int height){
tim@68:         // TODO Konfigurierbar machen
tim@68:         de.intevation.gnv.chart.Insets lInsets = new de.intevation.gnv.chart.Insets(5d, 5d, 5d, 5d);
tim@68:         Dimension lChartSize = new Dimension(witdh, height);
tim@68:         return new ChartStyle(Color.white, new Color(230, 230, 230), Color.white, Color.white, true, true, lInsets, lChartSize);
tim@68:     }
tim@68:     
tim@68:     protected Collection<KeyValueDescibeData> getParameters(){
tim@86:         String collectionName = "parameterid"; // TODO: Konfigurierbar machen
tim@82:         return this.getCollection(collectionName);
tim@64:     }
tim@68:     
tim@68:     protected Collection<KeyValueDescibeData> getMeasurements(){
tim@86:         String collectionName = "measurementid"; // TODO: Konfigurierbar machen
tim@82:         return this.getCollection(collectionName);
tim@82:     }
tim@82: 
tim@82:     /**
tim@82:      * @param collectionName
tim@82:      * @return
tim@82:      */
tim@82:     protected Collection<KeyValueDescibeData> getCollection(
tim@82:             String collectionName) {
tim@68:         Iterator<Object> it = this.descibeData.iterator();
tim@68:         while (it.hasNext()){
tim@68:            
tim@68:            Object o = it.next();
tim@82:            
tim@81:            if (o instanceof NamedCollection<?>){
tim@81:                NamedCollection<KeyValueDescibeData> nc = (NamedCollection<KeyValueDescibeData>)o;
tim@86:                if (nc.getName().equals(collectionName)){
tim@81:                    return nc;
tim@81:                }
tim@68:            }
tim@68:         }
tim@68:         return null;
tim@68:     }
tim@64: }