raimund@3131: package de.intevation.flys.exports.fixings; raimund@3131: sascha@3139: import de.intevation.artifactdatabase.state.ArtifactAndFacet; sascha@3139: import de.intevation.artifacts.ArtifactNamespaceContext; sascha@3139: import de.intevation.artifacts.CallContext; sascha@3139: import de.intevation.artifacts.common.utils.XMLUtils; sascha@3139: import de.intevation.flys.artifacts.FLYSArtifact; sascha@3408: import de.intevation.flys.artifacts.access.FixAnalysisAccess; sascha@3210: import de.intevation.flys.artifacts.model.DateRange; sascha@3139: import de.intevation.flys.artifacts.model.FacetTypes; felix@3467: import de.intevation.flys.artifacts.model.QWDDateRange; sascha@3139: import de.intevation.flys.artifacts.model.fixings.QWD; christian@3279: import de.intevation.flys.artifacts.resources.Resources; sascha@3139: import de.intevation.flys.exports.TimeseriesChartGenerator; christian@3212: import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; christian@3212: import de.intevation.flys.jfree.FLYSAnnotation; christian@3254: import de.intevation.flys.jfree.StyledDomainMarker; sascha@3139: import de.intevation.flys.jfree.StyledTimeSeries; christian@3254: import de.intevation.flys.jfree.StyledValueMarker; felix@3238: import de.intevation.flys.utils.ThemeUtil; sascha@3139: sascha@3139: import java.io.OutputStream; christian@3212: import java.util.ArrayList; christian@3212: import java.util.HashMap; christian@3212: import java.util.List; christian@3212: import java.util.Map; christian@3212: import java.util.Set; christian@3212: sascha@3139: import javax.xml.xpath.XPathConstants; raimund@3131: raimund@3131: import org.apache.log4j.Logger; christian@3212: import org.jfree.chart.annotations.XYTextAnnotation; raimund@3131: import org.jfree.data.time.Day; raimund@3131: import org.jfree.data.time.Month; raimund@3131: import org.jfree.data.time.RegularTimePeriod; raimund@3131: import org.jfree.data.time.TimeSeries; raimund@3131: import org.jfree.data.time.TimeSeriesCollection; sascha@3139: import org.w3c.dom.Document; sascha@3139: import org.w3c.dom.Element; raimund@3131: 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 = raimund@3131: Logger.getLogger(FixDeltaWtGenerator.class); raimund@3131: raimund@3131: public static final String XPATH_CHART_CURRENTKM = raimund@3131: "/art:action/art:attributes/art:currentKm"; raimund@3131: raimund@3131: public static final String I18N_CHART_TITLE = raimund@3131: "chart.fix.deltawt.title"; raimund@3131: raimund@3131: public static final String I18N_CHART_SUBTITLE = raimund@3131: "chart.fix.deltawt.subtitle"; raimund@3131: raimund@3131: public static final String I18N_XAXIS_LABEL = raimund@3131: "chart.fix.deltawt.xaxis.label"; raimund@3131: raimund@3131: public static final String I18N_YAXIS_LABEL = raimund@3131: "chart.fix.deltawt.yaxis.label"; raimund@3131: raimund@3131: public static final String I18N_YAXIS_SECOND_LABEL = raimund@3131: "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@3562: getCurrentKmFromRequest().doubleValue()); christian@3406: } christian@3406: christian@3406: christian@3406: @Override raimund@3131: protected String getDefaultChartSubtitle() { sascha@3408: FixAnalysisAccess access = new FixAnalysisAccess(artifact); 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( raimund@3131: ArtifactAndFacet artifactFacet, raimund@3131: Document theme, raimund@3131: boolean visible raimund@3131: ) { 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( raimund@3131: (FLYSArtifact) artifactFacet.getArtifact(), raimund@3131: artifactFacet.getData(context), raimund@3131: artifactFacet.getFacetDescription(), raimund@3131: theme, raimund@3131: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_REFERENCE_EVENTS_DWT)) { raimund@3131: doReferenceEventsOut( raimund@3131: (FLYSArtifact) artifactFacet.getArtifact(), raimund@3131: artifactFacet.getData(context), raimund@3131: artifactFacet.getFacetDescription(), raimund@3131: theme, raimund@3131: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_ANALYSIS_EVENTS_DWT)) { raimund@3131: doAnalysisEventsOut( raimund@3131: (FLYSArtifact) artifactFacet.getArtifact(), raimund@3131: artifactFacet.getData(context), raimund@3131: artifactFacet.getFacetDescription(), raimund@3131: theme, raimund@3131: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_DEVIATION_DWT)) { raimund@3131: doDeviationOut( raimund@3131: (FLYSArtifact) artifactFacet.getArtifact(), raimund@3131: artifactFacet.getData(context), raimund@3131: artifactFacet.getFacetDescription(), raimund@3131: theme, raimund@3131: visible); raimund@3131: } raimund@3131: else if (name.equals(FIX_ANALYSIS_PERIODS_DWT)) { raimund@3131: doAnalysisPeriodsOut( raimund@3131: (FLYSArtifact) artifactFacet.getArtifact(), raimund@3131: artifactFacet.getData(context), raimund@3131: artifactFacet.getFacetDescription(), raimund@3131: theme, raimund@3131: visible); raimund@3131: } raimund@3131: else { raimund@3131: logger.warn("doOut(): unknown facet name: " + name); raimund@3131: return; raimund@3131: } raimund@3131: } raimund@3131: raimund@3131: raimund@3131: protected void doSectorAverageOut( raimund@3131: FLYSArtifact artifact, raimund@3131: Object data, raimund@3131: String desc, raimund@3131: Document theme, raimund@3131: 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(); felix@3467: /* felix@3467: // Draw a line spanning the analysis time. raimund@3131: series.add(rtp, value); felix@3467: rtp = new Day(qwd.dateRange.getFrom()); felix@3467: series.add(rtp, value); felix@3467: rtp = new Day(qwd.dateRange.getTo()); felix@3467: series.add(rtp, value); felix@3467: */ felix@3467: raimund@3131: tsc.addSeries(series); raimund@3131: raimund@3131: addAxisDataset(tsc, 0, visible); raimund@3168: addAttribute(desc, "outline"); felix@3234: Map annoIdxMap = new HashMap(); felix@3234: annoIdxMap.put (0, new int[]{0,0}); raimund@3610: doQWDTextAnnotations(annoIdxMap, tsc, qwd.qwd, theme, visible); raimund@3131: } raimund@3131: raimund@3131: raimund@3131: protected void doAnalysisEventsOut( raimund@3131: FLYSArtifact artifact, raimund@3131: Object data, raimund@3131: String desc, raimund@3131: Document theme, raimund@3131: boolean visible raimund@3131: ) { 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@3438: List textAnnos = new ArrayList(); christian@3438: Set> entries = annoIdxMap.entrySet(); christian@3438: christian@3438: for(Map.Entry entry : entries) { christian@3438: int[] idxs = entry.getValue(); christian@3438: double x = tsc.getXValue(idxs[0], idxs[1]); christian@3438: XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( christian@3438: qwd.getQ() + " m\u00B3/s", christian@3438: x, christian@3438: 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@3438: FLYSArtifact artifact, christian@3438: Object data, christian@3438: String desc, christian@3438: Document theme, christian@3438: boolean visible christian@3438: ) { 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( raimund@3131: FLYSArtifact artifact, raimund@3131: Object data, raimund@3131: String desc, raimund@3131: Document theme, raimund@3131: boolean visible raimund@3131: ) { 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( raimund@3131: FLYSArtifact artifact, raimund@3131: Object data, raimund@3131: String desc, raimund@3131: Document theme, raimund@3131: boolean visible raimund@3131: ) { raimund@3131: logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); raimund@3131: 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@3131: RegularTimePeriod start = new Month(ranges[i].getFrom()); raimund@3131: RegularTimePeriod end = new Month(ranges[i].getTo()); christian@3254: StyledDomainMarker marker = christian@3254: new StyledDomainMarker(start.getMiddleMillisecond(), christian@3254: 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@3404: Double currentKm = getCurrentKmFromRequest(); 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: sascha@3561: protected Double getCurrentKmFromRequest() { raimund@3131: Element km = (Element)XMLUtils.xpath( raimund@3131: request, raimund@3131: XPATH_CHART_CURRENTKM, raimund@3131: XPathConstants.NODE, raimund@3131: ArtifactNamespaceContext.INSTANCE); raimund@3131: raimund@3131: if (km == null) { sascha@3404: return Double.valueOf(-1d); raimund@3131: } raimund@3131: raimund@3131: String uri = ArtifactNamespaceContext.NAMESPACE_URI; sascha@3404: // XXX: When using XPath already why is the 'km' sascha@3404: // attribute not fetched directly? raimund@3131: String currentKm = km.getAttributeNS(uri, "km"); raimund@3131: try { sascha@3404: return Double.valueOf(currentKm); raimund@3131: } sascha@3404: catch (NumberFormatException nfe) { sascha@3404: return Double.valueOf(-1d); raimund@3131: } raimund@3131: } raimund@3131: } raimund@3131: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :