ingo@927: package de.intevation.flys.artifacts.states; ingo@927: ingo@1091: import java.io.File; ingo@1091: import java.io.IOException; ingo@1106: import java.net.MalformedURLException; ingo@935: import java.util.List; ingo@935: ingo@1091: import javax.xml.xpath.XPathConstants; ingo@1091: ingo@1107: import com.vividsolutions.jts.geom.Geometry; ingo@1106: import com.vividsolutions.jts.geom.LineString; ingo@1106: import com.vividsolutions.jts.geom.Polygon; ingo@1106: ingo@927: import org.apache.log4j.Logger; ingo@927: ingo@1106: import org.opengis.feature.simple.SimpleFeature; ingo@1106: import org.opengis.feature.simple.SimpleFeatureType; ingo@1107: import org.opengis.referencing.FactoryException; ingo@1107: import org.opengis.referencing.NoSuchAuthorityCodeException; ingo@1106: ingo@1106: import org.geotools.feature.FeatureCollection; ingo@1106: import org.geotools.feature.FeatureCollections; ingo@1106: import org.geotools.feature.SchemaException; ingo@1107: import org.geotools.referencing.CRS; ingo@1106: ingo@1091: import de.intevation.artifacts.Artifact; ingo@935: import de.intevation.artifacts.CallContext; ingo@935: ingo@1091: import de.intevation.artifacts.common.utils.Config; ingo@1091: import de.intevation.artifacts.common.utils.FileTools; ingo@1091: ingo@935: import de.intevation.artifactdatabase.state.Facet; ingo@935: ingo@935: import de.intevation.flys.artifacts.FLYSArtifact; ingo@927: import de.intevation.flys.artifacts.model.FacetTypes; ingo@935: import de.intevation.flys.artifacts.model.WSPLGENFacet; ingo@1091: import de.intevation.flys.artifacts.model.WSPLGENJob; ingo@1096: import de.intevation.flys.utils.FLYSUtils; ingo@1106: import de.intevation.flys.utils.GeometryUtils; ingo@927: ingo@927: ingo@927: public class FloodMapState ingo@927: extends DefaultState ingo@927: implements FacetTypes ingo@927: { ingo@927: /** The logger that is used in this state.*/ ingo@927: private static Logger logger = Logger.getLogger(FloodMapState.class); ingo@927: ingo@935: ingo@1107: public static final String KEEP_ARTIFACT_DIR = ingo@1107: System.getProperty("flys.uesk.keep.artifactsdir", "false"); ingo@1107: ingo@1107: ingo@1091: public static final String XPATH_SHAPEFILE_DIR = ingo@1091: "/artifact-database/floodmap/shapefile-path/@value"; ingo@1091: ingo@1091: public static final String WSPLGEN_PARAMETER_FILE = "wsplgen.par"; ingo@1106: public static final String WSPLGEN_BARRIERS_LINES = "barrier_lines.shp"; ingo@1106: public static final String WSPLGEN_BARRIERS_POLY = "barrier_polygons.shp"; ingo@1091: ingo@1096: public static final int WSPLGEN_DEFAULT_OUTPUT = 0; ingo@1096: ingo@1091: ingo@1053: ingo@1053: @Override ingo@935: public Object computeAdvance( ingo@935: FLYSArtifact artifact, ingo@935: String hash, ingo@935: CallContext context, ingo@935: List facets, ingo@935: Object old ingo@935: ) { ingo@1091: logger.debug("FloodMapState.computeAdvance"); ingo@1091: ingo@1091: File artifactDir = getDirectory(artifact); ingo@1091: ingo@1091: if (artifactDir == null) { ingo@1091: logger.error("Could not create directory for WSPLGEN results!"); ingo@1091: return null; ingo@1091: } ingo@1091: ingo@1091: WSPLGENJob job = prepareWSPLGENJob(artifact, artifactDir); ingo@1091: ingo@1091: if (job == null) { ingo@1107: if (KEEP_ARTIFACT_DIR.equals("false")) { ingo@1107: removeDirectory(artifact); ingo@1107: } ingo@1091: ingo@1091: logger.error("No WSPLGEN processing has been started!"); ingo@1091: ingo@1091: return null; ingo@1091: } ingo@1091: ingo@935: facets.add(new WSPLGENFacet(0, FLOODMAP_WSPLGEN, "WSPLGEN")); ingo@935: ingo@1091: //context.afterCall(CallContext.BACKGROUND); ingo@1091: ingo@1091: return null; ingo@1091: } ingo@1091: ingo@1091: ingo@1091: /** ingo@1091: * Returns the shapefile path defined in the configuration. ingo@1091: * ingo@1091: * @return the shapefile path. ingo@1091: */ ingo@1091: protected String getShapefilePath() { ingo@1091: String shapePath = (String) Config.getXPath( ingo@1091: XPATH_SHAPEFILE_DIR, XPathConstants.STRING); ingo@1091: shapePath = Config.replaceConfigDir(shapePath); ingo@1091: ingo@1091: return shapePath; ingo@1091: } ingo@1091: ingo@1091: ingo@1091: /** ingo@1091: * Returns (and creates if not existing) the directory for storing WSPLEN ingo@1091: * data for the owner artifact. ingo@1091: * ingo@1091: * @param artifact The owner Artifact. ingo@1091: * ingo@1091: * @return the directory for WSPLEN data. ingo@1091: */ ingo@1091: protected File getDirectory(FLYSArtifact artifact) { ingo@1091: String shapePath = getShapefilePath(); ingo@1091: ingo@1091: File artifactDir = FileTools.getDirectory( ingo@1091: shapePath, artifact.identifier()); ingo@1091: ingo@1091: return artifactDir; ingo@1091: } ingo@1091: ingo@1091: ingo@1091: /** ingo@1091: * Removes the directory and all its content where the required data and the ingo@1091: * results of WSPLGEN are stored. Should be called in endOfLife(). ingo@1091: */ ingo@1091: protected void removeDirectory(FLYSArtifact artifact) { ingo@1091: String shapePath = getShapefilePath(); ingo@1091: File artifactDir = new File(shapePath, artifact.identifier()); ingo@1091: ingo@1091: if (artifactDir.exists()) { ingo@1091: logger.info("Delete directory: " + artifactDir.getAbsolutePath()); ingo@1091: boolean success = FileTools.deleteRecursive(artifactDir); ingo@1091: } ingo@1091: else { ingo@1091: logger.debug("There is no directory to remove."); ingo@1091: } ingo@1091: } ingo@1091: ingo@1091: ingo@1091: @Override ingo@1091: public void endOfLife(Artifact artifact, Object callContext) { ingo@1091: logger.info("FloodMapState.endOfLife: " + artifact.identifier()); ingo@1091: ingo@1091: FLYSArtifact flys = (FLYSArtifact) artifact; ingo@1091: removeDirectory(flys); ingo@1091: } ingo@1091: ingo@1091: ingo@1091: protected WSPLGENJob prepareWSPLGENJob( ingo@1091: FLYSArtifact artifact, ingo@1091: File artifactDir ingo@1091: ) { ingo@1091: logger.debug("FloodMapState.prepareWSPLGENJob"); ingo@1091: ingo@1091: WSPLGENJob job = new WSPLGENJob(); ingo@1091: File paraFile = new File(artifactDir, WSPLGEN_PARAMETER_FILE); ingo@1091: ingo@1096: setOut(artifact, job); ingo@1096: setRange(artifact, job); ingo@1096: setDelta(artifact, job); ingo@1096: setGel(artifact, job); ingo@1096: setDist(artifact, job); ingo@1106: setLine(artifact, artifactDir, job); ingo@1096: ingo@1096: // TODO ingo@1096: // setDgm(artifact, job); // SHP ingo@1096: // setPro(artifact, job); // SHP ingo@1096: // setWsp(artifact, job); // WSP ingo@1096: // setWspTag(artifact, job); ingo@1096: // setAxis(artifact, job); // SHP ingo@1096: // setArea(artifact, job); // SHP ingo@1096: // setOutFile(artifact, job); ingo@1096: ingo@1091: try { ingo@1091: job.toFile(paraFile); ingo@1091: ingo@1091: return job; ingo@1091: } ingo@1091: catch (IOException ioe) { ingo@1091: logger.warn("Cannot write PAR file: " + ioe.getMessage()); ingo@1091: } ingo@1091: catch (IllegalArgumentException iae) { ingo@1091: logger.warn("Cannot write PAR file: " + iae.getMessage()); ingo@1091: } ingo@1091: ingo@935: return null; ingo@935: } ingo@1096: ingo@1096: ingo@1096: protected void setOut(FLYSArtifact artifact, WSPLGENJob job) { ingo@1096: job.setOut(WSPLGEN_DEFAULT_OUTPUT); ingo@1096: } ingo@1096: ingo@1096: ingo@1096: protected void setRange(FLYSArtifact artifact, WSPLGENJob job) { ingo@1096: double[] range = FLYSUtils.getKmRange(artifact); ingo@1096: ingo@1096: job.setStart(range[0]); ingo@1096: job.setEnd(range[1]); ingo@1096: } ingo@1096: ingo@1096: ingo@1096: protected void setDelta(FLYSArtifact artifact, WSPLGENJob job) { ingo@1096: String from = artifact.getDataAsString("diff_from"); ingo@1096: String to = artifact.getDataAsString("diff_to"); ingo@1096: String diff = artifact.getDataAsString("diff_diff"); ingo@1096: ingo@1096: try { ingo@1096: job.setFrom(Double.parseDouble(from)); ingo@1096: } ingo@1096: catch (NumberFormatException nfe) { ingo@1096: } ingo@1096: ingo@1096: try { ingo@1096: job.setTo(Double.parseDouble(to)); ingo@1096: } ingo@1096: catch (NumberFormatException nfe) { ingo@1096: } ingo@1096: ingo@1096: try { ingo@1096: job.setDiff(Double.parseDouble(diff)); ingo@1096: } ingo@1096: catch (NumberFormatException nfe) { ingo@1096: } ingo@1096: } ingo@1096: ingo@1096: ingo@1096: protected void setGel(FLYSArtifact artifact, WSPLGENJob job) { ingo@1096: String gel = artifact.getDataAsString("use_floodplain"); ingo@1096: ingo@1096: if (gel != null && gel.length() > 0) { ingo@1096: boolean use = Boolean.parseBoolean(gel); ingo@1096: ingo@1096: if (use) { ingo@1096: job.setGel(WSPLGENJob.GEL_SPERRE); ingo@1096: } ingo@1096: else { ingo@1096: job.setGel(WSPLGENJob.GEL_NOSPERRE); ingo@1096: } ingo@1096: } ingo@1096: } ingo@1096: ingo@1096: ingo@1096: protected void setDist(FLYSArtifact artifact, WSPLGENJob job) { ingo@1096: String dist = artifact.getDataAsString("profile_distance"); ingo@1096: ingo@1096: try { ingo@1096: job.setDist(Double.parseDouble(dist)); ingo@1096: } ingo@1096: catch (NumberFormatException nfe) { ingo@1096: // nothing to do here ingo@1096: } ingo@1096: } ingo@1106: ingo@1106: ingo@1106: protected void setLine(FLYSArtifact artifact, File dir, WSPLGENJob job) { ingo@1106: String geoJSON = artifact.getDataAsString("uesk.barriers"); ingo@1106: String srid = FLYSUtils.getRiverSrid(artifact); ingo@1106: String srs = "EPSG:" + srid; ingo@1106: ingo@1107: List features = getBarriersFeatures(geoJSON, srs); ingo@1107: if (features == null || features.size() == 0) { ingo@1107: logger.debug("No barrier features extracted."); ingo@1107: return; ingo@1107: } ingo@1106: ingo@1106: FeatureCollection[] fcs = splitLinesAndPolygons(features); ingo@1106: ingo@1106: File shapeLines = new File(dir, WSPLGEN_BARRIERS_LINES); ingo@1106: File shapePolys = new File(dir, WSPLGEN_BARRIERS_POLY); ingo@1106: ingo@1106: try { ingo@1106: GeometryUtils.writeShapefile( ingo@1106: shapeLines, ingo@1107: GeometryUtils.buildFeatureType( ingo@1107: "lines", srs, LineString.class, CRS.decode(srs)), ingo@1106: fcs[0]); ingo@1106: job.addLin(shapeLines.getAbsolutePath()); ingo@1106: ingo@1106: GeometryUtils.writeShapefile( ingo@1106: shapePolys, ingo@1107: GeometryUtils.buildFeatureType( ingo@1107: "polygons", srs, Polygon.class, CRS.decode(srs)), ingo@1106: fcs[1]); ingo@1106: job.addLin(shapePolys.getAbsolutePath()); ingo@1106: } ingo@1106: catch (MalformedURLException mue) { ingo@1106: logger.error("Error while writing shapefile: " + mue.getMessage()); ingo@1106: } ingo@1106: catch (IOException ioe) { ingo@1106: logger.error("Error while writing shapefile: " + ioe.getMessage()); ingo@1106: } ingo@1106: catch (SchemaException se) { ingo@1106: logger.error("Error while writing shapefile: " + se.getMessage()); ingo@1106: } ingo@1107: catch (NoSuchAuthorityCodeException nsae) { ingo@1107: logger.error("Error while writing shapefile: " + nsae.getMessage()); ingo@1107: } ingo@1107: catch (FactoryException fe) { ingo@1107: logger.error("Error while writing shapefile: " + fe.getMessage()); ingo@1107: } ingo@1107: } ingo@1107: ingo@1107: ingo@1107: protected List getBarriersFeatures(String json, String srs) { ingo@1107: SimpleFeatureType ft = null; ingo@1107: List features = null; ingo@1107: ingo@1107: try { ingo@1107: ft = GeometryUtils.buildFeatureType( ingo@1107: "barriers", srs, Geometry.class, CRS.decode(srs)); ingo@1107: ingo@1107: features = GeometryUtils.parseGeoJSON(json, ft); ingo@1107: } ingo@1107: catch (SchemaException se) { ingo@1107: logger.warn("Error while reading GeoJSON: " + se.getMessage()); ingo@1107: } ingo@1107: catch (NoSuchAuthorityCodeException nsae) { ingo@1107: logger.warn("Error while reading GeoJSON: " + nsae.getMessage()); ingo@1107: } ingo@1107: catch (FactoryException fe) { ingo@1107: logger.warn("Error while reading GeoJSON: " + fe.getMessage()); ingo@1107: } ingo@1107: ingo@1107: return features; ingo@1106: } ingo@1106: ingo@1106: ingo@1106: protected FeatureCollection[] splitLinesAndPolygons(List f) { ingo@1106: FeatureCollection lines = FeatureCollections.newCollection(); ingo@1106: FeatureCollection polygons = FeatureCollections.newCollection(); ingo@1106: ingo@1106: for (SimpleFeature feature: f) { ingo@1106: Object geom = feature.getDefaultGeometry(); ingo@1106: ingo@1106: if (geom instanceof LineString) { ingo@1106: lines.add(feature); ingo@1106: } ingo@1106: else if (geom instanceof Polygon) { ingo@1106: polygons.add(feature); ingo@1106: } ingo@1106: else { ingo@1106: logger.warn("Feature not supported: " + geom.getClass()); ingo@1106: } ingo@1106: } ingo@1106: ingo@1106: logger.debug("Found " + lines.size() + " barrier lines."); ingo@1106: logger.debug("Found " + polygons.size() + " barrier polygons."); ingo@1106: ingo@1106: return new FeatureCollection[] { lines, polygons }; ingo@1106: } ingo@927: } ingo@927: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :