Merge commit '50e9f8614b4124288f606d90c3417caa2b5f80de' into nanzhang/hyracks_genomix
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/KmerBytesWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/KmerBytesWritable.java
index e042840..bbba2fb 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/KmerBytesWritable.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/KmerBytesWritable.java
@@ -71,8 +71,8 @@
     /**
      * Set as reference to existing data
      */
-    public KmerBytesWritable(byte[] storage, int offset) {
-        setAsReference(storage, offset);
+    public KmerBytesWritable(byte[] newStorage, int newOffset) {
+        setAsReference(newStorage, newOffset);
     }
 
     /**
@@ -84,6 +84,16 @@
         this();
         setAsCopy(other);
     }
+    
+    /**
+     * copy kmer in other
+     * 
+     * @param other
+     */
+    public KmerBytesWritable(VKmerBytesWritable other) {
+        this();
+        setAsCopy(other);
+    }
 
     /**
      * Deep copy of the given kmer
@@ -92,22 +102,37 @@
      */
     public void setAsCopy(KmerBytesWritable other) {
         if (lettersInKmer > 0) {
-            System.arraycopy(other.bytes, other.offset, bytes, this.offset, bytesUsed);
+            System.arraycopy(other.bytes, other.offset, bytes, offset, bytesUsed);
         }
     }
+    
+    /**
+     * Deep copy of the given kmer
+     * 
+     * @param other
+     */
+    public void setAsCopy(VKmerBytesWritable other) {
+        if (other.lettersInKmer != lettersInKmer) {
+            throw new IllegalArgumentException("Provided VKmer (" + other + ") is of an incompatible length (was " + other.getKmerLetterLength() + ", should be " + lettersInKmer + ")!");
+        }
+        if (lettersInKmer > 0) {
+            System.arraycopy(other.bytes, other.kmerStartOffset, bytes, offset, bytesUsed);
+        }
+    }
+
 
     /**
      * Deep copy of the given bytes data
      * 
      * @param newData
-     * @param offset
+     * @param newOffset
      */
-    public void setAsCopy(byte[] newData, int offset) {
-        if (newData.length - offset < bytesUsed) {
+    public void setAsCopy(byte[] newData, int newOffset) {
+        if (newData.length - newOffset < bytesUsed) {
             throw new IllegalArgumentException("Requested " + bytesUsed + " bytes (k=" + lettersInKmer
-                    + ") but buffer has only " + (newData.length - offset) + " bytes");
+                    + ") but buffer has only " + (newData.length - newOffset) + " bytes");
         }
-        System.arraycopy(newData, offset, bytes, this.offset, bytesUsed);
+        System.arraycopy(newData, newOffset, bytes, offset, bytesUsed);
     }
 
     /**
@@ -115,15 +140,30 @@
      * to new datablock.
      * 
      * @param newData
-     * @param offset
+     * @param newOffset
      */
-    public void setAsReference(byte[] newData, int offset) {
-        if (newData.length - offset < bytesUsed) {
+    public void setAsReference(byte[] newData, int newOffset) {
+        if (newData.length - newOffset < bytesUsed) {
             throw new IllegalArgumentException("Requested " + bytesUsed + " bytes (k=" + lettersInKmer
-                    + ") but buffer has only " + (newData.length - offset) + " bytes");
+                    + ") but buffer has only " + (newData.length - newOffset) + " bytes");
         }
         bytes = newData;
-        this.offset = offset;
+        offset = newOffset;
+    }
+    
+    /**
+     * Point this datablock to the given kmer's byte array It works like the pointer
+     * to new datablock.
+     * 
+     * @param newData
+     * @param offset
+     */
+    public void setAsReference(VKmerBytesWritable other) {
+        if (other.lettersInKmer != lettersInKmer) {
+            throw new IllegalArgumentException("Provided VKmer (" + other + ") is of an incompatible length (was " + other.getKmerLetterLength() + ", should be " + lettersInKmer + ")!");
+        }
+        bytes = other.bytes;
+        offset = other.kmerStartOffset;
     }
 
     /**
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java
index 9c6f9a3..11b0f12 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerBytesWritable.java
@@ -98,6 +98,16 @@
         this(other.lettersInKmer);
         setAsCopy(other);
     }
+    
+    /**
+     * deep copy of kmer in other
+     * 
+     * @param other
+     */
+    public VKmerBytesWritable(KmerBytesWritable other) {
+        this(other.lettersInKmer);
+        setAsCopy(other);
+    }
 
     /**
      * Deep copy of the given kmer
@@ -110,6 +120,18 @@
             System.arraycopy(other.bytes, other.kmerStartOffset, bytes, this.kmerStartOffset, bytesUsed);
         }
     }
+    
+    /**
+     * Deep copy of the given kmer
+     * 
+     * @param other
+     */
+    public void setAsCopy(KmerBytesWritable other) {
+        reset(other.lettersInKmer);
+        if (lettersInKmer > 0) {
+            System.arraycopy(other.bytes, other.offset, bytes, this.kmerStartOffset, bytesUsed);
+        }
+    }
 
     /**
      * set from String kmer
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerListWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerListWritable.java
index 1a006ca..f269b5a 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerListWritable.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/VKmerListWritable.java
@@ -69,6 +69,17 @@
         valueCount += 1;
         Marshal.putInt(valueCount, storage, offset);
     }
+    
+    public void append(KmerBytesWritable kmer) { // TODO optimize this into two separate containers...
+        setSize(getLength() + kmer.getLength() + VKmerBytesWritable.HEADER_SIZE);
+        int myLength = getLength();
+        Marshal.putInt(KmerBytesWritable.getKmerLength(), storage, offset + myLength); // write a new VKmer header
+        System.arraycopy(kmer.getBytes(), kmer.offset,
+                storage, offset + myLength + VKmerBytesWritable.HEADER_SIZE,
+                kmer.getLength());
+        valueCount += 1;
+        Marshal.putInt(valueCount, storage, offset);
+    }
 
     /*
      * Append the otherList to the end of myList