sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jso...@apache.org
Subject [sis] branch feat/geojson updated: GeoJson : fix test cases, reduce classes scopes, fix checkstyle issues
Date Fri, 29 Nov 2019 09:52:38 GMT
This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a commit to branch feat/geojson
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/feat/geojson by this push:
     new 993d7d4  GeoJson : fix test cases, reduce classes scopes, fix checkstyle issues
993d7d4 is described below

commit 993d7d4e75c1471dd079b5d3d9dd273d97699b20
Author: jsorel <johann.sorel@geomatys.com>
AuthorDate: Fri Nov 29 10:52:12 2019 +0100

    GeoJson : fix test cases, reduce classes scopes, fix checkstyle issues
---
 .../org/apache/sis/feature/FeatureComparator.java  | 310 +++++++++++++++++++++
 storage/sis-geojson/pom.xml                        |   6 +
 .../geojson}/FeatureTypeUtils.java                 |  72 ++---
 .../utils => internal/geojson}/GeoJSONParser.java  | 185 ++++++------
 .../apache/sis/internal/geojson/GeoJSONUtils.java  |  38 ++-
 .../geojson}/LiteJsonLocation.java                 |  38 ++-
 .../sis/internal/geojson/binding/GeoJSONCRS.java   |   3 +-
 .../internal/geojson/binding/GeoJSONFeature.java   |   8 +-
 .../geojson/binding/GeoJSONFeatureCollection.java  |  31 ++-
 .../internal/geojson/binding/GeoJSONGeometry.java  |  46 +--
 .../internal/geojson/binding/GeoJSONObject.java    |  24 +-
 .../org/apache/sis/storage/geojson/Bundle.java     |   6 -
 .../apache/sis/storage/geojson/Bundle.properties   |   4 -
 .../sis/storage/geojson/Bundle_en.properties       |   4 -
 .../sis/storage/geojson/Bundle_fr.properties       |   4 -
 .../GeoJSONTypes.java => GeoJSONConstants.java}    |  15 +-
 .../sis/storage/geojson/GeoJSONFileWriter.java     |  13 +-
 .../sis/storage/geojson/GeoJSONProvider.java       |  10 +-
 .../apache/sis/storage/geojson/GeoJSONReader.java  |  53 ++--
 .../apache/sis/storage/geojson/GeoJSONStore.java   |  31 ++-
 .../sis/storage/geojson/GeoJSONStreamWriter.java   |  12 +-
 .../apache/sis/storage/geojson/GeoJSONWriter.java  |  91 +++---
 .../sis/storage/geojson/utils/GeoJSONMembres.java  |  42 ---
 .../storage/geojson/FeatureTypeUtilsTest.java      |   2 +-
 .../internal/storage/geojson/GeoJSONReadTest.java  |  29 +-
 .../internal/storage/geojson/GeoJSONWriteTest.java |  14 +-
 .../storage/geojson/LiteJsonLocationTest.java      |   4 +-
 27 files changed, 707 insertions(+), 388 deletions(-)

diff --git a/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureComparator.java b/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureComparator.java
new file mode 100644
index 0000000..5176a7f
--- /dev/null
+++ b/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureComparator.java
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.sis.feature;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringJoiner;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.Deprecable;
+import org.junit.Assert;
+import org.opengis.feature.AttributeType;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureAssociationRole;
+import org.opengis.feature.FeatureType;
+import org.opengis.feature.IdentifiedType;
+import org.opengis.feature.Operation;
+import org.opengis.feature.PropertyType;
+import org.opengis.util.GenericName;
+
+/**
+ * Tool to compare feature and feature types.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 2.0
+ * @since   2.0
+ * @module
+ */
+public class FeatureComparator {
+
+    private final Object obj1;
+    private final Object obj2;
+
+    /**
+     * The fully-qualified name of properties to ignore in comparisons. This
+     * collection is initially empty. Users can add or remove elements in this
+     * collection as they wish.
+     *
+     * <p>
+     * The elements shall be names in the form {@code "namespace:name"}, or only
+     * {@code "name"} if there is no namespace.</p>
+     */
+    public final Set<String> ignoredProperties = new HashSet<>();
+    /**
+     * The fully-qualified name of characteristics to ignore in comparisons.
+     * This collection is initially empty. Users can add or remove elements in
+     * this collection as they wish.
+     *
+     * <p>
+     * The elements shall be names in the form {@code "namespace:name"}, or only
+     * {@code "name"} if there is no namespace.</p>
+     */
+    public final Set<String> ignoredCharacteristics = new HashSet<>();
+
+    public boolean ignoreDefinition = false;
+    public boolean ignoreDesignation = false;
+    public boolean ignoreDescription = false;
+
+    public FeatureComparator(Feature expected, Feature result) {
+        ArgumentChecks.ensureNonNull("expected", expected);
+        ArgumentChecks.ensureNonNull("result", result);
+        this.obj1 = expected;
+        this.obj2 = result;
+    }
+
+    public FeatureComparator(FeatureType expected, FeatureType result) {
+        ArgumentChecks.ensureNonNull("expected", expected);
+        ArgumentChecks.ensureNonNull("result", result);
+        this.obj1 = expected;
+        this.obj2 = result;
+    }
+
+    /**
+     * Compare the features or feature types specified at construction time.
+     */
+    public void compare() {
+        final Path path = new Path();
+        if (obj1 instanceof FeatureType) {
+            compareFeatureType(path, (FeatureType) obj1, (FeatureType) obj2);
+        } else {
+            compareFeature(path, (Feature) obj1, (Feature) obj2);
+        }
+    }
+
+    private void compareType(Path path, IdentifiedType expected, IdentifiedType result) {
+        if (expected instanceof FeatureType) {
+            compareFeatureType(path, (FeatureType) expected, (FeatureType) result);
+        } else if (expected instanceof PropertyType) {
+            comparePropertyType(path, (PropertyType) expected, (PropertyType) result);
+        } else {
+            Assert.fail(msg(path, "Unexpected type " + expected));
+        }
+    }
+
+    private void compareFeatureType(Path path, FeatureType expected, FeatureType result) {
+        compareIdentifiedType(path, expected, result);
+
+        Assert.assertEquals(msg(path, "Abstract state differ"), expected.isAbstract(), result.isAbstract());
+        Assert.assertEquals(msg(path, "Super types differ"), expected.getSuperTypes(), result.getSuperTypes());
+
+        List<? extends PropertyType> expectedProperties = new ArrayList<>(expected.getProperties(false));
+        List<? extends PropertyType> resultProperties = new ArrayList<>(result.getProperties(false));
+
+        while (!expectedProperties.isEmpty()) {
+            final PropertyType pte = expectedProperties.remove(0);
+            if (ignoredProperties.contains(pte.getName().toString())) {
+                continue;
+            }
+            Path sub = path.sub(pte.getName().toString());
+            PropertyType ptr = find(sub, resultProperties, pte.getName());
+            resultProperties.remove(ptr);
+            comparePropertyType(sub, pte, ptr);
+        }
+        while (!resultProperties.isEmpty()) {
+            final PropertyType pte = resultProperties.remove(0);
+            if (ignoredProperties.contains(pte.getName().toString())) {
+                continue;
+            }
+            Path sub = path.sub(pte.getName().toString());
+            Assert.fail(msg(sub, "Result type contains a property not declared in expected type : " + pte.getName()));
+        }
+
+    }
+
+    private void compareFeature(Path path, Feature expected, Feature result) {
+        compareFeatureType(path, expected.getType(), result.getType());
+
+        Collection<? extends PropertyType> properties = expected.getType().getProperties(true);
+        for (PropertyType pte : properties) {
+            if (ignoredProperties.contains(pte.getName().toString())) {
+                continue;
+            }
+            Path sub = path.sub(pte.getName().toString());
+
+            Object expectedValue = expected.getPropertyValue(pte.getName().toString());
+            Object resultValue = result.getPropertyValue(pte.getName().toString());
+            if (!(expectedValue instanceof Collection)) {
+                expectedValue = (expectedValue == null) ? Collections.EMPTY_LIST : Arrays.asList(expectedValue);
+            }
+            if (!(resultValue instanceof Collection)) {
+                resultValue = (resultValue == null) ? Collections.EMPTY_LIST : Arrays.asList(resultValue);
+            }
+
+            Collection<?> expectedCol = (Collection) expectedValue;
+            Collection<?> resultCol = (Collection) resultValue;
+
+            if (expectedCol.size() != resultCol.size()) {
+                Assert.fail(msg(sub, "Number of values differ, expected " + expectedCol.size() + " but was " + resultCol.size()));
+            }
+
+            Iterator<?> expectedIte = expectedCol.iterator();
+            Iterator<?> resultIte = resultCol.iterator();
+
+            while (expectedIte.hasNext()) {
+                Object subExpVal = expectedIte.next();
+                Object subResVal = resultIte.next();
+
+                if (subExpVal instanceof Feature) {
+                    compareFeature(path, (Feature) subExpVal, (Feature) subResVal);
+                } else {
+                    Assert.assertEquals(subExpVal, subResVal);
+                }
+            }
+        }
+    }
+
+    private void comparePropertyType(Path path, PropertyType expected, PropertyType result) {
+
+        if (expected instanceof AttributeType) {
+            if (!(result instanceof AttributeType)) {
+                Assert.fail(msg(path, "Expected an AttributeType for name " + ((AttributeType) expected).getName() + " but found a " + result));
+            }
+            compareAttribute(path, (AttributeType) expected, (AttributeType) result);
+
+        } else if (expected instanceof FeatureAssociationRole) {
+            if (!(result instanceof FeatureAssociationRole)) {
+                Assert.fail(msg(path, "Expected a FeatureAssociationRole for name " + ((AttributeType) expected).getName() + " but found a " + result));
+            }
+            compareFeatureAssociationRole(path, (FeatureAssociationRole) expected, (FeatureAssociationRole) result);
+
+        } else if (expected instanceof Operation) {
+            if (!(result instanceof Operation)) {
+                Assert.fail(msg(path, "Expected an Operation for name " + ((AttributeType) expected).getName() + " but found a " + result));
+            }
+            compareOperation(path, (Operation) expected, (Operation) result);
+        }
+    }
+
+    private void compareAttribute(Path path, AttributeType expected, AttributeType result) {
+        compareIdentifiedType(path, expected, result);
+        Assert.assertEquals(msg(path, "Value classe differ"), expected.getValueClass(), expected.getValueClass());
+        Assert.assertEquals(msg(path, "Default value differ"), expected.getDefaultValue(), expected.getDefaultValue());
+
+        Map<String, AttributeType<?>> expCharacteristics = expected.characteristics();
+        Map<String, AttributeType<?>> resCharacteristics = result.characteristics();
+
+        final List<String> expKeys = new ArrayList<>(expCharacteristics.keySet());
+        final List<String> resKeys = new ArrayList<>(resCharacteristics.keySet());
+
+        while (!expKeys.isEmpty()) {
+            final String pte = expKeys.remove(0);
+            if (ignoredCharacteristics.contains(pte)) {
+                continue;
+            }
+            AttributeType<?> exp = expCharacteristics.get(pte);
+            AttributeType<?> res = resCharacteristics.get(pte);
+            resKeys.remove(pte);
+            comparePropertyType(path.sub("characteristic(" + pte + ")"), exp, res);
+        }
+        while (!resKeys.isEmpty()) {
+            final String pte = resKeys.remove(0);
+            if (ignoredCharacteristics.contains(pte)) {
+                continue;
+            }
+            Assert.fail(msg(path, "Result type contains a characteristic not declared in expected type : " + pte));
+        }
+
+    }
+
+    private void compareFeatureAssociationRole(Path path, FeatureAssociationRole expected, FeatureAssociationRole result) {
+        compareIdentifiedType(path, expected, result);
+
+        Assert.assertEquals(msg(path, "Minimum occurences differ"), expected.getMinimumOccurs(), result.getMinimumOccurs());
+        Assert.assertEquals(msg(path, "Maximum occurences differ"), expected.getMaximumOccurs(), result.getMaximumOccurs());
+        compareFeatureType(path.sub("association-valuetype"), expected.getValueType(), result.getValueType());
+    }
+
+    private void compareOperation(Path path, Operation expected, Operation result) {
+        compareIdentifiedType(path, expected, result);
+        Assert.assertEquals(expected.getParameters(), result.getParameters());
+        compareType(path.sub("operation-result(" + expected.getResult().getName().toString() + ")"), expected.getResult(), result.getResult());
+    }
+
+    private void compareIdentifiedType(Path path, IdentifiedType expected, IdentifiedType result) {
+        Assert.assertEquals(msg(path, "Name differ"), expected.getName(), result.getName());
+        if (!ignoreDefinition) {
+            Assert.assertEquals(msg(path, "Definition differ"), expected.getDefinition(), result.getDefinition());
+        }
+        if (!ignoreDesignation) {
+            Assert.assertEquals(msg(path, "Designation differ"), expected.getDesignation(), result.getDesignation());
+        }
+        if (!ignoreDescription) {
+            Assert.assertEquals(msg(path, "Description differ"), expected.getDescription(), result.getDescription());
+        }
+
+        //check deprecable
+        if (expected instanceof Deprecable) {
+            if (result instanceof Deprecable) {
+                boolean dep1 = ((Deprecable) expected).isDeprecated();
+                boolean dep2 = ((Deprecable) result).isDeprecated();
+                if (dep1 != dep2) {
+                    Assert.fail(msg(path, "Deprecated state differ, " + dep1 + " in expected " + dep2 + " in result"));
+                }
+            }
+        }
+    }
+
+    private static PropertyType find(Path path, Collection<? extends PropertyType> properties, GenericName name) {
+        for (PropertyType pt : properties) {
+            if (pt.getName().equals(name)) {
+                return pt;
+            }
+        }
+        Assert.fail(msg(path, "Property not found for name " + name));
+        return null;
+    }
+
+    private static String msg(Path path, String errorMessage) {
+        return path.toString() + " " + errorMessage;
+    }
+
+    private static class Path {
+
+        private final List<String> segments = new ArrayList<>();
+
+        public Path sub(String segment) {
+            Path p = new Path();
+            p.segments.addAll(segments);
+            p.segments.add(segment);
+            return p;
+        }
+
+        @Override
+        public String toString() {
+            final StringJoiner sj = new StringJoiner(" > ");
+            segments.stream().forEach(sj::add);
+            return "[" + sj.toString() + "]";
+        }
+    }
+}
diff --git a/storage/sis-geojson/pom.xml b/storage/sis-geojson/pom.xml
index 3c49d4d..ce96135 100644
--- a/storage/sis-geojson/pom.xml
+++ b/storage/sis-geojson/pom.xml
@@ -120,6 +120,12 @@
       <version>2.10.0</version>
     </dependency>
 
+    <dependency>
+      <groupId>org.apache.sis.core</groupId>
+      <artifactId>sis-feature</artifactId>
+      <version>${project.version}</version>
+      <type>test-jar</type>
+    </dependency>
   </dependencies>
 
   <repositories>
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/FeatureTypeUtils.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/FeatureTypeUtils.java
similarity index 92%
rename from storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/FeatureTypeUtils.java
rename to storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/FeatureTypeUtils.java
index 3f64c65..d890837 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/FeatureTypeUtils.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/FeatureTypeUtils.java
@@ -14,9 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.storage.geojson.utils;
+package org.apache.sis.internal.geojson;
 
-import org.apache.sis.internal.geojson.GeoJSONUtils;
 import com.fasterxml.jackson.core.JsonEncoding;
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonParser;
@@ -33,7 +32,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.logging.Logger;
 import org.apache.sis.feature.builder.AttributeRole;
 import org.apache.sis.feature.builder.AttributeTypeBuilder;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
@@ -43,7 +41,6 @@ import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Static;
 import org.apache.sis.util.iso.Names;
 import org.apache.sis.util.iso.SimpleInternationalString;
-import org.apache.sis.util.logging.Logging;
 import org.locationtech.jts.geom.Geometry;
 import org.opengis.feature.AttributeType;
 import org.opengis.feature.FeatureAssociationRole;
@@ -74,9 +71,6 @@ import org.opengis.util.NameFactory;
  */
 public final class FeatureTypeUtils extends Static {
 
-    private static final Logger LOGGER = Logging.getLogger("org.apache.sis.storage.geojson.utils");
-//    private static final FilterFactory2 FF = (FilterFactory2) DefaultFactories.forBuildin(FilterFactory.class);
-
     private static final String TITLE = "title";
     private static final String TYPE = "type";
     private static final String JAVA_TYPE = "javatype";
@@ -101,6 +95,7 @@ public final class FeatureTypeUtils extends Static {
 
     /**
      * Write a FeatureType in output File.
+     *
      * @param ft
      * @param output
      * @throws IOException
@@ -114,7 +109,7 @@ public final class FeatureTypeUtils extends Static {
                 .orElseThrow(() -> new DataStoreException("No default Geometry in given FeatureType : " + ft));
 
         try (OutputStream outStream = Files.newOutputStream(output, CREATE, WRITE, TRUNCATE_EXISTING);
-             JsonGenerator writer = GeoJSONParser.FACTORY.createGenerator(outStream, JsonEncoding.UTF8)) {
+                JsonGenerator writer = GeoJSONParser.FACTORY.createGenerator(outStream, JsonEncoding.UTF8)) {
 
             writer.useDefaultPrettyPrinter();
             //start write feature collection.
@@ -138,7 +133,9 @@ public final class FeatureTypeUtils extends Static {
         ArgumentChecks.ensureNonNull("FeatureType", fts);
         ArgumentChecks.ensureNonNull("outputStream", output);
 
-        if (fts.isEmpty()) return;
+        if (fts.isEmpty()) {
+            return;
+        }
 
         if (fts.size() > 1) {
             JsonGenerator writer = GeoJSONParser.FACTORY.createGenerator(output, JsonEncoding.UTF8).useDefaultPrettyPrinter();
@@ -153,26 +150,27 @@ public final class FeatureTypeUtils extends Static {
             writeFeatureType(fts.get(0), output);
         }
     }
+
     /**
      * Write a FeatureType in output File.
+     *
      * @param ft
      * @param output
      * @throws IOException
      */
     public static void writeFeatureType(FeatureType ft, OutputStream output) throws IOException, DataStoreException {
-        JsonGenerator writer = GeoJSONParser.FACTORY.createGenerator(output,JsonEncoding.UTF8).useDefaultPrettyPrinter();
+        JsonGenerator writer = GeoJSONParser.FACTORY.createGenerator(output, JsonEncoding.UTF8).useDefaultPrettyPrinter();
         writeFeatureType(ft, output, writer);
         writer.flush();
         writer.close();
     }
 
-
     private static void writeFeatureType(FeatureType ft, OutputStream output, JsonGenerator writer) throws IOException, DataStoreException {
         ArgumentChecks.ensureNonNull("FeatureType", ft);
         ArgumentChecks.ensureNonNull("outputStream", output);
 
         if (GeoJSONUtils.getDefaultGeometry(ft) == null) {
-            throw new DataStoreException("No default Geometry in given FeatureType : "+ft);
+            throw new DataStoreException("No default Geometry in given FeatureType : " + ft);
         }
 
         //start write feature collection.
@@ -206,13 +204,13 @@ public final class FeatureTypeUtils extends Static {
             boolean isRequired = false;
 
             if (type instanceof FeatureAssociationRole) {
-                isRequired = writeComplexType((FeatureAssociationRole) type, ((FeatureAssociationRole)type).getValueType(), writer);
+                isRequired = writeComplexType((FeatureAssociationRole) type, ((FeatureAssociationRole) type).getValueType(), writer);
             } else if (type instanceof AttributeType) {
-                if(Geometry.class.isAssignableFrom( ((AttributeType) type).getValueClass())){
+                if (Geometry.class.isAssignableFrom(((AttributeType) type).getValueClass())) {
 //                    GeometryType geometryType = (GeometryType) type;
 //                    isRequired = writeGeometryType(descriptor, geometryType, writer);
                 } else {
-                    isRequired = writeAttributeType(ft, (AttributeType)type, writer);
+                    isRequired = writeAttributeType(ft, (AttributeType) type, writer);
                 }
             }
             if (isRequired) {
@@ -259,7 +257,7 @@ public final class FeatureTypeUtils extends Static {
         if (att.getDescription() != null) {
             writer.writeStringField(DESCRIPTION, att.getDescription().toString());
         }
-        if (GeoJSONUtils.isPartOfPrimaryKey(featureType,att.getName().toString())) {
+        if (GeoJSONUtils.isPartOfPrimaryKey(featureType, att.getName().toString())) {
             writer.writeBooleanField(PRIMARY_KEY, true);
         }
         writer.writeNumberField(MIN_ITEMS, att.getMinimumOccurs());
@@ -280,11 +278,11 @@ public final class FeatureTypeUtils extends Static {
             return INTEGER;
         } else if (Number.class.isAssignableFrom(binding)) {
             return NUMBER;
-        } else if(Boolean.class.isAssignableFrom(binding)) {
+        } else if (Boolean.class.isAssignableFrom(binding)) {
             return BOOLEAN;
         } else if (binding.isArray()) {
             return ARRAY;
-        } else  {
+        } else {
             //fallback
             return STRING;
         }
@@ -312,6 +310,7 @@ public final class FeatureTypeUtils extends Static {
 
     /**
      * Read a FeatureType from an input File.
+     *
      * @param input file to read
      * @return FeatureType
      * @throws IOException
@@ -319,7 +318,7 @@ public final class FeatureTypeUtils extends Static {
     public static FeatureType readFeatureType(Path input) throws IOException, DataStoreException {
 
         try (InputStream stream = Files.newInputStream(input);
-             JsonParser parser = GeoJSONParser.FACTORY.createParser(stream)) {
+                JsonParser parser = GeoJSONParser.FACTORY.createParser(stream)) {
 
             final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
             parser.nextToken();
@@ -349,10 +348,10 @@ public final class FeatureTypeUtils extends Static {
                 }
             }
 
-            try{
+            try {
                 return ftb.build();
-            }catch(IllegalStateException ex){
-                throw new DataStoreException("FeatureType name or default geometry not found in JSON schema\n"+ex.getMessage(),ex);
+            } catch (IllegalStateException ex) {
+                throw new DataStoreException("FeatureType name or default geometry not found in JSON schema\n" + ex.getMessage(), ex);
             }
         }
     }
@@ -491,7 +490,7 @@ public final class FeatureTypeUtils extends Static {
         if (subftb == null) {
             //build AttributeDescriptor
             if (binding == null) {
-                throw new DataStoreException("Empty javatype for attribute "+attributeName);
+                throw new DataStoreException("Empty javatype for attribute " + attributeName);
             }
 
             AttributeTypeBuilder<?> atb = ftb.addAttribute(binding)
@@ -541,29 +540,28 @@ public final class FeatureTypeUtils extends Static {
         return requiredList;
     }
 
-
     /**
      * Parse a string value that can be expressed in 2 different forms :
      * JSR-283 extended form : {uri}localpart
      * Separator form : uri:localpart
      *
-     * if the given string do not match any, then a Name with no namespace will be
-     * created and the localpart will be the given string.
+     * if the given string do not match any, then a Name with no namespace will
+     * be created and the localpart will be the given string.
      */
-    public static GenericName nameValueOf(final String candidate){
+    public static GenericName nameValueOf(final String candidate) {
 
-        if(candidate.startsWith("{")){
+        if (candidate.startsWith("{")) {
             //name is in extended form
             return toSessionNamespaceFromExtended(candidate);
         }
 
         int index = candidate.lastIndexOf(':');
 
-        if(index <= 0){
+        if (index <= 0) {
             return createName(null, candidate);
-        }else{
-            final String uri = candidate.substring(0,index);
-            final String name = candidate.substring(index+1,candidate.length());
+        } else {
+            final String uri = candidate.substring(0, index);
+            final String name = candidate.substring(index + 1, candidate.length());
             return createName(uri, name);
         }
 
@@ -572,10 +570,12 @@ public final class FeatureTypeUtils extends Static {
     private static GenericName toSessionNamespaceFromExtended(final String candidate) {
         final int index = candidate.indexOf('}');
 
-        if(index == -1) throw new IllegalArgumentException("Invalide extended form : "+ candidate);
+        if (index == -1) {
+            throw new IllegalArgumentException("Invalide extended form : " + candidate);
+        }
 
         final String uri = candidate.substring(1, index);
-        final String name = candidate.substring(index+1, candidate.length());
+        final String name = candidate.substring(index + 1, candidate.length());
 
         return createName(uri, name);
     }
@@ -588,9 +588,9 @@ public final class FeatureTypeUtils extends Static {
     public static GenericName createName(final String namespace, final String local) {
 
         // WARNING: DefaultFactories.NAMES is not a public API and may change in any future SIS version.
-        if(namespace==null || namespace.isEmpty()){
+        if (namespace == null || namespace.isEmpty()) {
             return DefaultFactories.forBuildin(NameFactory.class).createGenericName(null, local);
-        }else{
+        } else {
             return DefaultFactories.forBuildin(NameFactory.class).createGenericName(null, namespace, local);
         }
     }
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONParser.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/GeoJSONParser.java
similarity index 81%
rename from storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONParser.java
rename to storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/GeoJSONParser.java
index 9daf792..b7eecae 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONParser.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/GeoJSONParser.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.storage.geojson.utils;
+package org.apache.sis.internal.geojson;
 
 import org.apache.sis.internal.geojson.binding.GeoJSONGeometry;
 import org.apache.sis.internal.geojson.binding.GeoJSONCRS;
@@ -40,8 +40,7 @@ import org.apache.sis.internal.geojson.binding.GeoJSONGeometry.GeoJSONMultiPoint
 import org.apache.sis.internal.geojson.binding.GeoJSONGeometry.GeoJSONMultiPolygon;
 import org.apache.sis.internal.geojson.binding.GeoJSONGeometry.GeoJSONPoint;
 import org.apache.sis.internal.geojson.binding.GeoJSONGeometry.GeoJSONPolygon;
-import static org.apache.sis.storage.geojson.utils.GeoJSONMembres.*;
-import static org.apache.sis.storage.geojson.utils.GeoJSONTypes.*;
+import static org.apache.sis.storage.geojson.GeoJSONConstants.*;
 
 /**
  * Efficient GeoJSONParsing using jackson {@link JsonParser}
@@ -55,16 +54,16 @@ import static org.apache.sis.storage.geojson.utils.GeoJSONTypes.*;
 public final class GeoJSONParser {
 
     public static final JsonFactory FACTORY = new JsonFactory();
-    public final static Logger LOGGER = Logging.getLogger("org.apache.sis.storage.geojson.utils");
+    public static final Logger LOGGER = Logging.getLogger("org.apache.sis.storage.geojson.utils");
 
     private GeoJSONParser() {}
 
     /**
-     * Parse a json file and return a GeoJSONObject.
-     * If parser was construct with lazyParsing as {@code true} and root object
-     * is a FeatureCollection, returned GeoJSONFeatureCollection will only have
-     * start and end feature array location.
-     * Otherwise, all Feature will be parsed and add to GeoJSONFeatureCollection.
+     * Parse a json file and return a GeoJSONObject. If parser was construct
+     * with lazyParsing as {@code true} and root object is a FeatureCollection,
+     * returned GeoJSONFeatureCollection will only have start and end feature
+     * array location. Otherwise, all Feature will be parsed and add to
+     * GeoJSONFeatureCollection.
      *
      * @param jsonFile file to parse
      * @return GeoJSONObject
@@ -75,11 +74,11 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a json file and return a GeoJSONObject.
-     * If parser was construct with lazyParsing as {@code true} and root object
-     * is a FeatureCollection, returned GeoJSONFeatureCollection will only have
-     * start and end feature array location.
-     * Otherwise, all Feature will be parsed and add to GeoJSONFeatureCollection.
+     * Parse a json file and return a GeoJSONObject. If parser was construct
+     * with lazyParsing as {@code true} and root object is a FeatureCollection,
+     * returned GeoJSONFeatureCollection will only have start and end feature
+     * array location. Otherwise, all Feature will be parsed and add to
+     * GeoJSONFeatureCollection.
      *
      * @param jsonFile file to parse
      * @param lazy lazy mode flag
@@ -89,7 +88,7 @@ public final class GeoJSONParser {
     public static GeoJSONObject parse(Path jsonFile, boolean lazy) throws IOException {
 
         try (InputStream reader = Files.newInputStream(jsonFile);
-             JsonParser p = FACTORY.createParser(reader)) {
+                JsonParser p = FACTORY.createParser(reader)) {
 
             JsonToken startToken = p.nextToken();
             assert (startToken == JsonToken.START_OBJECT) : "Input File is not a JSON file " + jsonFile.toAbsolutePath().toString();
@@ -98,9 +97,8 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a json InputStream and return a GeoJSONObject.
-     * In InputStream case, lazy loading of FeatureCollection is
-     * disabled.
+     * Parse a json InputStream and return a GeoJSONObject. In InputStream case,
+     * lazy loading of FeatureCollection is disabled.
      *
      * @param inputStream stream to parse
      * @return GeoJSONObject
@@ -117,11 +115,11 @@ public final class GeoJSONParser {
     /**
      * Parse a GeoJSONObject (FeatureCollection, Feature or a Geometry)
      * JsonParser location MUST be on a START_OBJECT token.
+     *
      * @param p parser jackson parser with current token on a START_OBJECT.
      * @return GeoJSONObject (FeatureCollection, Feature or a Geometry)
      * @throws IOException
      */
-
     public static GeoJSONObject parseGeoJSONObject(JsonParser p) throws IOException {
         return parseGeoJSONObject(p, Boolean.FALSE, null);
     }
@@ -129,13 +127,14 @@ public final class GeoJSONParser {
     /**
      * Parse a GeoJSONObject (FeatureCollection, Feature or a Geometry)
      * JsonParser location MUST be on a START_OBJECT token.
+     *
      * @param p parser jackson parser with current token on a START_OBJECT.
      * @param lazy lazy mode flag
      * @return GeoJSONObject (FeatureCollection, Feature or a Geometry)
      * @throws IOException
      */
     private static GeoJSONObject parseGeoJSONObject(JsonParser p, Boolean lazy, Path source) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_OBJECT);
+        assert (p.getCurrentToken() == JsonToken.START_OBJECT);
 
         GeoJSONObject object = new GeoJSONObject();
         while (p.nextToken() != JsonToken.END_OBJECT) {
@@ -149,8 +148,8 @@ public final class GeoJSONParser {
                 case ID:
                     p.nextToken();
                     String id = p.getValueAsString();
-                    if(object instanceof GeoJSONFeature){
-                        ((GeoJSONFeature)object).setId(id);
+                    if (object instanceof GeoJSONFeature) {
+                        ((GeoJSONFeature) object).setId(id);
                     }
                     break;
                 case TYPE:
@@ -212,10 +211,10 @@ public final class GeoJSONParser {
                         LOGGER.log(Level.WARNING, "Error need type before coordinates");
                     }
                     break;
-                default :
-                    if(p.getCurrentToken()==JsonToken.START_OBJECT){
+                default:
+                    if (p.getCurrentToken() == JsonToken.START_OBJECT) {
                         //skip any unknown properties
-                        parseGeoJSONObject(p,lazy,source);
+                        parseGeoJSONObject(p, lazy, source);
                     }
                     break;
             }
@@ -225,6 +224,7 @@ public final class GeoJSONParser {
 
     /**
      * Parse properties map and add to given Feature
+     *
      * @param feature Feature to attach properties
      * @param p parser
      * @throws IOException
@@ -235,8 +235,9 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a map of String, Object.
-     * JsonParser location MUST be on a START_OBJECT token.
+     * Parse a map of String, Object. JsonParser location MUST be on a
+     * START_OBJECT token.
+     *
      * @param p parser jackson parser with current token on a START_OBJECT.
      * @return Map of String - Object
      * @throws IOException
@@ -249,11 +250,11 @@ public final class GeoJSONParser {
         }
 
         if (currentToken != JsonToken.START_OBJECT) {
-            LOGGER.log(Level.WARNING, "Expect START_OBJECT token but got "+currentToken+" for "+p.getCurrentName());
+            LOGGER.log(Level.WARNING, "Expect START_OBJECT token but got " + currentToken + " for " + p.getCurrentName());
             return map;
         }
 
-        assert(currentToken == JsonToken.START_OBJECT);
+        assert (currentToken == JsonToken.START_OBJECT);
         while (p.nextToken() != JsonToken.END_OBJECT) {
             String key = p.getCurrentName();
             JsonToken next = p.nextToken();
@@ -264,14 +265,15 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a List of Objects.
-     * JsonParser location MUST be on a START_ARRAY token.
+     * Parse a List of Objects. JsonParser location MUST be on a START_ARRAY
+     * token.
+     *
      * @param p parser jackson parser with current token on a START_ARRAY.
      * @return List of Objects
      * @throws IOException
      */
     private static List<Object> parseArray(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_ARRAY);
+        assert (p.getCurrentToken() == JsonToken.START_ARRAY);
         List<Object> list = new ArrayList<>();
         while (p.nextToken() != JsonToken.END_ARRAY) {
             list.add(getValue(p.getCurrentToken(), p));
@@ -280,14 +282,15 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a List of Objects.
-     * JsonParser location MUST be on a START_ARRAY token.
+     * Parse a List of Objects. JsonParser location MUST be on a START_ARRAY
+     * token.
+     *
      * @param p parser jackson parser with current token on a START_ARRAY.
      * @return array object typed after first element class
      * @throws IOException
      */
     private static Object parseArray2(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_ARRAY);
+        assert (p.getCurrentToken() == JsonToken.START_ARRAY);
         List<Object> list = new ArrayList<>();
         while (p.nextToken() != JsonToken.END_ARRAY) {
             list.add(getValue(p.getCurrentToken(), p));
@@ -307,12 +310,13 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Convert the current token to appropriate object.
-     * Supported (String, Integer, Float, Boolean, Null, Array, Map)
+     * Convert the current token to appropriate object. Supported (String,
+     * Integer, Float, Boolean, Null, Array, Map)
      *
      * @param token current token
      * @param p parser
-     * @return current token value String or Integer or Float or Boolean or null or an array or a map.
+     * @return current token value String or Integer or Float or Boolean or null
+     * or an array or a map.
      * @throws IOException
      */
     static Object getValue(JsonToken token, JsonParser p) throws IOException {
@@ -320,14 +324,14 @@ public final class GeoJSONParser {
             return p.getValueAsString();
         } else if (token == JsonToken.VALUE_NUMBER_INT) {
             final long value = p.getValueAsLong();
-            if(value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
+            if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) {
                 return (int) value;
             }
             return value;
         } else if (token == JsonToken.VALUE_NUMBER_FLOAT) {
             return p.getValueAsDouble();
         } else if (token == JsonToken.VALUE_TRUE || token == JsonToken.VALUE_FALSE) {
-                return token == JsonToken.VALUE_TRUE;
+            return token == JsonToken.VALUE_TRUE;
         } else if (token == JsonToken.VALUE_NULL) {
             return null;
         } else if (token == JsonToken.START_ARRAY) {
@@ -335,12 +339,13 @@ public final class GeoJSONParser {
         } else if (token == JsonToken.START_OBJECT) {
             return parseMap(p);
         } else {
-            throw new UnsupportedOperationException("Unsupported JSON token : "+token+ ", value : "+p.getText());
+            throw new UnsupportedOperationException("Unsupported JSON token : " + token + ", value : " + p.getText());
         }
     }
 
     /**
      * Parse a coordinates array(s) and add to given GeoJSONGeometry.
+     *
      * @param geom GeoJSONGeometry
      * @param p parser
      * @throws IOException
@@ -364,6 +369,7 @@ public final class GeoJSONParser {
 
     /**
      * Full parse of GeoJSONFeatures for a GeoJSONFeatureCollection
+     *
      * @param coll GeoJSONFeatureCollection
      * @param p parser
      * @throws IOException
@@ -375,7 +381,7 @@ public final class GeoJSONParser {
 
             GeoJSONObject obj = parseGeoJSONObject(p, false, null);
             if (obj instanceof GeoJSONFeature) {
-                coll.getFeatures().add((GeoJSONFeature)obj);
+                coll.getFeatures().add((GeoJSONFeature) obj);
             } else {
                 LOGGER.log(Level.WARNING, "ERROR feature collection");
             }
@@ -383,8 +389,8 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Lazy parse of GeoJSONFeatures for a GeoJSONFeatureCollection.
-     * Only find an set START_ARRAY and END_ARRAY TokenLocation of the features array to
+     * Lazy parse of GeoJSONFeatures for a GeoJSONFeatureCollection. Only find
+     * an set START_ARRAY and END_ARRAY TokenLocation of the features array to
      * the GeoJSONFeatureCollection object.
      *
      * @param coll GeoJSONFeatureCollection
@@ -404,8 +410,12 @@ public final class GeoJSONParser {
         //loop to the right "]"
         while (startArray != endArray) {
             JsonToken token = p.nextToken();
-            if (token ==  JsonToken.START_ARRAY) startArray ++;
-            if (token ==  JsonToken.END_ARRAY) endArray ++;
+            if (token == JsonToken.START_ARRAY) {
+                startArray++;
+            }
+            if (token == JsonToken.END_ARRAY) {
+                endArray++;
+            }
         }
 
         coll.setEndPosition(p.getCurrentLocation());
@@ -413,6 +423,7 @@ public final class GeoJSONParser {
 
     /**
      * Parse GeoJSONGeometry for GeoJSONFeature.
+     *
      * @param feature GeoJSONFeature
      * @param p parser
      * @throws IOException
@@ -420,13 +431,14 @@ public final class GeoJSONParser {
     private static void parseFeatureGeometry(GeoJSONFeature feature, JsonParser p) throws IOException {
         p.nextToken(); // "{"
         GeoJSONObject obj = parseGeoJSONObject(p);
-        assert(obj != null) : "Un-parsable GeoJSONGeometry.";
-        assert(obj instanceof GeoJSONGeometry) : "Unexpected GeoJSONObject : " + obj.getType()+" expected : GeoJSONGeometry";
+        assert (obj != null) : "Un-parsable GeoJSONGeometry.";
+        assert (obj instanceof GeoJSONGeometry) : "Unexpected GeoJSONObject : " + obj.getType() + " expected : GeoJSONGeometry";
         feature.setGeometry((GeoJSONGeometry) obj);
     }
 
     /**
      * Parse GeoJSONGeometry for GeoJSONGeometryCollection.
+     *
      * @param geom GeoJSONGeometryCollection
      * @param p parser
      * @throws IOException
@@ -436,18 +448,18 @@ public final class GeoJSONParser {
         // messages is array, loop until token equal to "]"
         while (p.nextToken() != JsonToken.END_ARRAY) {
             GeoJSONObject obj = parseGeoJSONObject(p);
-            assert(obj != null) : "Un-parsable GeoJSONGeometry.";
-            assert(obj instanceof GeoJSONGeometry) : "Unexpected GeoJSONObject : " + obj.getType()+" expected : GeoJSONGeometry";
-            geom.getGeometries().add((GeoJSONGeometry)obj);
+            assert (obj != null) : "Un-parsable GeoJSONGeometry.";
+            assert (obj instanceof GeoJSONGeometry) : "Unexpected GeoJSONObject : " + obj.getType() + " expected : GeoJSONGeometry";
+            geom.getGeometries().add((GeoJSONGeometry) obj);
         }
     }
 
     /**
-     * Create GeoJSONObject using type.
-     * If previous object is not null, forward bbox and crs parameter to the new GeoJSONObject.
+     * Create GeoJSONObject using type. If previous object is not null, forward
+     * bbox and crs parameter to the new GeoJSONObject.
      *
      * @param object previous object.
-     * @param type see {@link org.apache.sis.storage.geojson.utils.GeoJSONTypes}
+     * @param type see {@link org.apache.sis.storage.geojson.GeoJSONConstants}
      * @return GeoJSONObject
      */
     private static GeoJSONObject getOrCreateFromType(GeoJSONObject object, String type) {
@@ -456,11 +468,11 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Create GeoJSONObject using type.
-     * If previous object is not null, forward bbox and crs parameter to the new GeoJSONObject.
+     * Create GeoJSONObject using type. If previous object is not null, forward
+     * bbox and crs parameter to the new GeoJSONObject.
      *
      * @param object previous object.
-     * @param type see {@link org.apache.sis.storage.geojson.utils.GeoJSONTypes}
+     * @param type see {@link org.apache.sis.storage.geojson.GeoJSONConstants}
      * @param lazy lazy mode flag
      * @return GeoJSONObject
      */
@@ -545,14 +557,14 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse the bbox array.
-     * JsonParser location MUST be on a START_ARRAY token.
+     * Parse the bbox array. JsonParser location MUST be on a START_ARRAY token.
+     *
      * @param p JsonParser location MUST be on a START_ARRAY token.
-     * @return  an array of double with a length of 4 or 6.
+     * @return an array of double with a length of 4 or 6.
      * @throws IOException
      */
     private static double[] parseBBoxArray(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_ARRAY);
+        assert (p.getCurrentToken() == JsonToken.START_ARRAY);
         double[] bbox = new double[4];
 
         int idx = 0;
@@ -568,14 +580,14 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a CRS Object.
-     * JsonParser location MUST be on a START_OBJECT token.
+     * Parse a CRS Object. JsonParser location MUST be on a START_OBJECT token.
+     *
      * @param p JsonParser location MUST be on a START_OBJECT token.
      * @return GeoJSONCRS
      * @throws IOException
      */
     private static GeoJSONCRS parseCRS(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_OBJECT);
+        assert (p.getCurrentToken() == JsonToken.START_OBJECT);
         GeoJSONCRS crs = new GeoJSONCRS();
 
         while (p.nextToken() != JsonToken.END_OBJECT) {
@@ -595,14 +607,14 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a Coordinate.
-     * JsonParser location MUST be on a START_ARRAY token.
+     * Parse a Coordinate. JsonParser location MUST be on a START_ARRAY token.
+     *
      * @param p JsonParser location MUST be on a START_ARRAY token.
      * @return an array of double like [X,Y,(Z)]
      * @throws IOException
      */
     private static double[] parsePoint(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_ARRAY);
+        assert (p.getCurrentToken() == JsonToken.START_ARRAY);
         double[] pt = new double[2];
 
         int idx = 0;
@@ -617,14 +629,15 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a LineString/MultiPoint.
-     * JsonParser location MUST be on a START_ARRAY token.
+     * Parse a LineString/MultiPoint. JsonParser location MUST be on a
+     * START_ARRAY token.
+     *
      * @param p JsonParser location MUST be on a START_ARRAY token.
      * @return an array of double like [[X0,Y0,(Z0)], [X1,Y1,(Z1)]]
      * @throws IOException
      */
     private static double[][] parseLineString(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_ARRAY);
+        assert (p.getCurrentToken() == JsonToken.START_ARRAY);
         List<double[]> line = new ArrayList<>();
 
         // messages is array, loop until token equal to "]"
@@ -635,18 +648,16 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a List of LineString or Polygon.
-     * JsonParser location MUST be on a START_ARRAY token.
+     * Parse a List of LineString or Polygon. JsonParser location MUST be on a
+     * START_ARRAY token.
+     *
      * @param p JsonParser location MUST be on a START_ARRAY token.
-     * @return an array of double like
-     * [
-     *  [[X0,Y0,(Z0)], [X1,Y1,(Z1)]],
-     *  [[X0,Y0,(Z0)], [X1,Y1,(Z1)]], ...
-     * ]
+     * @return an array of double like [ [[X0,Y0,(Z0)], [X1,Y1,(Z1)]],
+     * [[X0,Y0,(Z0)], [X1,Y1,(Z1)]], ... ]
      * @throws IOException
      */
     private static double[][][] parseMultiLineString(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_ARRAY);
+        assert (p.getCurrentToken() == JsonToken.START_ARRAY);
         List<double[][]> lines = new ArrayList<>();
 
         // messages is array, loop until token equal to "]"
@@ -657,21 +668,17 @@ public final class GeoJSONParser {
     }
 
     /**
-     * Parse a List of Polygons (list of list of LineString).
-     * JsonParser location MUST be on a START_ARRAY token.
+     * Parse a List of Polygons (list of list of LineString). JsonParser
+     * location MUST be on a START_ARRAY token.
+     *
      * @param p JsonParser location MUST be on a START_ARRAY token.
-     * @return an array of double like
-     * [[
-     *      [[X0,Y0,(Z0)], [X1,Y1,(Z1)]],
-     *      [[X0,Y0,(Z0)], [X1,Y1,(Z1)]]
-     *  ],[
-     *      [[X0,Y0,(Z0)], [X1,Y1,(Z1)]],
-     *      [[X0,Y0,(Z0)], [X1,Y1,(Z1)]]
-     *  ], ... ]
+     * @return an array of double like [[ [[X0,Y0,(Z0)], [X1,Y1,(Z1)]],
+     * [[X0,Y0,(Z0)], [X1,Y1,(Z1)]] ],[ [[X0,Y0,(Z0)], [X1,Y1,(Z1)]],
+     * [[X0,Y0,(Z0)], [X1,Y1,(Z1)]] ], ... ]
      * @throws IOException
      */
     private static double[][][][] parseMultiPolygon(JsonParser p) throws IOException {
-        assert(p.getCurrentToken() == JsonToken.START_ARRAY);
+        assert (p.getCurrentToken() == JsonToken.START_ARRAY);
         List<double[][][]> polygons = new ArrayList<>();
 
         // messages is array, loop until token equal to "]"
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/GeoJSONUtils.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/GeoJSONUtils.java
index 95ce225..01246e0 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/GeoJSONUtils.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/GeoJSONUtils.java
@@ -60,10 +60,8 @@ import org.apache.sis.internal.storage.io.IOUtilities;
 import org.apache.sis.io.wkt.WKTFormat;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.referencing.IdentifiedObjects;
-import org.apache.sis.storage.geojson.utils.GeoJSONParser;
 import org.apache.sis.util.Numbers;
-import static org.apache.sis.storage.geojson.utils.GeoJSONMembres.*;
-import static org.apache.sis.storage.geojson.utils.GeoJSONTypes.*;
+import static org.apache.sis.storage.geojson.GeoJSONConstants.*;
 import org.apache.sis.util.Static;
 import org.opengis.feature.AttributeType;
 import org.opengis.feature.Feature;
@@ -109,7 +107,7 @@ public final class GeoJSONUtils extends Static {
     public static CoordinateReferenceSystem getCRS(FeatureType type){
         try {
             return getCRS(getDefaultGeometry(type));
-        } catch (IllegalArgumentException|IllegalStateException ex) {
+        } catch (IllegalArgumentException | IllegalStateException ex) {
             //no default geometry property
             return null;
         }
@@ -135,14 +133,14 @@ public final class GeoJSONUtils extends Static {
      * @return characteristic value or default value is not found
      */
     public static <T> T getCharacteristicValue(PropertyType type, String charName, T defaulValue){
-        while(type instanceof Operation){
-            type = (PropertyType) ((Operation)type).getResult();
+        while (type instanceof Operation) {
+            type = (PropertyType) ((Operation) type).getResult();
         }
-        if(type instanceof AttributeType){
-            final AttributeType at = (AttributeType) ((AttributeType)type).characteristics().get(charName);
-            if(at!=null){
+        if (type instanceof AttributeType) {
+            final AttributeType at = (AttributeType) ((AttributeType) type).characteristics().get(charName);
+            if (at != null) {
                 T val = (T) at.getDefaultValue();
-                return val==null ? defaulValue : val;
+                return (val == null) ? defaulValue : val;
             }
         }
         return defaulValue;
@@ -220,9 +218,9 @@ public final class GeoJSONUtils extends Static {
      */
     public static Optional<Object> getDefaultGeometryValue(Feature input) throws PropertyNotFoundException, IllegalStateException {
         Object geometry;
-        try{
+        try {
             geometry = input.getPropertyValue(AttributeConvention.GEOMETRY_PROPERTY.toString());
-        } catch(PropertyNotFoundException ex) {
+        } catch (PropertyNotFoundException ex) {
             try {
                 final PropertyType geomType = getDefaultGeometry(input.getType());
                 geometry = input.getPropertyValue(geomType.getName().toString());
@@ -243,7 +241,7 @@ public final class GeoJSONUtils extends Static {
      */
     public static CoordinateReferenceSystem parseCRS(String href, String crsType) {
         String wkt = null;
-        try(InputStream stream = new URL(href).openStream()) {
+        try (InputStream stream = new URL(href).openStream()) {
             wkt = IOUtilities.toString(stream);
         } catch (IOException e) {
             GeoJSONParser.LOGGER.log(Level.WARNING, "Can't access to linked CRS "+href, e);
@@ -281,11 +279,11 @@ public final class GeoJSONUtils extends Static {
         // In case an operation also implements attribute type, we check it first.
         // TODO : cycle detection ?
         while (!(input instanceof AttributeType) && input instanceof Operation) {
-            input = ((Operation)input).getResult();
+            input = ((Operation) input).getResult();
         }
 
         if (input instanceof AttributeType) {
-            return Optional.of((AttributeType)input);
+            return Optional.of((AttributeType) input);
         }
 
         return Optional.empty();
@@ -296,14 +294,14 @@ public final class GeoJSONUtils extends Static {
      */
     public static boolean isPartOfPrimaryKey(FeatureType type, String propertyName) {
         PropertyType property;
-        try{
+        try {
             property = type.getProperty(AttributeConvention.IDENTIFIER_PROPERTY.toString());
-        } catch(PropertyNotFoundException ex) {
+        } catch (PropertyNotFoundException ex) {
             //no identifier property
             return false;
         }
-        if(property instanceof AbstractOperation){
-            final Set<String> dependencies = ((AbstractOperation)property).getDependencies();
+        if (property instanceof AbstractOperation) {
+            final Set<String> dependencies = ((AbstractOperation) property).getDependencies();
             return dependencies.contains(propertyName);
         }
         return false;
@@ -444,7 +442,7 @@ public final class GeoJSONUtils extends Static {
 
         if (binding.isArray()) {
             if (byte.class.isAssignableFrom(binding.getComponentType())) {
-                writer.writeBinary((byte[])value);
+                writer.writeBinary((byte[]) value);
             } else {
                 writer.writeStartArray();
                 final int size = Array.getLength(value);
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/LiteJsonLocation.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/LiteJsonLocation.java
similarity index 75%
rename from storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/LiteJsonLocation.java
rename to storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/LiteJsonLocation.java
index 1cb4636..3fe39f4 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/LiteJsonLocation.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/LiteJsonLocation.java
@@ -14,16 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.storage.geojson.utils;
+package org.apache.sis.internal.geojson;
 
 import com.fasterxml.jackson.core.JsonLocation;
 
 import java.util.Objects;
 
 /**
- * Lightweight pojo of {@link JsonLocation} without internal source object reference and offset.
- * Because since 2.3.x+ of jackson byteOffset and charOffset values depend of underling
- * source type. (InputStream to use byteOffset, BufferedReader to use charOffset)
+ * Lightweight pojo of {@link JsonLocation} without internal source object
+ * reference and offset. Because since 2.3.x+ of jackson byteOffset and
+ * charOffset values depend of underling source type. (InputStream to use
+ * byteOffset, BufferedReader to use charOffset)
  *
  * @author Quentin Boileau (Geomatys)
  * @author Johann Sorel (Geomatys)
@@ -50,16 +51,20 @@ public class LiteJsonLocation {
     }
 
     /**
-     * Check if an JsonLocation position (line and column) is before
-     * current LiteJsonLocation.
+     * Check if an JsonLocation position (line and column) is before current
+     * LiteJsonLocation.
+     *
      * @param o JsonLocation
-     * @return true if before and false if input JsonLocation is equals or after current LiteJsonLocation
+     * @return true if before and false if input JsonLocation is equals or after
+     * current LiteJsonLocation
      */
     public boolean isBefore(JsonLocation o) {
-        if (o == null) return false;
+        if (o == null) {
+            return false;
+        }
         LiteJsonLocation that = new LiteJsonLocation(o);
 
-        return lineNr < that.lineNr || (lineNr == that.lineNr  && columnNr < that.columnNr);
+        return lineNr < that.lineNr || (lineNr == that.lineNr && columnNr < that.columnNr);
     }
 
     /**
@@ -70,12 +75,16 @@ public class LiteJsonLocation {
      */
     @Override
     public boolean equals(Object o) {
-        if (this == o) return true;
+        if (this == o) {
+            return true;
+        }
 
         // not equals if o is null or not an instance of LiteJsonLocation or JsonLocation
-        if (o == null ||
-                (!LiteJsonLocation.class.isAssignableFrom(o.getClass()) &&
-                        !JsonLocation.class.isAssignableFrom(o.getClass()))) return false;
+        if (o == null
+                || (!LiteJsonLocation.class.isAssignableFrom(o.getClass())
+                && !JsonLocation.class.isAssignableFrom(o.getClass()))) {
+            return false;
+        }
 
         LiteJsonLocation that;
         if (JsonLocation.class.isAssignableFrom(o.getClass())) {
@@ -84,8 +93,7 @@ public class LiteJsonLocation {
             that = (LiteJsonLocation) o;
         }
 
-        return lineNr == that.lineNr &&
-                columnNr == that.columnNr;
+        return lineNr == that.lineNr && columnNr == that.columnNr;
     }
 
     @Override
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONCRS.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONCRS.java
index d988322..63401ef 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONCRS.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONCRS.java
@@ -23,8 +23,7 @@ import java.util.HashMap;
 import java.util.Map;
 import org.apache.sis.referencing.crs.AbstractCRS;
 import org.apache.sis.referencing.cs.AxesConvention;
-import static org.apache.sis.storage.geojson.utils.GeoJSONMembres.*;
-import static org.apache.sis.storage.geojson.utils.GeoJSONTypes.*;
+import static org.apache.sis.storage.geojson.GeoJSONConstants.*;
 import org.apache.sis.internal.geojson.GeoJSONUtils;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.util.FactoryException;
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeature.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeature.java
index 2b6500d..a22a580 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeature.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeature.java
@@ -16,7 +16,7 @@
  */
 package org.apache.sis.internal.geojson.binding;
 
-import org.apache.sis.storage.geojson.utils.GeoJSONTypes;
+import org.apache.sis.storage.geojson.GeoJSONConstants;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -30,16 +30,16 @@ import java.util.Map;
  */
 public class GeoJSONFeature extends GeoJSONObject {
 
-    private GeoJSONGeometry geometry = null;
+    private GeoJSONGeometry geometry;
     /**
      * Identifier (id attribute) of the feature. According to RFC 7946, it is
      * optional and can either be a number or a string.
      */
-    private Object id = null;
+    private Object id;
     private Map<String, Object> properties = new HashMap<>();
 
     public GeoJSONFeature() {
-        setType(GeoJSONTypes.FEATURE);
+        setType(GeoJSONConstants.FEATURE);
     }
 
     public GeoJSONGeometry getGeometry() {
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeatureCollection.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeatureCollection.java
index 57fc264..ba2465b 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeatureCollection.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONFeatureCollection.java
@@ -16,6 +16,9 @@
  */
 package org.apache.sis.internal.geojson.binding;
 
+import org.apache.sis.internal.geojson.GeoJSONParser;
+import org.apache.sis.internal.geojson.LiteJsonLocation;
+import org.apache.sis.storage.geojson.GeoJSONConstants;
 import com.fasterxml.jackson.core.JsonLocation;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
@@ -27,7 +30,6 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import org.apache.sis.storage.geojson.utils.*;
 import org.apache.sis.util.collection.BackingStoreException;
 
 /**
@@ -41,23 +43,23 @@ public class GeoJSONFeatureCollection extends GeoJSONObject implements Iterator<
 
     private List<GeoJSONFeature> features = new ArrayList<>();
 
-    transient JsonLocation currentPos = null;
-    transient GeoJSONFeature current = null;
-    transient int currentIdx = 0;
+    transient JsonLocation currentPos;
+    transient GeoJSONFeature current;
+    transient int currentIdx;
     transient InputStream readStream;
     transient JsonParser parser;
 
     /**
-     * If current GeoJSONFeatureCollection is in lazy parsing mode,
-     * sourceInput should be not {@code null} and used to create {@link JsonParser object}
+     * If current GeoJSONFeatureCollection is in lazy parsing mode, sourceInput
+     * should be not {@code null} and used to create {@link JsonParser object}
      */
-    transient Path sourceInput = null;
-    transient LiteJsonLocation startPos = null;
-    transient LiteJsonLocation endPos = null;
+    transient Path sourceInput;
+    transient LiteJsonLocation startPos;
+    transient LiteJsonLocation endPos;
     transient Boolean lazyMode;
 
     public GeoJSONFeatureCollection(Boolean lazyMode) {
-        setType(GeoJSONTypes.FEATURE_COLLECTION);
+        setType(GeoJSONConstants.FEATURE_COLLECTION);
         this.lazyMode = lazyMode;
     }
 
@@ -112,12 +114,17 @@ public class GeoJSONFeatureCollection extends GeoJSONObject implements Iterator<
 
     /**
      * Find next Feature from features list or as lazy parsing.
+     *
      * @throws IOException
      */
     private void findNext() throws IOException {
-        if (current != null) return;
+        if (current != null) {
+            return;
+        }
         if (lazyMode) {
-            if (sourceInput == null || startPos == null || endPos == null) return;
+            if (sourceInput == null || startPos == null || endPos == null) {
+                return;
+            }
 
             if (parser == null) {
                 readStream = Files.newInputStream(sourceInput);
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONGeometry.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONGeometry.java
index cd82640..1c86ea0 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONGeometry.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONGeometry.java
@@ -21,7 +21,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import org.apache.sis.storage.geojson.utils.GeoJSONTypes;
+import org.apache.sis.storage.geojson.GeoJSONConstants;
 import org.locationtech.jts.geom.Coordinate;
 import org.locationtech.jts.geom.CoordinateSequence;
 import org.locationtech.jts.geom.Geometry;
@@ -54,10 +54,10 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
      */
     public static class GeoJSONPoint extends GeoJSONGeometry {
 
-        private double[] coordinates = null;
+        private double[] coordinates;
 
         public GeoJSONPoint() {
-            setType(GeoJSONTypes.POINT);
+            setType(GeoJSONConstants.POINT);
         }
 
         public double[] getCoordinates() {
@@ -75,10 +75,10 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
      */
     public static class GeoJSONMultiPoint extends GeoJSONGeometry {
 
-        private double[][] coordinates = null;
+        private double[][] coordinates;
 
         public GeoJSONMultiPoint() {
-            setType(GeoJSONTypes.MULTI_POINT);
+            setType(GeoJSONConstants.MULTI_POINT);
         }
 
         public double[][] getCoordinates() {
@@ -95,10 +95,10 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
      */
     public static class GeoJSONLineString extends GeoJSONGeometry {
 
-        private double[][] coordinates = null;
+        private double[][] coordinates;
 
         public GeoJSONLineString() {
-            setType(GeoJSONTypes.LINESTRING);
+            setType(GeoJSONConstants.LINESTRING);
         }
 
         public double[][] getCoordinates() {
@@ -115,10 +115,10 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
      */
     public static class GeoJSONMultiLineString extends GeoJSONGeometry {
 
-        private double[][][] coordinates = null;
+        private double[][][] coordinates;
 
         public GeoJSONMultiLineString() {
-            setType(GeoJSONTypes.MULTI_LINESTRING);
+            setType(GeoJSONConstants.MULTI_LINESTRING);
         }
 
         public double[][][] getCoordinates() {
@@ -135,10 +135,10 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
      */
     public static class GeoJSONPolygon extends GeoJSONGeometry {
 
-        private double[][][] coordinates = null;
+        private double[][][] coordinates;
 
         public GeoJSONPolygon() {
-            setType(GeoJSONTypes.POLYGON);
+            setType(GeoJSONConstants.POLYGON);
         }
 
         public double[][][] getCoordinates() {
@@ -153,12 +153,12 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
     /**
      * MULTI-POLYGON
      */
-    public static  class GeoJSONMultiPolygon extends GeoJSONGeometry {
+    public static class GeoJSONMultiPolygon extends GeoJSONGeometry {
 
-        private double[][][][] coordinates = null;
+        private double[][][][] coordinates;
 
         public GeoJSONMultiPolygon() {
-            setType(GeoJSONTypes.MULTI_POLYGON);
+            setType(GeoJSONConstants.MULTI_POLYGON);
         }
 
         public double[][][][] getCoordinates() {
@@ -178,7 +178,7 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
         protected List<GeoJSONGeometry> geometries = new ArrayList<GeoJSONGeometry>();
 
         public GeoJSONGeometryCollection() {
-            setType(GeoJSONTypes.GEOMETRY_COLLECTION);
+            setType(GeoJSONConstants.GEOMETRY_COLLECTION);
         }
 
         public List<GeoJSONGeometry> getGeometries() {
@@ -190,11 +190,11 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
         }
     }
 
-
     private static final GeometryFactory GF = new GeometryFactory();
 
     /**
      * Convert GeoJSONGeometry into JTS Geometry with included CRS
+     *
      * @param jsonGeometry
      * @param crs
      * @return JTS Geometry
@@ -255,10 +255,10 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
     private static Polygon toPolygon(double[][][] coords, CoordinateReferenceSystem crs) {
 
         LinearRing exterior = toLinearRing(coords[0]);
-        LinearRing[] holes = new LinearRing[coords.length-1];
+        LinearRing[] holes = new LinearRing[coords.length - 1];
         if (coords.length > 1) {
             for (int i = 0; i < holes.length; i++) {
-                holes[i] = toLinearRing(coords[i+1]);
+                holes[i] = toLinearRing(coords[i + 1]);
             }
         }
 
@@ -355,9 +355,9 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
         return null;
     }
 
-
     /**
      * Convert JTS geometry into a GeoJSONGeometry.
+     *
      * @param geom JTS Geometry
      * @return GeoJSONGeometry
      */
@@ -392,9 +392,9 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
         double z = coord.getZ();
 
         if (Double.isNaN(z)) {
-            return new double[] {x, y};
+            return new double[]{x, y};
         } else {
-            return new double[] {x, y, z};
+            return new double[]{x, y, z};
         }
     }
 
@@ -455,7 +455,7 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
 
         if (totalRings > 1) {
             for (int i = 0; i < totalRings - 1; i++) {
-                coords[i+1] = polygon.getInteriorRingN(i).getCoordinateSequence();
+                coords[i + 1] = polygon.getInteriorRingN(i).getCoordinateSequence();
             }
         }
         return coords;
@@ -472,7 +472,7 @@ public class GeoJSONGeometry extends GeoJSONObject implements Serializable {
         int totalRings = mln.getNumGeometries();
         CoordinateSequence[] coords = new CoordinateSequence[totalRings];
         for (int i = 0; i < totalRings; i++) {
-            coords[i] = ((LineString)mln.getGeometryN(i)).getCoordinateSequence();
+            coords[i] = ((LineString) mln.getGeometryN(i)).getCoordinateSequence();
         }
         jsonMln.setCoordinates(toArray(coords));
         return jsonMln;
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONObject.java b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONObject.java
index d3fca44..44ead79 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONObject.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/internal/geojson/binding/GeoJSONObject.java
@@ -30,23 +30,23 @@ import java.io.Serializable;
  * @since   2.0
  * @module
  */
-@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type")
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
 @JsonSubTypes({
-        @JsonSubTypes.Type(value=GeoJSONFeatureCollection.class,    name="FeatureCollection"),
-        @JsonSubTypes.Type(value=GeoJSONFeature.class,              name="Feature"),
-        @JsonSubTypes.Type(value=GeoJSONPoint.class,                name="Point"),
-        @JsonSubTypes.Type(value=GeoJSONLineString.class,           name="LineString"),
-        @JsonSubTypes.Type(value=GeoJSONPolygon.class,              name="Polygon"),
-        @JsonSubTypes.Type(value=GeoJSONMultiPoint.class,           name="MultiPoint"),
-        @JsonSubTypes.Type(value=GeoJSONMultiLineString.class,      name="MultiLineString"),
-        @JsonSubTypes.Type(value=GeoJSONMultiPolygon.class,         name="MultiPolygon"),
-        @JsonSubTypes.Type(value=GeoJSONGeometryCollection.class,   name="GeometryCollection")
+    @JsonSubTypes.Type(value = GeoJSONFeatureCollection.class, name = "FeatureCollection"),
+    @JsonSubTypes.Type(value = GeoJSONFeature.class, name = "Feature"),
+    @JsonSubTypes.Type(value = GeoJSONPoint.class, name = "Point"),
+    @JsonSubTypes.Type(value = GeoJSONLineString.class, name = "LineString"),
+    @JsonSubTypes.Type(value = GeoJSONPolygon.class, name = "Polygon"),
+    @JsonSubTypes.Type(value = GeoJSONMultiPoint.class, name = "MultiPoint"),
+    @JsonSubTypes.Type(value = GeoJSONMultiLineString.class, name = "MultiLineString"),
+    @JsonSubTypes.Type(value = GeoJSONMultiPolygon.class, name = "MultiPolygon"),
+    @JsonSubTypes.Type(value = GeoJSONGeometryCollection.class, name = "GeometryCollection")
 })
 public class GeoJSONObject implements Serializable {
 
     private String type;
-    private double[] bbox = null;
-    private GeoJSONCRS crs = null;
+    private double[] bbox;
+    private GeoJSONCRS crs;
 
     public GeoJSONObject() {
     }
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.java
index 0e09243..4d1c94e 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.java
@@ -53,14 +53,8 @@ public final class Bundle extends IndexedResourceBundle {
          */
         public static final short datastoreDescription = 3;
 
-        /**
-         * multiple GeoJSON data files (.json)
-         */
         public static final short datastoreFolderDescription = 4;
 
-        /**
-         * GeoJSON (folder)
-         */
         public static final short datastoreFolderTitle = 5;
 
         /**
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.properties b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.properties
index 9b25fe2..819dbb2 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.properties
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle.properties
@@ -1,9 +1,5 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
 
 datastoreTitle=GeoJSON
 datastoreDescription=GeoJSON data file (.json)
-datastoreFolderTitle=GeoJSON (folder)
-datastoreFolderDescription=multiple GeoJSON data files (.json)
 coordinate_accuracy=Number of decimals
 coordinate_accuracy_remarks=Number of decimals (default 7).
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_en.properties b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_en.properties
index 9b25fe2..819dbb2 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_en.properties
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_en.properties
@@ -1,9 +1,5 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
 
 datastoreTitle=GeoJSON
 datastoreDescription=GeoJSON data file (.json)
-datastoreFolderTitle=GeoJSON (folder)
-datastoreFolderDescription=multiple GeoJSON data files (.json)
 coordinate_accuracy=Number of decimals
 coordinate_accuracy_remarks=Number of decimals (default 7).
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_fr.properties b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_fr.properties
index b905f93..9938477 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_fr.properties
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/Bundle_fr.properties
@@ -1,9 +1,5 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
 
 datastoreTitle=GeoJSON
 datastoreDescription=fichier GeoJSON de donn\u00e9es vectorielles (.json)
-datastoreFolderTitle=GeoJSON (dossier)
-datastoreFolderDescription=Multiples fichiers de donn\u00e9es GeoJSON (.json)
 coordinate_accuracy=Chiffres apr\u00e8s la virgule
 coordinate_accuracy_remarks=Nombre de chiffres apr\u00e8s la virgule.
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONTypes.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONConstants.java
similarity index 73%
rename from storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONTypes.java
rename to storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONConstants.java
index cc580d9..fbe2780 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONTypes.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONConstants.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.storage.geojson.utils;
+package org.apache.sis.storage.geojson;
 
 import org.apache.sis.util.Static;
 
@@ -25,7 +25,7 @@ import org.apache.sis.util.Static;
  * @since   2.0
  * @module
  */
-public final class GeoJSONTypes extends Static {
+public final class GeoJSONConstants extends Static {
 
     public static final String FEATURE_COLLECTION = "FeatureCollection";
     public static final String FEATURE = "Feature";
@@ -45,4 +45,15 @@ public final class GeoJSONTypes extends Static {
     public static final String CRS_TYPE_OGCWKT = "ogcwkt";
     public static final String CRS_TYPE_ESRIWKT = "esriwkt";
 
+    public static final String TYPE = "type";
+    public static final String FEATURES = "features";
+    public static final String GEOMETRY = "geometry";
+    public static final String GEOMETRIES = "geometries";
+    public static final String COORDINATES = "coordinates";
+    public static final String PROPERTIES = "properties";
+    public static final String CRS = "crs";
+    public static final String NAME = "name";
+    public static final String HREF = "href";
+    public static final String BBOX = "bbox";
+    public static final String ID = "id";
 }
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONFileWriter.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONFileWriter.java
index ca387ae..8aa4c0f 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONFileWriter.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONFileWriter.java
@@ -28,7 +28,6 @@ import org.apache.sis.util.collection.BackingStoreException;
 import org.opengis.feature.Feature;
 import org.opengis.feature.FeatureType;
 
-
 /**
  * @author Quentin Boileau (Geomatys)
  * @author Johann Sorel (Geomatys)
@@ -40,12 +39,12 @@ final class GeoJSONFileWriter extends GeoJSONReader {
 
     private final GeoJSONWriter writer;
 
-    private Feature edited = null;
-    private Feature lastWritten = null;
+    private Feature edited;
+    private Feature lastWritten;
     private Path tmpFile;
 
     public GeoJSONFileWriter(Path jsonFile, FeatureType featureType, ReadWriteLock rwLock,
-                             final String encoding, final int doubleAccuracy) throws DataStoreException {
+            final String encoding, final int doubleAccuracy) throws DataStoreException {
         super(jsonFile, featureType, rwLock);
 
         JsonEncoding jsonEncoding = JsonEncoding.UTF8;
@@ -90,7 +89,9 @@ final class GeoJSONFileWriter extends GeoJSONReader {
     }
 
     public void write() throws BackingStoreException {
-        if (edited == null || edited.equals(lastWritten)) return;
+        if (edited == null || edited.equals(lastWritten)) {
+            return;
+        }
 
         lastWritten = edited;
         try {
@@ -108,7 +109,7 @@ final class GeoJSONFileWriter extends GeoJSONReader {
 
     @Override
     public void close() {
-        try (final GeoJSONWriter toClose = writer) {
+        try (GeoJSONWriter toClose = writer) {
             toClose.writeEndFeatureCollection();
             toClose.flush();
         } catch (IOException ex) {
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONProvider.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONProvider.java
index 02d98c2..3781740 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONProvider.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONProvider.java
@@ -79,7 +79,6 @@ public final class GeoJSONProvider extends DataStoreProvider {
             .setRequired(false)
             .create(Integer.class, 7);
 
-
     public static final ParameterDescriptorGroup PARAMETERS_DESCRIPTOR =
             new ParameterBuilder()
                     .addName(NAME)
@@ -148,8 +147,9 @@ public final class GeoJSONProvider extends DataStoreProvider {
     }
 
     /**
-     * Returns the next character which is not a white space, or -1 if the end of stream is reached.
-     * Exactly one of {@code buffer} and {@code reader} shall be non-null.
+     * Returns the next character which is not a white space, or -1 if the end
+     * of stream is reached. Exactly one of {@code buffer} and {@code reader}
+     * shall be non-null.
      */
     private static int nextAfterSpaces(final ByteBuffer buffer, final Reader reader) throws IOException {
         if (buffer != null) {
@@ -163,7 +163,9 @@ public final class GeoJSONProvider extends DataStoreProvider {
         }
         int c;
         while ((c = IOUtilities.readCodePoint(reader)) >= 0) {
-            if (!Character.isWhitespace(c)) break;
+            if (!Character.isWhitespace(c)) {
+                break;
+            }
         }
         return c;
     }
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONReader.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONReader.java
index 04cba99..bfb0ef5 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONReader.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONReader.java
@@ -34,7 +34,7 @@ import org.apache.sis.internal.geojson.binding.GeoJSONFeature;
 import org.apache.sis.internal.geojson.binding.GeoJSONFeatureCollection;
 import org.apache.sis.internal.geojson.binding.GeoJSONGeometry;
 import org.apache.sis.internal.geojson.binding.GeoJSONObject;
-import org.apache.sis.storage.geojson.utils.GeoJSONParser;
+import org.apache.sis.internal.geojson.GeoJSONParser;
 import org.apache.sis.internal.geojson.GeoJSONUtils;
 import org.apache.sis.util.ObjectConverter;
 import org.apache.sis.util.ObjectConverters;
@@ -57,23 +57,24 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
  * @since   2.0
  * @module
  */
-public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
+class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
 
-    private final static Logger LOGGER = Logging.getLogger("org.apache.sis.storage.geojson");
+    private static final Logger LOGGER = Logging.getLogger("org.apache.sis.storage.geojson");
     private final Map<Map.Entry<Class, Class>, ObjectConverter> convertersCache = new HashMap<>();
 
-    private GeoJSONObject jsonObj = null;
+    private GeoJSONObject jsonObj;
     private Boolean toRead = true;
 
     protected final ReadWriteLock rwlock;
     protected final FeatureType featureType;
     protected final Path jsonFile;
-    protected Feature current = null;
-    protected int currentFeatureIdx = 0;
+    protected Feature current;
+    protected int currentFeatureIdx;
 
     /**
      * A flag indicating if we should read identifiers from read stream. it's
-     * activated if the feature type given at built contains an {@link AttributeConvention#IDENTIFIER_PROPERTY}.
+     * activated if the feature type given at built contains an
+     * {@link AttributeConvention#IDENTIFIER_PROPERTY}.
      */
     protected final boolean hasIdentifier;
     final Function idConverter;
@@ -113,14 +114,14 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
         read();
         final Feature ob = current;
         current = null;
-        if(ob == null){
+        if (ob == null) {
             throw new BackingStoreException("No more records.");
         }
         return ob;
     }
 
     private void read() throws BackingStoreException {
-        if(current != null) return;
+        if (current != null) return;
 
         //first call
         if (toRead) {
@@ -147,16 +148,17 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
                 rwlock.readLock().unlock();
             }
         } else if (jsonObj instanceof GeoJSONFeature) {
-            current = toFeature((GeoJSONFeature)jsonObj);
+            current = toFeature((GeoJSONFeature) jsonObj);
             jsonObj = null;
         } else if (jsonObj instanceof GeoJSONGeometry) {
-            current = toFeature((GeoJSONGeometry)jsonObj);
+            current = toFeature((GeoJSONGeometry) jsonObj);
             jsonObj = null;
         }
     }
 
     /**
      * Convert a GeoJSONFeature to geotk Feature.
+     *
      * @param jsonFeature
      * @param featureId
      * @return
@@ -186,19 +188,22 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
 
     /**
      * Recursively fill a ComplexAttribute with properties map
+     *
      * @param feature
      * @param properties
      */
     private void fillFeature(Feature feature, Map<String, Object> properties) throws BackingStoreException {
         final FeatureType featureType = feature.getType();
 
-        for(final PropertyType type : featureType.getProperties(true)) {
+        for (final PropertyType type : featureType.getProperties(true)) {
 
             final String attName = type.getName().toString();
             final Object value = properties.get(attName);
-            if(value==null) continue;
+            if (value == null) {
+                continue;
+            }
 
-            if (type instanceof FeatureAssociationRole ) {
+            if (type instanceof FeatureAssociationRole) {
                 final FeatureAssociationRole asso = (FeatureAssociationRole) type;
                 final FeatureType assoType = asso.getValueType();
                 final Class<?> valueClass = value.getClass();
@@ -219,7 +224,7 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
                             fillFeature(subComplexAttribute, (Map) Array.get(value, i));
                             subs.add(subComplexAttribute);
                         }
-                        feature.setPropertyValue(attName,subs);
+                        feature.setPropertyValue(attName, subs);
                     }
                 } else if (value instanceof Map) {
                     final Feature subComplexAttribute = assoType.newInstance();
@@ -227,8 +232,8 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
                     feature.setPropertyValue(attName, subComplexAttribute);
                 }
 
-            } else if(type instanceof AttributeType) {
-                final Attribute<?> property = (Attribute<?>) feature.getProperty( type.getName().toString());
+            } else if (type instanceof AttributeType) {
+                final Attribute<?> property = (Attribute<?>) feature.getProperty(type.getName().toString());
                 fillProperty(property, value);
             }
         }
@@ -236,6 +241,7 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
 
     /**
      * Try to convert value as expected in PropertyType description.
+     *
      * @param prop
      * @param value
      */
@@ -272,6 +278,7 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
 
     /**
      * Rebuild nDim arrays recursively
+     *
      * @param candidate
      * @param componentType
      * @param depth
@@ -279,25 +286,28 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
      * @throws UnconvertibleObjectException
      */
     private Object rebuildArray(Object candidate, Class componentType, int depth) throws UnconvertibleObjectException {
-        if(candidate==null) return null;
+        if (candidate == null) {
+            return null;
+        }
 
-        if(candidate.getClass().isArray()){
+        if (candidate.getClass().isArray()) {
             final int size = Array.getLength(candidate);
             final int[] dims = new int[depth];
             dims[0] = size;
             final Object rarray = Array.newInstance(componentType, dims);
             depth--;
-            for(int k=0; k<size; k++){
+            for (int k = 0; k < size; k++) {
                 Array.set(rarray, k, rebuildArray(Array.get(candidate, k), componentType, depth));
             }
             return rarray;
-        }else{
+        } else {
             return convert(candidate, componentType);
         }
     }
 
     /**
      * Convert value object into binding class
+     *
      * @param value
      * @param binding
      * @return
@@ -316,6 +326,7 @@ public class GeoJSONReader implements Iterator<Feature>, AutoCloseable {
 
     /**
      * Convert a GeoJSONGeometry to Feature.
+     *
      * @param jsonGeometry
      * @return
      */
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStore.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStore.java
index 1b0740e..515b7c2 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStore.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStore.java
@@ -53,8 +53,8 @@ import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.WritableFeatureSet;
 import static org.apache.sis.storage.geojson.GeoJSONProvider.*;
-import org.apache.sis.storage.geojson.utils.FeatureTypeUtils;
-import org.apache.sis.storage.geojson.utils.GeoJSONParser;
+import org.apache.sis.internal.geojson.FeatureTypeUtils;
+import org.apache.sis.internal.geojson.GeoJSONParser;
 import org.apache.sis.internal.geojson.GeoJSONUtils;
 import org.apache.sis.util.iso.Names;
 import org.apache.sis.util.logging.Logging;
@@ -75,7 +75,7 @@ import org.opengis.util.GenericName;
  * @since   2.0
  * @module
  */
-public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, WritableFeatureSet {
+public final class GeoJSONStore extends DataStore implements ResourceOnFileSystem, WritableFeatureSet {
 
     private static final Logger LOGGER = Logging.getLogger("org.apache.sis.storage.geojson");
     private static final String DESC_FILE_SUFFIX = "_Type.json";
@@ -131,7 +131,7 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
         }
     }
 
-    private static ParameterValueGroup toParameter(final URI uri, Integer coordAccuracy){
+    private static ParameterValueGroup toParameter(final URI uri, Integer coordAccuracy) {
         final Parameters params = Parameters.castOrWrap(GeoJSONProvider.PARAMETERS_DESCRIPTOR.createValue());
         params.getOrCreate(GeoJSONProvider.PATH).setValue(uri);
         params.getOrCreate(GeoJSONProvider.COORDINATE_ACCURACY).setValue(coordAccuracy);
@@ -154,13 +154,13 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
     }
 
     @Override
-    public Optional<GenericName> getIdentifier() throws DataStoreException{
+    public Optional<GenericName> getIdentifier() throws DataStoreException {
         checkTypeExist();
         return Optional.of(name);
     }
 
     @Override
-    public FeatureType getType() throws DataStoreException{
+    public FeatureType getType() throws DataStoreException {
         checkTypeExist();
         return featureType;
     }
@@ -184,7 +184,9 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
     }
 
     /**
-     * Read FeatureType from a JSON-Schema file if exist or directly from the input JSON file.
+     * Read FeatureType from a JSON-Schema file if exist or directly from the
+     * input JSON file.
+     *
      * @return
      * @throws DataStoreException
      * @throws IOException
@@ -194,7 +196,7 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
             // build FeatureType from description JSON.
             return FeatureTypeUtils.readFeatureType(descFile);
         } else {
-            if(Files.exists(jsonFile) && Files.size(jsonFile) != 0) {
+            if (Files.exists(jsonFile) && Files.size(jsonFile) != 0) {
                 final String name = GeoJSONUtils.getNameWithoutExt(jsonFile);
 
                 final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
@@ -218,7 +220,6 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
                         // TODO should we analyse all Features from FeatureCollection to be sure
                         // that each Feature properties JSON object define exactly the same properties
                         // with the same bindings ?
-
                         GeoJSONFeature jsonFeature = jsonFeatureCollection.next();
                         fillTypeFromFeature(ftb, crs, jsonFeature, false);
                     }
@@ -233,13 +234,13 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
 
                 return ftb.build();
             } else {
-                throw new DataStoreException("Can't create FeatureType from empty/not found Json file "+jsonFile.getFileName().toString());
+                throw new DataStoreException("Can't create FeatureType from empty/not found Json file " + jsonFile.getFileName().toString());
             }
         }
     }
 
     private void fillTypeFromFeature(FeatureTypeBuilder ftb, CoordinateReferenceSystem crs,
-                                     GeoJSONFeature jsonFeature, boolean analyseGeometry) {
+            GeoJSONFeature jsonFeature, boolean analyseGeometry) {
         if (analyseGeometry) {
             ftb.addAttribute(findBinding(jsonFeature.getGeometry())).setName("geometry").setCRS(crs).addRole(AttributeRole.DEFAULT_GEOMETRY);
         } else {
@@ -287,7 +288,9 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
                         jsonFile.getFileName().toString(), featureType.getName()));
             }
 
-            if (!jsonExist) Files.createFile(jsonFile);
+            if (!jsonExist) {
+                Files.createFile(jsonFile);
+            }
             //create json with empty collection
             GeoJSONUtils.writeEmptyFeatureCollection(jsonFile);
 
@@ -299,7 +302,9 @@ public class GeoJSONStore extends DataStore implements ResourceOnFileSystem, Wri
                         descFile.getFileName().toString(), featureType.getName()));
             }
 
-            if (!descExist) Files.createFile(descFile);
+            if (!descExist) {
+                Files.createFile(descFile);
+            }
             //create json schema file
             FeatureTypeUtils.writeFeatureType(featureType, descFile);
 
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStreamWriter.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStreamWriter.java
index 7942b4e..35c483c 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStreamWriter.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONStreamWriter.java
@@ -40,7 +40,7 @@ import org.opengis.feature.Operation;
  * @author Quentin Boileau (Geomatys)
  * @author Johann Sorel (Geomatys)
  * @version 2.0
- * @since 2.0
+ * @since   2.0
  * @module
  */
 public final class GeoJSONStreamWriter implements Iterator<Feature>, AutoCloseable {
@@ -48,9 +48,9 @@ public final class GeoJSONStreamWriter implements Iterator<Feature>, AutoCloseab
     private final GeoJSONWriter writer;
     private final FeatureType featureType;
 
-    private Feature edited = null;
-    private Feature lastWritten = null;
-    private int currentFeatureIdx = 0;
+    private Feature edited;
+    private Feature lastWritten;
+    private int currentFeatureIdx;
 
     private final boolean hasIdentifier;
 
@@ -148,7 +148,7 @@ public final class GeoJSONStreamWriter implements Iterator<Feature>, AutoCloseab
     public static void writeSingleFeature(OutputStream outputStream, Feature feature, final JsonEncoding encoding,
             final int doubleAccuracy, boolean prettyPrint) throws IOException {
 
-        try (final GeoJSONWriter writer = new GeoJSONWriter(outputStream, encoding, doubleAccuracy, prettyPrint)) {
+        try (GeoJSONWriter writer = new GeoJSONWriter(outputStream, encoding, doubleAccuracy, prettyPrint)) {
             writer.writeSingleFeature(feature);
         }
     }
@@ -165,7 +165,7 @@ public final class GeoJSONStreamWriter implements Iterator<Feature>, AutoCloseab
     public static void writeSingleGeometry(OutputStream outputStream, Geometry geometry, final JsonEncoding encoding,
             final int doubleAccuracy, boolean prettyPrint) throws IOException {
 
-        try (final GeoJSONWriter writer = new GeoJSONWriter(outputStream, encoding, doubleAccuracy, prettyPrint)) {
+        try (GeoJSONWriter writer = new GeoJSONWriter(outputStream, encoding, doubleAccuracy, prettyPrint)) {
             writer.writeSingleGeometry(geometry);
         }
     }
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONWriter.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONWriter.java
index f519cd3..c919d12 100644
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONWriter.java
+++ b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/GeoJSONWriter.java
@@ -41,9 +41,8 @@ import org.apache.sis.internal.geojson.binding.GeoJSONGeometry.GeoJSONMultiPolyg
 import org.apache.sis.internal.geojson.binding.GeoJSONGeometry.GeoJSONPoint;
 import org.apache.sis.internal.geojson.binding.GeoJSONGeometry.GeoJSONPolygon;
 import org.apache.sis.referencing.CommonCRS;
-import static org.apache.sis.storage.geojson.utils.GeoJSONMembres.*;
-import org.apache.sis.storage.geojson.utils.GeoJSONParser;
-import static org.apache.sis.storage.geojson.utils.GeoJSONTypes.*;
+import org.apache.sis.internal.geojson.GeoJSONParser;
+import static org.apache.sis.storage.geojson.GeoJSONConstants.*;
 import org.apache.sis.internal.geojson.GeoJSONUtils;
 import org.apache.sis.util.Utilities;
 import org.locationtech.jts.geom.Geometry;
@@ -67,12 +66,15 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
  */
 final class GeoJSONWriter implements Closeable, Flushable {
 
-    private final static String SYS_LF;
+    private static final String SYS_LF;
+
     static {
         String lf = null;
         try {
             lf = System.getProperty("line.separator");
-        } catch (Throwable t) { } // access exception?
+        } catch (Throwable t) {
+            // access exception?
+        }
         SYS_LF = (lf == null) ? "\n" : lf;
     }
 
@@ -83,22 +85,17 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     // state boolean to ensure that we can't call writeStartFeatureCollection
     // if we first called writeSingleFeature
-    private boolean isFeatureCollection = false;
-    private boolean isSingleFeature = false;
-    private boolean isSingleGeometry = false;
+    private boolean isFeatureCollection;
+    private boolean isSingleFeature;
+    private boolean isSingleGeometry;
 
     private final NumberFormat numberFormat;
 
-    @Deprecated
-    GeoJSONWriter(File file, JsonEncoding encoding, int doubleAccuracy, boolean prettyPrint) throws IOException {
-        this(file.toPath(), encoding, doubleAccuracy, prettyPrint);
-    }
-
     GeoJSONWriter(Path file, JsonEncoding encoding, int doubleAccuracy, boolean prettyPrint) throws IOException {
         this(Files.newOutputStream(file, CREATE, WRITE, TRUNCATE_EXISTING), encoding, doubleAccuracy, prettyPrint);
     }
 
-    GeoJSONWriter(OutputStream stream, JsonEncoding encoding,  int doubleAccuracy, boolean prettyPrint) throws IOException {
+    GeoJSONWriter(OutputStream stream, JsonEncoding encoding, int doubleAccuracy, boolean prettyPrint) throws IOException {
         this.prettyPrint = prettyPrint;
         this.outputStream = null;
         if (prettyPrint) {
@@ -113,10 +110,9 @@ final class GeoJSONWriter implements Closeable, Flushable {
         numberFormat.setMaximumFractionDigits(doubleAccuracy);
     }
 
-
     void writeStartFeatureCollection(CoordinateReferenceSystem crs, Envelope envelope) throws IOException {
 
-        assert(!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
+        assert (!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
                 "Can't write FeatureCollection if we start a single feature or geometry GeoJSON.";
         isFeatureCollection = true;
 
@@ -130,7 +126,7 @@ final class GeoJSONWriter implements Closeable, Flushable {
             if (writeCRS(crs)) {
                 writeNewLine();
             } else {
-                throw new IOException("Cannot determine a valid URN for "+crs.getName());
+                throw new IOException("Cannot determine a valid URN for " + crs.getName());
             }
         }
 
@@ -141,7 +137,7 @@ final class GeoJSONWriter implements Closeable, Flushable {
     }
 
     void writeEndFeatureCollection() throws IOException {
-        assert(isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
+        assert (isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
                 "Can't write FeatureCollection end before writeStartFeatureCollection().";
 
         if (!first) {
@@ -152,12 +148,13 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     /**
      * Write GeoJSON with a single feature
+     *
      * @param feature
      * @throws IOException
      * @throws IllegalArgumentException
      */
     void writeSingleFeature(Feature feature) throws IOException, IllegalArgumentException {
-        assert(!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
+        assert (!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
                 "writeSingleFeature can called only once per GeoJSONWriter.";
 
         isSingleFeature = true;
@@ -165,13 +162,14 @@ final class GeoJSONWriter implements Closeable, Flushable {
     }
 
     void writeFeature(Feature feature) throws IOException, IllegalArgumentException {
-        assert(isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
+        assert (isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
                 "Can't write a Feature before writeStartFeatureCollection.";
         writeFeature(feature, false);
     }
 
     /**
      * Write a Feature.
+     *
      * @param feature
      * @param single
      * @throws IOException
@@ -206,15 +204,15 @@ final class GeoJSONWriter implements Closeable, Flushable {
             final CoordinateReferenceSystem crs = GeoJSONUtils.getCRS(feature.getType());
             if (crs != null && !Utilities.equalsApproximately(crs, CommonCRS.defaultGeographic())) {
                 if (!writeCRS(crs)) {
-                    throw new IOException("Cannot determine a valid URN for "+crs.getName());
+                    throw new IOException("Cannot determine a valid URN for " + crs.getName());
                 }
             }
         }
 
         //write geometry
         final Optional<Geometry> geom = GeoJSONUtils.getDefaultGeometryValue(feature)
-                        .filter(Geometry.class::isInstance)
-                        .map(Geometry.class::cast);
+                .filter(Geometry.class::isInstance)
+                .map(Geometry.class::cast);
 
         if (geom.isPresent()) {
             writer.writeFieldName(GEOMETRY);
@@ -225,15 +223,20 @@ final class GeoJSONWriter implements Closeable, Flushable {
         writeProperties(feature, PROPERTIES, true);
         writer.writeEndObject();
 
-        if (!single && !prettyPrint) writer.writeRaw(SYS_LF);
+        if (!single && !prettyPrint) {
+            writer.writeRaw(SYS_LF);
+        }
     }
 
     private void writeNewLine() throws IOException {
-        if (!prettyPrint) writer.writeRaw(SYS_LF);
+        if (!prettyPrint) {
+            writer.writeRaw(SYS_LF);
+        }
     }
 
     /**
      * Write CoordinateReferenceSystem
+     *
      * @param crs
      * @throws IOException
      */
@@ -253,6 +256,7 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     /**
      * Write ComplexAttribute.
+     *
      * @param edited
      * @param fieldName
      * @param writeFieldName
@@ -272,35 +276,35 @@ final class GeoJSONWriter implements Closeable, Flushable {
                 .filter(GeoJSONUtils.IS_NOT_CONVENTION)
                 .collect(Collectors.toList());
         for (PropertyType propType : descriptors) {
-            if(AttributeConvention.contains(propType.getName())) continue;
-            if(AttributeConvention.isGeometryAttribute(propType)) continue;
+            if (AttributeConvention.contains(propType.getName())) continue;
+            if (AttributeConvention.isGeometryAttribute(propType)) continue;
             final String name = propType.getName().tip().toString();
             final Object value = edited.getPropertyValue(propType.getName().toString());
 
-            if(propType instanceof AttributeType){
+            if (propType instanceof AttributeType) {
                 final AttributeType attType = (AttributeType) propType;
-                if(attType.getMaximumOccurs()>1){
+                if (attType.getMaximumOccurs() > 1) {
                     writer.writeArrayFieldStart(name);
-                    for(Object v : (Collection)value){
+                    for (Object v : (Collection) value) {
                         writeProperty(name, v, false);
                     }
                     writer.writeEndArray();
-                }else{
+                } else {
                     writeProperty(name, value, true);
                 }
-            }else if(propType instanceof FeatureAssociationRole){
+            } else if (propType instanceof FeatureAssociationRole) {
                 final FeatureAssociationRole asso = (FeatureAssociationRole) propType;
-                if(asso.getMaximumOccurs()>1){
+                if (asso.getMaximumOccurs() > 1) {
                     writer.writeArrayFieldStart(name);
-                    for(Object v : (Collection)value){
+                    for (Object v : (Collection) value) {
                         writeProperty(name, v, false);
                     }
                     writer.writeEndArray();
-                }else{
+                } else {
                     writeProperty(name, value, true);
                 }
 
-            }else if(propType instanceof Operation){
+            } else if (propType instanceof Operation) {
                 writeProperty(name, value, true);
             }
         }
@@ -310,6 +314,7 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     /**
      * Write a property (Complex or Simple)
+     *
      * @param property
      * @param writeFieldName
      * @throws IOException
@@ -323,12 +328,14 @@ final class GeoJSONWriter implements Closeable, Flushable {
     }
 
     /**
-     * Write an Attribute and check if attribute value is assignable to binding class.
+     * Write an Attribute and check if attribute value is assignable to binding
+     * class.
+     *
      * @param property
      * @param writeFieldName
      * @throws IOException
      */
-    private void writeAttribute(String name, Object value,  boolean writeFieldName) throws IOException, IllegalArgumentException {
+    private void writeAttribute(String name, Object value, boolean writeFieldName) throws IOException, IllegalArgumentException {
         if (writeFieldName) {
             writer.writeFieldName(name);
         }
@@ -337,11 +344,12 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     /**
      * Write a GeometryAttribute
+     *
      * @param geom
      * @throws IOException
      */
     void writeSingleGeometry(Attribute geom) throws IOException {
-        assert(!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
+        assert (!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
                 "writeSingleGeometry can called only once per GeoJSONWriter.";
         isSingleGeometry = true;
         GeoJSONGeometry jsonGeometry = GeoJSONGeometry.toGeoJSONGeometry((Geometry) geom.getValue());
@@ -350,11 +358,12 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     /**
      * Write a JTS Geometry
+     *
      * @param geom
      * @throws IOException
      */
     void writeSingleGeometry(Geometry geom) throws IOException {
-        assert(!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
+        assert (!isFeatureCollection && !isSingleFeature && !isSingleGeometry) :
                 "writeSingleGeometry can called only once per GeoJSONWriter.";
         isSingleGeometry = true;
         GeoJSONGeometry jsonGeometry = GeoJSONGeometry.toGeoJSONGeometry(geom);
@@ -363,6 +372,7 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     /**
      * Write a GeometryAttribute
+     *
      * @param geom
      * @throws IOException
      */
@@ -372,6 +382,7 @@ final class GeoJSONWriter implements Closeable, Flushable {
 
     /**
      * Write a GeoJSONGeometry
+     *
      * @param jsonGeometry
      * @throws IOException
      */
diff --git a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONMembres.java b/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONMembres.java
deleted file mode 100644
index 9416ba6..0000000
--- a/storage/sis-geojson/src/main/java/org/apache/sis/storage/geojson/utils/GeoJSONMembres.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.sis.storage.geojson.utils;
-
-import org.apache.sis.util.Static;
-
-/**
- * @author Quentin Boileau (Geomatys)
- * @author Johann Sorel (Geomatys)
- * @version 2.0
- * @since   2.0
- * @module
- */
-public final class GeoJSONMembres extends Static  {
-
-    public static final String TYPE = "type";
-    public static final String FEATURES = "features";
-    public static final String GEOMETRY = "geometry";
-    public static final String GEOMETRIES = "geometries";
-    public static final String COORDINATES = "coordinates";
-    public static final String PROPERTIES = "properties";
-    public static final String CRS = "crs";
-    public static final String NAME = "name";
-    public static final String HREF = "href";
-    public static final String BBOX = "bbox";
-    public static final String ID = "id";
-
-}
diff --git a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/FeatureTypeUtilsTest.java b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/FeatureTypeUtilsTest.java
index 474f6b6..61fe1c7 100644
--- a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/FeatureTypeUtilsTest.java
+++ b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/FeatureTypeUtilsTest.java
@@ -32,7 +32,7 @@ import java.util.Set;
 import org.apache.sis.feature.builder.AttributeRole;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.internal.feature.AttributeConvention;
-import org.apache.sis.storage.geojson.utils.FeatureTypeUtils;
+import org.apache.sis.internal.geojson.FeatureTypeUtils;
 import org.apache.sis.internal.geojson.GeoJSONUtils;
 import org.apache.sis.test.TestCase;
 
diff --git a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONReadTest.java b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONReadTest.java
index 16b563a..ee65118 100644
--- a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONReadTest.java
+++ b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONReadTest.java
@@ -28,11 +28,10 @@ import org.apache.sis.internal.feature.AttributeConvention;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStores;
-import org.apache.sis.storage.FeatureSet;
-import org.apache.sis.storage.geojson.GeoJSONStore;
 import org.apache.sis.internal.geojson.binding.GeoJSONFeatureCollection;
 import org.apache.sis.internal.geojson.binding.GeoJSONObject;
-import org.apache.sis.storage.geojson.utils.GeoJSONParser;
+import org.apache.sis.internal.geojson.GeoJSONParser;
+import org.apache.sis.storage.WritableFeatureSet;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.util.iso.Names;
 import static org.junit.Assert.*;
@@ -57,7 +56,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readPointTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/point.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -73,7 +72,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readMultiPointTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/multipoint.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -89,7 +88,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readLineStringTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/linestring.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -105,7 +104,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readMultiLineStringTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/multilinestring.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -121,7 +120,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readPolygonTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/polygon.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -137,7 +136,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readMultiPolygonTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/multipolygon.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -153,7 +152,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readGeometryCollectionTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/geometrycollection.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -170,7 +169,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readFeatureTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/feature.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -186,7 +185,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readFeatureCollectionTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/featurecollection.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -206,7 +205,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readPropertyArrayTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/f_prop_array.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -243,7 +242,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readNullPropsTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/sample_with_null_properties.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
@@ -260,7 +259,7 @@ public class GeoJSONReadTest extends TestCase {
     public void readLongTest() throws DataStoreException, URISyntaxException {
         URL file = GeoJSONReadTest.class.getResource("/org/apache/sis/internal/storage/geojson/longValue.json");
 
-        GeoJSONStore store = (GeoJSONStore) DataStores.open(file);
+        WritableFeatureSet store = (WritableFeatureSet) DataStores.open(file);
         assertNotNull(store);
 
         FeatureType ft = store.getType();
diff --git a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONWriteTest.java b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONWriteTest.java
index c4475f8..55b0028 100644
--- a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONWriteTest.java
+++ b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/GeoJSONWriteTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.internal.storage.geojson;
 
+import org.apache.sis.feature.FeatureComparator;
 import com.fasterxml.jackson.core.JsonEncoding;
 import java.io.*;
 import java.lang.reflect.Array;
@@ -31,10 +32,11 @@ import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.internal.feature.AttributeConvention;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.WritableFeatureSet;
 import org.apache.sis.storage.geojson.GeoJSONProvider;
+import org.apache.sis.storage.geojson.GeoJSONStore;
 import org.apache.sis.storage.geojson.GeoJSONStreamWriter;
 import org.apache.sis.util.iso.SimpleInternationalString;
-import org.apache.sis.storage.geojson.GeoJSONStore;
 import org.apache.sis.test.TestCase;
 import static org.junit.Assert.*;
 import org.junit.BeforeClass;
@@ -70,7 +72,7 @@ public class GeoJSONWriteTest extends TestCase {
 
         final Path file = Files.createTempFile("point", ".json");
 
-        final GeoJSONStore store = new GeoJSONStore(new GeoJSONProvider(), file, 7);
+        final WritableFeatureSet store = new GeoJSONStore(new GeoJSONProvider(), file, 7);
         assertNotNull(store);
         final String typeName = file.getFileName().toString().replace(".json", "");
 
@@ -116,7 +118,7 @@ public class GeoJSONWriteTest extends TestCase {
 
         Path file = Files.createTempFile("geoms", ".json");
 
-        GeoJSONStore store = new GeoJSONStore(new GeoJSONProvider(), file, 7);
+        WritableFeatureSet store = new GeoJSONStore(new GeoJSONProvider(), file, 7);
         assertNotNull(store);
 
         String typeName = file.getFileName().toString().replace(".json", "");
@@ -205,7 +207,7 @@ public class GeoJSONWriteTest extends TestCase {
     public void writeComplexFeaturesTest() throws Exception {
         Path file = Files.createTempFile("complex", ".json");
 
-        GeoJSONStore store = new GeoJSONStore(new GeoJSONProvider(), file, 7);
+        WritableFeatureSet store = new GeoJSONStore(new GeoJSONProvider(), file, 7);
         assertNotNull(store);
 
         String typeName = file.getFileName().toString().replace(".json", "");
@@ -268,7 +270,9 @@ public class GeoJSONWriteTest extends TestCase {
             Iterator<Feature> ite = stream.iterator();
             while (ite.hasNext()) {
                 Feature candidate = ite.next();
-                assertEquals(expected, candidate);
+                FeatureComparator comparator = new FeatureComparator(expected, candidate);
+                comparator.ignoredProperties.add(AttributeConvention.IDENTIFIER);
+                comparator.compare();
             }
         }
         Files.deleteIfExists(file);
diff --git a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/LiteJsonLocationTest.java b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/LiteJsonLocationTest.java
index 15ba514..94c43a3 100644
--- a/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/LiteJsonLocationTest.java
+++ b/storage/sis-geojson/src/test/java/org/apache/sis/internal/storage/geojson/LiteJsonLocationTest.java
@@ -30,9 +30,9 @@ import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import org.apache.sis.storage.geojson.utils.GeoJSONParser;
+import org.apache.sis.internal.geojson.GeoJSONParser;
 import org.apache.sis.internal.geojson.GeoJSONUtils;
-import org.apache.sis.storage.geojson.utils.LiteJsonLocation;
+import org.apache.sis.internal.geojson.LiteJsonLocation;
 import org.apache.sis.test.TestCase;
 
 /**


Mime
View raw message