comparison artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractProcessor.java @ 9347:08f46ccd37ba

salix.regional refactoring
author gernotbelger
date Tue, 31 Jul 2018 16:04:01 +0200
parents artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/AbstractSInfoProcessor.java@0dcd1cd41915
children d8e753d0fdb9
comparison
equal deleted inserted replaced
9346:d89976700474 9347:08f46ccd37ba
1 /* Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
2 * Software engineering by
3 * Björnsen Beratende Ingenieure GmbH
4 * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
5 *
6 * This file is Free Software under the GNU AGPL (>=v3)
7 * and comes with ABSOLUTELY NO WARRANTY! Check out the
8 * documentation coming with Dive4Elements River for details.
9 */
10
11 package org.dive4elements.river.artifacts.common;
12
13 import java.util.Map;
14 import java.util.Set;
15
16 import org.apache.log4j.Logger;
17 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
18 import org.dive4elements.artifactdatabase.state.Facet;
19 import org.dive4elements.artifacts.Artifact;
20 import org.dive4elements.artifacts.CallContext;
21 import org.dive4elements.river.artifacts.D4EArtifact;
22 import org.dive4elements.river.artifacts.access.RiverAccess;
23 import org.dive4elements.river.artifacts.context.RiverContext;
24 import org.dive4elements.river.artifacts.math.MovingAverage;
25 import org.dive4elements.river.artifacts.model.WQKms;
26 import org.dive4elements.river.artifacts.model.ZoomScale;
27 import org.dive4elements.river.artifacts.resources.Resources;
28 import org.dive4elements.river.artifacts.sinfo.common.AbstractTkhCalculationResult;
29 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
30 import org.dive4elements.river.exports.DiagramGenerator;
31 import org.dive4elements.river.exports.StyledSeriesBuilder;
32 import org.dive4elements.river.exports.process.DefaultProcessor;
33 import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
34 import org.dive4elements.river.jfree.StyledXYSeries;
35 import org.dive4elements.river.themes.ThemeDocument;
36
37 /**
38 * Abstraction for some processor implementation within S-INFO. Probably this abstraction could also be used for other
39 * cases as well.
40 *
41 * @author Gernot Belger
42 *
43 */
44
45 public abstract class AbstractProcessor extends DefaultProcessor {
46
47 protected static final double GAP_DISTANCE = 0.101;
48
49 private final static Logger log = Logger.getLogger(AbstractProcessor.class);
50
51 private String yAxisLabel;
52
53 private final Set<String> handled_facet_types;
54
55 private final String i18n_axis_label;
56
57 public AbstractProcessor(final String i18n_axis_label, final Set<String> handled_facet_types) {
58 this.i18n_axis_label = i18n_axis_label;
59 this.handled_facet_types = handled_facet_types;
60 }
61
62 @Override
63 public final void doOut(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible) {
64 try {
65 this.yAxisLabel = generateSeries(generator, bundle, theme, visible);
66 }
67 catch (final Exception e) {
68 log.error(e.getMessage(), e);
69 }
70 }
71
72 protected static final AbstractCalculationResult getResult(final DiagramGenerator generator, final ArtifactAndFacet bundle) {
73 final CallContext context = generator.getContext();
74 final AbstractCalculationResult data = (AbstractCalculationResult) bundle.getData(context);
75 if (data == null) {
76 // Check has been here before so we keep it for security reasons
77 // this should never happen though.
78 final String facetName = bundle.getFacetName();
79 throw new IllegalStateException("Data is null for facet: " + facetName);
80 }
81
82 return data;
83 }
84
85 /**
86 * @return The axis label
87 */
88 protected abstract String generateSeries(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible);
89
90 protected final String buildSeriesForType(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme, final boolean visible,
91 final IResultType resultType, final Double gapDistance) {
92
93 final AbstractCalculationResult data = getResult(generator, bundle);
94
95 final double[][] points = data.getStationPoints(resultType);
96
97 return buildSeriesForPoints(points, generator, bundle, theme, visible, gapDistance);
98 }
99
100 protected final String buildSeriesForPoints(final double[][] points, final DiagramGenerator generator, final ArtifactAndFacet bundle,
101 final ThemeDocument theme, final boolean visible, final Double gapDistance) {
102 final CallContext context = generator.getContext();
103 final Map<String, String> metaData = bundle.getFacet().getMetaData();
104
105 final Artifact artifact = bundle.getArtifact();
106
107 final StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
108 series.putMetaData(metaData, artifact, context);
109
110 final String facetName = bundle.getFacetName();
111
112 final double[][] filteredPoints = filterPoints(points, context, artifact, facetName);
113
114 if (gapDistance == null)
115 StyledSeriesBuilder.addPoints(series, filteredPoints, true);
116 else
117 StyledSeriesBuilder.addPoints(series, filteredPoints, true, gapDistance);
118
119 generator.addAxisSeries(series, getAxisName(), visible);
120
121 return metaData.get("Y");
122 }
123
124 protected final String buildStepLineSeriesForType(final double[][] points, final DiagramGenerator generator, final ArtifactAndFacet bundle,
125 final ThemeDocument theme, final boolean visible) {
126
127 final CallContext context = generator.getContext();
128 final Map<String, String> metaData = bundle.getFacet().getMetaData();
129
130 final Artifact artifact = bundle.getArtifact();
131
132 final StyledXYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
133 series.putMetaData(metaData, artifact, context);
134
135 final String facetName = bundle.getFacetName();
136
137 // Create WQKms to use the step points method
138 // REMARK: must have any values in w array; not sure whether the name is needed
139 final WQKms wqkms = new WQKms(points[0], points[1], points[1], facetName);
140
141 StyledSeriesBuilder.addStepPointsKmQ(series, wqkms);
142
143 generator.addAxisSeries(series, getAxisName(), visible);
144
145 return metaData.get("Y");
146 }
147
148 protected final String buildSeriesForTkh(final DiagramGenerator generator, final ArtifactAndFacet bundle, final ThemeDocument theme,
149 final boolean visible) {
150
151 final AbstractTkhCalculationResult data = (AbstractTkhCalculationResult) getResult(generator, bundle);
152
153 final StyledXYSeries seriesUp = new StyledXYSeries(bundle.getFacetDescription(), theme);
154 final double[][] pointsUp = data.getTkhUpPoints();
155 StyledSeriesBuilder.addPoints(seriesUp, pointsUp, true);
156
157 // REMARK: we add " " because the description is misused as id, which must be unique.
158 final StyledXYSeries seriesDown = new StyledXYSeries(bundle.getFacetDescription() + " ", theme);
159 final double[][] pointsDown = data.getTkhDownPoints();
160 StyledSeriesBuilder.addPoints(seriesDown, pointsDown, true);
161
162 final StyledAreaSeriesCollection area = new StyledAreaSeriesCollection(theme);
163 area.setMode(StyledAreaSeriesCollection.FILL_MODE.BETWEEN);
164 area.addSeries(seriesUp);
165 area.addSeries(seriesDown);
166
167 generator.addAreaSeries(area, getAxisName(), visible);
168
169 return null;
170 }
171
172 private Double findRadius(final CallContext context, final Artifact artifact) {
173 final Double start = (Double) context.getContextValue("startkm");
174 final Double end = (Double) context.getContextValue("endkm");
175
176 if (start == null || end == null)
177 return null;
178
179 final RiverContext fc = (RiverContext) context.globalContext();
180 final ZoomScale scales = (ZoomScale) fc.get("zoomscale");
181 final RiverAccess access = new RiverAccess((D4EArtifact) artifact);
182 final String river = access.getRiverName();
183
184 return scales.getRadius(river, start, end);
185 }
186
187 private double[][] filterPoints(final double[][] points, final CallContext context, final Artifact artifact, final String facetName) {
188
189 if (facetName.endsWith(".filtered")) {
190 final Double radius = findRadius(context, artifact);
191 return movingAverage(radius, points);
192 }
193
194 return points;
195 }
196
197 private double[][] movingAverage(final Double radius, final double[][] points) {
198
199 if (radius == null)
200 return points;
201
202 return MovingAverage.weighted(points, radius);
203 }
204
205 @Override
206 public final boolean canHandle(final String facettype) {
207 return this.handled_facet_types.contains(facettype);
208 }
209
210 @Override
211 public final String getAxisLabel(final DiagramGenerator generator) {
212 if (this.yAxisLabel != null && !this.yAxisLabel.isEmpty()) {
213 // REMARK/UNINTENDED: yAxisLabel may also be a resolved message (side-effect of StyledXYSeries#putMetadata),
214 // and cannot be resolved, so we need to give the resolved value as default
215 // TODO: In other implementations (i.e. FlowVelocityProcessor), an explicit (German) default label is given here,
216 // probably the English version will also show German (CHECK)
217 return generator.msg(this.yAxisLabel, this.yAxisLabel);
218 }
219 return generator.msg(this.i18n_axis_label, "MISSING");
220 }
221
222 protected static final Facet createFacet(final CallContext context, final String hash, final String id, final AbstractCalculationResult result,
223 final int resultIndex, final String axisLabel, final String facetId, final String description) {
224 final String facetFlowDepthFilteredDescription = Resources.getMsg(context.getMeta(), description, description, result.getLabel());
225 return new ResultFacet(resultIndex, facetId, facetFlowDepthFilteredDescription, axisLabel, ComputeType.ADVANCE, id, hash);
226 }
227 }

http://dive4elements.wald.intevation.org