Package edu.isi.karma.geospatial

Source Code of edu.isi.karma.geospatial.WorksheetToFeatureCollection

/*******************************************************************************
* Copyright 2012 University of Southern California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code was developed by the Information Integration Group as part
* of the Karma project at the Information Sciences Institute of the
* University of Southern California.  For more information, publications,
* and related projects, please see: http://www.isi.edu/integration
******************************************************************************/

package edu.isi.karma.geospatial;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.io.WKTReader;

import de.micromata.opengis.kml.v_2_2_0.*;
import edu.isi.karma.controller.command.selection.SuperSelection;
import edu.isi.karma.modeling.Namespaces;
import edu.isi.karma.modeling.ontology.OntologyManager;
import edu.isi.karma.rep.HNode;
import edu.isi.karma.rep.Node;
import edu.isi.karma.rep.Row;
import edu.isi.karma.rep.Worksheet;
import edu.isi.karma.rep.alignment.SemanticType;
import edu.isi.karma.util.RandomGUID;
import edu.isi.karma.webserver.ServletContextParameterMap;
import edu.isi.karma.webserver.ServletContextParameterMap.ContextParameter;

import org.geotools.data.DefaultTransaction;
import org.geotools.data.Transaction;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.AttributeTypeBuilder;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class WorksheetToFeatureCollection {
  private Worksheet worksheet;
  private OntologyManager om;

  List<SimpleFeature> pointFeatureList = new ArrayList<SimpleFeature>();
  List<SimpleFeature> lineFeatureList = new ArrayList<SimpleFeature>();
  List<SimpleFeature> polygonFeatureList = new ArrayList<SimpleFeature>();
  List<AttributeDescriptor> featureSchema = new ArrayList<AttributeDescriptor>();
  List<String> geomHNodeIdList = new ArrayList<String>();
  List<String> modeledHNodeIds = new ArrayList<String>();

  private HashMap<String, String> kmlStyles = new HashMap<String, String>();
  private int kmlStylesCounter = 0;
  private String[] kmlPushPings = {
      "http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png",
      "http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",
      "http://maps.google.com/mapfiles/kml/pushpin/ltblu-pushpin.png",
      "http://maps.google.com/mapfiles/kml/pushpin/pink-pushpin.png",
      "http://maps.google.com/mapfiles/kml/pushpin/purple-pushpin.png",
      "http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png",
      "http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png",
      "http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png" };
  private String[] kmlColors = { "641400FF", "641478FF", "6414F0FF",
      "6478FF3C", "6478FFB4", "64FF7800", "64FF7878", "64FF78B4",
      "64FF78F0", "64B4FF14", "64F0FF14" };
  private String GEOM = "GEOM";
  private String SRIDHNodeId = "";
  private String pointFeatureHNodeId = "";
  private String pointFeatureLatHNodeId = "";
  private String pointFeatureLonHNodeId = "";
  private String lineFeatureHNodeId = "";
  private String polygonFeatureHNodeId = "";
  private String kmlCategoryHNodeId = "";
  private String kmlCategoryColumnName = null;
  private String kmlLabelHNodeId = "";
  private String kmlLabelColumnName = null;
  private String zippedSpatialDataFolderAndName = "";

  private double kmlLookAtX = 0;
  private double kmlLookAtY = 0;
  private int featureCounter = 0;
  private SuperSelection selection;
 
  private static String SRID_PROPERTY = Namespaces.GEOSPATIAL
      + ServletContextParameterMap
          .getParameterValue(ContextParameter.SRID_PROPERTY);
  private static String KML_CATEGORY_PROPERTY = Namespaces.GEOSPATIAL
      + ServletContextParameterMap
          .getParameterValue(ContextParameter.KML_CATEGORY_PROPERTY);
  private static String KML_LABEL_PROPERTY = Namespaces.GEOSPATIAL
      + ServletContextParameterMap
          .getParameterValue(ContextParameter.KML_LABEL_PROPERTY);
  private static String WGS84_LAT_PROPERTY = ServletContextParameterMap
      .getParameterValue(ContextParameter.WGS84_LAT_PROPERTY);
  private static String WGS84_LNG_PROPERTY = ServletContextParameterMap
      .getParameterValue(ContextParameter.WGS84_LNG_PROPERTY);
  private static String POINT_POS_PROPERTY = ServletContextParameterMap
      .getParameterValue(ContextParameter.POINT_POS_PROPERTY);
  private static String POS_LIST_PROPERTY = ServletContextParameterMap
      .getParameterValue(ContextParameter.POS_LIST_PROPERTY);
  private static String SRID_CLASS = Namespaces.GEOSPATIAL
      + ServletContextParameterMap
          .getParameterValue(ContextParameter.SRID_CLASS);
  private static String KML_CUSTOMIZATION_CLASS = Namespaces.GEOSPATIAL
      + ServletContextParameterMap
          .getParameterValue(ContextParameter.KML_CUSTOMIZATION_CLASS);
  private static String POINT_CLASS = ServletContextParameterMap
      .getParameterValue(ContextParameter.POINT_CLASS);
  private static String LINE_CLASS = ServletContextParameterMap
      .getParameterValue(ContextParameter.LINE_CLASS);
  private static String POLYGON_CLASS = ServletContextParameterMap
      .getParameterValue(ContextParameter.POLYGON_CLASS);

  private static final Logger logger = LoggerFactory
      .getLogger(WorksheetGeospatialContent.class);

  public WorksheetToFeatureCollection(Worksheet worksheet, OntologyManager om, SuperSelection sel) {
    this.worksheet = worksheet;
    this.om = om;
    this.selection = sel;
    Go();
  }

  private boolean isSubClassOf(String subClassUri, String superClassUri,
      boolean recursive) {
    boolean isSub = false;
    isSub = this.om.isSubClass(subClassUri, superClassUri, recursive);
    return isSub;
  }

  private boolean isSubPropertyOf(String subPropertyUri,
      String superPropertyUri, boolean recursive) {
    boolean isSub = false;
    isSub = this.om.isSubProperty(subPropertyUri, superPropertyUri,
        recursive);
    return isSub;
  }

  private boolean hasType(SemanticType type, String property, String domain) {
    String typeURI = type.getType().getUri();
    String domainURI = type.getDomain().getUri();
    if ((typeURI.equals(property) && domainURI.equals(domain))
        || (isSubPropertyOf(typeURI, property, true) && isSubClassOf(
            domainURI, domain, true)))
      return true;
    else
      return false;
  }

  private void Go() {
    prepareFeatureSchema();
    if (pointFeatureHNodeId != "")
      populateSimpleFeatures(pointFeatureHNodeId,
          "", getRows(), pointFeatureList, Point.class);
    if (pointFeatureLatHNodeId != "" && pointFeatureLonHNodeId != "")
      populateSimpleFeatures(pointFeatureLonHNodeId,
          pointFeatureLatHNodeId, getRows(), pointFeatureList,
          Point.class);
    if (lineFeatureHNodeId != "")
      populateSimpleFeatures(lineFeatureHNodeId, "",
          getRows(), lineFeatureList, LineString.class);
    if (polygonFeatureHNodeId != "")
      populateSimpleFeatures(polygonFeatureHNodeId,
          "", getRows(), polygonFeatureList, Polygon.class);
  }
  private void prepareFeatureSchema() {
    List<String> spatialHNodeIds = new ArrayList<String>();

    for (SemanticType type : worksheet.getSemanticTypes().getListOfTypes()) {
      /*
       * System.out.println("PROPERTY:" +
       * type.getType().getUri().toString()); System.out.println("CLASS:"
       * + type.getDomain().getUri().toString());
       */

      if (hasType(type, SRID_PROPERTY, SRID_CLASS)) {
        SRIDHNodeId = type.getHNodeId();
        spatialHNodeIds.add(0, SRIDHNodeId);
      } else if (hasType(type, POINT_POS_PROPERTY, POINT_CLASS)
          && pointFeatureHNodeId == "") {
        spatialHNodeIds.add(0, type.getHNodeId());
        pointFeatureHNodeId = type.getHNodeId();
      } else if (hasType(type, WGS84_LAT_PROPERTY, POINT_CLASS)
          && pointFeatureLatHNodeId == "") {
        spatialHNodeIds.add(0, type.getHNodeId());
        pointFeatureLatHNodeId = type.getHNodeId();
      } else if (hasType(type, WGS84_LNG_PROPERTY, POINT_CLASS)
          && pointFeatureLonHNodeId == "") {
        spatialHNodeIds.add(0, type.getHNodeId());
        pointFeatureLonHNodeId = type.getHNodeId();
      } else if (hasType(type, POS_LIST_PROPERTY, LINE_CLASS)
          && lineFeatureHNodeId == "") {
        spatialHNodeIds.add(0, type.getHNodeId());
        lineFeatureHNodeId = type.getHNodeId();
      } else if (hasType(type, POS_LIST_PROPERTY, POLYGON_CLASS)
          && polygonFeatureHNodeId == "") {
        spatialHNodeIds.add(0, type.getHNodeId());
        polygonFeatureHNodeId = type.getHNodeId();
      } else if (hasType(type, KML_CATEGORY_PROPERTY,
          KML_CUSTOMIZATION_CLASS)) {
        kmlCategoryHNodeId = type.getHNodeId();
        if (kmlLabelHNodeId == "") {
          for (SemanticType synonymType : worksheet
              .getSemanticTypes()
              .getSynonymTypesForHNodeId(kmlCategoryHNodeId)
              .getSynonyms()) {
            if (hasType(synonymType, KML_LABEL_PROPERTY,
                KML_CUSTOMIZATION_CLASS))
              kmlLabelHNodeId = kmlCategoryHNodeId;
          }
        }
      } else if (hasType(type, KML_LABEL_PROPERTY,
          KML_CUSTOMIZATION_CLASS)) {
        kmlLabelHNodeId = type.getHNodeId();
        if (kmlCategoryHNodeId == "") {
          for (SemanticType synonymType : worksheet
              .getSemanticTypes()
              .getSynonymTypesForHNodeId(kmlLabelHNodeId)
              .getSynonyms()) {
            if (hasType(synonymType, KML_CATEGORY_PROPERTY,
                KML_CUSTOMIZATION_CLASS))
              kmlCategoryHNodeId = kmlLabelHNodeId;
          }
        }
      }
      modeledHNodeIds.add(0, type.getHNodeId());
    }

    if (spatialHNodeIds.size() > 0) {
      List<HNode> sortedLeafHNodes = new ArrayList<HNode>();
      worksheet.getHeaders().getSortedLeafHNodes(sortedLeafHNodes);
      for (HNode hNode : sortedLeafHNodes) {

        if (modeledHNodeIds.contains(hNode.getId())) {// &&
          AttributeTypeBuilder build = new AttributeTypeBuilder();
          build.setNillable(true);
          build.setBinding(String.class); // might need to change to
                          // specific bindings for
                          // sythetic data types
          AttributeDescriptor descriptor = build
              .buildDescriptor(hNode.getColumnName());
          featureSchema.add(descriptor);
          geomHNodeIdList.add(hNode.getId());

          if (hNode.getId().equals(kmlCategoryHNodeId))
            kmlCategoryColumnName = hNode.getColumnName();
          if (hNode.getId().equals(kmlLabelHNodeId))
            kmlLabelColumnName = hNode.getColumnName();
        }
      }
    }
  }

  private void populateSimpleFeatures(
      String geometryHNodeId, String geometry2HNodeId,
      ArrayList<Row> rows, List<SimpleFeature> features, @SuppressWarnings("rawtypes") Class binding) {

    for (Row row : rows) {
      try {
        Geometry JTSGeometry = null;
        String posList = null;
        if (geometry2HNodeId == "") {
          posList = row.getNode(geometryHNodeId).getValue()
              .asString();
          // Future work on WKB columns:
          // WKBReader wkbreader = new WKBReader();
          // byte[] wkbPosList = WKBReader.hexToBytes(posList);
          // JTSGeometry = wkbreader.read(wkbPosList);
        } else { // lat and lng case
          String lon = row.getNode(geometryHNodeId).getValue()
              .asString();
          String lat = row.getNode(geometry2HNodeId).getValue()
              .asString();
          if (lon.trim().length() == 0 || lat.trim().length() == 0)
            continue;
          posList = "POINT(" + lon + " " + lat + ")";
        }

        if (posList == null) // no spatial data
          continue;
        else if(!posList.contains("(")) { // assuming the lon, lat case ... we might need to handle additional cases
          posList = "POINT(" + posList.replace(","," ")+")";
        }
        posList = posList.toUpperCase();
        WKTReader reader = new WKTReader();
        JTSGeometry = reader.read(posList);

        if (JTSGeometry == null)
          continue;

        String srid = "";
        if (SRIDHNodeId != "")
          srid = row.getNode(SRIDHNodeId).getValue().asString();
        else
          srid = "4326"; // default to WGS84

        if (!srid.contains(":"))
          srid = "EPSG:" + srid;
        CoordinateReferenceSystem sourceCRS = null;

        try {
          sourceCRS = CRS.decode(srid, true);
        } catch (NoSuchAuthorityCodeException e) {
          logger.error("No such authority code!", e);
        } catch (FactoryException e) {
          logger.error("Error parsing SRID!", e);
        }
        SimpleFeatureTypeBuilder simpleFeatureTypeBuilder = new SimpleFeatureTypeBuilder();
        simpleFeatureTypeBuilder.setName("SimpleFeature");
        simpleFeatureTypeBuilder.setCRS(sourceCRS);
        simpleFeatureTypeBuilder.add("GEOM", binding);
        simpleFeatureTypeBuilder.addAll(featureSchema);
        SimpleFeatureType simpleFeatureTypeWithCRS = simpleFeatureTypeBuilder
            .buildFeatureType();
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(
            simpleFeatureTypeWithCRS);
        featureBuilder.add(JTSGeometry);

        for (String hNodeId : geomHNodeIdList) {
          Node node = row.getNode(hNodeId);
          if (node.hasNestedTable())
            featureBuilder.add("Nested table");
          else {
            String colValue = node.getValue().asString();
            featureBuilder.add(colValue);
          }
        }
        SimpleFeature feature = featureBuilder.buildFeature(null);
        features.add(feature);
      } catch (Exception e) {
        logger.error("Error creating geometry! Skipping it.", e);
        continue;
      }
    }
  }

  private ArrayList<Row> getRows() {
    int numRows = worksheet.getDataTable().getNumRows();
    return worksheet.getDataTable().getRows(0, numRows, selection);
  }

  public String getZippedSpatialDataPath() {
    return zippedSpatialDataFolderAndName;
  }

  public String SaveSpatialDataAndReturnKMLString() throws Exception {
    String spatialDataFolder = new RandomGUID().toString();
    String fileName = worksheet.getTitle();
    fileName = fileName.substring(0, fileName.length() - 4);
    zippedSpatialDataFolderAndName = spatialDataFolder + "/" + fileName
        + ".zip";
    spatialDataFolder = ServletContextParameterMap
        .getParameterValue(ContextParameter.USER_DIRECTORY_PATH)
        + "publish/SpatialData/" + spatialDataFolder + "/";
    File dir = new File(spatialDataFolder);
    dir.mkdir();

    File kml = publishKML(spatialDataFolder, fileName);
    if (pointFeatureHNodeId != ""
        || (pointFeatureLatHNodeId != "" && pointFeatureLonHNodeId != ""))
      saveShapefile(pointFeatureList, spatialDataFolder, fileName
          + "_point");
    if (lineFeatureHNodeId != "")
      saveShapefile(lineFeatureList, spatialDataFolder, fileName
          + "_line");
    if (polygonFeatureHNodeId != "")
      saveShapefile(polygonFeatureList, spatialDataFolder, fileName
          + "_polygon");

    saveSpatialDataToZip(spatialDataFolder, fileName);
    return fileToString(kml);
  }

  public String fileToString(File f) {
    String result = null;
    DataInputStream in = null;

    try {
      byte[] buffer = new byte[(int) f.length()];
      in = new DataInputStream(new FileInputStream(f));
      in.readFully(buffer);
      result = new String(buffer);
    } catch (IOException e) {
      throw new RuntimeException("IO problem in fileToString", e);
    } finally {
      try {
        in.close();
      } catch (IOException e) { /* ignore it */
      }
    }
    return result;
  }

  public File SaveSpatialData() throws Exception {
    String spatialDataFolder = new RandomGUID().toString();
    String fileName = worksheet.getTitle();
    fileName = fileName.substring(0, fileName.length() - 4);
    zippedSpatialDataFolderAndName = spatialDataFolder + "/" + fileName
        + ".zip";
    spatialDataFolder = ServletContextParameterMap
        .getParameterValue(ContextParameter.USER_DIRECTORY_PATH)
        + "publish/SpatialData/" + spatialDataFolder + "/";
    File dir = new File(spatialDataFolder);
    dir.mkdir();

    File kml = publishKML(spatialDataFolder, fileName);
    if (pointFeatureHNodeId != ""
        || (pointFeatureLatHNodeId != "" && pointFeatureLonHNodeId != ""))
      saveShapefile(pointFeatureList, spatialDataFolder, fileName
          + "_point");
    if (lineFeatureHNodeId != "")
      saveShapefile(lineFeatureList, spatialDataFolder, fileName
          + "_line");
    if (polygonFeatureHNodeId != "")
      saveShapefile(polygonFeatureList, spatialDataFolder, fileName
          + "_polygon");

    saveSpatialDataToZip(spatialDataFolder, fileName);
    return kml;
  }

  public File saveShapefile(List<SimpleFeature> features,
      String spatialDataFolder, String fileName)
      throws FileNotFoundException, Exception {
    File outputFile = new File(spatialDataFolder + fileName + ".shp");
   
    List<SimpleFeature> remainingFeatures = new ArrayList<SimpleFeature>();
   
    try {
      /*
       * Get an output file name and create the new shapefile
       */
      ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();

      Map<String, Serializable> params = new HashMap<String, Serializable>();
      params.put("url", outputFile.toURI().toURL());
      params.put("create spatial index", Boolean.TRUE);

      ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory
          .createNewDataStore(params);
      newDataStore.setStringCharset(Charset.forName("UTF-8"));
      newDataStore.createSchema(features.get(0).getFeatureType());

      /*
       * You can comment out this line if you are using the
       * createFeatureType method (at end of class file) rather than
       * DataUtilities.createType
       */
      CoordinateReferenceSystem crs = features.get(0).getFeatureType()
          .getCoordinateReferenceSystem();
      if (crs == null)
        newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);
     
      for (int i=1;i<features.size();i++) {
       
        SimpleFeature feature = features.get(i);
       
        CoordinateReferenceSystem crs2 = feature.getFeatureType()
        .getCoordinateReferenceSystem();
       
        if(crs2==null)
          continue;
       
        if(!crs.equals(crs2)) {
          remainingFeatures.add(feature);
          features.remove(i);
          i--;
        }
      }
      /*
       * Write the features to the shapefile
       */
      Transaction transaction = new DefaultTransaction("create");

      String typeName = newDataStore.getTypeNames()[0];
      SimpleFeatureSource featureSource = newDataStore
          .getFeatureSource(typeName);

      if (featureSource instanceof SimpleFeatureStore) {
        SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;

        /*
         * SimpleFeatureStore has a method to add features from a
         * SimpleFeatureCollection object, so we use the
         * ListFeatureCollection class to wrap our list of features.
         */
        SimpleFeatureCollection collection = new ListFeatureCollection(
            features.get(0).getFeatureType(), features);
        featureStore.setTransaction(transaction);
        try {
          featureStore.addFeatures(collection);
          transaction.commit();

        } catch (Exception problem) {
          problem.printStackTrace();
          transaction.rollback();

        } finally {
          transaction.close();
        }
        // success!
      } else {
        logger.error(typeName + " does not support read/write access");
      }
    } catch (Exception e) {
      logger.error("Shapefile file published failed! Do you have multiple SRID in a single worksheet?");
    }
    if(!remainingFeatures.isEmpty())
      saveShapefile(remainingFeatures,
        spatialDataFolder, fileName+"_");
       
    logger.info("Shapefile file published. Location:"
        + outputFile.getAbsolutePath());
    return outputFile;
  }

  public String getKMLStyle(String label, Folder folder) {
    if (kmlStyles.containsKey(label))
      return (String) kmlStyles.get(label);

    int pushpingLinkCounter = kmlStylesCounter % kmlPushPings.length;
    int colorCounter = kmlStylesCounter % kmlColors.length;

    Style style = folder.createAndAddStyle().withId(
        String.valueOf(kmlStylesCounter));
    style.createAndSetIconStyle()
        .withScale(1.399999976158142)
        .withIcon(
            new Icon().withHref(kmlPushPings[pushpingLinkCounter]));
    style.createAndSetLineStyle().withColor(kmlColors[colorCounter])
        .withWidth(2);
    style.createAndSetPolyStyle().withColor(kmlColors[colorCounter]);
    kmlStyles.put(label, String.valueOf(kmlStylesCounter));
    kmlStylesCounter++;
    return String.valueOf(kmlStylesCounter - 1);
  }
  private String getKMLLabel(SimpleFeature feature) {
   
    String outKMLLabel = "";
    if (kmlLabelColumnName != null) {
      outKMLLabel = (String) feature.getAttribute(kmlLabelColumnName);
    }
    return outKMLLabel;
  }
  private String getKMLCategory(SimpleFeature feature) {
   
    String outKMLCategory = "";
    if (kmlCategoryColumnName != null) {
      outKMLCategory = (String) feature.getAttribute(kmlCategoryColumnName);
    }
    return outKMLCategory;
  }
  public File publishKML(String spatialDataFolder, String fileName)
      throws IOException {
    File outputFile = new File(spatialDataFolder + fileName + ".kml");

    final Kml kml = KmlFactory.createKml();
    final Folder folder = kml.createAndSetFolder()
        .withName(worksheet.getTitle()).withOpen(true);
    LookAt lookat = new LookAt();

    folder.setAbstractView(lookat);
    /*
     * Style style = folder.createAndAddStyle().withId("karma");
     * style.createAndSetIconStyle() .withScale(1.399999976158142)
     * .withIcon( new Icon()
     * .withHref("http://maps.google.com/mapfiles/ms/icons/blue-pushpin.png"
     * )); style.createAndSetLineStyle().withColor("501400FF").withWidth(2);
     * style.createAndSetPolyStyle().withColor("5014F000");
     */
    for (SimpleFeature pointFeature : pointFeatureList) {

      CoordinateReferenceSystem sourceCRS = pointFeature.getType()
          .getCoordinateReferenceSystem();
      CoordinateReferenceSystem targetCRS = null;
      try {
        targetCRS = CRS.decode("EPSG:4326", true);
      } catch (NoSuchAuthorityCodeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (FactoryException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      Point p = (Point) SpatialReferenceSystemTransformationUtil
          .Transform((Geometry) pointFeature.getAttribute(GEOM),
              sourceCRS, targetCRS);
      /*
       * keep this for a while MathTransform transform=null; try {
       * transform = CRS.findMathTransform(sourceCRS, targetCRS,true); }
       * catch (FactoryException e) { // TODO Auto-generated catch block
       * e.printStackTrace(); } Point p=null; try { Point temp =
       * (Point)pointFeature.getAttribute("GEOM"); p =
       * (Point)JTS.transform( temp, transform); } catch
       * (MismatchedDimensionException e) { e.printStackTrace(); } catch
       * (TransformException e) { e.printStackTrace(); }
       */
      String label = getKMLLabel(pointFeature);
      String category = getKMLCategory(pointFeature);
      String htmlDescription = getHTMLDescription(pointFeature);
      String styleID = getKMLStyle(category, folder);
     
      folder.createAndAddPlacemark().withName(label)
          .withDescription(htmlDescription).withVisibility(true)
          .withStyleUrl("#" + styleID).createAndSetPoint()
          .withAltitudeMode(AltitudeMode.CLAMP_TO_GROUND)
          .addToCoordinates(p.getX() + "," + p.getY());
      featureCounter++;
      kmlLookAtX += p.getX();
      kmlLookAtY += p.getY();
    }
    for (SimpleFeature lineFeature : lineFeatureList) {
      String htmlDescription = getHTMLDescription(lineFeature);

      CoordinateReferenceSystem sourceCRS = lineFeature.getType()
          .getCoordinateReferenceSystem();
      CoordinateReferenceSystem targetCRS = null;
      try {
        targetCRS = CRS.decode("EPSG:4326", true);
      } catch (NoSuchAuthorityCodeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (FactoryException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      LineString line = (LineString) SpatialReferenceSystemTransformationUtil
          .Transform((Geometry) lineFeature.getAttribute(GEOM),
              sourceCRS, targetCRS);

      List<Coordinate> coordsList = new ArrayList<Coordinate>();
      double pointX = 0, pointY = 0;
      for (int i = 0; i < line.getNumPoints(); i++) {
        Coordinate coord = new Coordinate(
            line.getPointN(i).getX(), line.getPointN(i).getY());
        coordsList.add(coord);
        pointX += line.getPointN(i).getX();
        pointY += line.getPointN(i).getY();
      }
      featureCounter++;
      kmlLookAtX += pointX / line.getNumPoints();
      kmlLookAtY += pointY / line.getNumPoints();
      String label = getKMLLabel(lineFeature);
      String category = getKMLCategory(lineFeature);
      String styleID = getKMLStyle(category, folder);
      folder.createAndAddPlacemark().withName(label)
          .withDescription(htmlDescription).withVisibility(true)
          .withStyleUrl("#" + styleID).createAndSetLineString()
          .withAltitudeMode(AltitudeMode.CLAMP_TO_GROUND)
          .setCoordinates(coordsList);
    }
    for (SimpleFeature polygonFeature : polygonFeatureList) {
     

      CoordinateReferenceSystem sourceCRS = polygonFeature.getType()
          .getCoordinateReferenceSystem();
      CoordinateReferenceSystem targetCRS = null;
      try {
        targetCRS = CRS.decode("EPSG:4326", true);
      } catch (NoSuchAuthorityCodeException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (FactoryException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      Polygon polygon = (Polygon) SpatialReferenceSystemTransformationUtil
          .Transform((Geometry) polygonFeature.getAttribute(GEOM),
              sourceCRS, targetCRS);
     
      String label = getKMLLabel(polygonFeature);
      String category = getKMLCategory(polygonFeature);
      String htmlDescription = getHTMLDescription(polygonFeature);
      String styleID = getKMLStyle(category, folder);
      Placemark placemark = folder.createAndAddPlacemark()
          .withName(label).withDescription(htmlDescription)
          .withVisibility(true).withStyleUrl("#" + styleID);

      final de.micromata.opengis.kml.v_2_2_0.Polygon kmlPolygon = new de.micromata.opengis.kml.v_2_2_0.Polygon();
      placemark.setGeometry(kmlPolygon);

      kmlPolygon.setExtrude(true);
      kmlPolygon.setAltitudeMode(AltitudeMode.CLAMP_TO_GROUND);

      final Boundary outerboundary = new Boundary();
      kmlPolygon.setOuterBoundaryIs(outerboundary);

      final LinearRing outerlinearring = new LinearRing();
      outerboundary.setLinearRing(outerlinearring);

      List<Coordinate> outercoord = new ArrayList<Coordinate>();
      outerlinearring.setCoordinates(outercoord);
      double pointX = 0, pointY = 0;
      int pointCounter = 0;
      for (int i = 0; i < polygon.getExteriorRing().getNumPoints(); i++) {
        outercoord.add(new Coordinate(
            polygon.getExteriorRing().getPointN(i).getX(), polygon
                .getExteriorRing().getPointN(i).getY()));
        pointX += polygon.getExteriorRing().getPointN(i).getX();
        pointY += polygon.getExteriorRing().getPointN(i).getY();
        pointCounter++;
      }
      int numOfInnerBoundaries = polygon.getNumInteriorRing();
      for (int i = 0; i < numOfInnerBoundaries; i++) {
        final Boundary innerboundary = new Boundary();
        kmlPolygon.getInnerBoundaryIs().add(innerboundary);

        final LinearRing innerlinearring = new LinearRing();
        innerboundary.setLinearRing(innerlinearring);

        List<Coordinate> innercoord = new ArrayList<Coordinate>();
        innerlinearring.setCoordinates(innercoord);
        int numOfPoints = polygon.getInteriorRingN(i).getNumPoints();
        for (int j = 0; j < numOfPoints; j++) {
          innercoord
              .add(new Coordinate(
                  polygon.getInteriorRingN(i).getPointN(j)
                      .getX(), polygon
                      .getInteriorRingN(i).getPointN(j)
                      .getY()));

          pointX += polygon.getInteriorRingN(i).getPointN(i).getX();
          pointY += polygon.getInteriorRingN(i).getPointN(i).getY();
          pointCounter++;
        }
      }
      featureCounter++;
      kmlLookAtX += pointX / pointCounter;
      kmlLookAtY += pointY / pointCounter;
    }
   
    lookat.setLongitude(kmlLookAtX / featureCounter);
    lookat.setLatitude(kmlLookAtY / featureCounter);
    // lookat.setAltitude(2000.0d);
    lookat.setRange(1000.0);
    lookat.setTilt(45.0);
    lookat.setHeading(0.0);
    lookat.setAltitudeMode(AltitudeMode.CLAMP_TO_GROUND);
    
    final StringWriter out = new StringWriter();
    kml.marshal(out);
    String test = out.toString();
    Writer outUTF8 = null;
    try {
      outUTF8 = new BufferedWriter(new OutputStreamWriter(
          new FileOutputStream(outputFile), "UTF8"));
      outUTF8.append(test);
      outUTF8.flush();
      outUTF8.close();
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    logger.info("KML file published. Location:"
        + outputFile.getAbsolutePath());
    return outputFile;
  }

  private String getHTMLDescription(SimpleFeature simpleFeature) {

    StringBuilder str = new StringBuilder();
    for (Property property : simpleFeature.getProperties()) {
      if (property.getName().toString() != GEOM) {
        str.append("<b>" + property.getName() + "</b>: ");
        if (property.getValue() != null)
          str.append(property.getValue().toString() + " <br />");
        else
          str.append(" <br />");
      }
    }
    return str.toString();
  }

  private void saveSpatialDataToZip(String shapefileFolder, String fileName) {
    try {
      String zipFile = shapefileFolder + fileName + ".zip";
      String sourceDirectory = shapefileFolder;

      // create byte buffer
      byte[] buffer = new byte[1024];

      // create object of FileOutputStream
      FileOutputStream fout = new FileOutputStream(zipFile);

      // create object of ZipOutputStream from FileOutputStream
      ZipOutputStream zout = new ZipOutputStream(fout);

      // create File object from directory name
      File dir = new File(sourceDirectory);

      // check to see if this directory exists
      if (!dir.isDirectory())
        System.out.println(sourceDirectory + " is not a directory");
      else {
        File[] files = dir.listFiles();

        for (int i = 0; i < files.length; i++) {
          System.out.println("Adding " + files[i].getName());
          if (files[i].getName().contains(".zip"))
            continue;
          // create object of FileInputStream for source file
          FileInputStream fin = new FileInputStream(files[i]);

          /*
           * To begin writing ZipEntry in the zip file, use
           *
           * void putNextEntry(ZipEntry entry) method of
           * ZipOutputStream class.
           *
           * This method begins writing a new Zip entry to the zip
           * file and positions the stream to the start of the entry
           * data.
           */

          zout.putNextEntry(new ZipEntry(files[i].getName()));

          /*
           * After creating entry in the zip file, actually write the
           * file.
           */
          int length;

          while ((length = fin.read(buffer)) > 0) {
            zout.write(buffer, 0, length);
          }

          /*
           * After writing the file to ZipOutputStream, use
           *
           * void closeEntry() method of ZipOutputStream class to
           * close the current entry and position the stream to write
           * the next entry.
           */

          zout.closeEntry();
          // close the InputStream
          fin.close();
        }
      }
      // close the ZipOutputStream
      zout.close();
    } catch (IOException ioe) {
      logger.error("IOException :" + ioe);
    }
  }

  public boolean hasNoGeospatialData() {
    if (pointFeatureList.size() == 0 && lineFeatureList.size() == 0
        && polygonFeatureList.size() == 0)
      return true;
    return false;
  }

}
TOP

Related Classes of edu.isi.karma.geospatial.WorksheetToFeatureCollection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.