remake new graph class - PositionWritable and NodeWritable
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java
index e80d7da..4ce14cc 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java
@@ -20,6 +20,12 @@
                 + ((bytes[offset + 3] & 0xff) << 0);
     }
     
+    public static long getLong(byte[] bytes, int offset) {
+        return ((bytes[offset] & 0xff) << 54) + ((bytes[offset] & 0xff) << 48) + ((bytes[offset + 1] & 0xff) << 40) 
+                + ((bytes[offset + 2] & 0xff) << 32) + ((bytes[offset] & 0xff) << 24) + ((bytes[offset + 1] & 0xff) << 16) 
+                + ((bytes[offset + 2] & 0xff) << 8) + ((bytes[offset + 3] & 0xff) << 0);
+    }
+    
     public static void putInt(int val, byte[] bytes, int offset) {
         bytes[offset] = (byte)((val >>> 24) & 0xFF);        
         bytes[offset + 1] = (byte)((val >>> 16) & 0xFF);
@@ -27,6 +33,17 @@
         bytes[offset + 3] = (byte)((val >>>  0) & 0xFF);
     }
     
+    public static void putLong(long val, byte[] bytes, int offset) {
+        bytes[offset] = (byte)((val >>> 54) & 0xFF);        
+        bytes[offset + 1] = (byte)((val >>> 48) & 0xFF);
+        bytes[offset + 2] = (byte)((val >>>  40) & 0xFF);
+        bytes[offset + 3] = (byte)((val >>>  32) & 0xFF);
+        bytes[offset + 4] = (byte)((val >>>  24) & 0xFF);
+        bytes[offset + 5] = (byte)((val >>>  16) & 0xFF);
+        bytes[offset + 6] = (byte)((val >>>  8) & 0xFF);
+        bytes[offset + 7] = (byte)((val >>>  0) & 0xFF);
+    }
+    
     public static int hashBytes(byte[] bytes, int offset, int length) {
         int hash = 1;
         for (int i = offset; i < offset + length; i++)
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/NodeWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/NodeWritable.java
new file mode 100644
index 0000000..b6e2055
--- /dev/null
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/NodeWritable.java
@@ -0,0 +1,196 @@
+package edu.uci.ics.genomix.newtype;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.hadoop.io.WritableComparable;
+import edu.uci.ics.genomix.type.KmerBytesWritable;
+import edu.uci.ics.genomix.newtype.PositionListWritable;
+
+public class NodeWritable implements WritableComparable<NodeWritable>, Serializable{
+
+    private static final long serialVersionUID = 1L;
+    public static final NodeWritable EMPTY_NODE = new NodeWritable(0);
+    
+    private PositionListWritable forwardForwardList;
+    private PositionListWritable forwardReverseList;
+    private PositionListWritable reverseForwardList;
+    private PositionListWritable reverseReverseList;
+    private KmerBytesWritable kmer;
+    
+    // merge/update directions
+    public static class DirectionFlag {
+        public static final byte DIR_FF = 0b00 << 0;
+        public static final byte DIR_FR = 0b01 << 0;
+        public static final byte DIR_RF = 0b10 << 0;
+        public static final byte DIR_RR = 0b11 << 0;
+        public static final byte DIR_MASK = 0b11 << 0;
+    }
+    
+    public NodeWritable() {
+        this(21);
+    }
+    
+    public NodeWritable(int kmerSize) {
+        forwardForwardList = new PositionListWritable();
+        forwardReverseList = new PositionListWritable();
+        reverseForwardList = new PositionListWritable();
+        reverseReverseList = new PositionListWritable();
+        kmer = new KmerBytesWritable(kmerSize);
+    }
+    
+    public NodeWritable(PositionListWritable FFList, PositionListWritable FRList,
+            PositionListWritable RFList, PositionListWritable RRList, KmerBytesWritable kmer) {
+        this(kmer.getKmerLength());
+        set(FFList, FRList, RFList, RRList, kmer);
+    }
+    
+    public void set(NodeWritable node){
+        set(node.forwardForwardList, node.forwardReverseList, node.reverseForwardList, 
+                node.reverseReverseList, node.kmer);
+    }
+    
+    public void set(PositionListWritable FFList, PositionListWritable FRList,
+            PositionListWritable RFList, PositionListWritable RRList, KmerBytesWritable kmer) {
+        this.forwardForwardList.set(FFList);
+        this.forwardReverseList.set(FRList);
+        this.reverseForwardList.set(RFList);
+        this.reverseReverseList.set(RRList);
+        this.kmer.set(kmer);
+    }
+
+    public void reset(int kmerSize) {
+        forwardForwardList.reset();
+        forwardReverseList.reset();
+        reverseForwardList.reset();
+        reverseReverseList.reset();
+        kmer.reset(kmerSize);
+    }
+    
+    public KmerBytesWritable getKmer() {
+        return kmer;
+    }
+
+    public void setKmer(KmerBytesWritable kmer) {
+        this.kmer = kmer;
+    }
+    
+    public int getCount() {
+        return kmer.getKmerLength();
+    }
+    
+    public PositionListWritable getFFList() {
+        return forwardForwardList;
+    }
+
+    public PositionListWritable getFRList() {
+        return forwardReverseList;
+    }
+
+    public PositionListWritable getRFList() {
+        return reverseForwardList;
+    }
+
+    public PositionListWritable getRRList() {
+        return reverseReverseList;
+    }
+    
+    public PositionListWritable getListFromDir(byte dir) {
+        switch (dir & DirectionFlag.DIR_MASK) {
+            case DirectionFlag.DIR_FF:
+                return getFFList();
+            case DirectionFlag.DIR_FR:
+                return getFRList();
+            case DirectionFlag.DIR_RF:
+                return getRFList();
+            case DirectionFlag.DIR_RR:
+                return getRRList();
+            default:
+                throw new RuntimeException("Unrecognized direction in getListFromDir: " + dir);
+        }
+    }
+    @Override
+    public void write(DataOutput out) throws IOException {
+        this.forwardForwardList.write(out);
+        this.forwardReverseList.write(out);
+        this.reverseForwardList.write(out);
+        this.reverseReverseList.write(out);
+        this.kmer.write(out);
+    }
+
+    @Override
+    public void readFields(DataInput in) throws IOException {
+        this.forwardForwardList.readFields(in);
+        this.forwardReverseList.readFields(in);
+        this.reverseForwardList.readFields(in);
+        this.reverseReverseList.readFields(in);
+        this.kmer.readFields(in);
+    }
+
+    @Override
+    public int compareTo(NodeWritable other) {
+        return this.kmer.compareTo(other.kmer);
+    }
+    
+    @Override
+    public int hashCode() {
+        return this.kmer.hashCode();
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof NodeWritable) {
+            NodeWritable nw = (NodeWritable) o;
+            return (this.forwardForwardList.equals(nw.forwardForwardList)
+                    && this.forwardReverseList.equals(nw.forwardReverseList)
+                    && this.reverseForwardList.equals(nw.reverseForwardList)
+                    && this.reverseReverseList.equals(nw.reverseReverseList) && this.kmer.equals(nw.kmer));
+        }
+        return false;
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder sbuilder = new StringBuilder();
+        sbuilder.append('(');
+        sbuilder.append(forwardForwardList.toString()).append('\t');
+        sbuilder.append(forwardReverseList.toString()).append('\t');
+        sbuilder.append(reverseForwardList.toString()).append('\t');
+        sbuilder.append(reverseReverseList.toString()).append('\t');
+        sbuilder.append(kmer.toString()).append(')');
+        return sbuilder.toString();
+    }
+
+    public void mergeForwardNext(NodeWritable nextNode, int initialKmerSize) {
+        this.forwardForwardList.set(nextNode.forwardForwardList);
+        this.forwardReverseList.set(nextNode.forwardReverseList);
+        kmer.mergeWithFFKmer(initialKmerSize, nextNode.getKmer());
+    }
+
+    public void mergeForwardPre(NodeWritable preNode, int initialKmerSize) {
+        this.reverseForwardList.set(preNode.reverseForwardList);
+        this.reverseReverseList.set(preNode.reverseReverseList);
+        kmer.mergeWithRRKmer(initialKmerSize, preNode.getKmer());
+    }
+    
+    public int inDegree() {
+        return reverseReverseList.getCountOfPosition() + reverseForwardList.getCountOfPosition();
+    }
+
+    public int outDegree() {
+        return forwardForwardList.getCountOfPosition() + forwardReverseList.getCountOfPosition();
+    }
+
+    /*
+     * Return if this node is a "path" compressible node, that is, it has an in-degree and out-degree of 1 
+     */
+    public boolean isPathNode() {
+        return inDegree() == 1 && outDegree() == 1;
+    }
+
+    public boolean isSimpleOrTerminalPath() {
+        return isPathNode() || (inDegree() == 0 && outDegree() == 1) || (inDegree() == 1 && outDegree() == 0);
+    }
+}
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionListWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionListWritable.java
new file mode 100644
index 0000000..8ebeb3f
--- /dev/null
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionListWritable.java
@@ -0,0 +1,238 @@
+package edu.uci.ics.genomix.newtype;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hadoop.io.Writable;
+
+import edu.uci.ics.genomix.data.Marshal;
+import edu.uci.ics.genomix.newtype.PositionWritable;
+
+public class PositionListWritable implements Writable, Iterable<PositionWritable>, Serializable{
+    private static final long serialVersionUID = 1L;
+    protected byte[] storage;
+    protected int offset;
+    protected int valueCount;
+    protected static final byte[] EMPTY = {};
+    public static final int LONGBYTES = 8;
+    
+    protected PositionWritable posIter = new PositionWritable();
+    
+    public PositionListWritable() {
+        this.storage = EMPTY;
+        this.valueCount = 0;
+        this.offset = 0;
+    }
+    
+    public PositionListWritable(List<PositionWritable> posns) {
+        this();
+        for (PositionWritable p : posns) {
+            append(p);
+        }
+    }
+    
+    public void setNewReference(int count, byte[] data, int offset) {
+        this.valueCount = count;
+        this.storage = data;
+        this.offset = offset;
+    }
+    
+    public void append(long uuid) {
+        setSize((1 + valueCount) * PositionWritable.LENGTH);
+        Marshal.putLong(uuid, storage, offset + valueCount * PositionWritable.LENGTH);
+        valueCount += 1;
+    }
+    
+    public void append(PositionWritable pos) {
+        if(pos != null){
+            setSize((1 + valueCount) * PositionWritable.LENGTH);
+            System.arraycopy(pos.getByteArray(), pos.getStartOffset(), storage, offset + valueCount
+                    * PositionWritable.LENGTH, pos.getLength());
+            valueCount += 1;
+        }
+    }
+    
+    /*
+     * Append the otherList to the end of myList
+     */
+    public void appendList(PositionListWritable otherList) {
+        if (otherList.valueCount > 0) {
+            setSize((valueCount + otherList.valueCount) * PositionWritable.LENGTH);
+            // copy contents of otherList into the end of my storage
+            System.arraycopy(otherList.storage, otherList.offset,
+                    storage, offset + valueCount * PositionWritable.LENGTH, 
+                    otherList.valueCount * PositionWritable.LENGTH);
+            valueCount += otherList.valueCount;
+        }
+    }
+    
+    public static int getCountByDataLength(int length) {
+        if (length % PositionWritable.LENGTH != 0) {
+            throw new IllegalArgumentException("Length of positionlist is invalid");
+        }
+        return length / PositionWritable.LENGTH;
+    }
+    
+    public void set(PositionListWritable otherList) {
+        set(otherList.valueCount, otherList.storage, otherList.offset);
+    }
+
+    public void set(int valueCount, byte[] newData, int offset) {
+        this.valueCount = valueCount;
+        setSize(valueCount * PositionWritable.LENGTH);
+        if (valueCount > 0) {
+            System.arraycopy(newData, offset, storage, this.offset, valueCount * PositionWritable.LENGTH);
+        }
+    }
+
+    public void reset() {
+        valueCount = 0;
+    }
+    
+    protected void setSize(int size) {
+        if (size > getCapacity()) {
+            setCapacity((size * 3 / 2));
+        }
+    }
+    
+    protected int getCapacity() {
+        return storage.length - offset;
+    }
+
+    protected void setCapacity(int new_cap) {
+        if (new_cap > getCapacity()) {
+            byte[] new_data = new byte[new_cap];
+            if (storage.length - offset > 0) {
+                System.arraycopy(storage, offset, new_data, 0, storage.length - offset);
+            }
+            storage = new_data;
+            offset = 0;
+        }
+    }
+    
+    public PositionWritable getPosition(int i) {
+        if (i >= valueCount) {
+            throw new ArrayIndexOutOfBoundsException("No such positions");
+        }
+        posIter.setNewReference(storage, offset + i * PositionWritable.LENGTH);
+        return posIter;
+    }
+    
+    public void resetPosition(int i, long uuid) {
+        if (i >= valueCount) {
+            throw new ArrayIndexOutOfBoundsException("No such positions");
+        }
+        Marshal.putLong(uuid, storage, offset + i * PositionWritable.LENGTH);
+    }
+    
+    public int getCountOfPosition() {
+        return valueCount;
+    }
+
+    public byte[] getByteArray() {
+        return storage;
+    }
+
+    public int getStartOffset() {
+        return offset;
+    }
+
+    public int getLength() {
+        return valueCount * PositionWritable.LENGTH;
+    }
+    
+    @Override
+    public Iterator<PositionWritable> iterator() {
+        Iterator<PositionWritable> it = new Iterator<PositionWritable>() {
+
+            private int currentIndex = 0;
+
+            @Override
+            public boolean hasNext() {
+                return currentIndex < valueCount;
+            }
+
+            @Override
+            public PositionWritable next() {
+                return getPosition(currentIndex++);
+            }
+
+            @Override
+            public void remove() {
+                if(currentIndex < valueCount)
+                    System.arraycopy(storage, offset + currentIndex * PositionWritable.LENGTH, 
+                          storage, offset + (currentIndex - 1) * PositionWritable.LENGTH, 
+                          (valueCount - currentIndex) * PositionWritable.LENGTH);
+                valueCount--;
+                currentIndex--;
+            }
+        };
+        return it;
+    }
+    
+    /*
+     * remove the first instance of @toRemove. Uses a linear scan.  Throws an exception if not in this list.
+     */
+    public void remove(PositionWritable toRemove) {
+        Iterator<PositionWritable> posIterator = this.iterator();
+        while (posIterator.hasNext()) {
+            if(toRemove.equals(posIterator.next())) {
+                posIterator.remove();
+                return;
+            }
+        }
+        //throw new ArrayIndexOutOfBoundsException("the PositionWritable `" + toRemove.toString() + "` was not found in this list.");
+    }
+    
+    @Override
+    public void write(DataOutput out) throws IOException {
+        out.writeInt(valueCount);
+        out.write(storage, offset, valueCount * PositionWritable.LENGTH);
+    }
+    
+    @Override
+    public void readFields(DataInput in) throws IOException {
+        this.valueCount = in.readInt();
+        setSize(valueCount * PositionWritable.LENGTH);
+        in.readFully(storage, offset, valueCount * PositionWritable.LENGTH);
+    }
+    
+    @Override
+    public String toString() {
+        StringBuilder sbuilder = new StringBuilder();
+        sbuilder.append('[');
+        for (PositionWritable pos : this) {
+            sbuilder.append(pos.toString());
+            sbuilder.append(',');
+        }
+        if (valueCount > 0) {
+            sbuilder.setCharAt(sbuilder.length() - 1, ']');
+        } else {
+            sbuilder.append(']');
+        }
+        return sbuilder.toString();
+    }
+    
+    @Override
+    public int hashCode() {
+        return Marshal.hashBytes(getByteArray(), getStartOffset(), getLength());
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof PositionListWritable))
+            return false;
+        PositionListWritable other = (PositionListWritable) o;
+        if (this.valueCount != other.valueCount)
+            return false;
+        for (int i=0; i < this.valueCount; i++) {
+                if (!this.getPosition(i).equals(other.getPosition(i)))
+                    return false;
+        }
+        return true;
+    }
+}
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionWritable.java
new file mode 100644
index 0000000..cde7226
--- /dev/null
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionWritable.java
@@ -0,0 +1,91 @@
+package edu.uci.ics.genomix.newtype;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.hadoop.io.WritableComparable;
+
+import edu.uci.ics.genomix.data.Marshal;
+import edu.uci.ics.genomix.newtype.PositionWritable;
+
+public class PositionWritable implements WritableComparable<PositionWritable>, Serializable{
+    private static final long serialVersionUID = 1L;
+    protected byte[] storage;
+    protected int offset;
+    public static final int LENGTH = 5;
+    public static final int LONGBYTES = 8;
+    
+    public PositionWritable() {
+        storage = new byte[LENGTH];
+        offset = 0;
+    }
+    
+    public PositionWritable(long uuid){
+        this();
+        set(uuid);
+    }
+    
+    public void set(long uuid){
+        Marshal.putLong(uuid, storage, offset);
+    }
+    
+    public void set(PositionWritable pos) {
+        set(pos.getUUID());
+    }
+    
+    public void setNewReference(byte[] storage, int offset) {
+        this.storage = storage;
+        this.offset = offset;
+    }
+    
+    public long getUUID(){
+        return Marshal.getLong(storage, offset);
+    }
+    
+    public byte[] getByteArray() {
+        return storage;
+    }
+
+    public int getStartOffset() {
+        return offset;
+    }
+
+    public int getLength() {
+        return LENGTH;
+    }
+
+    @Override
+    public void readFields(DataInput in) throws IOException {
+        in.readFully(storage, offset, LENGTH);
+    }
+
+    @Override
+    public void write(DataOutput out) throws IOException {
+        out.write(storage, offset, LENGTH);
+    }
+    
+    @Override
+    public int hashCode() {
+        return Marshal.hashBytes(getByteArray(), getStartOffset(), getLength());
+    }
+    
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof PositionWritable))
+            return false;
+        PositionWritable other = (PositionWritable) o;
+        return this.getUUID() == other.getUUID();
+    }
+    
+    @Override
+    public int compareTo(PositionWritable other) {
+        return (this.getUUID() < other.getUUID()) ? -1 : ((this.getUUID() == other.getUUID()) ? 0 : 1);
+    }
+    
+    @Override
+    public String toString() {
+        return "(" + Long.toString(this.getUUID()) + ")";
+    }
+}
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java
index ebcf7f0..d929dfc 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java
@@ -117,10 +117,6 @@
 
             @Override
             public void remove() {
-//                for(int cursor = currentIndex; cursor < valueCount; cursor++){
-//                    System.arraycopy(storage, offset + cursor * PositionWritable.LENGTH, 
-//                            storage, offset + (cursor-1) * PositionWritable.LENGTH, PositionWritable.LENGTH);
-//                }
                 if(currentIndex < valueCount)
                     System.arraycopy(storage, offset + currentIndex * PositionWritable.LENGTH, 
                           storage, offset + (currentIndex - 1) * PositionWritable.LENGTH,