Author: desruisseaux
Date: Fri Mar 18 16:08:11 2016
New Revision: 1735631

URL: http://svn.apache.org/viewvc?rev=1735631&view=rev
Log:
Allows HyperRectangleReader to use an existing array of primitive type, not 
necessarily data provided by a ReadableByteChannel.

Added:
    
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
   (with props)
    
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
   (with props)
Modified:
    
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
    
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
    
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
    
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java

Modified: 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelData.java
 [UTF-8] Fri Mar 18 16:08:11 2016
@@ -222,7 +222,7 @@ public abstract class ChannelData {
         final int n = (int) (position - bufferOffset);
         final int p = buffer.position() - n;
         final int r = buffer.limit() - n;
-        flushAndSetPosition(n); // Number of bytes to forget.
+        flushAndSetPosition(n);                             // Number of bytes 
to forget.
         buffer.compact().position(p).limit(r);
         /*
          * Discard trailing obsolete marks. Note that obsolete marks between 
valid marks
@@ -242,7 +242,7 @@ public abstract class ChannelData {
     }
 
     /**
-     * Writes (if applicable) the buffer content up to the given position, 
then set the buffer position
+     * Writes (if applicable) the buffer content up to the given position, 
then sets the buffer position
      * to the given value. The {@linkplain ByteBuffer#limit() buffer limit} is 
unchanged, and the buffer
      * offset is incremented by the given value.
      */
@@ -327,6 +327,9 @@ public abstract class ChannelData {
     @Debug
     @Override
     public String toString() {
-        return getClass().getSimpleName() + "[“" + filename + "” at " + 
getStreamPosition() + ']';
+        final StringBuilder b = new 
StringBuilder().append(getClass().getSimpleName()).append("[“").append(filename).append('”');
+        // Even if the buffer should not be null, it is useful to keep the 
toString() method robust.
+        if (buffer != null) b.append(" at ").append(getStreamPosition());
+        return b.append(']').toString();
     }
 }

Modified: 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/ChannelDataInput.java
 [UTF-8] Fri Mar 18 16:08:11 2016
@@ -190,7 +190,7 @@ public class ChannelDataInput extends Ch
     /**
      * Returns the "end of file" error message, for {@link EOFException} 
creations.
      */
-    private String eof() {
+    final String eof() {
         return Errors.format(Errors.Keys.UnexpectedEndOfFile_1, filename);
     }
 
@@ -519,41 +519,20 @@ public class ChannelDataInput extends Ch
      * Helper class for the {@code readFully(…)} methods,
      * in order to avoid duplicating almost identical code many times.
      */
-    abstract class ArrayReader {
+    abstract class ArrayReader implements DataTransfer {
         /**
-         * Returns the size of the Java primitive type which is the element of 
the array.
-         * The size is expressed as the number of bits to shift.
-         */
-        abstract int dataSizeShift();
-
-        /**
-         * Returns the data as a {@code char[]}, {@code short[]}, {@code 
int[]}, {@code long[]},
-         * {@code float[]} or {@code double[]} array. This is either the array 
given in argument
-         * to the subclass constructor, or the array created by {@link 
#createArray(int)}.
-         */
-        abstract Object dataArray();
-
-        /**
-         * Creates a destination array of the given length.
-         */
-        abstract void createDataArray(int length);
-
-        /**
-         * Sets the destination to the given data array, which may be {@code 
null}.
-         */
-        abstract void setDest(Object array) throws ClassCastException;
-
-        /**
-         * Returns the view created by the last call to {@link #createView()}, 
or {@code null} if none.
+         * For subclass constructors only.
          */
-        abstract Buffer view();
+        ArrayReader() {
+        }
 
         /**
-         * Creates a new buffer of the type required by the array to fill.
-         * This method is guaranteed to be invoked exactly once, after the
-         * {@link ChannelDataInput#buffer} contains enough data.
+         * Returns the enclosing data input.
          */
-        abstract Buffer createView();
+        @Override
+        public final ChannelDataInput input() {
+            return ChannelDataInput.this;
+        }
 
         /**
          * Transfers the data from the buffer created by {@link #createView()} 
to array
@@ -563,19 +542,6 @@ public class ChannelDataInput extends Ch
         abstract void transfer(int offset, int n);
 
         /**
-         * For subclass constructors only.
-         */
-        ArrayReader() {
-        }
-
-        /**
-         * Returns the enclosing data input.
-         */
-        final ChannelDataInput input() {
-            return ChannelDataInput.this;
-        }
-
-        /**
          * Skips the given amount of bytes in the buffer. It is caller 
responsibility to ensure
          * that there is enough bytes remaining in the buffer.
          */
@@ -584,8 +550,16 @@ public class ChannelDataInput extends Ch
         }
 
         /**
-         * Reads {@code length} characters from the stream, and stores them 
into the array
-         * known to subclass, starting at index {@code offset}.
+         * Moves to the given position in the stream.
+         */
+        @Override
+        public final void seek(long n) throws IOException {
+            ChannelDataInput.this.seek(n);
+        }
+
+        /**
+         * Reads {@code length} values from the stream, and stores them into 
the array known to subclass,
+         * starting at index {@code offset}.
          *
          * <p>If a non-null {@code Buffer} is given in argument to this 
method, then it must be a view over
          * the full content of {@link ChannelDataInput#buffer} (i.e. the view 
element at index 0 shall be
@@ -593,10 +567,11 @@ public class ChannelDataInput extends Ch
          *
          * @param  view     Existing buffer to use as a view over {@link 
ChannelDataInput#buffer}, or {@code null}.
          * @param  offset   The starting position within {@code dest} to write.
-         * @param  length   The number of characters to read.
+         * @param  length   The number of values to read.
          * @throws IOException if an error (including EOF) occurred while 
reading the stream.
          */
-        void readFully(Buffer view, int offset, int length) throws IOException 
{
+        @Override
+        public void readFully(Buffer view, int offset, int length) throws 
IOException {
             final int dataSizeShift = dataSizeShift();
             ensureBufferContains(Math.min(length << dataSizeShift, 
buffer.capacity()));
             if (view == null) {
@@ -632,17 +607,16 @@ public class ChannelDataInput extends Ch
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final class BytesReader extends ArrayReader {
-        /** The array where to store the values. */ private byte[] dest;
-        BytesReader(final byte[] dest) {this.dest = dest;}
-
-        @Override int    dataSizeShift()        {return 0;}
-        @Override Object dataArray()            {return dest;}
-        @Override Buffer view()                 {return buffer;}
-        @Override Buffer createView()           {return buffer;}
-        @Override void   createDataArray(int n) {dest = new byte[n];}
-        @Override void   transfer(int p, int n) {buffer.get(dest, p, n);}
-        @Override void   setDest(Object array)  {dest = (byte[]) array;};
-        @Override void   readFully(Buffer view, int offset, int length) throws 
IOException {
+        /** The array where to store the values. */      private byte[] dest;
+        BytesReader(final byte[] dest)                  {this.dest = dest;}
+        @Override public int    dataSizeShift()         {return 0;}
+        @Override public Object dataArray()             {return dest;}
+        @Override public Buffer view()                  {return buffer;}
+        @Override public Buffer createView()            {return buffer;}
+        @Override public void   createDataArray(int n)  {dest = new byte[n];}
+        @Override        void   transfer(int p, int n)  {buffer.get(dest, p, 
n);}
+        @Override public void   setDest(Object array)   {dest = (byte[]) 
array;};
+        @Override public void readFully(Buffer view, int offset, int length) 
throws IOException {
             ChannelDataInput.this.readFully(dest, offset, length);
         }
     };
@@ -652,17 +626,17 @@ public class ChannelDataInput extends Ch
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final class CharsReader extends ArrayReader {
-        /** A view over the enclosing byte buffer. */ private CharBuffer view;
-        /** The array where to store the values.   */ private char[] dest;
-        CharsReader(final char[] dest) {this.dest = dest;}
-
-        @Override int    dataSizeShift()        {return 1;}
-        @Override Object dataArray()            {return dest;}
-        @Override Buffer view()                 {return view;}
-        @Override Buffer createView()           {return view = 
buffer.asCharBuffer();}
-        @Override void   createDataArray(int n) {dest = new char[n];}
-        @Override void   transfer(int p, int n) {view.get(dest, p, n);}
-        @Override void   setDest(Object array)  {dest = (char[]) array;};
+        /** A view over the enclosing byte buffer. */    private CharBuffer 
view;
+        /** The array where to store the values.   */    private char[] dest;
+        CharsReader(final CharBuffer source)            {this.view = source;}
+        CharsReader(final char[] dest)                  {this.dest = dest;}
+        @Override public int    dataSizeShift()         {return 1;}
+        @Override public Object dataArray()             {return dest;}
+        @Override public Buffer view()                  {return view;}
+        @Override public Buffer createView()            {return view = 
buffer.asCharBuffer();}
+        @Override public void   createDataArray(int n)  {dest = new char[n];}
+        @Override        void   transfer(int p, int n)  {view.get(dest, p, n);}
+        @Override public void   setDest(Object array)   {dest = (char[]) 
array;};
     };
 
     /**
@@ -670,17 +644,17 @@ public class ChannelDataInput extends Ch
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final class ShortsReader extends ArrayReader {
-        /** A view over the enclosing byte buffer. */ private ShortBuffer view;
-        /** The array where to store the values.   */ private short[] dest;
-        ShortsReader(final short[] dest) {this.dest = dest;}
-
-        @Override int    dataSizeShift()        {return 1;}
-        @Override Object dataArray()            {return dest;}
-        @Override Buffer view()                 {return view;}
-        @Override Buffer createView()           {return view = 
buffer.asShortBuffer();}
-        @Override void   createDataArray(int n) {dest = new short[n];}
-        @Override void   transfer(int p, int n) {view.get(dest, p, n);}
-        @Override void   setDest(Object array)  {dest = (short[]) array;};
+        /** A view over the enclosing byte buffer. */    private ShortBuffer 
view;
+        /** The array where to store the values.   */    private short[] dest;
+        ShortsReader(final ShortBuffer source)          {this.view = source;}
+        ShortsReader(final short[] dest)                {this.dest = dest;}
+        @Override public int    dataSizeShift()         {return 1;}
+        @Override public Object dataArray()             {return dest;}
+        @Override public Buffer view()                  {return view;}
+        @Override public Buffer createView()            {return view = 
buffer.asShortBuffer();}
+        @Override public void   createDataArray(int n)  {dest = new short[n];}
+        @Override void          transfer(int p, int n)  {view.get(dest, p, n);}
+        @Override public void   setDest(Object array)   {dest = (short[]) 
array;};
     };
 
     /**
@@ -688,17 +662,17 @@ public class ChannelDataInput extends Ch
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final class IntsReader extends ArrayReader {
-        /** A view over the enclosing byte buffer. */ private IntBuffer view;
-        /** The array where to store the values.   */ private int[] dest;
-        IntsReader(final int[] dest) {this.dest = dest;}
-
-        @Override int    dataSizeShift()        {return 2;}
-        @Override Object dataArray()            {return dest;}
-        @Override Buffer view()                 {return view;}
-        @Override Buffer createView()           {return view = 
buffer.asIntBuffer();}
-        @Override void   createDataArray(int n) {dest = new int[n];}
-        @Override void   transfer(int p, int n) {view.get(dest, p, n);}
-        @Override void   setDest(Object array)  {dest = (int[]) array;};
+        /** A view over the enclosing byte buffer. */    private IntBuffer 
view;
+        /** The array where to store the values.   */    private int[] dest;
+        IntsReader(final IntBuffer source)              {this.view = source;}
+        IntsReader(final int[] dest)                    {this.dest = dest;}
+        @Override public int    dataSizeShift()         {return 2;}
+        @Override public Object dataArray()             {return dest;}
+        @Override public Buffer view()                  {return view;}
+        @Override public Buffer createView()            {return view = 
buffer.asIntBuffer();}
+        @Override public void   createDataArray(int n)  {dest = new int[n];}
+        @Override void          transfer(int p, int n)  {view.get(dest, p, n);}
+        @Override public void   setDest(Object array)   {dest = (int[]) 
array;};
     };
 
     /**
@@ -706,17 +680,17 @@ public class ChannelDataInput extends Ch
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final class LongsReader extends ArrayReader {
-        /** A view over the enclosing byte buffer. */ private LongBuffer view;
-        /** The array where to store the values.   */ private long[] dest;
-        LongsReader(final long[] dest) {this.dest = dest;}
-
-        @Override int    dataSizeShift()        {return 3;}
-        @Override Object dataArray()            {return dest;}
-        @Override Buffer view()                 {return view;}
-        @Override Buffer createView()           {return view = 
buffer.asLongBuffer();}
-        @Override void   createDataArray(int n) {dest = new long[n];}
-        @Override void   transfer(int p, int n) {view.get(dest, p, n);}
-        @Override void   setDest(Object array)  {dest = (long[]) array;};
+        /** A view over the enclosing byte buffer. */    private LongBuffer 
view;
+        /** The array where to store the values.   */    private long[] dest;
+        LongsReader(final LongBuffer source)            {this.view = source;}
+        LongsReader(final long[] dest)                  {this.dest = dest;}
+        @Override public int    dataSizeShift()         {return 3;}
+        @Override public Object dataArray()             {return dest;}
+        @Override public Buffer view()                  {return view;}
+        @Override public Buffer createView()            {return view = 
buffer.asLongBuffer();}
+        @Override public void   createDataArray(int n)  {dest = new long[n];}
+        @Override void          transfer(int p, int n)  {view.get(dest, p, n);}
+        @Override public void   setDest(Object array)   {dest = (long[]) 
array;};
     };
 
     /**
@@ -724,17 +698,17 @@ public class ChannelDataInput extends Ch
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final class FloatsReader extends ArrayReader {
-        /** A view over the enclosing byte buffer. */ private FloatBuffer view;
-        /** The array where to store the values.   */ private float[] dest;
-        FloatsReader(final float[] dest) {this.dest = dest;}
-
-        @Override int    dataSizeShift()        {return 2;}
-        @Override Object dataArray()            {return dest;}
-        @Override Buffer view()                 {return view;}
-        @Override Buffer createView()           {return view = 
buffer.asFloatBuffer();}
-        @Override void   createDataArray(int n) {dest = new float[n];}
-        @Override void   transfer(int p, int n) {view.get(dest, p, n);}
-        @Override void   setDest(Object array)  {dest = (float[]) array;};
+        /** A view over the enclosing byte buffer. */    private FloatBuffer 
view;
+        /** The array where to store the values.   */    private float[] dest;
+        FloatsReader(final FloatBuffer source)          {this.view = source;}
+        FloatsReader(final float[] dest)                {this.dest = dest;}
+        @Override public int    dataSizeShift()         {return 2;}
+        @Override public Object dataArray()             {return dest;}
+        @Override public Buffer view()                  {return view;}
+        @Override public Buffer createView()            {return view = 
buffer.asFloatBuffer();}
+        @Override public void   createDataArray(int n)  {dest = new float[n];}
+        @Override void          transfer(int p, int n)  {view.get(dest, p, n);}
+        @Override public void   setDest(Object array)   {dest = (float[]) 
array;};
     };
 
     /**
@@ -742,17 +716,17 @@ public class ChannelDataInput extends Ch
      */
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final class DoublesReader extends ArrayReader {
-        /** A view over the enclosing byte buffer. */ private DoubleBuffer 
view;
-        /** The array where to store the values.   */ private double[] dest;
-        DoublesReader(final double[] dest) {this.dest = dest;}
-
-        @Override int    dataSizeShift()        {return 3;}
-        @Override Object dataArray()            {return dest;}
-        @Override Buffer view()                 {return view;}
-        @Override Buffer createView()           {return view = 
buffer.asDoubleBuffer();}
-        @Override void   createDataArray(int n) {dest = new double[n];}
-        @Override void   transfer(int p, int n) {view.get(dest, p, n);}
-        @Override void   setDest(Object array)  {dest = (double[]) array;};
+        /** A view over the enclosing byte buffer. */    private DoubleBuffer 
view;
+        /** The array where to store the values.   */    private double[] dest;
+        DoublesReader(final DoubleBuffer source)        {this.view = source;}
+        DoublesReader(final double[] dest)              {this.dest = dest;}
+        @Override public int    dataSizeShift()         {return 3;}
+        @Override public Object dataArray()             {return dest;}
+        @Override public Buffer view()                  {return view;}
+        @Override public Buffer createView()            {return view = 
buffer.asDoubleBuffer();}
+        @Override public void   createDataArray(int n)  {dest = new double[n];}
+        @Override void          transfer(int p, int n)  {view.get(dest, p, n);}
+        @Override public void   setDest(Object array)   {dest = (double[]) 
array;};
     };
 
     /**

Added: 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java?rev=1735631&view=auto
==============================================================================
--- 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
 (added)
+++ 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/DataTransfer.java
 [UTF-8] Fri Mar 18 16:08:11 2016
@@ -0,0 +1,95 @@
+/*
+ * 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.storage;
+
+import java.io.IOException;
+import java.nio.Buffer;
+
+
+/**
+ * Transfers data from a buffer to an array specified at construction time.
+ * The kind of buffer and the primitive type in the array depend on the 
implementation.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+interface DataTransfer {
+    /**
+     * Returns the enclosing data input.
+     */
+    ChannelDataInput input();
+
+    /**
+     * Returns the size of the Java primitive type which is the element of the 
array.
+     * The size is expressed as the number of bits to shift.
+     */
+    int dataSizeShift();
+
+    /**
+     * Returns the data as a {@code char[]}, {@code short[]}, {@code int[]}, 
{@code long[]},
+     * {@code float[]} or {@code double[]} array. This is either the array 
given in argument
+     * to the subclass constructor, or the array created by {@link 
#createArray(int)}.
+     */
+    Object dataArray();
+
+    /**
+     * Creates a destination array of the given length.
+     */
+    void createDataArray(int length);
+
+    /**
+     * Sets the destination to the given data array, which may be {@code null}.
+     */
+    void setDest(Object array) throws ClassCastException;
+
+    /**
+     * Returns the view created by the last call to {@link #createView()}, or 
{@code null} if none.
+     */
+    Buffer view();
+
+    /**
+     * Creates a new buffer of the type required by the array to fill.
+     * This method is guaranteed to be invoked exactly once, after the
+     * {@link ChannelDataInput#buffer} contains enough data.
+     */
+    Buffer createView();
+
+    /**
+     * Moves to the given position in the stream.
+     *
+     * @param  position The position where to move.
+     * @throws IOException if the stream can not be moved to the given 
position.
+     */
+    void seek(long position) throws IOException;
+
+    /**
+     * Reads {@code length} values from the stream and stores them into the 
array known to subclass,
+     * starting at index {@code offset}.
+     *
+     * <p>If a non-null {@code Buffer} is given in argument to this method, 
then it must be a view over
+     * the full content of {@link ChannelDataInput#buffer} (i.e. the view 
element at index 0 shall be
+     * defined by the buffer elements starting at index 0).</p>
+     *
+     * @param  view     Existing buffer to use as a view over {@link 
ChannelDataInput#buffer}, or {@code null}.
+     * @param  offset   The starting position within {@code dest} to write.
+     * @param  length   The number of values to read.
+     * @throws IOException if an error (including EOF) occurred while reading 
the stream.
+     */
+    void readFully(Buffer view, int offset, int length) throws IOException;
+}

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

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

Modified: 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/HyperRectangleReader.java
 [UTF-8] Fri Mar 18 16:08:11 2016
@@ -39,7 +39,7 @@ public final class HyperRectangleReader
     /**
      * The channel from which to read the values, together with a buffer for 
transferring data.
      */
-    private final ChannelDataInput.ArrayReader reader;
+    private final DataTransfer reader;
 
     /**
      * The {@link #input} position of the first sample (ignoring sub-area and 
sub-sampling).
@@ -58,13 +58,13 @@ public final class HyperRectangleReader
             throws DataStoreException
     {
         switch (dataType) {
-            case Numbers.BYTE:      reader = input.new BytesReader  (null); 
break;
-            case Numbers.CHARACTER: reader = input.new CharsReader  (null); 
break;
-            case Numbers.SHORT:     reader = input.new ShortsReader (null); 
break;
-            case Numbers.INTEGER:   reader = input.new IntsReader   (null); 
break;
-            case Numbers.LONG:      reader = input.new LongsReader  (null); 
break;
-            case Numbers.FLOAT:     reader = input.new FloatsReader (null); 
break;
-            case Numbers.DOUBLE:    reader = input.new DoublesReader(null); 
break;
+            case Numbers.BYTE:      reader = input.new BytesReader  (          
 null); break;
+            case Numbers.CHARACTER: reader = input.new CharsReader  ((char[])  
 null); break;
+            case Numbers.SHORT:     reader = input.new ShortsReader ((short[]) 
 null); break;
+            case Numbers.INTEGER:   reader = input.new IntsReader   ((int[])   
 null); break;
+            case Numbers.LONG:      reader = input.new LongsReader  ((long[])  
 null); break;
+            case Numbers.FLOAT:     reader = input.new FloatsReader ((float[]) 
 null); break;
+            case Numbers.DOUBLE:    reader = input.new 
DoublesReader((double[]) null); break;
             default: throw new 
DataStoreException(Errors.format(Errors.Keys.UnknownType_1, dataType));
         }
         this.origin = origin;
@@ -80,6 +80,19 @@ public final class HyperRectangleReader
     }
 
     /**
+     * Creates a new reader for the data in an existing buffer.
+     * The data will be read from the current buffer position to the buffer 
limit.
+     *
+     * @param name   The data source name, for information purpose only.
+     * @param data A buffer containing the data to read.
+     * @throws IOException should never happen.
+     */
+    public HyperRectangleReader(final String name, final Buffer data) throws 
IOException {
+        reader = new MemoryDataTransfer(name, data).reader();
+        origin = 0;
+    }
+
+    /**
      * Returns the data input specified at construction time.
      *
      * @return The input channel together with the buffer.
@@ -109,10 +122,9 @@ public final class HyperRectangleReader
         }
         try {
             reader.createDataArray(region.targetLength(region.getDimension()));
-            final ChannelDataInput input = reader.input();
             final Buffer view = reader.view();
 loop:       do {
-                input.seek(streamPosition);
+                reader.seek(streamPosition);
                 assert reader.view() == view;
                 reader.readFully(view, arrayPosition, contiguousDataLength);
                 for (int i=0; i<cursor.length; i++) {

Added: 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java?rev=1735631&view=auto
==============================================================================
--- 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
 (added)
+++ 
sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryDataTransfer.java
 [UTF-8] Fri Mar 18 16:08:11 2016
@@ -0,0 +1,144 @@
+/*
+ * 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.storage;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ShortBuffer;
+import java.nio.channels.ReadableByteChannel;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.Classes;
+
+
+/**
+ * A {@code DataTransfer} with all data in the given buffer, without channel.
+ *
+ * <div class="note"><b>Implementation note:</b>
+ * This class implements also an empty {@link ReadableByteChannel} as safety. 
When using {@link ChannelDataInput}
+ * without channel, only an existing {@code Buffer} pre-filled with the data 
should be used. If we have a bug in
+ * our reading process, the empty channel will cause an {@link 
java.io.EOFException} to be thrown instead of a
+ * {@link NullPointerException}.</div>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+final class MemoryDataTransfer implements DataTransfer, ReadableByteChannel {
+    /**
+     * The actual {@code DataTransfer} implementation.
+     */
+    private final ChannelDataInput.ArrayReader reader;
+
+    /**
+     * Creates a in-memory data input for the given buffer.
+     */
+    MemoryDataTransfer(final String filename, final Buffer data) throws 
IOException {
+        final ChannelDataInput input = new ChannelDataInput(filename, this,
+                (data instanceof   ByteBuffer) ? (ByteBuffer) data : null, 
true);
+             if (data instanceof   ByteBuffer) reader = input.new BytesReader  
(               null);
+        else if (data instanceof  ShortBuffer) reader = input.new ShortsReader 
( (ShortBuffer) data);
+        else if (data instanceof    IntBuffer) reader = input.new IntsReader   
(   (IntBuffer) data);
+        else if (data instanceof   LongBuffer) reader = input.new LongsReader  
(  (LongBuffer) data);
+        else if (data instanceof  FloatBuffer) reader = input.new FloatsReader 
( (FloatBuffer) data);
+        else if (data instanceof DoubleBuffer) reader = input.new 
DoublesReader((DoubleBuffer) data);
+        else if (data instanceof   CharBuffer) reader = input.new CharsReader  
(  (CharBuffer) data);
+        else throw new 
IllegalArgumentException(Errors.format(Errors.Keys.UnknownType_1, 
Classes.getClass(data)));
+    }
+
+    /**
+     * Returns the most efficient {@code DataTransfer} instance to use.
+     */
+    DataTransfer reader() {
+        return (view() instanceof ByteBuffer) ? reader : this;
+    }
+
+    /**
+     * Moves to the given byte position in the buffer.
+     */
+    @Override
+    public void seek(long position) throws IOException {
+        assert input().bufferOffset == 0;
+        if (position < 0) {
+            throw new 
IOException(Errors.format(Errors.Keys.NegativeArgument_2, "position", 
position));
+        }
+        final int dataSizeShift = dataSizeShift();
+        if ((position & ((1 << dataSizeShift) - 1)) != 0) {
+            throw new 
IOException(Errors.format(Errors.Keys.IllegalArgumentValue_2, "position", 
position));
+        }
+        position >>>= dataSizeShift;
+        final Buffer data = view();
+        if (position > data.limit()) {
+            throw new EOFException(input().eof());
+        }
+        data.position((int) position);
+    }
+
+    /**
+     * Delegates to the actual implementation.
+     */
+    @Override public ChannelDataInput input()                     {return 
reader.input();}
+    @Override public int              dataSizeShift()             {return 
reader.dataSizeShift();}
+    @Override public Object           dataArray()                 {return 
reader.dataArray();}
+    @Override public Buffer           view()                      {return 
reader.view();}
+    @Override public Buffer           createView()                {return 
reader.createView();}
+    @Override public void             createDataArray(int length) 
{reader.createDataArray(length);}
+    @Override public void             setDest(Object array)       
{reader.setDest(array);}
+
+    /**
+     * Reads {@code length} values from the buffer and stores them into the 
array known to subclass,
+     * starting at index {@code offset}.
+     *
+     * @param  view     Ignored.
+     * @param  offset   The starting position within {@code dest} to write.
+     * @param  length   The number of values to read.
+     */
+    @Override
+    public void readFully(final Buffer view, final int offset, final int 
length) {
+        reader.transfer(offset, length);
+    }
+
+    /**
+     * Returns -1 since an empty channel has reached the end-of-stream.
+     */
+    @Override
+    public int read(final ByteBuffer dst) {
+        return -1;
+    }
+
+    /**
+     * The channel is always open.
+     */
+    @Override
+    public boolean isOpen() {
+        return true;
+    }
+
+    /**
+     * Does nothing - keep the channel open.
+     */
+    @Override
+    public void close() throws IOException {
+    }
+}

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

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

Modified: 
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java?rev=1735631&r1=1735630&r2=1735631&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/HyperRectangleReaderTest.java
 [UTF-8] Fri Mar 18 16:08:11 2016
@@ -22,6 +22,8 @@ import java.nio.ByteOrder;
 import java.nio.ByteBuffer;
 import java.nio.ShortBuffer;
 import java.io.IOException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.SeekableByteChannel;
 import org.apache.sis.util.Numbers;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.test.DependsOnMethod;
@@ -83,8 +85,10 @@ public final strictfp class HyperRectang
      * Sample values are index values encoded in base 10. For example the 
value at index (4,1,2,3) will be 4123.
      *
      * @param random The random number generator to use for initializing the 
test.
+     * @param useChannel {@code true} for fetching the data from channel to a 
small buffer,
+     *        or {@code false} if the data are expected to be fully contained 
in the buffer.
      */
-    private void initialize(final Random random) throws IOException, 
DataStoreException {
+    private void initialize(final Random random, final boolean useChannel) 
throws IOException, DataStoreException {
         /*
          * Compute a random hyper-rectangle size, sub-region and sub-sampling. 
Each dimension will have a
          * size between 1 to 10, so we will be able to use decimal digits from 
0 to 9 in the sample values.
@@ -118,7 +122,7 @@ public final strictfp class HyperRectang
          * Fill the array with short values using the encoding describes in 
javadoc.
          * Then wrap the array in a pseudo-channel so we can create the reader 
to test.
          */
-        ShortBuffer view = ByteBuffer.wrap(array, origin, 
length*Short.BYTES).order(ByteOrder.nativeOrder()).asShortBuffer();
+        final ShortBuffer view = ByteBuffer.wrap(array, origin, 
length*Short.BYTES).order(ByteOrder.nativeOrder()).asShortBuffer();
         for (int i3=0; i3<size[3]; i3++) {
             for (int i2=0; i2<size[2]; i2++) {
                 for (int i1=0; i1<size[1]; i1++) {
@@ -129,10 +133,15 @@ public final strictfp class HyperRectang
             }
         }
         assertEquals(length, view.position());
-        final ByteArrayChannel channel = new ByteArrayChannel(array, true);
-        final ByteBuffer       buffer  = 
ByteBuffer.allocate(random.nextInt(20) + 20).order(ByteOrder.nativeOrder());
-        final ChannelDataInput input   = new 
ChannelDataInput("HyperRectangle", channel, buffer, false);
-        reader = new HyperRectangleReader(Numbers.SHORT, input, origin);
+        if (useChannel) {
+            final ByteArrayChannel channel = new ByteArrayChannel(array, true);
+            final ByteBuffer       buffer  = 
ByteBuffer.allocate(random.nextInt(20) + 20).order(ByteOrder.nativeOrder());
+            final ChannelDataInput input   = new 
ChannelDataInput("HyperRectangle in channel", channel, buffer, false);
+            reader = new HyperRectangleReader(Numbers.SHORT, input, origin);
+        } else {
+            view.clear();
+            reader = new HyperRectangleReader("HyperRectangle in buffer", 
view);
+        }
     }
 
     /**
@@ -159,6 +168,21 @@ public final strictfp class HyperRectang
     }
 
     /**
+     * Asserts that the reader used a channel and has read at least some bytes.
+     *
+     * @param expected {@code true} if the reader should have used a channel,
+     *        or {@code false} if it should have used in-memory data instead.
+     */
+    private void assertUsedChannel(final boolean expected) throws IOException {
+        final ChannelDataInput input = reader.input();
+        final ReadableByteChannel channel = input.channel;
+        assertEquals("(channel instanceof InMemoryInput)", !expected, channel 
instanceof MemoryDataTransfer);
+        if (expected) {
+            assertTrue(((SeekableByteChannel) channel).position() > 
input.channelOffset);
+        }
+    }
+
+    /**
      * Tests reading a random part of the hyper-cube without sub-sampling.
      *
      * @throws IOException should never happen.
@@ -166,9 +190,10 @@ public final strictfp class HyperRectang
      */
     @Test
     public void testSubRegion() throws IOException, DataStoreException {
-        initialize(TestUtilities.createRandomNumberGenerator());
+        initialize(TestUtilities.createRandomNumberGenerator(), true);
         Arrays.fill(subsampling, 0, subsampling.length, 1);
         verifyRegionRead();
+        assertUsedChannel(true);
     }
 
     /**
@@ -179,10 +204,11 @@ public final strictfp class HyperRectang
      */
     @Test
     public void testSubSampling() throws IOException, DataStoreException {
-        initialize(TestUtilities.createRandomNumberGenerator());
+        initialize(TestUtilities.createRandomNumberGenerator(), true);
         System.arraycopy(size, 0, upper, 0, size.length);
         Arrays.fill(lower, 0, lower.length, 0);
         verifyRegionRead();
+        assertUsedChannel(true);
     }
 
     /**
@@ -194,7 +220,22 @@ public final strictfp class HyperRectang
     @Test
     @DependsOnMethod({"testSubRegion", "testSubSampling"})
     public void testRandom() throws IOException, DataStoreException {
-        initialize(TestUtilities.createRandomNumberGenerator());
+        initialize(TestUtilities.createRandomNumberGenerator(), true);
+        verifyRegionRead();
+        assertUsedChannel(true);
+    }
+
+    /**
+     * Tests reading data in an existing buffer, without channel.
+     *
+     * @throws IOException should never happen.
+     * @throws DataStoreException should never happen.
+     */
+    @Test
+    @DependsOnMethod("testRandom")
+    public void testReadFromBuffer() throws IOException, DataStoreException {
+        initialize(TestUtilities.createRandomNumberGenerator(4), false);
         verifyRegionRead();
+        assertUsedChannel(false);
     }
 }



Reply via email to