Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/exports/OutputHelper.java @ 5818:a4ff4167be1e
Request feature info on all layers and show it as html if
the server does not return valid gml.
Non queryable layers produce an error message when the request
fails. This is good enough
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Wed, 24 Apr 2013 17:33:27 +0200 |
parents | 5b8919ef601d |
children |
line wrap: on
line source
package de.intevation.flys.exports; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; 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(); 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) { log.debug("found theme for facet '" + facet + "'"); t.setFacet(facet); t.setIndex(index); } else { log.warn("unable to find theme for facet '" + facet + "'"); } return t; } /** * Inner class to structure/order the themes of a chart. */ private static class ThemeList { private Logger logger = Logger.getLogger(ThemeList.class); protected List<ManagedFacet> themes; public ThemeList(Document output) { themes = new ArrayList<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; } for (int i = 0; i < num; i++) { Element theme = (Element) themeList.item(i); ManagedDomFacet facet = new ManagedDomFacet(theme); themes.add(facet); } Collections.sort(themes); } public ManagedFacet get(int idx) { return themes.get(idx); } public int size() { return themes.size(); } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :