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@4232: public class HistoricalDischargeCurveGenerator extends TimeseriesChartGenerator
ingo@4232: implements FacetTypes {
ingo@2249:
ingo@4232: private static Logger logger = Logger
ingo@4232: .getLogger(HistoricalDischargeCurveGenerator.class);
ingo@2249:
ingo@4232: public static final String I18N_CHART_TITLE = "chart.historical.discharge.title";
ingo@2249:
ingo@4232: public static final String I18N_CHART_SUBTITLE = "chart.historical.discharge.subtitle";
ingo@2249:
ingo@4232: public static final String I18N_XAXIS_LABEL = "chart.historical.discharge.xaxis.label";
ingo@4232:
ingo@4232: public static final String I18N_YAXIS_LABEL = "chart.historical.discharge.yaxis.label";
ingo@4232:
ingo@4232: public static final String I18N_YAXIS_SECOND_LABEL = "chart.historical.discharge.yaxis.second.label";
ingo@2249:
ingo@2215: public static enum YAXIS {
ingo@4232: W(0), Q(1);
ingo@4232:
ingo@2215: protected int idx;
ingo@4232:
ingo@2215: private YAXIS(int c) {
ingo@2215: idx = c;
ingo@2215: }
ingo@2215: }
ingo@2215:
ingo@2215: @Override
ingo@2215: protected YAxisWalker getYAxisWalker() {
ingo@2215: return new YAxisWalker() {
ingo@4232:
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: @Override
ingo@2215: protected String getDefaultChartTitle() {
ingo@2249: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE);
ingo@2249: }
ingo@2249:
ingo@2249: @Override
ingo@2249: protected String getDefaultChartSubtitle() {
ingo@4232: FLYSArtifact flys = (FLYSArtifact) master;
ingo@4232: Timerange evalTime = new HistoricalDischargeAccess(flys)
ingo@4232: .getEvaluationTimerange();
ingo@4152:
ingo@4232: Object[] args = new Object[] { FLYSUtils.getReferenceGaugeName(flys),
ingo@4232: evalTime.getStart(), evalTime.getEnd() };
ingo@2249:
ingo@2249: return msg(I18N_CHART_SUBTITLE, "", args);
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:
christian@3409: @Override
ingo@4232: public void doOut(ArtifactAndFacet artifactFacet, Document theme,
ingo@4232: boolean visible) {
ingo@2215: String name = artifactFacet.getFacetName();
ingo@2215: logger.debug("HistoricalDischargeCurveGenerator.doOut: " + name);
ingo@4232: logger.debug("Theme description is: "
ingo@4232: + artifactFacet.getFacetDescription());
ingo@2215:
ingo@2215: if (name.equals(HISTORICAL_DISCHARGE_Q)) {
ingo@4232: doHistoricalDischargeOutQ(
ingo@2215: (FLYSArtifact) artifactFacet.getArtifact(),
ingo@2215: artifactFacet.getData(context),
ingo@4232: artifactFacet.getFacetDescription(), theme, visible);
ingo@2215: }
ingo@4232: else if (name.equals(HISTORICAL_DISCHARGE_W)) {
ingo@4232: doHistoricalDischargeOutW(
ingo@2311: (FLYSArtifact) artifactFacet.getArtifact(),
ingo@2311: artifactFacet.getData(context),
ingo@4232: artifactFacet.getFacetDescription(), theme, visible);
ingo@4232: }
ingo@4232: else if (name.equals(HISTORICAL_DISCHARGE_Q_DIFF)) {
ingo@4232: doHistoricalDischargeDifferenceOutQ(
ingo@4232: (FLYSArtifact) artifactFacet.getArtifact(),
ingo@4232: artifactFacet.getData(context),
ingo@4232: artifactFacet.getFacetDescription(), theme, visible);
ingo@4232: }
ingo@4232: else if (name.equals(HISTORICAL_DISCHARGE_W_DIFF)) {
ingo@4232: doHistoricalDischargeDifferenceOutW(
ingo@4232: (FLYSArtifact) artifactFacet.getArtifact(),
ingo@4232: artifactFacet.getData(context),
ingo@4232: artifactFacet.getFacetDescription(), theme, visible);
ingo@2311: }
raimund@2633: else if (FacetTypes.IS.MANUALPOINTS(name)) {
ingo@4232: doPoints(artifactFacet.getData(context), artifactFacet, theme,
ingo@4232: visible, YAXIS.Q.idx);
raimund@2633: }
ingo@2215: else {
ingo@4232: logger.warn("doOut(): unknown facet name: " + name);
ingo@4232: return;
ingo@2215: }
ingo@2215: }
ingo@2215:
ingo@4232: protected void doHistoricalDischargeOutQ(FLYSArtifact artifact,
ingo@4232: Object data, String desc, Document theme, boolean visible) {
ingo@2215: logger.debug("doHistoricalDischargeOut(): description = " + desc);
ingo@2240:
ingo@2240: WQTimerange wqt = (WQTimerange) data;
ingo@2240:
ingo@4232: TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(),
ingo@4232: wqt.getQs(), theme, desc);
ingo@2311:
ingo@4232: addAxisDataset(tsc, YAXIS.Q.idx, visible);
ingo@2311: }
ingo@2311:
ingo@4232: protected void doHistoricalDischargeOutW(FLYSArtifact artifact,
ingo@4232: Object data, String desc, Document theme, boolean visible) {
ingo@4232: logger.debug("doHistoricalDischargeOut(): description = " + desc);
ingo@2311:
ingo@4232: WQTimerange wqt = (WQTimerange) data;
ingo@4232:
ingo@4232: TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(),
ingo@4232: wqt.getWs(), theme, desc);
ingo@4232:
ingo@4232: addAxisDataset(tsc, YAXIS.W.idx, visible);
ingo@4232: }
ingo@4232:
ingo@4232: protected void doHistoricalDischargeDifferenceOutQ(FLYSArtifact artifact,
ingo@4232: Object data, String desc, Document theme, boolean visible) {
ingo@2311: logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc);
ingo@2311:
ingo@2311: HistoricalWQTimerange wqt = (HistoricalWQTimerange) data;
ingo@2311:
ingo@4232: TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(),
ingo@4232: wqt.getDiffs(), theme, desc);
ingo@2240:
ingo@4232: addAxisDataset(tsc, YAXIS.Q.idx, visible);
ingo@2240: }
ingo@2240:
ingo@4232: protected void doHistoricalDischargeDifferenceOutW(FLYSArtifact artifact,
ingo@4232: Object data, String desc, Document theme, boolean visible) {
ingo@4232: logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc);
ingo@4232:
ingo@4232: HistoricalWQTimerange wqt = (HistoricalWQTimerange) data;
ingo@4232:
ingo@4232: TimeSeriesCollection tsc = newTimeSeriesCollection(wqt.getTimeranges(),
ingo@4232: wqt.getDiffs(), theme, desc);
ingo@4232:
ingo@4232: addAxisDataset(tsc, YAXIS.W.idx, visible);
ingo@4232: }
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@4232: Timerange[] timeranges, double[] values, Document theme, String desc) {
ingo@2240: logger.debug("Create new TimeSeriesCollection for: " + desc);
ingo@2240:
ingo@2240: TimeSeriesCollection tsc = new TimeSeriesCollection();
ingo@4232: 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: * Creates an array that consists of two Minute periods [start, end].
teichmann@4736: *
ingo@4232: * @param timerange
ingo@4232: * Supports start and end time.
teichmann@4736: *
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@4232: Date end = new Date(timerange.getEnd() - 1000 * 60 * 60 * 24);
ingo@2240:
ingo@4232: return new RegularTimePeriod[] { new Day(start), new Day(end) };
ingo@2215: }
ingo@2215: }
ingo@2215: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :