# HG changeset patch # User Sascha L. Teichmann # Date 1333649267 0 # Node ID cc0fa1798a3c4afa20adb456e2340bfd53f9754a # Parent 6ed24efc80debfd49adf8ed1554a213872e0146d FixingsKMChartService: Generate chart and deliver the image as the response of the service. flys-artifacts/trunk@4205 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 6ed24efc80de -r cc0fa1798a3c flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Thu Apr 05 15:29:52 2012 +0000 +++ b/flys-artifacts/ChangeLog Thu Apr 05 18:07:47 2012 +0000 @@ -1,3 +1,11 @@ +2012-04-05 Sascha L. Teichmann + + * src/main/java/de/intevation/flys/artifacts/services/FixingsKMChartService.java: + Generate chart and deliver the image as the response of the service. + + * src/main/java/de/intevation/flys/artifacts/model/FixingsColumnFactory.java: + Return null when looking for a fixing data column that does not exist. + 2012-04-05 Sascha L. Teichmann * src/main/java/de/intevation/flys/artifacts/model/FixingsColumnFactory.java: diff -r 6ed24efc80de -r cc0fa1798a3c flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsColumnFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsColumnFactory.java Thu Apr 05 15:29:52 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FixingsColumnFactory.java Thu Apr 05 18:07:47 2012 +0000 @@ -53,8 +53,9 @@ return (FixingsColumn)element.getValue(); } - result = getUncached(column); - cache.put(new Element(cacheKey, result)); + if ((result = getUncached(column)) != null) { + cache.put(new Element(cacheKey, result)); + } } else { result = getUncached(column); @@ -74,6 +75,10 @@ List results = sqlQuery.list(); + if (results.isEmpty()) { + return null; + } + double [] kms = new double[results.size()]; double [] ws = new double[kms.length]; @@ -92,6 +97,10 @@ results = sqlQuery.list(); + if (results.isEmpty()) { + return null; + } + QRangeTree qs = new QRangeTree( results, QRangeTree.WITHOUT_COLUMN, 0, results.size()); diff -r 6ed24efc80de -r cc0fa1798a3c flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsKMChartService.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsKMChartService.java Thu Apr 05 15:29:52 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/FixingsKMChartService.java Thu Apr 05 18:07:47 2012 +0000 @@ -1,25 +1,50 @@ package de.intevation.flys.artifacts.services; -import java.util.List; - import de.intevation.artifactdatabase.DefaultService; import de.intevation.artifacts.CallMeta; import de.intevation.artifacts.GlobalContext; import de.intevation.artifacts.Service; -import de.intevation.flys.artifacts.model.FixingsFilterBuilder; -import de.intevation.flys.artifacts.model.FixingsOverview; import de.intevation.flys.artifacts.model.FixingsColumn; import de.intevation.flys.artifacts.model.FixingsColumnFactory; -import de.intevation.flys.artifacts.model.FixingsOverviewFactory; +import de.intevation.flys.artifacts.model.FixingsFilterBuilder; import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; +import de.intevation.flys.artifacts.model.FixingsOverview; +import de.intevation.flys.artifacts.model.FixingsOverviewFactory; + import de.intevation.flys.backend.SessionHolder; +import de.intevation.flys.utils.Pair; + +import gnu.trove.TDoubleArrayList; + +import java.awt.Dimension; +import java.awt.Transparency; + +import java.awt.image.BufferedImage; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.List; + +import javax.imageio.ImageIO; + import org.apache.log4j.Logger; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; + +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; + +import org.jfree.data.xy.DefaultXYDataset; + import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -30,6 +55,12 @@ private static final Logger log = Logger.getLogger(FixingsKMChartService.class); + public static final int DEFAULT_WIDTH = 240; + public static final int DEFAULT_HEIGHT = 180; + + public static final String DEFAULT_FORMAT = "png"; + + // TODO: Load fancy image from resources. public static final byte [] EMPTY = { (byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47, (byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a, @@ -91,32 +122,17 @@ } protected Service.Output doProcess( - Document data, + Document input, GlobalContext globalContext, CallMeta callMeta ) { - NodeList rivers = data.getElementsByTagName("river"); - NodeList kms = data.getElementsByTagName("km"); - - if (rivers.getLength() == 0 || kms.getLength() == 0) { - log.warn("Missing river and/or km."); - return empty(); - } - - String river = ((Element)rivers.item(0)).getAttribute("name"); - String kmS = ((Element)kms .item(0)).getAttribute("value"); + String river = getRiverName(input); + Double km = getKM(input); + Dimension extent = getExtent(input); + String format = getFormat(input); - if (river.length() == 0 || kmS.length() == 0) { - log.warn("River and/or km empty string."); - return empty(); - } - - double km; - try { - km = Double.parseDouble(kmS); - } - catch (NumberFormatException nfe) { - log.warn("Km '" + kmS + " is not a valid number."); + if (river == null || km == null) { + log.warn("River and/or km invalid."); return empty(); } @@ -127,22 +143,170 @@ return empty(); } - FixingsFilterBuilder ffb = new FixingsFilterBuilder(data); + FixingsFilterBuilder ffb = new FixingsFilterBuilder(input); List columns = overview.filter( ffb.getRange(), ffb.getFilter()); - for (Fixing.Column column: columns) { - FixingsColumn columnData = - FixingsColumnFactory.INSTANCE.getColumnData(column); - if (columnData == null) { - continue; + List> cols = + new ArrayList>(); + + for (Fixing.Column col: columns) { + FixingsColumn data = + FixingsColumnFactory.INSTANCE.getColumnData(col); + if (data != null) { + cols.add(new Pair(col, data)); } } - // TODO: Implement chart generation! - return empty(); + JFreeChart chart = createChart(cols, river, km); + + return encode(chart, extent, format); + } + + protected static Output encode( + JFreeChart chart, + Dimension extent, + String format + ) { + BufferedImage image = chart.createBufferedImage( + extent.width, extent.height, + Transparency.BITMASK, + null); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + try { + ImageIO.write(image, format, out); + } + catch (IOException ioe) { + log.warn("writing image failed", ioe); + return empty(); + } + + return new Output(out.toByteArray(), "image/" + format); + } + + protected static JFreeChart createChart( + List> cols, + String river, + double km + ) { + + TDoubleArrayList ws = new TDoubleArrayList(cols.size()); + TDoubleArrayList qs = new TDoubleArrayList(cols.size()); + + double [] w = new double[1]; + for (Pair col: cols) { + boolean interpolated = col.getB().getW(km, w); + // TODO: Do something special with the interpolated values. + double q = col.getB().getQ(km); + if (!Double.isNaN(w[0]) && !Double.isNaN(q)) { + ws.add(w[0]); + qs.add(q); + // TODO: Generate labels depending on sectors. + } + } + + DefaultXYDataset dataset = new DefaultXYDataset(); + + dataset.addSeries( + "Fixierungen", // TODO: i18n + new double [][] { ws.toNativeArray(), qs.toNativeArray() }); + + JFreeChart chart = ChartFactory.createXYLineChart( + "Fixierungen " + river + ": km " + km, // TODO: i18n + "Q", // TODO: i18n + "W", // TODO: i18n + null, + PlotOrientation.VERTICAL, + true, + true, + false); + + XYPlot plot = chart.getXYPlot(); + + plot.setDataset(dataset); + + ChartUtilities.applyCurrentTheme(chart); + + return chart; + } + + protected static String getRiverName(Document input) { + NodeList rivers = input.getElementsByTagName("river"); + + if (rivers.getLength() == 0) { + return null; + } + + String river = ((Element)rivers.item(0)).getAttribute("name"); + + return river.length() == 0 ? river : null; + } + + protected static Double getKM(Document input) { + NodeList kms = input.getElementsByTagName("km"); + + if (kms.getLength() == 0) { + return null; + } + + String km = ((Element)kms.item(0)).getAttribute("value"); + + try { + return Double.valueOf(km); + } + catch (NumberFormatException nfe) { + log.warn("Km '" + km + " is not a valid number."); + return null; + } + } + + protected static Dimension getExtent(Document input) { + + int width = DEFAULT_WIDTH; + int height = DEFAULT_HEIGHT; + + NodeList extents = input.getElementsByTagName("extent"); + + if (extents.getLength() > 0) { + Element element = (Element)extents.item(0); + String w = element.getAttribute("width"); + String h = element.getAttribute("height"); + + try { + width = Math.max(1, Integer.parseInt(w)); + } + catch (NumberFormatException nfe) { + log.warn("width '" + w + "' is not a valid."); + } + + try { + height = Math.max(1, Integer.parseInt(h)); + } + catch (NumberFormatException nfe) { + log.warn("height '" + h + "' is not a valid"); + } + } + + return new Dimension(width, height); + } + + protected static String getFormat(Document input) { + String format = DEFAULT_FORMAT; + + NodeList formats = input.getElementsByTagName("format"); + + if (formats.getLength() > 0) { + String type = ((Element)formats.item(0)).getAttribute("type"); + if (type.length() > 0) { + format = type; + } + } + + return format; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :