src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java
branchJDK-8188051-branch
changeset 56997 c9cbac2979fb
parent 56824 62e92191354d
--- a/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java	Thu Jul 12 15:23:13 2018 -0400
+++ b/src/jdk.incubator.adba/share/classes/jdk/incubator/sql2/Result.java	Sat Oct 20 08:17:38 2018 -0400
@@ -37,7 +37,7 @@
 public interface Result {
 
   /**
-   * A {@link Result} that is just a number of rows modified, a {@link Long}.
+   * A {@code Result} that is just a number of rows modified, a {@link Long}.
    *
    * Note: It is certainly true that this is not needed; {@link Long} could be
    * used instead. Seems like there might be a documentational advantage to
@@ -56,10 +56,21 @@
   /**
    * A mutable handle to one value of an ordered sequence of columns of a row or
    * of out parameters. Columns have a 1-based index and optionally an
-   * identifier. Identifiers are not guaranteed to be unique. Only {@code clone}
-   * and {@code slice} create new instances. All other methods return this
-   * instance (modifying it if necessary) including {@code forEach},
-   * {@code next}, and {@code iterator}.
+   * identifier. Identifiers are not guaranteed to be unique.
+   * <br>
+   * A newly created Column is initially positioned on the first column of 
+   * it's sequence. The position is modified by calls to {@link #at(int)}, 
+   * {@link #at(String)}, {@link #next()}, or {@link #next(int)}. 
+   * The methods {@link #clone()}, {@link #slice(int)}, 
+   * {@link #forEach(Consumer)}, and {@link #iterator()} create new instances. 
+   * All other methods return this instance (modifying it if necessary) 
+   * including {@link #next()}, and {@link #forEachRemaining(Consumer)}.
+   * <br>
+   * In cases where the result of an operation has no columns, an instance of
+   * this class may represent an empty sequence of columns. Instances 
+   * associated to the empty sequence return 0 from calls to {@link #index()} 
+   * and {@link #absoluteIndex()}. It is illegal to modify the position or 
+   * accesses any attribute of a column if the sequence is empty.   
    */
   public interface Column extends Result, Iterable<Column>, Iterator<Column>, Cloneable {
 
@@ -69,6 +80,7 @@
      * @param <T>
      * @param type
      * @return the value of this {@link Column}
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public <T> T get(Class<T> type);
 
@@ -78,6 +90,7 @@
      *
      * @param <T>
      * @return the value of this {@link Column}
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public default <T> T get() {
       return get(javaType());
@@ -87,22 +100,30 @@
      * Return the identifier of this {@link Column}. May be null.
      *
      * @return the identifier of this {@link Column}. May be null
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public String identifier();
 
     /**
-     * Return the 1-based index of this {@link Column}. The returned value is
-     * relative to the slice if this {@link Column} is the result of a call to
-     * {@code slice()}. {@code
-     * col.slice(n).index() == 1}.
-     *
+     * Return the 1-based index of this {@link Column}. If the column 
+     * sequence is empty, the return value is 0.
+     * <br>
+     * The returned value is relative to the slice if this {@link Column} is 
+     * the result of a call to {@link #slice(int)}. 
+     * <br>
+     * {@code col.slice(n).index() == 1}.
+     * <br>
+     * {@code col.slice(n).next().index() == 2}.
+     *  
      * @return the index of this {@link Column}
      */
     public int index();
 
     /**
      * Return the 1-based index of this {@link Column} relative to the original
-     * sequence of values.
+     * sequence of values. If the column sequence is empty, the return value 
+     * is 0.
+     * <br>
      * {@code col.absoluteIndex() == col.slice(n).absoluteIndex()}.
      *
      * @return the absolute 1-based index of this {@link Column}
@@ -113,6 +134,7 @@
      * Return the SQL type of the value of this {@link Column}.
      *
      * @return the SQL type of this value
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public SqlType sqlType();
 
@@ -123,6 +145,7 @@
      * @param <T>
      * @return a {@link Class} that best represents the value of this
      * {@link Column}
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public <T>Class<T> javaType();
 
@@ -132,6 +155,7 @@
      * @return
      * @throws UnsupportedOperationException if the length of the current value
      * is undefined
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public long length();
 
@@ -158,18 +182,20 @@
      * @param id an identifier. Not null
      * @return this {@link Column}
      * @throws NoSuchElementException if id does not identify exactly one value
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public Column at(String id);
 
     /**
      * Modify this {@link Column} to point to the value at {@code index}. The
-     * first value is at index 1. Negative numbers count back from the last
+     * first value is at index 1. Negative numbers count back from the last 
      * value. The last value is at index -1.
      *
      * @param index a new index
      * @return this {@link Column}
-     * @throws NoSuchElementException if {@code index > length} or
-     * {@code index < -length}
+     * @throws NoSuchElementException if {@code index > length}, 
+     * {@code index < -length}, or {@code index == 0}
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public Column at(int index);
 
@@ -177,15 +203,20 @@
      * Modify this {@link Column} to point to the value at the current index +
      * {@code offset}. If {@code offset} is 0 this is a noop. If {@code offset}
      * is negative the new index is less than the current index. If the new
-     * index would be less than 1 or greater than length this {@link Column} is
-     * not modified and {@link IllegalArgumentException} is thrown.
+     * index would be less than 1 or greater than the sequence length this 
+     * {@link Column} is not modified and {@link IllegalArgumentException} is 
+     * thrown.
      *
      * @param offset an increment to the current index
      * @return this {@link Column}
      * @throws NoSuchElementException if the new index would be less than 1 or
-     * greater than {@code length}
+     * greater than the sequence length.
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public default Column next(int offset) {
+      if (index() == 0) {
+        throw new IllegalStateException();
+      }
       int newIndex = index() + offset;
       if (offset > numberOfValuesRemaining() || newIndex < 1) {
         throw new NoSuchElementException();
@@ -199,16 +230,20 @@
      * consists of {@code numValues} number of values. If {@code numValues} is
      * positive the values are the value of this column and its successors. If
      * {@code numValues} is negative the values are the predecessors of this
-     * column not including this {@link Column}. The order of the values of the
-     * new {@link Column} is the same as the order of the values of this
-     * {@link Column}. The returned {@link Column} points to the first value of
-     * the slice. This {@link Column} is not modified.
+     * column not including this {@link Column}.
+     * <br> 
+     * The returned {@link Column} is positioned on the first value of the 
+     * slice.
+     * <br>
+     * The order of the values of the new {@link Column} is the same as the 
+     * order of the values of this {@link Column}. This {@link Column} 
+     * is not modified.
      *
      * @param numValues the number of columns to include in the slice
      * @return a new {@link Column}.
      * @throws NoSuchElementException if the current index plus
-     * {@code numValues} is greater than the number of values of this
-     * {@link Column} or less than 1
+     * {@code numValues} is greater than the sequence length or less than 1
+     * @throws IllegalStateException if the column sequence is empty.
      */
     public Column slice(int numValues);
 
@@ -225,30 +260,66 @@
      *
      * @return this {@link Column}
      * @throws NoSuchElementException if the new index would be greater than
-     * {@code length}
+     * the sequence length.
+     * @throws IllegalStateException if the column sequence is empty.
      */
-    @Override
     public default Column next() {
       return next(1);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public default boolean hasNext() {
       return numberOfValuesRemaining() > 0;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public default void forEach(Consumer<? super Column> action) {
-      do {
-        action.accept(this);
-        if (!hasNext()) break;
-        next();
-      } while (true);
+      if (index() == 0) {
+        return;
+      }
+      action.accept(this.clone());
+      while (hasNext()) {
+        action.accept(next().clone());
+      }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
-    public default Column iterator() {
-      return this.clone();
+    public default Iterator<Column> iterator() {
+      return new Iterator<Column>() {
+        Column next = Column.this.index() == 0 ? null : Column.this.clone();
+  
+        @Override
+        public boolean hasNext() {
+          return next != null;
+        }
+  
+        @Override
+        public Column next() {
+          if (!hasNext()) {
+            throw new NoSuchElementException();
+          }
+          
+          Column prev = next.clone();
+          
+          if (next.hasNext()) {
+            next.next();
+          }
+          else {
+            next = null;
+          }
+          
+          return prev;
+        }
+      };
     }
 
     /**
@@ -264,9 +335,12 @@
      *
      * @return a {@link java.util.Spliterator}
      */
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public default Spliterator<Column> spliterator() {
-      List list = new ArrayList<>(numberOfValuesRemaining());
+      List<Column> list = new ArrayList<>(numberOfValuesRemaining());
       this.clone().forEach(c -> list.add(c.slice(1)));
       return java.util.Spliterators.spliterator(list.toArray(), numberOfValuesRemaining());
     }
@@ -294,7 +368,7 @@
      * @return the count of rows in the row sequence preceeding this
      * {@link RowColumn}
      * @throws IllegalStateException if the call that was passed this
-     * {@link Result} has ended
+     * {@code Result} has ended
      */
     public long rowNumber();