comparison flys-artifacts/src/main/java/org/dive4elements/river/exports/OutputHelper.java @ 5831:bd047b71ab37

Repaired internal references
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 12:06:39 +0200
parents flys-artifacts/src/main/java/de/intevation/flys/exports/OutputHelper.java@5b8919ef601d
children
comparison
equal deleted inserted replaced
5830:160f53ee0870 5831:bd047b71ab37
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 :

http://dive4elements.wald.intevation.org