teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.exports.sq; raimund@3296: raimund@3296: import java.awt.image.BufferedImage; raimund@3296: import java.io.IOException; raimund@3296: import java.io.OutputStream; raimund@3296: import java.util.ArrayList; raimund@3296: import java.util.HashMap; raimund@3296: import java.util.List; raimund@3296: import java.util.Map; raimund@3296: raimund@3296: import javax.imageio.ImageIO; raimund@3296: import javax.xml.xpath.XPathConstants; raimund@3296: raimund@3296: import org.apache.log4j.Logger; raimund@3296: import org.jfree.chart.ChartRenderingInfo; raimund@3296: import org.jfree.chart.JFreeChart; raimund@3296: import org.w3c.dom.Document; raimund@3296: import org.w3c.dom.Element; raimund@3296: import org.w3c.dom.Node; raimund@3296: teichmann@5831: import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; teichmann@5831: import org.dive4elements.artifactdatabase.state.Settings; teichmann@5831: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.ArtifactDatabaseException; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.artifacts.common.ArtifactNamespaceContext; teichmann@5831: import org.dive4elements.artifacts.common.utils.XMLUtils; teichmann@5866: import org.dive4elements.river.artifacts.context.RiverContext; teichmann@5867: import org.dive4elements.river.collections.D4EArtifactCollection; aheinecke@7242: import org.dive4elements.river.exports.ChartGenerator2; teichmann@5831: import org.dive4elements.river.exports.OutGenerator; teichmann@5831: import org.dive4elements.river.exports.OutputHelper; teichmann@6905: import org.dive4elements.river.themes.ThemeDocument; raimund@3296: raimund@3296: public class SQOverviewGenerator raimund@3296: implements OutGenerator raimund@3296: { raimund@3296: private static Logger logger = Logger.getLogger(SQOverviewGenerator.class); raimund@3296: raimund@3296: public static final String XPATH_CHART_SIZE = raimund@3296: "/art:action/art:attributes/art:size"; raimund@3296: teichmann@5867: protected D4EArtifactCollection collection; ingo@3422: raimund@3296: protected Artifact master; raimund@3296: raimund@3296: protected Settings settings; raimund@3296: raimund@3296: protected Document request; raimund@3296: raimund@3296: protected OutputStream out; raimund@3296: raimund@3296: protected CallContext context; raimund@3296: raimund@3296: protected List charts; raimund@3296: teichmann@7077: protected String outName; teichmann@7077: teichmann@7037: @Override teichmann@7087: public void setup(Object config) { teichmann@7037: logger.debug("SQOverviewGenerator.setup"); teichmann@7037: } teichmann@7037: raimund@3296: /** raimund@3296: * Produce output. raimund@3296: * @param artifactAndFacet current facet and artifact. raimund@3296: * @param attr theme for facet raimund@3296: */ ingo@3425: @Override raimund@3296: public void doOut( raimund@3296: ArtifactAndFacet artifactAndFacet, teichmann@6905: ThemeDocument attr, raimund@3296: boolean visible raimund@3296: ) { raimund@3296: logger.debug("doOut()"); raimund@3296: teichmann@7077: // TODO: Why not using outName for this. teichmann@7077: raimund@3296: String name = artifactAndFacet.getData(context).toString(); raimund@3296: if(name != null) { raimund@3296: logger.debug("name: " + name); aheinecke@7242: ChartGenerator2 g = aheinecke@7242: (ChartGenerator2)RiverContext.getOutGenerator( raimund@3296: context, raimund@3296: name, raimund@3296: null); aheinecke@7243: /* Make sure master is also set in those */ aheinecke@7243: g.setMasterArtifact(master); ingo@3422: raimund@3296: if (g == null) { raimund@3296: logger.debug("generator is null."); raimund@3296: return; raimund@3296: } ingo@3422: raimund@3296: OutputHelper helper = new OutputHelper(master.identifier()); ingo@3422: Document collectionAttribute = collection.getAttribute(); ingo@3422: raimund@3296: try { ingo@3422: Document cAttr = getAttribute(context, collectionAttribute, name); teichmann@7077: g.init(name, request, out, context); ingo@3422: ingo@3422: helper.doOut(g, name, name, cAttr, context); ingo@3425: JFreeChart chart = g.generateChart(); ingo@3425: chart.removeLegend(); ingo@3425: charts.add(chart); ingo@3422: } ingo@3422: catch (IOException e) { raimund@3296: logger.warn(e); ingo@3422: } ingo@3422: catch (ArtifactDatabaseException e) { raimund@3296: logger.warn(e); raimund@3296: } raimund@3296: } raimund@3296: } raimund@3296: ingo@3425: @Override teichmann@7077: public void init(String outName, Document request, OutputStream out, CallContext context) { teichmann@7077: this.outName = outName; raimund@3296: this.request = request; raimund@3296: this.out = out; raimund@3296: this.context = context; raimund@3296: charts = new ArrayList(); raimund@3296: } raimund@3296: ingo@3425: @Override raimund@3296: public void setMasterArtifact(Artifact master) { raimund@3296: this.master = master; raimund@3296: } raimund@3296: ingo@3425: @Override teichmann@5867: public void setCollection(D4EArtifactCollection collection) { ingo@3422: this.collection = collection; ingo@3422: } ingo@3422: ingo@3425: @Override raimund@3296: public void generate() throws IOException { raimund@3296: logger.debug("SQOverviewGenerator.generate"); raimund@3296: raimund@3296: int[] size = getSize(); raimund@3296: raimund@3296: if (size == null) { raimund@3296: size = new int[] {400, 600}; raimund@3296: } raimund@3296: BufferedImage result = raimund@3296: new BufferedImage(size[0], size[1], BufferedImage.TYPE_INT_RGB); raimund@3296: for (int i = 0; i < charts.size(); i++) { raimund@3296: logger.debug("index: " + i); raimund@3296: JFreeChart chart = charts.get(i); raimund@3296: ChartRenderingInfo info = new ChartRenderingInfo(); raimund@3296: BufferedImage img = raimund@3296: chart.createBufferedImage(size[0]/2, size[1]/3, info); raimund@3296: int horPos = 0; raimund@3296: int vertPos = 0; raimund@3296: if (i % 2 == 1) { raimund@3296: horPos = size[0]/2; raimund@3296: } raimund@3296: if (i > 1) { raimund@3296: vertPos = (size[1] / 3) * (i / 2); raimund@3296: } teichmann@7077: // TODO: Dispose Graphics object! raimund@3296: result.createGraphics().drawImage(img, horPos, vertPos, null); raimund@3296: } raimund@3296: ImageIO.write(result, "png", out); raimund@3296: } raimund@3296: ingo@3425: @Override raimund@3296: public void setSettings(Settings settings) { raimund@3296: this.settings = settings; raimund@3296: } raimund@3296: ingo@3425: @Override raimund@3296: public Settings getSettings() { raimund@3296: return this.settings; raimund@3296: } raimund@3296: raimund@3296: raimund@3296: /** raimund@3296: * Returns the "attribute" (part of description document) for a specific raimund@3296: * output type. raimund@3296: * raimund@3296: * @param context The CallContext object. ingo@3422: * @param attr The xml attribute saved at the collection. raimund@3296: * @param output The name of the desired output type. raimund@3296: * raimund@3296: * @return the attribute for the desired output type. raimund@3296: */ raimund@3296: protected Document getAttribute( ingo@3422: CallContext context, ingo@3422: Document attr, ingo@3422: String output) raimund@3296: throws ArtifactDatabaseException raimund@3296: { ingo@3422: logger.debug("find specific XML node for Output: " + output); raimund@3296: raimund@3296: Map vars = new HashMap(); raimund@3296: vars.put("output", output); raimund@3296: raimund@3296: Node out = (Node) XMLUtils.xpath( raimund@3296: attr, raimund@3296: "art:attribute/art:outputs/art:output[@name=$output]", raimund@3296: XPathConstants.NODE, raimund@3296: ArtifactNamespaceContext.INSTANCE, raimund@3296: vars); raimund@3296: raimund@3296: if (out != null) { raimund@3296: Document o = XMLUtils.newDocument(); raimund@3296: o.appendChild(o.importNode(out, true)); raimund@3296: raimund@3296: return o; raimund@3296: } raimund@3296: raimund@3296: return null; raimund@3296: } raimund@3296: raimund@3296: raimund@3296: /** raimund@3296: * Returns the size of a chart export as array which has been specified by raimund@3296: * the incoming request document. raimund@3296: * raimund@3296: * @return the size of a chart as [width, height] or null if no width or raimund@3296: * height are given in the request document. raimund@3296: */ raimund@3296: protected int[] getSize() { raimund@3296: int[] size = new int[2]; raimund@3296: raimund@3296: Element sizeEl = (Element)XMLUtils.xpath( raimund@3296: request, raimund@3296: XPATH_CHART_SIZE, raimund@3296: XPathConstants.NODE, raimund@3296: ArtifactNamespaceContext.INSTANCE); raimund@3296: raimund@3296: if (sizeEl != null) { raimund@3296: String uri = ArtifactNamespaceContext.NAMESPACE_URI; raimund@3296: raimund@3296: String w = sizeEl.getAttributeNS(uri, "width"); raimund@3296: String h = sizeEl.getAttributeNS(uri, "height"); raimund@3296: raimund@3296: if (w.length() > 0 && h.length() > 0) { raimund@3296: try { raimund@3296: size[0] = Integer.parseInt(w); raimund@3296: size[1] = Integer.parseInt(h); raimund@3296: } raimund@3296: catch (NumberFormatException nfe) { raimund@3296: logger.warn("Wrong values for chart width/height."); raimund@3296: } raimund@3296: } raimund@3296: } raimund@3296: raimund@3296: return size[0] > 0 && size[1] > 0 ? size : null; raimund@3296: } raimund@3296: } sascha@3304: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :