comparison flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java @ 3814:8083f6384023

merged flys-artifacts/pre2.6-2012-01-04
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:56 +0200
parents 0318fa6f0844
children 588db6f2e05a
comparison
equal deleted inserted replaced
1491:2a00f4849738 3814:8083f6384023
1 package de.intevation.flys.collections;
2
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10
11 import javax.xml.xpath.XPathConstants;
12
13 import org.apache.log4j.Logger;
14
15 import org.w3c.dom.Document;
16 import org.w3c.dom.Element;
17 import org.w3c.dom.Node;
18 import org.w3c.dom.NodeList;
19
20 import de.intevation.artifacts.Artifact;
21 import de.intevation.artifacts.ArtifactDatabase;
22 import de.intevation.artifacts.ArtifactDatabaseException;
23 import de.intevation.artifacts.ArtifactNamespaceContext;
24 import de.intevation.artifacts.CallContext;
25 import de.intevation.artifacts.CallMeta;
26
27 import de.intevation.artifacts.common.utils.ClientProtocolUtils;
28 import de.intevation.artifacts.common.utils.XMLUtils;
29
30 import de.intevation.artifactdatabase.Backend;
31 import de.intevation.artifactdatabase.Backend.PersistentArtifact;
32 import de.intevation.artifactdatabase.DefaultArtifactCollection;
33 import de.intevation.artifactdatabase.state.ArtifactAndFacet;
34 import de.intevation.artifactdatabase.state.Output;
35 import de.intevation.artifactdatabase.state.Settings;
36 import de.intevation.artifactdatabase.state.StateEngine;
37
38 import de.intevation.flys.artifacts.context.FLYSContext;
39 import de.intevation.flys.artifacts.FLYSArtifact;
40 import de.intevation.flys.artifacts.model.ManagedFacet;
41 import de.intevation.flys.artifacts.model.ManagedDomFacet;
42 import de.intevation.flys.exports.OutGenerator;
43 import de.intevation.flys.themes.Theme;
44 import de.intevation.flys.themes.ThemeFactory;
45
46 import de.intevation.flys.utils.FLYSUtils;
47
48 /**
49 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
50 */
51 public class FLYSArtifactCollection extends DefaultArtifactCollection {
52 /** The logger used in this class. */
53 private static Logger log = Logger.getLogger(FLYSArtifactCollection.class);
54
55 /** Constant XPath that points to the outputmodes of an artifact. */
56 public static final String XPATH_ARTIFACT_OUTPUTMODES =
57 "/art:result/art:outputmodes";
58
59 public static final String XPATH_ARTIFACT_STATE_DATA =
60 "/art:result/art:ui/art:static/art:state/art:data";
61
62 public static final String XPATH_COLLECTION_ITEMS =
63 "/art:result/art:artifact-collection/art:collection-item";
64
65 public static final String XPATH_OUT_NAME = "/art:action/@art:name";
66
67 public static final String XPATH_OUT_TYPE = "/art:action/@art:type";
68
69 /** Xpath to master artifacts uuid. */
70 public static final String XPATH_MASTER_UUID =
71 "/art:artifact-collection/art:artifact/@art:uuid";
72
73 public static final String XPATH_LOADED_RECOMMENDATIONS =
74 "/art:attribute/art:loaded-recommendations";
75
76
77 /**
78 * Return description Document for this collection.
79 */
80 @Override
81 public Document describe(CallContext context) {
82 log.debug("FLYSArtifactCollection.describe: " + identifier);
83
84 CollectionDescriptionHelper helper = new CollectionDescriptionHelper(
85 getName(), identifier(), getCreationTime(), getTTL(),
86 context);
87
88 ArtifactDatabase db = context.getDatabase();
89
90 Document oldAttrs = getAttribute();
91 AttributeParser parser = new AttributeParser(oldAttrs);
92
93 try {
94 String[] aUUIDs = getArtifactUUIDs(context);
95 CollectionAttribute newAttr = mergeAttributes(
96 db, context, parser, aUUIDs);
97
98 if (checkOutputSettings(newAttr, context)) {
99 saveCollectionAttribute(db, context, newAttr);
100 }
101
102 helper.setAttribute(newAttr);
103
104 // Make it an empty array if null.
105 if (aUUIDs == null) {
106 aUUIDs = new String[] {};
107 }
108
109 for (String uuid: aUUIDs) {
110 helper.addArtifact(uuid);
111 }
112 }
113 catch (ArtifactDatabaseException ade) {
114 log.error("Error while merging attribute documents.", ade);
115
116 helper.setAttribute(parser.getCollectionAttribute());
117 }
118
119 return helper.toXML();
120 }
121
122
123 /**
124 * Merge the current art:outputs nodes with the the outputs provided by the
125 * artifacts in the Collection.
126 *
127 * @param uuids Artifact uuids.
128 */
129 protected CollectionAttribute mergeAttributes(
130 ArtifactDatabase db,
131 CallContext context,
132 AttributeParser oldParser,
133 String[] uuids
134 ) {
135 CollectionAttribute cAttribute =
136 buildOutAttributes(db, context, oldParser, uuids);
137
138 cAttribute.setLoadedRecommendations(
139 getLoadedRecommendations(oldParser.getAttributeDocument()));
140
141 saveCollectionAttribute(db, context, cAttribute);
142
143 return cAttribute;
144 }
145
146
147 /**
148 * @param db The ArtifactDatabase which is required to save the attribute
149 * into.
150 * @param attribute The CollectionAttribute that should be stored in the
151 * database.
152 *
153 * @return true, if the transaction was successful, otherwise false.
154 */
155 protected boolean saveCollectionAttribute(
156 ArtifactDatabase db,
157 CallContext context,
158 CollectionAttribute attribute
159 ) {
160 log.info("Save new CollectionAttribute into database.");
161
162 Document doc = attribute.toXML();
163
164 try {
165 // Save the merged document into database.
166 db.setCollectionAttribute(identifier(), context.getMeta(), doc);
167
168 log.info("Saving CollectionAttribute was successful.");
169
170 return true;
171 }
172 catch (ArtifactDatabaseException adb) {
173 log.error(adb, adb);
174 }
175
176 return false;
177 }
178
179
180 /**
181 * Merge the recommendations which have already been loaded from the old
182 * attribute document into the new attribute document. This is necessary,
183 * because mergeAttributes() only merges the art:outputs nodes - all
184 * other nodes are skiped.
185 */
186 protected Node getLoadedRecommendations(Document oldAttrs) {
187 Element loadedRecoms = (Element) XMLUtils.xpath(
188 oldAttrs,
189 XPATH_LOADED_RECOMMENDATIONS,
190 XPathConstants.NODE,
191 ArtifactNamespaceContext.INSTANCE);
192
193 return loadedRecoms;
194 }
195
196
197 /**
198 * Evaluates the Output settings. If an Output has no Settings set, the
199 * relevant OutGenerator is used to initialize a default Settings object.
200 *
201 * @param attribute The CollectionAttribute.
202 * @param cc The CallContext.
203 *
204 * @return true, if the CollectionAttribute was modified, otherwise false.
205 */
206 protected boolean checkOutputSettings(
207 CollectionAttribute attribute,
208 CallContext cc
209 ) {
210 boolean modified = false;
211
212 Map<String, Output> outputMap = attribute != null
213 ? attribute.getOutputs()
214 : null;
215
216 if (outputMap == null || outputMap.size() == 0) {
217 log.debug("No Output Settings check necessary.");
218 return modified;
219 }
220
221 Set<Map.Entry<String, Output>> entries = outputMap.entrySet();
222
223 for (Map.Entry<String, Output> entry: entries) {
224 String outName = entry.getKey();
225 Output output = entry.getValue();
226
227 Settings settings = output.getSettings();
228
229 if (settings == null) {
230 log.debug("No Settings set for Output '" + outName + "'.");
231 output.setSettings(
232 createInitialOutputSettings(cc, attribute, outName));
233
234 modified = true;
235 }
236 }
237
238 return modified;
239 }
240
241
242 /**
243 * This method uses the the OutGenerator for the specified Output
244 * <i>out</i> to create an initial Settings object.
245 *
246 * @param cc The CallContext object.
247 * @param attr The CollectionAttribute.
248 * @param out The name of the output.
249 *
250 * @return a default Settings object for the specified Output.
251 */
252 protected Settings createInitialOutputSettings(
253 CallContext cc,
254 CollectionAttribute attr,
255 String out
256 ) {
257 OutGenerator outGen = getOutGenerator(cc, out, null);
258
259 if (outGen == null) {
260 return null;
261 }
262
263 // XXX NOTE: the outGen is not able to process its generate() operation,
264 // because it has no OutputStream set!
265 outGen.init(XMLUtils.newDocument(), null, cc);
266 prepareMasterArtifact(outGen, cc);
267
268 try {
269 Document outAttr = getAttribute(cc, attr, out);
270 doOut(outGen, out, out, outAttr, cc);
271 }
272 catch (ArtifactDatabaseException adbe) {
273 log.error(adbe, adbe);
274 }
275 catch (IOException ioe) {
276 log.error(ioe, ioe);
277 }
278
279 return outGen.getSettings();
280 }
281
282
283 @Override
284 public void out(
285 String type,
286 Document format,
287 OutputStream out,
288 CallContext context)
289 throws IOException
290 {
291 long reqBegin = System.currentTimeMillis();
292
293 log.info("FLYSArtifactCollection.out");
294
295 String name = XMLUtils.xpathString(
296 format, XPATH_OUT_NAME, ArtifactNamespaceContext.INSTANCE);
297
298 String subtype = XMLUtils.xpathString(
299 format, XPATH_OUT_TYPE, ArtifactNamespaceContext.INSTANCE);
300
301 log.info("-> Output name = " + name);
302 log.info("-> Output type = " + type);
303 log.info("-> Output subtype = " + subtype);
304
305 OutGenerator generator = null;
306 if (type != null
307 && type.length() > 0
308 && type.indexOf("chartinfo") > 0)
309 {
310 generator = getOutGenerator(context, type, subtype);
311 }
312 else {
313 generator = getOutGenerator(context, name, subtype);
314 }
315
316 if (generator == null) {
317 log.error("There is no generator specified for output: " + name);
318 // TODO Throw an exception.
319
320 return;
321 }
322
323 Document oldAttrs = getAttribute();
324 AttributeParser parser = new AttributeParser(oldAttrs);
325 CollectionAttribute cAttr = parser.getCollectionAttribute();
326
327 Output output = cAttr.getOutput(name);
328 Settings settings = output.getSettings();
329
330 generator.init(format, out, context);
331 generator.setSettings(settings);
332 prepareMasterArtifact(generator, context);
333
334 try {
335 Document attr = getAttribute(context, cAttr, name);
336 doOut(generator, name, subtype, attr, context);
337 generator.generate();
338 }
339 catch (ArtifactDatabaseException adbe) {
340 log.error(adbe, adbe);
341 }
342
343 long duration = System.currentTimeMillis() -reqBegin;
344 log.info("Processing out(" + name + ") took " + duration + " ms.");
345 }
346
347
348 /**
349 * Sets the master Artifact at the given <i>generator</i>.
350 *
351 * @param generator The generator that gets a master Artifact.
352 * @param cc The CallContext.
353 */
354 protected void prepareMasterArtifact(OutGenerator generator, CallContext cc
355 ) {
356 // Get master artifact.
357 FLYSArtifact master = getMasterArtifact(cc);
358 if (master != null) {
359 log.debug("Set master Artifact to uuid: " + master.identifier());
360 generator.setMasterArtifact(master);
361 }
362 else {
363 log.warn("Could not set master artifact.");
364 }
365 }
366
367
368 /**
369 * Creates the concrete output.
370 *
371 * @param generator The OutGenerator that creates the output.
372 * @param outputName The name of the requested output.
373 * @param attributes The collection's attributes for this concrete output
374 * type.
375 * @param context The context object.
376 */
377 protected void doOut(
378 OutGenerator generator,
379 String outName,
380 String facet,
381 Document attributes,
382 CallContext context)
383 throws IOException
384 {
385 log.info("FLYSArtifactCollection.doOut: " + outName);
386
387 ThemeList themeList = new ThemeList(attributes);
388
389 int size = themeList.size();
390 log.debug("Output will contain " + size + " elements.");
391
392 List<ArtifactAndFacet> dataProviders =
393 doBlackboardPass(themeList, context);
394
395 try {
396 for (int i = 0; i < size; i++) {
397 ManagedFacet theme = themeList.get(i);
398
399 if (theme == null) {
400 log.debug("Theme is empty - no output is generated.");
401 continue;
402 }
403
404 String art = theme.getArtifact();
405 String facetName = theme.getName();
406
407 if (log.isDebugEnabled()) {
408 log.debug("Do output for...");
409 log.debug("... artifact: " + art);
410 log.debug("... facet: " + facetName);
411 }
412
413 if (outName.equals("export") && !facetName.equals(facet)) {
414 continue;
415 }
416
417 // Skip invisible themes.
418 if (theme.getVisible() == 0) {
419 continue;
420 }
421
422 generator.doOut(
423 dataProviders.get(i),
424 getFacetThemeFromAttribute(
425 art,
426 outName,
427 facetName,
428 theme.getDescription(),
429 theme.getIndex(),
430 context),
431 theme.getActive() == 1);
432 }
433 }
434 catch (ArtifactDatabaseException ade) {
435 log.error(ade, ade);
436 }
437 }
438
439
440 /**
441 * Show blackboard (context) to each facet and create a list of
442 * ArtifactAndFacets on the fly (with the same ordering as the passed
443 * ThemeList).
444 * @param themeList ThemeList to create a ArtifactAndFacetList along.
445 * @param contect The "Blackboard".
446 */
447 protected List<ArtifactAndFacet> doBlackboardPass(
448 ThemeList themeList, CallContext context
449 ) {
450 ArrayList<ArtifactAndFacet> dataProviders =
451 new ArrayList<ArtifactAndFacet>();
452 int size = themeList.size();
453
454 try {
455 // Collect all ArtifactAndFacets for blackboard pass.
456 for (int i = 0; i < size; i++) {
457 ManagedFacet theme = themeList.get(i);
458 String uuid = theme.getArtifact();
459 Artifact artifact = getArtifact(uuid, context);
460 FLYSArtifact flys = (FLYSArtifact) artifact;
461 ArtifactAndFacet artifactAndFacet = new ArtifactAndFacet(artifact,
462 flys.getNativeFacet(theme));
463
464 // Show blackboard to facet.
465 artifactAndFacet.register(context);
466
467 // Add to themes.
468 dataProviders.add(i, artifactAndFacet);
469 }
470 }
471 catch (ArtifactDatabaseException ade) {
472 log.error("ArtifactDatabaseException!", ade);
473 }
474
475 return dataProviders;
476 }
477
478
479 /**
480 * @return masterartifact or null if exception/not found.
481 */
482 protected FLYSArtifact getMasterArtifact(CallContext context)
483 {
484 try {
485 ArtifactDatabase db = context.getDatabase();
486 CallMeta callMeta = context.getMeta();
487 Document document = db.getCollectionsMasterArtifact(
488 identifier(), callMeta);
489
490 String masterUUID = XMLUtils.xpathString(
491 document, XPATH_MASTER_UUID, ArtifactNamespaceContext.INSTANCE);
492 FLYSArtifact masterArtifact =
493 (FLYSArtifact) getArtifact(masterUUID, context);
494 return masterArtifact;
495 }
496 catch (ArtifactDatabaseException ade) {
497 log.error(ade, ade);
498 }
499 return null;
500 }
501
502
503 /**
504 * Return merged output document.
505 * @param uuids List of artifact uuids.
506 */
507 protected CollectionAttribute buildOutAttributes(
508 ArtifactDatabase db,
509 CallContext context,
510 AttributeParser aParser,
511 String[] uuids)
512 {
513 Document doc = XMLUtils.newDocument();
514
515 FLYSContext flysContext = FLYSUtils.getFlysContext(context);
516 StateEngine engine = (StateEngine) flysContext.get(
517 FLYSContext.STATE_ENGINE_KEY);
518
519 FLYSArtifact masterArtifact = getMasterArtifact(context);
520
521 XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
522 doc,
523 ArtifactNamespaceContext.NAMESPACE_URI,
524 ArtifactNamespaceContext.NAMESPACE_PREFIX);
525
526 OutputParser oParser = new OutputParser(db, context);
527
528 if (uuids != null) {
529 for (String uuid: uuids) {
530 try {
531 oParser.parse(uuid);
532 }
533 catch (ArtifactDatabaseException ade) {
534 log.warn(ade, ade);
535 }
536 }
537 }
538
539 aParser.parse();
540
541 return new AttributeWriter(
542 db,
543 aParser.getCollectionAttribute(),
544 aParser.getOuts(),
545 aParser.getFacets(),
546 oParser.getOuts(),
547 oParser.getFacets(),
548 engine.getCompatibleFacets(masterArtifact.getStateHistoryIds())
549 ).write();
550 }
551
552
553 /**
554 * Returns the "attribute" (part of description document) for a specific
555 * output type.
556 *
557 * @param context The CallContext object.
558 * @param cAttr The CollectionAttribute.
559 * @param output The name of the desired output type.
560 *
561 * @return the attribute for the desired output type.
562 */
563 protected Document getAttribute(
564 CallContext context,
565 CollectionAttribute cAttr,
566 String output)
567 throws ArtifactDatabaseException
568 {
569 Document attr = cAttr.toXML();
570
571 Node out = (Node) XMLUtils.xpath(
572 attr,
573 "art:attribute/art:outputs/art:output[@name='" + output + "']",
574 XPathConstants.NODE,
575 ArtifactNamespaceContext.INSTANCE);
576
577
578 if (out != null) {
579 Document o = XMLUtils.newDocument();
580
581 o.appendChild(o.importNode(out, true));
582
583 return o;
584 }
585
586 return null;
587 }
588
589
590 /**
591 * This method returns the list of artifact UUIDs that this collections
592 * contains.
593 *
594 * @param context The CallContext that is necessary to get information about
595 * the ArtifactDatabase.
596 *
597 * @return a list of uuids.
598 */
599 protected String[] getArtifactUUIDs(CallContext context)
600 throws ArtifactDatabaseException
601 {
602 log.debug("FLYSArtifactCollection.getArtifactUUIDs");
603
604 ArtifactDatabase db = context.getDatabase();
605 CallMeta meta = context.getMeta();
606
607 Document itemList = db.listCollectionArtifacts(identifier(), meta);
608 NodeList items = (NodeList) XMLUtils.xpath(
609 itemList,
610 XPATH_COLLECTION_ITEMS,
611 XPathConstants.NODESET,
612 ArtifactNamespaceContext.INSTANCE);
613
614 if (items == null || items.getLength() == 0) {
615 log.debug("No artifacts found in this collection.");
616 return null;
617 }
618
619 int num = items.getLength();
620
621 List<String> uuids = new ArrayList<String>(num);
622
623 for (int i = 0; i < num; i++) {
624 String uuid = XMLUtils.xpathString(
625 items.item(i),
626 "@art:uuid",
627 ArtifactNamespaceContext.INSTANCE);
628
629 if (uuid != null && uuid.trim().length() != 0) {
630 uuids.add(uuid);
631 }
632 }
633
634 return (String[]) uuids.toArray(new String[uuids.size()]);
635 }
636
637
638 /**
639 * Returns a concrete Artifact of this collection specified by its uuid.
640 *
641 * @param uuid The Artifact's uuid.
642 * @param context The CallContext.
643 *
644 * @return an Artifact.
645 */
646 protected Artifact getArtifact(String uuid, CallContext context)
647 throws ArtifactDatabaseException
648 {
649 log.debug("FLYSArtifactCollection.getArtifact");
650
651 Backend backend = Backend.getInstance();
652 PersistentArtifact persistent = backend.getArtifact(uuid);
653
654 return persistent != null ? persistent.getArtifact() : null;
655 }
656
657
658 /**
659 * Returns the attribute that belongs to an artifact and facet stored in
660 * this collection.
661 *
662 * @param uuid The Artifact's uuid.
663 * @param outname The name of the requested output.
664 * @param facet The name of the requested facet.
665 * @param context The CallContext.
666 *
667 * @return an attribute in form of a document.
668 */
669 protected Document getFacetThemeFromAttribute(
670 String uuid,
671 String outName,
672 String facet,
673 String pattern,
674 int index,
675 CallContext context)
676 throws ArtifactDatabaseException
677 {
678 log.debug("FLYSArtifactCollection.getFacetThemeFromAttribute");
679
680 ArtifactDatabase db = context.getDatabase();
681 CallMeta meta = context.getMeta();
682
683 FLYSContext flysContext = context instanceof FLYSContext
684 ? (FLYSContext) context
685 : (FLYSContext) context.globalContext();
686
687 Document attr = db.getCollectionItemAttribute(identifier(), uuid, meta);
688
689 if (attr == null) {
690 attr = initItemAttribute(uuid, facet, pattern, index, outName, context);
691
692 if (attr == null) {
693 return null;
694 }
695 }
696
697 log.debug("Search attribute of collection item: " + uuid);
698
699 Node tmp = (Node) XMLUtils.xpath(
700 attr,
701 "/art:attribute",
702 XPathConstants.NODE,
703 ArtifactNamespaceContext.INSTANCE);
704
705 if (tmp == null) {
706 log.warn("No attribute found. Operation failed.");
707 return null;
708 }
709
710 log.debug("Search theme for facet '" + facet + "' in attribute.");
711
712 Node theme = (Node) XMLUtils.xpath(
713 tmp,
714 "art:themes/theme[@facet='" + facet +
715 "' and @index='" + String.valueOf(index) + "']",
716 XPathConstants.NODE,
717 ArtifactNamespaceContext.INSTANCE);
718
719 if (theme == null) {
720 log.warn("Could not find the theme in attribute of: " + uuid);
721
722 Theme t = getThemeForFacet(
723 uuid, facet, pattern, index, outName, context);
724
725 if (t == null) {
726 log.warn("No theme found for facet: " + facet);
727 return null;
728 }
729
730 addThemeToAttribute(uuid, attr, t, context);
731 theme = t.toXML().getFirstChild();
732 }
733
734 Document doc = XMLUtils.newDocument();
735 doc.appendChild(doc.importNode(theme, true));
736
737 return doc;
738 }
739
740
741 /**
742 * Adds the theme of a facet to a CollectionItem's attribute.
743 *
744 * @param uuid The uuid of the artifact.
745 * @param attr The current attribute of an artifact.
746 * @param t The theme to add.
747 * @param context The CallContext.
748 */
749 protected void addThemeToAttribute(
750 String uuid,
751 Document attr,
752 Theme t,
753 CallContext context)
754 {
755 log.debug("FLYSArtifactCollection.addThemeToAttribute: " + uuid);
756
757 if (t == null) {
758 log.warn("Theme is empty - cancel adding it to attribute!");
759 return;
760 }
761
762 XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
763 attr,
764 ArtifactNamespaceContext.NAMESPACE_URI,
765 ArtifactNamespaceContext.NAMESPACE_PREFIX);
766
767 Node tmp = (Node) XMLUtils.xpath(
768 attr,
769 "/art:attribute",
770 XPathConstants.NODE,
771 ArtifactNamespaceContext.INSTANCE);
772
773 if (tmp == null) {
774 tmp = ec.create("attribute");
775 attr.appendChild(tmp);
776 }
777
778 Node themes = (Node) XMLUtils.xpath(
779 tmp,
780 "art:themes",
781 XPathConstants.NODE,
782 ArtifactNamespaceContext.INSTANCE);
783
784 if (themes == null) {
785 themes = ec.create("themes");
786 tmp.appendChild(themes);
787 }
788
789 themes.appendChild(attr.importNode(t.toXML().getFirstChild(), true));
790
791 try {
792 setCollectionItemAttribute(uuid, attr, context);
793
794 log.debug("Successfully added theme to item attribute.");
795 }
796 catch (ArtifactDatabaseException e) {
797 // do nothing
798 log.warn("Cannot set attribute of item: " + uuid);
799 }
800 }
801
802
803 /**
804 * Initializes the attribute of an collection item with the theme of a
805 * specific facet.
806 *
807 * @param uuid The uuid of an artifact.
808 * @param facet The name of a facet.
809 * @param context The CallContext.
810 *
811 * @param the new attribute.
812 */
813 protected Document initItemAttribute(
814 String uuid,
815 String facet,
816 String pattern,
817 int index,
818 String outName,
819 CallContext context)
820 {
821 log.info("FLYSArtifactCollection.initItemAttribute");
822
823 Theme t = getThemeForFacet(uuid, facet, pattern, index, outName, context);
824
825 if (t == null) {
826 log.info("Could not find theme for facet. Cancel initialization.");
827 return null;
828 }
829
830 Document attr = XMLUtils.newDocument();
831
832 addThemeToAttribute(uuid, attr, t, context);
833
834 return attr;
835 }
836
837
838 /**
839 * Sets the attribute of a CollectionItem specified by <i>uuid</i> to a new
840 * value <i>attr</i>.
841 *
842 * @param uuid The uuid of the CollectionItem.
843 * @param attr The new attribute for the CollectionItem.
844 * @param context The CallContext.
845 */
846 public void setCollectionItemAttribute(
847 String uuid,
848 Document attr,
849 CallContext context)
850 throws ArtifactDatabaseException
851 {
852 Document doc = ClientProtocolUtils.newSetItemAttributeDocument(
853 uuid,
854 attr);
855
856 if (doc == null) {
857 log.warn("Cannot set item attribute: No attribute found.");
858 return;
859 }
860
861 ArtifactDatabase db = context.getDatabase();
862 CallMeta meta = context.getMeta();
863
864 db.setCollectionItemAttribute(identifier(), uuid, doc, meta);
865 }
866
867
868 /**
869 * Returns the theme of a specific facet.
870 *
871 * @param uuid The uuid of an artifact.
872 * @param facet The name of the facet.
873 * @param context The CallContext object.
874 *
875 * @return the desired theme.
876 */
877 protected Theme getThemeForFacet(
878 String uuid,
879 String facet,
880 String pattern,
881 int index,
882 String outName,
883 CallContext context)
884 {
885 log.info("FLYSArtifactCollection.getThemeForFacet: " + facet);
886
887 FLYSContext flysContext = context instanceof FLYSContext
888 ? (FLYSContext) context
889 : (FLYSContext) context.globalContext();
890
891 // Push artifact in flysContext.
892 ArtifactDatabase db = context.getDatabase();
893 try {
894 FLYSArtifact artifact = (FLYSArtifact) db.getRawArtifact(uuid);
895 log.debug("Got raw artifact");
896 flysContext.put(flysContext.ARTIFACT_KEY, artifact);
897 }
898 catch (ArtifactDatabaseException dbe) {
899 log.error("Exception caught when trying to get art.", dbe);
900 }
901
902 Theme t = ThemeFactory.getTheme(flysContext, facet, pattern, outName);
903
904 if (t != null) {
905 t.setFacet(facet);
906 t.setIndex(index);
907 }
908
909 return t;
910 }
911
912
913 /**
914 * Returns the OutGenerator for a specified <i>type</i>.
915 *
916 * @param name The name of the output type.
917 * @param type Defines the type of the desired OutGenerator.
918 *
919 * @return Instance of an OutGenerator for specified <i>type</i>.
920 */
921 protected OutGenerator getOutGenerator(
922 CallContext context,
923 String name,
924 String type)
925 {
926 log.debug("Search OutGenerator for Output '" + name + "'");
927
928 FLYSContext flysContext = context instanceof FLYSContext
929 ? (FLYSContext) context
930 : (FLYSContext) context.globalContext();
931
932 Map<String, Class> generators = (Map<String, Class>)
933 flysContext.get(FLYSContext.OUTGENERATORS_KEY);
934
935 if (generators == null) {
936 log.error("No output generators found in the running application!");
937 return null;
938 }
939
940 Class clazz = generators.get(name);
941
942 try {
943 return clazz != null ? (OutGenerator) clazz.newInstance() : null;
944 }
945 catch (InstantiationException ie) {
946 log.error(ie, ie);
947 }
948 catch (IllegalAccessException iae) {
949 log.error(iae, iae);
950 }
951
952 return null;
953 }
954
955
956 /**
957 * Inner class to structure/order the themes of a chart.
958 */
959 private static class ThemeList {
960 private Logger logger = Logger.getLogger(ThemeList.class);
961 protected Map<Integer, ManagedFacet> themes;
962
963 public ThemeList(Document output) {
964 themes = new HashMap<Integer, ManagedFacet>();
965 parse(output);
966 }
967
968 protected void parse(Document output) {
969 NodeList themeList = (NodeList) XMLUtils.xpath(
970 output,
971 "art:output/art:facet",
972 XPathConstants.NODESET,
973 ArtifactNamespaceContext.INSTANCE);
974
975 int num = themeList != null ? themeList.getLength() : 0;
976
977 logger.debug("Output has " + num + " elements.");
978
979 if (num == 0) {
980 return;
981 }
982
983 String uri = ArtifactNamespaceContext.NAMESPACE_URI;
984
985 for (int i = 0; i < num; i++) {
986 Element theme = (Element) themeList.item(i);
987
988 ManagedDomFacet facet = new ManagedDomFacet(theme);
989 themes.put(Integer.valueOf(facet.getPosition()-1), facet);
990 }
991 }
992
993 public ManagedFacet get(int idx) {
994 return themes.get(Integer.valueOf(idx));
995 }
996
997 public int size() {
998 return themes.size();
999 }
1000 }
1001 }
1002 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org