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