ingo@348: package de.intevation.flys.exports;
ingo@348:
ingo@348: import java.io.IOException;
ingo@348: import java.io.OutputStream;
ingo@1645: import java.util.Locale;
ingo@348:
ingo@423: import javax.xml.xpath.XPathConstants;
ingo@423:
ingo@348: import org.apache.log4j.Logger;
ingo@348:
ingo@348: import org.w3c.dom.Document;
sascha@719: import org.w3c.dom.Element;
ingo@348:
ingo@652: import org.jfree.data.Range;
ingo@652:
ingo@348: import de.intevation.artifacts.Artifact;
ingo@412: import de.intevation.artifacts.CallContext;
ingo@1645: import de.intevation.artifacts.CallMeta;
ingo@1645: import de.intevation.artifacts.PreferredLocale;
ingo@412:
ingo@423: import de.intevation.artifacts.ArtifactNamespaceContext;
ingo@423: import de.intevation.artifacts.common.utils.XMLUtils;
ingo@423:
ingo@1979: import de.intevation.artifactdatabase.state.ArtifactAndFacet;
ingo@1979: import de.intevation.artifactdatabase.state.Settings;
ingo@1979:
ingo@412: import de.intevation.flys.model.River;
ingo@412:
sascha@1055: import de.intevation.flys.artifacts.WINFOArtifact;
sascha@1055:
ingo@408: import de.intevation.flys.artifacts.resources.Resources;
ingo@1095: import de.intevation.flys.utils.FLYSUtils;
ingo@348:
ingo@348:
ingo@348: /**
ingo@348: * The base class for chart creation. It should provide some basic things that
ingo@348: * equal in all chart types.
ingo@348: *
ingo@348: * @author Ingo Weinzierl
ingo@348: */
ingo@348: public abstract class ChartGenerator implements OutGenerator {
ingo@348:
ingo@348: private static Logger logger = Logger.getLogger(ChartGenerator.class);
ingo@348:
felix@1104: /** The default chart width, if no other width is set. */
ingo@423: public static final int DEFAULT_CHART_WIDTH = 600;
ingo@423:
ingo@423: /** The default chart height, if no other height is set.*/
ingo@423: public static final int DEFAULT_CHART_HEIGHT = 400;
ingo@423:
ingo@1735: /** The default chart format, if no other height is set.*/
ingo@1735: public static final String DEFAULT_CHART_FORMAT = "png";
ingo@1735:
ingo@423: /** The XPath that points to the chart size of the incoming request
ingo@423: * document.*/
ingo@423: public static final String XPATH_CHART_SIZE =
ingo@423: "/art:action/art:attributes/art:size";
ingo@423:
ingo@1735: public static final String XPATH_CHART_FORMAT =
ingo@1735: "/art:action/art:attributes/art:format/@art:value";
ingo@1735:
ingo@652: public static final String XPATH_CHART_X_RANGE =
ingo@652: "/art:action/art:attributes/art:xrange";
ingo@652:
ingo@652: public static final String XPATH_CHART_Y_RANGE =
ingo@652: "/art:action/art:attributes/art:yrange";
ingo@652:
ingo@423:
ingo@348: /** The document of the incoming out() request.*/
ingo@348: protected Document request;
ingo@348:
ingo@348: /** The output stream where the data should be written to.*/
ingo@348: protected OutputStream out;
ingo@348:
ingo@348: /** The CallContext object.*/
ingo@348: protected CallContext context;
ingo@348:
ingo@412: /** The artifact that is used to decorate the chart with meta information.*/
ingo@412: protected Artifact master;
ingo@412:
ingo@348:
ingo@348: public void init(Document request, OutputStream out, CallContext context) {
ingo@348: logger.debug("ChartGenerator.init");
ingo@348:
ingo@348: this.request = request;
ingo@348: this.out = out;
ingo@348: this.context = context;
ingo@348: }
ingo@348:
ingo@348:
ingo@412: public void setMasterArtifact(Artifact master) {
ingo@412: this.master = master;
ingo@412: }
ingo@412:
ingo@412:
ingo@1645: protected Locale getLocale() {
ingo@1645: CallMeta meta = context.getMeta();
ingo@1645: PreferredLocale[] prefs = meta.getLanguages();
ingo@1645:
ingo@1645: int len = prefs != null ? prefs.length : 0;
ingo@1645:
ingo@1645: Locale[] locales = new Locale[len];
ingo@1645:
ingo@1645: for (int i = 0; i < len; i++) {
ingo@1645: locales[i] = prefs[i].getLocale();
ingo@1645: }
ingo@1645:
ingo@1645: return meta.getPreferredLocale(locales);
ingo@1645: }
ingo@1645:
ingo@1645:
ingo@408: protected String msg(String key, String def) {
ingo@408: return Resources.getMsg(context.getMeta(), key, def);
ingo@408: }
ingo@408:
ingo@408:
ingo@412: protected String msg(String key, String def, Object[] args) {
ingo@412: return Resources.getMsg(context.getMeta(), key, def, args);
ingo@412: }
ingo@412:
ingo@412:
ingo@412: protected String getRiverName() {
sascha@1055: WINFOArtifact flys = (WINFOArtifact) master;
ingo@412:
felix@1104: River river = FLYSUtils.getRiver(flys);
felix@1104: return (river != null) ? river.getName() : "";
ingo@412: }
ingo@412:
ingo@412:
ingo@412: protected double[] getRange() {
sascha@1055: WINFOArtifact flys = (WINFOArtifact) master;
ingo@412:
ingo@1095: return FLYSUtils.getKmRange(flys);
ingo@412: }
ingo@412:
ingo@412:
ingo@423: /**
ingo@423: * Returns the size of a chart export as array which has been specified by
ingo@423: * the incoming request document.
ingo@423: *
ingo@423: * @return the size of a chart as [width, height] or the result of
ingo@423: * getDefaultSize() if no width or height are given in the request document.
ingo@423: */
ingo@423: protected int[] getSize() {
ingo@423: int[] size = new int[2];
ingo@423:
sascha@719: Element sizeEl = (Element)XMLUtils.xpath(
ingo@423: request,
ingo@423: XPATH_CHART_SIZE,
ingo@423: XPathConstants.NODE,
ingo@423: ArtifactNamespaceContext.INSTANCE);
ingo@423:
ingo@423: if (sizeEl != null) {
sascha@719: String uri = ArtifactNamespaceContext.NAMESPACE_URI;
ingo@423:
sascha@719: String w = sizeEl.getAttributeNS(uri, "width");
sascha@719: String h = sizeEl.getAttributeNS(uri, "height");
ingo@423:
sascha@719: if (w.length() > 0 && h.length() > 0) {
ingo@423: try {
ingo@423: size[0] = Integer.parseInt(w);
ingo@423: size[1] = Integer.parseInt(h);
ingo@423: }
ingo@423: catch (NumberFormatException nfe) {
ingo@423: logger.warn("Wrong values for chart width/height.");
ingo@423: }
ingo@423: }
ingo@423: }
ingo@423:
ingo@423: return size[0] > 0 && size[1] > 0 ? size : getDefaultSize();
ingo@423: }
ingo@423:
ingo@423:
ingo@1735: protected String getFormat() {
ingo@1735: String format = (String) XMLUtils.xpath(
ingo@1735: request,
ingo@1735: XPATH_CHART_FORMAT,
ingo@1735: XPathConstants.STRING,
ingo@1735: ArtifactNamespaceContext.INSTANCE);
ingo@1735:
ingo@1735: return format == null || format.length() == 0
ingo@1735: ? DEFAULT_CHART_FORMAT
ingo@1735: : format;
ingo@1735: }
ingo@1735:
ingo@1735:
felix@1944: /**
felix@1944: * Get Range of Domain ("X"-) Axis from request.
felix@1944: */
ingo@652: protected Range getDomainAxisRange() {
sascha@719: Element xrange = (Element)XMLUtils.xpath(
ingo@652: request,
ingo@652: XPATH_CHART_X_RANGE,
ingo@652: XPathConstants.NODE,
ingo@652: ArtifactNamespaceContext.INSTANCE);
ingo@652:
ingo@652: if (xrange == null) {
ingo@652: return null;
ingo@652: }
ingo@652:
sascha@719: String uri = ArtifactNamespaceContext.NAMESPACE_URI;
ingo@652:
sascha@719: String lower = xrange.getAttributeNS(uri, "from");
sascha@719: String upper = xrange.getAttributeNS(uri, "to");
ingo@652:
sascha@719: if (lower.length() > 0 && upper.length() > 0) {
ingo@652: try {
ingo@652: double from = Double.parseDouble(lower);
ingo@652: double to = Double.parseDouble(upper);
ingo@652:
ingo@652: if (from == 0 && to == 0) {
ingo@652: logger.debug("No range specified. Lower and upper X == 0");
ingo@652: return null;
ingo@652: }
ingo@652:
ingo@652: if (from > to) {
ingo@652: double tmp = to;
ingo@652: to = from;
ingo@652: from = tmp;
ingo@652: }
ingo@652:
ingo@652: return new Range(from, to);
ingo@652: }
ingo@652: catch (NumberFormatException nfe) {
ingo@652: logger.warn("Wrong values for domain axis range.");
ingo@652: }
ingo@652: }
ingo@652:
ingo@652: return null;
ingo@652: }
ingo@652:
ingo@652:
ingo@652: protected Range getValueAxisRange() {
sascha@719: Element yrange = (Element)XMLUtils.xpath(
ingo@652: request,
ingo@652: XPATH_CHART_Y_RANGE,
ingo@652: XPathConstants.NODE,
ingo@652: ArtifactNamespaceContext.INSTANCE);
ingo@652:
ingo@652: if (yrange == null) {
ingo@652: return null;
ingo@652: }
ingo@652:
felix@1944:
sascha@719: String uri = ArtifactNamespaceContext.NAMESPACE_URI;
ingo@652:
felix@1944:
sascha@719: String lower = yrange.getAttributeNS(uri, "from");
sascha@719: String upper = yrange.getAttributeNS(uri, "to");
ingo@652:
sascha@719: if (lower.length() > 0 && upper.length() > 0) {
ingo@652: try {
ingo@652: double from = Double.parseDouble(lower);
ingo@652: double to = Double.parseDouble(upper);
ingo@652:
ingo@652: if (from == 0 && to == 0) {
ingo@652: logger.debug("No range specified. Lower and upper Y == 0");
ingo@652: return null;
ingo@652: }
ingo@652:
felix@1944: return from > to
felix@1944: ? new Range(to, from)
felix@1944: : new Range(from, to);
ingo@652: }
ingo@652: catch (NumberFormatException nfe) {
ingo@652: logger.warn("Wrong values for value axis range.");
ingo@652: }
ingo@652: }
ingo@652:
ingo@652: return null;
ingo@652: }
ingo@652:
ingo@652:
ingo@423: /**
ingo@423: * Returns the default size of a chart export as array.
ingo@423: *
ingo@423: * @return the default size of a chart as [width, height].
ingo@423: */
ingo@423: protected int[] getDefaultSize() {
ingo@423: return new int[] { DEFAULT_CHART_WIDTH, DEFAULT_CHART_HEIGHT };
ingo@423: }
ingo@423:
ingo@423:
ingo@1684: public abstract void doOut(
felix@1944: ArtifactAndFacet bundle,
ingo@1684: Document attr,
ingo@1684: boolean visible);
ingo@348:
ingo@348: public abstract void generate() throws IOException;
ingo@1979:
ingo@1979:
ingo@1979: /**
ingo@1979: * Returns an instance of EmptySettings currently!
ingo@1979: *
ingo@1979: * @return an instance of EmptySettings.
ingo@1979: */
ingo@1979: public Settings getSettings() {
ingo@1979: return new EmptySettings();
ingo@1979: }
ingo@348: }
ingo@348: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :