Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/exports/WaterlevelExporter.java @ 2156:4e0878695c5f
Made StyledSeriesBuilder more robust.
flys-artifacts/trunk@3741 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Fri, 20 Jan 2012 10:23:27 +0000 |
parents | a4bdf7d8527e |
children | 65dac9cf6ff5 |
line wrap: on
line source
package de.intevation.flys.exports; import java.io.IOException; import java.io.OutputStream; import java.text.DateFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.w3c.dom.Document; import org.apache.log4j.Logger; import au.com.bytecode.opencsv.CSVWriter; import de.intevation.artifacts.CallContext; import de.intevation.artifacts.CallMeta; import de.intevation.flys.model.Gauge; import de.intevation.flys.artifacts.FLYSArtifact; import de.intevation.flys.artifacts.WINFOArtifact; 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.resources.Resources; import de.intevation.flys.utils.FLYSUtils; import de.intevation.flys.utils.FLYSUtils.WQ_MODE; import de.intevation.flys.utils.Formatter; /** * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class WaterlevelExporter extends AbstractExporter { /** The logger used in this exporter.*/ private static Logger logger = Logger.getLogger(WaterlevelExporter.class); public static final String FACET_WST = "wst"; public static final String CSV_KM_HEADER = "export.waterlevel.csv.header.km"; public static final String CSV_W_HEADER = "export.waterlevel.csv.header.w"; public static final String CSV_Q_HEADER = "export.waterlevel.csv.header.q"; public static final String CSV_Q_DESC_HEADER = "export.waterlevel.csv.header.q.desc"; public static final String CSV_W_DESC_HEADER = "export.waterlevel.csv.header.w.desc"; public static final String CSV_LOCATION_HEADER = "export.waterlevel.csv.header.location"; public static final String CSV_GAUGE_HEADER = "export.waterlevel.csv.header.gauge"; public static final String CSV_META_RESULT = "export.waterlevel.csv.meta.result"; public static final String CSV_META_CREATION = "export.waterlevel.csv.meta.creation"; public static final String CSV_META_CALCULATIONBASE = "export.waterlevel.csv.meta.calculationbase"; public static final String CSV_META_RIVER = "export.waterlevel.csv.meta.river"; public static final String CSV_META_RANGE = "export.waterlevel.csv.meta.range"; public static final String CSV_META_GAUGE = "export.waterlevel.csv.meta.gauge"; public static final String CSV_META_Q = "export.waterlevel.csv.meta.q"; public static final String CSV_META_W = "export.waterlevel.csv.meta.w"; public static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range"; public static final Pattern NUMBERS_PATTERN = Pattern.compile("\\D*(\\d++.\\d*)\\D*"); public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km"; public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; public static final String DEFAULT_CSV_Q_DESC_HEADER = "Bezeichnung"; public static final String DEFAULT_CSV_W_DESC_HEADER = "W/Pegel [cm]"; public static final String DEFAULT_CSV_LOCATION_HEADER = "Lage"; public static final String DEFAULT_CSV_GAUGE_HEADER = "Bezugspegel"; public static final String DEFAULT_CSV_NOT_IN_GAUGE_RANGE = "außerhalb des gewählten Bezugspegels"; /** The storage that contains all WQKms objects for the different facets.*/ protected List<WQKms[]> data; public void init(Document request, OutputStream out, CallContext context) { logger.debug("WaterlevelExporter.init"); super.init(request, out, context); this.data = new ArrayList<WQKms[]>(); } @Override public void generate() throws IOException { logger.debug("WaterlevelExporter.generate"); if (facet != null && facet.equals(AbstractExporter.FACET_CSV)) { generateCSV(); } else if (facet != null && facet.equals(FACET_WST)) { generateWST(); } else { throw new IOException("invalid facet for exporter"); } } @Override protected void addData(Object d) { if (d instanceof CalculationResult) { d = ((CalculationResult)d).getData(); if (d instanceof WQKms []) { data.add((WQKms [])d); } } } /** * This method is used to prepare the column titles of waterlevel exports. * Titles in this export include the Q value. If a Q value matches a named * main value (as HQ100 or MNQ) this named main value should be used as * title. This method resets the name of the <i>wqkms</i> object if such * named main value fits to the chosen Q. * * @param winfo A WINFO Artifact. * @param wqkms A WQKms object that should be prepared. */ protected String getColumnTitle(WINFOArtifact winfo, WQKms wqkms) { logger.debug("WaterlevelExporter.prepareNamedValue"); String name = wqkms.getName(); logger.debug("Name of WQKms = '" + name + "'"); if (name.indexOf("W=") >= 0) { return name; } Matcher m = NUMBERS_PATTERN.matcher(name); if (m.matches()) { String raw = m.group(1); try { double v = Double.valueOf(raw); String nmv = FLYSUtils.getNamedMainValue(winfo, v); if (nmv != null && nmv.length() > 0) { nmv = FLYSUtils.stripNamedMainValue(nmv); logger.debug("Set named main value '" + nmv + "'"); return nmv; } } catch (NumberFormatException nfe) { // do nothing here } } return name; } protected String getCSVRowTitle(WINFOArtifact winfo, WQKms wqkms) { logger.debug("WaterlevelExporter.prepareNamedValue"); String name = wqkms.getName(); logger.debug("Name of WQKms = '" + name + "'"); WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.QGAUGE) { return localizeWQKms(winfo, wqkms); } Double v = wqkms.getRawValue(); String nmv = FLYSUtils.getNamedMainValue(winfo, v); if (nmv != null && nmv.length() > 0) { nmv = FLYSUtils.stripNamedMainValue(nmv); logger.debug("Set named main value '" + nmv + "'"); return nmv; } return localizeWQKms(winfo, wqkms); } protected String localizeWQKms(WINFOArtifact winfo, WQKms wqkms) { WQ_MODE wqmode = FLYSUtils.getWQMode(winfo); Double rawValue = wqkms.getRawValue(); if (rawValue == null) { return wqkms.getName(); } NumberFormat nf = Formatter.getRawFormatter(context); if (wqmode == WQ_MODE.WFREE || wqmode == WQ_MODE.WGAUGE) { return "W=" + nf.format(rawValue); } else { return "Q=" + nf.format(rawValue); } } @Override protected void writeCSVData(CSVWriter writer) { logger.info("WaterlevelExporter.writeData"); 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; writeCSVMeta(writer); writeCSVHeader(writer, atGauge, isQ); for (WQKms[] tmp: data) { for (WQKms wqkms: tmp) { wQKms2CSV(writer, wqkms, atGauge, isQ); } } } protected void writeCSVMeta(CSVWriter writer) { logger.info("WaterlevelExporter.writeCSVMeta"); CallMeta meta = context.getMeta(); FLYSArtifact flys = (FLYSArtifact) master; writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_RESULT, CSV_META_RESULT, new Object[] { FLYSUtils.getRivername(flys) }) }); Locale locale = Resources.getLocale(meta); DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_CREATION, CSV_META_CREATION, new Object[] { df.format(new Date()) }) }); writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_CALCULATIONBASE, CSV_META_CALCULATIONBASE, new Object[] { "" }) // TODO what is required at this place? }); writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_RIVER, CSV_META_RIVER, new Object[] { FLYSUtils.getRivername(flys) }) }); double[] kms = FLYSUtils.getKmRange(flys); writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_RANGE, CSV_META_RANGE, new Object[] { kms[0], kms[kms.length-1] }) }); writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_GAUGE, CSV_META_GAUGE, new Object[] { FLYSUtils.getGaugename(flys) }) }); FLYSUtils.WQ_MODE wq = FLYSUtils.getWQMode(flys); if (wq == FLYSUtils.WQ_MODE.QFREE || wq == FLYSUtils.WQ_MODE.QGAUGE) { double[] qs = FLYSUtils.getQs(flys); String lower = ""; String upper = ""; if (qs != null && qs.length > 0) { lower = String.valueOf(qs[0]); upper = String.valueOf(qs[qs.length-1]); } else { logger.warn("Could not determine Q range!"); } writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_Q, CSV_META_Q, new Object[] { lower, upper }) }); } else { double[] ws = FLYSUtils.getWs(flys); String lower = ""; String upper = ""; if (ws != null && ws.length > 0) { lower = String.valueOf(ws[0]); upper = String.valueOf(ws[ws.length-1]); } else { logger.warn("Could not determine W range!"); } writer.writeNext(new String[] { Resources.getMsg( meta, CSV_META_W, CSV_META_W, new Object[] { lower, upper }) }); } writer.writeNext(new String[] { "" }); } protected void writeCSVHeader( CSVWriter writer, boolean atGauge, boolean isQ ) { logger.info("WaterlevelExporter.writeCSVHeader"); if (atGauge) { writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), (isQ ? msg(CSV_Q_DESC_HEADER, DEFAULT_CSV_Q_DESC_HEADER) : msg(CSV_W_DESC_HEADER, DEFAULT_CSV_W_DESC_HEADER)), msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER), msg(CSV_GAUGE_HEADER, DEFAULT_CSV_GAUGE_HEADER) }); } else { writer.writeNext(new String[] { msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER), msg(CSV_LOCATION_HEADER, DEFAULT_CSV_LOCATION_HEADER) }); } } protected void wQKms2CSV( CSVWriter writer, WQKms wqkms, boolean atGauge, boolean isQ ) { logger.debug("WaterlevelExporter.wQKms2CSV"); 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) { writer.writeNext(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 { writer.writeNext(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 CSV took " + (float)(stopTime-startTime)/1000f + " secs."); } } /** * Generates the output in WST format. */ protected void generateWST() throws IOException { logger.info("WaterlevelExporter.generateWST"); int cols = data.get(0).length; WstWriter writer = new WstWriter(cols); writeWSTData(writer); writer.write(out); } protected void writeWSTData(WstWriter writer) { logger.debug("WaterlevelExporter.writeWSTData"); double[] result = new double[4]; for (WQKms[] tmp: data) { for (WQKms wqkms: tmp) { int size = wqkms != null ? wqkms.size() : 0; addWSTColumn(writer, wqkms); for (int i = 0; i < size; i++) { result = wqkms.get(i, result); writer.add(result); } if (wqkms instanceof WQCKms) { addWSTColumn(writer, wqkms); for (int c = 0; c < size; c++) { result = wqkms.get(c, result); writer.addCorrected(result); } } } } } /** * This method is used to register a new column at <i>writer</i>. The name / * title of the column depends on the Q or W value of <i>wqkms</i>. If a Q * was selected and the Q fits to a named main value, the title is set to * the named main value. Otherwise, the name returned by * <i>WQKms.getName()</i> is set. * * @param writer The WstWriter. * @param wqkms The new WST column. */ protected void addWSTColumn(WstWriter writer, WQKms wqkms) { if (master instanceof WINFOArtifact) { writer.addColumn(getColumnTitle((WINFOArtifact) master, wqkms)); } else { writer.addColumn(wqkms.getName()); } } /** * Returns the number formatter for kilometer values. * * @return the number formatter for kilometer values. */ protected NumberFormat getKmFormatter() { return Formatter.getWaterlevelKM(context); } /** * Returns the number formatter for W values. * * @return the number formatter for W values. */ protected NumberFormat getWFormatter() { return Formatter.getWaterlevelW(context); } /** * Returns the number formatter for Q values. * * @return the number formatter for Q values. */ protected NumberFormat getQFormatter() { return Formatter.getWaterlevelQ(context); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :