comparison flys-artifacts/src/main/java/de/intevation/flys/exports/OutputHelper.java @ 3295:4fc442f1b4f6

Refactored FLYSArtifactCollection. flys-artifacts/trunk@4976 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Raimund Renkert <raimund.renkert@intevation.de>
date Fri, 13 Jul 2012 09:33:16 +0000
parents
children d76a889bc30d
comparison
equal deleted inserted replaced
3294:5e52202302e5 3295:4fc442f1b4f6
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 }

http://dive4elements.wald.intevation.org