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: 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: ingo@695: import de.intevation.artifactdatabase.state.Facet; 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: sascha@701: import de.intevation.flys.artifacts.FLYSArtifact; sascha@701: 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: 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: /** 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( ingo@1684: Artifact artifact, ingo@1684: Facet facet, ingo@1684: Document attr, ingo@1684: boolean visible ingo@1684: ) { ingo@695: String name = facet.getName(); 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: sascha@701: FLYSArtifact flys = (FLYSArtifact)artifact; sascha@701: sascha@701: Facet nativeFacet = flys.getNativeFacet(facet); sascha@701: sascha@701: if (nativeFacet != null) { sascha@701: addData(nativeFacet.getData(flys, context)); sascha@701: } 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: } 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) { ingo@391: logger.debug("AbstractExporter.isFacetValid"); 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@391: } ingo@391: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :