ingo@2215: package de.intevation.flys.exports; ingo@2215: ingo@4176: import java.util.Date; ingo@4176: ingo@4176: import org.apache.log4j.Logger; ingo@4176: import org.jfree.chart.plot.XYPlot; ingo@4176: import org.jfree.data.general.SeriesException; ingo@4176: import org.jfree.data.time.Day; ingo@4176: import org.jfree.data.time.RegularTimePeriod; ingo@4176: import org.jfree.data.time.TimeSeries; ingo@4176: import org.jfree.data.time.TimeSeriesCollection; ingo@4176: import org.w3c.dom.Document; ingo@4176: ingo@2215: import de.intevation.artifactdatabase.state.ArtifactAndFacet; ingo@2215: import de.intevation.flys.artifacts.FLYSArtifact; ingo@4152: import de.intevation.flys.artifacts.access.HistoricalDischargeAccess; ingo@2215: import de.intevation.flys.artifacts.model.FacetTypes; ingo@2311: import de.intevation.flys.artifacts.model.HistoricalWQTimerange; ingo@2240: import de.intevation.flys.artifacts.model.Timerange; ingo@2240: import de.intevation.flys.artifacts.model.WQTimerange; ingo@2321: import de.intevation.flys.jfree.StyledTimeSeries; ingo@2249: import de.intevation.flys.utils.FLYSUtils; ingo@2215: ingo@2215: ingo@2215: /** ingo@2215: * @author Ingo Weinzierl ingo@2215: */ ingo@2215: public class HistoricalDischargeCurveGenerator ingo@2233: extends TimeseriesChartGenerator ingo@2215: implements FacetTypes ingo@2215: { ingo@2215: private static Logger logger = ingo@2215: Logger.getLogger(HistoricalDischargeCurveGenerator.class); ingo@2215: ingo@2215: ingo@2249: public static final String I18N_CHART_TITLE = ingo@2249: "chart.historical.discharge.title"; ingo@2249: ingo@2249: public static final String I18N_CHART_SUBTITLE = ingo@2249: "chart.historical.discharge.subtitle"; ingo@2249: ingo@2249: public static final String I18N_XAXIS_LABEL = ingo@2249: "chart.historical.discharge.xaxis.label"; ingo@2249: ingo@2249: public static final String I18N_YAXIS_LABEL = ingo@2249: "chart.historical.discharge.yaxis.label"; ingo@2249: ingo@2249: public static final String I18N_YAXIS_SECOND_LABEL = ingo@2249: "chart.historical.discharge.yaxis.second.label"; ingo@2249: ingo@2249: ingo@2215: public static enum YAXIS { ingo@2215: Q(0); ingo@2215: protected int idx; ingo@2215: private YAXIS(int c) { ingo@2215: idx = c; ingo@2215: } ingo@2215: } ingo@2215: ingo@2215: ingo@2215: @Override ingo@2215: protected YAxisWalker getYAxisWalker() { ingo@2215: return new YAxisWalker() { ingo@2215: @Override ingo@2215: public int length() { ingo@2215: return YAXIS.values().length; ingo@2215: } ingo@2215: ingo@2215: @Override ingo@2215: public String getId(int idx) { ingo@2215: YAXIS[] yaxes = YAXIS.values(); ingo@2215: return yaxes[idx].toString(); ingo@2215: } ingo@2215: }; ingo@2215: } ingo@2215: ingo@2215: ingo@2215: @Override ingo@2215: protected String getDefaultChartTitle() { ingo@2249: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); ingo@2249: } ingo@2249: ingo@2249: ingo@2249: @Override ingo@2249: protected String getDefaultChartSubtitle() { ingo@4152: FLYSArtifact flys = (FLYSArtifact) master; ingo@4152: Timerange evalTime = ingo@4152: new HistoricalDischargeAccess(flys).getEvaluationTimerange(); ingo@4152: ingo@4152: Object[] args = new Object[] { ingo@4152: FLYSUtils.getReferenceGaugeName(flys), ingo@4152: evalTime.getStart(), ingo@4152: evalTime.getEnd() ingo@2249: }; ingo@2249: ingo@2249: return msg(I18N_CHART_SUBTITLE, "", args); ingo@2215: } ingo@2215: ingo@2215: ingo@2215: @Override ingo@2215: protected String getDefaultXAxisLabel() { ingo@2249: return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); ingo@2215: } ingo@2215: ingo@2215: @Override ingo@2215: protected String getDefaultYAxisLabel(int pos) { ingo@2249: if (pos == 0) { ingo@2249: return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); ingo@2249: } ingo@2249: else if (pos == 1) { ingo@2249: return msg(I18N_YAXIS_SECOND_LABEL, I18N_YAXIS_SECOND_LABEL); ingo@2249: } ingo@2249: else { ingo@2249: return "NO TITLE FOR Y AXIS: " + pos; ingo@2249: } ingo@2215: } ingo@2215: ingo@4176: @Override ingo@4176: protected void adjustPlot(XYPlot plot) { ingo@4176: super.adjustPlot(plot); ingo@4176: plot.setRangeZeroBaselineVisible(true); ingo@4176: } ingo@4176: ingo@2215: christian@3409: @Override ingo@2215: public void doOut( ingo@2215: ArtifactAndFacet artifactFacet, ingo@2215: Document theme, ingo@2215: boolean visible ingo@2215: ) { ingo@2215: String name = artifactFacet.getFacetName(); ingo@2215: logger.debug("HistoricalDischargeCurveGenerator.doOut: " + name); ingo@2325: logger.debug("Theme description is: " + artifactFacet.getFacetDescription()); ingo@2215: ingo@2215: ingo@2215: if (name.equals(HISTORICAL_DISCHARGE_Q)) { ingo@2215: doHistoricalDischargeOut( ingo@2215: (FLYSArtifact) artifactFacet.getArtifact(), ingo@2215: artifactFacet.getData(context), ingo@2215: artifactFacet.getFacetDescription(), ingo@2215: theme, ingo@2215: visible); ingo@2215: } ingo@2311: else if (name.equals(HISTORICAL_DISCHARGE_Q_DIFF)) { ingo@2311: doHistoricalDischargeDifferenceOut( ingo@2311: (FLYSArtifact) artifactFacet.getArtifact(), ingo@2311: artifactFacet.getData(context), ingo@2311: artifactFacet.getFacetDescription(), ingo@2311: theme, ingo@2311: visible); ingo@2311: } raimund@2633: else if (FacetTypes.IS.MANUALPOINTS(name)) { raimund@2633: doPoints (artifactFacet.getData(context), raimund@2633: artifactFacet, raimund@2633: theme, visible, YAXIS.Q.idx); raimund@2633: } ingo@2311: // TODO ADD THE CASE FOR DISPLAYING W VALUES ingo@2215: else { ingo@2215: logger.warn("doOut(): unknown facet name: " + name); ingo@2215: return; ingo@2215: } ingo@2215: } ingo@2215: ingo@2215: ingo@2215: protected void doHistoricalDischargeOut( ingo@2215: FLYSArtifact artifact, ingo@2215: Object data, ingo@2215: String desc, ingo@2215: Document theme, ingo@2215: boolean visible) ingo@2215: { ingo@2215: logger.debug("doHistoricalDischargeOut(): description = " + desc); ingo@2240: ingo@2240: WQTimerange wqt = (WQTimerange) data; ingo@2240: ingo@2311: TimeSeriesCollection tsc = newTimeSeriesCollection( ingo@2311: wqt.getTimeranges(), ingo@2311: wqt.getQs(), ingo@2321: theme, ingo@2311: desc); ingo@2311: ingo@2311: addAxisDataset(tsc, 0, visible); ingo@2311: } ingo@2311: ingo@2311: ingo@2311: protected void doHistoricalDischargeDifferenceOut( ingo@2311: FLYSArtifact artifact, ingo@2311: Object data, ingo@2311: String desc, ingo@2311: Document theme, ingo@2311: boolean visible ingo@2311: ) { ingo@2311: logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); ingo@2311: ingo@2311: HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; ingo@2311: ingo@2311: TimeSeriesCollection tsc = newTimeSeriesCollection( ingo@2311: wqt.getTimeranges(), ingo@2311: wqt.getDiffs(), ingo@2321: theme, ingo@2311: desc); ingo@2240: ingo@2240: addAxisDataset(tsc, 0, visible); ingo@2240: } ingo@2240: ingo@2240: ingo@2240: /** ingo@2240: * Creates a new TimeSeriesCollection with a single TimeSeries. The ingo@2240: * TimeSeries will consist of two RegularTimePeriods for each W/Q value ingo@2240: * provided by wqt. This has the effect, that the line in the chart ingo@2240: * looks like a "step chart". ingo@2240: */ ingo@2240: protected TimeSeriesCollection newTimeSeriesCollection( ingo@2311: Timerange[] timeranges, ingo@2311: double[] values, ingo@2321: Document theme, ingo@2240: String desc ingo@2240: ) { ingo@2240: logger.debug("Create new TimeSeriesCollection for: " + desc); ingo@2240: ingo@2240: TimeSeriesCollection tsc = new TimeSeriesCollection(); ingo@2321: TimeSeries series = new StyledTimeSeries(desc, theme); ingo@2240: ingo@2311: for (int i = 0, n = timeranges.length; i < n; i++) { ingo@2311: RegularTimePeriod[] rtp = newRegularTimePeriod(timeranges[i]); ingo@2240: ingo@2240: try { ingo@2311: if (Double.isNaN(values[i])) { ingo@2243: logger.warn("Skip TimePeriod because value is NaN."); ingo@2243: continue; ingo@2243: } ingo@2243: ingo@2311: series.add(rtp[0], values[i]); ingo@2311: series.add(rtp[1], values[i]); ingo@2243: ingo@2243: if (logger.isDebugEnabled()) { ingo@2243: logger.debug("added Item to TimeSeries:"); ingo@2243: logger.debug(" TimePeriod: " + rtp[0] + " - " + rtp[1]); ingo@2311: logger.debug(" Value: " + values[i]); ingo@2243: } ingo@2240: } ingo@2240: catch (SeriesException se) { ingo@2240: logger.warn("Error while adding TimePeriod: " + se); ingo@2240: } ingo@2240: } ingo@2240: ingo@2240: tsc.addSeries(series); ingo@2240: ingo@2240: return tsc; ingo@2240: } ingo@2240: ingo@2240: ingo@2240: /** ingo@2240: * Creates an array that consists of two Minute periods [start, end]. ingo@2240: * ingo@2240: * @param timerange Supports start and end time. ingo@2240: * ingo@2240: * @return an array with two Minute periods [start, end]. ingo@2240: */ ingo@2240: protected RegularTimePeriod[] newRegularTimePeriod(Timerange timerange) { ingo@2240: Date start = new Date(timerange.getStart()); ingo@2243: Date end = new Date(timerange.getEnd() - 1000 * 60 * 60 * 24); ingo@2240: ingo@2240: return new RegularTimePeriod[] { ingo@2243: new Day(start), ingo@2243: new Day(end) ingo@2240: }; ingo@2215: } ingo@2215: } ingo@2215: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :