rrenkert@5310: package de.intevation.flys.artifacts.states;
rrenkert@5310: 
rrenkert@5310: import java.io.File;
rrenkert@5310: import java.io.FileNotFoundException;
rrenkert@5310: import java.io.IOException;
teichmann@5313: 
rrenkert@5310: import java.util.ArrayList;
rrenkert@5310: import java.util.Arrays;
rrenkert@5310: import java.util.List;
rrenkert@5310: 
rrenkert@5310: import org.apache.log4j.Logger;
teichmann@5313: 
rrenkert@5310: import org.apache.velocity.Template;
teichmann@5313: 
rrenkert@5310: import org.geotools.data.shapefile.ShapefileDataStore;
teichmann@5313: 
rrenkert@5310: import org.geotools.feature.FeatureCollection;
rrenkert@5310: import org.geotools.feature.FeatureCollections;
teichmann@5313: 
rrenkert@5310: import org.opengis.feature.simple.SimpleFeatureType;
teichmann@5313: 
rrenkert@5310: import org.opengis.feature.type.GeometryDescriptor;
teichmann@5313: 
rrenkert@5310: import org.w3c.dom.Element;
rrenkert@5310: 
rrenkert@5310: import de.intevation.artifactdatabase.state.Facet;
teichmann@5313: 
rrenkert@5310: import de.intevation.artifacts.Artifact;
rrenkert@5310: import de.intevation.artifacts.CallContext;
teichmann@5313: 
rrenkert@5310: import de.intevation.artifacts.common.utils.FileTools;
teichmann@5313: 
rrenkert@5310: import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator;
teichmann@5313: 
rrenkert@5310: import de.intevation.flys.artifacts.FLYSArtifact;
teichmann@5313: 
rrenkert@5310: import de.intevation.flys.artifacts.access.MapAccess;
teichmann@5313: 
rrenkert@5310: import de.intevation.flys.artifacts.model.LayerInfo;
teichmann@5313: 
rrenkert@5310: import de.intevation.flys.artifacts.model.map.HWS;
rrenkert@5310: import de.intevation.flys.artifacts.model.map.HWSContainer;
rrenkert@5310: import de.intevation.flys.artifacts.model.map.HWSFactory;
teichmann@5313: 
rrenkert@5310: import de.intevation.flys.utils.ArtifactMapfileGenerator;
rrenkert@5310: import de.intevation.flys.utils.FLYSUtils;
rrenkert@5310: import de.intevation.flys.utils.GeometryUtils;
rrenkert@5310: import de.intevation.flys.utils.MapfileGenerator;
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";
rrenkert@5310:     private static final String USER_RGD_SHAPE     = "user-rgd.shp";
rrenkert@5310:     private static final String USER_RGD_ZIP       = "user-rgd.zip";
rrenkert@5310:     private static final String USER_RGD_FILENAME  = "user-rgd";
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(
rrenkert@5310:         FLYSArtifact   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(
rrenkert@5310:         FLYSArtifact artifact,
rrenkert@5310:         String hash,
rrenkert@5310:         CallContext context,
rrenkert@5310:         List<Facet> 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: 
rrenkert@5310:         MapAccess access = new MapAccess(artifact, context);
rrenkert@5310:         String river = access.getRiver();
rrenkert@5310:         HWSContainer hwsLines = HWSFactory.getHWSLines(river);
rrenkert@5310:         HWSContainer hwsPoints = HWSFactory.getHWSPoints(river);
rrenkert@5310:         List<String> selected = access.getHWS();
rrenkert@5310: 
rrenkert@5310:         List<HWS> selectedLines = hwsLines.getHws(selected);
rrenkert@5310:         List<HWS> 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) {
rrenkert@5310:             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) {
rrenkert@5310:             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() +
rrenkert@5310:                         "/" + 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:                     }
rrenkert@5310:                     createMapfile(
rrenkert@5310:                         artifact,
rrenkert@5310:                         artifactDir,
rrenkert@5310:                         MapfileGenerator.MS_LAYER_PREFIX + USER_RGD_FILENAME,
rrenkert@5310:                         USER_RGD_SHAPE,
rrenkert@5310:                         type,
rrenkert@5310:                         epsg,
rrenkert@5310:                         "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) {
rrenkert@5310:         // TODO Auto-generated method stub
rrenkert@5310:         File archive = new File(dir, 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 + "/"
rrenkert@5310:                     + 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 {
rrenkert@5310:                         FileTools.copyFile(file, new File(target, USER_RGD_FILENAME + "." + 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:     private void createMapfile(
rrenkert@5310:         FLYSArtifact artifact,
rrenkert@5310:         File artifactDir,
rrenkert@5310:         String name,
rrenkert@5310:         String hwsShapefile,
rrenkert@5310:         String type,
rrenkert@5310:         String srid,
rrenkert@5310:         String group
rrenkert@5310:     ) {
rrenkert@5310:         LayerInfo info = new LayerInfo();
rrenkert@5310:         info.setName(name + artifact.identifier());
rrenkert@5310:         info.setType(type);
rrenkert@5310:         info.setDirectory(artifact.identifier());
rrenkert@5310:         info.setTitle(name);
rrenkert@5310:         info.setData(hwsShapefile);
rrenkert@5310:         info.setSrid(srid);
rrenkert@5310:         info.setGroupTitle(group);
rrenkert@5310:         MapfileGenerator generator = new ArtifactMapfileGenerator();
rrenkert@5310:         Template tpl = generator.getTemplateByName(MapfileGenerator.SHP_LAYER_TEMPLATE);
rrenkert@5310:         try {
rrenkert@5310:             File layer = new File(artifactDir.getCanonicalPath() + "/" + name);
rrenkert@5310:             generator.writeLayer(info, layer, tpl);
rrenkert@5310:             List<String> layers = new ArrayList<String>();
rrenkert@5310:             layers.add(layer.getAbsolutePath());
rrenkert@5310:             generator.generate();
rrenkert@5310:         }
rrenkert@5310:         catch(FileNotFoundException fnfe) {
rrenkert@5310:             logger.warn("Could not find mapfile for hws layer");
rrenkert@5310:         }
rrenkert@5310:         catch (Exception ioe) {
rrenkert@5310:             logger.warn("Could not create mapfile for hws layer");
rrenkert@5310:             logger.warn(Arrays.toString(ioe.getStackTrace()));
rrenkert@5310:         }
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: 
rrenkert@5310:         FLYSArtifact flys = (FLYSArtifact) 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...
rrenkert@5310:     protected void removeDirectory(FLYSArtifact artifact) {
rrenkert@5310:         String shapePath = FLYSUtils.getXPathString(
rrenkert@5310:             FLYSUtils.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:      */
rrenkert@5310:     protected File getDirectory(FLYSArtifact artifact) {
rrenkert@5310:         String shapePath = FLYSUtils.getXPathString(
rrenkert@5310:             FLYSUtils.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 :