sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1775863 - in /sis/branches/JDK8: core/sis-utility/src/main/java/org/apache/sis/internal/util/ ide-project/NetBeans/nbproject/ storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/ storage/sis-xmlstore/src/main/java/org/apache/sis...
Date Fri, 23 Dec 2016 17:50:12 GMT
Author: desruisseaux
Date: Fri Dec 23 17:50:12 2016
New Revision: 1775863

URL: http://svn.apache.org/viewvc?rev=1775863&view=rev
Log:
Partial StaxDataStore implementation, enough for having StaxStreamReader to delegate XMLStreamReader creation.

Added:
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
    sis/branches/JDK8/ide-project/NetBeans/nbproject/cfg_hints.xml
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java
    sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java
    sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXReaderTest.java
    sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXWriterTest.java

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/AbstractMap.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -18,6 +18,7 @@ package org.apache.sis.internal.util;
 
 import java.util.Map;
 import java.util.Set;
+import java.util.Objects;
 import java.util.Iterator;
 import java.util.Collection;
 import java.util.Collections;
@@ -26,9 +27,6 @@ import java.util.NoSuchElementException;
 import org.apache.sis.io.TableAppender;
 import org.apache.sis.util.resources.Errors;
 
-// Branch-dependent imports
-import java.util.Objects;
-
 
 /**
  * An alternative to {@link java.util.AbstractMap java.util.AbstractMap} using different implementation strategies.
@@ -68,7 +66,7 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.5
- * @version 0.7
+ * @version 0.8
  * @module
  */
 public abstract class AbstractMap<K,V> implements Map<K,V> {
@@ -132,6 +130,48 @@ public abstract class AbstractMap<K,V> i
     }
 
     /**
+     * Convenience {@code EntryIterator} implementation which iterates over a list of key candidates.
+     * All keys associated to a null value will be skipped.
+     *
+     * @see AbstractMap#entryIterator()
+     *
+     * @since 0.8
+     */
+    protected final class KeyIterator extends EntryIterator<K,V> {
+        /** The key candidates.              */ private final K[] keys;
+        /** Index of current key.            */ private int index = -1;
+        /** Value associated to current key. */ private V value;
+
+        /**
+         * Creates a new iterator over the given key candidates.
+         * The given array is not cloned; do not modify.
+         *
+         * @param  keys  all keys that the map may possibly contain.
+         */
+        @SafeVarargs
+        public KeyIterator(final K... keys) {this.keys = keys;}
+
+        /**
+         * Moves to the next key associated to a non-null value.
+         *
+         * @return {@code false} if this method reached iteration end.
+         */
+        @Override
+        protected boolean next() {
+            while (++index < keys.length) {
+                value = get(keys[index]);
+                if (value != null) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override protected K getKey()   {return keys[index];}
+        @Override protected V getValue() {return value;}
+    }
+
+    /**
      * An implementation of {@link EntryIterator} which delegates its work to a standard iterator.
      * Subclasses can modify the {@link #value} or other properties during iteration.
      *
@@ -499,6 +539,9 @@ public abstract class AbstractMap<K,V> i
      * Returns an iterator over the entries in this map.
      * It is okay (but not required) to return {@code null} if the map is empty.
      *
+     * <div class="note"><b>Tip:</b>
+     * {@link KeyIterator} provides a convenient implementation for simple cases.</div>
+     *
      * @return an iterator over the entries in this map, or {@code null}.
      */
     protected abstract EntryIterator<K,V> entryIterator();

Modified: sis/branches/JDK8/ide-project/NetBeans/nbproject/cfg_hints.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/ide-project/NetBeans/nbproject/cfg_hints.xml?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/ide-project/NetBeans/nbproject/cfg_hints.xml (original)
+++ sis/branches/JDK8/ide-project/NetBeans/nbproject/cfg_hints.xml Fri Dec 23 17:50:12 2016
@@ -79,6 +79,8 @@
         </node>
         <node name="org.netbeans.modules.java.hints.SuspiciousNamesCombination">
             <attribute name="groups" value="x, width|y, height"/>
+            <attribute name="enabled" value="true"/>
+            <attribute name="hintSeverity" value="HINT"/>
         </node>
         <node name="org.netbeans.modules.java.hints.finalize.FinalizeNotProtected">
             <attribute name="enabled" value="true"/>
@@ -150,5 +152,10 @@
             <attribute name="maxLength" value="35"/>
             <attribute name="enabled" value="false"/>
         </node>
+        <node name="org.netbeans.modules.java.hints.bugs.CollectionRemove">
+            <attribute name="warn-for-castable" value="true"/>
+            <attribute name="enabled" value="true"/>
+            <attribute name="hintSeverity" value="HINT"/>
+        </node>
     </tool>
 </configuration>

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXReader.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -27,7 +27,6 @@ import javax.xml.stream.XMLStreamReader;
 import javax.xml.bind.JAXBException;
 import com.esri.core.geometry.Point;
 import org.apache.sis.storage.gps.Fix;
-import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreContentException;
 import org.apache.sis.internal.xml.StaxStreamReader;
@@ -48,7 +47,7 @@ import org.opengis.feature.Feature;
  *
  * {@preformat java
  *     Consumer<Feature> consumer = ...;
- *     try (Reader reader = new Reader(dataStore, connector)) {
+ *     try (Reader reader = new Reader(dataStore)) {
  *         final Version  version  = reader.initialize(true);
  *         final Metadata metadata = reader.getMetadata();
  *         reader.forEachRemaining(consumer);
@@ -99,18 +98,15 @@ public class GPXReader extends StaxStrea
     private int trackId;
 
     /**
-     * Creates a new GPX reader from the given file, URL, stream or reader object.
+     * Creates a new GPX reader for the given data store.
      * The {@link #initialize(boolean)} method must be invoked after this constructor.
      *
      * @param  owner      the data store for which this reader is created.
-     * @param  connector  information about the storage (URL, stream, <i>etc</i>).
      * @throws DataStoreException if the input type is not recognized.
      * @throws XMLStreamException if an error occurred while opening the XML file.
      */
-    public GPXReader(final GPXStore owner, final StorageConnector connector)
-            throws DataStoreException, XMLStreamException
-    {
-        super(owner, connector);
+    public GPXReader(final GPXStore owner) throws DataStoreException, XMLStreamException {
+        super(owner);
         types = Types.DEFAULT;
     }
 
@@ -126,7 +122,7 @@ public class GPXReader extends StaxStrea
      * Strictly speaking we should require the namespace URI to be exactly {@link #namespace},
      * but this method is a little bit more lenient.
      */
-    private boolean isGPX(final XMLStreamReader reader) {
+    private boolean isGPX() {
         final String ns = reader.getNamespaceURI();
         return Objects.equals(namespace, ns) || isGPX(ns);
     }
@@ -135,7 +131,7 @@ public class GPXReader extends StaxStrea
      * Returns {@code true} if the current position of the given reader is the closing {@code </gpx>} tag.
      * The reader event should be {@link #END_ELEMENT} before to invoke this method.
      */
-    private boolean isEndGPX(final XMLStreamReader reader) {
+    private boolean isEndGPX() {
         assert reader.isEndElement();
         return Tags.GPX.equals(reader.getLocalName()) && Objects.equals(namespace, reader.getNamespaceURI());
     }
@@ -168,7 +164,6 @@ public class GPXReader extends StaxStrea
          * If a version is specified, we require major.minor version 1.0 or 1.1 but accept any bug-fix versions
          * (e.g. 1.1.x). If no version attribute was found, try to infer the version from the namespace URL.
          */
-        final XMLStreamReader reader = getReader();
         namespace = reader.getNamespaceURI();
         String ver = reader.getAttributeValue(null, Attributes.VERSION);
         Version version = null;
@@ -204,7 +199,7 @@ parse:  while (reader.hasNext()) {
                      * if GPX 1.0 metadata like <name> or <author> appear after the GPX 1.1 <metadata> element.
                      * If both kind of metadata are specified, the latest value overwrites the values before it.
                      */
-                    if (isGPX(reader)) {
+                    if (isGPX()) {
                         final String name = reader.getLocalName();
                         if (readMetadata) {
                             switch (name) {
@@ -246,7 +241,7 @@ parse:  while (reader.hasNext()) {
                      * Reminder: END_ELEMENT events are skipped by getElementText(), getElementAsFoo()
                      * and unmarshal(…) methods. There is only the enclosing <gpx> tag to check here.
                      */
-                    if (isEndGPX(reader)) {
+                    if (isEndGPX()) {
                         break parse;
                     }
                     break;
@@ -383,7 +378,6 @@ parse:  while (reader.hasNext()) {
      */
     @SuppressWarnings("fallthrough")
     private boolean parse(final Consumer<? super Feature> action, final boolean all) throws Exception {
-        final XMLStreamReader reader = getReader();
         for (int type = reader.getEventType(); ; type = reader.next()) {
             /*
              * We do not need to check 'reader.hasNext()' in above loop
@@ -392,10 +386,10 @@ parse:  while (reader.hasNext()) {
             switch (type) {
                 case START_ELEMENT: {
                     final Feature f;
-                    switch (isGPX(reader) ? reader.getLocalName() : "") {
-                        case Tags.WAY_POINT: f = parseWayPoint(reader, ++wayPointId); break;
-                        case Tags.ROUTES:    f = parseRoute   (reader, ++routeId);    break;
-                        case Tags.TRACKS:    f = parseTrack   (reader, ++trackId);    break;
+                    switch (isGPX() ? reader.getLocalName() : "") {
+                        case Tags.WAY_POINT: f = parseWayPoint(++wayPointId); break;
+                        case Tags.ROUTES:    f = parseRoute   (++routeId);    break;
+                        case Tags.TRACKS:    f = parseTrack   (++trackId);    break;
                         case Tags.GPX:       throw new DataStoreContentException(nestedElement(Tags.GPX));
                         default:             skipUntilEnd(reader.getName()); continue;
                     }
@@ -404,7 +398,7 @@ parse:  while (reader.hasNext()) {
                     reader.next();                                      // Skip the END_ELEMENT
                     return true;
                 }
-                case END_ELEMENT:  if (!isEndGPX(reader)) continue;     // else fallthrough
+                case END_ELEMENT:  if (!isEndGPX()) continue;           // else fallthrough
                 case END_DOCUMENT: return false;
             }
         }
@@ -416,7 +410,7 @@ parse:  while (reader.hasNext()) {
      *
      * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseWayPoint(final XMLStreamReader reader, final int index) throws Exception {
+    private Feature parseWayPoint(final int index) throws Exception {
         assert reader.isStartElement();
         /*
          * Way points might be located in different elements: <wpt>, <rtept> and <trkpt>.
@@ -443,7 +437,7 @@ parse:  while (reader.hasNext()) {
                 case START_ELEMENT: {
                     final Object value;
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader) ? name : "") {
+                    switch (isGPX() ? name : "") {
                         case Tags.NAME:             // Fallthrough to getElementText()
                         case Tags.COMMENT:          // ︙
                         case Tags.DESCRIPTION:      // ︙
@@ -474,7 +468,7 @@ parse:  while (reader.hasNext()) {
                     break;
                 }
                 case END_ELEMENT: {
-                    if (tagName.equals(reader.getLocalName()) && isGPX(reader)) {
+                    if (tagName.equals(reader.getLocalName()) && isGPX()) {
                         if (links != null) feature.setPropertyValue(Tags.LINK, links);
                         return feature;
                     }
@@ -493,7 +487,7 @@ parse:  while (reader.hasNext()) {
      *
      * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseRoute(final XMLStreamReader reader, final int index) throws Exception {
+    private Feature parseRoute(final int index) throws Exception {
         assert reader.isStartElement() && Tags.ROUTES.equals(reader.getLocalName());
         final Feature feature = types.route.newInstance();
         feature.setPropertyValue("@identifier", index);
@@ -508,7 +502,7 @@ parse:  while (reader.hasNext()) {
                 case START_ELEMENT: {
                     final Object value;
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader) ? name : "") {
+                    switch (isGPX() ? name : "") {
                         default: continue;
                         case Tags.NAME:        // Fallthrough to getElementText()
                         case Tags.COMMENT:     // ︙
@@ -521,7 +515,7 @@ parse:  while (reader.hasNext()) {
                         case Tags.ROUTES:      throw new DataStoreContentException(nestedElement(name));
                         case Tags.ROUTE_POINTS: {
                             if (wayPoints == null) wayPoints = new ArrayList<>(8);
-                            wayPoints.add(parseWayPoint(reader, wayPoints.size() + 1));
+                            wayPoints.add(parseWayPoint(wayPoints.size() + 1));
                             continue;
                         }
                     }
@@ -529,7 +523,7 @@ parse:  while (reader.hasNext()) {
                     break;
                 }
                 case END_ELEMENT: {
-                    if (Tags.ROUTES.equals(reader.getLocalName()) && isGPX(reader)) {
+                    if (Tags.ROUTES.equals(reader.getLocalName()) && isGPX()) {
                         if (wayPoints != null) feature.setPropertyValue(Tags.ROUTE_POINTS, wayPoints);
                         if (links     != null) feature.setPropertyValue(Tags.LINK, links);
                         return feature;
@@ -549,7 +543,7 @@ parse:  while (reader.hasNext()) {
      *
      * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseTrackSegment(final XMLStreamReader reader, final int index) throws Exception {
+    private Feature parseTrackSegment(final int index) throws Exception {
         assert reader.isStartElement() && Tags.TRACK_SEGMENTS.equals(reader.getLocalName());
         final Feature feature = types.trackSegment.newInstance();
         feature.setPropertyValue("@identifier", index);
@@ -562,18 +556,18 @@ parse:  while (reader.hasNext()) {
             switch (reader.next()) {
                 case START_ELEMENT: {
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader) ? name : "") {
+                    switch (isGPX() ? name : "") {
                         default: continue;
                         case Tags.TRACK_POINTS: {
                             if (wayPoints == null) wayPoints = new ArrayList<>(8);
-                            wayPoints.add(parseWayPoint(reader, wayPoints.size() + 1));
+                            wayPoints.add(parseWayPoint(wayPoints.size() + 1));
                             continue;
                         }
                         case Tags.TRACK_SEGMENTS: throw new DataStoreContentException(nestedElement(name));
                     }
                 }
                 case END_ELEMENT: {
-                    if (Tags.TRACK_SEGMENTS.equals(reader.getLocalName()) && isGPX(reader)) {
+                    if (Tags.TRACK_SEGMENTS.equals(reader.getLocalName()) && isGPX()) {
                         if (wayPoints != null) feature.setPropertyValue(Tags.TRACK_POINTS, wayPoints);
                         return feature;
                     }
@@ -592,7 +586,7 @@ parse:  while (reader.hasNext()) {
      *
      * @throws Exception see the list of exceptions documented in {@link #parse(Consumer, boolean)}.
      */
-    private Feature parseTrack(final XMLStreamReader reader, final int index) throws Exception {
+    private Feature parseTrack(final int index) throws Exception {
         assert reader.isStartElement() && Tags.TRACKS.equals(reader.getLocalName());
         final Feature feature = types.track.newInstance();
         feature.setPropertyValue("@identifier", index);
@@ -607,7 +601,7 @@ parse:  while (reader.hasNext()) {
                 case START_ELEMENT: {
                     final Object value;
                     final String name = reader.getLocalName();
-                    switch (isGPX(reader) ? name : "") {
+                    switch (isGPX() ? name : "") {
                         default: continue;
                         case Tags.NAME:         // Fallthrough to getElementText()
                         case Tags.COMMENT:      // ︙
@@ -620,7 +614,7 @@ parse:  while (reader.hasNext()) {
                         case Tags.TRACKS:       throw new DataStoreContentException(nestedElement(name));
                         case Tags.TRACK_SEGMENTS: {
                             if (segments == null) segments = new ArrayList<>(8);
-                            segments.add(parseTrackSegment(reader, segments.size() + 1));
+                            segments.add(parseTrackSegment(segments.size() + 1));
                             continue;
                         }
                     }
@@ -628,7 +622,7 @@ parse:  while (reader.hasNext()) {
                     break;
                 }
                 case END_ELEMENT: {
-                    if (Tags.TRACKS.equals(reader.getLocalName()) && isGPX(reader)) {
+                    if (Tags.TRACKS.equals(reader.getLocalName()) && isGPX()) {
                         if (segments != null) feature.setPropertyValue(Tags.TRACK_SEGMENTS, segments);
                         if (links    != null) feature.setPropertyValue(Tags.LINK, links);
                         return feature;

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/gpx/GPXStore.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -18,6 +18,7 @@ package org.apache.sis.internal.gpx;
 
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
+import javax.xml.stream.XMLStreamException;
 import org.apache.sis.internal.xml.StaxDataStore;
 import org.apache.sis.setup.OptionKey;
 import org.apache.sis.storage.DataStoreException;
@@ -26,6 +27,11 @@ import org.apache.sis.util.ArgumentCheck
 import org.apache.sis.util.Version;
 import org.opengis.metadata.Metadata;
 
+// Branch-dependent imports
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+import org.opengis.feature.Feature;
+
 
 /**
  * A data store backed by GPX files.
@@ -53,6 +59,16 @@ public class GPXStore extends StaxDataSt
     final Charset encoding;
 
     /**
+     * The metadata, or {@code null} if not yet parsed.
+     */
+    private transient Metadata metadata;
+
+    /**
+     * Iterator over the features.
+     */
+    private GPXReader reader;
+
+    /**
      * Creates a new GPX store from the given file, URL or stream object.
      * This constructor invokes {@link StorageConnector#closeAllExcept(Object)},
      * keeping open only the needed resource.
@@ -82,8 +98,42 @@ public class GPXStore extends StaxDataSt
         return null;    // TODO
     }
 
+    /**
+     * Returns the stream of features.
+     *
+     * @return a stream over all features in the CSV file.
+     *
+     * @todo Needs to reset the position when doing another pass on the features.
+     */
+    @Override
+    public Stream<Feature> getFeatures() {
+        return StreamSupport.stream(reader, false);
+    }
+
+    final GPXReader reader() throws DataStoreException, XMLStreamException {
+        return reader = new GPXReader(this);
+    }
+
+    /**
+     * Closes this data store and releases any underlying resources.
+     *
+     * @throws DataStoreException if an error occurred while closing this data store.
+     */
     @Override
-    public void close() throws DataStoreException {
-        // TODO
+    public synchronized void close() throws DataStoreException {
+        final GPXReader r = reader;
+        reader = null;
+        if (r != null) try {
+            r.close();
+        } catch (XMLStreamException e) {
+            final DataStoreException ds = new DataStoreException(e);
+            try {
+                super.close();
+            } catch (DataStoreException s) {
+                ds.addSuppressed(s.getCause());
+            }
+            throw ds;
+        }
+        super.close();
     }
 }

Added: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java?rev=1775863&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java (added)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -0,0 +1,153 @@
+/*
+ * 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.internal.xml;
+
+import java.io.Reader;
+import java.io.InputStream;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXSource;
+import org.xml.sax.InputSource;
+import org.w3c.dom.Node;
+
+
+/**
+ * Creates {@link XMLStreamReader} from a given input. This enumeration allows to analyze the input type
+ * only once before to create as many instances of {@link XMLStreamReader} as needed for that input.
+ * The enumeration order is the preference order (i.e. we will test if the object already implements the
+ * {@link XMLStreamReader} interface before to test for {@link InputStream}, {@link Reader}, <i>etc.</i>).
+ *
+ * <p>Some kinds of inputs can be used many time (for example {@link Node}).
+ * Other inputs can be used only once (for example {@link XMLEventReader}).
+ * For some inputs, it depends on whether the stream support marks.</p>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.8
+ * @version 0.8
+ * @module
+ */
+enum InputType {
+    /**
+     * The input is already an instance of {@link XMLStreamReader}.
+     * That input is returned directly and can be used only once.
+     */
+    STAX(XMLStreamReader.class) {
+        @Override XMLStreamReader create(StaxDataStore ds, Object s) {
+            return (XMLStreamReader) s;
+        }
+    },
+
+    /**
+     * The input is an instance of Java I/O {@link InputStream}.
+     * Decoding may depend on the {@linkplain StaxDataStore#encoding data store character encoding}.
+     */
+    STREAM(InputStream.class) {
+        @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException {
+            final XMLInputFactory f = ds.inputFactory();
+            return (ds.encoding != null) ? f.createXMLStreamReader((InputStream) s, ds.encoding.name())
+                                         : f.createXMLStreamReader((InputStream) s);
+        }
+    },
+
+    /**
+     * The input is an instance of Java I/O {@link Reader}.
+     */
+    CHARACTERS(Reader.class) {
+        @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException {
+            return ds.inputFactory().createXMLStreamReader((Reader) s);
+        }
+    },
+
+    /**
+     * The input is an instance of XML {@link Source}, which is itself a wrapper around another kind of source.
+     */
+    SOURCE(Source.class) {
+        @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException {
+            return ds.inputFactory().createXMLStreamReader((Source) s);
+        }
+    },
+
+    /**
+     * The input is an instance of DOM {@link Node}.
+     */
+    NODE(Node.class) {
+        @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException {
+            return ds.inputFactory().createXMLStreamReader(new DOMSource((Node) s));
+        }
+    },
+
+    /**
+     * The input is an instance of SAX {@link InputSource}.
+     */
+    SAX(InputSource.class) {
+        @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException {
+            return ds.inputFactory().createXMLStreamReader(new SAXSource((InputSource) s));
+        }
+    },
+
+    /**
+     * The input is an instance of STAX {@link XMLEventReader}.
+     */
+    EVENT(XMLEventReader.class) {
+        @Override XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException {
+            return ds.inputFactory().createXMLStreamReader(new StAXSource((XMLEventReader) s));
+        }
+    };
+
+    /**
+     * The kind of input that this enumeration can handle.
+     */
+    private final Class<?> inputType;
+
+    /**
+     * Creates a new enumeration for the given type of input.
+     */
+    private InputType(final Class<?> inputType) {
+        this.inputType = inputType;
+    }
+
+    /**
+     * Creates a XML reader for the given input.
+     *
+     * @param  ds  the data store for which to create reader instances.
+     * @param  s   the input stream or the storage object (URL, <i>etc</i>).
+     * @return the XML reader.
+     * @throws XMLStreamException if the XML reader creation failed.
+     */
+    abstract XMLStreamReader create(StaxDataStore ds, Object s) throws XMLStreamException;
+
+    /**
+     * Returns a {@code ReaderFactory} for the given input type. The {@code type} argument given to this method
+     * shall be the class of the {@code s} argument to be given in {@link #create(StaxDataStore, Object)} calls.
+     *
+     * @param  type  the type of the input stream or storage object (URL, <i>etc</i>).
+     * @return a factory for the given stream or storage type, or {@code null} if the given type is not recognized.
+     */
+    static InputType forType(final Class<?> type) {
+        for (final InputType c : values()) {
+            if (c.inputType.isAssignableFrom(type)) {
+                return c;
+            }
+        }
+        return null;
+    }
+}

Propchange: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/InputType.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxDataStore.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -16,21 +16,31 @@
  */
 package org.apache.sis.internal.xml;
 
-import java.util.Map;
-import java.util.HashMap;
 import java.util.Locale;
 import java.util.TimeZone;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
 import javax.xml.stream.Location;
 import javax.xml.stream.XMLReporter;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamException;
 import org.apache.sis.xml.XML;
 import org.apache.sis.setup.OptionKey;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.StorageConnector;
-import org.apache.sis.util.logging.WarningListeners;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.internal.storage.FeatureStore;
+import org.apache.sis.internal.util.AbstractMap;
+import org.apache.sis.storage.UnsupportedStorageException;
+import org.apache.sis.util.logging.WarningListener;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.Classes;
 
 
 /**
@@ -42,22 +52,61 @@ import org.apache.sis.util.logging.Warni
  * @version 0.8
  * @module
  */
-public abstract class StaxDataStore extends DataStore implements XMLReporter {
+public abstract class StaxDataStore extends FeatureStore {
     /**
-     * The locale to use for locale-sensitive data (<strong>not</strong> for logging or warning messages),
-     * or {@code null} if unspecified.
+     * The store name (typically filename) for formatting error messages.
+     */
+    protected final String name;
+
+    /**
+     * Configuration information for JAXB (un)marshaller (actually the SIS wrappers) or for the STAX factories.
+     * This object is a read-only map which may contain the following entries:
+     *
+     * <ul>
+     *   <li>{@link XML#LOCALE}   — the locale to use for locale-sensitive data (<strong>not</strong> for logging or warning messages).</li>
+     *   <li>{@link XML#TIMEZONE} — the timezone to use when parsing or formatting dates and times without explicit timezone.</li>
+     * </ul>
+     *
+     * In addition, the {@link Config} class also implements various listener interfaces to be given to
+     * JAXB (un)marshallers (actually the SIS wrappers) and STAX factories configuration.
      *
      * @see OptionKey#LOCALE
+     * @see OptionKey#TIMEZONE
      */
-    private final Locale locale;
+    final Config configuration;
 
     /**
-     * The timezone to use when parsing or formatting dates and times without explicit timezone,
-     * or {@code null} if unspecified.
+     * The character encoding, or {@code null} if unspecified.
+     * This is often (but not always) ignored at reading time, but taken in account at writing time.
+     */
+    final Charset encoding;
+
+    /**
+     * The storage object has given by the user. Can be {@link java.nio.file.Path}, {@link java.net.URL},
+     * {@link java.io.InputStream}, {@link java.io.Reader}, {@link javax.xml.stream.XMLStreamReader},
+     * {@link org.w3c.dom.Node} or some other types including the writer variants of above list.
      *
-     * @see OptionKey#TIMEZONE
+     * <p>A {@code null} value means that this datastore has been {@linkplain #close() closed}.</p>
+     *
+     * @see StorageConnector#getStorage()
+     */
+    private Object storage;
+
+    /**
+     * The underlying stream to close when this {@code StaxDataStore} is closed, or {@code null} if none.
+     * This is often the same reference than {@link #storage} if the later is closeable, but not always.
+     * For example if {@code storage} is a {@link java.nio.file.Path}, then {@code stream} will be some
+     * stream or channel opened for that path.
+     *
+     * @see #close()
      */
-    private final TimeZone timezone;
+    private Closeable stream;
+
+    /**
+     * The function in charge of producing a {@link XMLStreamReader} from the {@link #storage} or {@link #stream}.
+     * This field is {@code null} if the XML file is write only.
+     */
+    private final InputType storageToReader;
 
     /**
      * The STAX readers factory, created when first needed.
@@ -77,11 +126,118 @@ public abstract class StaxDataStore exte
      * Creates a new data store.
      *
      * @param  connector  information about the storage (URL, stream, <i>etc</i>).
+     * @throws DataStoreException if the input or output type is not recognized.
      */
-    protected StaxDataStore(final StorageConnector connector) {
+    protected StaxDataStore(final StorageConnector connector) throws DataStoreException {
         super(connector);
-        locale   = connector.getOption(OptionKey.LOCALE);
-        timezone = connector.getOption(OptionKey.TIMEZONE);
+        name          = connector.getStorageName();
+        storage       = connector.getStorage();
+        encoding      = connector.getOption(OptionKey.ENCODING);
+        configuration = new Config(connector);
+        InputType storageToReader = InputType.forType(storage.getClass());
+        if (storageToReader == null) {
+            stream = connector.getStorageAs(InputStream.class);
+            if (stream != null) {
+                storageToReader = InputType.STREAM;
+            }
+        } else if (storage instanceof Closeable) {
+            stream = (Closeable) storage;
+        }
+        this.storageToReader = storageToReader;
+        connector.closeAllExcept(stream);
+    }
+
+    /**
+     * Holds information that can be used for (un)marshallers configuration, and opportunistically
+     * implement various listeners used by JAXB (actually the SIS wrappers) or STAX.
+     */
+    private final class Config extends AbstractMap<String,Object> implements XMLReporter, WarningListener<Object> {
+        /**
+         * The locale to use for locale-sensitive data (<strong>not</strong> for logging or warning messages),
+         * or {@code null} if unspecified.
+         *
+         * @see OptionKey#LOCALE
+         */
+        private final Locale locale;
+
+        /**
+         * The timezone to use when parsing or formatting dates and times without explicit timezone,
+         * or {@code null} if unspecified.
+         *
+         * @see OptionKey#TIMEZONE
+         */
+        private final TimeZone timezone;
+
+        /**
+         * Fetches configuration information from the given object.
+         */
+        Config(final StorageConnector connector) {
+            locale   = connector.getOption(OptionKey.LOCALE);
+            timezone = connector.getOption(OptionKey.TIMEZONE);
+        }
+
+        /**
+         * Returns configuration associated to the given key, or {@code null} if none.
+         *
+         * @param  key  one of {@link XML#LOCALE}, {@link XML#TIMEZONE} or {@link XML#WARNING_LISTENER}.
+         * @return the configuration for the given key, or {@code null} if none or if the given key is invalid.
+         */
+        @Override
+        @SuppressWarnings("ReturnOfCollectionOrArrayField")
+        public Object get(final Object key) {
+            if (key instanceof String) {
+                switch ((String) key) {
+                    case XML.LOCALE:           return locale;
+                    case XML.TIMEZONE:         return timezone;
+                    case XML.WARNING_LISTENER: return this;
+                }
+            }
+            return null;
+        }
+
+        /**
+         * Returns an iterator over all entries in this map.
+         */
+        @Override
+        protected EntryIterator<String, Object> entryIterator() {
+            return new KeyIterator(XML.LOCALE, XML.TIMEZONE, XML.WARNING_LISTENER);
+        }
+
+        /**
+         * Forwards STAX warnings to {@link DataStore} listeners.
+         * This method is invoked by {@link XMLStreamReader} when needed.
+         *
+         * @param message    the message to put in a logging record.
+         * @param errorType  ignored.
+         * @param info       ignored.
+         * @param location   ignored.
+         */
+        @Override
+        public void report(String message, String errorType, Object info, Location location) {
+            final LogRecord record = new LogRecord(Level.WARNING, message);
+            record.setSourceClassName(getClass().getCanonicalName());
+            listeners.warning(record);
+        }
+
+        /**
+         * Reports a warning represented by the given log record.
+         *
+         * @param source   ignored (typically a JAXB object being unmarshalled). Can be {@code null}.
+         * @param warning  the warning as a log record.
+         */
+        @Override
+        public void warningOccured(final Object source, final LogRecord warning) {
+            listeners.warning(warning);
+        }
+
+        /**
+         * Returns the type of objects that emit warnings of interest for this listener.
+         * Fixed to {@code Object.class} as required by {@link org.apache.sis.xml.XML#WARNING_LISTENER} documentation.
+         */
+        @Override
+        public final Class<Object> getSourceClass() {
+            return Object.class;
+        }
     }
 
     /**
@@ -94,17 +250,19 @@ public abstract class StaxDataStore exte
 
     /**
      * Returns the factory for STAX readers.
+     * This method is invoked by {@link InputType#create(StaxDataStore, Object)}.
      */
     final synchronized XMLInputFactory inputFactory() {
         if (inputFactory == null) {
             inputFactory = XMLInputFactory.newInstance();
-            inputFactory.setXMLReporter(this);
+            inputFactory.setXMLReporter(configuration);
         }
         return inputFactory;
     }
 
     /**
      * Returns the factory for STAX writers.
+     * This method is invoked by {@link OutputType#create(StaxDataStore, Object)}.
      */
     final synchronized XMLOutputFactory outputFactory() {
         if (outputFactory == null) {
@@ -114,39 +272,39 @@ public abstract class StaxDataStore exte
         return outputFactory;
     }
 
-    /**
-     * Returns the properties that can be used to JAXB (un)marshaller.
-     *
-     * @param  target  the object for which we are creating (un)marshaller configuration.
-     */
-    final Map<String,Object> configuration(final StaxStreamIO target) {
-        final Map<String,Object> properties = new HashMap<>(4);
-        if (locale   != null) properties.put(XML.LOCALE,   locale);
-        if (timezone != null) properties.put(XML.TIMEZONE, timezone);
-        properties.put(XML.WARNING_LISTENER, target);
-        return properties;
+    protected final XMLStreamReader createReader() throws DataStoreException, XMLStreamException {
+        if (storageToReader == null) {
+            throw new UnsupportedStorageException(errors().getString(Errors.Keys.IllegalInputTypeForReader_2,
+                    getFormatName(), Classes.getClass(storage)));
+        }
+        // TODO: mark the stream
+        return storageToReader.create(this, stream != null ? stream : storage);
     }
 
     /**
-     * Gives to {@link StaxStreamIO} an access to the {@link #listeners} field.
+     * Returns the error resources in the current locale.
      */
-    final WarningListeners<DataStore> listeners() {
-        return listeners;
+    private Errors errors() {
+        return Errors.getResources(getLocale());
     }
 
     /**
-     * Forwards STAX warnings to {@link DataStore} listeners.
-     * This method is invoked by {@link javax.xml.stream.XMLStreamReader} when needed.
+     * Closes the input or output stream and releases any resources used by this XML data store.
+     * This data store can not be used anymore after this method has been invoked.
      *
-     * @param message    the message to put in a logging record.
-     * @param errorType  ignored.
-     * @param info       ignored.
-     * @param location   ignored.
+     * @throws DataStoreException if an error occurred while closing the input or output stream.
      */
     @Override
-    public void report(String message, String errorType, Object info, Location location) {
-        final LogRecord record = new LogRecord(Level.WARNING, message);
-        record.setSourceClassName(getClass().getCanonicalName());
-        listeners.warning(record);
+    public synchronized void close() throws DataStoreException {
+        final Closeable s = stream;
+        stream        = null;
+        storage       = null;
+        inputFactory  = null;
+        outputFactory = null;
+        if (s != null) try {
+            s.close();
+        } catch (IOException e) {
+            throw new DataStoreException(e);
+        }
     }
 }

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamIO.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -16,12 +16,7 @@
  */
 package org.apache.sis.internal.xml;
 
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.logging.LogRecord;
-import javax.xml.stream.XMLStreamException;
 import org.apache.sis.util.ArgumentChecks;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.util.resources.Errors;
 
 
@@ -42,19 +37,13 @@ import org.apache.sis.util.resources.Err
  * @version 0.8
  * @module
  */
-abstract class StaxStreamIO implements AutoCloseable, WarningListener<Object> {
+abstract class StaxStreamIO implements AutoCloseable {
     /**
      * The data store for which this reader or writer has been created.
      */
     protected final StaxDataStore owner;
 
     /**
-     * The underlying stream to close when this {@code StaxStreamIO} reader or writer is closed,
-     * or {@code null} if none.
-     */
-    private Closeable stream;
-
-    /**
      * For sub-classes constructors.
      *
      * @param owner  the data store for which this reader or writer is created.
@@ -65,60 +54,9 @@ abstract class StaxStreamIO implements A
     }
 
     /**
-     * Notifies this {@code StaxStreamIO} that the given stream will need to be closed by the {@link #close()} method.
-     * This method can be invoked at most once. This method does nothing if the given object does not implement the
-     * {@link Closeable} interface.
-     *
-     * @param stream the stream to be closed when {@link #close()} will be invoked.
-     */
-    protected final void initCloseable(final Object stream) {
-        if (this.stream != null) {
-            throw new IllegalStateException();
-        }
-        if (stream instanceof Closeable) {
-            this.stream = (Closeable) stream;
-        }
-    }
-
-    /**
-     * Closes the input or output stream and releases any resources used by this XML reader or writer.
-     * This reader or writer can not be used anymore after this method has been invoked.
-     *
-     * @throws IOException if an error occurred while closing the input or output stream.
-     * @throws XMLStreamException if an error occurred while releasing XML reader/writer resources.
-     */
-    @Override
-    public void close() throws IOException, XMLStreamException {
-        if (stream != null) {
-            stream.close();
-            stream = null;
-        }
-    }
-
-    /**
      * Returns the error resources in the current locale.
      */
     protected final Errors errors() {
         return Errors.getResources(owner.getLocale());
     }
-
-    /**
-     * Reports a warning represented by the given log record.
-     *
-     * @param source  ignored (typically a JAXB object being unmarshalled). Can be {@code null}.
-     * @param record  the warning as a log record.
-     */
-    @Override
-    public final void warningOccured(final Object source, final LogRecord warning) {
-        owner.listeners().warning(warning);
-    }
-
-    /**
-     * Returns the type of objects that emit warnings of interest for this listener.
-     * Fixed to {@code Object.class} as required by {@link org.apache.sis.xml.XML#WARNING_LISTENER} documentation.
-     */
-    @Override
-    public final Class<Object> getSourceClass() {
-        return Object.class;
-    }
 }

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamReader.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -22,38 +22,26 @@ import java.util.Arrays;
 import java.util.function.Predicate;
 import java.util.NoSuchElementException;
 import java.net.URI;
-import java.io.Reader;
-import java.io.InputStream;
 import java.io.IOException;
 import java.io.EOFException;
 import java.net.URISyntaxException;
 import javax.xml.namespace.QName;
 import javax.xml.stream.Location;
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.util.StreamReaderDelegate;
-import javax.xml.transform.Source;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.sax.SAXSource;
 import javax.xml.transform.stax.StAXSource;
 import javax.xml.bind.JAXBException;
-import org.xml.sax.InputSource;
-import org.w3c.dom.Node;
 import org.apache.sis.xml.XML;
 import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.util.StandardDateFormat;
 import org.apache.sis.internal.storage.IOUtilities;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreContentException;
-import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.util.collection.BackingStoreException;
 import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.Classes;
 
 // Branch-dependent imports
 import java.util.Spliterator;
@@ -97,7 +85,7 @@ import org.opengis.feature.Feature;
  *
  * {@preformat java
  *     Consumer<Feature> consumer = ...;
- *     try (UserObjectReader reader = new UserObjectReader(input)) {
+ *     try (UserObjectReader reader = new UserObjectReader(dataStore)) {
  *         reader.forEachRemaining(consumer);
  *     }
  * }
@@ -116,47 +104,18 @@ public abstract class StaxStreamReader e
     /**
      * The XML stream reader.
      */
-    private XMLStreamReader reader;
+    protected final XMLStreamReader reader;
 
     /**
-     * Input name (typically filename) for formatting error messages.
-     */
-    protected final String inputName;
-
-    /**
-     * Creates a new XML reader from the given file, URL, stream or reader object.
+     * Creates a new XML reader for the given data store.
      *
-     * @param  owner      the data store for which this reader is created.
-     * @param  connector  information about the storage (URL, stream, <i>etc</i>).
+     * @param  owner  the data store for which this reader is created.
      * @throws DataStoreException if the input type is not recognized.
      * @throws XMLStreamException if an error occurred while opening the XML file.
      */
-    protected StaxStreamReader(final StaxDataStore owner, final StorageConnector connector)
-            throws DataStoreException, XMLStreamException
-    {
+    protected StaxStreamReader(final StaxDataStore owner) throws DataStoreException, XMLStreamException {
         super(owner);
-        inputName = connector.getStorageName();
-        final Object input = connector.getStorage();
-        if      (input instanceof XMLStreamReader) reader = (XMLStreamReader) input;
-        else if (input instanceof XMLEventReader)  reader = factory().createXMLStreamReader(new StAXSource((XMLEventReader) input));
-        else if (input instanceof InputSource)     reader = factory().createXMLStreamReader(new SAXSource((InputSource) input));
-        else if (input instanceof InputStream)     reader = factory().createXMLStreamReader((InputStream) input);
-        else if (input instanceof Reader)          reader = factory().createXMLStreamReader((Reader) input);
-        else if (input instanceof Source)          reader = factory().createXMLStreamReader((Source) input);
-        else if (input instanceof Node)            reader = factory().createXMLStreamReader(new DOMSource((Node) input));
-        else {
-            final InputStream in = connector.getStorageAs(InputStream.class);
-            connector.closeAllExcept(in);
-            if (in == null) {
-                throw new UnsupportedStorageException(errors().getString(Errors.Keys.IllegalInputTypeForReader_2,
-                        owner.getFormatName(), Classes.getClass(input)));
-            }
-            reader = factory().createXMLStreamReader(in);
-            initCloseable(in);
-            return;
-        }
-        initCloseable(input);
-        connector.closeAllExcept(input);
+        reader = owner.createReader();
     }
 
     /**
@@ -216,28 +175,6 @@ public abstract class StaxStreamReader e
     ////////////////////////////////////////////////////////////////////////////////////////////////
 
     /**
-     * Convenience method invoking {@link StaxDataStore#inputFactory()}.
-     */
-    private XMLInputFactory factory() {
-        return owner.inputFactory();
-    }
-
-    /**
-     * Returns the XML stream reader if it is not closed.
-     *
-     * @return the XML stream reader (never null).
-     * @throws XMLStreamException if this XML reader has been closed. Note that a closed reader does not mean that
-     *         the whole {@link StaxDataStore} has been closed since the same datastore may produce many iterators,
-     *         which is why the exception type is not {@link org.apache.sis.storage.DataStoreContentException}.
-     */
-    protected final XMLStreamReader getReader() throws XMLStreamException {
-        if (reader != null) {
-            return reader;
-        }
-        throw new XMLStreamException(errors().getString(Errors.Keys.ClosedReader_1, owner.getFormatName()));
-    }
-
-    /**
      * Returns a XML stream reader over only a portion of the document, from given position inclusive
      * until the end of the given element exclusive. Nested elements of the same name, if any, will be
      * ignored.
@@ -247,7 +184,7 @@ public abstract class StaxStreamReader e
      * @throws XMLStreamException if this XML reader has been closed.
      */
     protected final XMLStreamReader getSubReader(final QName tagName) throws XMLStreamException {
-        return new StreamReaderDelegate(getReader()) {
+        return new StreamReaderDelegate(reader) {
             /** Increased every time a nested element of the same name is found. */
             private int nested;
 
@@ -289,7 +226,6 @@ public abstract class StaxStreamReader e
     protected final void moveToRootElement(final Predicate<String> isNamespace, final String localName)
             throws EOFException, XMLStreamException, DataStoreContentException
     {
-        final XMLStreamReader reader = getReader();
         if (!reader.isStartElement()) {
             do if (!reader.hasNext()) {
                 throw new EOFException(endOfFile());
@@ -297,7 +233,7 @@ public abstract class StaxStreamReader e
         }
         if (!isNamespace.test(reader.getNamespaceURI()) || !localName.equals(reader.getLocalName())) {
             throw new DataStoreContentException(errors().getString(
-                    Errors.Keys.UnexpectedFileFormat_2, owner.getFormatName(), inputName));
+                    Errors.Keys.UnexpectedFileFormat_2, owner.getFormatName(), owner.name));
         }
     }
 
@@ -311,7 +247,6 @@ public abstract class StaxStreamReader e
      * @throws XMLStreamException if an error occurred while reading the XML stream.
      */
     protected final void skipUntilEnd(final QName tagName) throws EOFException, XMLStreamException {
-        final XMLStreamReader reader = getReader();
         int nested = 0;
         while (reader.hasNext()) {
             switch (reader.next()) {
@@ -340,7 +275,7 @@ public abstract class StaxStreamReader e
      * @throws XMLStreamException if a text element can not be returned.
      */
     protected final String getElementText() throws XMLStreamException {
-        String text = getReader().getElementText();
+        String text = reader.getElementText();
         if (text != null) {
             text = text.trim();
             if (!text.isEmpty()) {
@@ -457,23 +392,18 @@ public abstract class StaxStreamReader e
      * @see javax.xml.bind.Unmarshaller#unmarshal(XMLStreamReader, Class)
      */
     protected final <T> T unmarshal(final Class<T> type) throws XMLStreamException, JAXBException {
-        return XML.unmarshal(new StAXSource(getReader()), type, owner.configuration(this)).getValue();
+        return XML.unmarshal(new StAXSource(reader), type, owner.configuration).getValue();
     }
 
     /**
      * Closes the input stream and releases any resources used by this XML reader.
      * This reader can not be used anymore after this method has been invoked.
      *
-     * @throws IOException if an error occurred while closing the input stream.
      * @throws XMLStreamException if an error occurred while releasing XML reader/writer resources.
      */
     @Override
-    public void close() throws IOException, XMLStreamException {
-        if (reader != null) {
-            reader.close();
-            reader = null;
-        }
-        super.close();
+    public void close() throws XMLStreamException {
+        reader.close();
     }
 
     /**
@@ -483,7 +413,7 @@ public abstract class StaxStreamReader e
      * @return a localized error message for end of file error.
      */
     protected final String endOfFile() {
-        return errors().getString(Errors.Keys.UnexpectedEndOfFile_1, inputName);
+        return errors().getString(Errors.Keys.UnexpectedEndOfFile_1, owner.name);
     }
 
     /**
@@ -503,7 +433,7 @@ public abstract class StaxStreamReader e
             line   = 0;
             column = 0;
         }
-        return IOUtilities.canNotParseFile(errors(), owner.getFormatName(), inputName, line, column);
+        return IOUtilities.canNotParseFile(errors(), owner.getFormatName(), owner.name, line, column);
     }
 
     /**

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/xml/StaxStreamWriter.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -119,13 +119,10 @@ public abstract class StaxStreamWriter e
             final Path path = ObjectConverters.convert(output, Path.class);
             final BufferedOutputStream out = new BufferedOutputStream(Files.newOutputStream(path));
             writer = factory().createXMLStreamWriter(out, encoding);
-            initCloseable(out);
-            return;
         } catch (UnconvertibleObjectException e) {
             throw new UnsupportedStorageException(errors().getString(Errors.Keys.IllegalOutputTypeForWriter_2,
                                                   owner.getFormatName(), Classes.getClass(output)), e);
         }
-        initCloseable(output);
     }
 
     /**
@@ -189,15 +186,13 @@ public abstract class StaxStreamWriter e
      * Closes the output stream and releases any resources used by this XML writer.
      * This writer can not be used anymore after this method has been invoked.
      *
-     * @throws IOException if an error occurred while closing the output stream.
      * @throws XMLStreamException if an error occurred while releasing XML writer resources.
      */
     @Override
-    public void close() throws IOException, XMLStreamException {
+    public void close() throws XMLStreamException {
         if (writer != null) {
             writer.close();
             writer = null;
         }
-        super.close();
     }
 }

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXReaderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXReaderTest.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXReaderTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXReaderTest.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -26,6 +26,7 @@ import org.opengis.geometry.Envelope;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.gps.Fix;
 import org.apache.sis.test.TestCase;
+import org.junit.After;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
@@ -33,11 +34,12 @@ import static org.apache.sis.test.TestUt
 
 // Branch-dependent imports
 import java.util.Spliterators;
+import org.apache.sis.storage.DataStoreException;
 import org.opengis.feature.Feature;
 
 
 /**
- * Test {@link GPXReader} class.
+ * Tests the {@link GPXReader} class.
  *
  * @author  Johann Sorel (Geomatys)
  * @since   0.8
@@ -45,13 +47,18 @@ import org.opengis.feature.Feature;
  * @module
  */
 public final strictfp class GPXReaderTest extends TestCase {
+    private GPXStore store;
 
-    private static final double DELTA = 0.000001;
-
-
-    private static GPXReader create(final String resource) throws Exception {
+    private GPXReader create(final String resource) throws Exception {
         StorageConnector storage = new StorageConnector(GPXReaderTest.class.getResource(resource));
-        return new GPXReader(new GPXStore(storage), storage);
+        return new GPXReader(store = new GPXStore(storage));
+    }
+
+    @After
+    public void closeReader() throws DataStoreException {
+        if (store != null) {
+            store.close();
+        }
     }
 
     private static void assertBoundsEquals(final double westBoundLongitude,
@@ -229,10 +236,10 @@ public final strictfp class GPXReaderTes
             checkPoint(points.get(2), 2, false);
 
             Envelope bbox = (Envelope) f.getPropertyValue("@envelope");
-            assertEquals(bbox.getMinimum(0), 15.0d, DELTA);
-            assertEquals(bbox.getMaximum(0), 35.0d, DELTA);
-            assertEquals(bbox.getMinimum(1), 10.0d, DELTA);
-            assertEquals(bbox.getMaximum(1), 30.0d, DELTA);
+            assertEquals(bbox.getMinimum(0), 15.0d, STRICT);
+            assertEquals(bbox.getMaximum(0), 35.0d, STRICT);
+            assertEquals(bbox.getMinimum(1), 10.0d, STRICT);
+            assertEquals(bbox.getMaximum(1), 30.0d, STRICT);
 
             f = it.next();
             assertEquals(null,                  f.getPropertyValue("name"));
@@ -297,10 +304,10 @@ public final strictfp class GPXReaderTes
             checkPoint(points.get(2), 2, true);
 
             Envelope bbox = (Envelope) f.getPropertyValue("@envelope");
-            assertEquals(bbox.getMinimum(0), 15.0d, DELTA);
-            assertEquals(bbox.getMaximum(0), 35.0d, DELTA);
-            assertEquals(bbox.getMinimum(1), 10.0d, DELTA);
-            assertEquals(bbox.getMaximum(1), 30.0d, DELTA);
+            assertEquals(bbox.getMinimum(0), 15.0d, STRICT);
+            assertEquals(bbox.getMaximum(0), 35.0d, STRICT);
+            assertEquals(bbox.getMinimum(1), 10.0d, STRICT);
+            assertEquals(bbox.getMaximum(1), 30.0d, STRICT);
 
             f = it.next();
             assertEquals(null,                  f.getPropertyValue("name"));
@@ -369,10 +376,10 @@ public final strictfp class GPXReaderTes
             assertEquals(0, points.size());
 
             Envelope bbox = (Envelope) f.getPropertyValue("@envelope");
-            assertEquals(bbox.getMinimum(0), 15.0d, DELTA);
-            assertEquals(bbox.getMaximum(0), 35.0d, DELTA);
-            assertEquals(bbox.getMinimum(1), 10.0d, DELTA);
-            assertEquals(bbox.getMaximum(1), 30.0d, DELTA);
+            assertEquals(bbox.getMinimum(0), 15.0d, STRICT);
+            assertEquals(bbox.getMaximum(0), 35.0d, STRICT);
+            assertEquals(bbox.getMinimum(1), 10.0d, STRICT);
+            assertEquals(bbox.getMaximum(1), 30.0d, STRICT);
 
             f = it.next();
             assertEquals(null,                  f.getPropertyValue("name"));
@@ -443,10 +450,10 @@ public final strictfp class GPXReaderTes
             assertEquals(0, points.size());
 
             Envelope bbox = (Envelope) f.getPropertyValue("@envelope");
-            assertEquals(bbox.getMinimum(0), 15.0d, DELTA);
-            assertEquals(bbox.getMaximum(0), 35.0d, DELTA);
-            assertEquals(bbox.getMinimum(1), 10.0d, DELTA);
-            assertEquals(bbox.getMaximum(1), 30.0d, DELTA);
+            assertEquals(bbox.getMinimum(0), 15.0d, STRICT);
+            assertEquals(bbox.getMaximum(0), 35.0d, STRICT);
+            assertEquals(bbox.getMinimum(1), 10.0d, STRICT);
+            assertEquals(bbox.getMaximum(1), 30.0d, STRICT);
 
             f = it.next();
             assertEquals(null,                  f.getPropertyValue("name"));
@@ -472,8 +479,8 @@ public final strictfp class GPXReaderTes
     private void checkPoint(final Feature f, final int num, final boolean v11) throws Exception {
         if (num == 0) {
             assertEquals(1,                     f.getPropertyValue("@identifier"));
-            assertEquals(15.0,                  ((Point)f.getPropertyValue("@geometry")).getX(), DELTA);
-            assertEquals(10.0,                  ((Point)f.getPropertyValue("@geometry")).getY(), DELTA);
+            assertEquals(15.0,                  ((Point)f.getPropertyValue("@geometry")).getX(), STRICT);
+            assertEquals(10.0,                  ((Point)f.getPropertyValue("@geometry")).getY(), STRICT);
             assertEquals(140.0,                 f.getPropertyValue("ele"));
             assertEquals(Instant.parse("2010-01-10T00:00:00Z"), f.getPropertyValue("time"));
             assertEquals(35.0,                  f.getPropertyValue("magvar"));
@@ -504,15 +511,15 @@ public final strictfp class GPXReaderTes
             }
 
             final Envelope bbox = (Envelope) f.getPropertyValue("@envelope");
-            assertEquals(bbox.getMinimum(0), 15.0d, DELTA);
-            assertEquals(bbox.getMaximum(0), 15.0d, DELTA);
-            assertEquals(bbox.getMinimum(1), 10.0d, DELTA);
-            assertEquals(bbox.getMaximum(1), 10.0d, DELTA);
+            assertEquals(bbox.getMinimum(0), 15.0d, STRICT);
+            assertEquals(bbox.getMaximum(0), 15.0d, STRICT);
+            assertEquals(bbox.getMinimum(1), 10.0d, STRICT);
+            assertEquals(bbox.getMaximum(1), 10.0d, STRICT);
 
         } else if (num == 1) {
             assertEquals(2,                     f.getPropertyValue("@identifier"));
-            assertEquals(25.0,                  ((Point)f.getPropertyValue("@geometry")).getX(), DELTA);
-            assertEquals(20.0,                  ((Point)f.getPropertyValue("@geometry")).getY(), DELTA);
+            assertEquals(25.0,                  ((Point)f.getPropertyValue("@geometry")).getX(), STRICT);
+            assertEquals(20.0,                  ((Point)f.getPropertyValue("@geometry")).getY(), STRICT);
             assertEquals(null,                  f.getPropertyValue("ele"));
             assertEquals(null,                  f.getPropertyValue("time"));
             assertEquals(null,                  f.getPropertyValue("magvar"));
@@ -535,15 +542,15 @@ public final strictfp class GPXReaderTes
             assertEquals(0,links.size());
 
             final Envelope bbox = (Envelope) f.getPropertyValue("@envelope");
-            assertEquals(bbox.getMinimum(0), 25.0d, DELTA);
-            assertEquals(bbox.getMaximum(0), 25.0d, DELTA);
-            assertEquals(bbox.getMinimum(1), 20.0d, DELTA);
-            assertEquals(bbox.getMaximum(1), 20.0d, DELTA);
+            assertEquals(bbox.getMinimum(0), 25.0d, STRICT);
+            assertEquals(bbox.getMaximum(0), 25.0d, STRICT);
+            assertEquals(bbox.getMinimum(1), 20.0d, STRICT);
+            assertEquals(bbox.getMaximum(1), 20.0d, STRICT);
 
         } else if (num == 2) {
             assertEquals(3,                     f.getPropertyValue("@identifier"));
-            assertEquals(35.0,                  ((Point) f.getPropertyValue("@geometry")).getX(), DELTA);
-            assertEquals(30.0,                  ((Point) f.getPropertyValue("@geometry")).getY(), DELTA);
+            assertEquals(35.0,                  ((Point) f.getPropertyValue("@geometry")).getX(), STRICT);
+            assertEquals(30.0,                  ((Point) f.getPropertyValue("@geometry")).getY(), STRICT);
             assertEquals(150.0,                 f.getPropertyValue("ele"));
             assertEquals(Instant.parse("2010-01-30T00:00:00Z"), f.getPropertyValue("time"));
             assertEquals(25.0,                  f.getPropertyValue("magvar"));
@@ -573,10 +580,10 @@ public final strictfp class GPXReaderTes
             }
 
             final Envelope bbox = (Envelope) f.getPropertyValue("@envelope");
-            assertEquals(bbox.getMinimum(0), 35.0d, DELTA);
-            assertEquals(bbox.getMaximum(0), 35.0d, DELTA);
-            assertEquals(bbox.getMinimum(1), 30.0d, DELTA);
-            assertEquals(bbox.getMaximum(1), 30.0d, DELTA);
+            assertEquals(bbox.getMinimum(0), 35.0d, STRICT);
+            assertEquals(bbox.getMaximum(0), 35.0d, STRICT);
+            assertEquals(bbox.getMinimum(1), 30.0d, STRICT);
+            assertEquals(bbox.getMaximum(1), 30.0d, STRICT);
 
         } else {
             fail("unexpected point number :" + num);

Modified: sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXWriterTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXWriterTest.java?rev=1775863&r1=1775862&r2=1775863&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXWriterTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/gpx/GPXWriterTest.java [UTF-8] Fri Dec 23 17:50:12 2016
@@ -31,6 +31,7 @@ import org.apache.sis.storage.DataStoreE
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
+import org.junit.After;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
@@ -52,10 +53,18 @@ import org.opengis.feature.Feature;
  */
 @DependsOn(GPXReaderTest.class)
 public final strictfp class GPXWriterTest extends TestCase {
+    private GPXStore store;
 
-    private static GPXReader reader(final File resource) throws Exception {
+    private GPXReader reader(final File resource) throws Exception {
         StorageConnector storage = new StorageConnector(resource);
-        return new GPXReader(new GPXStore(storage), storage);
+        return new GPXReader(store = new GPXStore(storage));
+    }
+
+    @After
+    public void closeReader() throws DataStoreException {
+        if (store != null) {
+            store.close();
+        }
     }
 
     private static GPXWriter110 writer(final File f) throws DataStoreException, IOException, XMLStreamException {
@@ -68,6 +77,7 @@ public final strictfp class GPXWriterTes
      * @throws Exception
      */
     @Test
+    @org.junit.Ignore("Writer not yet synchronized with changes in reader.")
     public void testWritingMetadata() throws Exception {
         final File f = new File("output.xml");
         f.deleteOnExit();



Mime
View raw message