diff --git a/src/main/java/net/onrc/onos/apps/bgproute/PatriciaTrie.java b/src/main/java/net/onrc/onos/apps/bgproute/PatriciaTrie.java
index 9badd11..8225d7d 100644
--- a/src/main/java/net/onrc/onos/apps/bgproute/PatriciaTrie.java
+++ b/src/main/java/net/onrc/onos/apps/bgproute/PatriciaTrie.java
@@ -4,503 +4,500 @@
 import java.util.NoSuchElementException;
 
 public class PatriciaTrie<V> implements IPatriciaTrie<V> {
-	private final byte maskBits[] = {(byte)0x00, (byte)0x80, (byte)0xc0, (byte)0xe0, (byte)0xf0, 
-												 (byte)0xf8, (byte)0xfc, (byte)0xfe, (byte)0xff};
-	
-	private int maxPrefixLength;
-	
-	private Node top;
+    private final byte maskBits[] = {(byte) 0x00, (byte) 0x80, (byte) 0xc0, (byte) 0xe0, (byte) 0xf0,
+            (byte) 0xf8, (byte) 0xfc, (byte) 0xfe, (byte) 0xff};
 
-	public PatriciaTrie(int maxPrefixLength) {
-		this.maxPrefixLength = maxPrefixLength;
-	}
+    private int maxPrefixLength;
 
-	@Override
-	public synchronized V put(Prefix prefix, V value) {
-		if (prefix == null || value == null) {
-			throw new NullPointerException();
-		}
-		
-		if (prefix.getPrefixLength() > maxPrefixLength) {
-			throw new IllegalArgumentException(String.format(
-					"Prefix length %d is greater than max prefix length %d", 
-					prefix.getPrefixLength(), maxPrefixLength));
-		}
-		
-		Node node = top;
-		Node match = null;
-		
-		while (node != null
-				&& node.prefix.getPrefixLength() <= prefix.getPrefixLength()
-				&& key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
-		    if (node.prefix.getPrefixLength() == prefix.getPrefixLength()) {
-		    	/*
-		    	 * Prefix is already in tree. This may be an aggregate node, in which case
-		    	 * we are inserting a new prefix, or it could be an actual node, in which 
-		    	 * case we are inserting a new nexthop for the prefix and should return
-		    	 * the old nexthop.
-		    	 */
-		    	V oldValue = node.value;
-		    	node.value = value;
-		    	return oldValue;
-			}
+    private Node top;
 
-			match = node;
-			
-			if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
-				node = node.right;
-			} else {
-				node = node.left;
-			}
-		}
+    public PatriciaTrie(int maxPrefixLength) {
+        this.maxPrefixLength = maxPrefixLength;
+    }
 
-		Node add = null;
-		
-		if (node == null) {
-			//add = new Node(p, r);
-			add = new Node(prefix);
-			add.value = value;
-			
-			if (match != null) {
-				node_link(match, add);
-			} else {
-				top = add;
-			}
-		} else {
-			add = node_common(node, prefix.getAddress(), prefix.getPrefixLength());
-			if (add == null) {
-				//I think this is -ENOMEM?
-				//return null;
-			}				
-			
-			if (match != null) {
-				node_link(match, add);
-			} else {
-				top = add;
-			}
-			node_link(add, node);
-			
-			if (add.prefix.getPrefixLength() != prefix.getPrefixLength()) {
-				match = add;
-				
-				//add = new Node(p, r);
-				add = new Node(prefix);
-				add.value = value;
-				node_link(match, add);
-			}
-			else {
-				add.value = value;
-			}
-		}
-		
-		//If we added a new Node, there was no previous mapping
-		return null;
-		//return addReference(add);
-	}
-	
-	/*exact match*/
-	@Override
-	public synchronized V lookup(Prefix prefix) {
-		if (prefix.getPrefixLength() > maxPrefixLength) {
-			return null;
-		}
-		
-		/*
-		Node node = top;
-		
-		while (node != null
-				&& node.prefix.getPrefixLength() <= p.getPrefixLength()
-				&& key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), p.getAddress(), p.getPrefixLength()) == true) {
-			if (node.prefix.getPrefixLength() == p.getPrefixLength()) {
-				//return addReference(node);
-				return node.rib;
-			}
-			
-			if (bit_check(p.getAddress(), node.prefix.getPrefixLength()) == true) {
-				node = node.right;
-			} else {
-				node = node.left;
-			}
-		}
-		*/
-		
-		Node node = findNode(prefix);
-		
-		return node == null ? null : node.value;
-	}
-	
-	/*closest containing prefix*/
-	@Override
-	public synchronized V match(Prefix prefix) {
-		//TODO
-		if (prefix.getPrefixLength() > maxPrefixLength) {
-			return null;
-		}
-		
-		Node closestNode = findClosestNode(prefix);
-		
-		return closestNode == null ? null : closestNode.value;
-	}
-	
-	@Override
-	public synchronized boolean remove(Prefix prefix, V value) {
-		Node child;
-		Node parent;
-		
-		if (prefix == null || value == null) {
-			return false;
-		}
-		
-		Node node = findNode(prefix);
-		
-		if (node == null || node.isAggregate() || !node.value.equals(value)) {
-			//Given <prefix, nexthop> mapping is not in the tree
-			return false;
-		}
-		
-		if (node.left != null && node.right != null) {
-			//Remove the RibEntry entry and leave this node as an aggregate node
-			//In the future, maybe we should re-evaluate what the aggregate prefix should be?
-			//It shouldn't necessarily stay the same.
-			//More complicated if the above prefix is also aggregate.
-			node.value = null;
-			return true;
-		}
-		
-		if (node.left != null) {
-			child = node.left;
-		} else {
-			child = node.right;
-		}
-		
-		parent = node.parent;
-		
-		if (child != null) {
-			child.parent = parent;
-		}
-		
-		if (parent != null) {
-			if (parent.left == node) {
-				parent.left = child;
-			} else {
-				parent.right = child;
-			}
-		} else {
-			top = child;
-		}
-		
-		/*
-		 * TODO not sure what to do here. I think this is lazily deleting aggregate nodes,
-		 * notice that it used to do nothing if it detected both children were not null earlier.
-		 * But here, what we really should do is reevaluate the aggregate prefix of the parent
-		 * node (if it is indeed an aggregate). Because at the moment, no aggregate node will ever
-		 * be removed. BUT, I don't actually think this presents a correctness problem, at
-		 * least from an external point of view.
-		 */
-		//if (parent != null && parent.refCount == 0) {
-			//node_remove(parent);
-		//}
-		
-		return true;
-	}
-	
-	@Override
-	public Iterator<Entry<V>> iterator() {
-		return new PatriciaTrieIterator(top);
-	}
-	
-	private Node findNode(Prefix prefix) {
-		Node node = top;
-		
-		while (node != null
-				&& node.prefix.getPrefixLength() <= prefix.getPrefixLength()
-				&& key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
-			if (node.prefix.getPrefixLength() == prefix.getPrefixLength()) {
-				//return addReference(node);
-				return node;
-			}
-			
-			if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
-				node = node.right;
-			} else {
-				node = node.left;
-			}
-		}
-		
-		return null;
-	}
-	
-	private Node findClosestNode(Prefix prefix) {
-		Node node = top;
-		Node match = null;
-		
-		while (node != null
-				&& node.prefix.getPrefixLength() <= prefix.getPrefixLength()
-				&& key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
-			if (!node.isAggregate()) {
-				match = node;
-			}
-			
-			if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
-				node = node.right;
-			} else {
-				node = node.left;
-			}
-		}
-		
-		return match;
-	}
-	
-	/*
-	 * Receives a 1-based bit index
-	 * Returns a 1-based byte index
-	 * eg. (0 => 1), 1 => 1, 8 => 1, 9 => 2, 17 => 3
-	 */
-	private int getByteContainingBit(int bitNumber) {
-		return Math.max((bitNumber + 7) / 8, 1);
-	}
-	
-	private boolean key_match(byte [] key1, int key1_len, byte [] key2, int key2_len) {
-		//int offset;
-		//int shift;
-		
-		if (key1_len > key2_len) {
-			return false;
-		}
-		
-		int offset = (Math.min(key1_len, key2_len)) / 8;
-		int shift = (Math.min(key1_len, key2_len)) % 8;
-		
-		if (shift != 0) {
-			if ((maskBits[shift] & (key1[offset] ^ key2[offset])) != 0) {
-				return false;
-			}
-		}
-		
-		while (offset != 0) {
-			offset--;
-			if (key1[offset] != key2[offset]) {
-				return false;
-			}
-		}
-		return true;
-	}
-	
-	private boolean bit_check(byte [] key, int key_bits) {
-		int offset = key_bits / 8;
-		int shift = 7 - (key_bits % 8);
-		int bit = key[offset] & 0xff;
+    @Override
+    public synchronized V put(Prefix prefix, V value) {
+        if (prefix == null || value == null) {
+            throw new NullPointerException();
+        }
 
-		bit >>= shift;
-		
-		if ((bit & 1) == 1) {
-			return true;
-		} else {
-			return false;
-		}
-	}
-	
-	private void node_link(Node node, Node add) {
-		boolean bit = bit_check(add.prefix.getAddress(), node.prefix.getPrefixLength());
-		
-		if (bit == true) {
-			node.right = add;
-		} else {
-			node.left = add;
-		}
-		add.parent = node;
-	}
-	
-    private Node node_common(Node node, byte [] key, int key_bits) {
-		int i;
-		int limit = Math.min(node.prefix.getPrefixLength(), key_bits) / 8;
+        if (prefix.getPrefixLength() > maxPrefixLength) {
+            throw new IllegalArgumentException(String.format(
+                    "Prefix length %d is greater than max prefix length %d",
+                    prefix.getPrefixLength(), maxPrefixLength));
+        }
 
-		for (i = 0; i < limit; i++) {
-			if (node.prefix.getAddress()[i] != key[i]) {
-				break;
-			}
-		}
-		
-		int common_len = i * 8;
-		int boundary = 0;
+        Node node = top;
+        Node match = null;
 
-		if (common_len != key_bits) {
-			byte diff = (byte)(node.prefix.getAddress()[i] ^ key[i]);
-			byte mask = (byte)0x80;
-			int shift_mask = 0;
-			
-			while (common_len < key_bits && ((mask & diff) == 0)) {
-				boundary = 1;
+        while (node != null
+                && node.prefix.getPrefixLength() <= prefix.getPrefixLength()
+                && key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
+            if (node.prefix.getPrefixLength() == prefix.getPrefixLength()) {
+                /*
+                 * Prefix is already in tree. This may be an aggregate node, in which case
+                 * we are inserting a new prefix, or it could be an actual node, in which
+                 * case we are inserting a new nexthop for the prefix and should return
+                 * the old nexthop.
+                 */
+                V oldValue = node.value;
+                node.value = value;
+                return oldValue;
+            }
 
-				shift_mask = (mask & 0xff);
-				shift_mask >>= 1;
-				mask = (byte)shift_mask;
+            match = node;
 
-				common_len++;
-			}
-		}
-		
-		//Node add = new Node(null, common_len, maxKeyOctets);
-		//if (add == null)
-			//Another -ENOMEM;
-			//return null;
-		
-		//Creating a new Prefix with a prefix length of common_len
-		//Bits are copied from node's up until the common_len'th bit
-		//RibEntry is null, because this is an aggregate prefix - it's not
-		//actually been added to the trie.
-		
-		byte[] newPrefix = new byte[getByteContainingBit(maxPrefixLength)];
-		
-		int j;
-		for (j = 0; j < i; j++)
-			newPrefix[j] = node.prefix.getAddress()[j];
+            if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
+                node = node.right;
+            } else {
+                node = node.left;
+            }
+        }
 
-		if (boundary != 0)
-			newPrefix[j] = (byte)(node.prefix.getAddress()[j] & maskBits[common_len % 8]);
-		
-		//return new Node(new Prefix(newPrefix, common_len), null);
-		return new Node(new Prefix(newPrefix, common_len));
-		//return add;
-	}
-	
-	private class Node {
-		public Node parent = null;
-		public Node left = null;
-		public Node right = null;
-		
-		public final Prefix prefix;
-		public V value;
-		
-		//public Node(Prefix p, RibEntry r) {
-		//	this.prefix = p;
-		//	this.rib = r;
-		//}
-		public Node(Prefix p) {
-			this.prefix = p;
-		}
-		
-		public boolean isAggregate() {
-			return value == null;
-		}
-				
-		public Entry<V> getEntry() {
-			return new PatriciaTrieEntry(prefix, value);
-		}
-	}
-	
-	private class PatriciaTrieEntry implements Entry<V> {
-		private Prefix prefix;
-		private V value;
-		
-		public PatriciaTrieEntry(Prefix prefix, V value) {
-			this.prefix = prefix;
-			this.value = value;
-		}
-		
-		@Override
-		public Prefix getPrefix() {
-			return prefix;
-		}
-		
-		@Override
-		public V getValue() {
-			return value;
-		}
-	}
-	
-	private class PatriciaTrieIterator implements Iterator<Entry<V>> {
-		
-		private Node current;
-		private boolean started = false;
-		
-		public PatriciaTrieIterator(Node start) {
-			current = start;
-			
-			//If the start is an aggregate node fast forward to find the next valid node
-			if (current != null && current.isAggregate()) {
-				current = findNext(current);
-			}
-		}
+        Node add = null;
 
-		@Override
-		public boolean hasNext() {
-			if (current == null) {
-				return false;
-			}
-			
-			if (!started) {
-				return true;
-			}
-			
-			return findNext(current) != null;
-		}
+        if (node == null) {
+            //add = new Node(p, r);
+            add = new Node(prefix);
+            add.value = value;
 
-		@Override
-		public Entry<V> next() {
-			if (current == null) {
-				throw new NoSuchElementException();
-			}
-			
-			if (!started) {
-				started = true;
-				return current.getEntry();
-			}
-			
-			current = findNext(current);
-			if (current == null) {
-				throw new NoSuchElementException();
-			}
-			
-			return current.getEntry();
-		}
+            if (match != null) {
+                node_link(match, add);
+            } else {
+                top = add;
+            }
+        } else {
+            add = node_common(node, prefix.getAddress(), prefix.getPrefixLength());
+            if (add == null) {
+                //I think this is -ENOMEM?
+                //return null;
+            }
 
-		@Override
-		public void remove() {
-			// TODO This could be implemented, if it were needed
-			throw new NoSuchElementException();
-		}
-		
-		private Node findNext(Node node) {
-			Node next = null;
-			
-			if (node.left != null) {
-				next = node.left;
-				//addReference(next);
-				//delReference(node);
-				//return next;
-			}
-			else if (node.right != null) {
-				next = node.right;
-				//addReference(next);
-				//delReference(node);
-				//return next;
-			}
-			else {
-				//Node start = node;
-				while (node.parent != null) {
-					if (node.parent.left == node && node.parent.right != null) {
-						next = node.parent.right;
-						//addReference(next);
-						//delReference(start);
-						//return next;
-						break;
-					}
-					node = node.parent;
-				}
-			}
-			
-			if (next == null) {
-				return null;
-			}
-			
-			//If the node doesn't have a value, it's not an actual node, it's an artifically
-			//inserted aggregate node. We don't want to return these to the user.
-			if (next.isAggregate()) {
-				return findNext(next);
-			}
-			
-			return next;
-		}
-	}
+            if (match != null) {
+                node_link(match, add);
+            } else {
+                top = add;
+            }
+            node_link(add, node);
+
+            if (add.prefix.getPrefixLength() != prefix.getPrefixLength()) {
+                match = add;
+
+                //add = new Node(p, r);
+                add = new Node(prefix);
+                add.value = value;
+                node_link(match, add);
+            } else {
+                add.value = value;
+            }
+        }
+
+        //If we added a new Node, there was no previous mapping
+        return null;
+        //return addReference(add);
+    }
+
+    /*exact match*/
+    @Override
+    public synchronized V lookup(Prefix prefix) {
+        if (prefix.getPrefixLength() > maxPrefixLength) {
+            return null;
+        }
+
+        /*
+        Node node = top;
+
+        while (node != null
+                && node.prefix.getPrefixLength() <= p.getPrefixLength()
+                && key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), p.getAddress(), p.getPrefixLength()) == true) {
+            if (node.prefix.getPrefixLength() == p.getPrefixLength()) {
+                //return addReference(node);
+                return node.rib;
+            }
+
+            if (bit_check(p.getAddress(), node.prefix.getPrefixLength()) == true) {
+                node = node.right;
+            } else {
+                node = node.left;
+            }
+        }
+        */
+
+        Node node = findNode(prefix);
+
+        return node == null ? null : node.value;
+    }
+
+    /*closest containing prefix*/
+    @Override
+    public synchronized V match(Prefix prefix) {
+        //TODO
+        if (prefix.getPrefixLength() > maxPrefixLength) {
+            return null;
+        }
+
+        Node closestNode = findClosestNode(prefix);
+
+        return closestNode == null ? null : closestNode.value;
+    }
+
+    @Override
+    public synchronized boolean remove(Prefix prefix, V value) {
+        Node child;
+        Node parent;
+
+        if (prefix == null || value == null) {
+            return false;
+        }
+
+        Node node = findNode(prefix);
+
+        if (node == null || node.isAggregate() || !node.value.equals(value)) {
+            //Given <prefix, nexthop> mapping is not in the tree
+            return false;
+        }
+
+        if (node.left != null && node.right != null) {
+            //Remove the RibEntry entry and leave this node as an aggregate node
+            //In the future, maybe we should re-evaluate what the aggregate prefix should be?
+            //It shouldn't necessarily stay the same.
+            //More complicated if the above prefix is also aggregate.
+            node.value = null;
+            return true;
+        }
+
+        if (node.left != null) {
+            child = node.left;
+        } else {
+            child = node.right;
+        }
+
+        parent = node.parent;
+
+        if (child != null) {
+            child.parent = parent;
+        }
+
+        if (parent != null) {
+            if (parent.left == node) {
+                parent.left = child;
+            } else {
+                parent.right = child;
+            }
+        } else {
+            top = child;
+        }
+
+        /*
+         * TODO not sure what to do here. I think this is lazily deleting aggregate nodes,
+         * notice that it used to do nothing if it detected both children were not null earlier.
+         * But here, what we really should do is reevaluate the aggregate prefix of the parent
+         * node (if it is indeed an aggregate). Because at the moment, no aggregate node will ever
+         * be removed. BUT, I don't actually think this presents a correctness problem, at
+         * least from an external point of view.
+         */
+        //if (parent != null && parent.refCount == 0) {
+        //node_remove(parent);
+        //}
+
+        return true;
+    }
+
+    @Override
+    public Iterator<Entry<V>> iterator() {
+        return new PatriciaTrieIterator(top);
+    }
+
+    private Node findNode(Prefix prefix) {
+        Node node = top;
+
+        while (node != null
+                && node.prefix.getPrefixLength() <= prefix.getPrefixLength()
+                && key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
+            if (node.prefix.getPrefixLength() == prefix.getPrefixLength()) {
+                //return addReference(node);
+                return node;
+            }
+
+            if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
+                node = node.right;
+            } else {
+                node = node.left;
+            }
+        }
+
+        return null;
+    }
+
+    private Node findClosestNode(Prefix prefix) {
+        Node node = top;
+        Node match = null;
+
+        while (node != null
+                && node.prefix.getPrefixLength() <= prefix.getPrefixLength()
+                && key_match(node.prefix.getAddress(), node.prefix.getPrefixLength(), prefix.getAddress(), prefix.getPrefixLength()) == true) {
+            if (!node.isAggregate()) {
+                match = node;
+            }
+
+            if (bit_check(prefix.getAddress(), node.prefix.getPrefixLength()) == true) {
+                node = node.right;
+            } else {
+                node = node.left;
+            }
+        }
+
+        return match;
+    }
+
+    /*
+     * Receives a 1-based bit index
+     * Returns a 1-based byte index
+     * eg. (0 => 1), 1 => 1, 8 => 1, 9 => 2, 17 => 3
+     */
+    private int getByteContainingBit(int bitNumber) {
+        return Math.max((bitNumber + 7) / 8, 1);
+    }
+
+    private boolean key_match(byte[] key1, int key1_len, byte[] key2, int key2_len) {
+        //int offset;
+        //int shift;
+
+        if (key1_len > key2_len) {
+            return false;
+        }
+
+        int offset = (Math.min(key1_len, key2_len)) / 8;
+        int shift = (Math.min(key1_len, key2_len)) % 8;
+
+        if (shift != 0) {
+            if ((maskBits[shift] & (key1[offset] ^ key2[offset])) != 0) {
+                return false;
+            }
+        }
+
+        while (offset != 0) {
+            offset--;
+            if (key1[offset] != key2[offset]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean bit_check(byte[] key, int key_bits) {
+        int offset = key_bits / 8;
+        int shift = 7 - (key_bits % 8);
+        int bit = key[offset] & 0xff;
+
+        bit >>= shift;
+
+        if ((bit & 1) == 1) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private void node_link(Node node, Node add) {
+        boolean bit = bit_check(add.prefix.getAddress(), node.prefix.getPrefixLength());
+
+        if (bit == true) {
+            node.right = add;
+        } else {
+            node.left = add;
+        }
+        add.parent = node;
+    }
+
+    private Node node_common(Node node, byte[] key, int key_bits) {
+        int i;
+        int limit = Math.min(node.prefix.getPrefixLength(), key_bits) / 8;
+
+        for (i = 0; i < limit; i++) {
+            if (node.prefix.getAddress()[i] != key[i]) {
+                break;
+            }
+        }
+
+        int common_len = i * 8;
+        int boundary = 0;
+
+        if (common_len != key_bits) {
+            byte diff = (byte) (node.prefix.getAddress()[i] ^ key[i]);
+            byte mask = (byte) 0x80;
+            int shift_mask = 0;
+
+            while (common_len < key_bits && ((mask & diff) == 0)) {
+                boundary = 1;
+
+                shift_mask = (mask & 0xff);
+                shift_mask >>= 1;
+                mask = (byte) shift_mask;
+
+                common_len++;
+            }
+        }
+
+        //Node add = new Node(null, common_len, maxKeyOctets);
+        //if (add == null)
+        //Another -ENOMEM;
+        //return null;
+
+        //Creating a new Prefix with a prefix length of common_len
+        //Bits are copied from node's up until the common_len'th bit
+        //RibEntry is null, because this is an aggregate prefix - it's not
+        //actually been added to the trie.
+
+        byte[] newPrefix = new byte[getByteContainingBit(maxPrefixLength)];
+
+        int j;
+        for (j = 0; j < i; j++)
+            newPrefix[j] = node.prefix.getAddress()[j];
+
+        if (boundary != 0)
+            newPrefix[j] = (byte) (node.prefix.getAddress()[j] & maskBits[common_len % 8]);
+
+        //return new Node(new Prefix(newPrefix, common_len), null);
+        return new Node(new Prefix(newPrefix, common_len));
+        //return add;
+    }
+
+    private class Node {
+        public Node parent = null;
+        public Node left = null;
+        public Node right = null;
+
+        public final Prefix prefix;
+        public V value;
+
+        //public Node(Prefix p, RibEntry r) {
+        //      this.prefix = p;
+        //      this.rib = r;
+        //}
+        public Node(Prefix p) {
+            this.prefix = p;
+        }
+
+        public boolean isAggregate() {
+            return value == null;
+        }
+
+        public Entry<V> getEntry() {
+            return new PatriciaTrieEntry(prefix, value);
+        }
+    }
+
+    private class PatriciaTrieEntry implements Entry<V> {
+        private Prefix prefix;
+        private V value;
+
+        public PatriciaTrieEntry(Prefix prefix, V value) {
+            this.prefix = prefix;
+            this.value = value;
+        }
+
+        @Override
+        public Prefix getPrefix() {
+            return prefix;
+        }
+
+        @Override
+        public V getValue() {
+            return value;
+        }
+    }
+
+    private class PatriciaTrieIterator implements Iterator<Entry<V>> {
+
+        private Node current;
+        private boolean started = false;
+
+        public PatriciaTrieIterator(Node start) {
+            current = start;
+
+            //If the start is an aggregate node fast forward to find the next valid node
+            if (current != null && current.isAggregate()) {
+                current = findNext(current);
+            }
+        }
+
+        @Override
+        public boolean hasNext() {
+            if (current == null) {
+                return false;
+            }
+
+            if (!started) {
+                return true;
+            }
+
+            return findNext(current) != null;
+        }
+
+        @Override
+        public Entry<V> next() {
+            if (current == null) {
+                throw new NoSuchElementException();
+            }
+
+            if (!started) {
+                started = true;
+                return current.getEntry();
+            }
+
+            current = findNext(current);
+            if (current == null) {
+                throw new NoSuchElementException();
+            }
+
+            return current.getEntry();
+        }
+
+        @Override
+        public void remove() {
+            // TODO This could be implemented, if it were needed
+            throw new NoSuchElementException();
+        }
+
+        private Node findNext(Node node) {
+            Node next = null;
+
+            if (node.left != null) {
+                next = node.left;
+                //addReference(next);
+                //delReference(node);
+                //return next;
+            } else if (node.right != null) {
+                next = node.right;
+                //addReference(next);
+                //delReference(node);
+                //return next;
+            } else {
+                //Node start = node;
+                while (node.parent != null) {
+                    if (node.parent.left == node && node.parent.right != null) {
+                        next = node.parent.right;
+                        //addReference(next);
+                        //delReference(start);
+                        //return next;
+                        break;
+                    }
+                    node = node.parent;
+                }
+            }
+
+            if (next == null) {
+                return null;
+            }
+
+            //If the node doesn't have a value, it's not an actual node, it's an artifically
+            //inserted aggregate node. We don't want to return these to the user.
+            if (next.isAggregate()) {
+                return findNext(next);
+            }
+
+            return next;
+        }
+    }
 }
