teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.states; rrenkert@5310: rrenkert@5310: import java.io.File; rrenkert@5310: import java.io.IOException; rrenkert@5310: import java.util.List; rrenkert@5310: rrenkert@5310: import org.apache.log4j.Logger; teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet; teichmann@5831: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.artifacts.common.utils.FileTools; teichmann@5831: import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.access.MapAccess; teichmann@5831: import org.dive4elements.river.artifacts.model.map.HWS; teichmann@5831: import org.dive4elements.river.artifacts.model.map.HWSContainer; teichmann@5831: import org.dive4elements.river.artifacts.model.map.HWSFactory; teichmann@5831: import org.dive4elements.river.utils.GeometryUtils; teichmann@5831: import org.dive4elements.river.utils.MapfileGenerator; christian@6710: import org.dive4elements.river.utils.RiverUtils; christian@6710: import org.geotools.data.shapefile.ShapefileDataStore; christian@6710: import org.geotools.feature.FeatureCollection; christian@6710: import org.geotools.feature.FeatureCollections; christian@6710: import org.opengis.feature.simple.SimpleFeatureType; christian@6710: import org.opengis.feature.type.GeometryDescriptor; christian@6710: import org.w3c.dom.Element; rrenkert@5310: rrenkert@5310: public class HWSBarriersState rrenkert@5310: extends DefaultState rrenkert@5310: { rrenkert@5310: rrenkert@5310: /** The logger that is used in this class.*/ rrenkert@5310: private static Logger logger = Logger.getLogger(HWSBarriersState.class); rrenkert@5310: private static final String HWS_SHAPEFILE_LINES = "hws-lines.shp"; rrenkert@5310: private static final String HWS_SHAPEFILE_POINTS = "hws-points.shp"; christian@6710: christian@6710: rrenkert@5310: @Override rrenkert@5310: protected String getUIProvider() { rrenkert@5310: return "map_digitize"; rrenkert@5310: } rrenkert@5310: rrenkert@5310: rrenkert@5310: @Override rrenkert@5310: protected Element createStaticData( teichmann@5867: D4EArtifact flys, rrenkert@5310: ElementCreator creator, rrenkert@5310: CallContext cc, rrenkert@5310: String name, rrenkert@5310: String value, rrenkert@5310: String type rrenkert@5310: ) { rrenkert@5310: Element dataElement = creator.create("data"); rrenkert@5310: creator.addAttr(dataElement, "name", name, true); rrenkert@5310: creator.addAttr(dataElement, "type", type, true); rrenkert@5310: rrenkert@5310: Element itemElement = creator.create("item"); rrenkert@5310: creator.addAttr(itemElement, "value", value, true); rrenkert@5310: rrenkert@5310: creator.addAttr(itemElement, "label", "", true); rrenkert@5310: dataElement.appendChild(itemElement); rrenkert@5310: rrenkert@5310: return dataElement; rrenkert@5310: } rrenkert@5310: rrenkert@5310: rrenkert@5310: @Override rrenkert@5310: public Object computeAdvance( teichmann@5867: D4EArtifact artifact, rrenkert@5310: String hash, rrenkert@5310: CallContext context, rrenkert@5310: List facets, rrenkert@5310: Object old rrenkert@5310: ) { rrenkert@5310: File artifactDir = getDirectory(artifact); rrenkert@5310: rrenkert@5310: if (artifactDir == null) { rrenkert@5310: logger.error("Could not create directory for HWS shapefile!"); rrenkert@5310: return null; rrenkert@5310: } rrenkert@5310: teichmann@6101: MapAccess access = new MapAccess(artifact); felix@7261: String river = access.getRiverName(); rrenkert@5310: HWSContainer hwsLines = HWSFactory.getHWSLines(river); rrenkert@5310: HWSContainer hwsPoints = HWSFactory.getHWSPoints(river); rrenkert@5310: List selected = access.getHWS(); rrenkert@5310: rrenkert@5310: List selectedLines = hwsLines.getHws(selected); rrenkert@5310: List selectedPoints = hwsPoints.getHws(selected); rrenkert@5310: rrenkert@5310: FeatureCollection collectionLines = FeatureCollections.newCollection(); rrenkert@5310: SimpleFeatureType lineType = null; rrenkert@5310: for (HWS h : selectedLines) { rrenkert@5310: lineType = h.getFeatureType(); rrenkert@5310: collectionLines.add(h.getFeature()); rrenkert@5310: } rrenkert@5310: boolean successLines = false; rrenkert@5310: if (lineType != null && collectionLines.size() > 0) { rrenkert@5310: File shapeLines = new File(artifactDir, HWS_SHAPEFILE_LINES); rrenkert@5310: successLines = GeometryUtils.writeShapefile( rrenkert@5310: shapeLines, lineType, collectionLines); rrenkert@5310: } rrenkert@5310: rrenkert@5310: FeatureCollection collectionPoints = FeatureCollections.newCollection(); rrenkert@5310: SimpleFeatureType pointType = null; rrenkert@5310: for (HWS h : selectedPoints) { rrenkert@5310: pointType = h.getFeatureType(); rrenkert@5310: collectionPoints.add(h.getFeature()); rrenkert@5310: } rrenkert@5310: boolean successPoints = false; rrenkert@5310: if (pointType != null && collectionPoints.size() > 0) { rrenkert@5310: File shapePoints = new File(artifactDir, HWS_SHAPEFILE_POINTS); rrenkert@5310: successPoints =GeometryUtils.writeShapefile( rrenkert@5310: shapePoints, pointType, collectionPoints); rrenkert@5310: } rrenkert@5310: rrenkert@5310: if (successLines) { christian@6710: FloodMapState.createMapfile( rrenkert@5310: artifact, rrenkert@5310: artifactDir, rrenkert@5310: MapfileGenerator.MS_LAYER_PREFIX + "hws-lines", rrenkert@5310: HWS_SHAPEFILE_LINES, rrenkert@5310: "LINE", rrenkert@5310: "31467", rrenkert@5310: "hws"); rrenkert@5310: } rrenkert@5310: if (successPoints) { christian@6710: FloodMapState.createMapfile( rrenkert@5310: artifact, rrenkert@5310: artifactDir, rrenkert@5310: MapfileGenerator.MS_LAYER_PREFIX + "hws-points", rrenkert@5310: HWS_SHAPEFILE_POINTS, rrenkert@5310: "POINT", rrenkert@5310: "31467", rrenkert@5310: "hws"); rrenkert@5310: } rrenkert@5310: rrenkert@5310: String userRgd = artifact.getDataAsString("uesk.user-rgd"); rrenkert@5310: if (!userRgd.equals("none")) { rrenkert@5310: if (extractUserShp(artifactDir)) { rrenkert@5310: try { rrenkert@5310: ShapefileDataStore store = new ShapefileDataStore( rrenkert@5310: new File(artifactDir.getCanonicalPath() + christian@6710: "/" + FloodMapState.WSPLGEN_USER_RGD_SHAPE) rrenkert@5310: .toURI().toURL()); rrenkert@5310: GeometryDescriptor desc = rrenkert@5310: store.getSchema().getGeometryDescriptor(); rrenkert@5310: String type = desc.getType().getName().toString(); rrenkert@5310: String proj = rrenkert@5310: desc.getCoordinateReferenceSystem(). rrenkert@5310: getCoordinateSystem().toString(); rrenkert@5310: int pos1 = proj.indexOf("EPSG\",\""); rrenkert@5310: int pos2 = proj.indexOf("\"]]"); rrenkert@5310: String epsg = ""; rrenkert@5310: if (pos1 >= 0 && pos2 >= 0) { rrenkert@5310: epsg = rrenkert@5310: proj.substring(proj.indexOf("EPSG\",\"") + 7, rrenkert@5310: proj.indexOf("\"]]")); rrenkert@5310: } rrenkert@5310: else { rrenkert@5310: logger.warn("Could not read EPSG code from shapefile."); rrenkert@5310: return null; rrenkert@5310: } rrenkert@5310: if (type.contains("Line")) { rrenkert@5310: type = "LINE"; rrenkert@5310: } rrenkert@5310: else if (type.contains("Poly")) { aheinecke@5394: type = "POLYGON"; rrenkert@5310: } rrenkert@5310: else { rrenkert@5310: type = "POINT"; rrenkert@5310: } christian@6710: FloodMapState.createMapfile( rrenkert@5310: artifact, rrenkert@5310: artifactDir, christian@6710: MapfileGenerator.MS_LAYER_PREFIX + FloodMapState.WSPLGEN_USER_RGD, christian@6710: FloodMapState.WSPLGEN_USER_RGD_SHAPE, rrenkert@5310: type, rrenkert@5310: epsg, christian@6710: FloodMapState.WSPLGEN_USER_RGD); rrenkert@5310: } rrenkert@5310: catch (IOException e) { rrenkert@5310: logger.warn("No mapfile for user-rgd created!"); rrenkert@5310: } rrenkert@5310: } rrenkert@5310: } rrenkert@5310: return null; rrenkert@5310: } rrenkert@5310: rrenkert@5310: private boolean extractUserShp(File dir) { christian@6710: File archive = new File(dir, FloodMapState.WSPLGEN_USER_RGD_ZIP); rrenkert@5310: boolean exists = archive.exists(); rrenkert@5310: logger.debug("Zip file exists: " + exists); rrenkert@5310: if (exists) { rrenkert@5310: try { rrenkert@5310: File tmpDir = new File(dir, "usr_tmp"); rrenkert@5310: FileTools.extractArchive(archive, tmpDir); rrenkert@5310: moveFiles(tmpDir, dir); rrenkert@5310: return true; rrenkert@5310: } rrenkert@5310: catch (IOException ioe) { rrenkert@5310: logger.warn("Zip archive " + dir + "/" christian@6710: + FloodMapState.WSPLGEN_USER_RGD_ZIP + " could not be extracted."); rrenkert@5310: return false; rrenkert@5310: } rrenkert@5310: } rrenkert@5310: return false; rrenkert@5310: } rrenkert@5310: rrenkert@5310: private void moveFiles(File source, final File target) rrenkert@5310: throws IOException rrenkert@5310: { rrenkert@5310: if (!source.exists()) { rrenkert@5310: return; rrenkert@5310: } rrenkert@5310: if (!target.exists()) { rrenkert@5310: target.mkdir(); rrenkert@5310: } rrenkert@5310: FileTools.walkTree(source, new FileTools.FileVisitor() { rrenkert@5310: @Override rrenkert@5310: public boolean visit(File file) { rrenkert@5310: if (!file.isDirectory()) { rrenkert@5310: String name = file.getName(); rrenkert@5310: String suffix = ""; rrenkert@5310: int pos = name.lastIndexOf('.'); rrenkert@5310: if (pos > 0 && pos < name.length() - 1) { rrenkert@5310: suffix = name.substring(pos + 1); rrenkert@5310: } rrenkert@5310: else { rrenkert@5310: return true; rrenkert@5310: } rrenkert@5310: try { christian@6710: FileTools.copyFile(file, new File(target, FloodMapState.WSPLGEN_USER_RGD + "." + suffix)); rrenkert@5310: } rrenkert@5310: catch (IOException ioe) { rrenkert@5310: logger.warn ("Error while copying file " + file.getName()); rrenkert@5310: return true; rrenkert@5310: } rrenkert@5310: } rrenkert@5310: return true; rrenkert@5310: } rrenkert@5310: }); rrenkert@5310: rrenkert@5310: FileTools.deleteRecursive(source); rrenkert@5310: } rrenkert@5310: rrenkert@5310: rrenkert@5310: @Override rrenkert@5310: public void endOfLife(Artifact artifact, Object callContext) { rrenkert@5310: super.endOfLife(artifact, callContext); rrenkert@5310: logger.info("ScenarioSelect.endOfLife: " + artifact.identifier()); rrenkert@5310: teichmann@5867: D4EArtifact flys = (D4EArtifact) artifact; rrenkert@5310: removeDirectory(flys); rrenkert@5310: } rrenkert@5310: rrenkert@5310: rrenkert@5310: /** rrenkert@5310: * Removes the directory and all its content where the required data and the rrenkert@5310: * results of WSPLGEN are stored. Should be called in endOfLife(). rrenkert@5310: */ rrenkert@5310: // FIXME: I've seen this code somewhere else... teichmann@5867: protected void removeDirectory(D4EArtifact artifact) { teichmann@5865: String shapePath = RiverUtils.getXPathString( teichmann@5865: RiverUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); rrenkert@5310: rrenkert@5310: File artifactDir = new File(shapePath, artifact.identifier()); rrenkert@5310: rrenkert@5310: if (artifactDir.exists()) { rrenkert@5310: logger.debug("Delete directory: " + artifactDir.getAbsolutePath()); rrenkert@5310: boolean success = FileTools.deleteRecursive(artifactDir); rrenkert@5310: if (!success) { rrenkert@5310: logger.warn("could not remove dir '" + artifactDir + "'"); rrenkert@5310: } rrenkert@5310: } rrenkert@5310: else { rrenkert@5310: logger.debug("There is no directory to remove."); rrenkert@5310: } rrenkert@5310: } rrenkert@5310: rrenkert@5310: /** rrenkert@5310: * Returns (and creates if not existing) the directory for storing WSPLEN rrenkert@5310: * data for the owner artifact. rrenkert@5310: * rrenkert@5310: * @param artifact The owner Artifact. rrenkert@5310: * rrenkert@5310: * @return the directory for WSPLEN data. rrenkert@5310: */ teichmann@5867: protected File getDirectory(D4EArtifact artifact) { teichmann@5865: String shapePath = RiverUtils.getXPathString( teichmann@5865: RiverUtils.XPATH_FLOODMAP_SHAPEFILE_DIR); rrenkert@5310: rrenkert@5310: File artifactDir = FileTools.getDirectory( rrenkert@5310: shapePath, artifact.identifier()); rrenkert@5310: rrenkert@5310: return artifactDir; rrenkert@5310: } rrenkert@5310: rrenkert@5310: } teichmann@5313: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :