/** * Copyright (C) 2007 - 2016 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * • Apache License, version 2.0 * • Apache Software License, version 1.0 * • GNU Lesser General Public License, version 3 * • Mozilla Public License, versions 1.0, 1.1 and 2.0 * • Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * License version 2 and the aforementioned licenses. * * As an exception to the terms of the GPL, you may copy, modify, * propagate, and distribute a work formed by combining 52°North WPS * GeoTools Modules with the Eclipse Libraries, or a work derivative of * such a combination, even if such copying, modification, propagation, or * distribution would otherwise violate the terms of the GPL. Nothing in * this exception exempts you from complying with the GPL in all respects * for all of the code used other than the Eclipse Libraries. You may * include this exception and its grant of permissions when you distribute * 52°North WPS GeoTools Modules. Inclusion of this notice with such a * distribution constitutes a grant of such permissions. If you do not wish * to grant these permissions, remove this paragraph from your * distribution. "52°North WPS GeoTools Modules" means the 52°North WPS * modules using GeoTools functionality - software licensed under version 2 * or any later version of the GPL, or a work based on such software and * licensed under the GPL. "Eclipse Libraries" means Eclipse Modeling * Framework Project and XML Schema Definition software distributed by the * Eclipse Foundation and licensed under the Eclipse Public License Version * 1.0 ("EPL"), or a work based on such software and licensed under the EPL. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. */ package org.n52.wps.io.datahandler.generator.mapserver; import java.io.File; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import org.geotools.data.FeatureSource; import org.geotools.data.FileDataStore; import org.geotools.data.FileDataStoreFinder; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.opengis.feature.type.GeometryDescriptor; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.umn.gis.mapscript.MS_LAYER_TYPE; import edu.umn.gis.mapscript.rectObj; /** * This Class managed the communication between the input shapefile and the * mapscript layer objects. It extracts out from the shapefile different * information and creates the corresponding mapscript object. * * @author Jacob Mendt * * @TODO Layer management * @TODO Timestamp */ public class MSLayerBinding { // metadata parameter private String mdSrs; private String mdTitle; private String mdTimestamp; // filesystem paths private String dataSourcePath; // FeatureSource representation of the shapefile private FeatureSource<?, ?> ftSource; // mapscript objects private MS_LAYER_TYPE geometryType; private rectObj bbox; private CoordinateReferenceSystem crs; private static Logger LOGGER = LoggerFactory.getLogger(MSLayerBinding.class); /** * Initializes a new MSLayerBinding Object. * * @param shapePath * Path to the shapefile object which should be encapsulated. * @param workspace * Path to the workspace of the mapfile object. * * @throws Exception */ public MSLayerBinding(String shapePath, String workspace) throws Exception { /* * Checks if the shapefile path lies within the folder hierarchy of the * mapfile workspace and opens the shapefile for which mapscript objects * should be extracted. */ if (this.parseDataSourcePath(shapePath, workspace)) { LOGGER.debug("Parsing of the relativ data source path successful."); if (this.openShapefile(shapePath)) { LOGGER.debug("Opening and parsing of the shapefile successful."); } else LOGGER.error("Error while opening and parsing the shapefile."); } else { LOGGER.error("Shapefile doesn't lie in the folder hierarchy of the mapfile workspace."); throw new Exception("Error while opening shapefile: " + shapePath); } // parse featureType (POINT,POLYLINE, ...) if (this.parseGeometryDescription()) { LOGGER.debug("Parsing Geometry sucessful."); } else { LOGGER.error("Error while parsing Geometry type."); throw new Exception("Error while parsing Geometry type."); } /* * Parsing the code of the CoordinateReferenceSystem. If the Code is * "CRS:84" it replaced the code with the epsg code 4326 */ ReferencedEnvelope envelope = null; try { envelope = ftSource.getBounds(); crs = envelope.getCoordinateReferenceSystem(); } catch (IOException e) { LOGGER.error("Error while parsing the CoordinateReferenceSystem from the shapefile."); e.printStackTrace(); } try { String code = CRS.lookupIdentifier(crs, true); if (code.equalsIgnoreCase("CRS:84")) { mdSrs = "EPSG:4326"; LOGGER.debug("Parsing CoordinateReferenceSystem successful."); } else { mdSrs = code; LOGGER.debug("Parsing CoordinateReferenceSystem successful."); } } catch (FactoryException e) { LOGGER.error("Could not parse the CoorinateReferenceSystem"); e.printStackTrace(); } // create out of the envelope object an rectObj (mapscript) bbox = new rectObj(envelope.getMinX(), envelope.getMinY(), envelope.getMaxX(), envelope.getMaxY(), 0); // parse the name mdTitle = ftSource.getName().getLocalPart(); // creates a timestamp (actual date) for this layer DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd,HH:mm:ss"); mdTimestamp = dateFormat.format(new Date()); LOGGER.debug("Creating timestamp object sucessful: " + mdTimestamp); } /** * Parse the relativ data source path for referencing the data source folder * in the mapfile. Data source folder have to be in the folder hierarchy of * the workspace. * * @param shapePath * Path to the shapefile. * @param workspace * Path to the folder/workspace of the mapfile. * * @return <tt>true</tt> if relativ data source path is set and lies in the * folder hierarchy of the workspace */ private boolean parseDataSourcePath(String shapePath, String workspace) { if (shapePath.contains(workspace)) { int tmp = shapePath.length() - (shapePath.length() - workspace.length() - 1); dataSourcePath = shapePath.substring(tmp, shapePath.length()); LOGGER.debug("Shapefile lies in the folder hierarchy of the mapfile workspace."); return true; } else { LOGGER.warn("Shapefile doesn't lies in the folder hierarchy of the mapfile workspace."); return false; } } /** * Opens the shapefile as a GeoTools FeatureSource for further use in the * MSLayerBinding class. * * @param shapePath * Path to the shapefile * * @return <tt>true</tt> if the shapefile could be opened successful. */ private boolean openShapefile(String shapePath) { ftSource = null; try { FileDataStore store = FileDataStoreFinder.getDataStore(new File( shapePath)); ftSource = store.getFeatureSource(); } catch (IOException e) { LOGGER.error("Error while opening the shapefile."); e.printStackTrace(); } // tests if the featureSource is empty if (ftSource == null) { LOGGER.debug("Could not open shapefile: " + shapePath); return false; } else if (ftSource != null) { LOGGER.debug("Open shapefile as FeatureSource successful."); return true; } // default return return false; } /** * Parse the GeometryType from the FeatureSource and creates an mapscript * MS_LAYER_TYPE object. Right know this class supports the geometryType * POINT, MULTIPOINT, LINE, MULTILINESTRING, POLYGON, MULTIPOLYGON * * @return <tt>true</tt> if the GeometryType could be parsed */ private boolean parseGeometryDescription() { GeometryDescriptor geomDescription = ftSource.getSchema() .getGeometryDescriptor(); if (geomDescription.getType().getName().toString() .equalsIgnoreCase("POINT")) { geometryType = MS_LAYER_TYPE.MS_LAYER_POINT; return true; } else if (geomDescription.getType().getName().toString() .equalsIgnoreCase("MULTIPOINT")) { geometryType = MS_LAYER_TYPE.MS_LAYER_POINT; return true; } else if (geomDescription.getType().getName().toString() .equalsIgnoreCase("LINE")) { geometryType = MS_LAYER_TYPE.MS_LAYER_LINE; return true; } else if (geomDescription.getType().getName().toString() .equalsIgnoreCase("MULTILINESTRING")) { geometryType = MS_LAYER_TYPE.MS_LAYER_LINE; return true; } else if (geomDescription.getType().getName().toString() .equalsIgnoreCase("POLYGON")) { geometryType = MS_LAYER_TYPE.MS_LAYER_POLYGON; return true; } else if (geomDescription.getType().getName().toString() .equalsIgnoreCase("MULTIPOLYGON")) { geometryType = MS_LAYER_TYPE.MS_LAYER_POLYGON; return true; } return false; } /** * * @return CoordinateReferenceSystem */ public CoordinateReferenceSystem getCRS() { return crs; } /** * * @return String EPSG Code for the SRS of the layer */ public String getMdCRS() { return mdSrs; } /** * * @return String Title of the layer */ public String getMdTitle() { return mdTitle; } /** * * @return String Timestamp of the layer */ public String getMdTimestamp() { return mdTimestamp; } /** * * @return GeomtryType Right now the class supports POINT, MULTIPOINT, LINE, * MULTILINESTRING, POLYGON and MULTIPOLYGON */ public MS_LAYER_TYPE getGeometryType() { return geometryType; } /** * * @return String Path to the shapefile data source of the layer */ public String getDataSourcePath() { return dataSourcePath; } /** * * @return rectObj BoundingBox of the layer */ public rectObj getBBox() { return bbox; } /** * * @return String BoundingBox as a String */ public String getMdBBox() { return bbox.getMinx() + " " + bbox.getMiny() + " " + bbox.getMaxx() + " " + bbox.getMaxy(); } }