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 :