fluo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ktur...@apache.org
Subject [2/3] incubator-fluo git commit: closes #746 Misc Bytes updates
Date Thu, 04 Aug 2016 14:18:45 GMT
closes #746 Misc Bytes updates


Project: http://git-wip-us.apache.org/repos/asf/incubator-fluo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-fluo/commit/aa36c88f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-fluo/tree/aa36c88f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-fluo/diff/aa36c88f

Branch: refs/heads/master
Commit: aa36c88f0d23b1788bc2d637c777d1ca0b62bf00
Parents: 2805e2f
Author: Keith Turner <kturner@apache.org>
Authored: Fri Jul 29 15:30:59 2016 -0400
Committer: Keith Turner <keith@deenlo.com>
Committed: Thu Aug 4 09:56:13 2016 -0400

----------------------------------------------------------------------
 .../fluo/accumulo/data/WriteUtilImpl.java       |  36 ---
 .../fluo/accumulo/util/ByteArrayUtil.java       |  65 +++-
 .../fluo/accumulo/util/NotificationUtil.java    |   4 +-
 .../apache/fluo/accumulo/values/LockValue.java  |   6 +-
 .../java/org/apache/fluo/api/data/Bytes.java    | 307 ++++++++++++-------
 .../org/apache/fluo/api/data/BytesBuilder.java  | 133 --------
 .../apache/fluo/api/data/BytesBuilderTest.java  | 164 ++++++++++
 .../org/apache/fluo/api/data/BytesTest.java     | 163 ++++++++++
 .../org/apache/fluo/api/data/ColumnTest.java    | 122 ++++++++
 .../org/apache/fluo/api/data/RowColumnTest.java |  86 ++++++
 .../fluo/api/data/RowColumnValueTest.java       |  87 ++++++
 .../java/org/apache/fluo/api/data/SpanTest.java | 260 ++++++++++++++++
 .../org/apache/fluo/core/util/ByteUtil.java     |  19 ++
 .../org/apache/fluo/core/util/ColumnUtil.java   |  22 +-
 .../apache/fluo/core/data/BytesBuilderTest.java | 131 --------
 .../org/apache/fluo/core/data/BytesTest.java    |  94 ------
 .../org/apache/fluo/core/data/ColumnTest.java   | 122 --------
 .../apache/fluo/core/data/RowColumnTest.java    |  86 ------
 .../fluo/core/data/RowColumnValueTest.java      |  87 ------
 .../org/apache/fluo/core/data/SpanTest.java     | 260 ----------------
 .../org/apache/fluo/core/util/ByteUtilTest.java |  18 ++
 21 files changed, 1188 insertions(+), 1084 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/accumulo/src/main/java/org/apache/fluo/accumulo/data/WriteUtilImpl.java
----------------------------------------------------------------------
diff --git a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/data/WriteUtilImpl.java b/modules/accumulo/src/main/java/org/apache/fluo/accumulo/data/WriteUtilImpl.java
deleted file mode 100644
index 1d1a482..0000000
--- a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/data/WriteUtilImpl.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.fluo.accumulo.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import org.apache.fluo.api.data.Bytes;
-import org.apache.hadoop.io.WritableUtils;
-
-public class WriteUtilImpl implements Bytes.WriteUtil {
-
-  @Override
-  public void writeVInt(DataOutput stream, int i) throws IOException {
-    WritableUtils.writeVInt(stream, i);
-  }
-
-  @Override
-  public int readVInt(DataInput stream) throws IOException {
-    return WritableUtils.readVInt(stream);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/ByteArrayUtil.java
----------------------------------------------------------------------
diff --git a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/ByteArrayUtil.java b/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/ByteArrayUtil.java
index a59cf88..72c0060 100644
--- a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/ByteArrayUtil.java
+++ b/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/ByteArrayUtil.java
@@ -15,7 +15,19 @@
 
 package org.apache.fluo.accumulo.util;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Bytes.BytesBuilder;
+import org.apache.hadoop.io.WritableUtils;
 
 /**
  * Utilities for manipulating byte arrays
@@ -81,16 +93,51 @@ public class ByteArrayUtil {
   }
 
   /**
-   * Concatenate several byte arrays into one
-   * 
-   * @param byteArrays List of byte arrays
-   * @return concatenated byte array
+   * Concatenates of list of Bytes objects to create a byte array
+   *
+   * @param listOfBytes Bytes objects to concatenate
+   * @return Bytes
    */
-  public static byte[] concat(byte[]... byteArrays) {
-    Bytes[] bs = new Bytes[byteArrays.length];
-    for (int i = 0; i < byteArrays.length; i++) {
-      bs[i] = Bytes.of(byteArrays[i]);
+  public static final byte[] concat(Bytes... listOfBytes) {
+    try {
+      // TODO calculate exact array size needed
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      DataOutputStream dos = new DataOutputStream(baos);
+
+      for (Bytes b : listOfBytes) {
+        WritableUtils.writeVInt(dos, b.length());
+        b.writeTo(dos);
+      }
+
+      dos.close();
+      return baos.toByteArray();
+    } catch (IOException e) {
+      throw new RuntimeException(e);
     }
-    return Bytes.concat(bs).toArray();
   }
+
+  public static final List<Bytes> split(byte[] b) {
+
+    ArrayList<Bytes> ret = new ArrayList<>();
+
+    try (InputStream in = new ByteArrayInputStream(b)) {
+      DataInputStream dis = new DataInputStream(in);
+
+      BytesBuilder builder = Bytes.newBuilder(b.length);
+
+      while (true) {
+        int len = WritableUtils.readVInt(dis);
+        builder.append(dis, len);
+        ret.add(builder.toBytes());
+        builder.setLength(0);
+      }
+    } catch (EOFException ee) {
+      // at end of file
+    } catch (IOException e) {
+      throw new RuntimeException(e);
+    }
+
+    return ret;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/NotificationUtil.java
----------------------------------------------------------------------
diff --git a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/NotificationUtil.java b/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/NotificationUtil.java
index ef100e3..2b4589f 100644
--- a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/NotificationUtil.java
+++ b/modules/accumulo/src/main/java/org/apache/fluo/accumulo/util/NotificationUtil.java
@@ -51,7 +51,7 @@ public class NotificationUtil {
   }
 
   public static byte[] encodeCol(Column c) {
-    return Bytes.concat(c.getFamily(), c.getQualifier()).toArray();
+    return ByteArrayUtil.concat(c.getFamily(), c.getQualifier());
   }
 
   public static Column decodeCol(Key k) {
@@ -59,7 +59,7 @@ public class NotificationUtil {
   }
 
   public static Column decodeCol(byte[] cq) {
-    List<Bytes> ca = Bytes.split(Bytes.of(cq));
+    List<Bytes> ca = ByteArrayUtil.split(cq);
     Column col = new Column(ca.get(0), ca.get(1));
     return col;
   }

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/accumulo/src/main/java/org/apache/fluo/accumulo/values/LockValue.java
----------------------------------------------------------------------
diff --git a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/values/LockValue.java b/modules/accumulo/src/main/java/org/apache/fluo/accumulo/values/LockValue.java
index 0e66b31..3b7c54b 100644
--- a/modules/accumulo/src/main/java/org/apache/fluo/accumulo/values/LockValue.java
+++ b/modules/accumulo/src/main/java/org/apache/fluo/accumulo/values/LockValue.java
@@ -37,7 +37,7 @@ public class LockValue {
   private final Long transactor;
 
   public LockValue(byte[] enc) {
-    List<Bytes> fields = Bytes.split(Bytes.of(enc));
+    List<Bytes> fields = ByteArrayUtil.split(enc);
 
     if (fields.size() != 6) {
       throw new IllegalArgumentException("more fields than expected");
@@ -88,8 +88,8 @@ public class LockValue {
     if (isTrigger) {
       bools[0] |= 0x4;
     }
-    return Bytes.concat(prow, pcol.getFamily(), pcol.getQualifier(), pcol.getVisibility(),
-        Bytes.of(bools), Bytes.of(ByteArrayUtil.encode(transactor))).toArray();
+    return ByteArrayUtil.concat(prow, pcol.getFamily(), pcol.getQualifier(), pcol.getVisibility(),
+        Bytes.of(bools), Bytes.of(ByteArrayUtil.encode(transactor)));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java
----------------------------------------------------------------------
diff --git a/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java b/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java
index 3728243..6c4a310 100644
--- a/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java
+++ b/modules/api/src/main/java/org/apache/fluo/api/data/Bytes.java
@@ -16,60 +16,55 @@
 package org.apache.fluo.api.data;
 
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInput;
 import java.io.DataInputStream;
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.EOFException;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.Serializable;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
 import java.util.Objects;
 
+import com.google.common.base.Preconditions;
+
 /**
- * Represents bytes in Fluo. Similar to an Accumulo ByteSequence. Bytes is immutable after it is
- * created. Bytes.EMPTY is used to represent a Bytes object with no data.
+ * Represents bytes in Fluo. Bytes is an immutable wrapper around a byte array. Bytes always copies
+ * on creation and never lets its internal byte array escape. Its modeled after Java's String which
+ * is an immutable wrapper around a char array. It was created because there is nothing in Java like
+ * it at the moment. Its very nice having this immutable type, it avoids having to do defensive
+ * copies to ensure correctness. Maybe one day Java will have equivalents of String, StringBuilder,
+ * and Charsequence for bytes.
+ * 
+ * <p>
+ * The reason Fluo did not use ByteBuffer is because its not immutable, even a read only ByteBuffer
+ * has a mutable position. This makes ByteBuffer unsuitable for place where an immutable data type
+ * is desirable, like a key for a map.
+ * 
+ * <p>
+ * Bytes.EMPTY is used to represent a Bytes object with no data.
  *
  * @since 1.0.0
  */
 public final class Bytes implements Comparable<Bytes>, Serializable {
 
   private static final long serialVersionUID = 1L;
-  private static final String WRITE_UTIL_CLASS = "org.apache.fluo.accumulo.data.WriteUtilImpl";
 
   private final byte[] data;
   private final int offset;
   private final int length;
 
-  /**
-   * @since 1.0.0
-   */
-  public interface WriteUtil {
-    void writeVInt(DataOutput stream, int i) throws IOException;
-
-    int readVInt(DataInput stream) throws IOException;
-  }
-
-  private static WriteUtil writeUtil;
-
-  static {
-    try {
-      writeUtil =
-          (WriteUtil) Class.forName(WRITE_UTIL_CLASS).getDeclaredConstructor().newInstance();
-    } catch (Exception e) {
-      throw new IllegalStateException(e);
-    }
-  }
-
   public static final Bytes EMPTY = new Bytes(new byte[0]);
 
   private Integer hashCode = null;
 
+  public Bytes() {
+    data = EMPTY.data;
+    offset = 0;
+    length = 0;
+  }
+
   private Bytes(byte[] data) {
     this.data = data;
     this.offset = 0;
@@ -121,7 +116,7 @@ public final class Bytes implements Comparable<Bytes>, Serializable {
    */
   public Bytes subSequence(int start, int end) {
     if (start > end || start < 0 || end > length) {
-      throw new IllegalArgumentException("Bad start and/end start = " + start + " end=" + end
+      throw new IndexOutOfBoundsException("Bad start and/end start = " + start + " end=" + end
           + " offset=" + offset + " length=" + length);
     }
     return new Bytes(data, offset + start, end - start);
@@ -145,14 +140,38 @@ public final class Bytes implements Comparable<Bytes>, Serializable {
   }
 
   /**
-   * Compares this to the given bytes, byte by byte, returning a negative, zero, or positive result
+   * @return A read only byte buffer thats backed by the internal byte array.
+   */
+  public ByteBuffer toByteBuffer() {
+    return ByteBuffer.wrap(data, offset, length).asReadOnlyBuffer();
+  }
+
+  /**
+   * @return An input stream thats backed by the internal byte array
+   */
+  public InputStream toInputStream() {
+    return new ByteArrayInputStream(data, offset, length);
+  }
+
+  public void writeTo(OutputStream out) throws IOException {
+    // since Bytes is immutable, its important the we do not let the internal byte array escape
+    if (length <= 32) {
+      int end = offset + length;
+      for (int i = offset; i < end; i++) {
+        out.write(data[i]);
+      }
+    } else {
+      out.write(toArray());
+    }
+  }
+
+  /**
+   * Compares this to the passed bytes, byte by byte, returning a negative, zero, or positive result
    * if the first sequence is less than, equal to, or greater than the second. The comparison is
    * performed starting with the first byte of each sequence, and proceeds until a pair of bytes
    * differs, or one sequence runs out of byte (is shorter). A shorter sequence is considered less
    * than a longer one.
    *
-   * @param b1 first byte sequence to compare
-   * @param b2 second byte sequence to compare
    * @return comparison result
    */
   @Override
@@ -234,16 +253,26 @@ public final class Bytes implements Comparable<Bytes>, Serializable {
   }
 
   /**
-   * Creates a Bytes object by copying the data of the given ByteBuffer
+   * Creates a Bytes object by copying the data of the given ByteBuffer.
+   * 
+   * @param bb Data will be read from this ByteBuffer in such a way that its position is not
+   *        changed.
    */
   public static final Bytes of(ByteBuffer bb) {
     Objects.requireNonNull(bb);
     if (bb.remaining() == 0) {
       return EMPTY;
     }
-    byte[] data = new byte[bb.remaining()];
-    // duplicate so that it does not change position
-    bb.duplicate().get(data);
+    byte[] data;
+    if (bb.hasArray()) {
+      data =
+          Arrays.copyOfRange(bb.array(), bb.position() + bb.arrayOffset(),
+              bb.limit() + bb.arrayOffset());
+    } else {
+      data = new byte[bb.remaining()];
+      // duplicate so that it does not change position
+      bb.duplicate().get(data);
+    }
     return new Bytes(data);
   }
 
@@ -273,29 +302,139 @@ public final class Bytes implements Comparable<Bytes>, Serializable {
   }
 
   /**
-   * Writes Bytes to DataOutput
+   * This class provides an easy, efficient, reusable mechanism for building immutable Bytes
+   * objects.
    *
-   * @param out DataOutput
-   * @param b Bytes
+   * @since 1.0.0
    */
-  public static final void write(DataOutput out, Bytes b) throws IOException {
-    writeUtil.writeVInt(out, b.length());
-    for (int i = 0; i < b.length(); i++) {
-      out.write(b.byteAt(i) & 0xff);
+  public static class BytesBuilder {
+
+    private byte[] ba;
+    private int len;
+
+    BytesBuilder(int initialCapacity) {
+      ba = new byte[initialCapacity];
+      len = 0;
     }
-  }
 
-  /**
-   * Wraps data input as Bytes
-   *
-   * @param in DataInput
-   * @return Bytes
-   */
-  public static final Bytes read(DataInput in) throws IOException {
-    int len = writeUtil.readVInt(in);
-    byte[] b = new byte[len];
-    in.readFully(b);
-    return of(b);
+    BytesBuilder() {
+      this(32);
+    }
+
+    private void ensureCapacity(int min) {
+      if (ba.length < min) {
+        int newLen = ba.length * 2;
+        if (newLen < min) {
+          newLen = min;
+        }
+
+        ba = Arrays.copyOf(ba, newLen);
+      }
+    }
+
+    /**
+     * Converts string to bytes using UTF-8 encoding and appends bytes.
+     *
+     * @return self
+     */
+    public BytesBuilder append(String s) {
+      return append(s.getBytes(StandardCharsets.UTF_8));
+    }
+
+    public BytesBuilder append(Bytes b) {
+      ensureCapacity(len + b.length());
+      System.arraycopy(b.data, b.offset, ba, len, b.length);
+      len += b.length();
+      return this;
+    }
+
+    public BytesBuilder append(byte[] bytes) {
+      ensureCapacity(len + bytes.length);
+      System.arraycopy(bytes, 0, ba, len, bytes.length);
+      len += bytes.length;
+      return this;
+    }
+
+    /**
+     * Append a single byte.
+     *
+     * @param b take the lower 8 bits and appends it.
+     * @return self
+     */
+    public BytesBuilder append(int b) {
+      ensureCapacity(len + 1);
+      ba[len] = (byte) b;
+      len += 1;
+      return this;
+    }
+
+    /**
+     * Append a section of bytes from array
+     * 
+     * @param bytes - bytes to be appended
+     * @param offset - start of bytes to be appended
+     * @param length - how many bytes from 'offset' to be appended
+     * @return self
+     */
+    public BytesBuilder append(byte[] bytes, int offset, int length) {
+      ensureCapacity(len + length);
+      System.arraycopy(bytes, offset, ba, len, length);
+      len += length;
+      return this;
+    }
+
+    /**
+     * Append a sequence of bytes from an InputStream
+     * 
+     * @param in data source to append from
+     * @param length number of bytes to read from data source
+     * @return self
+     */
+    public BytesBuilder append(InputStream in, int length) throws IOException {
+      ensureCapacity(len + length);
+      new DataInputStream(in).readFully(ba, len, length);
+      len += length;
+      return this;
+    }
+
+    /**
+     * Append data from a ByteBuffer
+     * 
+     * @param bb data is read from the ByteBuffer in such a way that its position is not changed.
+     * @return self
+     */
+    public BytesBuilder append(ByteBuffer bb) {
+      int length = bb.remaining();
+      ensureCapacity(len + length);
+      bb.duplicate().get(ba, len, length);
+      len += length;
+      return this;
+    }
+
+    /**
+     * Sets the point at which appending will start. This method can shrink or grow the ByteBuilder
+     * from its current state. If it grows it will zero pad.
+     */
+    public void setLength(int newLen) {
+      Preconditions.checkArgument(newLen >= 0, "Negative length passed : " + newLen);
+      if (newLen > ba.length) {
+        ba = Arrays.copyOf(ba, newLen);
+      }
+
+      if (newLen > len) {
+        Arrays.fill(ba, len, newLen, (byte) 0);
+      }
+
+      len = newLen;
+    }
+
+    public int getLength() {
+      return len;
+    }
+
+    public Bytes toBytes() {
+      return Bytes.of(ba, 0, len);
+    }
   }
 
   /**
@@ -311,58 +450,4 @@ public final class Bytes implements Comparable<Bytes>, Serializable {
   public static BytesBuilder newBuilder(int initialCapacity) {
     return new BytesBuilder(initialCapacity);
   }
-
-  /**
-   * Concatenates of list of Bytes objects to create a byte array
-   *
-   * @param listOfBytes Bytes objects to concatenate
-   * @return Bytes
-   */
-  public static final Bytes concat(Bytes... listOfBytes) {
-    try {
-      // TODO calculate exact array size needed
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      DataOutputStream dos = new DataOutputStream(baos);
-
-      for (Bytes b : listOfBytes) {
-        writeUtil.writeVInt(dos, b.length());
-        dos.write(b.toArray());
-      }
-
-      dos.close();
-      return of(baos.toByteArray());
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-  /**
-   * Splits a bytes object into several bytes objects
-   *
-   * @param b Original bytes object
-   * @return List of bytes objects
-   */
-  public static final List<Bytes> split(Bytes b) {
-    ByteArrayInputStream bais;
-    bais = new ByteArrayInputStream(b.toArray());
-
-    DataInputStream dis = new DataInputStream(bais);
-
-    ArrayList<Bytes> ret = new ArrayList<>();
-
-    try {
-      while (true) {
-        int len = writeUtil.readVInt(dis);
-        // TODO could get pointers into original byte seq
-        byte[] field = new byte[len];
-        dis.readFully(field);
-        ret.add(of(field));
-      }
-    } catch (EOFException ee) {
-      // at end of file
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
-    return ret;
-  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/main/java/org/apache/fluo/api/data/BytesBuilder.java
----------------------------------------------------------------------
diff --git a/modules/api/src/main/java/org/apache/fluo/api/data/BytesBuilder.java b/modules/api/src/main/java/org/apache/fluo/api/data/BytesBuilder.java
deleted file mode 100644
index 1ca721c..0000000
--- a/modules/api/src/main/java/org/apache/fluo/api/data/BytesBuilder.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.fluo.api.data;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-
-import com.google.common.base.Preconditions;
-
-/**
- * This class provides an easy, efficient, reusable mechanism for building immutable Bytes objects.
- *
- * @since 1.0.0
- */
-public class BytesBuilder {
-
-  private byte[] ba;
-  private int len;
-
-  BytesBuilder(int initialCapacity) {
-    ba = new byte[initialCapacity];
-    len = 0;
-  }
-
-  BytesBuilder() {
-    this(32);
-  }
-
-  private void ensureCapacity(int min) {
-    if (ba.length < min) {
-      int newLen = ba.length * 2;
-      if (newLen < min) {
-        newLen = min;
-      }
-
-      ba = Arrays.copyOf(ba, newLen);
-    }
-  }
-
-  /**
-   * Converts string to bytes using UTF-8 encoding and appends bytes.
-   *
-   * @return self
-   */
-  public BytesBuilder append(String s) {
-    return append(s.getBytes(StandardCharsets.UTF_8));
-  }
-
-  public BytesBuilder append(Bytes b) {
-    ensureCapacity(len + b.length());
-    for (int i = 0; i < b.length(); i++) {
-      ba[len++] = b.byteAt(i);
-    }
-
-    return this;
-  }
-
-  public BytesBuilder append(byte[] bytes) {
-    ensureCapacity(len + bytes.length);
-    System.arraycopy(bytes, 0, ba, len, bytes.length);
-    len += bytes.length;
-
-    return this;
-  }
-
-  /**
-   * Append a single byte.
-   *
-   * @param b take the lower 8 bits and appends it.
-   * @return self
-   */
-  public BytesBuilder append(int b) {
-    ensureCapacity(len + 1);
-    ba[len] = (byte) b;
-    len += 1;
-    return this;
-  }
-
-  /**
-   * Append a section of bytes from array
-   * 
-   * @param bytes - bytes to be appended
-   * @param offset - start of bytes to be appended
-   * @param length - how many bytes from 'offset' to be appended
-   * @return self
-   */
-  public BytesBuilder append(byte[] bytes, int offset, int length) {
-    ensureCapacity(len + length);
-    System.arraycopy(bytes, offset, ba, len, length);
-    len += length;
-
-    return this;
-  }
-
-
-  /**
-   * Sets the point at which appending will start. This method can shrink or grow the ByteBuilder
-   * from its current state. If it grows it will zero pad.
-   */
-  public void setLength(int newLen) {
-    Preconditions.checkArgument(newLen >= 0, "Negative length passed : " + newLen);
-    if (newLen > ba.length) {
-      ba = Arrays.copyOf(ba, newLen);
-    }
-
-    if (newLen > len) {
-      Arrays.fill(ba, len, newLen, (byte) 0);
-    }
-
-    len = newLen;
-  }
-
-  public int getLength() {
-    return len;
-  }
-
-  public Bytes toBytes() {
-    return Bytes.of(ba, 0, len);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/test/java/org/apache/fluo/api/data/BytesBuilderTest.java
----------------------------------------------------------------------
diff --git a/modules/api/src/test/java/org/apache/fluo/api/data/BytesBuilderTest.java b/modules/api/src/test/java/org/apache/fluo/api/data/BytesBuilderTest.java
new file mode 100644
index 0000000..538eda6
--- /dev/null
+++ b/modules/api/src/test/java/org/apache/fluo/api/data/BytesBuilderTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.fluo.api.data;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Bytes.BytesBuilder;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BytesBuilderTest {
+  @Test
+  public void testBasic() {
+    BytesBuilder bb = Bytes.newBuilder();
+
+    Bytes bytes1 = bb.append(new byte[] {'a', 'b'}).append("cd").append(Bytes.of("ef")).toBytes();
+    Assert.assertEquals(Bytes.of("abcdef"), bytes1);
+
+    bb = Bytes.newBuilder();
+    Bytes bytes2 = bb.append(Bytes.of("ab")).append("cd").append(new byte[] {'e', 'f'}).toBytes();
+    Assert.assertEquals(Bytes.of("abcdef"), bytes2);
+  }
+
+  @Test
+  public void testInputStream() throws IOException {
+
+    ByteArrayInputStream bais =
+        new ByteArrayInputStream("abcdefg".getBytes(StandardCharsets.UTF_8));
+    BytesBuilder bb = Bytes.newBuilder();
+
+    bb.append(bais, 2);
+    bb.append(bais, 3);
+
+    Assert.assertEquals(Bytes.of("abcde"), bb.toBytes());
+  }
+
+  @Test
+  public void testByteBuffer() {
+    ByteBuffer buffer = ByteBuffer.wrap("abcdefg".getBytes(StandardCharsets.UTF_8));
+
+    BytesBuilder bb = Bytes.newBuilder();
+
+    bb.append(buffer);
+    bb.append(buffer);
+
+    Assert.assertEquals(0, buffer.position());
+    Assert.assertEquals(7, buffer.remaining());
+
+    Assert.assertEquals(Bytes.of("abcdefg" + "abcdefg"), bb.toBytes());
+  }
+
+  @Test
+  public void testSetLength() {
+    BytesBuilder bb = Bytes.newBuilder();
+
+    Bytes bytes1 = bb.append(new byte[] {'a', 'b'}).append("cd").append(Bytes.of("ef")).toBytes();
+    Assert.assertEquals(Bytes.of("abcdef"), bytes1);
+
+    bb.setLength(0);
+    Bytes bytes2 = bb.append(Bytes.of("ab")).append("cd").append(new byte[] {'e', 'f'}).toBytes();
+    Assert.assertEquals(Bytes.of("abcdef"), bytes2);
+
+    bb.setLength(10);
+    Bytes bytes3 = bb.toBytes();
+    Assert.assertEquals(Bytes.of(new byte[] {'a', 'b', 'c', 'd', 'e', 'f', 0, 0, 0, 0}), bytes3);
+
+    bb.setLength(100);
+    Bytes bytes4 = bb.toBytes();
+    Assert.assertEquals(Bytes.of("abcdef"), bytes4.subSequence(0, 6));
+    for (int i = 6; i < 100; i++) {
+      Assert.assertEquals(0, bytes4.byteAt(i));
+    }
+  }
+
+  @Test
+  public void testSingleByte() {
+    BytesBuilder bb = Bytes.newBuilder();
+
+    bb.append('c');
+    bb.append(0);
+    bb.append(127);
+    bb.append(128);
+    bb.append(255);
+
+    Bytes bytes = bb.toBytes();
+    Assert.assertEquals(Bytes.of(new byte[] {'c', 0, 127, (byte) 128, (byte) 0xff}), bytes);
+  }
+
+  @Test
+  public void testArraySection() {
+    BytesBuilder bb = Bytes.newBuilder();
+
+    byte[] testing = new byte[] {'a', 'b', 'c', 'd', 'e'};
+
+    bb.append(testing, 0, 3);
+    bb.append(testing, 1, 3);
+    bb.append(testing, 2, 2);
+
+    Bytes bytes = bb.toBytes();
+    Assert.assertEquals(Bytes.of("abcbcdcd"), bytes);
+  }
+
+  @Test
+  public void testIncreaseCapacity() {
+
+    // test appending 3 chars at a time
+    StringBuilder sb = new StringBuilder();
+    BytesBuilder bb = Bytes.newBuilder();
+    BytesBuilder bb2 = Bytes.newBuilder();
+    BytesBuilder bb3 = Bytes.newBuilder();
+    int m = 19;
+    for (int i = 0; i < 100; i++) {
+      // produce a deterministic non repeating pattern
+      String s = (m % 1000) + "";
+      m = Math.abs(m * 19 + i);
+
+      bb.append(s);
+      bb2.append(Bytes.of(s));
+      bb3.append(s);
+      sb.append(s);
+    }
+
+    Assert.assertEquals(Bytes.of(sb.toString()), bb.toBytes());
+    Assert.assertEquals(Bytes.of(sb.toString()), bb2.toBytes());
+    Assert.assertEquals(Bytes.of(sb.toString()), bb3.toBytes());
+
+    // test appending one char at a time
+    sb.setLength(0);
+    bb = Bytes.newBuilder();
+    bb2 = Bytes.newBuilder();
+    bb3.setLength(0);
+    for (int i = 0; i < 500; i++) {
+      // produce a deterministic non repeating pattern
+      String s = (m % 10) + "";
+      m = Math.abs(m * 19 + i);
+      sb.append(s);
+      bb.append(s);
+      bb2.append(Bytes.of(s));
+      bb3.append(s);
+
+    }
+
+    Assert.assertEquals(Bytes.of(sb.toString()), bb.toBytes());
+    Assert.assertEquals(Bytes.of(sb.toString()), bb2.toBytes());
+    Assert.assertEquals(Bytes.of(sb.toString()), bb3.toBytes());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java
----------------------------------------------------------------------
diff --git a/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java b/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java
new file mode 100644
index 0000000..12acdcc
--- /dev/null
+++ b/modules/api/src/test/java/org/apache/fluo/api/data/BytesTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.fluo.api.data;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+import org.apache.fluo.api.data.Bytes;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit test for {@link Bytes}
+ */
+public class BytesTest {
+
+  @Test
+  public void testBytesWrap() {
+
+    String s1 = "test1";
+    Bytes b1 = Bytes.of(s1);
+    Assert.assertArrayEquals(s1.getBytes(), b1.toArray());
+    Assert.assertEquals(s1, b1.toString());
+
+    String s2 = "test2";
+    ByteBuffer bb = ByteBuffer.wrap(s2.getBytes());
+    Bytes b2 = Bytes.of(bb);
+    Assert.assertArrayEquals(s2.getBytes(), b2.toArray());
+    Assert.assertEquals(s2, b2.toString());
+
+    // call again to ensure that position was not changed by previous call
+    b2 = Bytes.of(bb);
+    Assert.assertArrayEquals(s2.getBytes(), b2.toArray());
+    Assert.assertEquals(s2, b2.toString());
+
+    String s3 = "test3";
+    Bytes b3 = Bytes.of(s3.getBytes());
+    Assert.assertArrayEquals(s3.getBytes(), b3.toArray());
+    Assert.assertEquals(s3, b3.toString());
+
+    String s4 = "test4";
+    byte[] d4 = s4.getBytes();
+    Bytes b4 = Bytes.of(d4, 0, d4.length);
+    Assert.assertArrayEquals(s4.getBytes(), b4.toArray());
+    Assert.assertEquals(s4, b4.toString());
+  }
+
+  @Test
+  public void testImmutable() {
+    byte[] d1 = Bytes.of("mydata").toArray();
+
+    Bytes imm = Bytes.of(d1);
+    Assert.assertNotSame(d1, imm.toArray());
+  }
+
+  @Test
+  public void testCompare() {
+    Bytes b1 = Bytes.of("a");
+    Bytes b2 = Bytes.of("b");
+    Bytes b3 = Bytes.of("a");
+    Assert.assertEquals(-1, b1.compareTo(b2));
+    Assert.assertEquals(1, b2.compareTo(b1));
+    Assert.assertEquals(0, b1.compareTo(b3));
+    Assert.assertEquals(1, b1.compareTo(Bytes.EMPTY));
+  }
+
+  @Test
+  public void testToByteBuffer() {
+    Bytes b1 = Bytes.of("fluofluo");
+    ByteBuffer buffer = b1.toByteBuffer();
+    Assert.assertFalse(buffer.hasArray());
+    Assert.assertEquals(buffer.remaining(), 8);
+
+    byte[] copy = new byte[8];
+    buffer.duplicate().get(copy);
+    Assert.assertEquals("fluofluo", new String(copy, StandardCharsets.UTF_8));
+
+    try {
+      buffer.put((byte) 6);
+      Assert.fail();
+    } catch (ReadOnlyBufferException e) {
+    }
+  }
+
+  @Test
+  public void testWrite() throws IOException {
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+    byte[] ba1 = "abc".getBytes(StandardCharsets.UTF_8);
+    Bytes little = Bytes.of(ba1);
+    byte[] ba2 = new byte[1024];
+    Arrays.fill(ba2, (byte) 42);
+    Bytes big = Bytes.of(ba2);
+
+    little.writeTo(out);
+    big.writeTo(out);
+
+    byte[] expected = new byte[ba1.length + ba2.length];
+    System.arraycopy(ba1, 0, expected, 0, ba1.length);
+    System.arraycopy(ba2, 0, expected, ba1.length, ba2.length);
+
+    Assert.assertArrayEquals(expected, out.toByteArray());
+    out.close();
+  }
+
+  @Test
+  public void testBounds() {
+    Bytes bytes = Bytes.of("abcdefg").subSequence(2, 5);
+    Assert.assertEquals("abcdefg".substring(2, 5), bytes.toString());
+    Assert.assertEquals('c', bytes.byteAt(0));
+    Assert.assertEquals('d', bytes.byteAt(1));
+    Assert.assertEquals('e', bytes.byteAt(2));
+
+    Assert.assertEquals("de", bytes.subSequence(1, 3).toString());
+
+    try {
+      bytes.byteAt(-1);
+      Assert.fail();
+    } catch (IndexOutOfBoundsException e) {
+    }
+
+    try {
+      bytes.byteAt(3);
+      Assert.fail();
+    } catch (IndexOutOfBoundsException e) {
+    }
+
+    try {
+      bytes.subSequence(-1, 2);
+      Assert.fail();
+    } catch (IndexOutOfBoundsException e) {
+    }
+
+    try {
+      bytes.subSequence(0, 5);
+      Assert.fail();
+    } catch (IndexOutOfBoundsException e) {
+    }
+
+    try {
+      bytes.subSequence(2, 1);
+      Assert.fail();
+    } catch (IndexOutOfBoundsException e) {
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/test/java/org/apache/fluo/api/data/ColumnTest.java
----------------------------------------------------------------------
diff --git a/modules/api/src/test/java/org/apache/fluo/api/data/ColumnTest.java b/modules/api/src/test/java/org/apache/fluo/api/data/ColumnTest.java
new file mode 100644
index 0000000..11e6dd0
--- /dev/null
+++ b/modules/api/src/test/java/org/apache/fluo/api/data/ColumnTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.fluo.api.data;
+
+import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Column;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit test for {@link Column}
+ */
+public class ColumnTest {
+
+  @Test
+  public void testCreation() {
+    Column col = new Column();
+    Assert.assertFalse(col.isFamilySet());
+    Assert.assertFalse(col.isQualifierSet());
+    Assert.assertFalse(col.isVisibilitySet());
+    Assert.assertSame(Bytes.EMPTY, col.getFamily());
+    Assert.assertSame(Bytes.EMPTY, col.getQualifier());
+    Assert.assertSame(Bytes.EMPTY, col.getVisibility());
+
+    col = Column.EMPTY;
+    Assert.assertFalse(col.isFamilySet());
+    Assert.assertFalse(col.isQualifierSet());
+    Assert.assertFalse(col.isVisibilitySet());
+
+    Assert.assertEquals(new Column(), new Column());
+    Assert.assertEquals(Column.EMPTY, Column.EMPTY);
+    Assert.assertEquals(Column.EMPTY, new Column());
+
+    Assert.assertEquals(new Column("a"), new Column(Bytes.of("a")));
+    Assert.assertEquals(new Column("a"), new Column(Bytes.of("a"), Bytes.EMPTY, Bytes.EMPTY));
+    Assert.assertEquals(new Column("a").hashCode(), new Column(Bytes.of("a"), Bytes.EMPTY,
+        Bytes.EMPTY).hashCode());
+
+    col = new Column("cf1");
+    Assert.assertTrue(col.isFamilySet());
+    Assert.assertFalse(col.isQualifierSet());
+    Assert.assertFalse(col.isVisibilitySet());
+    Assert.assertEquals(Bytes.of("cf1"), col.getFamily());
+    Assert.assertSame(Bytes.EMPTY, col.getQualifier());
+    Assert.assertSame(Bytes.EMPTY, col.getVisibility());
+    Assert.assertEquals(new Column("cf1"), col);
+
+    col = new Column("cf2", "cq2");
+    Assert.assertTrue(col.isFamilySet());
+    Assert.assertTrue(col.isQualifierSet());
+    Assert.assertFalse(col.isVisibilitySet());
+    Assert.assertEquals(Bytes.of("cf2"), col.getFamily());
+    Assert.assertEquals(Bytes.of("cq2"), col.getQualifier());
+    Assert.assertSame(Bytes.EMPTY, col.getVisibility());
+    Assert.assertEquals(new Column("cf2", "cq2"), col);
+
+    col = new Column("cf3", "cq3", "cv3");
+    Assert.assertTrue(col.isFamilySet());
+    Assert.assertTrue(col.isQualifierSet());
+    Assert.assertTrue(col.isVisibilitySet());
+    Assert.assertEquals(Bytes.of("cf3"), col.getFamily());
+    Assert.assertEquals(Bytes.of("cq3"), col.getQualifier());
+    Assert.assertEquals(Bytes.of("cv3"), col.getVisibility());
+    Assert.assertEquals(new Column("cf3", "cq3", "cv3"), col);
+  }
+
+  @Test
+  public void testCompare() {
+    Column c1 = new Column("a", "b");
+    Column c2 = new Column("a", "c");
+    Column c3 = new Column("a", "b", "d");
+    Column c4 = new Column("a");
+    Column c5 = Column.EMPTY;
+    Column c6 = new Column("a", "b");
+
+    Assert.assertEquals(-1, c1.compareTo(c2));
+    Assert.assertEquals(1, c2.compareTo(c1));
+    Assert.assertEquals(0, c1.compareTo(c6));
+    Assert.assertEquals(1, c1.compareTo(c5));
+    Assert.assertEquals(-1, c4.compareTo(c1));
+    Assert.assertEquals(-1, c1.compareTo(c3));
+    Assert.assertEquals(1, c4.compareTo(c5));
+    Assert.assertEquals(-1, c3.compareTo(c2));
+  }
+
+  @Test
+  public void testStringGetters() {
+    Column c0 = Column.EMPTY;
+    Column c1 = new Column("cf");
+    Column c2 = new Column("cf", "cq");
+    Column c3 = new Column("cf", "cq", "cv");
+
+    Assert.assertEquals("", c0.getsFamily());
+    Assert.assertEquals("", c0.getsQualifier());
+    Assert.assertEquals("", c0.getsVisibility());
+
+    Assert.assertEquals("cf", c1.getsFamily());
+    Assert.assertEquals("", c1.getsQualifier());
+    Assert.assertEquals("", c1.getsVisibility());
+
+    Assert.assertEquals("cf", c2.getsFamily());
+    Assert.assertEquals("cq", c2.getsQualifier());
+    Assert.assertEquals("", c2.getsVisibility());
+
+    Assert.assertEquals("cf", c3.getsFamily());
+    Assert.assertEquals("cq", c3.getsQualifier());
+    Assert.assertEquals("cv", c3.getsVisibility());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnTest.java
----------------------------------------------------------------------
diff --git a/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnTest.java b/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnTest.java
new file mode 100644
index 0000000..f5b5fdb
--- /dev/null
+++ b/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.fluo.api.data;
+
+import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Column;
+import org.apache.fluo.api.data.RowColumn;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit test for {@link RowColumn}
+ */
+public class RowColumnTest {
+
+  @Test
+  public void testBasic() {
+
+    RowColumn rc = new RowColumn();
+    Assert.assertEquals(RowColumn.EMPTY, rc);
+    Assert.assertEquals(Bytes.EMPTY, rc.getRow());
+    Assert.assertEquals("", rc.getsRow());
+    Assert.assertEquals(Column.EMPTY, rc.getColumn());
+    Assert.assertEquals("   ", rc.toString());
+    Assert.assertNotEquals(RowColumn.EMPTY, Column.EMPTY);
+
+    rc = new RowColumn(Bytes.of("r1"));
+    Assert.assertEquals(Bytes.of("r1"), rc.getRow());
+    Assert.assertEquals("r1", rc.getsRow());
+    Assert.assertEquals(Column.EMPTY, rc.getColumn());
+    Assert.assertEquals(new RowColumn("r1"), rc);
+    Assert.assertEquals("r1   ", rc.toString());
+
+    rc = new RowColumn("r2", new Column("cf2"));
+    Assert.assertEquals(Bytes.of("r2"), rc.getRow());
+    Assert.assertEquals("r2", rc.getsRow());
+    Assert.assertEquals(new Column("cf2"), rc.getColumn());
+    Assert.assertEquals(new RowColumn(Bytes.of("r2"), new Column("cf2")), rc);
+    Assert.assertEquals("r2 cf2  ", rc.toString());
+    Assert.assertEquals(4007699, rc.hashCode());
+  }
+
+  @Test
+  public void testFollowing() {
+    byte[] fdata = new String("data1").getBytes();
+    fdata[4] = (byte) 0x00;
+    Bytes fb = Bytes.of(fdata);
+
+    Assert.assertEquals(RowColumn.EMPTY, new RowColumn().following());
+    Assert.assertEquals(new RowColumn(fb), new RowColumn("data").following());
+    Assert.assertEquals(new RowColumn("row", new Column(fb)), new RowColumn("row", new Column(
+        "data")).following());
+    Assert.assertEquals(new RowColumn("row", new Column(Bytes.of("cf"), fb)), new RowColumn("row",
+        new Column("cf", "data")).following());
+    Assert.assertEquals(new RowColumn("row", new Column(Bytes.of("cf"), Bytes.of("cq"), fb)),
+        new RowColumn("row", new Column("cf", "cq", "data")).following());
+  }
+
+  @Test
+  public void testCompare() {
+    RowColumn rc1 = new RowColumn("a", new Column("b"));
+    RowColumn rc2 = new RowColumn("b");
+    RowColumn rc3 = new RowColumn("a", new Column("c"));
+    RowColumn rc4 = new RowColumn("a", new Column("c", "d"));
+    Assert.assertEquals(-1, rc1.compareTo(rc2));
+    Assert.assertEquals(1, rc2.compareTo(rc1));
+    Assert.assertEquals(-1, rc1.compareTo(rc3));
+    Assert.assertEquals(-1, rc3.compareTo(rc2));
+    Assert.assertEquals(0, rc3.compareTo(rc3));
+    Assert.assertEquals(1, rc2.compareTo(RowColumn.EMPTY));
+    Assert.assertEquals(-1, rc3.compareTo(rc4));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnValueTest.java
----------------------------------------------------------------------
diff --git a/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnValueTest.java b/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnValueTest.java
new file mode 100644
index 0000000..f67f6c1
--- /dev/null
+++ b/modules/api/src/test/java/org/apache/fluo/api/data/RowColumnValueTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.fluo.api.data;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Column;
+import org.apache.fluo.api.data.RowColumnValue;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class RowColumnValueTest {
+
+  RowColumnValue rcv1 = new RowColumnValue("row1", new Column("fam1", "qual1"), "a");
+  RowColumnValue rcv2 = new RowColumnValue("row1", new Column("fam1", "qual1"), "a");
+  RowColumnValue rcv3 = new RowColumnValue("row2", new Column("fam1", "qual1"), "a");
+  RowColumnValue rcv4 = new RowColumnValue("row1", new Column("fam1", "qual1"), "b");
+  RowColumnValue rcv5 = new RowColumnValue("row1", new Column("fam2", "qual1"), "a");
+  RowColumnValue rcv6 = new RowColumnValue("row2", new Column("fam2", "qual1"), "a");
+  RowColumnValue rcv7 = new RowColumnValue("row2", new Column("fam2", "qual1"), "b");
+
+  @Test
+  public void testEquals() {
+    for (RowColumnValue rcv : Arrays.asList(rcv1, rcv2)) {
+      Assert.assertEquals(rcv1, rcv);
+      Assert.assertEquals(rcv1.hashCode(), rcv.hashCode());
+    }
+
+    for (RowColumnValue rcv : Arrays.asList(rcv3, rcv4, rcv5, rcv6, rcv7)) {
+      Assert.assertNotEquals(rcv1, rcv);
+      Assert.assertNotEquals(rcv1.hashCode(), rcv.hashCode());
+    }
+  }
+
+  @Test
+  public void testGet() {
+    RowColumnValue rcv1 = new RowColumnValue("row1", new Column("fam1", "qual1"), "a");
+
+    Assert.assertEquals(rcv1.getRow(), Bytes.of("row1"));
+    Assert.assertEquals(rcv1.getValue(), Bytes.of("a"));
+    Assert.assertEquals(rcv1.getsValue(), "a");
+    Assert.assertEquals(rcv1.getColumn(), new Column("fam1", "qual1"));
+  }
+
+  @Test
+  public void testCompare() {
+    Assert.assertTrue(rcv1.compareTo(rcv1) == 0);
+    Assert.assertTrue(rcv1.compareTo(rcv2) == 0);
+    Assert.assertTrue(rcv1.compareTo(rcv3) < 0);
+    Assert.assertTrue(rcv3.compareTo(rcv1) > 0);
+    Assert.assertTrue(rcv1.compareTo(rcv3) < 0);
+    Assert.assertTrue(rcv3.compareTo(rcv1) > 0);
+    Assert.assertTrue(rcv1.compareTo(rcv5) < 0);
+    Assert.assertTrue(rcv5.compareTo(rcv1) > 0);
+    Assert.assertTrue(rcv1.compareTo(rcv4) < 0);
+    Assert.assertTrue(rcv4.compareTo(rcv1) > 0);
+
+    List<RowColumnValue> l1 = Arrays.asList(rcv7, rcv6, rcv5, rcv4, rcv3, rcv2, rcv1);
+    Collections.shuffle(l1);
+    Collections.sort(l1);
+
+    List<RowColumnValue> l2 = Arrays.asList(rcv1, rcv2, rcv4, rcv5, rcv3, rcv6, rcv7);
+
+    Assert.assertEquals(l2, l1);
+  }
+
+  @Test
+  public void testToString() {
+    Assert.assertEquals("row1 fam1 qual1  a", rcv1.toString());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/api/src/test/java/org/apache/fluo/api/data/SpanTest.java
----------------------------------------------------------------------
diff --git a/modules/api/src/test/java/org/apache/fluo/api/data/SpanTest.java b/modules/api/src/test/java/org/apache/fluo/api/data/SpanTest.java
new file mode 100644
index 0000000..7a2b7f5
--- /dev/null
+++ b/modules/api/src/test/java/org/apache/fluo/api/data/SpanTest.java
@@ -0,0 +1,260 @@
+/*
+ * 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.fluo.api.data;
+
+import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Column;
+import org.apache.fluo.api.data.RowColumn;
+import org.apache.fluo.api.data.Span;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit test for {@link Span}
+ */
+public class SpanTest {
+
+  String rw1s = "rw1";
+  String cf1s = "cf1";
+  String cq1s = "cq1";
+  String cv1s = "cv1";
+  long ts1 = 51;
+  String rw2s = "rw2";
+  String cf2s = "cf2";
+  String cq2s = "cq2";
+  String cv2s = "cv2";
+  long ts2 = 51;
+  Bytes rw1b = Bytes.of(rw1s);
+  Bytes cf1b = Bytes.of(cf1s);
+  Bytes cq1b = Bytes.of(cq1s);
+  Bytes cv1b = Bytes.of(cv1s);
+  Bytes rw2b = Bytes.of(rw2s);
+  Bytes cf2b = Bytes.of(cf2s);
+  Bytes cq2b = Bytes.of(cq2s);
+  Bytes cv2b = Bytes.of(cv2s);
+
+  @Test
+  public void testRowRange() {
+    // Test with Bytes input
+    Assert.assertEquals(new Span(rw1b, true, rw2b, false), new Span.Builder().startRow(rw1b)
+        .endRow(rw2b).exclusive().build());
+    Assert.assertEquals(new Span(rw1b, false, rw2b, false), new Span.Builder().startRow(rw1b)
+        .exclusive().endRow(rw2b).exclusive().build());
+    Assert.assertEquals(new Span(rw1b, true, rw2b, true),
+        new Span.Builder().startRow(rw1b).endRow(rw2b).build());
+    Assert.assertEquals(new Span(rw1b, false, rw2b, true), new Span.Builder().startRow(rw1b)
+        .exclusive().endRow(rw2b).build());
+
+    // Test with String input
+    Assert.assertEquals(new Span(rw1b, true, rw2b, false), new Span.Builder().startRow(rw1s)
+        .endRow(rw2s).exclusive().build());
+    Assert.assertEquals(new Span(rw1b, false, rw2b, false), new Span.Builder().startRow(rw1s)
+        .exclusive().endRow(rw2s).exclusive().build());
+    Assert.assertEquals(new Span(rw1b, true, rw2b, true),
+        new Span.Builder().startRow(rw1s).endRow(rw2s).build());
+    Assert.assertEquals(new Span(rw1b, false, rw2b, true), new Span.Builder().startRow(rw1s)
+        .exclusive().endRow(rw2s).build());
+  }
+
+  @Test
+  public void testInfiniteRanges() {
+    RowColumn rc1 = new RowColumn(rw1b, new Column(cf1b));
+    RowColumn frc1 = rc1.following();
+    RowColumn rc2 = new RowColumn(rw2b, new Column(cf2b));
+    RowColumn frc2 = rc2.following();
+
+    Assert.assertEquals(new Span(RowColumn.EMPTY, true, frc2, false),
+        new Span.Builder().endRow(rw2b).fam(cf2b).build());
+    Assert.assertEquals(new Span(RowColumn.EMPTY, true, rc2, false), new Span.Builder()
+        .endRow(rw2b).fam(cf2b).exclusive().build());
+    Assert.assertEquals(new Span(rc1, true, RowColumn.EMPTY, true),
+        new Span.Builder().startRow(rw1b).fam(cf1b).build());
+    Assert.assertEquals(new Span(frc1, true, RowColumn.EMPTY, true),
+        new Span.Builder().startRow(rw1b).fam(cf1b).exclusive().build());
+  }
+
+  @Test
+  public void testRowCFRange() {
+    RowColumn rc1 = new RowColumn(rw1b, new Column(cf1b));
+    RowColumn frc1 = rc1.following();
+    RowColumn rc2 = new RowColumn(rw2b, new Column(cf2b));
+    RowColumn frc2 = rc2.following();
+
+    Assert.assertEquals(new Span(rc1, true, frc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).endRow(rw2b).fam(cf2b).build());
+    Assert.assertEquals(new Span(rc1, true, rc2, false), new Span.Builder().startRow(rw1b)
+        .fam(cf1b).endRow(rw2b).fam(cf2b).exclusive().build());
+    Assert.assertEquals(new Span(frc1, true, frc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).exclusive().endRow(rw2b).fam(cf2b).build());
+    Assert.assertEquals(new Span(frc1, true, rc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).exclusive().endRow(rw2b).fam(cf2b).exclusive()
+            .build());
+  }
+
+  @Test
+  public void testRowCFCQRange() {
+    RowColumn rc1 = new RowColumn(rw1b, new Column(cf1b, cq1b));
+    RowColumn frc1 = rc1.following();
+    RowColumn rc2 = new RowColumn(rw2b, new Column(cf2b, cq2b));
+    RowColumn frc2 = rc2.following();
+
+    Assert.assertEquals(new Span(rc1, true, frc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).qual(cq1b).endRow(rw2b).fam(cf2b).qual(cq2b)
+            .build());
+    Assert.assertEquals(new Span(rc1, true, rc2, false), new Span.Builder().startRow(rw1b)
+        .fam(cf1b).qual(cq1b).endRow(rw2b).fam(cf2b).qual(cq2b).exclusive().build());
+    Assert.assertEquals(new Span(frc1, true, frc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).qual(cq1b).exclusive().endRow(rw2b).fam(cf2b)
+            .qual(cq2b).build());
+    Assert.assertEquals(new Span(frc1, true, rc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).qual(cq1b).exclusive().endRow(rw2b).fam(cf2b)
+            .qual(cq2b).exclusive().build());
+  }
+
+  @Test
+  public void testRowCFCQCVRange() {
+    RowColumn rc1 = new RowColumn(rw1b, new Column(cf1b, cq1b, Bytes.of(cv1s)));
+    RowColumn frc1 = rc1.following();
+    RowColumn rc2 = new RowColumn(rw2b, new Column(cf2b, cq2b, Bytes.of(cv2s)));
+    RowColumn frc2 = rc2.following();
+
+    Assert.assertEquals(new Span(rc1, true, frc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).qual(cq1b).vis(cv1b).endRow(rw2b).fam(cf2b)
+            .qual(cq2b).vis(cv2b).build());
+    Assert.assertEquals(new Span(rc1, true, rc2, false), new Span.Builder().startRow(rw1b)
+        .fam(cf1b).qual(cq1b).vis(cv1b).endRow(rw2b).fam(cf2b).qual(cq2b).vis(cv2b).exclusive()
+        .build());
+    Assert.assertEquals(new Span(frc1, true, frc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).qual(cq1b).vis(cv1b).exclusive().endRow(rw2b)
+            .fam(cf2b).qual(cq2b).vis(cv2b).build());
+    Assert.assertEquals(new Span(frc1, true, rc2, false),
+        new Span.Builder().startRow(rw1b).fam(cf1b).qual(cq1b).vis(cv1b).exclusive().endRow(rw2b)
+            .fam(cf2b).qual(cq2b).vis(cv2b).exclusive().build());
+  }
+
+  @Test
+  public void testExactSpan() {
+    Span s = Span.exact(rw1b);
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getStart().getColumn());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(new RowColumn(rw1b).following().getRow(), s.getEnd().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getEnd().getColumn());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.exact(rw1b, Column.EMPTY);
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getStart().getColumn());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(new RowColumn(rw1b).following().getRow(), s.getEnd().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getEnd().getColumn());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.exact(rw1b, new Column(cf1b));
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getStart().getColumn().getFamily());
+    Assert.assertFalse(s.getStart().getColumn().isQualifierSet());
+    Assert.assertFalse(s.getStart().getColumn().isVisibilitySet());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw1b, s.getEnd().getRow());
+    Assert.assertEquals(new RowColumn(rw1b, new Column(cf1b)).following().getColumn().getFamily(),
+        s.getEnd().getColumn().getFamily());
+    Assert.assertFalse(s.getEnd().getColumn().isQualifierSet());
+    Assert.assertFalse(s.getEnd().getColumn().isVisibilitySet());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.exact(rw1b, new Column(cf1b, cq1b));
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getStart().getColumn().getFamily());
+    Assert.assertEquals(cq1b, s.getStart().getColumn().getQualifier());
+    Assert.assertFalse(s.getStart().getColumn().isVisibilitySet());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw1b, s.getEnd().getRow());
+    Assert.assertEquals(cf1b, s.getEnd().getColumn().getFamily());
+    Assert.assertEquals(new RowColumn(rw1b, new Column(cf1b, cq1b)).following().getColumn()
+        .getQualifier(), s.getEnd().getColumn().getQualifier());
+    Assert.assertFalse(s.getEnd().getColumn().isVisibilitySet());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.exact(rw1b, new Column(cf1b, cq1b, cv1b));
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getStart().getColumn().getFamily());
+    Assert.assertEquals(cq1b, s.getStart().getColumn().getQualifier());
+    Assert.assertEquals(cv1b, s.getStart().getColumn().getVisibility());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw1b, s.getEnd().getRow());
+    Assert.assertEquals(cf1b, s.getEnd().getColumn().getFamily());
+    Assert.assertEquals(cq1b, s.getEnd().getColumn().getQualifier());
+    Assert.assertEquals(new RowColumn(rw1b, new Column(cf1b, cq1b, cv1b)).following().getColumn()
+        .getVisibility(), s.getEnd().getColumn().getVisibility());
+    Assert.assertFalse(s.isEndInclusive());
+  }
+
+  @Test
+  public void testPrefixSpan() {
+    Span s = Span.prefix(rw1b);
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getStart().getColumn());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw2b, s.getEnd().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getEnd().getColumn());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.prefix(rw1b, new Column());
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getStart().getColumn());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw2b, s.getEnd().getRow());
+    Assert.assertEquals(Column.EMPTY, s.getEnd().getColumn());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.prefix(rw1b, new Column(cf1b));
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getStart().getColumn().getFamily());
+    Assert.assertFalse(s.getStart().getColumn().isQualifierSet());
+    Assert.assertFalse(s.getStart().getColumn().isVisibilitySet());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf2b, s.getEnd().getColumn().getFamily());
+    Assert.assertFalse(s.getEnd().getColumn().isQualifierSet());
+    Assert.assertFalse(s.getEnd().getColumn().isVisibilitySet());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.prefix(rw1b, new Column(cf1b, cq1b));
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getStart().getColumn().getFamily());
+    Assert.assertEquals(cq1b, s.getStart().getColumn().getQualifier());
+    Assert.assertFalse(s.getStart().getColumn().isVisibilitySet());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getEnd().getColumn().getFamily());
+    Assert.assertEquals(cq2b, s.getEnd().getColumn().getQualifier());
+    Assert.assertFalse(s.getEnd().getColumn().isVisibilitySet());
+    Assert.assertFalse(s.isEndInclusive());
+
+    s = Span.prefix(rw1b, new Column(cf1b, cq1b, cv1b));
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getStart().getColumn().getFamily());
+    Assert.assertEquals(cq1b, s.getStart().getColumn().getQualifier());
+    Assert.assertEquals(cv1b, s.getStart().getColumn().getVisibility());
+    Assert.assertTrue(s.isStartInclusive());
+    Assert.assertEquals(rw1b, s.getStart().getRow());
+    Assert.assertEquals(cf1b, s.getEnd().getColumn().getFamily());
+    Assert.assertEquals(cq1b, s.getEnd().getColumn().getQualifier());
+    Assert.assertEquals(cv2b, s.getEnd().getColumn().getVisibility());
+    Assert.assertFalse(s.isEndInclusive());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/core/src/main/java/org/apache/fluo/core/util/ByteUtil.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/fluo/core/util/ByteUtil.java b/modules/core/src/main/java/org/apache/fluo/core/util/ByteUtil.java
index d1dcb2b..3fcb2c9 100644
--- a/modules/core/src/main/java/org/apache/fluo/core/util/ByteUtil.java
+++ b/modules/core/src/main/java/org/apache/fluo/core/util/ByteUtil.java
@@ -15,10 +15,16 @@
 
 package org.apache.fluo.core.util;
 
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
 import org.apache.accumulo.core.data.ArrayByteSequence;
 import org.apache.accumulo.core.data.ByteSequence;
 import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Bytes.BytesBuilder;
 import org.apache.hadoop.io.Text;
+import org.apache.hadoop.io.WritableUtils;
 
 /**
  * Utilities for modifying byte arrays and converting Bytes objects to external formats
@@ -73,4 +79,17 @@ public class ByteUtil {
     }
     return bytes;
   }
+
+  public static void write(DataOutputStream out, Bytes b) throws IOException {
+    WritableUtils.writeVInt(out, b.length());
+    b.writeTo(out);
+  }
+
+  public static Bytes read(BytesBuilder bb, DataInputStream in) throws IOException {
+    bb.setLength(0);
+    int len = WritableUtils.readVInt(in);
+    bb.append(in, len);
+    return bb.toBytes();
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/core/src/main/java/org/apache/fluo/core/util/ColumnUtil.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/fluo/core/util/ColumnUtil.java b/modules/core/src/main/java/org/apache/fluo/core/util/ColumnUtil.java
index 752d4e8..9ffc94a 100644
--- a/modules/core/src/main/java/org/apache/fluo/core/util/ColumnUtil.java
+++ b/modules/core/src/main/java/org/apache/fluo/core/util/ColumnUtil.java
@@ -15,8 +15,8 @@
 
 package org.apache.fluo.core.util;
 
-import java.io.DataInput;
-import java.io.DataOutput;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.Iterator;
 import java.util.Map.Entry;
@@ -33,6 +33,7 @@ import org.apache.fluo.accumulo.util.ColumnConstants;
 import org.apache.fluo.accumulo.values.DelLockValue;
 import org.apache.fluo.accumulo.values.WriteValue;
 import org.apache.fluo.api.data.Bytes;
+import org.apache.fluo.api.data.Bytes.BytesBuilder;
 import org.apache.fluo.api.data.Column;
 import org.apache.fluo.api.data.Span;
 import org.apache.fluo.core.impl.Environment;
@@ -101,16 +102,17 @@ public class ColumnUtil {
     return null;
   }
 
-  public static void writeColumn(Column col, DataOutput out) throws IOException {
-    Bytes.write(out, col.getFamily());
-    Bytes.write(out, col.getQualifier());
-    Bytes.write(out, col.getVisibility());
+  public static void writeColumn(Column col, DataOutputStream out) throws IOException {
+    ByteUtil.write(out, col.getFamily());
+    ByteUtil.write(out, col.getQualifier());
+    ByteUtil.write(out, col.getVisibility());
   }
 
-  public static Column readColumn(DataInput in) throws IOException {
-    Bytes family = Bytes.read(in);
-    Bytes qualifier = Bytes.read(in);
-    Bytes visibility = Bytes.read(in);
+  public static Column readColumn(DataInputStream in) throws IOException {
+    BytesBuilder bb = Bytes.newBuilder();
+    Bytes family = ByteUtil.read(bb, in);
+    Bytes qualifier = ByteUtil.read(bb, in);
+    Bytes visibility = ByteUtil.read(bb, in);
     return new Column(family, qualifier, visibility);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/core/src/test/java/org/apache/fluo/core/data/BytesBuilderTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/fluo/core/data/BytesBuilderTest.java b/modules/core/src/test/java/org/apache/fluo/core/data/BytesBuilderTest.java
deleted file mode 100644
index 37c011f..0000000
--- a/modules/core/src/test/java/org/apache/fluo/core/data/BytesBuilderTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.fluo.core.data;
-
-import org.apache.fluo.api.data.Bytes;
-import org.apache.fluo.api.data.BytesBuilder;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class BytesBuilderTest {
-  @Test
-  public void testBasic() {
-    BytesBuilder bb = Bytes.newBuilder();
-
-    Bytes bytes1 = bb.append(new byte[] {'a', 'b'}).append("cd").append(Bytes.of("ef")).toBytes();
-    Assert.assertEquals(Bytes.of("abcdef"), bytes1);
-
-    bb = Bytes.newBuilder();
-    Bytes bytes2 = bb.append(Bytes.of("ab")).append("cd").append(new byte[] {'e', 'f'}).toBytes();
-    Assert.assertEquals(Bytes.of("abcdef"), bytes2);
-  }
-
-  @Test
-  public void testSetLength() {
-    BytesBuilder bb = Bytes.newBuilder();
-
-    Bytes bytes1 = bb.append(new byte[] {'a', 'b'}).append("cd").append(Bytes.of("ef")).toBytes();
-    Assert.assertEquals(Bytes.of("abcdef"), bytes1);
-
-    bb.setLength(0);
-    Bytes bytes2 = bb.append(Bytes.of("ab")).append("cd").append(new byte[] {'e', 'f'}).toBytes();
-    Assert.assertEquals(Bytes.of("abcdef"), bytes2);
-
-    bb.setLength(10);
-    Bytes bytes3 = bb.toBytes();
-    Assert.assertEquals(Bytes.of(new byte[] {'a', 'b', 'c', 'd', 'e', 'f', 0, 0, 0, 0}), bytes3);
-
-    bb.setLength(100);
-    Bytes bytes4 = bb.toBytes();
-    Assert.assertEquals(Bytes.of("abcdef"), bytes4.subSequence(0, 6));
-    for (int i = 6; i < 100; i++) {
-      Assert.assertEquals(0, bytes4.byteAt(i));
-    }
-  }
-
-  @Test
-  public void testSingleByte() {
-    BytesBuilder bb = Bytes.newBuilder();
-
-    bb.append('c');
-    bb.append(0);
-    bb.append(127);
-    bb.append(128);
-    bb.append(255);
-
-    Bytes bytes = bb.toBytes();
-    Assert.assertEquals(Bytes.of(new byte[] {'c', 0, 127, (byte) 128, (byte) 0xff}), bytes);
-  }
-
-  @Test
-  public void testArraySection() {
-    BytesBuilder bb = Bytes.newBuilder();
-
-    byte[] testing = new byte[] {'a', 'b', 'c', 'd', 'e'};
-
-    bb.append(testing, 0, 3);
-    bb.append(testing, 1, 3);
-    bb.append(testing, 2, 2);
-
-    Bytes bytes = bb.toBytes();
-    Assert.assertEquals(Bytes.of("abcbcdcd"), bytes);
-  }
-
-  @Test
-  public void testIncreaseCapacity() {
-
-    // test appending 3 chars at a time
-    StringBuilder sb = new StringBuilder();
-    BytesBuilder bb = Bytes.newBuilder();
-    BytesBuilder bb2 = Bytes.newBuilder();
-    BytesBuilder bb3 = Bytes.newBuilder();
-    int m = 19;
-    for (int i = 0; i < 100; i++) {
-      // produce a deterministic non repeating pattern
-      String s = (m % 1000) + "";
-      m = Math.abs(m * 19 + i);
-
-      bb.append(s);
-      bb2.append(Bytes.of(s));
-      bb3.append(s);
-      sb.append(s);
-    }
-
-    Assert.assertEquals(Bytes.of(sb.toString()), bb.toBytes());
-    Assert.assertEquals(Bytes.of(sb.toString()), bb2.toBytes());
-    Assert.assertEquals(Bytes.of(sb.toString()), bb3.toBytes());
-
-    // test appending one char at a time
-    sb.setLength(0);
-    bb = Bytes.newBuilder();
-    bb2 = Bytes.newBuilder();
-    bb3.setLength(0);
-    for (int i = 0; i < 500; i++) {
-      // produce a deterministic non repeating pattern
-      String s = (m % 10) + "";
-      m = Math.abs(m * 19 + i);
-      sb.append(s);
-      bb.append(s);
-      bb2.append(Bytes.of(s));
-      bb3.append(s);
-
-    }
-
-    Assert.assertEquals(Bytes.of(sb.toString()), bb.toBytes());
-    Assert.assertEquals(Bytes.of(sb.toString()), bb2.toBytes());
-    Assert.assertEquals(Bytes.of(sb.toString()), bb3.toBytes());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/core/src/test/java/org/apache/fluo/core/data/BytesTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/fluo/core/data/BytesTest.java b/modules/core/src/test/java/org/apache/fluo/core/data/BytesTest.java
deleted file mode 100644
index 00eee55..0000000
--- a/modules/core/src/test/java/org/apache/fluo/core/data/BytesTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.fluo.core.data;
-
-import java.nio.ByteBuffer;
-import java.util.List;
-
-import org.apache.fluo.api.data.Bytes;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Unit test for {@link Bytes}
- */
-public class BytesTest {
-
-  @Test
-  public void testBytesWrap() {
-
-    String s1 = "test1";
-    Bytes b1 = Bytes.of(s1);
-    Assert.assertArrayEquals(s1.getBytes(), b1.toArray());
-    Assert.assertEquals(s1, b1.toString());
-
-    String s2 = "test2";
-    ByteBuffer bb = ByteBuffer.wrap(s2.getBytes());
-    Bytes b2 = Bytes.of(bb);
-    Assert.assertArrayEquals(s2.getBytes(), b2.toArray());
-    Assert.assertEquals(s2, b2.toString());
-
-    // call again to ensure that position was not changed by previous call
-    b2 = Bytes.of(bb);
-    Assert.assertArrayEquals(s2.getBytes(), b2.toArray());
-    Assert.assertEquals(s2, b2.toString());
-
-    String s3 = "test3";
-    Bytes b3 = Bytes.of(s3.getBytes());
-    Assert.assertArrayEquals(s3.getBytes(), b3.toArray());
-    Assert.assertEquals(s3, b3.toString());
-
-    String s4 = "test4";
-    byte[] d4 = s4.getBytes();
-    Bytes b4 = Bytes.of(d4, 0, d4.length);
-    Assert.assertArrayEquals(s4.getBytes(), b4.toArray());
-    Assert.assertEquals(s4, b4.toString());
-  }
-
-  @Test
-  public void testConcatSplit() {
-
-    Bytes b1 = Bytes.of("str1");
-    Bytes b2 = Bytes.of("string2");
-    Bytes b3 = Bytes.of("s3");
-    Bytes ball = Bytes.concat(b1, b2, b3);
-
-    List<Bytes> blist = Bytes.split(ball);
-
-    Assert.assertEquals(b1, blist.get(0));
-    Assert.assertEquals(b2, blist.get(1));
-    Assert.assertEquals(b3, blist.get(2));
-  }
-
-  @Test
-  public void testImmutable() {
-    byte[] d1 = Bytes.of("mydata").toArray();
-
-    Bytes imm = Bytes.of(d1);
-    Assert.assertNotSame(d1, imm.toArray());
-  }
-
-  @Test
-  public void testCompare() {
-    Bytes b1 = Bytes.of("a");
-    Bytes b2 = Bytes.of("b");
-    Bytes b3 = Bytes.of("a");
-    Assert.assertEquals(-1, b1.compareTo(b2));
-    Assert.assertEquals(1, b2.compareTo(b1));
-    Assert.assertEquals(0, b1.compareTo(b3));
-    Assert.assertEquals(1, b1.compareTo(Bytes.EMPTY));
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/core/src/test/java/org/apache/fluo/core/data/ColumnTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/fluo/core/data/ColumnTest.java b/modules/core/src/test/java/org/apache/fluo/core/data/ColumnTest.java
deleted file mode 100644
index feebcb1..0000000
--- a/modules/core/src/test/java/org/apache/fluo/core/data/ColumnTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.fluo.core.data;
-
-import org.apache.fluo.api.data.Bytes;
-import org.apache.fluo.api.data.Column;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Unit test for {@link Column}
- */
-public class ColumnTest {
-
-  @Test
-  public void testCreation() {
-    Column col = new Column();
-    Assert.assertFalse(col.isFamilySet());
-    Assert.assertFalse(col.isQualifierSet());
-    Assert.assertFalse(col.isVisibilitySet());
-    Assert.assertSame(Bytes.EMPTY, col.getFamily());
-    Assert.assertSame(Bytes.EMPTY, col.getQualifier());
-    Assert.assertSame(Bytes.EMPTY, col.getVisibility());
-
-    col = Column.EMPTY;
-    Assert.assertFalse(col.isFamilySet());
-    Assert.assertFalse(col.isQualifierSet());
-    Assert.assertFalse(col.isVisibilitySet());
-
-    Assert.assertEquals(new Column(), new Column());
-    Assert.assertEquals(Column.EMPTY, Column.EMPTY);
-    Assert.assertEquals(Column.EMPTY, new Column());
-
-    Assert.assertEquals(new Column("a"), new Column(Bytes.of("a")));
-    Assert.assertEquals(new Column("a"), new Column(Bytes.of("a"), Bytes.EMPTY, Bytes.EMPTY));
-    Assert.assertEquals(new Column("a").hashCode(), new Column(Bytes.of("a"), Bytes.EMPTY,
-        Bytes.EMPTY).hashCode());
-
-    col = new Column("cf1");
-    Assert.assertTrue(col.isFamilySet());
-    Assert.assertFalse(col.isQualifierSet());
-    Assert.assertFalse(col.isVisibilitySet());
-    Assert.assertEquals(Bytes.of("cf1"), col.getFamily());
-    Assert.assertSame(Bytes.EMPTY, col.getQualifier());
-    Assert.assertSame(Bytes.EMPTY, col.getVisibility());
-    Assert.assertEquals(new Column("cf1"), col);
-
-    col = new Column("cf2", "cq2");
-    Assert.assertTrue(col.isFamilySet());
-    Assert.assertTrue(col.isQualifierSet());
-    Assert.assertFalse(col.isVisibilitySet());
-    Assert.assertEquals(Bytes.of("cf2"), col.getFamily());
-    Assert.assertEquals(Bytes.of("cq2"), col.getQualifier());
-    Assert.assertSame(Bytes.EMPTY, col.getVisibility());
-    Assert.assertEquals(new Column("cf2", "cq2"), col);
-
-    col = new Column("cf3", "cq3", "cv3");
-    Assert.assertTrue(col.isFamilySet());
-    Assert.assertTrue(col.isQualifierSet());
-    Assert.assertTrue(col.isVisibilitySet());
-    Assert.assertEquals(Bytes.of("cf3"), col.getFamily());
-    Assert.assertEquals(Bytes.of("cq3"), col.getQualifier());
-    Assert.assertEquals(Bytes.of("cv3"), col.getVisibility());
-    Assert.assertEquals(new Column("cf3", "cq3", "cv3"), col);
-  }
-
-  @Test
-  public void testCompare() {
-    Column c1 = new Column("a", "b");
-    Column c2 = new Column("a", "c");
-    Column c3 = new Column("a", "b", "d");
-    Column c4 = new Column("a");
-    Column c5 = Column.EMPTY;
-    Column c6 = new Column("a", "b");
-
-    Assert.assertEquals(-1, c1.compareTo(c2));
-    Assert.assertEquals(1, c2.compareTo(c1));
-    Assert.assertEquals(0, c1.compareTo(c6));
-    Assert.assertEquals(1, c1.compareTo(c5));
-    Assert.assertEquals(-1, c4.compareTo(c1));
-    Assert.assertEquals(-1, c1.compareTo(c3));
-    Assert.assertEquals(1, c4.compareTo(c5));
-    Assert.assertEquals(-1, c3.compareTo(c2));
-  }
-
-  @Test
-  public void testStringGetters() {
-    Column c0 = Column.EMPTY;
-    Column c1 = new Column("cf");
-    Column c2 = new Column("cf", "cq");
-    Column c3 = new Column("cf", "cq", "cv");
-
-    Assert.assertEquals("", c0.getsFamily());
-    Assert.assertEquals("", c0.getsQualifier());
-    Assert.assertEquals("", c0.getsVisibility());
-
-    Assert.assertEquals("cf", c1.getsFamily());
-    Assert.assertEquals("", c1.getsQualifier());
-    Assert.assertEquals("", c1.getsVisibility());
-
-    Assert.assertEquals("cf", c2.getsFamily());
-    Assert.assertEquals("cq", c2.getsQualifier());
-    Assert.assertEquals("", c2.getsVisibility());
-
-    Assert.assertEquals("cf", c3.getsFamily());
-    Assert.assertEquals("cq", c3.getsQualifier());
-    Assert.assertEquals("cv", c3.getsVisibility());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnTest.java b/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnTest.java
deleted file mode 100644
index dfd51e5..0000000
--- a/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.fluo.core.data;
-
-import org.apache.fluo.api.data.Bytes;
-import org.apache.fluo.api.data.Column;
-import org.apache.fluo.api.data.RowColumn;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Unit test for {@link RowColumn}
- */
-public class RowColumnTest {
-
-  @Test
-  public void testBasic() {
-
-    RowColumn rc = new RowColumn();
-    Assert.assertEquals(RowColumn.EMPTY, rc);
-    Assert.assertEquals(Bytes.EMPTY, rc.getRow());
-    Assert.assertEquals("", rc.getsRow());
-    Assert.assertEquals(Column.EMPTY, rc.getColumn());
-    Assert.assertEquals("   ", rc.toString());
-    Assert.assertNotEquals(RowColumn.EMPTY, Column.EMPTY);
-
-    rc = new RowColumn(Bytes.of("r1"));
-    Assert.assertEquals(Bytes.of("r1"), rc.getRow());
-    Assert.assertEquals("r1", rc.getsRow());
-    Assert.assertEquals(Column.EMPTY, rc.getColumn());
-    Assert.assertEquals(new RowColumn("r1"), rc);
-    Assert.assertEquals("r1   ", rc.toString());
-
-    rc = new RowColumn("r2", new Column("cf2"));
-    Assert.assertEquals(Bytes.of("r2"), rc.getRow());
-    Assert.assertEquals("r2", rc.getsRow());
-    Assert.assertEquals(new Column("cf2"), rc.getColumn());
-    Assert.assertEquals(new RowColumn(Bytes.of("r2"), new Column("cf2")), rc);
-    Assert.assertEquals("r2 cf2  ", rc.toString());
-    Assert.assertEquals(4007699, rc.hashCode());
-  }
-
-  @Test
-  public void testFollowing() {
-    byte[] fdata = new String("data1").getBytes();
-    fdata[4] = (byte) 0x00;
-    Bytes fb = Bytes.of(fdata);
-
-    Assert.assertEquals(RowColumn.EMPTY, new RowColumn().following());
-    Assert.assertEquals(new RowColumn(fb), new RowColumn("data").following());
-    Assert.assertEquals(new RowColumn("row", new Column(fb)), new RowColumn("row", new Column(
-        "data")).following());
-    Assert.assertEquals(new RowColumn("row", new Column(Bytes.of("cf"), fb)), new RowColumn("row",
-        new Column("cf", "data")).following());
-    Assert.assertEquals(new RowColumn("row", new Column(Bytes.of("cf"), Bytes.of("cq"), fb)),
-        new RowColumn("row", new Column("cf", "cq", "data")).following());
-  }
-
-  @Test
-  public void testCompare() {
-    RowColumn rc1 = new RowColumn("a", new Column("b"));
-    RowColumn rc2 = new RowColumn("b");
-    RowColumn rc3 = new RowColumn("a", new Column("c"));
-    RowColumn rc4 = new RowColumn("a", new Column("c", "d"));
-    Assert.assertEquals(-1, rc1.compareTo(rc2));
-    Assert.assertEquals(1, rc2.compareTo(rc1));
-    Assert.assertEquals(-1, rc1.compareTo(rc3));
-    Assert.assertEquals(-1, rc3.compareTo(rc2));
-    Assert.assertEquals(0, rc3.compareTo(rc3));
-    Assert.assertEquals(1, rc2.compareTo(RowColumn.EMPTY));
-    Assert.assertEquals(-1, rc3.compareTo(rc4));
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-fluo/blob/aa36c88f/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnValueTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnValueTest.java b/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnValueTest.java
deleted file mode 100644
index 63348b1..0000000
--- a/modules/core/src/test/java/org/apache/fluo/core/data/RowColumnValueTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for additional information regarding
- * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package org.apache.fluo.core.data;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.fluo.api.data.Bytes;
-import org.apache.fluo.api.data.Column;
-import org.apache.fluo.api.data.RowColumnValue;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class RowColumnValueTest {
-
-  RowColumnValue rcv1 = new RowColumnValue("row1", new Column("fam1", "qual1"), "a");
-  RowColumnValue rcv2 = new RowColumnValue("row1", new Column("fam1", "qual1"), "a");
-  RowColumnValue rcv3 = new RowColumnValue("row2", new Column("fam1", "qual1"), "a");
-  RowColumnValue rcv4 = new RowColumnValue("row1", new Column("fam1", "qual1"), "b");
-  RowColumnValue rcv5 = new RowColumnValue("row1", new Column("fam2", "qual1"), "a");
-  RowColumnValue rcv6 = new RowColumnValue("row2", new Column("fam2", "qual1"), "a");
-  RowColumnValue rcv7 = new RowColumnValue("row2", new Column("fam2", "qual1"), "b");
-
-  @Test
-  public void testEquals() {
-    for (RowColumnValue rcv : Arrays.asList(rcv1, rcv2)) {
-      Assert.assertEquals(rcv1, rcv);
-      Assert.assertEquals(rcv1.hashCode(), rcv.hashCode());
-    }
-
-    for (RowColumnValue rcv : Arrays.asList(rcv3, rcv4, rcv5, rcv6, rcv7)) {
-      Assert.assertNotEquals(rcv1, rcv);
-      Assert.assertNotEquals(rcv1.hashCode(), rcv.hashCode());
-    }
-  }
-
-  @Test
-  public void testGet() {
-    RowColumnValue rcv1 = new RowColumnValue("row1", new Column("fam1", "qual1"), "a");
-
-    Assert.assertEquals(rcv1.getRow(), Bytes.of("row1"));
-    Assert.assertEquals(rcv1.getValue(), Bytes.of("a"));
-    Assert.assertEquals(rcv1.getsValue(), "a");
-    Assert.assertEquals(rcv1.getColumn(), new Column("fam1", "qual1"));
-  }
-
-  @Test
-  public void testCompare() {
-    Assert.assertTrue(rcv1.compareTo(rcv1) == 0);
-    Assert.assertTrue(rcv1.compareTo(rcv2) == 0);
-    Assert.assertTrue(rcv1.compareTo(rcv3) < 0);
-    Assert.assertTrue(rcv3.compareTo(rcv1) > 0);
-    Assert.assertTrue(rcv1.compareTo(rcv3) < 0);
-    Assert.assertTrue(rcv3.compareTo(rcv1) > 0);
-    Assert.assertTrue(rcv1.compareTo(rcv5) < 0);
-    Assert.assertTrue(rcv5.compareTo(rcv1) > 0);
-    Assert.assertTrue(rcv1.compareTo(rcv4) < 0);
-    Assert.assertTrue(rcv4.compareTo(rcv1) > 0);
-
-    List<RowColumnValue> l1 = Arrays.asList(rcv7, rcv6, rcv5, rcv4, rcv3, rcv2, rcv1);
-    Collections.shuffle(l1);
-    Collections.sort(l1);
-
-    List<RowColumnValue> l2 = Arrays.asList(rcv1, rcv2, rcv4, rcv5, rcv3, rcv6, rcv7);
-
-    Assert.assertEquals(l2, l1);
-  }
-
-  @Test
-  public void testToString() {
-    Assert.assertEquals("row1 fam1 qual1  a", rcv1.toString());
-  }
-}



Mime
View raw message