Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/exports/OutputHelper.java @ 3313:1a9ab048573a
Prevent nasty NPE.
flys-artifacts/trunk@5002 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Felix Wolfsteller <felix.wolfsteller@intevation.de> |
---|---|
date | Fri, 13 Jul 2012 19:01:03 +0000 |
parents | 02d5731b43a2 |
children | 8e713e9bb4d7 |
line wrap: on
line source
package de.intevation.flys.exports; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.xpath.XPathConstants; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import de.intevation.artifactdatabase.Backend; import de.intevation.artifactdatabase.Backend.PersistentArtifact; import de.intevation.artifactdatabase.state.ArtifactAndFacet; import de.intevation.artifacts.Artifact; import de.intevation.artifacts.ArtifactDatabase; import de.intevation.artifacts.ArtifactDatabaseException; import de.intevation.artifacts.CallContext; import de.intevation.artifacts.CallMeta; import de.intevation.artifacts.common.ArtifactNamespaceContext; import de.intevation.artifacts.common.utils.ClientProtocolUtils; import de.intevation.artifacts.common.utils.XMLUtils; import de.intevation.flys.artifacts.FLYSArtifact; import de.intevation.flys.artifacts.context.FLYSContext; import de.intevation.flys.artifacts.model.ManagedDomFacet; import de.intevation.flys.artifacts.model.ManagedFacet; import de.intevation.flys.themes.Theme; import de.intevation.flys.themes.ThemeFactory; public class OutputHelper { /** The logger used in this class. */ private static Logger log = Logger.getLogger(OutputHelper.class); protected String identifier; public OutputHelper(String identifier) { this.identifier = identifier; } /** * Creates a concrete output. * * @param generator The OutGenerator that creates the output. * @param outputName The name of the requested output. * @param attributes The collection's attributes for this concrete output * type. * @param context The context object. */ public void doOut( OutGenerator generator, String outName, String facet, Document attributes, CallContext context) throws IOException { boolean debug = log.isDebugEnabled(); if (debug) { log.debug("FLYSArtifactCollection.doOut: " + outName); } ThemeList themeList = new ThemeList(attributes); int size = themeList.size(); if (debug) { log.debug("Output will contain " + size + " elements."); } List<ArtifactAndFacet> dataProviders = doBlackboardPass(themeList, context); try { for (int i = 0; i < size; i++) { ManagedFacet theme = themeList.get(i); if (theme == null) { log.debug("Theme is empty - no output is generated."); continue; } String art = theme.getArtifact(); String facetName = theme.getName(); if (debug) { log.debug("Do output for..."); log.debug("... artifact: " + art); log.debug("... facet: " + facetName); } if (outName.equals("export") && !facetName.equals(facet)) { continue; } // Skip invisible themes. if (theme.getVisible() == 0) { continue; } if (outName.equals("sq_overview")) { generator.doOut( dataProviders.get(i), attributes, theme.getActive() == 1); } else { generator.doOut( dataProviders.get(i), getFacetThemeFromAttribute( art, outName, facetName, theme.getDescription(), theme.getIndex(), context), theme.getActive() == 1); } } } catch (ArtifactDatabaseException ade) { log.error(ade, ade); } } /** * Returns the attribute that belongs to an artifact and facet stored in * this collection. * * @param uuid The Artifact's uuid. * @param outname The name of the requested output. * @param facet The name of the requested facet. * @param context The CallContext. * * @return an attribute in form of a document. */ protected Document getFacetThemeFromAttribute( String uuid, String outName, String facet, String pattern, int index, CallContext context) throws ArtifactDatabaseException { boolean debug = log.isDebugEnabled(); if (debug) { log.debug( "FLYSArtifactCollection.getFacetThemeFromAttribute(facet=" + facet + ", index=" + index + ")"); } ArtifactDatabase db = context.getDatabase(); CallMeta meta = context.getMeta(); FLYSContext flysContext = context instanceof FLYSContext ? (FLYSContext) context : (FLYSContext) context.globalContext(); Document attr = db.getCollectionItemAttribute(identifier, uuid, meta); if (attr == null) { attr = initItemAttribute(uuid, facet, pattern, index, outName, context); if (attr == null) { return null; } } if (debug) { log.debug("Search attribute of collection item: " + uuid); } Node tmp = (Node) XMLUtils.xpath( attr, "/art:attribute", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE); if (tmp == null) { log.warn("No attribute found. Operation failed."); return null; } if (debug) { log.debug("Search theme for facet '" + facet + "' in attribute."); } Map<String, String> vars = new HashMap<String, String>(); vars.put("facet", facet); vars.put("index", String.valueOf(index)); Node theme = (Node) XMLUtils.xpath( tmp, "art:themes/theme[@facet=$facet and @index=$index]", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE, vars); if (theme == null) { log.warn("Could not find the theme in attribute of: " + facet + " " + uuid); Theme t = getThemeForFacet( uuid, facet, pattern, index, outName, context); if (t == null) { log.warn("No theme found for facet: " + facet); return null; } addThemeToAttribute(uuid, attr, t, context); theme = t.toXML().getFirstChild(); } Document doc = XMLUtils.newDocument(); doc.appendChild(doc.importNode(theme, true)); return doc; } /** * Adds the theme of a facet to a CollectionItem's attribute. * * @param uuid The uuid of the artifact. * @param attr The current attribute of an artifact. * @param t The theme to add. * @param context The CallContext. */ protected void addThemeToAttribute( String uuid, Document attr, Theme t, CallContext context) { log.debug("FLYSArtifactCollection.addThemeToAttribute: " + uuid); if (t == null) { log.warn("Theme is empty - cancel adding it to attribute!"); return; } XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( attr, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX); Node tmp = (Node) XMLUtils.xpath( attr, "/art:attribute", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE); if (tmp == null) { tmp = ec.create("attribute"); attr.appendChild(tmp); } Node themes = (Node) XMLUtils.xpath( tmp, "art:themes", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE); if (themes == null) { themes = ec.create("themes"); tmp.appendChild(themes); } themes.appendChild(attr.importNode(t.toXML().getFirstChild(), true)); try { setCollectionItemAttribute(uuid, attr, context); } catch (ArtifactDatabaseException e) { // do nothing log.warn("Cannot set attribute of item: " + uuid); } } /** * Sets the attribute of a CollectionItem specified by <i>uuid</i> to a new * value <i>attr</i>. * * @param uuid The uuid of the CollectionItem. * @param attr The new attribute for the CollectionItem. * @param context The CallContext. */ public void setCollectionItemAttribute( String uuid, Document attr, CallContext context) throws ArtifactDatabaseException { Document doc = ClientProtocolUtils.newSetItemAttributeDocument( uuid, attr); if (doc == null) { log.warn("Cannot set item attribute: No attribute found."); return; } ArtifactDatabase db = context.getDatabase(); CallMeta meta = context.getMeta(); db.setCollectionItemAttribute(identifier, uuid, doc, meta); } /** * Show blackboard (context) to each facet and create a list of * ArtifactAndFacets on the fly (with the same ordering as the passed * ThemeList). * @param themeList ThemeList to create a ArtifactAndFacetList along. * @param context The "Blackboard". */ protected List<ArtifactAndFacet> doBlackboardPass( ThemeList themeList, CallContext context ) { ArrayList<ArtifactAndFacet> dataProviders = new ArrayList<ArtifactAndFacet>(); int size = themeList.size(); try { // Collect all ArtifactAndFacets for blackboard pass. for (int i = 0; i < size; i++) { ManagedFacet theme = themeList.get(i); if (theme == null) { log.warn("A ManagedFacet in ThemeList is null."); continue; } String uuid = theme.getArtifact(); Artifact artifact = getArtifact(uuid, context); FLYSArtifact flys = (FLYSArtifact) artifact; ArtifactAndFacet artifactAndFacet = new ArtifactAndFacet( artifact, flys.getNativeFacet(theme)); // XXX HELP ME PLEASE artifactAndFacet.setFacetDescription(theme.getDescription()); // Show blackboard to facet. artifactAndFacet.register(context); // Add to themes. dataProviders.add(i, artifactAndFacet); } } catch (ArtifactDatabaseException ade) { log.error("ArtifactDatabaseException!", ade); } return dataProviders; } /** * Returns a concrete Artifact of this collection specified by its uuid. * * @param uuid The Artifact's uuid. * @param context The CallContext. * * @return an Artifact. */ protected Artifact getArtifact(String uuid, CallContext context) throws ArtifactDatabaseException { log.debug("FLYSArtifactCollection.getArtifact"); Backend backend = Backend.getInstance(); PersistentArtifact persistent = backend.getArtifact(uuid); return persistent != null ? persistent.getArtifact() : null; } /** * Initializes the attribute of an collection item with the theme of a * specific facet. * * @param uuid The uuid of an artifact. * @param facet The name of a facet. * @param context The CallContext. * * @param the new attribute. */ protected Document initItemAttribute( String uuid, String facet, String pattern, int index, String outName, CallContext context) { boolean debug = log.isDebugEnabled(); if (debug) { log.debug("FLYSArtifactCollection.initItemAttribute"); } Theme t = getThemeForFacet(uuid, facet, pattern, index, outName, context); if (t == null) { log.info("Could not find theme for facet. Cancel initialization."); return null; } Document attr = XMLUtils.newDocument(); addThemeToAttribute(uuid, attr, t, context); if (debug) { log.debug("initItemAttribute for facet " + facet + ": " + XMLUtils.toString(attr)); } return attr; } /** * Returns the theme of a specific facet. * * @param uuid The uuid of an artifact. * @param facet The name of the facet. * @param context The CallContext object. * * @return the desired theme. */ protected Theme getThemeForFacet( String uuid, String facet, String pattern, int index, String outName, CallContext context) { log.info("FLYSArtifactCollection.getThemeForFacet: " + facet); FLYSContext flysContext = context instanceof FLYSContext ? (FLYSContext) context : (FLYSContext) context.globalContext(); // Push artifact in flysContext. ArtifactDatabase db = context.getDatabase(); try { FLYSArtifact artifact = (FLYSArtifact) db.getRawArtifact(uuid); log.debug("Got raw artifact"); flysContext.put(FLYSContext.ARTIFACT_KEY, artifact); } catch (ArtifactDatabaseException dbe) { log.error("Exception caught when trying to get art.", dbe); } Theme t = ThemeFactory.getTheme( flysContext, facet, pattern, outName, "default"); if (t != null) { t.setFacet(facet); t.setIndex(index); } return t; } /** * Inner class to structure/order the themes of a chart. */ private static class ThemeList { private Logger logger = Logger.getLogger(ThemeList.class); protected Map<Integer, ManagedFacet> themes; public ThemeList(Document output) { themes = new HashMap<Integer, ManagedFacet>(); parse(output); } protected void parse(Document output) { NodeList themeList = (NodeList) XMLUtils.xpath( output, "art:output/art:facet", XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); int num = themeList != null ? themeList.getLength() : 0; logger.debug("Output has " + num + " elements."); if (num == 0) { return; } String uri = ArtifactNamespaceContext.NAMESPACE_URI; for (int i = 0; i < num; i++) { Element theme = (Element) themeList.item(i); ManagedDomFacet facet = new ManagedDomFacet(theme); themes.put(Integer.valueOf(facet.getPosition()-1), facet); } } public ManagedFacet get(int idx) { return themes.get(Integer.valueOf(idx)); } public int size() { return themes.size(); } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :