# HG changeset patch # User Raimund Renkert # Date 1327592326 0 # Node ID 65dac9cf6ff508e4722de3e2c264c6a0deebe82e # Parent 3f90f4d37c8d2bb5b2150c0abc28d15f804e547f Issue 138. PDF output for waterlevel calculation result. flys-artifacts/trunk@3774 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/ChangeLog Thu Jan 26 15:38:46 2012 +0000 @@ -1,3 +1,45 @@ +2012-01-26 Raimund Renkert + + Issue 138: PDF output for calculations. + + * pom.xml: New Dependency to net.sf.jasperreports/jasperreports and + org.codehaus.groovy/groovy-all. + + * src/main/java/de/intevation/flys/exports/AbstractExporter.java: + Added methods for PDF generation. + + * src/main/java/de/intevation/flys/exports/WaterlevelExporter.java: + Create the PDF data source and generate the PDF report output. + + * src/main/java/de/intevation/flys/artifacts/model/WKmsJRDataSource.java: + New. Data source for jasper reports containing the waterlevel calculation + result. + + * src/main/java/de/intevation/flys/artifacts/states/WaterlevelState.java: + Added facet for PDF export to state. + + * src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java: + Added PDF facet type. + + * src/main/java/de/intevation/flys/exports/DurationCurveExporter.java, + src/main/java/de/intevation/flys/exports/ComputedDischargeCurveExporter.java, + src/main/java/de/intevation/flys/exports/WDifferencesExporter.java: + Added stub for inherited abstract method. + + * doc/conf/artifacts/winfo.xml: + Added PDF facet to outputmode 'export'. + + * doc/conf/jasper, + doc/conf/jasper/waterlevel.jasper: + New. Folder for jasperreports templates and first template for + waterlevel report. + + * src/main/resources/messages.properties, + src/main/resources/messages_de_DE.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: + Added i18n string for calculation mode. + 2012-01-26 Felix Wolfsteller Renderer 'manual' points in LongitudinalSectionGenerator. diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/doc/conf/artifacts/winfo.xml --- a/flys-artifacts/doc/conf/artifacts/winfo.xml Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/doc/conf/artifacts/winfo.xml Thu Jan 26 15:38:46 2012 +0000 @@ -285,6 +285,7 @@ + diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/doc/conf/jasper/waterlevel.jasper Binary file flys-artifacts/doc/conf/jasper/waterlevel.jasper has changed diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/pom.xml --- a/flys-artifacts/pom.xml Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/pom.xml Thu Jan 26 15:38:46 2012 +0000 @@ -130,6 +130,16 @@ velocity 1.7 + + net.sf.jasperreports + jasperreports + 4.5.0 + + + org.codehaus.groovy + groovy-all + 1.6.0 + diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java Thu Jan 26 15:38:46 2012 +0000 @@ -93,6 +93,7 @@ String CSV = "csv"; String WST = "wst"; String AT = "at"; + String PDF = "pdf"; String REPORT = "report"; } diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsJRDataSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WKmsJRDataSource.java Thu Jan 26 15:38:46 2012 +0000 @@ -0,0 +1,108 @@ +package de.intevation.flys.artifacts.model; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.apache.log4j.Logger; + +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JRField; + + +/** + * @author Raimund Renkert + */ +public class WKmsJRDataSource implements JRDataSource +{ + /** The logger used in this exporter.*/ + private static Logger logger = Logger.getLogger(WKmsJRDataSource.class); + + /** + * + */ + private ArrayList data; + private HashMap metaData; + + private int index = -1; + + /** + * + */ + public WKmsJRDataSource() + { + data = new ArrayList(); + metaData = new HashMap(); + } + + + /** + * + */ + public void addData(String[] data) { + this.data.add(data); + } + + + /** + * + */ + public void addMetaData(String key, String value) { + this.metaData.put(key, value); + } + + + /** + * + */ + public boolean next() throws JRException + { + index++; + + return (index < data.size()); + } + + + /** + * + */ + public Object getFieldValue(JRField field) throws JRException + { + Object value = ""; + String fieldName = field.getName(); + if ("river".equals(fieldName)) { + value = metaData.get("river"); + } + if ("date".equals(fieldName)) { + value = metaData.get("date"); + } + if ("range".equals(fieldName)) { + value = metaData.get("range"); + } + if ("gauge".equals(fieldName)) { + value = metaData.get("gauge"); + } + if ("calculation".equals(fieldName)) { + value = metaData.get("calculation"); + } + if ("km".equals(fieldName)) { + value = data.get(index)[0]; + } + if ("W".equals(fieldName)) { + value = data.get(index)[1]; + } + if ("Q".equals(fieldName)) { + value = data.get(index)[2]; + } + if ("description".equals(fieldName)) { + value = data.get(index)[3]; + } + if ("location".equals(fieldName)) { + value = data.get(index)[4]; + } + if ("gaugename".equals(fieldName)) { + value = data.get(index)[5]; + } + return value; + } +} diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelState.java Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelState.java Thu Jan 26 15:38:46 2012 +0000 @@ -89,9 +89,12 @@ WST, "WST data", ComputeType.ADVANCE, hash, id); Facet csv = new DataFacet( CSV, "CSV data", ComputeType.ADVANCE, hash, id); + Facet pdf = new DataFacet( + PDF, "PDF data", ComputeType.ADVANCE, hash, id); facets.add(wst); facets.add(csv); + facets.add(pdf); } if (res.getReport().hasProblems()) { diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/exports/AbstractExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/AbstractExporter.java Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/AbstractExporter.java Thu Jan 26 15:38:46 2012 +0000 @@ -37,6 +37,9 @@ /** The name of the CSV facet which triggers the CSV creation. */ public static final String FACET_CSV = "csv"; + /** The name of the PDF facet which triggers the PDF creation. */ + public static final String FACET_PDF = "pdf"; + /** The default charset for the CSV export. */ public static final String DEFAULT_CSV_CHARSET = "UTF-8"; @@ -73,6 +76,13 @@ /** + * Concrete subclasses need to use this method to write their special data + * objects into the PDF document. + */ + protected abstract void writePDF(OutputStream out); + + + /** * This method enables concrete subclasses to collected its own special * data. * @@ -140,6 +150,9 @@ if (facet != null && facet.equals(FACET_CSV)) { generateCSV(); } + else if (facet != null && facet.equals(FACET_PDF)) { + generatePDF(); + } else { throw new IOException("invalid facet for exporter."); } @@ -223,6 +236,17 @@ /** + * This method starts PDF creation. + */ + protected void generatePDF() + throws IOException + { + logger.info("AbstractExporter.generatePDF"); + writePDF(this.out); + } + + + /** * Returns an instance of EmptySettings currently! * * @return an instance of EmptySettings. diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveExporter.java Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/ComputedDischargeCurveExporter.java Thu Jan 26 15:38:46 2012 +0000 @@ -116,5 +116,9 @@ protected NumberFormat getQFormatter() { return Formatter.getComputedDischargeQ(context); } + + + @Override + protected void writePDF(OutputStream out) {} } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveExporter.java Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveExporter.java Thu Jan 26 15:38:46 2012 +0000 @@ -146,4 +146,9 @@ protected NumberFormat getDFormatter() { return Formatter.getDurationD(context); } + + + @Override + protected void writePDF(OutputStream out) {} + } diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesExporter.java Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/WDifferencesExporter.java Thu Jan 26 15:38:46 2012 +0000 @@ -157,5 +157,9 @@ protected NumberFormat getWFormatter() { return Formatter.getWaterlevelW(context); } + + + @Override + protected void writePDF(OutputStream out) {} } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/java/de/intevation/flys/exports/WaterlevelExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/WaterlevelExporter.java Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/WaterlevelExporter.java Thu Jan 26 15:38:46 2012 +0000 @@ -5,6 +5,8 @@ import java.text.DateFormat; import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; import java.util.Date; import java.util.List; import java.util.Locale; @@ -17,6 +19,12 @@ import au.com.bytecode.opencsv.CSVWriter; +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JasperExportManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JRException; + import de.intevation.artifacts.CallContext; import de.intevation.artifacts.CallMeta; @@ -27,6 +35,7 @@ import de.intevation.flys.artifacts.model.CalculationResult; import de.intevation.flys.artifacts.model.WQCKms; import de.intevation.flys.artifacts.model.WQKms; +import de.intevation.flys.artifacts.model.WKmsJRDataSource; import de.intevation.flys.artifacts.resources.Resources; import de.intevation.flys.utils.FLYSUtils; @@ -108,6 +117,7 @@ public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE = "außerhalb des gewählten Bezugspegels"; + public static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode"; /** The storage that contains all WQKms objects for the different facets.*/ protected List data; @@ -134,6 +144,9 @@ else if (facet != null && facet.equals(FACET_WST)) { generateWST(); } + else if (facet != null && facet.equals(AbstractExporter.FACET_PDF)) { + generatePDF(); + } else { throw new IOException("invalid facet for exporter"); } @@ -570,5 +583,138 @@ protected NumberFormat getQFormatter() { return Formatter.getWaterlevelQ(context); } + + + /** + * + */ + @Override + protected void writePDF(OutputStream out) { + logger.debug("write PDF"); + WKmsJRDataSource source = createJRData(); + Map parameters = new HashMap(); + parameters.put("ReportTitle", "Exported Data"); + try { + JasperPrint print = JasperFillManager.fillReport( + "conf/jasper/waterlevel.jasper", + parameters, + source); + JasperExportManager.exportReportToPdfStream(print, out); + } + catch(JRException je) { + logger.warn("Error generating PDF Report!"); + je.printStackTrace(); + } + } + + protected WKmsJRDataSource createJRData() { + WKmsJRDataSource source = new WKmsJRDataSource(); + + WQ_MODE mode = FLYSUtils.getWQMode((FLYSArtifact)master); + boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; + boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; + + addMetaData(source); + for (WQKms[] tmp: data) { + for (WQKms wqkms: tmp) { + addWKmsData(wqkms, atGauge, isQ, source); + } + } + return source; + } + + protected void addMetaData(WKmsJRDataSource source) { + CallMeta meta = context.getMeta(); + + FLYSArtifact flys = (FLYSArtifact) master; + + source.addMetaData ("river", FLYSUtils.getRivername(flys)); + + Locale locale = Resources.getLocale(meta); + DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + + source.addMetaData("date", df.format(new Date())); + + double[] kms = FLYSUtils.getKmRange(flys); + source.addMetaData("range", kms[0] + " - " + kms[kms.length-1]); + + source.addMetaData("gauge", FLYSUtils.getGaugename(flys)); + + source.addMetaData("calculation", Resources.getMsg( + locale, + PDF_HEADER_MODE, + "Waterlevel")); + } + + protected void addWKmsData( + WQKms wqkms, + boolean atGauge, + boolean isQ, + WKmsJRDataSource source) + { + logger.debug("WaterlevelExporter.addWKmsData"); + + NumberFormat kmf = getKmFormatter(); + NumberFormat wf = getWFormatter(); + NumberFormat qf = getQFormatter(); + + int size = wqkms.size(); + double[] result = new double[3]; + + FLYSArtifact flys = (FLYSArtifact) master; + Gauge gauge = FLYSUtils.getGauge(flys); + String gaugeName = gauge.getName(); + String desc = ""; + String notinrange = msg( + CSV_NOT_IN_GAUGE_RANGE, + DEFAULT_CSV_NOT_IN_GAUGE_RANGE); + + double a = gauge.getRange().getA().doubleValue(); + double b = gauge.getRange().getB().doubleValue(); + + if (flys instanceof WINFOArtifact && isQ) { + desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); + } + else if (!isQ) { + Double value = FLYSUtils.getValueFromWQ(wqkms); + desc = value != null + ? Formatter.getWaterlevelW(context).format(value) : null; + } + + long startTime = System.currentTimeMillis(); + + for (int i = 0; i < size; i ++) { + result = wqkms.get(i, result); + + if (atGauge) { + source.addData(new String[] { + kmf.format(result[2]), + wf.format(result[0]), + qf.format(result[1]), + desc, + FLYSUtils.getLocationDescription(flys, result[2]), + result[2] >= a && result[2] <= b + ? gaugeName + : notinrange + }); + } + else { + source.addData(new String[] { + kmf.format(result[2]), + wf.format(result[0]), + qf.format(result[1]), + FLYSUtils.getLocationDescription(flys, result[2]) + }); + } + } + + long stopTime = System.currentTimeMillis(); + + if (logger.isDebugEnabled()) { + logger.debug("Writing PDF data took " + + (float)(stopTime-startTime)/1000f + " secs."); + } + + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/resources/messages.properties --- a/flys-artifacts/src/main/resources/messages.properties Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages.properties Thu Jan 26 15:38:46 2012 +0000 @@ -107,6 +107,8 @@ export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s] export.discharge.curve.at.header = Computed Discharge Curve for {0} {0}-km: {1} +export.waterlevel.pdf.mode = Waterlevel + floodmap.wmsbackground = Background Map floodmap.riveraxis = River Axis floodmap.uesk = Floodmap diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/resources/messages_de.properties --- a/flys-artifacts/src/main/resources/messages_de.properties Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_de.properties Thu Jan 26 15:38:46 2012 +0000 @@ -107,6 +107,8 @@ export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s] export.discharge.curve.at.header = Berechnete Abflusskurve f\u00fcr {0} {0}-km: {1} +export.waterlevel.pdf.mode = Wasserstand + floodmap.wmsbackground = Hintergrundkarte floodmap.riveraxis = Flussachse floodmap.uesk = \u00dcberschwemmungsfl\u00e4che diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/resources/messages_de_DE.properties --- a/flys-artifacts/src/main/resources/messages_de_DE.properties Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_de_DE.properties Thu Jan 26 15:38:46 2012 +0000 @@ -107,6 +107,8 @@ export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s] export.discharge.curve.at.header = Berechnete Abflusskurve f\u00fcr {0} {0}-km: {1} +export.waterlevel.pdf.mode = Wasserstand + floodmap.wmsbackground = Hintergrundkarte floodmap.riveraxis = Flussachse floodmap.uesk = \u00dcberschwemmungsfl\u00e4che diff -r 3f90f4d37c8d -r 65dac9cf6ff5 flys-artifacts/src/main/resources/messages_en.properties --- a/flys-artifacts/src/main/resources/messages_en.properties Thu Jan 26 13:12:19 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_en.properties Thu Jan 26 15:38:46 2012 +0000 @@ -103,6 +103,8 @@ export.discharge.longitudinal.section.csv.header.q = Q [m\u00b3/s] export.discharge.curve.at.header = Computed Discharge Curve for {0} {0}-km: {1} +export.waterlevel.pdf.mode = Waterlevel + floodmap.wmsbackground = Background Map floodmap.riveraxis = River Axis floodmap.uesk = Floodmap