Revision: 4948
          http://sourceforge.net/p/jump-pilot/code/4948
Author:   edso
Date:     2016-07-03 14:54:43 +0000 (Sun, 03 Jul 2016)
Log Message:
-----------
added  GeoJSON data types support

Modified Paths:
--------------
    core/trunk/ChangeLog
    core/trunk/src/com/vividsolutions/jump/io/GeoJSONReader.java

Modified: core/trunk/ChangeLog
===================================================================
--- core/trunk/ChangeLog        2016-07-03 14:38:17 UTC (rev 4947)
+++ core/trunk/ChangeLog        2016-07-03 14:54:43 UTC (rev 4948)
@@ -3,6 +3,9 @@
 # 2. make sure that lines break at 80 chars for constricted display situations
 #<-------------------------------- 80 chars 
---------------------------------->#
 
+2016-07-03 ede
+  * GeoJSON reader supports native json data types now
+
 2016-07-01 ede
   * GeoJSON read support added, sponsored by Jukka Rahkonen
 
@@ -13,7 +16,7 @@
   * Update TopologyExtension to 0.9.0.
 
 2016-06-17 mmichaud <m.michael.mich...@orange.fr>
-  * Fix a problem with z interoplation in Noder plugin (note : there is still
+  * Fix a problem with z interpolation in Noder plugin (note : there is still
     a bug related to JTS when using a PrecisionModel of 0 decimal - scale=1)
 
 2016-06-12 mmichaud <m.michael.mich...@orange.fr>

Modified: core/trunk/src/com/vividsolutions/jump/io/GeoJSONReader.java
===================================================================
--- core/trunk/src/com/vividsolutions/jump/io/GeoJSONReader.java        
2016-07-03 14:38:17 UTC (rev 4947)
+++ core/trunk/src/com/vividsolutions/jump/io/GeoJSONReader.java        
2016-07-03 14:54:43 UTC (rev 4948)
@@ -1,7 +1,6 @@
 package com.vividsolutions.jump.io;
 
 import java.io.BufferedReader;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -11,24 +10,18 @@
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Stack;
-import java.util.Vector;
 
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.json.simple.parser.ContainerFactory;
 import org.json.simple.parser.ContentHandler;
 import org.json.simple.parser.JSONParser;
 import org.json.simple.parser.ParseException;
 
 import com.vividsolutions.jts.geom.Geometry;
 import com.vividsolutions.jts.geom.GeometryFactory;
-import com.vividsolutions.jts.io.geojson.GeoJsonConstants;
 import com.vividsolutions.jts.io.geojson.GeoJsonReader;
 import com.vividsolutions.jump.feature.AttributeType;
 import com.vividsolutions.jump.feature.BasicFeature;
@@ -118,26 +111,91 @@
 }
 
 /**
+ * a FeatureSchema implementation that allows changing attrib types without
+ * cloning the whole schema first
+ */
+class FlexibleFeatureSchema extends FeatureSchema {
+  public FlexibleFeatureSchema() {
+  }
+
+  public FlexibleFeatureSchema(FeatureSchema featureSchema) {
+    super(featureSchema);
+  }
+
+  public void setAttributeType(int attributeIndex, AttributeType type) {
+    attributeTypes.set(attributeIndex, type);
+  }
+}
+
+/**
  * a wrapper for a feature collection to do funky geojson stuff to/with
  *
  */
 class GeoJSONFeatureCollectionWrapper {
   MapGeoJsonGeometryReader geomReader = null;
-  FeatureSchema featureSchema = null;
-  List<Feature> featureList = new LinkedList<Feature>();
+  FlexibleFeatureSchema featureSchema = null;
   FeatureCollection featureCollection = null;
+  List<String> columnsWithMixedValues = new LinkedList<String>();
 
+  /**
+   * create a new empty FeatureCollection wrapper
+   */
   public GeoJSONFeatureCollectionWrapper() {
-    featureSchema = new FeatureSchema();
+    this.featureSchema = new FlexibleFeatureSchema();
+    this.featureCollection = new FeatureDataset(featureSchema);
   }
 
+  /**
+   * create a wrapper for an existing FeatureCollection
+   */
   public GeoJSONFeatureCollectionWrapper(FeatureCollection fc) {
-    this.featureSchema = fc.getFeatureSchema();
+    this.featureSchema = new FlexibleFeatureSchema(fc.getFeatureSchema());
     this.featureCollection = fc;
   }
 
+  /**
+   * add a Feature defined by given JSON-simple map the to the collection
+   */
   public void add(Map featureMap) throws Exception {
 
+    // this type of feature "autoextends" by returning null for undefined
+    // attribs
+    Feature feature = new BasicFeature(featureSchema) {
+      @Override
+      public Object getAttribute(int i) {
+        Object[] attributes = getAttributes();
+        if (i >= attributes.length)
+          return null;
+
+        return attributes[i];
+      }
+
+      /**
+       * setting an attribute, fixing the underlying array in case the schema
+       * changed inbetween
+       */
+      public void setAttribute(int attributeIndex, Object newAttribute) {
+        FeatureSchema schema = getSchema();
+        Object[] oldAttribs = getAttributes();
+        // add fields if schema changed in between
+        int diffCount = schema.getAttributeCount() - oldAttribs.length;
+        if (diffCount > 0) {
+          List attributes = new ArrayList(Arrays.asList(oldAttribs));
+          attributes.addAll(Arrays.asList(new Object[diffCount]));
+          super.setAttributes(attributes.toArray());
+        }
+        super.setAttribute(attributeIndex, newAttribute);
+      }
+
+      /**
+       * setting the geometry by explicitly using the flexible setAttribute()
+       * method above
+       */
+      public void setGeometry(Geometry geometry) {
+        setAttribute(getSchema().getGeometryIndex(), geometry);
+      }
+    };
+
     // parse geometry
     Geometry geom = null;
     if (featureMap.containsKey(GeoJSONConstants.GEOMETRY)
@@ -152,60 +210,71 @@
       }
 
       geom = geomReader.read(geometryMap);
+      feature.setGeometry(geom);
     }
 
     // parse attributes
-    Map attribsMap = null;
+    Map<String, Object> attribsMap = null;
     if (featureMap.containsKey(GeoJSONConstants.PROPERTIES)
         && featureMap.get(GeoJSONConstants.PROPERTIES) instanceof Map) {
       attribsMap = (Map) featureMap.get(GeoJSONConstants.PROPERTIES);
-      for (Object key : attribsMap.keySet()) {
+      // iterate over this feature's attribs
+      for (String key : attribsMap.keySet()) {
+        Object value = attribsMap.get(key);
+        // System.out.println(value+"/"+(value!=null?value.getClass():""));
         String attribName = key.toString();
         // extend schema if attrib is unknown
         if (!featureSchema.hasAttribute(attribName)) {
-          featureSchema.addAttribute(attribName, AttributeType.STRING);
+          Class clazz = value != null ? value.getClass() : Object.class;
+          featureSchema.addAttribute(attribName,
+              AttributeType.toAttributeType(clazz));
+          ;
         }
-      }
-    }
+        // detect mixedType columns to fixup Schema later
+        else if (value != null
+            && !columnsWithMixedValues.contains(key)
+            && featureSchema.getAttributeType(key).toJavaClass() != value
+                .getClass()) {
+          System.out.println(featureSchema.getAttributeType(key).toJavaClass()
+              + " != " + value.getClass());
+          // Object class columns are still undecided, because it was null 
until
+          // now. set the first concrete class provided as type
+          if (featureSchema.getAttributeType(key).toJavaClass() == 
Object.class)
+            featureSchema.setAttributeType(
+                featureSchema.getAttributeIndex(key),
+                AttributeType.toAttributeType(value.getClass()));
+          // all other obviously are mixed value columns
+          else
+            columnsWithMixedValues.add(key);
+        }
 
-    // this type of feature "autoextends" by returning null for unknown attribs
-    Feature feature = new BasicFeature(featureSchema) {
-      public Object getAttribute(int i) {
-        Object[] attributes = getAttributes();
-        if (i >= attributes.length)
-          return null;
-
-        return attributes[i];
+        feature.setAttribute(attribName, value);
       }
-    };
-
-    // set geo, if any
-    if (geom != null)
-      feature.setGeometry(geom);
-
-    // set attribs, if any
-    if (attribsMap != null) {
-      for (Object key : attribsMap.keySet()) {
-        String attribName = key.toString();
-        feature.setAttribute(attribName, attribsMap.get(attribName));
-      }
     }
 
-    featureList.add(feature);
+    featureCollection.add(feature);
   }
 
   public FeatureCollection getFeatureCollection() {
-    return new FeatureDataset(featureList, featureSchema);
+    // set type to String for mixed columns
+    for (String key : columnsWithMixedValues) {
+      featureSchema.setAttributeType(featureSchema.getAttributeIndex(key),
+          AttributeType.STRING);
+    }
+    return featureCollection;
   }
 }
 
+/**
+ * a sax like content handler to create features already during parsing the 
json
+ * file (saves memory and processing loops)
+ */
 class Transformer implements ContentHandler {
   private Stack valueStack;
   private Object featsId = null;
   private GeoJSONFeatureCollectionWrapper fcwrap = null;
 
   public Transformer(GeoJSONFeatureCollectionWrapper fcwrap) {
-    super();
     this.fcwrap = fcwrap;
   }
 
@@ -250,6 +319,7 @@
   }
 
   public boolean primitive(Object value) throws ParseException, IOException {
+    // System.out.println(value+"/"+(value!=null?value.getClass():""));
     consumeValue(value);
     return true;
   }


------------------------------------------------------------------------------
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
Francisco, CA to explore cutting-edge tech and listen to tech luminaries
present their vision of the future. This family event has something for
everyone, including kids. Get more information and register today.
http://sdm.link/attshape
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to