ingo@927: package de.intevation.flys.artifacts.states;
ingo@927: 
ingo@1091: import java.io.File;
ingo@1118: import java.io.FileNotFoundException;
ingo@1118: import java.io.FileOutputStream;
ingo@1091: import java.io.IOException;
ingo@1123: import java.util.ArrayList;
ingo@935: import java.util.List;
ingo@935: 
ingo@3302: import org.apache.log4j.Logger;
ingo@3302: import org.geotools.feature.FeatureCollection;
ingo@3302: import org.geotools.feature.FeatureCollections;
ingo@3302: import org.geotools.feature.simple.SimpleFeatureBuilder;
ingo@3302: import org.opengis.feature.simple.SimpleFeature;
ingo@3302: import org.opengis.feature.simple.SimpleFeatureType;
ingo@3302: 
ingo@1123: import com.vividsolutions.jts.geom.Coordinate;
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@3302: import de.intevation.artifactdatabase.state.Facet;
ingo@1091: import de.intevation.artifacts.Artifact;
ingo@935: import de.intevation.artifacts.CallContext;
ingo@2093: import de.intevation.artifacts.CallMeta;
ingo@1970: import de.intevation.artifacts.GlobalContext;
ingo@1091: import de.intevation.artifacts.common.utils.FileTools;
ingo@935: import de.intevation.flys.artifacts.FLYSArtifact;
ingo@1970: import de.intevation.flys.artifacts.context.FLYSContext;
ingo@1165: import de.intevation.flys.artifacts.model.CalculationMessage;
ingo@1118: import de.intevation.flys.artifacts.model.CalculationResult;
ingo@927: import de.intevation.flys.artifacts.model.FacetTypes;
ingo@1118: import de.intevation.flys.artifacts.model.WQKms;
ingo@3302: import de.intevation.flys.artifacts.model.map.WMSLayerFacet;
ingo@3302: import de.intevation.flys.artifacts.model.map.WSPLGENCalculation;
ingo@3302: import de.intevation.flys.artifacts.model.map.WSPLGENJob;
ingo@3302: import de.intevation.flys.artifacts.model.map.WSPLGENReportFacet;
ingo@1165: import de.intevation.flys.artifacts.resources.Resources;
ingo@1118: import de.intevation.flys.exports.WstWriter;
ingo@3302: import de.intevation.flys.model.CrossSectionTrack;
ingo@3302: import de.intevation.flys.model.DGM;
ingo@3302: import de.intevation.flys.model.Floodplain;
ingo@3302: import de.intevation.flys.model.RiverAxis;
ingo@1096: import de.intevation.flys.utils.FLYSUtils;
ingo@3302: import de.intevation.flys.utils.GeometryUtils;
ingo@1782: import de.intevation.flys.utils.MapfileGenerator;
ingo@1650: import de.intevation.flys.wsplgen.FacetCreator;
ingo@1165: import de.intevation.flys.wsplgen.JobObserver;
ingo@1127: import de.intevation.flys.wsplgen.Scheduler;
ingo@927: 
ingo@927: 
ingo@927: public class FloodMapState
ingo@927: extends      DefaultState
ingo@927: implements   FacetTypes
ingo@927: {
felix@1160:     /** 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@2095:     public static final String OUTPUT_NAME = "floodmap";
ingo@2095: 
ingo@1178:     public static final String WSP_ARTIFACT = "wsp";
ingo@1118: 
ingo@1118:     public static final String WINFO_WSP_STATE_ID = "state.winfo.waterlevel";
ingo@1118: 
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@1108:     public static final String WSPLGEN_AXIS           = "axis.shp";
ingo@1108:     public static final String WSPLGEN_QPS            = "qps.shp";
ingo@1110:     public static final String WSPLGEN_FLOODPLAIN     = "talaue.shp";
ingo@1120:     public static final String WSPLGEN_WSP_FILE       = "waterlevel.wst";
ingo@1118:     public static final String WSPLGEN_OUTPUT_FILE    = "wsplgen.shp";
raimund@2639:     public static final String WSPLGEN_USER_SHAPE     = "user-rgd.shp";
raimund@2639:     public static final String WSPLGEN_USER_ZIP       = "user-rgd.zip";
raimund@2639:     public static final String WSPLGEN_USER_FILENAME  = "user-rgd";
ingo@1091: 
ingo@3070:     public static final String WSPLGEN_QPS_NAME = "qps";
ingo@3070: 
ingo@1096:     public static final int WSPLGEN_DEFAULT_OUTPUT = 0;
ingo@1096: 
ingo@1091: 
ingo@2095:     /**
ingo@2095:      * @param orig
ingo@2095:      * @param owner
ingo@2095:      * @param context
ingo@2095:      * @param callMeta
ingo@2095:      */
ingo@2093:     @Override
ingo@2095:     public void initialize(
ingo@2095:         Artifact orig,
ingo@2095:         Artifact owner,
ingo@2095:         Object   context,
ingo@2095:         CallMeta callMeta
ingo@2095:     ) {
ingo@2093:         logger.info("Initialize State with Artifact: " + orig.identifier());
ingo@2095: 
ingo@2095:         copyShapeDir(orig, owner);
ingo@2095:         modifyFacets(orig, owner, context, callMeta);
ingo@2095: 
ingo@2095:         MapfileGenerator.getInstance().update();
ingo@2093:     }
ingo@2093: 
ingo@2093: 
ingo@2095:     protected void copyShapeDir(Artifact orig, Artifact owner) {
ingo@2095:         File origDir = getDirectory((FLYSArtifact) orig);
ingo@2095:         File thisDir = getDirectory((FLYSArtifact) owner);
ingo@2095: 
ingo@2095:         FileTools.copyDirectory(origDir, thisDir);
ingo@2095:     }
ingo@2095: 
ingo@2095: 
ingo@2095:     protected void modifyFacets(
ingo@2095:         Artifact orig,
ingo@2095:         Artifact owner,
ingo@2095:         Object   context,
ingo@2095:         CallMeta callMeta
ingo@2095:     ) {
ingo@2095:         FLYSArtifact flys  = (FLYSArtifact) owner;
ingo@2095:         List<Facet> facets = flys.getFacets();
sascha@3555:         if (facets == null || facets.isEmpty()) {
ingo@2095:             logger.warn("No facets for '" + OUTPUT_NAME + "' given!");
ingo@2095:             return;
ingo@2095:         }
ingo@2095: 
ingo@2095:         for (Facet facet: facets) {
ingo@2095:             if (facet instanceof WMSLayerFacet) {
ingo@2095:                 WMSLayerFacet wms = (WMSLayerFacet) facet;
ingo@2095: 
ingo@2095:                 List<String> layers = wms.getLayers();
ingo@2095: 
ingo@2095:                 for (String layer: layers) {
ingo@2095:                     if (layer.startsWith(MapfileGenerator.MS_WSPLGEN_PREFIX)) {
ingo@2095:                         wms.removeLayer(layer);
ingo@2095: 
ingo@2095:                         String newLayer = MapfileGenerator.MS_WSPLGEN_PREFIX +
ingo@2095:                             owner.identifier();
ingo@2095: 
ingo@2095:                         wms.addLayer(newLayer);
ingo@2095: 
ingo@2095:                         logger.debug(
ingo@2095:                             "Replaced layer: " + layer + " with " + newLayer);
ingo@2095:                     }
ingo@2095:                 }
ingo@2095:             }
ingo@2095:         }
ingo@2095:     }
ingo@2095: 
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<Facet>  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@1149:         WSPLGENCalculation calculation = new WSPLGENCalculation();
ingo@1149: 
ingo@1638:         FacetCreator facetCreator = new FacetCreator(
ingo@1650:             artifact, context, hash, getID(), facets);
ingo@1164: 
ingo@1149:         WSPLGENJob job = prepareWSPLGENJob(
ingo@1149:             artifact,
ingo@1164:             facetCreator,
ingo@1149:             artifactDir,
ingo@1149:             context,
ingo@1149:             calculation);
ingo@1091: 
ingo@1168:         CalculationResult  res   = new CalculationResult(null, calculation);
ingo@1168:         WSPLGENReportFacet report= new WSPLGENReportFacet(
ingo@1168:             ComputeType.ADVANCE, hash, getID(), res);
ingo@1168: 
ingo@1168:         facets.add(report);
ingo@1168: 
ingo@1091:         if (job == null) {
ingo@1107:             if (KEEP_ARTIFACT_DIR.equals("false")) {
ingo@1107:                 removeDirectory(artifact);
ingo@1107:             }
ingo@1091: 
ingo@1168:             calculation.addError(-1, Resources.getMsg(
ingo@1168:                 context.getMeta(),
ingo@1168:                 "wsplgen.job.error",
ingo@1168:                 "wsplgen.job.error"));
ingo@1168: 
ingo@1091:             logger.error("No WSPLGEN processing has been started!");
ingo@1091: 
ingo@1091:             return null;
ingo@1091:         }
ingo@1091: 
ingo@1128:         context.afterCall(CallContext.BACKGROUND);
ingo@1165:         context.addBackgroundMessage(new CalculationMessage(
ingo@1165:             JobObserver.STEPS.length,
ingo@1165:             0,
ingo@1165:             Resources.getMsg(
ingo@1165:                 context.getMeta(),
ingo@1165:                 "wsplgen.job.queued",
ingo@1165:                 "wsplgen.job.queued")
ingo@1165:         ));
ingo@1091: 
ingo@1970:         GlobalContext gc    = (GlobalContext) context.globalContext();
ingo@1970:         Scheduler scheduler = (Scheduler) gc.get(FLYSContext.SCHEDULER);
ingo@1649:         scheduler.addJob(job);
ingo@1649: 
ingo@1091:         return null;
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@1129:         String shapePath = FLYSUtils.getXPathString(
ingo@1129:             FLYSUtils.XPATH_SHAPEFILE_DIR);
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@1129:         String shapePath = FLYSUtils.getXPathString(
ingo@1129:             FLYSUtils.XPATH_SHAPEFILE_DIR);
ingo@1129: 
ingo@1129:         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@1782: 
ingo@1970:         Scheduler scheduler = Scheduler.getInstance();
ingo@1970:         scheduler.cancelJob(flys.identifier());
ingo@1970: 
ingo@1782:         MapfileGenerator.getInstance().update();
ingo@1091:     }
ingo@1091: 
ingo@1091: 
ingo@1091:     protected WSPLGENJob prepareWSPLGENJob(
ingo@1149:         FLYSArtifact       artifact,
ingo@1164:         FacetCreator       facetCreator,
ingo@1149:         File               artifactDir,
ingo@1149:         CallContext        context,
ingo@1149:         WSPLGENCalculation calculation
ingo@1091:     ) {
ingo@1091:         logger.debug("FloodMapState.prepareWSPLGENJob");
ingo@1091: 
ingo@1149:         WSPLGENJob job = new WSPLGENJob(
ingo@1149:             artifact,
ingo@1149:             artifactDir,
ingo@1650:             facetCreator,
ingo@1149:             context,
ingo@1149:             calculation);
ingo@1149: 
ingo@1149:         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@1164:         setLine(artifact, facetCreator, artifactDir, job);
raimund@2639:         setUserShape(artifact, facetCreator, artifactDir, job);
ingo@1108:         setAxis(artifact, artifactDir, job);
ingo@1108:         setPro(artifact, artifactDir, job);
ingo@1109:         setDgm(artifact, job);
ingo@1110:         setArea(artifact, artifactDir, job);
ingo@1118:         setOutFile(artifact, job);
ingo@1118:         setWsp(artifact, context, artifactDir, job);    // WSP
ingo@1096: 
ingo@1096:         // TODO
ingo@1096:         // setWspTag(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@1955:         String gel = artifact.getDataAsString("scenario");
ingo@1096: 
ingo@1955:         logger.debug("Selected gel = '" + gel + "'");
ingo@1955: 
ingo@1955:         if (gel == null || gel.length() == 0) {
ingo@1955:             job.setGel(WSPLGENJob.GEL_NOSPERRE);
ingo@1955:         }
ingo@1955:         else if (gel.equals("scenario.current")) {
ingo@1955:             job.setGel(WSPLGENJob.GEL_SPERRE);
ingo@1955:         }
ingo@1955:         else if (gel.equals("scenario.scenario")) {
ingo@1955:             job.setGel(WSPLGENJob.GEL_SPERRE);
ingo@1955:         }
ingo@1955:         else {
ingo@1955:             job.setGel(WSPLGENJob.GEL_NOSPERRE);
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@1164:     protected void setLine(
ingo@1164:         FLYSArtifact artifact,
ingo@1164:         FacetCreator facetCreator,
ingo@1164:         File         dir,
ingo@1164:         WSPLGENJob   job
ingo@1164:     ) {
ingo@1106:         String geoJSON = artifact.getDataAsString("uesk.barriers");
ingo@1106:         String srid    = FLYSUtils.getRiverSrid(artifact);
ingo@1106:         String srs     = "EPSG:" + srid;
ingo@1106: 
ingo@1164:         if (geoJSON == null || geoJSON.length() == 0) {
ingo@1164:             logger.debug("No barrier features in parameterization existing.");
ingo@1164:             return;
ingo@1164:         }
ingo@1164: 
ingo@1123:         SimpleFeatureType ft = getBarriersFeatureType(
ingo@1123:             "barriers", srs, Geometry.class);
ingo@1123: 
ingo@1123:         List<SimpleFeature> features = GeometryUtils.parseGeoJSON(geoJSON, ft);
sascha@3555:         if (features == null || features.isEmpty()) {
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@1124:         Object[][] obj = new Object[][] {
ingo@1124:             new Object[] { "typ", String.class }
ingo@1124:         };
ingo@1124: 
ingo@1955:         String scenario = job.getGel();
ingo@1955: 
ingo@1121:         boolean l = GeometryUtils.writeShapefile(
ingo@1121:             shapeLines,
ingo@1124:             GeometryUtils.buildFeatureType("lines", srs, LineString.class, obj),
ingo@1121:             fcs[0]);
ingo@1106: 
ingo@1121:         if (l) {
ingo@1123:             logger.debug(
ingo@1123:                 "Successfully created barrier line shapefile. " +
ingo@1123:                 "Write shapefile path into WSPLGEN job.");
ingo@1955: 
ingo@1955:             if (scenario.equals(WSPLGENJob.GEL_NOSPERRE)) {
ingo@1955:                 logger.debug("WSPLGEN will not use barrier features.");
ingo@1955:             }
ingo@1955:             else {
ingo@1955:                 job.addLin(shapeLines.getAbsolutePath());
ingo@1955:             }
ingo@1121:         }
ingo@1121: 
ingo@1121:         boolean p = GeometryUtils.writeShapefile(
ingo@1121:             shapePolys,
ingo@1124:             GeometryUtils.buildFeatureType("polygons", srs, Polygon.class, obj),
ingo@1121:             fcs[1]);
ingo@1121: 
ingo@1121:         if (p) {
ingo@1123:             logger.debug(
ingo@1123:                 "Successfully created barrier polygon shapefile. " +
ingo@1123:                 "Write shapefile path into WSPLGEN job.");
ingo@1955: 
ingo@1955:             if (scenario.equals(WSPLGENJob.GEL_NOSPERRE)) {
ingo@1955:                 logger.debug("WSPLGEN will not use barrier features.");
ingo@1955:             }
ingo@1955:             else {
ingo@1955:                 job.addLin(shapePolys.getAbsolutePath());
ingo@1955:             }
ingo@1106:         }
ingo@1164: 
ingo@1164:         if (p || l) {
ingo@1164:             facetCreator.createBarrierFacet();
ingo@1164:         }
ingo@1107:     }
ingo@1107: 
ingo@1107: 
raimund@2639:     protected void setUserShape(
raimund@2639:         FLYSArtifact artifact,
raimund@2639:         FacetCreator facetCreator,
raimund@2639:         File         dir,
raimund@2639:         WSPLGENJob   job
raimund@2639:     ) {
raimund@2639:         File archive = new File(dir, WSPLGEN_USER_ZIP);
raimund@2639:         boolean exists = archive.exists();
raimund@2639:         logger.debug("Zip file exists: " + exists);
raimund@2639:         if (exists) {
raimund@2639:             try {
raimund@2639:                 File tmpDir = new File(dir, "usr_tmp");
raimund@2639:                 FileTools.extractArchive(archive, tmpDir);
raimund@2639:                 moveFiles(tmpDir, dir);
raimund@2639:             }
raimund@2639:             catch (IOException ioe) {
raimund@2639:                 logger.warn("Zip archive " + dir + "/" + WSPLGEN_USER_ZIP + " could not be extracted.");
raimund@2639:                 return;
raimund@2639:             }
raimund@2639: 
raimund@2639:             job.addLin(dir + "/" + WSPLGEN_USER_SHAPE);
raimund@2639:             facetCreator.createUserShapeFacet();
raimund@2639:         }
raimund@2639:     }
raimund@2639: 
ingo@1123:     protected SimpleFeatureType getBarriersFeatureType(
ingo@1123:         String name,
ingo@1123:         String srs,
ingo@1123:         Class  type
ingo@1123:     ) {
ingo@1707:         Object[][] attrs = new Object[3][];
ingo@1123:         attrs[0] = new Object[] { "typ", String.class };
ingo@1123:         attrs[1] = new Object[] { "elevation", Double.class };
ingo@1707:         attrs[2] = new Object[] { "mark.selected", Integer.class };
ingo@1107: 
ingo@1123:         return GeometryUtils.buildFeatureType(name, srs, type, attrs);
ingo@1106:     }
ingo@1106: 
ingo@1106: 
ingo@1106:     protected FeatureCollection[] splitLinesAndPolygons(List<SimpleFeature> f) {
ingo@1106:         FeatureCollection lines    = FeatureCollections.newCollection();
ingo@1106:         FeatureCollection polygons = FeatureCollections.newCollection();
ingo@1106: 
ingo@1106:         for (SimpleFeature feature: f) {
ingo@1119:             Geometry geom = (Geometry) feature.getDefaultGeometry();
ingo@1106: 
ingo@1123: 
ingo@1106:             if (geom instanceof LineString) {
ingo@1123:                 geom = applyElevationAttribute(feature, (LineString) geom);
ingo@1106:                 lines.add(feature);
ingo@1106:             }
ingo@1106:             else if (geom instanceof Polygon) {
ingo@1123:                 geom = applyElevationAttribute(feature, (Polygon) geom);
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@1108: 
ingo@1108: 
ingo@1123:     protected static Geometry applyElevationAttribute(
ingo@1123:         SimpleFeature feature,
ingo@1123:         Geometry      geom
ingo@1123:     ) {
ingo@1123:         logger.debug("Apply elevations for: " + geom.getClass());
ingo@1123: 
ingo@1123:         List<Double> elevations = extractElevations(feature);
ingo@1123:         int           numPoints = geom.getNumPoints();
ingo@1123:         int        numElevation = elevations.size();
ingo@1123: 
ingo@1123:         String typ = (String) feature.getAttribute("typ");
ingo@1123: 
ingo@1123:         if (numPoints > numElevation) {
ingo@1123:             logger.warn("More vertices in Geometry than elevations given.");
ingo@1123:         }
ingo@1123: 
ingo@1123:         Coordinate[] c = geom.getCoordinates();
ingo@1123:         for (int i = 0; i < numPoints; i++) {
ingo@1123:             if (i < numElevation) {
ingo@1123:                 c[i].z = elevations.get(i);
ingo@1123:             }
ingo@1123:             else if (typ != null && typ.equals("Graben")) {
ingo@1123:                 c[i].z = -9999d;
ingo@1123:             }
ingo@1123:             else {
ingo@1123:                 c[i].z = 9999d;
ingo@1123:             }
ingo@1123:         }
ingo@1123: 
ingo@1123:         return geom;
ingo@1123:     }
ingo@1123: 
ingo@1123: 
ingo@1123:     protected static List<Double> extractElevations(SimpleFeature feature) {
ingo@1123:         String tmp = (String) feature.getAttribute("elevation");
ingo@1123:         String typ = (String) feature.getAttribute("typ");
ingo@1123: 
ingo@1123:         String[] elevations = tmp == null ? null : tmp.split(" ");
ingo@1123: 
ingo@1123:         int num = elevations != null ? elevations.length : 0;
ingo@1123: 
ingo@1123:         List<Double> list = new ArrayList<Double>(num);
ingo@1123: 
ingo@1123:         for (int i = 0; i < num; i++) {
ingo@1123:             try {
ingo@1123:                 list.add(Double.parseDouble(elevations[i]));
ingo@1123:             }
ingo@1123:             catch (NumberFormatException nfe) {
ingo@1123:                 logger.warn("Error while parsing elevation at pos: " + i);
ingo@1123:                 if (typ != null && typ.equals("Graben")) {
ingo@1123:                     list.add(new Double(-9999.0));
ingo@1123:                 }
ingo@1123:                 else {
ingo@1123:                     list.add(new Double(9999.0));
ingo@1123:                 }
ingo@1123:             }
ingo@1123:         }
ingo@1123: 
ingo@1123:         return list;
ingo@1123:     }
ingo@1123: 
ingo@1123: 
ingo@1108:     protected void setAxis(FLYSArtifact artifact, File dir, WSPLGENJob job) {
ingo@1108:         String river = artifact.getDataAsString("river");
ingo@1108:         String srid    = FLYSUtils.getRiverSrid(artifact);
ingo@1108:         String srs     = "EPSG:" + srid;
ingo@1108: 
ingo@2078:         List<RiverAxis> axes = RiverAxis.getRiverAxis(river);
sascha@3555:         if (axes == null || axes.isEmpty()) {
ingo@1108:             logger.warn("Could not find river axis for: '" + river + "'");
ingo@1108:             return;
ingo@1108:         }
ingo@1108: 
ingo@1108:         SimpleFeatureType ft = GeometryUtils.buildFeatureType(
ingo@1108:             "axis", srs, LineString.class);
ingo@1108: 
ingo@1108:         SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft);
ingo@2078:         FeatureCollection collection = FeatureCollections.newCollection();
ingo@1108: 
ingo@2078:         for (int i = 0, n = axes.size(); i < n; i++) {
ingo@2078:             RiverAxis axis = axes.get(i);
ingo@2078: 
ingo@2078:             builder.add(axis.getGeom());
ingo@2078:             collection.add(builder.buildFeature(String.valueOf(i)));
ingo@2078: 
ingo@2078:             builder.reset();
ingo@2078:         }
ingo@1108: 
ingo@1108:         File axisShape = new File(dir, WSPLGEN_AXIS);
ingo@1108: 
ingo@1121:         boolean a = GeometryUtils.writeShapefile(
ingo@1121:             axisShape,
ingo@1121:             GeometryUtils.buildFeatureType("axis", srs, LineString.class),
ingo@1121:             collection);
ingo@1121: 
ingo@1121:         if (a) {
ingo@1108:             job.setAxis(axisShape.getAbsolutePath());
ingo@1108:         }
ingo@1108:     }
ingo@1108: 
ingo@1108: 
ingo@1108:     protected void setPro(FLYSArtifact artifact, File dir, WSPLGENJob job) {
ingo@1108:         String river = artifact.getDataAsString("river");
ingo@1108:         String srid    = FLYSUtils.getRiverSrid(artifact);
ingo@1108:         String srs     = "EPSG:" + srid;
ingo@1108: 
ingo@1108:         List<CrossSectionTrack> cst =
ingo@3070:             CrossSectionTrack.getCrossSectionTrack(river, WSPLGEN_QPS_NAME);
ingo@1108: 
ingo@1108:         logger.debug("Found " + cst.size() + " CrossSectionTracks.");
ingo@1108: 
ingo@1119:         Object[][] attrs = new Object[2][];
ingo@1119:         attrs[0] = new Object[] { "ELEVATION", Double.class };
ingo@1119:         attrs[1] = new Object[] { "KILOMETER", Double.class };
ingo@1119: 
ingo@1108:         SimpleFeatureType ft = GeometryUtils.buildFeatureType(
ingo@1119:             "qps", srs, LineString.class, attrs);
ingo@1108: 
ingo@1108:         SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft);
ingo@1108:         FeatureCollection collection = FeatureCollections.newCollection();
ingo@1108: 
ingo@1108:         int i = 0;
ingo@1108:         for (CrossSectionTrack track: cst) {
ingo@1108:             builder.reset();
ingo@1108:             builder.add(track.getGeom());
ingo@1119:             builder.add(track.getZ().doubleValue());
ingo@1119:             builder.add(track.getKm().doubleValue());
ingo@1108: 
ingo@1108:             collection.add(builder.buildFeature(String.valueOf(i++)));
ingo@1108:         }
ingo@1108: 
ingo@1108:         File qpsShape = new File(dir, WSPLGEN_QPS);
ingo@1108: 
ingo@1121:         boolean q = GeometryUtils.writeShapefile(
ingo@1121:             qpsShape,
ingo@1121:             GeometryUtils.buildFeatureType("qps", srs, LineString.class, attrs),
ingo@1121:             collection);
ingo@1121: 
ingo@1121:         if (q) {
ingo@1108:             job.setPro(qpsShape.getAbsolutePath());
ingo@1108:         }
ingo@1108:     }
ingo@1109: 
ingo@1109: 
ingo@1109:     protected void setDgm(FLYSArtifact artifact, WSPLGENJob job) {
ingo@1186:         String dgm_id = artifact.getDataAsString("dgm");
ingo@1109: 
ingo@1186:         int id = -1;
ingo@1186:         try {
ingo@1186:             id = Integer.parseInt(dgm_id);
ingo@1186:         }
ingo@1186:         catch (NumberFormatException nfe) { /* do nothing */ }
ingo@1186: 
ingo@1186:         DGM dgm = DGM.getDGM(id);
ingo@1109: 
ingo@1109:         if (dgm == null) {
ingo@1186:             logger.warn("Could not find specified DGM.");
ingo@1109: 
ingo@1109:             return;
ingo@1109:         }
ingo@1109: 
ingo@1109:         job.setDgm(dgm.getPath());
ingo@1109:     }
ingo@1110: 
ingo@1110: 
ingo@1110:     protected void setArea(FLYSArtifact artifact, File dir, WSPLGENJob job) {
ingo@1955:         String useFloodplain = artifact.getDataAsString("use_floodplain");
ingo@1955:         if (!Boolean.valueOf(useFloodplain)) {
ingo@1955:             logger.debug("WSPLGEN will not use floodplain.");
ingo@1955:             return;
ingo@1955:         }
ingo@1955: 
ingo@1110:         String river = artifact.getDataAsString("river");
ingo@1110:         String srid  = FLYSUtils.getRiverSrid(artifact);
ingo@1110:         String srs   = "EPSG:" + srid;
ingo@1110: 
ingo@1110:         Floodplain plain = Floodplain.getFloodplain(river);
ingo@1110: 
ingo@1110:         SimpleFeatureType ft = GeometryUtils.buildFeatureType(
ingo@1845:             "talaue", srs, Polygon.class);
ingo@1110: 
ingo@1110:         SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft);
ingo@1110:         builder.add(plain.getGeom());
ingo@1110: 
ingo@1110:         FeatureCollection collection = FeatureCollections.newCollection();
ingo@1110:         collection.add(builder.buildFeature("0"));
ingo@1110: 
ingo@1110:         File talaueShape = new File(dir, WSPLGEN_FLOODPLAIN);
ingo@1110: 
ingo@1121:         boolean t = GeometryUtils.writeShapefile(
ingo@1121:             talaueShape,
ingo@1845:             GeometryUtils.buildFeatureType("talaue", srs, Polygon.class),
ingo@1121:             collection);
ingo@1121: 
ingo@1121:         if (t) {
ingo@1110:             job.setArea(talaueShape.getAbsolutePath());
ingo@1110:         }
ingo@1110:     }
ingo@1118: 
ingo@1118: 
ingo@1118:     protected void setOutFile(FLYSArtifact artifact, WSPLGENJob job) {
ingo@1118:         job.setOutFile(WSPLGEN_OUTPUT_FILE);
ingo@1118:     }
ingo@1118: 
ingo@1118: 
ingo@1178:     protected WQKms getWQKms(FLYSArtifact flys, CallContext cc) {
ingo@1178:         String   wspString = flys.getDataAsString(WSP_ARTIFACT);
ingo@1178:         String[] parts     = wspString.split(";");
ingo@1178: 
ingo@1178:         String otherArtifact = parts[0];
ingo@1178: 
ingo@1178:         int idx = -1;
ingo@1178:         try {
ingo@1178:             idx = Integer.parseInt(parts[2]);
ingo@1178:         }
ingo@1178:         catch (NumberFormatException nfe) { /* do nothing */ }
ingo@1178: 
ingo@1178:         FLYSArtifact src = otherArtifact != null
ingo@1178:             ? FLYSUtils.getArtifact(otherArtifact, cc)
ingo@1178:             : flys;
ingo@1178: 
ingo@1178:         logger.debug("Use waterlevel provided by Artifact: " + src.identifier());
ingo@1178: 
ingo@1178:         CalculationResult rawData = (CalculationResult) src.compute(
ingo@1178:             cc,
ingo@1178:             null,
ingo@1178:             WINFO_WSP_STATE_ID,
ingo@1178:             ComputeType.ADVANCE,
ingo@1178:             false);
ingo@1178: 
ingo@1178:         WQKms[] wqkms = (WQKms[]) rawData.getData();
ingo@1178: 
ingo@1178:         return wqkms == null || idx == -1 || idx >= wqkms.length
ingo@1178:             ? null
ingo@1178:             : wqkms[idx];
ingo@1178:     }
ingo@1178: 
ingo@1178: 
ingo@1118:     protected void setWsp(
ingo@1118:         FLYSArtifact artifact,
ingo@1118:         CallContext  context,
ingo@1118:         File         dir,
ingo@1118:         WSPLGENJob   job)
ingo@1118:     {
ingo@1118:         logger.debug("FloodMapState.setWsp");
ingo@1118: 
ingo@1178:         WQKms data = getWQKms(artifact, context);
ingo@1118: 
ingo@1178:         if (data == null) {
ingo@1118:             logger.warn("No WST data found!");
ingo@1118:             return;
ingo@1118:         }
ingo@1118: 
ingo@1178:         WstWriter writer = new WstWriter(1);
ingo@1118: 
ingo@1118:         // TODO REMOVE job.setWspTag(...) This is only used until the user is
ingo@1118:         // able to select the WSP column himself!
ingo@1118:         boolean writeWspTag = true;
ingo@1118: 
ingo@1118:         double[] buf = new double[4];
ingo@1178:         logger.debug("Add WST column: " + data.getName());
ingo@1178:         writer.addColumn(data.getName());
ingo@1118: 
ingo@1178:         if (writeWspTag) {
ingo@1178:             job.setWspTag(data.getName());
ingo@1178:             writeWspTag = false;
ingo@1178:         }
ingo@1118: 
ingo@1178:         for (int i = 0, num = data.size(); i < num; i++) {
ingo@1178:             data.get(i, buf);
ingo@1178:             writer.add(buf);
ingo@1118:         }
ingo@1118: 
ingo@1118:         FileOutputStream fout = null;
ingo@1118: 
ingo@1118:         try {
ingo@1118:             File wspFile = new File(dir, WSPLGEN_WSP_FILE);
ingo@1118:             fout         = new FileOutputStream(wspFile);
ingo@1118: 
ingo@1118:             writer.write(fout);
ingo@1118: 
ingo@1118:             job.setWsp(wspFile.getAbsolutePath());
ingo@1118:         }
ingo@1118:         catch (FileNotFoundException fnfe) {
ingo@1118:             logger.warn("Error while writing wsp file: " + fnfe.getMessage());
ingo@1118:         }
ingo@1118:         finally {
ingo@1118:             if (fout != null) {
ingo@1118:                 try {
ingo@1118:                     fout.close();
ingo@1118:                 }
ingo@1118:                 catch (IOException ioe) { /* do nothing */ }
ingo@1118:             }
ingo@1118:         }
ingo@1118:     }
raimund@2639: 
raimund@2639: 
raimund@2639:     protected void moveFiles(File source, final File target)
raimund@2639:     throws IOException
raimund@2639:     {
raimund@2639:         if (!source.exists()) {
raimund@2639:             return;
raimund@2639:         }
raimund@2639:         if (!target.exists()) {
raimund@2639:             target.mkdir();
raimund@2639:         }
raimund@2639:         FileTools.walkTree(source, new FileTools.FileVisitor() {
raimund@2639:             public boolean visit(File file) {
raimund@2639:                 if (!file.isDirectory()) {
raimund@2639:                     String name = file.getName();
raimund@2639:                     String suffix = "";
raimund@2639:                     int pos = name.lastIndexOf('.');
raimund@2639:                     if (pos > 0 && pos < name.length() - 1) {
raimund@2639:                         suffix = name.substring(pos + 1);
raimund@2639:                     }
raimund@2639:                     else {
raimund@2639:                         return true;
raimund@2639:                     }
raimund@2639:                     try {
raimund@2639:                         FileTools.copyFile(file, new File(target, WSPLGEN_USER_FILENAME + "." + suffix));
raimund@2639:                     }
raimund@2639:                     catch (IOException ioe) {
raimund@2639:                         logger.warn ("Error while copying file " + file.getName());
raimund@2639:                         return true;
raimund@2639:                     }
raimund@2639:                 }
raimund@2639:                 return true;
raimund@2639:             }
raimund@2639:         });
raimund@2639: 
raimund@2639:         FileTools.deleteRecursive(source);
raimund@2639:     }
ingo@927: }
ingo@927: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :