gernotbelger@9145: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde gernotbelger@9145: * Software engineering by Intevation GmbH gernotbelger@9145: * gernotbelger@9145: * This file is Free Software under the GNU AGPL (>=v3) gernotbelger@9145: * and comes with ABSOLUTELY NO WARRANTY! Check out the gernotbelger@9145: * documentation coming with Dive4Elements River for details. gernotbelger@9145: */ gernotbelger@9145: gernotbelger@9145: package org.dive4elements.river.artifacts.sinfo.flood_duration; gernotbelger@9145: gernotbelger@9145: import java.io.OutputStream; gernotbelger@9145: import java.text.NumberFormat; gernotbelger@9145: import java.util.ArrayList; gernotbelger@9145: import java.util.Collection; gernotbelger@9145: import java.util.List; gernotbelger@9145: gernotbelger@9145: import org.apache.log4j.Logger; gernotbelger@9145: import org.dive4elements.river.artifacts.common.GeneralResultType; gernotbelger@9145: import org.dive4elements.river.artifacts.common.JasperDesigner; gernotbelger@9145: import org.dive4elements.river.artifacts.common.JasperReporter; gernotbelger@9145: import org.dive4elements.river.artifacts.common.MetaAndTableJRDataSource; gernotbelger@9145: import org.dive4elements.river.artifacts.common.ResultRow; gernotbelger@9145: import org.dive4elements.river.artifacts.sinfo.common.AbstractSInfoExporter; gernotbelger@9145: import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType; gernotbelger@9145: import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; gernotbelger@9145: import org.dive4elements.river.artifacts.sinfo.util.WstInfo; gernotbelger@9145: gernotbelger@9145: import au.com.bytecode.opencsv.CSVWriter; gernotbelger@9145: import net.sf.jasperreports.engine.JRException; gernotbelger@9145: gernotbelger@9145: /** gernotbelger@9145: * Generates different output formats (csv, pdf) of data that resulted from a flow depths min/max computation. gernotbelger@9145: * gernotbelger@9145: * @author Ingo Weinzierl gernotbelger@9145: * @author Gernot Belger gernotbelger@9145: */ gernotbelger@9145: // REMARK: must be public because its registered in generators.xml gernotbelger@9145: public class FloodDurationExporter extends AbstractSInfoExporter { gernotbelger@9145: gernotbelger@9145: /** The log used in this exporter. */ gernotbelger@9145: private static Logger log = Logger.getLogger(FloodDurationExporter.class); gernotbelger@9145: gernotbelger@9145: private final String getJasperFile(final int waterlevelCount) { gernotbelger@9145: if (waterlevelCount <= 1) gernotbelger@9145: return "/jasper/templates/sinfo.floodduration.jrxml"; // TODO use jrxml-path all over the project gernotbelger@9145: else gernotbelger@9145: return "/jasper/templates/sinfo.floodduration2.jrxml"; gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: private static final int maxPdfWspls = 3; gernotbelger@9145: gernotbelger@9145: @Override gernotbelger@9145: protected Logger getLog() { gernotbelger@9145: return log; gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: @Override gernotbelger@9145: protected void writeCSVGlobalMetadata(final CSVWriter writer, final FloodDurationCalculationResults results) { gernotbelger@9145: log.info("FloodDurationExporter.writeCSVMeta"); gernotbelger@9145: super.writeCSVGlobalMetadataDefaults(writer, results); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: @Override gernotbelger@9145: protected void writeCSVResultMetadata(final CSVWriter writer, final FloodDurationCalculationResults results, final FloodDurationCalculationResult result) { gernotbelger@9145: gernotbelger@9145: final WstInfo wst = result.getWst(); gernotbelger@9145: super.writeCSVWaterlevelMetadata(writer, wst); // TODO: Abweichend vom Allgemeinen werden hier andere Felder benötigt bei den Wasserspiegellagen gernotbelger@9145: gernotbelger@9145: writer.writeNext(new String[] { "" }); // break line gernotbelger@9145: gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: /** gernotbelger@9145: * Write the header, with different headings depending on whether at a gernotbelger@9145: * gauge or at a location. gernotbelger@9145: * gernotbelger@9145: * @param river gernotbelger@9145: * @param useTkh gernotbelger@9145: */ gernotbelger@9145: @Override gernotbelger@9145: protected void writeCSVHeader(final CSVWriter writer, final FloodDurationCalculationResults results, final RiverInfo river) { gernotbelger@9145: log.info("FloodDurationExporter.writeCSVHeader"); gernotbelger@9145: gernotbelger@9145: final Collection header = new ArrayList<>(99); gernotbelger@9145: gernotbelger@9145: header.add(msg(GeneralResultType.station.getCsvHeader())); gernotbelger@9145: header.add(msg(SInfoResultType.riverside.getCsvHeader())); gernotbelger@9145: header.add(msg(SInfoResultType.inundationduration.getCsvHeader())); gernotbelger@9145: header.add(msg(SInfoResultType.inundationdurationq.getCsvHeader())); gernotbelger@9145: header.add(msg(SInfoResultType.infrastructureHeight.getCsvHeader())); gernotbelger@9145: header.add(msg(SInfoResultType.infrastructuretype.getCsvHeader())); gernotbelger@9145: // add dynamic headers gernotbelger@9145: final int waterlevelCount = getWaterlevelCount(); gernotbelger@9145: for (int i = 0; i < waterlevelCount; i++) { gernotbelger@9145: final int naturalIndex = i + 1; gernotbelger@9145: final String appendIndex = new StringBuilder().append("_").append(naturalIndex).toString(); gernotbelger@9145: final Object[] args = new Object[] { appendIndex }; gernotbelger@9145: // new StringBuilder().append('\u2081').toString(); // schlechter UTF-8-Support für subscript ints gernotbelger@9145: header.add(msg(DurationWaterlevel.getHeaderW(), new Object[] { appendIndex, "results.getRiver().getWstUnit()" })); gernotbelger@9145: header.add(msg(DurationWaterlevel.getHeaderFloodDurPerYear(), args)); gernotbelger@9145: header.add(msg(DurationWaterlevel.getHeaderQ(), args)); gernotbelger@9145: header.add(msg(DurationWaterlevel.getHeaderBezeichn(), args)); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: header.add(msg(SInfoResultType.gaugeLabel.getCsvHeader())); gernotbelger@9145: header.add(msg(SInfoResultType.location.getCsvHeader())); gernotbelger@9145: gernotbelger@9145: writer.writeNext(header.toArray(new String[header.size()])); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: private int getWaterlevelCount() { gernotbelger@9145: final FloodDurationCalculationResults results = getData(); gernotbelger@9145: if (results != null) { gernotbelger@9145: final List list = results.getResults(); gernotbelger@9145: if (list != null && list.size() > 0) { gernotbelger@9145: final FloodDurationCalculationResult result = list.get(0); gernotbelger@9145: return result.getWaterlevelCount(); gernotbelger@9145: } gernotbelger@9145: } gernotbelger@9145: return 0; gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: @Override gernotbelger@9145: protected String[] formatRow(final FloodDurationCalculationResults results, final ResultRow row, final ExportMode mode) { gernotbelger@9145: gernotbelger@9145: final Collection lines = new ArrayList<>(99); gernotbelger@9145: gernotbelger@9145: lines.add(row.exportValue(this.context, GeneralResultType.station)); gernotbelger@9145: lines.add(row.exportValue(this.context, SInfoResultType.riverside)); gernotbelger@9145: lines.add(row.exportValue(this.context, SInfoResultType.inundationduration)); gernotbelger@9145: lines.add(row.exportValue(this.context, SInfoResultType.inundationdurationq)); gernotbelger@9145: lines.add(row.exportValue(this.context, SInfoResultType.infrastructureHeight)); gernotbelger@9145: lines.add(row.exportValue(this.context, SInfoResultType.infrastructuretype)); gernotbelger@9145: gernotbelger@9145: final int waterlevelcount = this.getWaterlevelCount(); gernotbelger@9145: gernotbelger@9145: final List waterlevelList = (List) row.getValue(SInfoResultType.customMultiRowColWaterlevel); gernotbelger@9145: if (waterlevelList != null) { gernotbelger@9145: final NumberFormat wFormatter = getFlowDepthFormatter(); gernotbelger@9145: final NumberFormat qFormatter = getQFormatter(); gernotbelger@9145: gernotbelger@9145: for (int i = 0; i < waterlevelList.size(); i++) { gernotbelger@9145: gernotbelger@9145: if (i == FloodDurationExporter.maxPdfWspls && mode == ExportMode.pdf) gernotbelger@9145: break; gernotbelger@9145: gernotbelger@9145: final DurationWaterlevel item = waterlevelList.get(i); gernotbelger@9145: lines.add(item.getWFormatted(wFormatter)); gernotbelger@9145: lines.add(item.getFloodDurDaysPerYearFormatted()); gernotbelger@9145: lines.add(item.getQFormatted(qFormatter)); gernotbelger@9145: lines.add(item.getBezeichnung()); gernotbelger@9145: } gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: if ((waterlevelcount == 0 || waterlevelcount == 2) && mode == ExportMode.pdf) { gernotbelger@9145: lines.add("dummy"); gernotbelger@9145: lines.add("dummy"); gernotbelger@9145: lines.add("dummy"); gernotbelger@9145: lines.add("dummy"); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: lines.add(row.exportValue(this.context, SInfoResultType.gaugeLabel)); gernotbelger@9145: lines.add(row.exportValue(this.context, SInfoResultType.location)); gernotbelger@9145: return lines.toArray(new String[lines.size()]); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: @Override gernotbelger@9145: protected void writePDF(final OutputStream out) { gernotbelger@9145: gernotbelger@9145: try { gernotbelger@9145: final MetaAndTableJRDataSource source = createJRData(this.data); gernotbelger@9145: final JasperReporter reporter = new JasperReporter(); gernotbelger@9145: final int waterlevelCount = getWaterlevelCount(); gernotbelger@9145: final JasperDesigner design = reporter.addReport(getJasperFile(waterlevelCount), source); gernotbelger@9145: gernotbelger@9145: if (waterlevelCount == 0 || waterlevelCount == 2) { gernotbelger@9145: design.removeColumn("wOpt"); gernotbelger@9145: design.removeColumn("qOpt"); gernotbelger@9145: design.removeColumn("bezOpt"); gernotbelger@9145: design.removeColumn("durOpt"); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: reporter.exportPDF(out); gernotbelger@9145: } gernotbelger@9145: catch (final JRException je) { gernotbelger@9145: getLog().warn("Error generating PDF Report!", je); gernotbelger@9145: } gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: @Override gernotbelger@9145: protected final void addJRMetaData(final MetaAndTableJRDataSource source, final FloodDurationCalculationResults results) { gernotbelger@9145: gernotbelger@9145: /* general metadata */ gernotbelger@9145: super.addJRMetaData(source, results); gernotbelger@9145: gernotbelger@9145: /* column headings */ gernotbelger@9145: source.addMetaData("station_header", GeneralResultType.station.getPdfHeader(this.context.getMeta())); gernotbelger@9145: source.addMetaData("riverside_header", SInfoResultType.riverside.getPdfHeader(this.context.getMeta())); gernotbelger@9145: source.addMetaData("inundationduration_header", SInfoResultType.inundationduration.getPdfHeader(this.context.getMeta())); gernotbelger@9145: source.addMetaData("inundationduration_q_header", SInfoResultType.inundationdurationq.getPdfHeader(this.context.getMeta())); gernotbelger@9145: source.addMetaData("infrastructure_height_header", SInfoResultType.infrastructureHeightFloodDur.getPdfHeader(this.context.getMeta())); gernotbelger@9145: source.addMetaData("infrastructure_type_header", SInfoResultType.infrastructuretype.getPdfHeader(this.context.getMeta())); gernotbelger@9145: gernotbelger@9145: // add dynamic headers gernotbelger@9145: gernotbelger@9145: final int waterlevelCount = getWaterlevelCount() > FloodDurationExporter.maxPdfWspls ? FloodDurationExporter.maxPdfWspls : getWaterlevelCount(); gernotbelger@9145: gernotbelger@9145: if (waterlevelCount == 0 || waterlevelCount == 2) { gernotbelger@9145: source.addMetaData("dummy", "dummy"); gernotbelger@9145: source.addMetaData("dummy", "dummy"); gernotbelger@9145: source.addMetaData("dummy", "dummy"); gernotbelger@9145: source.addMetaData("dummy", "dummy"); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: for (int i = 0; i < waterlevelCount; i++) { gernotbelger@9145: final int naturalIndex = i + 1; gernotbelger@9145: gernotbelger@9145: final Object[] args = new String[] { new StringBuilder().append("_").append(naturalIndex).toString() }; gernotbelger@9145: source.addMetaData(getPdfHeader("w", naturalIndex), msg(DurationWaterlevel.getHeaderW(), args)); gernotbelger@9145: source.addMetaData(getPdfHeader("duration", naturalIndex), msg(DurationWaterlevel.getHeaderFloodDurPerYear(), args)); gernotbelger@9145: source.addMetaData(getPdfHeader("q", naturalIndex), msg(DurationWaterlevel.getHeaderQ(), args)); gernotbelger@9145: source.addMetaData(getPdfHeader("bezeichnung", naturalIndex), msg(DurationWaterlevel.getHeaderBezeichn(), args)); gernotbelger@9145: gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: source.addMetaData("gauge_header", SInfoResultType.gaugeLabel.getPdfHeader(this.context.getMeta())); gernotbelger@9145: source.addMetaData("location_header", SInfoResultType.location.getPdfHeader(this.context.getMeta())); gernotbelger@9145: gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: private String getPdfHeader(final String rootStr, final int index) { gernotbelger@9145: final String hd = "_header"; gernotbelger@9145: final StringBuilder builder = new StringBuilder(); gernotbelger@9145: return builder.append(rootStr).append("_").append(index).append(hd).toString(); gernotbelger@9145: } gernotbelger@9145: gernotbelger@9145: }