teichmann@5831: package org.dive4elements.river.exports.fixings; raimund@3131: teichmann@5831: import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.river.artifacts.FLYSArtifact; teichmann@5831: import org.dive4elements.river.artifacts.access.FixAnalysisAccess; teichmann@5831: import org.dive4elements.river.artifacts.model.DateRange; teichmann@5831: import org.dive4elements.river.artifacts.model.FacetTypes; teichmann@5831: import org.dive4elements.river.artifacts.model.QWDDateRange; teichmann@5831: import org.dive4elements.river.artifacts.model.fixings.QWD; teichmann@5831: import org.dive4elements.river.artifacts.resources.Resources; teichmann@5831: import org.dive4elements.river.exports.TimeseriesChartGenerator; teichmann@5831: import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; teichmann@5831: import org.dive4elements.river.jfree.FLYSAnnotation; teichmann@5831: import org.dive4elements.river.jfree.StyledDomainMarker; teichmann@5831: import org.dive4elements.river.jfree.StyledTimeSeries; teichmann@5831: import org.dive4elements.river.jfree.StyledValueMarker; teichmann@5831: import org.dive4elements.river.utils.ThemeUtil; christian@3988: christian@3746: import java.io.OutputStream; christian@3908: import java.text.NumberFormat; christian@3746: import java.util.ArrayList; christian@3746: import java.util.HashMap; christian@3746: import java.util.List; christian@3908: import java.util.Locale; christian@3746: import java.util.Map; christian@3746: christian@3746: import org.apache.log4j.Logger; christian@3746: import org.jfree.chart.annotations.XYTextAnnotation; christian@3746: import org.jfree.data.time.Day; christian@3746: import org.jfree.data.time.RegularTimePeriod; christian@3746: import org.jfree.data.time.TimeSeries; christian@3746: import org.jfree.data.time.TimeSeriesCollection; christian@3746: import org.w3c.dom.Document; christian@3746: christian@3251: raimund@3131: /** christian@3251: * Generator for Delta W(t) charts. raimund@3131: * @author Raimund Renkert raimund@3131: */ raimund@3131: public class FixDeltaWtGenerator raimund@3131: extends TimeseriesChartGenerator raimund@3131: implements FacetTypes raimund@3131: { felix@3467: /** Private logger. */ raimund@3131: private static Logger logger = christian@3746: Logger.getLogger(FixDeltaWtGenerator.class); raimund@3131: raimund@3131: public static final String I18N_CHART_TITLE = christian@3746: "chart.fix.deltawt.title"; raimund@3131: raimund@3131: public static final String I18N_CHART_SUBTITLE = christian@3746: "chart.fix.deltawt.subtitle"; raimund@3131: raimund@3131: public static final String I18N_XAXIS_LABEL = christian@3746: "chart.fix.deltawt.xaxis.label"; raimund@3131: raimund@3131: public static final String I18N_YAXIS_LABEL = christian@3746: "chart.fix.deltawt.yaxis.label"; raimund@3131: raimund@3131: public static final String I18N_YAXIS_SECOND_LABEL = christian@3746: "chart.fix.deltawt.yaxis.second.label"; raimund@3131: raimund@3131: raimund@3131: public static enum YAXIS { raimund@3131: dW(0); raimund@3131: protected int idx; raimund@3131: private YAXIS(int c) { raimund@3131: idx = c; raimund@3131: } raimund@3131: } sascha@3280: sascha@3280: christian@3279: private FLYSArtifact artifact = null; raimund@3131: raimund@3131: raimund@3131: @Override raimund@3131: protected YAxisWalker getYAxisWalker() { raimund@3131: return new YAxisWalker() { raimund@3131: @Override raimund@3131: public int length() { raimund@3131: return YAXIS.values().length; raimund@3131: } raimund@3131: raimund@3131: @Override raimund@3131: public String getId(int idx) { raimund@3131: YAXIS[] yaxes = YAXIS.values(); raimund@3131: return yaxes[idx].toString(); raimund@3131: } raimund@3131: }; raimund@3131: } raimund@3131: raimund@3131: raimund@3131: @Override raimund@3131: protected String getDefaultChartTitle() { raimund@3131: return msg(I18N_CHART_TITLE, I18N_CHART_TITLE); raimund@3131: } raimund@3131: raimund@3131: raimund@3131: @Override christian@3406: protected String getChartTitle() { christian@3406: return Resources.format( christian@3406: context.getMeta(), christian@3406: I18N_CHART_TITLE, christian@3406: "", sascha@3727: FixChartGenerator christian@3746: .getCurrentKmFromRequest(request).doubleValue()); christian@3406: } christian@3406: christian@3406: christian@3406: @Override raimund@3131: protected String getDefaultChartSubtitle() { rrenkert@4866: FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); christian@3409: DateRange dateRange = access.getDateRange(); christian@3409: DateRange refRange = access.getReferencePeriod(); christian@3279: return Resources.format( sascha@3280: context.getMeta(), sascha@3280: I18N_CHART_SUBTITLE, sascha@3280: "", christian@3279: access.getRiver(), christian@3409: dateRange.getFrom(), christian@3409: dateRange.getTo(), christian@3409: refRange.getFrom(), christian@3409: refRange.getTo()); raimund@3131: } raimund@3131: raimund@3131: raimund@3131: @Override raimund@3131: protected String getDefaultXAxisLabel() { raimund@3131: return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL); raimund@3131: } raimund@3131: raimund@3131: @Override raimund@3131: protected String getDefaultYAxisLabel(int pos) { raimund@3131: if (pos == 0) { raimund@3131: return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL); raimund@3131: } raimund@3131: else if (pos == 1) { raimund@3131: return msg(I18N_YAXIS_SECOND_LABEL, I18N_YAXIS_SECOND_LABEL); raimund@3131: } raimund@3131: else { raimund@3131: return "NO TITLE FOR Y AXIS: " + pos; raimund@3131: } raimund@3131: } raimund@3131: raimund@3131: christian@3251: @Override raimund@3131: public void doOut( christian@3746: ArtifactAndFacet artifactFacet, christian@3746: Document theme, christian@3746: boolean visible christian@3746: ) { raimund@3131: String name = artifactFacet.getFacetName(); raimund@3131: logger.debug("FixDeltaWtGenerator.doOut: " + name); raimund@3131: logger.debug("Theme description is: " + artifactFacet.getFacetDescription()); sascha@3280: christian@3279: this.artifact = (FLYSArtifact)artifactFacet.getArtifact(); raimund@3131: raimund@3131: if (name.contains(FIX_SECTOR_AVERAGE_DWT)) { raimund@3131: doSectorAverageOut( christian@3746: (FLYSArtifact) artifactFacet.getArtifact(), christian@3746: artifactFacet.getData(context), christian@3746: artifactFacet.getFacetDescription(), christian@3746: theme, christian@3746: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_REFERENCE_EVENTS_DWT)) { raimund@3131: doReferenceEventsOut( christian@3746: (FLYSArtifact) artifactFacet.getArtifact(), christian@3746: artifactFacet.getData(context), christian@3746: artifactFacet.getFacetDescription(), christian@3746: theme, christian@3746: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_ANALYSIS_EVENTS_DWT)) { raimund@3131: doAnalysisEventsOut( christian@3746: (FLYSArtifact) artifactFacet.getArtifact(), christian@3746: artifactFacet.getData(context), christian@3746: artifactFacet.getFacetDescription(), christian@3746: theme, christian@3746: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_DEVIATION_DWT)) { raimund@3131: doDeviationOut( christian@3746: (FLYSArtifact) artifactFacet.getArtifact(), christian@3746: artifactFacet.getData(context), christian@3746: artifactFacet.getFacetDescription(), christian@3746: theme, christian@3746: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_ANALYSIS_PERIODS_DWT)) { raimund@3131: doAnalysisPeriodsOut( christian@3746: (FLYSArtifact) artifactFacet.getArtifact(), christian@3746: artifactFacet.getData(context), christian@3746: artifactFacet.getFacetDescription(), christian@3746: theme, christian@3746: visible); raimund@3131: } christian@3907: else if (name.equals(FIX_REFERENCE_PERIOD_DWT)) { christian@3907: doReferencePeriodsOut( christian@3907: (FLYSArtifact) artifactFacet.getArtifact(), christian@3907: artifactFacet.getData(context), christian@3907: artifactFacet.getFacetDescription(), christian@3907: theme, christian@3907: visible); christian@3907: } christian@3770: else if (FacetTypes.IS.MANUALPOINTS(name)) { christian@3770: doPoints (artifactFacet.getData(context), christian@3770: artifactFacet, christian@3770: theme, visible, YAXIS.dW.idx); christian@3770: } raimund@3131: else { christian@3746: logger.warn("doOut(): unknown facet name: " + name); christian@3746: return; raimund@3131: } raimund@3131: } raimund@3131: raimund@3131: christian@3907: protected void doReferencePeriodsOut( christian@3907: FLYSArtifact artifact, christian@3907: Object data, christian@3907: String desc, christian@3907: Document theme, christian@3907: boolean visible) christian@3907: { christian@3907: logger.debug("doReferencePeriodsOut()"); christian@3907: christian@3988: if (visible) { rrenkert@4866: FixAnalysisAccess access = new FixAnalysisAccess(artifact, context); christian@3988: DateRange refRange = access.getReferencePeriod(); christian@3907: christian@3988: RegularTimePeriod start = new Day(refRange.getFrom()); christian@3988: RegularTimePeriod end = new Day(refRange.getTo()); christian@3988: StyledDomainMarker marker = new StyledDomainMarker( christian@3988: start.getMiddleMillisecond(), christian@3988: end.getMiddleMillisecond(), christian@3988: theme); christian@3988: domainMarker.add(marker); christian@3988: } christian@3907: } christian@3907: christian@3907: raimund@3131: protected void doSectorAverageOut( christian@3746: FLYSArtifact artifact, christian@3746: Object data, christian@3746: String desc, christian@3746: Document theme, christian@3746: boolean visible) raimund@3131: { raimund@3131: logger.debug("doSectorAverageOut(): description = " + desc); raimund@3131: felix@3467: QWDDateRange qwd = (QWDDateRange) data; raimund@3131: TimeSeriesCollection tsc = new TimeSeriesCollection(); raimund@3131: TimeSeries series = new StyledTimeSeries(desc, theme); raimund@3131: felix@3467: if (qwd == null || qwd.qwd == null || qwd.dateRange == null) { raimund@3131: return; raimund@3131: } felix@3467: RegularTimePeriod rtp = new Day(qwd.qwd.getDate()); felix@3467: double value = qwd.qwd.getDeltaW(); raimund@3611: felix@3467: // Draw a line spanning the analysis time. raimund@3131: series.add(rtp, value); felix@3467: rtp = new Day(qwd.dateRange.getFrom()); raimund@3611: series.addOrUpdate(rtp, value); felix@3467: rtp = new Day(qwd.dateRange.getTo()); raimund@3611: series.addOrUpdate(rtp, value); felix@3467: raimund@3131: tsc.addSeries(series); raimund@3131: raimund@3131: addAxisDataset(tsc, 0, visible); christian@3746: christian@3746: if (visible && ThemeUtil.parseShowLineLabel(theme)) { christian@3746: List textAnnos = new ArrayList(); christian@3746: XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( christian@3746: "\u0394 W(t) [cm] " + (float)Math.round(qwd.qwd.getDeltaW() * 10000) / 10000, christian@3746: tsc.getXValue(0, 0), christian@3746: qwd.qwd.getDeltaW()); christian@3746: textAnnos.add(anno); christian@3746: christian@3746: FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme); christian@3746: flysAnno.setTextAnnotations(textAnnos); christian@3746: addAnnotations(flysAnno); christian@3746: } raimund@3131: } raimund@3131: raimund@3131: raimund@3131: protected void doAnalysisEventsOut( christian@3746: FLYSArtifact artifact, christian@3746: Object data, christian@3746: String desc, christian@3746: Document theme, christian@3746: boolean visible christian@3746: ) { raimund@3131: logger.debug("doAnalysisEventsOut: desc = " + desc); raimund@3131: raimund@3610: QWD qwd = (QWD) data; raimund@3610: doQWDEventsOut(qwd, desc, theme, visible); christian@3438: } christian@3438: christian@3438: raimund@3610: protected void doQWDEventsOut(QWD qwd, String desc, Document theme, boolean visible) christian@3438: { raimund@3131: TimeSeriesCollection tsc = new TimeSeriesCollection(); raimund@3134: raimund@3134: TimeSeries series = new StyledTimeSeries(desc, theme); raimund@3134: TimeSeries interpol = new StyledTimeSeries(desc + "interpol", theme); raimund@3131: raimund@3610: if (qwd == null) { raimund@3610: logger.debug("doQWDEventsOut: qwd == null"); christian@3212: return; christian@3212: } christian@3212: christian@3212: Map annoIdxMap = new HashMap(); christian@3212: felix@3237: int idxInterpol = 0; felix@3237: int idxRegular = 0; raimund@3610: RegularTimePeriod rtp = new Day(qwd.getDate()); raimund@3610: double value = qwd.getDeltaW(); raimund@3610: boolean interpolate = qwd.getInterpolated(); raimund@3610: if (interpolate) { raimund@3610: if(interpol.addOrUpdate(rtp, value) == null) { raimund@3610: annoIdxMap.put( raimund@3610: 0, raimund@3610: new int[]{1, idxInterpol}); raimund@3610: idxInterpol++; raimund@3134: } raimund@3131: } raimund@3610: else { raimund@3610: if(series.addOrUpdate(rtp, value) == null) { raimund@3610: annoIdxMap.put( raimund@3610: 0, raimund@3610: new int[]{0, idxRegular}); raimund@3610: idxRegular++; raimund@3610: } raimund@3610: } raimund@3610: raimund@3131: tsc.addSeries(series); raimund@3134: tsc.addSeries(interpol); raimund@3131: addAxisDataset(tsc, 0, visible); raimund@3134: addAttribute(desc + "interpol", "interpolate"); raimund@3168: addAttribute(desc, "outline"); christian@3212: raimund@3610: doQWDTextAnnotations(annoIdxMap, tsc, qwd, theme, visible); raimund@3131: } raimund@3131: raimund@3131: christian@3438: /** christian@3438: * @param annoIdxMap map of index in qwds to series/data item indices in tsc. christian@3438: */ christian@3438: protected void doQWDTextAnnotations(Map annoIdxMap, raimund@3610: TimeSeriesCollection tsc, QWD qwd, Document theme, christian@3438: boolean visible) { christian@3438: logger.debug("doQWDTextAnnotation()"); christian@3438: christian@3438: if (!visible || !ThemeUtil.parseShowPointLabel(theme)) { christian@3438: logger.debug("doQWDTextAnnotation: annotation not visible"); christian@3438: return; christian@3438: } christian@3438: christian@3908: Locale locale = Resources.getLocale(context.getMeta()); christian@3908: NumberFormat nf = NumberFormat.getInstance(locale); christian@3908: christian@3438: List textAnnos = new ArrayList(); christian@3438: teichmann@4050: for (int[] idxs: annoIdxMap.values()) { teichmann@4050: christian@3438: double x = tsc.getXValue(idxs[0], idxs[1]); christian@3908: christian@3438: XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( christian@3908: nf.format(qwd.getQ()) + " m\u00B3/s", christian@3746: x, christian@3746: qwd.getDeltaW()); christian@3438: textAnnos.add(anno); christian@3438: } christian@3438: christian@3438: FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme); christian@3438: flysAnno.setTextAnnotations(textAnnos); christian@3438: addAnnotations(flysAnno); christian@3438: } christian@3438: christian@3438: christian@3438: protected void doReferenceEventsOut( christian@3746: FLYSArtifact artifact, christian@3746: Object data, christian@3746: String desc, christian@3746: Document theme, christian@3746: boolean visible christian@3746: ) { christian@3438: logger.debug("doReferenceEventsOut: desc = " + desc); christian@3438: raimund@3610: QWD qwd = (QWD) data; raimund@3610: doQWDEventsOut(qwd, desc, theme, visible); christian@3438: } christian@3438: christian@3438: raimund@3131: protected void doDeviationOut( christian@3746: FLYSArtifact artifact, christian@3746: Object data, christian@3746: String desc, christian@3746: Document theme, christian@3746: boolean visible christian@3746: ) { raimund@3131: logger.debug("doDeviationOut: desc = " + desc); raimund@3131: raimund@3131: if (data == null || !visible) { raimund@3131: logger.debug("no standard deviation"); raimund@3131: return; raimund@3131: } raimund@3131: double[] value = (double[]) data; christian@3254: StyledDomainMarker lower = new StyledDomainMarker((value[0] * -1), 0, theme); christian@3254: StyledDomainMarker upper = new StyledDomainMarker(0, value[0], theme); raimund@3131: raimund@3131: valueMarker.add(lower); raimund@3131: valueMarker.add(upper); raimund@3131: } raimund@3131: raimund@3131: raimund@3131: protected void doAnalysisPeriodsOut( christian@3746: FLYSArtifact artifact, christian@3746: Object data, christian@3746: String desc, christian@3746: Document theme, christian@3907: boolean visible) christian@3907: { raimund@3131: DateRange[] ranges = (DateRange[]) data; raimund@3131: if (ranges == null || !visible) { raimund@3131: return; raimund@3131: } raimund@3131: for (int i = 0; i < ranges.length; i++) { raimund@3131: logger.debug("creating domain marker"); raimund@3611: RegularTimePeriod start = new Day(ranges[i].getFrom()); raimund@3611: RegularTimePeriod end = new Day(ranges[i].getTo()); christian@3254: StyledDomainMarker marker = christian@3746: new StyledDomainMarker(start.getMiddleMillisecond(), christian@3746: end.getMiddleMillisecond(), theme); christian@3254: marker.useSecondColor(i % 2 == 0); raimund@3131: domainMarker.add(marker); raimund@3131: } raimund@3131: logger.debug("domainmarkers: " + domainMarker.size()); raimund@3131: } raimund@3131: raimund@3131: raimund@3131: @Override raimund@3131: public void init(Document request, OutputStream out, CallContext context) { raimund@3131: super.init(request, out, context); raimund@3131: sascha@3727: Double currentKm = FixChartGenerator.getCurrentKmFromRequest(request); sascha@3404: sascha@3404: if (logger.isDebugEnabled()) { sascha@3404: logger.debug("currentKm = " + currentKm); sascha@3404: } sascha@3404: sascha@3404: context.putContextValue("currentKm", currentKm); raimund@3131: christian@3254: StyledValueMarker marker = new StyledValueMarker(0, request); raimund@3131: valueMarker.add(marker); raimund@3131: } raimund@3131: } raimund@3131: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :