ingo@391: package de.intevation.flys.exports;
ingo@391:
ingo@391: import java.io.IOException;
ingo@391: import java.io.OutputStream;
ingo@391: import java.io.OutputStreamWriter;
ingo@391:
felix@2284: import java.text.NumberFormat;
felix@2284:
ingo@391: import org.w3c.dom.Document;
ingo@391:
ingo@391: import org.apache.log4j.Logger;
ingo@391:
ingo@391: import au.com.bytecode.opencsv.CSVWriter;
ingo@391:
ingo@391: import de.intevation.artifacts.Artifact;
ingo@391: import de.intevation.artifacts.CallContext;
ingo@391:
felix@1944: import de.intevation.artifactdatabase.state.ArtifactAndFacet;
ingo@1979: import de.intevation.artifactdatabase.state.Settings;
ingo@695:
ingo@445: import de.intevation.artifacts.common.ArtifactNamespaceContext;
ingo@445: import de.intevation.artifacts.common.utils.XMLUtils;
ingo@445:
ingo@416: import de.intevation.flys.artifacts.resources.Resources;
ingo@416:
felix@2284: import de.intevation.flys.utils.Formatter;
felix@2284:
ingo@391:
ingo@391: /**
ingo@391: * An abstract exporter that implements some basic methods for exporting data of
ingo@391: * artifacts.
ingo@391: *
ingo@391: * @author Ingo Weinzierl
ingo@391: */
ingo@391: public abstract class AbstractExporter implements OutGenerator {
ingo@391:
ingo@391: /** The logger used in this exporter.*/
ingo@391: private static Logger logger = Logger.getLogger(AbstractExporter.class);
ingo@391:
ingo@391:
felix@1160: /** The name of the CSV facet which triggers the CSV creation. */
ingo@391: public static final String FACET_CSV = "csv";
ingo@391:
raimund@2176: /** The name of the PDF facet which triggers the PDF creation. */
raimund@2176: public static final String FACET_PDF = "pdf";
raimund@2176:
felix@1160: /** The default charset for the CSV export. */
ingo@391: public static final String DEFAULT_CSV_CHARSET = "UTF-8";
ingo@391:
felix@1160: /** The default separator for the CSV export. */
ingo@391: public static final char DEFAULT_CSV_SEPARATOR = ',';
ingo@391:
felix@1160: /** XPath that points to the desired export facet. */
ingo@445: public static final String XPATH_FACET = "/art:action/@art:type";
ingo@445:
ingo@391:
felix@1160: /** The document of the incoming out() request. */
ingo@391: protected Document request;
ingo@391:
felix@1160: /** The output stream where the data should be written to. */
ingo@391: protected OutputStream out;
ingo@391:
felix@1160: /** The CallContext object. */
ingo@391: protected CallContext context;
ingo@391:
felix@1160: /** The selected facet. */
ingo@391: protected String facet;
ingo@391:
felix@1160: /** The master artifact. */
ingo@412: protected Artifact master;
ingo@412:
ingo@391:
ingo@391: /**
ingo@391: * Concrete subclasses need to use this method to write their special data
ingo@391: * objects into the CSV document.
ingo@391: *
ingo@391: * @param writer The CSVWriter.
ingo@391: */
ingo@391: protected abstract void writeCSVData(CSVWriter writer);
ingo@391:
ingo@391:
ingo@391: /**
raimund@2176: * Concrete subclasses need to use this method to write their special data
raimund@2176: * objects into the PDF document.
raimund@2176: */
raimund@2176: protected abstract void writePDF(OutputStream out);
raimund@2176:
raimund@2176:
raimund@2176: /**
ingo@391: * This method enables concrete subclasses to collected its own special
ingo@391: * data.
ingo@391: *
ingo@391: * @param artifacts The artifact that stores the data that has to be
ingo@391: * exported.
ingo@391: */
sascha@701: protected abstract void addData(Object data);
ingo@391:
sascha@710: @Override
ingo@391: public void init(Document request, OutputStream out, CallContext context) {
ingo@391: logger.debug("AbstractExporter.init");
ingo@391:
ingo@391: this.request = request;
ingo@391: this.out = out;
ingo@391: this.context = context;
ingo@391: }
ingo@391:
ingo@391:
sascha@710: @Override
ingo@412: public void setMasterArtifact(Artifact master) {
ingo@412: this.master = master;
ingo@412: }
ingo@412:
ingo@412:
ingo@391: /**
ingo@391: * This doOut() just collects the data of multiple artifacts. Therefore, it
ingo@391: * makes use of the addData() method which enables concrete subclasses to
ingo@391: * store its data on its own. The real output creation takes place in the
ingo@391: * concrete generate() methods.
ingo@391: *
ingo@391: * @param artifact The artifact.
ingo@391: * @param facet The facet to add - NOTE: the facet needs to fit to the first
ingo@391: * facet inserted into this exporter. Otherwise this artifact/facet is
ingo@391: * skipped.
ingo@391: * @param attr The attr document.
ingo@391: */
sascha@710: @Override
ingo@1684: public void doOut(
felix@1944: ArtifactAndFacet artifactFacet,
felix@1944: Document attr,
felix@1944: boolean visible
ingo@1684: ) {
felix@1944: String name = artifactFacet.getFacetName();
ingo@391:
ingo@695: logger.debug("AbstractExporter.doOut: " + name);
ingo@695:
ingo@695: if (!isFacetValid(name)) {
ingo@695: logger.warn("Facet '" + name + "' not valid. No output created!");
ingo@391: return;
ingo@391: }
ingo@391:
ingo@2038: addData(artifactFacet.getData(context));
ingo@391: }
ingo@391:
ingo@391:
ingo@391: /**
ingo@391: * Generates an export based on a specified facet.
ingo@391: */
sascha@710: @Override
ingo@391: public void generate()
ingo@391: throws IOException
ingo@391: {
ingo@391: logger.debug("AbstractExporter.generate");
ingo@391:
ingo@391: if (facet != null && facet.equals(FACET_CSV)) {
ingo@391: generateCSV();
ingo@391: }
raimund@2176: else if (facet != null && facet.equals(FACET_PDF)) {
raimund@2176: generatePDF();
raimund@2176: }
ingo@391: else {
ingo@391: throw new IOException("invalid facet for exporter.");
ingo@391: }
ingo@391: }
ingo@391:
ingo@391:
ingo@391: /**
ingo@391: * Determines if the desired facet is valid for this exporter. If no facet
ingo@391: * is currently set, facet is set.
ingo@391: *
ingo@391: * @param facet The desired facet.
ingo@391: *
ingo@391: * @return true, if facet is valid, otherwise false.
ingo@391: */
ingo@391: protected boolean isFacetValid(String facet) {
felix@2284: logger.debug("AbstractExporter.isFacetValid : " + facet + " (" + getFacet() + ")" );
ingo@391:
ingo@445: String thisFacet = getFacet();
ingo@445:
ingo@445: if (thisFacet == null || thisFacet.length() == 0) {
ingo@391: return false;
ingo@391: }
ingo@445: else if (facet == null || facet.length() == 0) {
ingo@445: return false;
ingo@391: }
ingo@391: else {
ingo@445: return thisFacet.equals(facet);
ingo@391: }
ingo@391: }
ingo@391:
ingo@391:
ingo@445: /**
ingo@445: * Returns the name of the desired facet.
ingo@445: *
ingo@445: * @return the name of the desired facet.
ingo@445: */
ingo@445: protected String getFacet() {
ingo@445: if (facet == null) {
ingo@445: facet = getFacetFromRequest();
ingo@445: }
ingo@445:
ingo@445: return facet;
ingo@445: }
ingo@445:
ingo@445:
ingo@445: /**
ingo@445: * Extracts the name of the requested facet from request document.
ingo@445: *
ingo@445: * @return the name of the requested facet.
ingo@445: */
ingo@445: protected String getFacetFromRequest() {
ingo@445: return XMLUtils.xpathString(
ingo@445: request, XPATH_FACET, ArtifactNamespaceContext.INSTANCE);
ingo@445: }
ingo@445:
ingo@416:
ingo@416: protected String msg(String key, String def) {
ingo@416: return Resources.getMsg(context.getMeta(), key, def);
ingo@416: }
ingo@416:
ingo@416:
ingo@391: /**
ingo@391: * This method starts CSV creation. It makes use of writeCSVData() which has
ingo@391: * to be implemented by concrete subclasses.
ingo@391: */
ingo@391: protected void generateCSV()
ingo@391: throws IOException
ingo@391: {
ingo@391: logger.info("AbstractExporter.generateCSV");
ingo@391:
ingo@391: CSVWriter writer = new CSVWriter(
ingo@391: new OutputStreamWriter(
ingo@391: out,
ingo@391: DEFAULT_CSV_CHARSET),
ingo@391: DEFAULT_CSV_SEPARATOR);
ingo@391:
ingo@391: writeCSVData(writer);
ingo@391:
ingo@391: writer.close();
ingo@391: }
ingo@1979:
ingo@1979:
ingo@1979: /**
raimund@2176: * This method starts PDF creation.
raimund@2176: */
raimund@2176: protected void generatePDF()
raimund@2176: throws IOException
raimund@2176: {
raimund@2176: logger.info("AbstractExporter.generatePDF");
raimund@2176: writePDF(this.out);
raimund@2176: }
raimund@2176:
raimund@2176:
raimund@2176: /**
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@2047:
ingo@2047:
ingo@2047: /**
ingo@2047: * This method is not implemented. Override it in subclasses if those need a
ingo@2047: * Settings object.
ingo@2047: */
ingo@2047: public void setSettings(Settings settings) {
ingo@2047: // do nothing
ingo@2047: }
felix@2284:
felix@2284:
felix@2284: /**
felix@2284: * Returns the number formatter for kilometer values.
felix@2284: *
felix@2284: * @return the number formatter for kilometer values.
felix@2284: */
felix@2284: protected NumberFormat getKmFormatter() {
felix@2284: return Formatter.getWaterlevelKM(context);
felix@2284: }
felix@2284:
felix@2284:
felix@2284: /**
felix@2284: * Returns the number formatter for W values.
felix@2284: *
felix@2284: * @return the number formatter for W values.
felix@2284: */
felix@2284: protected NumberFormat getWFormatter() {
felix@2284: return Formatter.getWaterlevelW(context);
felix@2284: }
felix@2284:
felix@2284:
felix@2284: /**
felix@2284: * Returns the number formatter for Q values.
felix@2284: *
felix@2284: * @return the number formatter for Q values.
felix@2284: */
felix@2284: protected NumberFormat getQFormatter() {
felix@2284: return Formatter.getWaterlevelQ(context);
felix@2284: }
ingo@391: }
ingo@391: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :