Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/exports/OutputHelper.java @ 3318:dbe2f85bf160
merged flys-artifacts/2.8
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:35 +0200 |
parents | 02d5731b43a2 |
children | 8e713e9bb4d7 |
comparison
equal
deleted
inserted
replaced
2987:98c7a46ec5ae | 3318:dbe2f85bf160 |
---|---|
1 package de.intevation.flys.exports; | |
2 | |
3 import java.io.IOException; | |
4 import java.util.ArrayList; | |
5 import java.util.HashMap; | |
6 import java.util.List; | |
7 import java.util.Map; | |
8 | |
9 import javax.xml.xpath.XPathConstants; | |
10 | |
11 import org.apache.log4j.Logger; | |
12 import org.w3c.dom.Document; | |
13 import org.w3c.dom.Element; | |
14 import org.w3c.dom.Node; | |
15 import org.w3c.dom.NodeList; | |
16 | |
17 import de.intevation.artifactdatabase.Backend; | |
18 import de.intevation.artifactdatabase.Backend.PersistentArtifact; | |
19 import de.intevation.artifactdatabase.state.ArtifactAndFacet; | |
20 import de.intevation.artifacts.Artifact; | |
21 import de.intevation.artifacts.ArtifactDatabase; | |
22 import de.intevation.artifacts.ArtifactDatabaseException; | |
23 import de.intevation.artifacts.CallContext; | |
24 import de.intevation.artifacts.CallMeta; | |
25 import de.intevation.artifacts.common.ArtifactNamespaceContext; | |
26 import de.intevation.artifacts.common.utils.ClientProtocolUtils; | |
27 import de.intevation.artifacts.common.utils.XMLUtils; | |
28 import de.intevation.flys.artifacts.FLYSArtifact; | |
29 import de.intevation.flys.artifacts.context.FLYSContext; | |
30 import de.intevation.flys.artifacts.model.ManagedDomFacet; | |
31 import de.intevation.flys.artifacts.model.ManagedFacet; | |
32 import de.intevation.flys.themes.Theme; | |
33 import de.intevation.flys.themes.ThemeFactory; | |
34 | |
35 public class OutputHelper { | |
36 /** The logger used in this class. */ | |
37 private static Logger log = Logger.getLogger(OutputHelper.class); | |
38 | |
39 protected String identifier; | |
40 | |
41 public OutputHelper(String identifier) { | |
42 this.identifier = identifier; | |
43 } | |
44 /** | |
45 * Creates a concrete output. | |
46 * | |
47 * @param generator The OutGenerator that creates the output. | |
48 * @param outputName The name of the requested output. | |
49 * @param attributes The collection's attributes for this concrete output | |
50 * type. | |
51 * @param context The context object. | |
52 */ | |
53 public void doOut( | |
54 OutGenerator generator, | |
55 String outName, | |
56 String facet, | |
57 Document attributes, | |
58 CallContext context) | |
59 throws IOException | |
60 { | |
61 boolean debug = log.isDebugEnabled(); | |
62 | |
63 if (debug) { | |
64 log.debug("FLYSArtifactCollection.doOut: " + outName); | |
65 } | |
66 | |
67 ThemeList themeList = new ThemeList(attributes); | |
68 | |
69 int size = themeList.size(); | |
70 if (debug) { | |
71 log.debug("Output will contain " + size + " elements."); | |
72 } | |
73 | |
74 List<ArtifactAndFacet> dataProviders = | |
75 doBlackboardPass(themeList, context); | |
76 | |
77 try { | |
78 for (int i = 0; i < size; i++) { | |
79 ManagedFacet theme = themeList.get(i); | |
80 | |
81 if (theme == null) { | |
82 log.debug("Theme is empty - no output is generated."); | |
83 continue; | |
84 } | |
85 | |
86 String art = theme.getArtifact(); | |
87 String facetName = theme.getName(); | |
88 | |
89 if (debug) { | |
90 log.debug("Do output for..."); | |
91 log.debug("... artifact: " + art); | |
92 log.debug("... facet: " + facetName); | |
93 } | |
94 | |
95 if (outName.equals("export") && !facetName.equals(facet)) { | |
96 continue; | |
97 } | |
98 | |
99 // Skip invisible themes. | |
100 if (theme.getVisible() == 0) { | |
101 continue; | |
102 } | |
103 | |
104 if (outName.equals("sq_overview")) { | |
105 generator.doOut( | |
106 dataProviders.get(i), | |
107 attributes, | |
108 theme.getActive() == 1); | |
109 } | |
110 else { | |
111 generator.doOut( | |
112 dataProviders.get(i), | |
113 getFacetThemeFromAttribute( | |
114 art, | |
115 outName, | |
116 facetName, | |
117 theme.getDescription(), | |
118 theme.getIndex(), | |
119 context), | |
120 theme.getActive() == 1); | |
121 } | |
122 } | |
123 } | |
124 catch (ArtifactDatabaseException ade) { | |
125 log.error(ade, ade); | |
126 } | |
127 } | |
128 /** | |
129 * Returns the attribute that belongs to an artifact and facet stored in | |
130 * this collection. | |
131 * | |
132 * @param uuid The Artifact's uuid. | |
133 * @param outname The name of the requested output. | |
134 * @param facet The name of the requested facet. | |
135 * @param context The CallContext. | |
136 * | |
137 * @return an attribute in form of a document. | |
138 */ | |
139 protected Document getFacetThemeFromAttribute( | |
140 String uuid, | |
141 String outName, | |
142 String facet, | |
143 String pattern, | |
144 int index, | |
145 CallContext context) | |
146 throws ArtifactDatabaseException | |
147 { | |
148 boolean debug = log.isDebugEnabled(); | |
149 | |
150 if (debug) { | |
151 log.debug( | |
152 "FLYSArtifactCollection.getFacetThemeFromAttribute(facet=" | |
153 + facet + ", index=" + index + ")"); | |
154 } | |
155 | |
156 | |
157 ArtifactDatabase db = context.getDatabase(); | |
158 CallMeta meta = context.getMeta(); | |
159 | |
160 FLYSContext flysContext = context instanceof FLYSContext | |
161 ? (FLYSContext) context | |
162 : (FLYSContext) context.globalContext(); | |
163 | |
164 Document attr = db.getCollectionItemAttribute(identifier, uuid, meta); | |
165 | |
166 if (attr == null) { | |
167 attr = initItemAttribute(uuid, facet, pattern, index, outName, context); | |
168 | |
169 if (attr == null) { | |
170 return null; | |
171 } | |
172 } | |
173 | |
174 if (debug) { | |
175 log.debug("Search attribute of collection item: " + uuid); | |
176 } | |
177 | |
178 Node tmp = (Node) XMLUtils.xpath( | |
179 attr, | |
180 "/art:attribute", | |
181 XPathConstants.NODE, | |
182 ArtifactNamespaceContext.INSTANCE); | |
183 | |
184 if (tmp == null) { | |
185 log.warn("No attribute found. Operation failed."); | |
186 return null; | |
187 } | |
188 | |
189 if (debug) { | |
190 log.debug("Search theme for facet '" + facet + "' in attribute."); | |
191 } | |
192 | |
193 Map<String, String> vars = new HashMap<String, String>(); | |
194 vars.put("facet", facet); | |
195 vars.put("index", String.valueOf(index)); | |
196 | |
197 Node theme = (Node) XMLUtils.xpath( | |
198 tmp, | |
199 "art:themes/theme[@facet=$facet and @index=$index]", | |
200 XPathConstants.NODE, | |
201 ArtifactNamespaceContext.INSTANCE, | |
202 vars); | |
203 | |
204 if (theme == null) { | |
205 log.warn("Could not find the theme in attribute of: " + facet + " " + uuid); | |
206 | |
207 Theme t = getThemeForFacet( | |
208 uuid, facet, pattern, index, outName, context); | |
209 | |
210 if (t == null) { | |
211 log.warn("No theme found for facet: " + facet); | |
212 return null; | |
213 } | |
214 | |
215 addThemeToAttribute(uuid, attr, t, context); | |
216 theme = t.toXML().getFirstChild(); | |
217 } | |
218 | |
219 Document doc = XMLUtils.newDocument(); | |
220 doc.appendChild(doc.importNode(theme, true)); | |
221 | |
222 return doc; | |
223 } | |
224 /** | |
225 * Adds the theme of a facet to a CollectionItem's attribute. | |
226 * | |
227 * @param uuid The uuid of the artifact. | |
228 * @param attr The current attribute of an artifact. | |
229 * @param t The theme to add. | |
230 * @param context The CallContext. | |
231 */ | |
232 protected void addThemeToAttribute( | |
233 String uuid, | |
234 Document attr, | |
235 Theme t, | |
236 CallContext context) | |
237 { | |
238 log.debug("FLYSArtifactCollection.addThemeToAttribute: " + uuid); | |
239 | |
240 if (t == null) { | |
241 log.warn("Theme is empty - cancel adding it to attribute!"); | |
242 return; | |
243 } | |
244 | |
245 XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( | |
246 attr, | |
247 ArtifactNamespaceContext.NAMESPACE_URI, | |
248 ArtifactNamespaceContext.NAMESPACE_PREFIX); | |
249 | |
250 Node tmp = (Node) XMLUtils.xpath( | |
251 attr, | |
252 "/art:attribute", | |
253 XPathConstants.NODE, | |
254 ArtifactNamespaceContext.INSTANCE); | |
255 | |
256 if (tmp == null) { | |
257 tmp = ec.create("attribute"); | |
258 attr.appendChild(tmp); | |
259 } | |
260 | |
261 Node themes = (Node) XMLUtils.xpath( | |
262 tmp, | |
263 "art:themes", | |
264 XPathConstants.NODE, | |
265 ArtifactNamespaceContext.INSTANCE); | |
266 | |
267 if (themes == null) { | |
268 themes = ec.create("themes"); | |
269 tmp.appendChild(themes); | |
270 } | |
271 | |
272 themes.appendChild(attr.importNode(t.toXML().getFirstChild(), true)); | |
273 | |
274 try { | |
275 setCollectionItemAttribute(uuid, attr, context); | |
276 } | |
277 catch (ArtifactDatabaseException e) { | |
278 // do nothing | |
279 log.warn("Cannot set attribute of item: " + uuid); | |
280 } | |
281 } | |
282 | |
283 /** | |
284 * Sets the attribute of a CollectionItem specified by <i>uuid</i> to a new | |
285 * value <i>attr</i>. | |
286 * | |
287 * @param uuid The uuid of the CollectionItem. | |
288 * @param attr The new attribute for the CollectionItem. | |
289 * @param context The CallContext. | |
290 */ | |
291 public void setCollectionItemAttribute( | |
292 String uuid, | |
293 Document attr, | |
294 CallContext context) | |
295 throws ArtifactDatabaseException | |
296 { | |
297 Document doc = ClientProtocolUtils.newSetItemAttributeDocument( | |
298 uuid, | |
299 attr); | |
300 | |
301 if (doc == null) { | |
302 log.warn("Cannot set item attribute: No attribute found."); | |
303 return; | |
304 } | |
305 | |
306 ArtifactDatabase db = context.getDatabase(); | |
307 CallMeta meta = context.getMeta(); | |
308 | |
309 db.setCollectionItemAttribute(identifier, uuid, doc, meta); | |
310 } | |
311 | |
312 | |
313 /** | |
314 * Show blackboard (context) to each facet and create a list of | |
315 * ArtifactAndFacets on the fly (with the same ordering as the passed | |
316 * ThemeList). | |
317 * @param themeList ThemeList to create a ArtifactAndFacetList along. | |
318 * @param context The "Blackboard". | |
319 */ | |
320 protected List<ArtifactAndFacet> doBlackboardPass( | |
321 ThemeList themeList, CallContext context | |
322 ) { | |
323 ArrayList<ArtifactAndFacet> dataProviders = | |
324 new ArrayList<ArtifactAndFacet>(); | |
325 int size = themeList.size(); | |
326 | |
327 try { | |
328 // Collect all ArtifactAndFacets for blackboard pass. | |
329 for (int i = 0; i < size; i++) { | |
330 ManagedFacet theme = themeList.get(i); | |
331 if (theme == null) { | |
332 log.warn("A ManagedFacet in ThemeList is null."); | |
333 continue; | |
334 } | |
335 String uuid = theme.getArtifact(); | |
336 Artifact artifact = getArtifact(uuid, context); | |
337 FLYSArtifact flys = (FLYSArtifact) artifact; | |
338 | |
339 ArtifactAndFacet artifactAndFacet = new ArtifactAndFacet( | |
340 artifact, | |
341 flys.getNativeFacet(theme)); | |
342 | |
343 // XXX HELP ME PLEASE | |
344 artifactAndFacet.setFacetDescription(theme.getDescription()); | |
345 | |
346 // Show blackboard to facet. | |
347 artifactAndFacet.register(context); | |
348 | |
349 // Add to themes. | |
350 dataProviders.add(i, artifactAndFacet); | |
351 } | |
352 } | |
353 catch (ArtifactDatabaseException ade) { | |
354 log.error("ArtifactDatabaseException!", ade); | |
355 } | |
356 | |
357 return dataProviders; | |
358 } | |
359 /** | |
360 * Returns a concrete Artifact of this collection specified by its uuid. | |
361 * | |
362 * @param uuid The Artifact's uuid. | |
363 * @param context The CallContext. | |
364 * | |
365 * @return an Artifact. | |
366 */ | |
367 protected Artifact getArtifact(String uuid, CallContext context) | |
368 throws ArtifactDatabaseException | |
369 { | |
370 log.debug("FLYSArtifactCollection.getArtifact"); | |
371 | |
372 Backend backend = Backend.getInstance(); | |
373 PersistentArtifact persistent = backend.getArtifact(uuid); | |
374 | |
375 return persistent != null ? persistent.getArtifact() : null; | |
376 } | |
377 | |
378 /** | |
379 * Initializes the attribute of an collection item with the theme of a | |
380 * specific facet. | |
381 * | |
382 * @param uuid The uuid of an artifact. | |
383 * @param facet The name of a facet. | |
384 * @param context The CallContext. | |
385 * | |
386 * @param the new attribute. | |
387 */ | |
388 protected Document initItemAttribute( | |
389 String uuid, | |
390 String facet, | |
391 String pattern, | |
392 int index, | |
393 String outName, | |
394 CallContext context) | |
395 { | |
396 boolean debug = log.isDebugEnabled(); | |
397 | |
398 if (debug) { | |
399 log.debug("FLYSArtifactCollection.initItemAttribute"); | |
400 } | |
401 | |
402 Theme t = getThemeForFacet(uuid, facet, pattern, index, outName, context); | |
403 | |
404 if (t == null) { | |
405 log.info("Could not find theme for facet. Cancel initialization."); | |
406 return null; | |
407 } | |
408 | |
409 Document attr = XMLUtils.newDocument(); | |
410 addThemeToAttribute(uuid, attr, t, context); | |
411 | |
412 if (debug) { | |
413 log.debug("initItemAttribute for facet " + facet + ": " | |
414 + XMLUtils.toString(attr)); | |
415 } | |
416 | |
417 return attr; | |
418 } | |
419 | |
420 /** | |
421 * Returns the theme of a specific facet. | |
422 * | |
423 * @param uuid The uuid of an artifact. | |
424 * @param facet The name of the facet. | |
425 * @param context The CallContext object. | |
426 * | |
427 * @return the desired theme. | |
428 */ | |
429 protected Theme getThemeForFacet( | |
430 String uuid, | |
431 String facet, | |
432 String pattern, | |
433 int index, | |
434 String outName, | |
435 CallContext context) | |
436 { | |
437 log.info("FLYSArtifactCollection.getThemeForFacet: " + facet); | |
438 | |
439 FLYSContext flysContext = context instanceof FLYSContext | |
440 ? (FLYSContext) context | |
441 : (FLYSContext) context.globalContext(); | |
442 | |
443 // Push artifact in flysContext. | |
444 ArtifactDatabase db = context.getDatabase(); | |
445 try { | |
446 FLYSArtifact artifact = (FLYSArtifact) db.getRawArtifact(uuid); | |
447 log.debug("Got raw artifact"); | |
448 flysContext.put(FLYSContext.ARTIFACT_KEY, artifact); | |
449 } | |
450 catch (ArtifactDatabaseException dbe) { | |
451 log.error("Exception caught when trying to get art.", dbe); | |
452 } | |
453 | |
454 Theme t = ThemeFactory.getTheme( | |
455 flysContext, | |
456 facet, | |
457 pattern, | |
458 outName, | |
459 "default"); | |
460 | |
461 if (t != null) { | |
462 t.setFacet(facet); | |
463 t.setIndex(index); | |
464 } | |
465 | |
466 return t; | |
467 } | |
468 | |
469 /** | |
470 * Inner class to structure/order the themes of a chart. | |
471 */ | |
472 private static class ThemeList { | |
473 private Logger logger = Logger.getLogger(ThemeList.class); | |
474 protected Map<Integer, ManagedFacet> themes; | |
475 | |
476 public ThemeList(Document output) { | |
477 themes = new HashMap<Integer, ManagedFacet>(); | |
478 parse(output); | |
479 } | |
480 | |
481 protected void parse(Document output) { | |
482 NodeList themeList = (NodeList) XMLUtils.xpath( | |
483 output, | |
484 "art:output/art:facet", | |
485 XPathConstants.NODESET, | |
486 ArtifactNamespaceContext.INSTANCE); | |
487 | |
488 int num = themeList != null ? themeList.getLength() : 0; | |
489 | |
490 logger.debug("Output has " + num + " elements."); | |
491 | |
492 if (num == 0) { | |
493 return; | |
494 } | |
495 | |
496 String uri = ArtifactNamespaceContext.NAMESPACE_URI; | |
497 | |
498 for (int i = 0; i < num; i++) { | |
499 Element theme = (Element) themeList.item(i); | |
500 | |
501 ManagedDomFacet facet = new ManagedDomFacet(theme); | |
502 themes.put(Integer.valueOf(facet.getPosition()-1), facet); | |
503 } | |
504 } | |
505 | |
506 public ManagedFacet get(int idx) { | |
507 return themes.get(Integer.valueOf(idx)); | |
508 } | |
509 | |
510 public int size() { | |
511 return themes.size(); | |
512 } | |
513 } | |
514 } | |
515 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |