tim@335: package de.intevation.gnv.state.profile.horizontalcrosssection; tim@335: tim@468: import com.vividsolutions.jts.geom.Coordinate; tim@468: import com.vividsolutions.jts.geom.Envelope; tim@468: import com.vividsolutions.jts.geom.Polygon; ingo@358: sascha@480: import de.intevation.artifactdatabase.Config; sascha@480: import de.intevation.artifactdatabase.XMLUtils; sascha@480: sascha@480: import de.intevation.artifacts.ArtifactNamespaceContext; sascha@480: import de.intevation.artifacts.CallContext; sascha@474: tim@468: import de.intevation.gnv.artifacts.cache.CacheFactory; sascha@480: tim@468: import de.intevation.gnv.artifacts.context.GNVArtifactContext; sascha@474: tim@335: import de.intevation.gnv.geobackend.base.Result; sascha@480: import de.intevation.gnv.geobackend.base.ResultDescriptor; sascha@474: tim@468: import de.intevation.gnv.geobackend.base.query.QueryExecutor; tim@468: import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory; sascha@480: tim@468: import de.intevation.gnv.geobackend.base.query.exception.QueryException; sascha@474: sascha@480: import de.intevation.gnv.geobackend.sde.datasources.RasterObject; sascha@480: sascha@480: import de.intevation.gnv.math.AttributedPoint2ds; sascha@480: tim@459: import de.intevation.gnv.state.InputData; sascha@480: import de.intevation.gnv.state.OutputStateBase; sascha@474: tim@335: import de.intevation.gnv.state.exception.StateException; sascha@474: tim@335: import de.intevation.gnv.state.timeseries.TimeSeriesOutputState; sascha@474: sascha@481: import de.intevation.gnv.utils.FileUtils; tim@468: import de.intevation.gnv.utils.StringUtils; tim@468: import de.intevation.gnv.utils.WKTUtils; tim@335: sascha@480: import java.io.File; sascha@480: import java.io.IOException; sascha@480: import java.io.OutputStream; sascha@474: sascha@480: import java.util.Collection; sascha@439: sascha@480: import org.apache.log4j.Logger; sascha@480: sascha@480: import org.w3c.dom.Document; sascha@481: import org.w3c.dom.Element; sascha@480: import org.w3c.dom.Node; sascha@474: tim@335: /** sascha@474: * @author Tim Englich (tim.englich@intevation.de) sascha@474: * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) tim@335: */ tim@335: public class HorizontalCrossSectionMeshOutputState sascha@480: extends OutputStateBase sascha@474: { tim@335: private static Logger log = Logger sascha@474: .getLogger(HorizontalCrossSectionMeshOutputState.class); tim@335: tim@335: /** tim@335: * The UID of this Class tim@335: */ tim@335: private static final long serialVersionUID = 3233620652465061860L; tim@468: sascha@481: private String ijkQueryID; sascha@481: sascha@481: private Boolean shapeFileLock = new Boolean(true); sascha@481: sascha@481: private String shapeFilePath; tim@335: tim@335: /** tim@335: * Constructor tim@335: */ tim@335: public HorizontalCrossSectionMeshOutputState() { tim@335: } tim@335: sascha@481: public String getShapeFilePath() { sascha@481: synchronized (shapeFileLock) { sascha@481: return shapeFilePath; sascha@481: } sascha@481: } sascha@481: sascha@481: public void setShapeFilePath(String shapeFilePath) { sascha@481: synchronized (shapeFileLock) { sascha@481: this.shapeFilePath = shapeFilePath; sascha@481: } sascha@481: } sascha@481: sascha@481: public String resetShapeFilePath() { sascha@481: synchronized (shapeFileLock) { sascha@481: String path = shapeFilePath; sascha@481: shapeFilePath = null; sascha@481: return path; sascha@481: } sascha@481: } sascha@481: sascha@481: public void endOfLife(Object globalContext) { sascha@481: super.endOfLife(globalContext); sascha@481: sascha@481: // do it in background sascha@481: new Thread() { sascha@481: public void run() { sascha@481: // TODO: Do the un-publishing WMS stuff. sascha@481: String path = resetShapeFilePath(); sascha@481: sascha@481: if (path == null) { sascha@481: return; sascha@481: } sascha@481: sascha@481: File dir = new File(path); sascha@481: sascha@481: for (int i = 0; i < 10; ++i) { sascha@481: if (!dir.exists() || FileUtils.deleteRecursive(dir)) { sascha@481: return; sascha@481: } sascha@481: try { sascha@481: Thread.sleep(10000L); sascha@481: } sascha@481: catch (InterruptedException ie) { sascha@481: } sascha@481: } sascha@481: sascha@481: log.error("failed to remove directory '" + path + "'"); sascha@481: } // run sascha@481: }.start(); sascha@481: } sascha@481: sascha@480: public void out( sascha@480: Document format, sascha@480: Collection inputData, sascha@480: OutputStream outputStream, sascha@480: String uuid, sascha@480: CallContext callContext sascha@480: ) sascha@480: throws StateException sascha@480: { sascha@480: String outputMode = XMLUtils.xpathString( sascha@480: format, XPATH_OUTPUT_MODE, ArtifactNamespaceContext.INSTANCE); tim@335: sascha@480: String mimeType = XMLUtils.xpathString( sascha@480: format, XPATH_MIME_TYPE, ArtifactNamespaceContext.INSTANCE); sascha@480: sascha@480: if (outputMode == null || mimeType == null) { sascha@480: throw new StateException("cannot find outputMode or mime"); tim@335: } tim@335: sascha@480: outputMode = outputMode.toLowerCase(); sascha@471: sascha@480: log.debug("---- asking for: " + outputMode); tim@468: sascha@480: if ("zip".equals(outputMode)) { sascha@481: writeZip(uuid, callContext, outputStream); sascha@480: } sascha@480: else if ("wms".equals(outputMode)) { sascha@481: XMLUtils.toStream( sascha@481: getWMS(uuid, callContext), sascha@481: outputStream); sascha@480: } sascha@480: else if ("statistics".equals(outputMode)) { sascha@480: // TODO: REMOVE THIS! sascha@481: try { outputStream.write("\n".getBytes()); } sascha@481: catch (IOException ioe) {} tim@468: } sascha@480: else { sascha@480: throw new StateException("unsupported output mode"); sascha@480: } sascha@480: } sascha@480: sascha@481: protected void writeZip( sascha@481: String uuid, sascha@481: CallContext callContext, sascha@481: OutputStream output sascha@481: ) sascha@481: throws StateException sascha@481: { sascha@481: try { sascha@481: String p = getShapeFilePath(); sascha@481: if (p != null) { sascha@481: File dir = new File(p); sascha@481: if (dir.isDirectory()) { sascha@481: FileUtils.createZipArchive(dir, output); sascha@481: } sascha@481: } sascha@481: AttributedPoint2ds result = getResult(uuid, callContext); sascha@481: if (result != null sascha@481: && (p = writeToShapeFile(uuid, result, callContext)) != null) { sascha@481: FileUtils.createZipArchive(new File(p), output); sascha@481: } sascha@481: } sascha@481: catch (IOException ioe) { sascha@481: log.error(ioe.getLocalizedMessage(), ioe); sascha@481: } sascha@481: } sascha@481: sascha@481: protected Document getWMS(String uuid, CallContext callContext) sascha@481: throws StateException sascha@481: { sascha@481: // TODO: Do the real WMS publishing here! sascha@481: Document document = XMLUtils.newDocument(); sascha@481: sascha@481: Element pathElement = document.createElement("path"); sascha@481: document.appendChild(pathElement); sascha@481: sascha@481: String path = getShapeFilePath(); sascha@481: sascha@481: if (path != null && new File(path).isDirectory()) { sascha@481: pathElement.setTextContent(path); sascha@481: } sascha@481: else { sascha@481: AttributedPoint2ds result = getResult(uuid, callContext); sascha@481: if (result != null sascha@481: && (path = writeToShapeFile(uuid, result, callContext)) != null) { sascha@481: pathElement.setTextContent(path); sascha@481: } sascha@481: } sascha@481: sascha@481: return document; sascha@481: } sascha@481: sascha@481: protected String writeToShapeFile( sascha@481: String uuid, sascha@481: AttributedPoint2ds result, sascha@481: CallContext callContext sascha@481: ) { sascha@481: File baseDir = shapefileDirectory(callContext); sascha@481: sascha@481: File shapeDir = new File(baseDir, uuid); sascha@481: sascha@481: int count = 0; sascha@481: sascha@481: synchronized (shapeFileLock) { sascha@481: while (shapeDir.exists()) { sascha@481: shapeDir = new File(baseDir, uuid + "-" + count); sascha@481: ++count; sascha@481: } sascha@481: sascha@481: if (!shapeDir.mkdirs()) { sascha@481: log.error("cannot create directory '" sascha@481: + shapeDir.getAbsolutePath() + "'"); sascha@481: return null; sascha@481: } sascha@481: shapeFilePath = shapeDir.getAbsolutePath(); sascha@481: } sascha@481: sascha@481: // TODO: Do the writing sascha@481: sascha@481: return shapeFilePath; sascha@481: } sascha@481: sascha@481: protected AttributedPoint2ds getResult(String uuid, CallContext callContext) sascha@480: throws StateException sascha@480: { sascha@480: CacheFactory cf = CacheFactory.getInstance(); sascha@480: String key = uuid + super.getID(); sascha@480: sascha@480: if (cf.isInitialized()) { sascha@480: net.sf.ehcache.Element value = cf.getCache().get(key); sascha@480: if (value != null) { sascha@481: return (AttributedPoint2ds)value.getObjectValue(); sascha@480: } sascha@480: } sascha@480: sascha@481: AttributedPoint2ds result = produceResult(callContext); sascha@480: sascha@480: if (result != null && cf.isInitialized()) { sascha@480: cf.getCache().put(new net.sf.ehcache.Element(key, result)); sascha@480: } sascha@480: tim@468: return result; tim@468: } tim@468: sascha@481: protected AttributedPoint2ds produceResult(CallContext callContext) sascha@480: throws StateException sascha@480: { sascha@480: InputData meshPolygon = inputData.get("mesh_polygon"); sascha@480: InputData meshId = inputData.get("meshid"); sascha@480: sascha@480: if (meshPolygon == null) { sascha@480: log.error("mesh_polygon is not defined"); sascha@480: throw new StateException("missing mesh_linestring"); sascha@480: } sascha@480: sascha@480: if (meshId == null) { sascha@480: log.error("meshid is not defined"); sascha@480: throw new StateException("missing meshid"); sascha@480: } sascha@480: sascha@480: Polygon p = WKTUtils.toPolygon(meshPolygon.getValue()); sascha@480: sascha@480: if (p == null) { sascha@480: log.error("no valid polygon"); sascha@480: throw new StateException("no valid polygon"); sascha@480: } sascha@480: sascha@480: try { sascha@480: Envelope env = p.getEnvelopeInternal(); sascha@480: sascha@480: Coordinate [] coords = new Coordinate [] { sascha@480: new Coordinate(env.getMinX(), env.getMinY()), sascha@480: new Coordinate(env.getMinX(), env.getMaxY()), sascha@480: new Coordinate(env.getMaxX(), env.getMaxY()), sascha@480: new Coordinate(env.getMaxX(), env.getMinY()) }; sascha@480: sascha@480: String additionWhere = sascha@480: WKTUtils.worldEnvelopeCoordinatesToIndex( sascha@480: coords, sascha@480: meshId.getValue(), sascha@480: ijkQueryID); sascha@480: sascha@480: String[] addedFilterValues = StringUtils.append( sascha@480: generateFilterValuesFromInputData(), sascha@480: additionWhere); sascha@480: sascha@480: QueryExecutor queryExecutor = QueryExecutorFactory sascha@480: .getInstance() sascha@480: .getQueryExecutor(); sascha@480: sascha@480: return process( sascha@480: env, sascha@480: p, sascha@480: numSamples(callContext), sascha@480: preprocess( sascha@480: queryExecutor.executeQuery( sascha@480: queryID, sascha@480: addedFilterValues))); sascha@480: } sascha@480: catch (QueryException e) { sascha@480: log.error(e,e); sascha@480: } sascha@480: sascha@480: throw new StateException("no result produced"); tim@468: } tim@335: sascha@480: public AttributedPoint2ds preprocess(Collection results) { sascha@480: sascha@480: boolean debug = log.isDebugEnabled(); sascha@480: sascha@480: if (debug) { sascha@480: log.debug("--- preprocess: " + results.size() + " results"); sascha@480: } sascha@480: sascha@480: AttributedPoint2ds ap2ds = new AttributedPoint2ds(); sascha@480: sascha@480: boolean first = true; sascha@480: sascha@480: for (Result result: results) { sascha@480: sascha@480: if (debug && first) { sascha@480: first = false; sascha@480: ResultDescriptor rd = result.getResultDescriptor(); sascha@480: log.debug(rd); sascha@480: } sascha@480: } sascha@480: sascha@481: // TODO: do the interpolation sascha@481: sascha@480: return ap2ds; tim@335: } tim@335: sascha@481: public AttributedPoint2ds process( sascha@480: Envelope env, sascha@480: Polygon polygon, sascha@480: int numSamples, sascha@480: AttributedPoint2ds input sascha@480: ) { sascha@480: return input; tim@335: } sascha@480: tim@468: tim@468: /** tim@468: * @see de.intevation.gnv.state.timeseries.TimeSeriesOutputState#setup(org.w3c.dom.Node) tim@468: */ tim@468: @Override tim@468: public void setup(Node configuration) { tim@468: super.setup(configuration); tim@468: this.ijkQueryID = Config.getStringXPath(configuration,"queryID-ijk"); tim@468: tim@468: } tim@468: tim@468: private static int numSamples(CallContext callContext) { tim@468: GNVArtifactContext context = tim@468: (GNVArtifactContext)callContext.globalContext(); tim@468: Integer samples = (Integer)context.get( tim@468: GNVArtifactContext.HORIZONTAL_CROSS_SECTION_SAMPLES_KEY); tim@468: return samples != null tim@468: ? samples.intValue() tim@468: : GNVArtifactContext.DEFAULT_HORIZONTAL_CROSS_SECTION_SAMPLES; tim@468: } tim@335: sascha@474: private static File shapefileDirectory(CallContext callContext) { sascha@474: GNVArtifactContext context = sascha@474: (GNVArtifactContext)callContext.globalContext(); sascha@474: File dir = (File)context.get( sascha@474: GNVArtifactContext.HORIZONTAL_CROSS_SECTION_RESULT_SHAPEFILE_PATH_KEY); sascha@474: return dir != null sascha@474: ? dir sascha@474: : GNVArtifactContext.DEFAULT_HORIZONTAL_CROSS_SECTION_PROFILE_SHAPEFILE_PATH; sascha@474: } sascha@474: sascha@474: private static int getGroundInterpolation(CallContext callContext) { sascha@474: GNVArtifactContext context = sascha@474: (GNVArtifactContext)callContext.globalContext(); sascha@474: sascha@474: String interpolation = (String)context.get( sascha@474: GNVArtifactContext.HORIZONTAL_CROSS_SECTION_GROUND_INTERPOLATION_KEY); sascha@474: sascha@474: return RasterObject.getInterpolationType(interpolation); sascha@474: } tim@335: } sascha@474: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :