andre@8578: /* Copyright (C) 2011, 2012, 2013, 2015 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.exports.sq; ingo@3077: ingo@3077: import java.io.OutputStream; aheinecke@6172: import java.text.DateFormat; aheinecke@6828: import java.text.NumberFormat; gernotbelger@9312: import java.util.ArrayList; gernotbelger@9312: import java.util.Date; gernotbelger@9312: import java.util.HashMap; gernotbelger@9312: import java.util.List; gernotbelger@9312: import java.util.Locale; gernotbelger@9312: import java.util.Map; ingo@3077: gernotbelger@9312: import org.apache.log4j.Logger; gernotbelger@9312: import org.dive4elements.artifacts.CallMeta; gernotbelger@9312: import org.dive4elements.artifacts.common.utils.Config; gernotbelger@9312: import org.dive4elements.river.artifacts.D4EArtifact; gernotbelger@9312: import org.dive4elements.river.artifacts.access.SQRelationAccess; gernotbelger@9312: import org.dive4elements.river.artifacts.model.CalculationResult; gernotbelger@9312: import org.dive4elements.river.artifacts.model.DateRange; gernotbelger@9312: import org.dive4elements.river.artifacts.model.Parameters; gernotbelger@9312: import org.dive4elements.river.artifacts.model.sq.SQ; gernotbelger@9312: import org.dive4elements.river.artifacts.model.sq.SQFractionResult; gernotbelger@9312: import org.dive4elements.river.artifacts.model.sq.SQMeasurementsJRDataSource; gernotbelger@9312: import org.dive4elements.river.artifacts.model.sq.SQRelationJRDataSource; gernotbelger@9312: import org.dive4elements.river.artifacts.model.sq.SQResult; gernotbelger@9312: import org.dive4elements.river.artifacts.resources.Resources; gernotbelger@9312: import org.dive4elements.river.exports.AbstractExporter; gernotbelger@9312: import org.dive4elements.river.utils.Formatter; gernotbelger@9312: import org.dive4elements.river.utils.RiverUtils; gernotbelger@9312: gernotbelger@9312: import au.com.bytecode.opencsv.CSVWriter; gernotbelger@9312: import net.sf.jasperreports.engine.JRException; gernotbelger@9312: import net.sf.jasperreports.engine.JRPrintPage; aheinecke@6172: import net.sf.jasperreports.engine.JasperExportManager; aheinecke@6172: import net.sf.jasperreports.engine.JasperFillManager; aheinecke@6172: import net.sf.jasperreports.engine.JasperPrint; ingo@3077: ingo@3077: /** ingo@3077: * @author Ingo Weinzierl ingo@3077: */ ingo@3077: public class SQRelationExporter extends AbstractExporter { ingo@3077: teichmann@8202: /** Private log. */ gernotbelger@9312: private static final Logger log = Logger.getLogger(SQRelationExporter.class); ingo@3077: gernotbelger@9312: public static final String INFO_COEFF_A = "export.sqrelation.csv.info.coeff.a"; ingo@3077: gernotbelger@9312: public static final String INFO_COEFF_B = "export.sqrelation.csv.info.coeff.b"; andre@8541: gernotbelger@9312: public static final String INFO_QMAX = "export.sqrelation.csv.info.qmax"; aheinecke@6172: gernotbelger@9312: public static final String INFO_STDERR = "export.sqrelation.csv.info.stderr"; aheinecke@6172: gernotbelger@9312: public static final String INFO_R2 = "export.sqrelation.csv.info.r2"; ingo@3077: gernotbelger@9312: public static final String INFO_NTOT = "export.sqrelation.csv.info.ntot"; andre@8578: gernotbelger@9312: public static final String INFO_NOUTL = "export.sqrelation.csv.info.noutl"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_CFERGUSON = "export.sqrelation.csv.info.cferguson"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_CDUAN = "export.sqrelation.csv.info.cduan"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_PARAM_A = "export.sqrelation.csv.info.param.a"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_PARAM_B = "export.sqrelation.csv.info.param.b"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_PARAM_C = "export.sqrelation.csv.info.param.c"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_PARAM_D = "export.sqrelation.csv.info.param.d"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_PARAM_E = "export.sqrelation.csv.info.param.e"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_PARAM_F = "export.sqrelation.csv.info.param.f"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_Q = "export.sqrelation.csv.info.q"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_S_KG = "export.sqrelation.csv.info.s_kg"; gernotbelger@9312: gernotbelger@9312: public static final String INFO_DATE = "export.sqrelation.csv.info.date"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_PARAMETER = "export.sqrelation.csv.header.parameter"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_STATION = "export.sqrelation.csv.header.station"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_KM = "export.sqrelation.csv.header.km"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_FUNCTION = "export.sqrelation.csv.header.function"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_GAUGE = "export.sqrelation.csv.header.gauge"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_COEFF_A = "export.sqrelation.csv.header.coeff.a"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_COEFF_B = "export.sqrelation.csv.header.coeff.b"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_COEFF_Q = "export.sqrelation.csv.header.coeff.q"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_COEFF_R = "export.sqrelation.csv.header.coeff.r"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_N_TOTAL = "export.sqrelation.csv.header.n.total"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_N_OUTLIERS = "export.sqrelation.csv.header.n.outliers"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_C_DUAN = "export.sqrelation.csv.header.c.duan"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_C_FERGUSON = "export.sqrelation.csv.header.c.ferguson"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_QMAX = "export.sqrelation.csv.header.qmax"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_SD = "export.sqrelation.csv.header.sd"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_S_KG = "export.sqrelation.csv.header.s_kg"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_Q = "common.export.csv.header.q"; gernotbelger@9312: gernotbelger@9312: public static final String CSV_DATE = "export.sqrelation.csv.header.date"; gernotbelger@9312: gernotbelger@9312: public static final String PDF_TITLE = "export.sqrelation.pdf.title"; gernotbelger@9312: gernotbelger@9312: public static final String PDF_HEADER_MODE = "export.sqrelation.pdf.mode"; gernotbelger@9312: gernotbelger@9312: public static final String JASPER_FILE = "export.sqrelation.pdf.file"; gernotbelger@9312: gernotbelger@9312: public static final String JASPER_MEASUREMENTS_FILE = "export.sqrelation.measurements.pdf.file"; gernotbelger@9312: gernotbelger@9312: protected List data; ingo@3077: teichmann@7077: public SQRelationExporter() { gernotbelger@9312: this.data = new ArrayList<>(); ingo@3077: } ingo@3077: ingo@3077: @Override ingo@3077: protected void addData(Object d) { ingo@3077: if (d instanceof CalculationResult) { gernotbelger@9312: d = ((CalculationResult) d).getData(); gernotbelger@9312: if (d instanceof SQResult[]) { gernotbelger@9312: this.data.add((SQResult[]) d); ingo@3077: } ingo@3077: } ingo@3077: } ingo@3077: gernotbelger@9312: protected void writeCSVHeader(final CSVWriter writer) { gernotbelger@9312: writer.writeNext(new String[] { msg(CSV_KM), msg(CSV_PARAMETER), msg(CSV_COEFF_A), msg(CSV_COEFF_B), msg(CSV_SD), msg(CSV_QMAX), msg(CSV_COEFF_R), gernotbelger@9312: msg(CSV_N_TOTAL), msg(CSV_N_OUTLIERS), msg(CSV_C_DUAN), msg(CSV_C_FERGUSON), msg(CSV_S_KG), msg(CSV_Q), msg(CSV_DATE) }); sascha@3392: } ingo@3077: ingo@3077: @Override gernotbelger@9312: protected void writeCSVData(final CSVWriter writer) { teichmann@8202: log.debug("writeCSVData"); ingo@3077: gernotbelger@9312: writeCSVInfo(writer, gernotbelger@9312: new String[] { msg(INFO_PARAM_A), msg(INFO_PARAM_B), msg(INFO_PARAM_C), msg(INFO_PARAM_D), msg(INFO_PARAM_E), msg(INFO_PARAM_F), gernotbelger@9312: msg(INFO_COEFF_A), msg(INFO_COEFF_B), msg(INFO_QMAX), msg(INFO_STDERR), msg(INFO_R2), msg(INFO_NTOT), msg(INFO_NOUTL), gernotbelger@9312: msg(INFO_CFERGUSON), msg(INFO_CDUAN), msg(INFO_S_KG), msg(INFO_Q), msg(INFO_DATE) }); tom@7937: ingo@3077: writeCSVHeader(writer); ingo@3077: gernotbelger@9312: for (final SQResult[] results : this.data) { gernotbelger@9312: for (final SQResult result : results) { andre@8578: writer.writeAll(data2StringArrays(result, true)); sascha@3392: } ingo@3077: } ingo@3077: } ingo@3077: gernotbelger@9312: protected List data2StringArrays(final SQResult result, final boolean includeMeasurements) { gernotbelger@9312: final String km = Formatter.getSQRelationKM(this.context).format(result.getKm()); gernotbelger@9312: final List retval = new ArrayList<>(); ingo@3077: gernotbelger@9312: final NumberFormat sqAFormatter = Formatter.getSQRelationA(this.context); gernotbelger@9312: final NumberFormat sqBFormatter = Formatter.getSQRelationB(this.context); gernotbelger@9312: final NumberFormat fThreeFormatter = Formatter.getFormatter(this.context, 3, 3); gernotbelger@9312: final NumberFormat fTwoFormatter = Formatter.getFormatter(this.context, 2, 2); gernotbelger@9312: final NumberFormat fZeroFormatter = Formatter.getFormatter(this.context, 0, 0); gernotbelger@9312: final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Resources.getLocale(this.context.getMeta())); aheinecke@6828: sascha@3392: for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) { gernotbelger@9312: final SQFractionResult fraction = result.getFraction(i); sascha@3552: gernotbelger@9312: final String name = result.getFractionName(i); sascha@3552: gernotbelger@9312: final Parameters parameters = fraction.getParameters(); sascha@3552: sascha@3552: if (parameters == null) { sascha@3392: continue; sascha@3392: } sascha@3552: aheinecke@6828: String a, b, sd, o, t, max_q, c_ferguson, c_duan, r2; gernotbelger@9312: a = sqAFormatter.format(parameters.getValue(0, "a")); gernotbelger@9312: b = sqBFormatter.format(parameters.getValue(0, "b")); aheinecke@6828: aheinecke@6828: /* The std_dev parameter contains the standard error actually */ aheinecke@6828: sd = fThreeFormatter.format(parameters.getValue(0, "std_dev")); aheinecke@6828: max_q = fZeroFormatter.format(parameters.getValue(0, "max_q")); gernotbelger@9312: c_ferguson = fTwoFormatter.format(parameters.getValue(0, "c_ferguson")); aheinecke@6828: c_duan = fTwoFormatter.format(parameters.getValue(0, "c_duan")); aheinecke@6828: r2 = fTwoFormatter.format(parameters.getValue(0, "r2")); aheinecke@6828: gernotbelger@9312: o = String.valueOf(fraction.totalNumOutliers()); gernotbelger@9312: t = String.valueOf(fraction.numMeasurements()); aheinecke@6172: andre@8578: if (includeMeasurements) { gernotbelger@9312: for (final SQ sq : fraction.getMeasurements()) { gernotbelger@9312: retval.add(new String[] { km, name, a, b, sd, // 4 gernotbelger@9312: max_q, // 5 gernotbelger@9312: r2, // 6 gernotbelger@9312: t, // 7 gernotbelger@9312: o, // 8 gernotbelger@9312: c_duan, // 9 gernotbelger@9312: c_ferguson, // 10 gernotbelger@9312: fThreeFormatter.format(sq.getS()), fZeroFormatter.format(sq.getQ()), df.format(sq.getDate()) }); gernotbelger@9312: } gernotbelger@9312: } else { gernotbelger@9312: retval.add(new String[] { km, name, a, b, sd, // 4 andre@8578: max_q, // 5 andre@8578: r2, // 6 andre@8578: t, // 7 andre@8578: o, // 8 andre@8578: c_duan, // 9 gernotbelger@9312: c_ferguson // 10 andre@8541: }); andre@8541: } andre@8541: sascha@3392: } aheinecke@6172: return retval; ingo@3077: } ingo@3077: aheinecke@6172: protected SQRelationJRDataSource createJRData() { gernotbelger@9312: final SQRelationJRDataSource source = new SQRelationJRDataSource(); aheinecke@6172: aheinecke@6172: addMetaData(source); gernotbelger@9312: for (final SQResult[] results : this.data) { gernotbelger@9312: for (final SQResult result : results) { gernotbelger@9312: for (final String[] res : data2StringArrays(result, false)) { aheinecke@6172: source.addData(res); aheinecke@6172: } aheinecke@6172: } aheinecke@6172: } aheinecke@6172: return source; aheinecke@6172: } aheinecke@6172: andre@8578: protected SQMeasurementsJRDataSource createMeasurementJRData() { gernotbelger@9312: final SQMeasurementsJRDataSource source = new SQMeasurementsJRDataSource(); gernotbelger@9312: final NumberFormat fZeroFormatter = Formatter.getFormatter(this.context, 0, 0); gernotbelger@9312: final NumberFormat fThreeFormatter = Formatter.getFormatter(this.context, 3, 3); gernotbelger@9312: final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Resources.getLocale(this.context.getMeta())); andre@8578: gernotbelger@9312: for (final SQResult[] results : this.data) { gernotbelger@9312: for (final SQResult result : results) { andre@8578: for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) { gernotbelger@9312: final String name = result.getFractionName(i); gernotbelger@9312: final SQFractionResult fraction = result.getFraction(i); gernotbelger@9312: for (final SQ sq : fraction.getMeasurements()) { gernotbelger@9312: source.addData( gernotbelger@9312: new String[] { name, fThreeFormatter.format(sq.getS()), fZeroFormatter.format(sq.getQ()), df.format(sq.getDate()), null }); andre@8578: } andre@8578: for (int j = 0; j < fraction.numIterations(); j++) { gernotbelger@9312: for (final SQ sq : fraction.getOutliers(j)) { gernotbelger@9312: source.addData(new String[] { name, fThreeFormatter.format(sq.getS()), fZeroFormatter.format(sq.getQ()), df.format(sq.getDate()), gernotbelger@9312: Integer.toString(j + 1) }); andre@8578: } andre@8578: } andre@8578: } andre@8578: } andre@8578: } andre@8578: return source; andre@8578: } andre@8578: gernotbelger@9312: protected void addMetaData(final SQRelationJRDataSource source) { gernotbelger@9312: final CallMeta meta = this.context.getMeta(); aheinecke@6172: gernotbelger@9312: final D4EArtifact arti = (D4EArtifact) this.master; aheinecke@6172: gernotbelger@9312: source.addMetaData("river", RiverUtils.getRivername(arti)); aheinecke@6172: gernotbelger@9312: final Locale locale = Resources.getLocale(meta); gernotbelger@9312: final DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); aheinecke@6172: aheinecke@6172: source.addMetaData("date", df.format(new Date())); aheinecke@6172: gernotbelger@9312: final SQRelationAccess access = new SQRelationAccess(arti); gernotbelger@9312: source.addMetaData("location", "KM " + getKmFormatter().format(access.getLocation())); aheinecke@6172: gernotbelger@9312: final DateRange period = access.getPeriod(); gernotbelger@9312: source.addMetaData("periods", df.format(period.getFrom()) + " - " + df.format(period.getTo())); aheinecke@6172: gernotbelger@9312: source.addMetaData("outliertest", Resources.getMsg(meta, access.getOutlierMethod(), access.getOutlierMethod())); gernotbelger@9312: source.addMetaData("outliers", Formatter.getRawFormatter(this.context).format(access.getOutliers())); aheinecke@6859: gernotbelger@9312: source.addMetaData("calculation", Resources.getMsg(locale, PDF_HEADER_MODE, "SQRelation")); gernotbelger@9312: gernotbelger@9312: final String measurementStationName = access.getMeasurementStationName(); aheinecke@6859: aheinecke@6859: if (measurementStationName != null) { aheinecke@6859: source.addMetaData("msName", measurementStationName); aheinecke@7380: } else { aheinecke@7380: source.addMetaData("msName", ""); aheinecke@6859: } aheinecke@6859: gernotbelger@9312: final String measurementStationGaugeName = access.getMeasurementStationGaugeName(); aheinecke@6859: aheinecke@6859: if (measurementStationGaugeName != null) { aheinecke@6859: source.addMetaData("msGauge", measurementStationGaugeName); aheinecke@7380: } else { aheinecke@7380: source.addMetaData("msGauge", ""); aheinecke@6859: } aheinecke@6859: aheinecke@6172: } aheinecke@6172: ingo@3077: @Override gernotbelger@9312: protected void writePDF(final OutputStream out) { teichmann@8202: log.debug("write PDF"); gernotbelger@9312: final SQRelationJRDataSource source = createJRData(); gernotbelger@9312: final SQMeasurementsJRDataSource measureSource = createMeasurementJRData(); aheinecke@6172: gernotbelger@9312: final String jasperFile = Resources.getMsg(this.context.getMeta(), JASPER_FILE, "/jasper/sqrelation_en.jasper"); gernotbelger@9312: final String jasperMeasurementsFile = Resources.getMsg(this.context.getMeta(), JASPER_MEASUREMENTS_FILE, "/jasper/sqmeasurements_en.jasper"); gernotbelger@9312: final String confPath = Config.getConfigDirectory().toString(); gernotbelger@9312: gernotbelger@9312: final Map parameters = new HashMap(); gernotbelger@9312: parameters.put("ReportTitle", Resources.getMsg(this.context.getMeta(), PDF_TITLE, "Exported Data")); aheinecke@6172: try { gernotbelger@9312: /* gernotbelger@9312: * Page numbers start have a built in offset of 1 so this gernotbelger@9312: * is fine. gernotbelger@9312: */ gernotbelger@9312: final JasperPrint p2 = JasperFillManager.fillReport(confPath + jasperMeasurementsFile, parameters, measureSource); andre@8578: parameters.put("MEASUREMENT_PAGE_NUM", p2.getPages().size()); gernotbelger@9312: final JasperPrint p1 = JasperFillManager.fillReport(confPath + jasperFile, parameters, source); gernotbelger@9312: for (final Object page : p2.getPages()) { gernotbelger@9312: final JRPrintPage object = (JRPrintPage) page; andre@8578: p1.addPage(object); andre@8578: } andre@8578: JasperExportManager.exportReportToPdfStream(p1, out); aheinecke@6172: } gernotbelger@9312: catch (final JRException je) { teichmann@8202: log.warn("Error generating PDF Report!", je); aheinecke@6172: } ingo@3077: } ingo@3077: } ingo@3077: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :