Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/state/timeseries/TimeSeriesOutputState.java @ 447:92b7ccbf6163
Improved generation of iso lines in vertical cross section.
gnv-artifacts/trunk@495 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Fri, 01 Jan 2010 21:52:41 +0000 |
parents | f5a041000357 |
children | 4cd03910f97e |
line wrap: on
line source
/** * */ package de.intevation.gnv.state.timeseries; import java.io.IOException; import java.io.File; import java.io.OutputStream; import java.io.FileOutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Vector; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.jfree.chart.ChartTheme; import au.com.bytecode.opencsv.CSVWriter; import de.intevation.artifactdatabase.Config; import de.intevation.artifactdatabase.XMLUtils; import de.intevation.artifacts.CallMeta; import de.intevation.artifacts.CallContext; import de.intevation.artifacts.PreferredLocale; import de.intevation.gnv.artifacts.context.GNVArtifactContext; import de.intevation.gnv.artifacts.ressource.RessourceFactory; import de.intevation.gnv.chart.Chart; import de.intevation.gnv.chart.ChartLabels; import de.intevation.gnv.chart.TimeSeriesChart; import de.intevation.gnv.chart.XMLChartTheme; import de.intevation.gnv.chart.exception.TechnicalChartException; import de.intevation.gnv.exports.ChartExportHelper; import de.intevation.gnv.exports.DefaultExport; import de.intevation.gnv.exports.DefaultDataCollector; import de.intevation.gnv.exports.SimpleOdvDataCollector; import de.intevation.gnv.exports.DefaultProfile; import de.intevation.gnv.exports.Export.Profile; import de.intevation.gnv.geobackend.base.Result; import de.intevation.gnv.state.InputData; import de.intevation.gnv.state.OutputStateBase; import de.intevation.gnv.state.describedata.KeyValueDescibeData; import de.intevation.gnv.state.describedata.NamedCollection; import de.intevation.gnv.state.exception.StateException; import de.intevation.gnv.statistics.Statistic; import de.intevation.gnv.statistics.StatisticSet; import de.intevation.gnv.statistics.Statistics; import de.intevation.gnv.statistics.TimeseriesStatistics; import de.intevation.gnv.statistics.exception.StatisticsException; import de.intevation.gnv.timeseries.gap.DefaultTimeGap; import de.intevation.gnv.timeseries.gap.TimeGap; import de.intevation.gnv.utils.ArtifactXMLUtilities; /** * @author Tim Englich <tim.englich@intevation.de> * */ public class TimeSeriesOutputState extends OutputStateBase { protected static final boolean CACHE_CHART = Boolean.parseBoolean(System.getProperty("cache.chart", "false")); protected static final boolean PDF_FORMAT_LANDSCAPE = Boolean.parseBoolean(System.getProperty("export.pdf.landscape","true")); protected static final String[] IMG_EXPORT_FORMAT = { "PNG", "JPEG", "GIF" }; /** * The UID of this Class */ private static final long serialVersionUID = 4178407570503098858L; /** * the logger, used to log exceptions and additonaly information */ private static Logger log = Logger .getLogger(TimeSeriesOutputState.class); private static List<TimeGap> timeGapDefinitions = null; protected String domainLable = "chart.timeseries.title.xaxis"; protected String featureValuesName = "featureid"; protected String parameterValuesName = "parameterid"; protected String measuremenValueName = "measurementid"; protected String dateValueName = "dateid"; public static final String [] TIMESERIES_CSV_PROFILE_COLUMNS = { "XORDINATE", "YORDINATE", "GROUP1", "GROUP2", "GROUP3" }; public static final String [] TIMESERIES_TIMESERIES_CSV_COLUMN_LABEL = { "Date/Time", "Value", "ParameterID", "MeasurementID", "TimeseriesID" }; public static final String [] TIMESERIES_MESH_CSV_COLUMN_LABEL = { "Date/Time", "Value", "ParameterID", "FeatureID", "MeshID" }; public static final String [] TIMESERIES_ODV_PROFILE_NAMES = { "CRUISE", "STATION", "TYPE", "SHAPE", "BOTDEPTH", "DEPTH", "TIMEVALUE", "DATAVALUE", "PARAMETER" }; public static final String [] ODV_COLUMN_HEADER = { "Cruise", "Station", "Type", "Longitude [deegrees_east]", "Latitude [deegrees_north]", "Bot. Depth [m]", "Depth [m]", "Date/Time", "Value", "Parameterid" }; /** * Profile for exporting data to odv * TODO Change TIMESERIES_PROFILE_NAMES, which belong to CSV exports */ public static final Profile TIMESERIES_ODV_PROFILE = new DefaultProfile( ODV_COLUMN_HEADER, '\t', CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER, "ODV", "ISO-8859-1"); /** * Constructor */ public TimeSeriesOutputState() { super(); } /** * @see de.intevation.gnv.transition.OutputTransition#out(java.lang.String, * java.util.Collection, java.io.OutputStream, java.lang.String, * de.intevation.artifacts.CallMeta) */ public void out( Document format, Collection<InputData> inputData, OutputStream outputStream, String uuid, CallContext callContext ) throws StateException { log.debug("TimeSeriesOutputTransition.out"); String outputMode = Config.getStringXPath( format, "action/out/@name" ); String mimeType = Config.getStringXPath( format, "action/out/mime-type/@value" ); CallMeta callMeta = callContext.getMeta(); try { if (outputMode.equalsIgnoreCase("chart")) { log.debug("Chart will be generated."); int chartWidth = 600; int chartHeight = 400; try { if (inputData != null) { Iterator<InputData> it = inputData.iterator(); while (it.hasNext()) { InputData ip = it.next(); if (ip.getName().equalsIgnoreCase("width")) { chartWidth = Integer.parseInt(ip.getValue()); } else if (ip.getName().equalsIgnoreCase("height")) { chartHeight = Integer.parseInt(ip.getValue()); } } } } catch (NumberFormatException e) { log.error(e, e); throw new StateException(e); } PreferredLocale[] locales = callMeta.getLanguages(); Locale[] serverLocales = RessourceFactory.getInstance().getLocales(); Locale locale = callMeta.getPreferredLocale(serverLocales); log.debug( "Best locale - regarding intersection of server and " + "browser locales - is " + locale.toString() ); Collection parameters = this.getCleanedParameters(uuid); Collection measurements = this.getMeasurements(uuid); Collection dates = this.getDates(uuid); ChartLabels chartLables = new ChartLabels( createChartTitle(locale, uuid), createChartSubtitle(locale, uuid), RessourceFactory.getInstance().getRessource( locale, domainLable, domainLable ) ); String exportFormat = getExportFormat(mimeType); // TODO Remove this and parse input data boolean linesVisible = true; boolean shapesVisible = true; this.createChart( outputStream, parameters, measurements, dates, chartLables, callContext, uuid, exportFormat, locale, chartWidth, chartHeight, linesVisible, shapesVisible, callContext ); } else if (outputMode.equalsIgnoreCase("pdf")) { log.debug("Output mode == pdf"); Locale[] serverLocales = RessourceFactory.getInstance().getLocales(); Locale locale = callMeta.getPreferredLocale(serverLocales); // TODO Remove this and parse input data boolean linesVisible = true; boolean shapesVisible = true; log.debug( "Best locale - regarding intersection of server and " + "browser locales - is " + locale.toString() ); createPDF( outputStream, getCleanedParameters(uuid), getMeasurements(uuid), getDates(uuid), new ChartLabels( createChartTitle(locale, uuid), createChartSubtitle(locale, uuid), RessourceFactory.getInstance().getRessource( locale, domainLable, domainLable ) ), uuid, "A4", true, linesVisible, shapesVisible, locale, callContext ); } else if (outputMode.equalsIgnoreCase("svg")) { log.debug("Output mode == svg"); int width = 600; int height = 400; // TODO Remove this and parse input data boolean linesVisible = true; boolean shapesVisible = true; Locale[] serverLocales = RessourceFactory.getInstance().getLocales(); Locale locale = callMeta.getPreferredLocale(serverLocales); log.debug( "Best locale - regarding intersection of server and " + "browser locales - is " + locale.toString() ); createSVG( outputStream, getCleanedParameters(uuid), getMeasurements(uuid), getDates(uuid), new ChartLabels( createChartTitle(locale, uuid), createChartSubtitle(locale, uuid), RessourceFactory.getInstance().getRessource( locale, domainLable, domainLable ) ), uuid, locale, width, height, linesVisible, shapesVisible, callContext ); } else if (outputMode.equalsIgnoreCase("csv")) { log.debug("CSV-File will be generated."); Collection<Result> chartResult = (Collection<Result>) getChartResult(uuid, callContext); this.createCSV(outputStream, chartResult); } else if (outputMode.equalsIgnoreCase("statistics")) { log.debug("Statistics will be generated."); Statistics s = getStatisticsGenerator(); Collection<StatisticSet> statistics; Object result = getChartResult(uuid, callContext); if (result instanceof Collection) { Collection<Result> chartResult = (Collection<Result>) result; Collection<KeyValueDescibeData> parameters = this.getParameters(uuid); Collection<KeyValueDescibeData> measurements = this.getMeasurements(uuid); Collection<KeyValueDescibeData> dates = this.getDates(uuid); statistics = s.calculateStatistics( chartResult, parameters, measurements, dates); } else { statistics = new ArrayList<StatisticSet>(); } Document doc = this.writeStatistics2XML(statistics); this.writeDocument2OutputStream(doc, outputStream); } else if (outputMode.equalsIgnoreCase("odv")) { Collection<Result> odvResult = this.getODVResult(uuid); this.createODV(outputStream, odvResult); } } catch (IOException e) { log.error(e, e); throw new StateException(e); } catch (TechnicalChartException e) { log.error(e, e); throw new StateException(e); } catch (StatisticsException e) { log.error(e, e); throw new StateException(e); } } protected String getExportFormat(String mime) { for(int i = 0; i < IMG_EXPORT_FORMAT.length; i++) { if (mime.trim().toUpperCase().indexOf(IMG_EXPORT_FORMAT[i]) > 0) return IMG_EXPORT_FORMAT[i]; } // no format found relating to mimeType, default export as PNG return IMG_EXPORT_FORMAT[0]; } protected Collection getCleanedParameters(Collection parameters) { Iterator iter = parameters.iterator(); Collection parameter = new Vector(parameters); while (iter.hasNext()) { KeyValueDescibeData data = (KeyValueDescibeData)iter.next(); if (!data.isSelected()) parameter.remove(data); } return parameter; } protected Collection getCleanedParameters(String uuid) { return getCleanedParameters(getParameters(uuid)); } protected void createCSV(OutputStream out, Collection<Result> results) throws UnsupportedEncodingException, IOException, StateException { Iterator iter = results.iterator(); Result res = iter.hasNext() ? (Result) iter.next() : null; if (res == null) return; Profile profile = null; int dataid = res.getInteger("DATAID").intValue(); // on meshes if (dataid == 2) { profile = new DefaultProfile( TIMESERIES_MESH_CSV_COLUMN_LABEL, ',', '"', '"', "CSV", "ISO-8859-1"); } // on timeseries else { profile = new DefaultProfile( TIMESERIES_TIMESERIES_CSV_COLUMN_LABEL, ',', '"', '"', "CSV", "ISO-8859-1"); } DefaultExport export = new DefaultExport( new DefaultDataCollector(TIMESERIES_CSV_PROFILE_COLUMNS)); export.create(profile, out, results); } /** * TODO Result is not used at the moment. Change result with correct data. */ protected void createODV(OutputStream outputStream, Collection result) throws IOException, StateException { DefaultExport export = new DefaultExport(new SimpleOdvDataCollector( TIMESERIES_ODV_PROFILE_NAMES)); if (result == null) log.error("#################### RESULT == NULL #################"); export.create(TIMESERIES_ODV_PROFILE, outputStream, result); } /** * @return */ protected Statistics getStatisticsGenerator() { Statistics s = new TimeseriesStatistics(); return s; } protected void writeDocument2OutputStream(Document document, OutputStream os) { try { TransformerFactory transformerFactory = TransformerFactory .newInstance(); Transformer transformer = transformerFactory.newTransformer(); DOMSource source = new DOMSource(document); StreamResult result = new StreamResult(os); transformer.transform(source, result); } catch (TransformerConfigurationException e) { log.error(e, e); } catch (TransformerFactoryConfigurationError e) { log.error(e, e); } catch (TransformerException e) { log.error(e, e); } } protected Document writeStatistics2XML( Collection<StatisticSet> statistic) { ArtifactXMLUtilities xmlUtilities = new ArtifactXMLUtilities(); Document doc = XMLUtils.newDocument(); if (statistic != null) { Node statisticResults = xmlUtilities.createArtifactElement(doc, "statistics"); doc.appendChild(statisticResults); Iterator<StatisticSet> it = statistic.iterator(); while (it.hasNext()) { StatisticSet set = it.next(); Element setElement = xmlUtilities.createArtifactElement(doc, "statistic"); setElement.setAttribute("name", set.getName()); Iterator<Statistic> sit = set.getStatistics().iterator(); while (sit.hasNext()){ Statistic s = sit.next(); Element result = xmlUtilities.createArtifactElement(doc, "statistic-value"); result.setAttribute("name", s.getKey()); result.setAttribute("value", s.getStringValue()); setElement.appendChild(result); } statisticResults.appendChild(setElement); } } return doc; } protected String getSelectedFeatureName(String uuid) { Collection values = getCollection(featureValuesName, uuid); if (values != null) { Iterator it = values.iterator(); while (it.hasNext()) { KeyValueDescibeData data = (KeyValueDescibeData) it.next(); if (data.isSelected()) { return data.getValue(); } } } return null; } /** * @param outputStream * @param parameters * @param measurements * @param timeSeriesName * @param chartStyle * @param chartLables * @throws IOException * @throws TechnicalChartException */ protected void createChart( OutputStream outputStream, Collection parameters, Collection measurements, Collection dates, ChartLabels chartLables, CallContext context, String uuid, String exportFormat, Locale locale, int width, int height, boolean linesVisible, boolean shapesVisible, CallContext callContext ) throws IOException, TechnicalChartException { log.debug("Create chart."); Chart chart = getChart( chartLables, createStyle(context), parameters, measurements, dates, getChartResult(uuid, callContext), locale, // Locale uuid, linesVisible, shapesVisible, callContext ); if (chart == null) { log.error("Could not initialize chart."); return; } log.debug( "export chart as " + exportFormat + " in " + width + "x" + height ); ChartExportHelper.exportImage( outputStream, chart.generateChart(), exportFormat, width, height ); } protected void createPDF( OutputStream outputStream, Collection parameters, Collection measurements, Collection dates, ChartLabels chartLables, String uuid, String exportFormat, boolean landscape, boolean linesVisible, boolean shapesVisible, Locale locale, CallContext context ) { Chart chart = getChart( chartLables, createStyle(context), parameters, measurements, dates, (Collection) getChartResult(uuid, context), locale, uuid, linesVisible, shapesVisible, context ); if (chart == null) { log.error("Could not initialize chart."); return; } ChartExportHelper.exportPDF( outputStream, chart.generateChart(), "A4", PDF_FORMAT_LANDSCAPE, 50F, 50F, 50F, 50F ); /* XXX: @Ingo: What's this? Looks like dev test remains. try { OutputStream toFile = new FileOutputStream("/vol1/home/iweinzierl/tmp/test.svg"); ChartExportHelper.exportSVG( toFile, chart.generateChart(), null, 600, 400 ); toFile.flush(); toFile.close(); } catch(Exception e) { log.debug("ERROR WHLILE TEST."); } */ } protected void createSVG( OutputStream outputStream, Collection parameters, Collection measurements, Collection dates, ChartLabels chartLables, String uuid, Locale locale, int width, int height, boolean linesVisible, boolean shapesVisible, CallContext callContext ) { Chart chart = getChart( chartLables, createStyle(callContext), parameters, measurements, dates, getChartResult(uuid, callContext), locale, uuid, linesVisible, shapesVisible, callContext ); if (chart == null) { log.error("Could not initialize chart."); return; } ChartExportHelper.exportSVG( outputStream, chart.generateChart(), null, 600, 400 ); log.debug("svg export finished."); } 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 = null; if (CACHE_CHART) { log.info("Try to get timeseries chart from cache."); chart = (Chart) getChartFromCache(uuid, callContext); } if (chart != null) return chart; log.info("Chart not in cache yet."); chart = new TimeSeriesChart( chartLables, theme, parameters, measurements, dates, (Collection)result, timeGapDefinitions, locale, linesVisible, shapesVisible ); chart.generateChart(); if (CACHE_CHART) { log.info("Put chart into cache."); purifyChart(chart, uuid); } return chart; } protected ChartTheme createStyle(CallContext callContext) { log.debug("Fetch chart theme from global context"); GNVArtifactContext context = (GNVArtifactContext) callContext.globalContext(); XMLChartTheme theme = (XMLChartTheme) context.get( GNVArtifactContext.CHART_TEMPLATE_KEY); return theme; } protected String createChartTitle(Locale locale, String uuid) { return getFisName(locale); } protected String createChartSubtitle(Locale locale, String uuid) { return getSelectedFeatureName(uuid); } protected String getFisName(Locale locale) { String returnValue = ""; InputData input = inputData.get("fisname"); if (input != null) { String value = input.getValue(); returnValue = RessourceFactory.getInstance().getRessource( locale, value, value ); } return returnValue; } protected Collection<KeyValueDescibeData> getParameters(String uuid) { return this.getCollection(parameterValuesName, uuid); } protected Collection<KeyValueDescibeData> getMeasurements(String uuid) { return this.getCollection(measuremenValueName, uuid); } protected Collection<KeyValueDescibeData> getDates(String uuid) { return this.getCollection(dateValueName,uuid); } @Override public void setup(Node configuration) { super.setup(configuration); String featureNameValue = Config.getStringXPath(configuration, "value-names/value-name[@name='feature']/@value"); if (featureNameValue != null) { this.featureValuesName = featureNameValue; } String parameterNameValue = Config.getStringXPath(configuration, "value-names/value-name[@name='parameter']/@value"); if (parameterNameValue != null) { this.parameterValuesName = parameterNameValue; } String measurementNameValue = Config.getStringXPath(configuration, "value-names/value-name[@name='measurement']/@value"); if (measurementNameValue != null) { this.measuremenValueName = measurementNameValue; } String dateNameValue = Config.getStringXPath(configuration, "value-names/value-name[@name='date']/@value"); if (dateNameValue != null) { this.dateValueName = dateNameValue; } if (timeGapDefinitions == null){ Element gapDefinition = (Element)Config.getNodeXPath(configuration, "time-gap-definition"); synchronized (this.getClass()) { if (gapDefinition != null){ String link = gapDefinition.getAttribute("xlink:href"); if (link != null ){ String absolutFileName = Config.replaceConfigDir(link); gapDefinition = (Element)new ArtifactXMLUtilities(). readConfiguration(absolutFileName); } NodeList gapDefinitions = Config.getNodeSetXPath(gapDefinition, "/time-gaps/time-gap"); if (gapDefinition != null){ timeGapDefinitions = new ArrayList<TimeGap>(gapDefinitions. getLength()); for (int i = 0; i < gapDefinitions.getLength(); i++){ Element gapNode = (Element)gapDefinitions.item(i); String unit = gapNode.getAttribute("unit"); int key = Integer.parseInt(gapNode.getAttribute("key")); int value = Integer.parseInt(gapNode.getAttribute("gap")); log.info("Add new Timegap: "+key+" "+value+" "+ unit); timeGapDefinitions.add(new DefaultTimeGap(unit, key, value)); } } } } } } /** * @param collectionName * @return */ protected Collection<KeyValueDescibeData> getCollection( String collectionName, String uuid) { Iterator<Object> it = this.getDescibeData(uuid).iterator(); while (it.hasNext()) { Object o = it.next(); if (o instanceof NamedCollection<?>) { NamedCollection<KeyValueDescibeData> nc = (NamedCollection<KeyValueDescibeData>) o; if (nc.getName().equals(collectionName)) { return nc; } } } return null; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :