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@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; 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: 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; 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@232: import de.intevation.gnv.exports.DefaultExport; 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@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; ingo@233: import de.intevation.gnv.exports.DefaultExport; ingo@233: import de.intevation.gnv.exports.DefaultDataCollector; ingo@238: import de.intevation.gnv.exports.SimpleOdvDataCollector; ingo@233: import de.intevation.gnv.exports.DefaultProfile; ingo@233: import de.intevation.gnv.exports.Export.Profile; tim@95: import de.intevation.gnv.utils.ArtifactXMLUtilities; tim@64: ingo@230: tim@64: /** tim@64: * @author Tim Englich tim@117: * tim@64: */ tim@117: 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@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); tim@217: tim@217: tim@217: private static List 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@241: "TIMEVALUE", tim@232: "TYPE", ingo@238: "SHAPE", tim@232: "BOTDEPTH", tim@241: "DEPTH" ingo@238: //"DATAVALUE", ingo@238: //"PARAMETER", ingo@238: //"MEASUREMENTID", ingo@238: //"TIMESERIESID" 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: "Date/Time", ingo@239: "Longitude [deegrees_east]", ingo@239: "Latitude [deegrees_north]", tim@241: "Bot. Depth [m]", tim@241: "Depth [m]" 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: */ tim@117: public void out(String outputMode, Collection inputData, tim@117: OutputStream outputStream, String uuid, CallMeta callMeta) tim@117: throws TransitionException { tim@90: log.debug("TimeSeriesOutputTransition.out"); tim@68: try { tim@117: tim@232: this.advance(uuid, callMeta); // TODO This hsould only be done if it is nessessary tim@232: 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 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: } tim@207: Collection parameters = this.getParameters(uuid); tim@207: Collection measurements = this.getMeasurements(uuid); tim@207: Collection dates = this.getDates(uuid); tim@117: ChartStyle chartStyle = this tim@117: .creatStyle(chartWidth, chartHeight); tim@178: ChartLabels chartLables = new ChartLabels(this.getFisName(callMeta.getLanguages())+" "+this tim@207: .getSelectedFeatureName(uuid), this.domainLable); tim@179: this.createChart(outputStream, parameters, measurements,dates, tim@117: chartStyle, chartLables, uuid); tim@117: } else if (outputMode.equalsIgnoreCase("csv")) { tim@90: log.debug("CSV-File will be generated."); tim@232: Collection 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 chartResult = this.getChartResult(uuid); tim@117: Collection statistics = s tim@117: .calculateStatistics(chartResult); 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 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@230: 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 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@117: protected Document writeStatistics2XML(Collection 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@117: "statistic-values"); tim@95: doc.appendChild(statisticResults); tim@95: Iterator it = statistic.iterator(); tim@117: while (it.hasNext()) { tim@95: Statistic s = it.next(); tim@117: Element result = xmlUtilities.createArtifactElement(doc, tim@117: "statistic"); tim@95: result.setAttribute("name", s.getKey()); tim@95: result.setAttribute("value", s.getStringValue()); tim@95: statisticResults.appendChild(result); tim@95: } tim@117: tim@95: } tim@95: return doc; tim@95: } tim@68: tim@207: protected String getSelectedFeatureName(String uuid) { tim@117: Collection values = this tim@207: .getCollection(featureValuesName, uuid); tim@117: if (values != null) { tim@86: Iterator it = values.iterator(); tim@117: while (it.hasNext()) { tim@86: KeyValueDescibeData data = it.next(); tim@117: if (data.isSelected()) { tim@86: return data.getValue(); tim@86: } tim@86: } tim@86: } tim@86: return null; tim@86: } tim@117: 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@117: Collection parameters, tim@117: Collection measurements, tim@179: Collection dates, tim@117: ChartStyle chartStyle, ChartLabels chartLables, tim@117: String uuid) throws IOException, tim@117: TechnicalChartException { tim@86: ChartFactory chartFactory = new ChartFactory(); tim@86: chartFactory.createSimpleTimeSeriesChart(chartLables, chartStyle, tim@117: parameters, measurements, outputStream, this tim@217: .getChartResult(uuid),timeGapDefinitions); tim@68: } tim@117: tim@117: protected ChartStyle creatStyle(int witdh, int height) { tim@68: // TODO Konfigurierbar machen tim@117: de.intevation.gnv.chart.Insets lInsets = new de.intevation.gnv.chart.Insets( tim@117: 5d, 5d, 5d, 5d); tim@68: Dimension lChartSize = new Dimension(witdh, height); tim@117: return new ChartStyle(Color.white, new Color(230, 230, 230), tim@117: Color.white, Color.white, true, true, lInsets, lChartSize); tim@68: } tim@178: tim@178: protected String getFisName(PreferredLocale[] preferredLocales){ tim@178: String returnValue = ""; tim@178: InputData inputData = this.inputData.get("fisname"); tim@178: if (inputData != null){ tim@178: returnValue = RessourceFactory.getInstance() tim@178: .getRessource(preferredLocales, tim@178: inputData.getValue(), tim@178: inputData.getValue()); tim@178: } tim@178: return returnValue; tim@178: } tim@117: tim@207: protected Collection getParameters(String uuid) { tim@207: return this.getCollection(parameterValuesName, uuid); tim@64: } tim@117: tim@207: protected Collection getMeasurements(String uuid) { tim@207: return this.getCollection(measuremenValueName, uuid); tim@119: } tim@207: protected Collection 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(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 getCollection( tim@207: String collectionName, tim@207: String uuid) { tim@207: Iterator 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 nc = (NamedCollection) 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: }