comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/CrossSectionArtifact.java @ 2793:6310b1582f2d

merged flys-artifacts/2.7
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:30 +0200
parents 2f7fed1eb4bf
children 31168ac9c7e7
comparison
equal deleted inserted replaced
2548:ada02bbd3b7f 2793:6310b1582f2d
1 package de.intevation.flys.artifacts;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.NavigableMap;
6
7 import org.apache.log4j.Logger;
8
9 import org.w3c.dom.Document;
10
11 import de.intevation.artifacts.Artifact;
12 import de.intevation.artifacts.ArtifactFactory;
13 import de.intevation.artifacts.CallMeta;
14
15 import de.intevation.flys.artifacts.model.CrossSectionFacet;
16 import de.intevation.flys.artifacts.model.FastCrossSectionLineFactory;
17
18 import de.intevation.flys.model.FastCrossSectionLine;
19
20 import de.intevation.flys.model.CrossSection;
21 import de.intevation.flys.model.CrossSectionLine;
22 import de.intevation.flys.artifacts.model.CrossSectionFactory;
23
24 import de.intevation.flys.artifacts.states.StaticState;
25
26 import de.intevation.artifactdatabase.state.Facet;
27 import de.intevation.artifactdatabase.state.State;
28
29 import de.intevation.flys.utils.FLYSUtils;
30
31 import de.intevation.flys.artifacts.services.CrossSectionKMService;
32
33
34 /**
35 * Artifact describing a cross-section.
36 */
37 public class CrossSectionArtifact extends StaticFLYSArtifact {
38
39 /** Name of Artifact. */
40 public static final String CS_ARTIFACT_NAME = "cross_section";
41
42 /** Name of state. */
43 public static final String STATIC_STATE_NAME = "state.cross_section";
44
45 /** Name of data item keeping the position. */
46 public static final String DATA_KM = "cross_section.km";
47
48 /** Name of data item keeping the database id of this c.s.. */
49 public static final String DATA_DBID = "cross_section.dbid";
50
51 /** Name of data item flagging whether we think that we are master. */
52 public static final String DATA_IS_MASTER = "cross_section.master?";
53
54 /** Name of data item flagging whether we are the newest. */
55 public static final String DATA_IS_NEWEST = "cross_section.newest?";
56
57 /** Own logger. */
58 private static final Logger logger =
59 Logger.getLogger(CrossSectionArtifact.class);
60
61
62 /** Return given name. */
63 @Override
64 public String getName() {
65 return CS_ARTIFACT_NAME;
66 }
67
68
69 /** Store ids, create a CrossSectionFacet. */
70 @Override
71 public void setup(
72 String identifier,
73 ArtifactFactory factory,
74 Object context,
75 CallMeta callMeta,
76 Document data)
77 {
78 logger.info("CrossSectionArtifact.setup");
79
80 super.setup(identifier, factory, context, callMeta, data);
81
82 String ids = getDatacageIDValue(data);
83
84 if (ids != null && ids.length() > 0) {
85 addStringData(DATA_DBID, ids);
86 logger.debug("CrossSectionArtifacts db-id: " + ids);
87 }
88 else {
89 throw new IllegalArgumentException("No attribute 'ids' found!");
90 }
91
92 List<Facet> fs = new ArrayList<Facet>();
93 CrossSection cs = CrossSectionFactory.getCrossSection(
94 Integer.valueOf(ids));
95
96 List<CrossSectionLine> csls = cs.getLines();
97 if (!csls.isEmpty()) {
98 CrossSectionLine csl = csls.get(0);
99 // Find min-km of cross sections,
100 // then set DATA_KM to min(DATA_KM, minCross).
101 double masterKm = Double.valueOf(getDataAsString(DATA_KM));
102 if (masterKm < csl.getKm().doubleValue()) {
103 addStringData(DATA_KM, csl.getKm().toString());
104 }
105 }
106 fs.add(new CrossSectionFacet(0, cs.getDescription()));
107
108 // Find out if we are newest.
109 boolean isNewest = CrossSectionFactory.isNewest(cs);
110 String newString = (isNewest) ? "1" : "0";
111 addStringData(DATA_IS_NEWEST, newString);
112 addStringData(DATA_IS_MASTER, newString);
113
114 StaticState state = (StaticState) getCurrentState(context);
115
116 if (!fs.isEmpty()) {
117 facets.put(getCurrentStateId(), fs);
118 }
119 }
120
121
122 /** Copy km where master-artifact "starts". */
123 @Override
124 protected void initialize(
125 Artifact artifact,
126 Object context,
127 CallMeta callMeta)
128 {
129 FLYSArtifact winfo = (FLYSArtifact) artifact;
130 double[] range = FLYSUtils.getKmRange(winfo);
131 double min = 0.0f;
132 if (range != null && range.length > 0) {
133 min = range[0];
134 }
135 this.addStringData(DATA_KM, Double.toString(min));
136 }
137
138
139 /**
140 * Create and return a new StaticState with charting output.
141 */
142 @Override
143 public State getCurrentState(Object cc) {
144 final List<Facet> fs = facets.get(getCurrentStateId());
145
146 StaticState state = new StaticState(STATIC_STATE_NAME) {
147 @Override
148 public Object staticCompute(List<Facet> facets) {
149 if (facets != null) {
150 facets.addAll(fs);
151 }
152 return null;
153 }
154 };
155
156 state.addDefaultChartOutput("cross_section", fs);
157
158 return state;
159 }
160
161
162 /**
163 * Get a list containing the one and only State.
164 * @param context ignored.
165 * @return list with one and only state.
166 */
167 @Override
168 protected List<State> getStates(Object context) {
169 ArrayList<State> states = new ArrayList<State>();
170 states.add(getCurrentState(context));
171
172 return states;
173 }
174
175 // TODO all data access needs proper caching.
176
177 /**
178 * Get a DataItem casted to int (0 if fails).
179 */
180 public int getDataAsIntNull(String dataName) {
181 String val = getDataAsString(dataName);
182 try {
183 return Integer.valueOf(val);
184 }
185 catch (NumberFormatException e) {
186 logger.warn("Could not get data " + dataName + " as int", e);
187 return 0;
188 }
189 }
190
191
192 /** Returns database-id of cross-section (from data). */
193 protected int getDBID() {
194 return getDataAsIntNull(DATA_DBID);
195 }
196
197
198 /**
199 * Return position (km) from data, 0 if not found.
200 */
201 protected double getKm() {
202 String val = getDataAsString(DATA_KM);
203 try {
204 return Double.valueOf(val);
205 }
206 catch (NumberFormatException e) {
207 logger.warn("Could not get data " + DATA_KM + " as double", e);
208 return 0;
209 }
210 }
211
212
213 /** Returns true if artifact is set to be a "master" (other facets will
214 * refer to this). */
215 public boolean isMaster() {
216 return !getDataAsString(DATA_IS_MASTER).equals("0");
217 }
218
219
220 /**
221 * Get points of Profile of cross section at given kilometer.
222 *
223 * @return an array holding coordinates of points of profile (
224 * in the form {{x1, x2} {y1, y2}} ).
225 */
226 public double [][] getCrossSectionData() {
227 logger.info("getCrossSectionData() for cross_section.km "
228 + getDataAsString(DATA_KM));
229 FastCrossSectionLine line = searchCrossSectionLine();
230
231 return line != null
232 ? line.fetchCrossSectionProfile()
233 : null;
234 }
235
236
237 /**
238 * Get CrossSectionLine spatially closest to what is specified in the data
239 * "cross_section.km", null if considered too far.
240 *
241 * @return CrossSectionLine closest to "cross_section.km", might be null
242 * if considered too far.
243 */
244 public FastCrossSectionLine searchCrossSectionLine() {
245 double TOO_FAR = 1d;
246 CrossSection crossSection = CrossSectionFactory
247 .getCrossSection(getDBID());
248
249 if (logger.isDebugEnabled()) {
250 logger.debug("dbid " + getDBID() + " : " + crossSection);
251 }
252
253 NavigableMap<Double, Integer> kms = CrossSectionKMService
254 .getKms(crossSection.getId());
255
256 Double wishKM = getKm();
257
258 Double floor = kms.floorKey(wishKM);
259 Double ceil = kms.ceilingKey(wishKM);
260
261 double floorD = floor != null
262 ? Math.abs(floor - wishKM)
263 : Double.MAX_VALUE;
264
265 double ceilD = ceil != null
266 ? Math.abs(ceil - wishKM)
267 : Double.MAX_VALUE;
268
269 double km = floorD < ceilD ? floor : ceil;
270
271 // If we are too far from the wished km, return null.
272 if (Math.abs(km - wishKM) > TOO_FAR) {
273 return null;
274 }
275
276 return FastCrossSectionLineFactory
277 .getCrossSectionLine(crossSection, km);
278 }
279
280
281 /**
282 * Determines Facets initial disposition regarding activity (think of
283 * selection in Client ThemeList GUI). This will be checked one time
284 * when the facet enters a collections describe document.
285 *
286 * @param outputName Ignored.
287 * @param facetName Ignored.
288 * @param index Ignored.
289 * @return 0 if not active
290 */
291 @Override
292 public int getInitialFacetActivity(String outputName, String facetName, int index) {
293 return (getDataAsString(DATA_IS_NEWEST) != null
294 && getDataAsString(DATA_IS_NEWEST).equals("1")) ? 1 : 0;
295 }
296 }
297 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org