ingo@389: package de.intevation.flys.exports; ingo@389: ingo@446: import java.io.IOException; ingo@389: import java.io.OutputStream; ingo@418: import java.text.NumberFormat; ingo@389: import java.util.ArrayList; ingo@389: import java.util.List; ingo@2035: import java.util.regex.Matcher; ingo@2035: import java.util.regex.Pattern; ingo@389: ingo@389: import org.w3c.dom.Document; ingo@389: ingo@389: import org.apache.log4j.Logger; ingo@389: ingo@389: import au.com.bytecode.opencsv.CSVWriter; ingo@389: ingo@389: import de.intevation.artifacts.CallContext; ingo@389: ingo@2035: import de.intevation.flys.artifacts.WINFOArtifact; sascha@709: import de.intevation.flys.artifacts.model.CalculationResult; ingo@749: import de.intevation.flys.artifacts.model.WQCKms; ingo@389: import de.intevation.flys.artifacts.model.WQKms; sascha@706: ingo@2035: import de.intevation.flys.utils.FLYSUtils; ingo@445: import de.intevation.flys.utils.Formatter; ingo@389: ingo@389: ingo@389: /** ingo@389: * @author Ingo Weinzierl ingo@389: */ ingo@391: public class WaterlevelExporter extends AbstractExporter { ingo@389: ingo@389: /** The logger used in this exporter.*/ ingo@389: private static Logger logger = Logger.getLogger(WaterlevelExporter.class); ingo@389: ingo@389: ingo@446: public static final String FACET_WST = "wst"; ingo@446: ingo@446: ingo@416: public static final String CSV_KM_HEADER = ingo@416: "export.waterlevel.csv.header.km"; ingo@416: ingo@416: public static final String CSV_W_HEADER = ingo@416: "export.waterlevel.csv.header.w"; ingo@416: ingo@416: public static final String CSV_Q_HEADER = ingo@416: "export.waterlevel.csv.header.q"; ingo@416: ingo@2035: public static final Pattern NUMBERS_PATTERN = ingo@2035: Pattern.compile("\\D*(\\d++.\\d*)\\D*"); ingo@2035: ingo@416: public static final String DEFAULT_CSV_KM_HEADER = "Fluss-Km"; ingo@416: public static final String DEFAULT_CSV_W_HEADER = "W [NN + m]"; sascha@664: public static final String DEFAULT_CSV_Q_HEADER = "Q [m\u00b3/s]"; ingo@416: ingo@416: ingo@389: /** The storage that contains all WQKms objects for the different facets.*/ ingo@389: protected List data; ingo@389: ingo@389: ingo@389: public void init(Document request, OutputStream out, CallContext context) { ingo@389: logger.debug("WaterlevelExporter.init"); ingo@389: ingo@391: super.init(request, out, context); ingo@389: ingo@391: this.data = new ArrayList(); ingo@389: } ingo@389: ingo@389: ingo@446: @Override ingo@446: public void generate() ingo@446: throws IOException ingo@446: { ingo@446: logger.debug("WaterlevelExporter.generate"); ingo@446: ingo@446: if (facet != null && facet.equals(AbstractExporter.FACET_CSV)) { ingo@446: generateCSV(); ingo@446: } ingo@446: else if (facet != null && facet.equals(FACET_WST)) { ingo@446: generateWST(); ingo@446: } ingo@446: else { ingo@446: throw new IOException("invalid facet for exporter"); ingo@446: } ingo@446: } ingo@446: ingo@446: sascha@701: @Override sascha@701: protected void addData(Object d) { sascha@709: if (d instanceof CalculationResult) { sascha@709: d = ((CalculationResult)d).getData(); sascha@709: if (d instanceof WQKms []) { sascha@709: data.add((WQKms [])d); sascha@709: } sascha@701: } ingo@389: } ingo@389: ingo@389: ingo@2035: /** ingo@2035: * This method is used to prepare the column titles of waterlevel exports. ingo@2035: * Titles in this export include the Q value. If a Q value matches a named ingo@2035: * main value (as HQ100 or MNQ) this named main value should be used as ingo@2035: * title. This method resets the name of the wqkms object if such ingo@2035: * named main value fits to the chosen Q. ingo@2035: * ingo@2035: * @param winfo A WINFO Artifact. ingo@2035: * @param wqkms A WQKms object that should be prepared. ingo@2035: */ ingo@2038: protected String getColumnTitle(WINFOArtifact winfo, WQKms wqkms) { ingo@2035: logger.debug("WaterlevelExporter.prepareNamedValue"); ingo@2035: ingo@2035: String name = wqkms.getName(); ingo@2035: ingo@2035: logger.debug("Name of WQKms = '" + name + "'"); ingo@2035: ingo@2038: if (name.indexOf("W=") >= 0) { ingo@2038: return name; ingo@2038: } ingo@2038: ingo@2035: Matcher m = NUMBERS_PATTERN.matcher(name); ingo@2035: ingo@2035: if (m.matches()) { ingo@2035: String raw = m.group(1); ingo@2035: ingo@2035: try { ingo@2035: double v = Double.valueOf(raw); ingo@2035: ingo@2038: String nmv = FLYSUtils.getNamedMainValue(winfo, v); ingo@2035: ingo@2035: if (nmv != null && nmv.length() > 0) { ingo@2035: nmv = FLYSUtils.stripNamedMainValue(nmv); ingo@2035: logger.debug("Set named main value '" + nmv + "'"); ingo@2035: ingo@2038: return nmv; ingo@2035: } ingo@2035: } ingo@2035: catch (NumberFormatException nfe) { ingo@2035: // do nothing here ingo@2035: } ingo@2035: } ingo@2038: ingo@2038: return name; ingo@2035: } ingo@2035: ingo@2035: sascha@701: @Override ingo@391: protected void writeCSVData(CSVWriter writer) { ingo@391: logger.info("WaterlevelExporter.writeData"); ingo@389: ingo@416: writeCSVHeader(writer); ingo@416: ingo@389: for (WQKms[] tmp: data) { ingo@389: for (WQKms wqkms: tmp) { ingo@389: wQKms2CSV(writer, wqkms); ingo@389: } ingo@389: } ingo@389: } ingo@389: ingo@389: ingo@416: protected void writeCSVHeader(CSVWriter writer) { ingo@416: logger.info("WaterlevelExporter.writeCSVHeader"); ingo@416: ingo@416: writer.writeNext(new String[] { ingo@416: msg(CSV_KM_HEADER, DEFAULT_CSV_KM_HEADER), ingo@416: msg(CSV_W_HEADER, DEFAULT_CSV_W_HEADER), ingo@416: msg(CSV_Q_HEADER, DEFAULT_CSV_Q_HEADER) ingo@416: }); ingo@416: } ingo@416: ingo@416: ingo@389: protected void wQKms2CSV(CSVWriter writer, WQKms wqkms) { ingo@389: logger.debug("WaterlevelExporter.wQKms2CSV"); ingo@389: ingo@418: NumberFormat kmf = getKmFormatter(); ingo@418: NumberFormat wf = getWFormatter(); ingo@418: NumberFormat qf = getQFormatter(); ingo@418: ingo@389: int size = wqkms.size(); ingo@389: double[] result = new double[3]; ingo@389: ingo@389: for (int i = 0; i < size; i ++) { ingo@389: result = wqkms.get(i, result); ingo@389: ingo@389: writer.writeNext(new String[] { ingo@418: kmf.format(result[2]), ingo@418: wf.format(result[0]), ingo@418: qf.format(result[1]) ingo@389: }); ingo@389: } ingo@389: } ingo@418: ingo@418: ingo@418: /** ingo@446: * Generates the output in WST format. ingo@446: */ ingo@446: protected void generateWST() ingo@446: throws IOException ingo@446: { ingo@446: logger.info("WaterlevelExporter.generateWST"); ingo@446: ingo@446: int cols = data.get(0).length; ingo@446: WstWriter writer = new WstWriter(cols); ingo@446: ingo@446: writeWSTData(writer); ingo@446: ingo@446: writer.write(out); ingo@446: } ingo@446: ingo@446: ingo@446: protected void writeWSTData(WstWriter writer) { ingo@446: logger.debug("WaterlevelExporter.writeWSTData"); ingo@446: ingo@749: double[] result = new double[4]; ingo@446: ingo@446: for (WQKms[] tmp: data) { ingo@446: for (WQKms wqkms: tmp) { ingo@446: int size = wqkms != null ? wqkms.size() : 0; ingo@446: ingo@450: addWSTColumn(writer, wqkms); ingo@447: ingo@446: for (int i = 0; i < size; i++) { ingo@446: result = wqkms.get(i, result); ingo@446: ingo@446: writer.add(result); ingo@446: } ingo@749: ingo@749: if (wqkms instanceof WQCKms) { ingo@749: addWSTColumn(writer, wqkms); ingo@749: ingo@749: for (int c = 0; c < size; c++) { ingo@749: result = wqkms.get(c, result); ingo@749: ingo@749: writer.addCorrected(result); ingo@749: } ingo@749: } ingo@446: } ingo@446: } ingo@446: } ingo@446: ingo@446: ingo@2038: /** ingo@2038: * This method is used to register a new column at writer. The name / ingo@2038: * title of the column depends on the Q or W value of wqkms. If a Q ingo@2038: * was selected and the Q fits to a named main value, the title is set to ingo@2038: * the named main value. Otherwise, the name returned by ingo@2038: * WQKms.getName() is set. ingo@2038: * ingo@2038: * @param writer The WstWriter. ingo@2038: * @param wqkms The new WST column. ingo@2038: */ ingo@450: protected void addWSTColumn(WstWriter writer, WQKms wqkms) { ingo@2038: if (master instanceof WINFOArtifact) { ingo@2038: writer.addColumn(getColumnTitle((WINFOArtifact) master, wqkms)); ingo@2038: } ingo@2038: else { ingo@2038: writer.addColumn(wqkms.getName()); ingo@2038: } ingo@450: } ingo@450: ingo@450: ingo@446: /** ingo@418: * Returns the number formatter for kilometer values. ingo@418: * ingo@418: * @return the number formatter for kilometer values. ingo@418: */ ingo@418: protected NumberFormat getKmFormatter() { ingo@445: return Formatter.getWaterlevelKM(context); ingo@418: } ingo@418: ingo@418: ingo@418: /** ingo@418: * Returns the number formatter for W values. ingo@418: * ingo@418: * @return the number formatter for W values. ingo@418: */ ingo@418: protected NumberFormat getWFormatter() { ingo@445: return Formatter.getWaterlevelW(context); ingo@418: } ingo@418: ingo@418: ingo@418: /** ingo@418: * Returns the number formatter for Q values. ingo@418: * ingo@418: * @return the number formatter for Q values. ingo@418: */ ingo@418: protected NumberFormat getQFormatter() { ingo@445: return Formatter.getWaterlevelQ(context); ingo@418: } ingo@389: } ingo@389: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :