changeset 4:761d04aecfcb

added Graph API and some implementation
author shoshi <shoshi@cr.ie.u-ryukyu.ac.jp>
date Tue, 19 Jun 2012 23:38:31 +0900
parents 9eb9fabd9f29
children 07b26b4b21e0
files memo.txt pom.xml src/main/java/jungle/core/Jungle.java src/main/java/jungle/core/graph/Graph.java src/main/java/jungle/core/graph/Vertex.java src/main/java/jungle/core/graph/Vertexes.java src/main/java/jungle/core/graph/simple/SimpleGraph.java src/main/java/jungle/core/graph/simple/SimpleVertex.java src/main/java/jungle/core/graph/simple/SimpleVertexes.java src/main/java/jungle/core/table/PropertySequence.java src/main/java/jungle/core/table/Record.java src/main/java/jungle/core/table/Table.java src/main/java/jungle/core/table/simple/SimplePropertySequence.java src/main/java/jungle/core/table/simple/SimpleRecord.java src/main/java/jungle/core/table/simple/SimpleTable.java src/main/java/jungle/impl/SimpleChildren.java src/main/java/jungle/impl/SimpleJungle.java src/main/java/jungle/impl/SimpleTree.java src/main/java/jungle/impl/SimpleTreeGroup.java src/main/java/jungle/impl/SimpleTreeNode.java src/main/java/jungle/impl/Simples.java src/test/java/jungle/core/graph/AbstractGraphTest.java src/test/java/jungle/core/graph/AbstractVertexTest.java src/test/java/jungle/core/graph/AbstractVertexesTest.java src/test/java/jungle/core/graph/simple/SimpleGraphTest.java src/test/java/jungle/core/graph/simple/SimpleVertexTest.java src/test/java/jungle/core/graph/simple/SimpleVertexesTest.java src/test/java/jungle/core/table/AbstractPropertySequenceTestTemplate.java src/test/java/jungle/core/table/AbstractRecordTestTemplate.java src/test/java/jungle/core/table/AbstractTableTestTemplate.java src/test/java/jungle/core/table/simple/SimplePropertySequenceTest.java src/test/java/jungle/misc/fj/ImmutableListExample.java src/test/java/jungle/misc/fj/ImmutableSetExample.java
diffstat 33 files changed, 1337 insertions(+), 101 deletions(-) [+]
line wrap: on
line diff
--- a/memo.txt	Wed Jun 13 01:29:02 2012 +0900
+++ b/memo.txt	Tue Jun 19 23:38:31 2012 +0900
@@ -21,4 +21,23 @@
   ・ Node : Record の Property で Attribute を表現
   ・ TreeGroup : Node で表すべき?
   ・ Tree : TreeNode を継承している よって Node で表す、 Children や Links は PropertySequence による.
-  ・ Link : Node で表す。
\ No newline at end of file
+  ・ Link : Node で表す。
+  
+2012/06/15
+ ・Functional Java を使って PropertySequence を実装するといいかも?
+ ・Record , PropertySequence の hashCode , equals の実装について、ちゃんとテストを作ること!(重要)
+ ・なるべく、equals と hashCode はオーバーライドしないようにする、独自の比較メソッドを提供する。
+ ・Table , Record , PropertySequence に Atomic なオペレーションを追加する
+  ・Table は Record の作成に CAS を追加する
+  ・Record は Map と PropertySequence に CAS を追加する。
+  ・PropertySequence は・・・いらないか・・
+  ・Jungle の API から getTreeGroups を削除した
+  ・Table , Record , PropertySequence では足りない、もっと美味いやりかたがあるはず
+  
+2012/06/19
+ ・Graph API を定義することにした
+  ・ Graph , Vertex , Vertexes
+ ・Neo4j で言うと
+  ・ GraphDB , Node , Iterator<Relationship>
+ ・とりあえずこれで実装してみる。
+ ・今日は、SimpleVertexes をほぼ完成させた、あとすこしとテストコードを追加すること。
\ No newline at end of file
--- a/pom.xml	Wed Jun 13 01:29:02 2012 +0900
+++ b/pom.xml	Tue Jun 19 23:38:31 2012 +0900
@@ -36,6 +36,11 @@
     	<artifactId>jpf</artifactId>
     	<version>1.5</version>
     </dependency>
+    <dependency>
+    	<groupId>org.functionaljava</groupId>
+    	<artifactId>functionaljava</artifactId>
+    	<version>3.1</version>
+    </dependency>
   </dependencies>
   <build>
   	<plugins>
--- a/src/main/java/jungle/core/Jungle.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/core/Jungle.java	Tue Jun 19 23:38:31 2012 +0900
@@ -3,5 +3,4 @@
 public interface Jungle
 {
 	TreeGroup createTreeGroup();
-	Iterable<TreeGroup> treeGroups();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jungle/core/graph/Graph.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,13 @@
+package jungle.core.graph;
+
+import java.util.Iterator;
+
+public interface Graph
+{
+	public Vertex getVertex(String _id);
+	public Vertex createVertex(String _id);
+	public Vertex createVertex();
+	
+	public boolean isSame(Graph _g);
+	public Iterator<Vertex> vertexes();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jungle/core/graph/Vertex.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,16 @@
+package jungle.core.graph;
+
+public interface Vertex
+{
+	public String getID();
+	public Graph getGraph();
+	
+	public String getProperty(String _key);
+	public void setProperty(String _key,String _value);
+	public String removeProperty(String _key);
+	public boolean compareAndSwapProprety(String _key,String _except,String _value);
+	
+	public Vertexes removeVertexes(String _type);
+	public Vertexes getVertexes(String _type);
+	public Vertexes createVertexes(String _type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jungle/core/graph/Vertexes.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,28 @@
+package jungle.core.graph;
+
+import java.util.Collection;
+
+public interface Vertexes extends Iterable<Vertex>
+{
+	public int size();
+	public Vertex at(int _i);
+	
+	public void add(Vertex _v);
+	public void add(Vertex _v,int _i);
+	public void add(Collection<Vertex> _vs);
+	public void add(Vertexes _vs);
+	
+	public void removeFirst(Vertex _v);
+	public void removeFirst(Collection<Vertex> _vs);
+	public void removeFirst(Vertexes _vs);
+	public void remove(int _i);
+	
+	public void replace(Vertex _v,int _i);
+	public void replaceFirst(Vertex _vertex,Vertex _newVertex);
+	
+	public boolean compareAndSwap(int _index,Vertex _vertex,Vertex _newVertex);
+	public boolean contains(Vertex _v);
+	
+	public Graph getGraph();
+	public String type();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jungle/core/graph/simple/SimpleGraph.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,83 @@
+package jungle.core.graph.simple;
+
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import jungle.core.graph.Graph;
+import jungle.core.graph.Vertex;
+
+public class SimpleGraph implements Graph
+{
+	private final AtomicLong ids;
+	private final ConcurrentHashMap<String,SimpleVertex> vertexes;
+	
+	public SimpleGraph()
+	{
+		ids = new AtomicLong(0);
+		vertexes = new ConcurrentHashMap<String,SimpleVertex>();
+	}
+
+	@Override
+	public Vertex createVertex()
+	{
+		SimpleVertex vertex,newVertex;
+		do{
+			String id = Long.toString(ids.getAndIncrement());
+			newVertex = new SimpleVertex(this,id);
+			vertex = vertexes.putIfAbsent(id,newVertex);
+		}while(vertex != null);
+		
+		return newVertex;
+	}
+	
+	@Override
+	public boolean isSame(Graph _g)
+	{
+		if(_g instanceof SimpleGraph){
+			return _g == this;
+		}
+		
+		return false;
+	}
+	
+	@Override
+	public Vertex createVertex(String _id)
+	{
+		SimpleVertex vertex = new SimpleVertex(this,_id);
+		SimpleVertex value = vertexes.putIfAbsent(_id,vertex);
+		return value != null ? value : vertex;
+	}
+	
+	@Override
+	public Vertex getVertex(String _id)
+	{
+		return vertexes.get(_id);
+	}
+
+	@Override
+	public Iterator<Vertex> vertexes()
+	{
+		final Iterator<SimpleVertex> itr = vertexes.values().iterator();
+		Iterator<Vertex> wrapper = new Iterator<Vertex>(){
+			@Override
+			public boolean hasNext()
+			{
+				return itr.hasNext();
+			}
+
+			@Override
+			public Vertex next()
+			{
+				return itr.next();
+			}
+
+			@Override
+			public void remove()
+			{
+				throw new UnsupportedOperationException("remove is not supported");
+			}
+		};
+		return wrapper;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jungle/core/graph/simple/SimpleVertex.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,85 @@
+package jungle.core.graph.simple;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import jungle.core.graph.Graph;
+import jungle.core.graph.Vertex;
+import jungle.core.graph.Vertexes;
+
+public class SimpleVertex implements Vertex
+{
+	private String id;
+	private final SimpleGraph parent;
+	private final ConcurrentHashMap<String,String> properties;
+	private final ConcurrentHashMap<String,SimpleVertexes> relations;
+	
+	public SimpleVertex(SimpleGraph _parent,String _id)
+	{
+		id = _id;
+		parent = _parent;
+		properties = new ConcurrentHashMap<String,String>();
+		relations = new ConcurrentHashMap<String,SimpleVertexes>();
+	}
+	
+	void setID(String _id)
+	{
+		id = _id;
+	}
+	
+	@Override
+	public String getID()
+	{
+		return id;
+	}
+
+	@Override
+	public String getProperty(String _key)
+	{
+		return properties.get(_key);
+	}
+
+	@Override
+	public void setProperty(String _key, String _value)
+	{
+		properties.put(_key,_value);
+	}
+
+	@Override
+	public String removeProperty(String _key)
+	{
+		return properties.remove(_key);
+	}
+
+	@Override
+	public Vertexes getVertexes(String _key)
+	{
+		return relations.get(_key);
+	}
+	
+	@Override
+	public Vertexes removeVertexes(String _type)
+	{
+		SimpleVertexes vertexes = relations.remove(_type);
+		return vertexes;
+	}
+
+	@Override
+	public boolean compareAndSwapProprety(String _key, String _except,String _value)
+	{
+		return properties.replace(_key,_except,_value);
+	}
+	
+	@Override
+	public Graph getGraph()
+	{
+		return parent;
+	}
+
+	@Override
+	public Vertexes createVertexes(String _type)
+	{
+		SimpleVertexes vertexes = new SimpleVertexes(_type,parent);
+		SimpleVertexes result = relations.putIfAbsent(_type,vertexes);
+		return result == null ? vertexes : null;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jungle/core/graph/simple/SimpleVertexes.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,376 @@
+package jungle.core.graph.simple;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicReference;
+
+import fj.Equal;
+import fj.F;
+import fj.P2;
+import fj.data.List;
+
+import jungle.core.graph.Graph;
+import jungle.core.graph.Vertex;
+import jungle.core.graph.Vertexes;
+
+public class SimpleVertexes implements Vertexes
+{
+	private final String type;
+	private final AtomicReference<List<SimpleVertex>> vertexes;
+	private final SimpleGraph parent;
+	
+	public SimpleVertexes(String _type,SimpleGraph _parent)
+	{
+		parent = _parent;
+		type = _type;
+		List<SimpleVertex> nil = List.nil();
+		vertexes = new AtomicReference<List<SimpleVertex>>(nil);
+	}
+	
+	@Override
+	public void remove(final int _index)
+	{
+		List<SimpleVertex> current = null,update = null;
+		do{
+			final List<SimpleVertex> list = vertexes.get();
+			update = List.iterableList(new Iterable<SimpleVertex>(){
+				@Override
+				public Iterator<SimpleVertex> iterator() {
+					return new Iterator<SimpleVertex>(){
+						int count = 0;
+						Iterator<SimpleVertex> itr = list.iterator();
+
+						@Override
+						public boolean hasNext()
+						{
+							if(itr.hasNext() && count + 1 == _index){
+								itr.next();
+							}
+							
+							count ++;
+							return itr.hasNext();
+						}
+
+						@Override
+						public SimpleVertex next()
+						{
+							return itr.next();
+						}
+
+						@Override
+						public void remove()
+						{
+							throw new UnsupportedOperationException("removeing is not supported.");
+						}
+					};
+				}
+			});
+		}while(!vertexes.compareAndSet(current,update));
+	}
+
+	@Override
+	public int size()
+	{
+		return vertexes.get().length();
+	}
+	
+	@Override
+	public Graph getGraph()
+	{
+		return parent;
+	}
+
+	@Override
+	public void add(Vertex _v)
+	{
+		if(_v.getGraph() != parent){
+			throw new IllegalArgumentException("Vertex _v is not belongs to same graph");
+		}
+		
+		if(!(_v instanceof SimpleVertex)){
+			throw new IllegalArgumentException("Vertex _v is not instanceof SimpleVertex");
+		}
+		
+		List<SimpleVertex> cur,update;
+		do{
+			cur = vertexes.get();
+			update = cur.append(List.list((SimpleVertex)_v));
+		}while(!vertexes.compareAndSet(cur,update));
+	}
+	
+	@Override
+	public void add(Vertexes _vs)
+	{
+		if(!(_vs instanceof SimpleVertexes)){
+			throw new IllegalArgumentException("Vertexes _vs is not instanceof SimpleVertex");
+		}
+		
+		List<SimpleVertex> list = ((SimpleVertexes)_vs).vertexes.get();
+		
+		List<SimpleVertex> cur,update;
+		do{
+			cur = vertexes.get();
+			update = cur.append(list);
+		}while(!vertexes.compareAndSet(cur,update));
+	}
+	
+	@Override
+	public boolean contains(final Vertex _v)
+	{
+		if(_v.getGraph() == parent){
+			throw new IllegalArgumentException("Vertex _v is not a number of graph");
+		}
+		
+		List<SimpleVertex> list = vertexes.get();
+		F<SimpleVertex,Boolean> predicate = new F<SimpleVertex,Boolean>(){
+			@Override
+			public Boolean f(SimpleVertex _target)
+			{
+				return _v == _target;
+			}
+		};
+		
+		return list.exists(predicate);
+	}
+	
+	@Override
+	public Iterator<Vertex> iterator()
+	{
+		List<SimpleVertex> list = vertexes.get();
+		final Iterator<SimpleVertex> itr = list.iterator();
+		Iterator<Vertex> wrapper = new Iterator<Vertex>(){
+
+			@Override
+			public boolean hasNext()
+			{
+				return itr.hasNext();
+			}
+
+			@Override
+			public Vertex next()
+			{
+				return itr.next();
+			}
+
+			@Override
+			public void remove()
+			{
+				throw new UnsupportedOperationException("removing is not supported");
+			}
+		};
+		
+		return wrapper;
+	}
+	
+	@Override
+	public String type()
+	{
+		return type;
+	}
+	
+	public static Equal<SimpleVertex> VERTEX_EQUAL = Equal.equal(
+		new F<SimpleVertex,F<SimpleVertex,Boolean>>(){
+			@Override
+			public F<SimpleVertex, Boolean> f(final SimpleVertex _v1){
+				return new F<SimpleVertex,Boolean>(){
+					@Override
+					public Boolean f(SimpleVertex _v2){
+						return _v1 == _v2;
+					}
+				};
+			}
+		});
+
+	@Override
+	public void removeFirst(final Vertex _v)
+	{
+		if(_v == null){
+			throw new NullPointerException("_v is null");
+		}
+		
+		if(_v instanceof SimpleVertex){
+			SimpleGraph g = (SimpleGraph)_v.getGraph();
+			if(g != parent){
+				throw new IllegalArgumentException("_v is not a part of graph");
+			}
+		}else{
+			throw new IllegalArgumentException("_v is not instanceof SimpleVertex it was " + _v.getClass().getName());
+		}
+		
+		List<SimpleVertex> list,update;
+		do{
+			list = vertexes.get();
+			update = list.delete((SimpleVertex)_v,VERTEX_EQUAL);
+		}while(!vertexes.compareAndSet(list,update));
+	}
+	
+	public Collection<Vertex> toCollection()
+	{
+		Collection<? extends Vertex> c = vertexes.get().toCollection();
+		return Collections.unmodifiableCollection(c);
+	}
+
+	@Override
+	public void removeFirst(Vertexes _vs)
+	{
+		if(_vs instanceof SimpleVertexes){
+			Collection<Vertex> vs = ((SimpleVertexes)_vs).toCollection();
+			removeFirst(vs);
+		}
+	}
+	
+	@Override
+	public void removeFirst(final Collection<Vertex> _vs)
+	{
+		if(_vs == null){
+			throw new NullPointerException("_vs is null");
+		}
+		
+		final HashSet<Vertex> tmp = new HashSet<Vertex>(_vs);
+		F<SimpleVertex,Boolean> predicate = new F<SimpleVertex,Boolean>(){
+			@Override
+			public Boolean f(SimpleVertex _target)
+			{
+				return tmp.remove(_target);
+			}
+		};
+		
+		List<SimpleVertex> list,update;
+		do{
+			list = vertexes.get();
+			update = list.removeAll(predicate);
+		}while(!vertexes.compareAndSet(list,update));
+	}
+
+	@Override
+	public Vertex at(int _index)
+	{
+		List<SimpleVertex> list = vertexes.get();
+		
+		if(list.length() < _index){
+			throw new IndexOutOfBoundsException("vertex.length() < _index");
+		}
+		
+		return list.take(_index).last();
+	}
+
+	@Override
+	public void add(Vertex _v, int _index)
+	{
+		
+		if(_v instanceof SimpleVertex){
+			throw new IllegalArgumentException("_v is not a SimpleVertex");
+		}
+		
+		
+		List<SimpleVertex> list = null,update = null;
+		do{
+			list = vertexes.get();
+			if(list.length() < _index){
+				throw new IndexOutOfBoundsException("vertex.length() < _index");
+			}
+			P2<List<SimpleVertex>,List<SimpleVertex>> slice = list.splitAt(_index);
+			
+			update = slice._1().snoc((SimpleVertex)_v).append(slice._2());
+		}while(!vertexes.compareAndSet(list,update));
+	}
+
+	@Override
+	public void add(Collection<Vertex> _vs)
+	{
+		final Iterator<Vertex> itr = _vs.iterator();
+		Iterable<SimpleVertex> wrapper = new Iterable<SimpleVertex>(){
+			@Override
+			public Iterator<SimpleVertex> iterator() {
+				return new Iterator<SimpleVertex>(){
+					@Override
+					public boolean hasNext(){
+						return itr.hasNext();
+					}
+					@Override
+					public SimpleVertex next(){
+						Vertex v = itr.next();
+						if(!(v instanceof SimpleVertex)){
+							throw new IllegalArgumentException("_vs is including not a SimpleVertex instance.");
+						}
+						
+						if(v.getGraph() == parent){
+							throw new IllegalArgumentException("_vs has vertex from other graph instance");
+						}
+						return (SimpleVertex)v;
+					}
+					@Override
+					public void remove(){
+						throw new UnsupportedOperationException("removeing is not supported.");
+					}
+				};
+			}
+		};
+		
+		List<SimpleVertex> a = List.iterableList(wrapper);
+		
+		List<SimpleVertex> current = null,update = null;
+		do{
+			current = vertexes.get();
+			update = current.append(a);
+		}while(!vertexes.compareAndSet(current,update));
+	}
+
+	@Override
+	public void replace(Vertex _v, int _index)
+	{
+		if(_v == null){
+			throw new NullPointerException("_v is null");
+		}
+		
+		if(!(_v instanceof SimpleVertex)){
+			throw new IllegalArgumentException("_v is not a instanceof SimpleVertex");
+		}
+		
+		List<SimpleVertex> current = null,update = null;
+		do{
+			current = vertexes.get();
+			if(current.length() < _index){
+				throw new IndexOutOfBoundsException("current.length() < _index");
+			}
+		
+			P2<List<SimpleVertex>,List<SimpleVertex>> slice = current.splitAt(_index);
+			update = slice._1().snoc((SimpleVertex)_v).append(slice._2().drop(1));
+		}while(!vertexes.compareAndSet(current,update));
+	}
+
+	@Override
+	public void replaceFirst(final Vertex _vertex, Vertex _newVertex)
+	{
+		if(_vertex == null || _newVertex == null){
+			throw new NullPointerException("_vertex or _newVertex is null");
+		}
+		
+		if(!(_vertex instanceof SimpleVertex) || !(_newVertex instanceof SimpleVertex)){
+			throw new IllegalArgumentException("_v is not a instanceof SimpleVertex");
+		}
+		
+		F<SimpleVertex,Boolean> predicate = new F<SimpleVertex,Boolean>(){
+			@Override
+			public Boolean f(SimpleVertex _vertex2){
+				return _vertex != _vertex2;
+			}
+		};
+		
+		List<SimpleVertex> current = null,update = null;
+		do{
+			P2<List<SimpleVertex>,List<SimpleVertex>> slice = current.span(predicate);
+			if(slice._2().length() != 0){
+				//TODO , next day write here.
+			}
+		}while(!vertexes.compareAndSet(current,update));
+	}
+
+	@Override
+	public boolean compareAndSwap(int _index, Vertex _vertex, Vertex _newVertex)
+	{
+		return false;
+	}
+}
--- a/src/main/java/jungle/core/table/PropertySequence.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/core/table/PropertySequence.java	Tue Jun 19 23:38:31 2012 +0900
@@ -5,5 +5,6 @@
 	public void add(String _value);
 	public String get(int _pos);
 	public String remove(int _pos);
+	public boolean isSameSequence(PropertySequence _seq);
 	public int size();
 }
--- a/src/main/java/jungle/core/table/Record.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/core/table/Record.java	Tue Jun 19 23:38:31 2012 +0900
@@ -12,7 +12,14 @@
 	public PropertySequence createSequence(String _key);
 	public PropertySequence getSequence(String _key);
 	public PropertySequence removeSequence(String _key);
+	public void setSequence(String _key,PropertySequence _seq);
 	
 	public Iterator<Pair<String,String>> properties();
 	public Iterator<Pair<String,PropertySequence>> sequences();
+	
+	/*
+	 * for concurrent purpose
+	 */
+	public boolean compareAndSwapProperty(String _key,String _expect,String _value);
+	public PropertySequence createSequenceIfAbsent(String _key);
 }
--- a/src/main/java/jungle/core/table/Table.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/core/table/Table.java	Tue Jun 19 23:38:31 2012 +0900
@@ -5,4 +5,6 @@
 	public Record create(String _key);
 	public Record find(String _key);
 	public Record remove(String _key);
+	
+	public Record findAndCreateIfNotExist(String _key);
 }
--- a/src/main/java/jungle/core/table/simple/SimplePropertySequence.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/core/table/simple/SimplePropertySequence.java	Tue Jun 19 23:38:31 2012 +0900
@@ -3,6 +3,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import javax.annotation.concurrent.ThreadSafe;
 
@@ -19,6 +20,12 @@
 		sequence = new CopyOnWriteArrayList<String>();
 		readonlyWrapper = Collections.unmodifiableCollection(sequence);
 	}
+	
+	private SimplePropertySequence(List<String> _copyTarget)
+	{
+		sequence = new CopyOnWriteArrayList<String>(_copyTarget);
+		readonlyWrapper = Collections.unmodifiableCollection(sequence);
+	}
 
 	@Override
 	public Iterator<String> iterator()
@@ -29,6 +36,10 @@
 	@Override
 	public void add(String _value)
 	{
+		if(_value == null){
+			throw new NullPointerException("_value == null");
+		}
+		
 		sequence.add(_value);
 	}
 
@@ -49,5 +60,38 @@
 	{
 		return sequence.size();
 	}
+	
+	public boolean isSameSequence(PropertySequence _obj)
+	{
+		// suspicious
+		if(_obj instanceof PropertySequence){
+			PropertySequence seq = (PropertySequence)_obj;
+			if(seq.size() != size()){
+				return false;
+			}
+			
+			Iterator<String> itr1 = seq.iterator();
+			Iterator<String> itr2 = this.iterator();
+			
+			while(itr1.hasNext() && itr2.hasNext()){
+				String s1 = itr1.next();
+				String s2 = itr2.next();
+				
+				if(!s1.equals(s2)){
+					return false;
+				}
+			}
+		
+			if(itr1.hasNext() == itr2.hasNext()){
+				return true;
+			}
+		}
+		
+		return false;
+	}
 
+	SimplePropertySequence snapshot()
+	{
+		return new SimplePropertySequence(sequence);
+	}
 }
\ No newline at end of file
--- a/src/main/java/jungle/core/table/simple/SimpleRecord.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/core/table/simple/SimpleRecord.java	Tue Jun 19 23:38:31 2012 +0900
@@ -15,12 +15,12 @@
 public class SimpleRecord implements Record
 {
 	private final ConcurrentHashMap<String,String> properties;
-	private final ConcurrentHashMap<String,PropertySequence> sequences;
+	private final ConcurrentHashMap<String,SimplePropertySequence> sequences;
 	
 	public SimpleRecord()
 	{
 		properties = new ConcurrentHashMap<String,String>();
-		sequences = new ConcurrentHashMap<String,PropertySequence>();
+		sequences = new ConcurrentHashMap<String,SimplePropertySequence>();
 	}
 
 	@Override
@@ -60,6 +60,14 @@
 	{
 		return sequences.remove(_key);
 	}
+	
+	@Override
+	public void setSequence(String _key,PropertySequence _seq)
+	{
+		if(_seq instanceof SimplePropertySequence){
+			
+		}
+	}
 
 	@Override
 	public Iterator<Pair<String, String>> properties()
@@ -92,8 +100,8 @@
 	@Override
 	public Iterator<Pair<String, PropertySequence>> sequences()
 	{
-		final Set<Entry<String,PropertySequence>> entries = sequences.entrySet();
-		final Iterator<Entry<String,PropertySequence>> itr = entries.iterator();
+		final Set<Entry<String,SimplePropertySequence>> entries = sequences.entrySet();
+		final Iterator<Entry<String,SimplePropertySequence>> itr = entries.iterator();
 		return new Iterator<Pair<String,PropertySequence>>(){
 
 			@Override
@@ -105,7 +113,7 @@
 			@Override
 			public Pair<String, PropertySequence> next()
 			{
-				Entry<String,PropertySequence> ent = itr.next();
+				Entry<String,SimplePropertySequence> ent = itr.next();
 				return new Pair<String,PropertySequence> (ent.getKey(),ent.getValue());
 			}
 
@@ -116,4 +124,18 @@
 			}
 		};
 	}
+
+	@Override
+	public boolean compareAndSwapProperty(String _key, String _expect,String _value)
+	{
+		return properties.replace(_key,_expect,_value);
+	}
+
+	@Override
+	public PropertySequence createSequenceIfAbsent(String _key)
+	{
+		SimplePropertySequence seq = new SimplePropertySequence();
+		SimplePropertySequence old = sequences.putIfAbsent(_key,seq);
+		return old != null ? old : seq;
+	}
 }
--- a/src/main/java/jungle/core/table/simple/SimpleTable.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/core/table/simple/SimpleTable.java	Tue Jun 19 23:38:31 2012 +0900
@@ -7,11 +7,11 @@
 
 public class SimpleTable implements Table
 {
-	private final ConcurrentHashMap<String,Record> table;
+	private final ConcurrentHashMap<String,SimpleRecord> table;
 	
 	public SimpleTable()
 	{
-		table = new ConcurrentHashMap<String,Record>();
+		table = new ConcurrentHashMap<String,SimpleRecord>();
 	}
 
 	@Override
@@ -33,4 +33,12 @@
 	{
 		return table.remove(_key);
 	}
+
+	@Override
+	public Record findAndCreateIfNotExist(String _key)
+	{
+		SimpleRecord r = new SimpleRecord();
+		SimpleRecord find = table.putIfAbsent(_key,r);
+		return find != null ? find : r;
+	}
 }
--- a/src/main/java/jungle/impl/SimpleChildren.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/impl/SimpleChildren.java	Tue Jun 19 23:38:31 2012 +0900
@@ -11,7 +11,7 @@
 {
 	private final OrderedNodeSet<TreeNode> sets;
 	
-	public SimpleChildren()
+	public SimpleChildren(PropertySequence _seq)
 	{
 		this(new SimpleOrderedNodeSet<TreeNode>());
 	}
--- a/src/main/java/jungle/impl/SimpleJungle.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/impl/SimpleJungle.java	Tue Jun 19 23:38:31 2012 +0900
@@ -1,31 +1,25 @@
 package jungle.impl;
 
-import java.util.Collections;
 import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-
 import jungle.core.Jungle;
 import jungle.core.TreeGroup;
+import jungle.core.table.Record;
+import jungle.core.table.Table;
 
 public class SimpleJungle implements Jungle
 {
-	private final ConcurrentHashMap<String,TreeGroup> treeGroups;
+	private final Table tb;
 	
-	public SimpleJungle()
+	public SimpleJungle(Table _tb)
 	{
-		treeGroups = new ConcurrentHashMap<String,TreeGroup>();
+		tb = _tb;
 	}
 
 	public TreeGroup createTreeGroup()
 	{
-		String tid = UUID.randomUUID().toString();
-		SimpleTreeGroup g = new SimpleTreeGroup(tid);
-		treeGroups.put(tid,g);
-		return g;
-	}
-
-	public Iterable<TreeGroup> treeGroups()
-	{
-		return Collections.unmodifiableCollection(treeGroups.values());
+		String groupID = UUID.randomUUID().toString();
+		Record tg = tb.create(groupID);
+		
+		return new SimpleTreeGroup(groupID,tg,tb);
 	}
 }
--- a/src/main/java/jungle/impl/SimpleTree.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/impl/SimpleTree.java	Tue Jun 19 23:38:31 2012 +0900
@@ -6,27 +6,24 @@
 import jungle.core.Links;
 import jungle.core.Tree;
 import jungle.core.TreeGroup;
+import jungle.core.table.Record;
 
 public class SimpleTree implements Tree
 {
-	private final String tid;
-	private final Attributes attrs;
-	private final Children children;
-	private final Links links;
+	private final String treeID;
 	private final TreeGroup group;
+	private final Record record;
 	
-	public SimpleTree(String _tid,TreeGroup _group)
+	private final SimpleChildren children;
+	private final SimpleLinks links;
+	
+	public SimpleTree(TreeGroup _group,String _treeID,Record _r)
 	{
-		this(_tid,_group,Simples.EMPTY_ATTRIBUTES,Simples.EMPTY_CHILDREN,Simples.EMPTY_LINKS);
-	}
-	
-	public SimpleTree(String _tid,TreeGroup _group,Attributes _attrs,Children _children,Links _links)
-	{
-		tid = _tid;
-		attrs = _attrs;
-		children = _children;
-		links = _links;
+		treeID = _treeID;
 		group = _group;
+		record = _r;
+		children = new SimpleChildren(_r.createSequenceIfAbsent(Simples.TREENODE_CHILDREN_KEY));
+		links = new SimpleLinks(_r.createSequenceIfAbsent(Simples.TREENODE_LINKS_KEY));
 	}
 	
 	public TreeGroup getGroup()
@@ -36,12 +33,12 @@
 	
 	public String get(String _key)
 	{
-		return attrs.get(_key);
+		return record.getProperty(Simples.PROPERTY_KEY_PREFIX+_key);
 	}
 
 	public String treeID()
 	{
-		return tid;
+		return treeID;
 	}
 	
 	public Children children()
@@ -56,6 +53,6 @@
 
 	public String cid()
 	{
-		return tid;
+		return treeID;
 	}
 }
--- a/src/main/java/jungle/impl/SimpleTreeGroup.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/impl/SimpleTreeGroup.java	Tue Jun 19 23:38:31 2012 +0900
@@ -6,28 +6,36 @@
 import jungle.core.Editor;
 import jungle.core.Tree;
 import jungle.core.TreeGroup;
+import jungle.core.table.Record;
+import jungle.core.table.Table;
 
 public class SimpleTreeGroup implements TreeGroup
 {
-	private String id;
-	private AtomicReference<Tree> latestTree;
-	private AtomicLong revisionCounter;
+	private final String groupID;
+	private final Record record;
+	private final AtomicLong revisionCounter;
+	private final Table table;
 	
-	public SimpleTreeGroup(String _id)
+	public SimpleTreeGroup(String _groupID,Record _r,Table _tb)
 	{
-		latestTree = new AtomicReference<Tree>();
-		id = _id;
+		groupID = _groupID;
+		record = _r;
+		table = _tb;
 		revisionCounter = new AtomicLong();
 	}
 
 	public String getID()
 	{
-		return id;
+		return groupID;
 	}
 
 	public Tree latestTree()
 	{
-		return latestTree.get();
+		String treeID = record.getProperty(Simples.TREEGROUP_TIP_TREE_KEY);
+		String key = String.format(Simples.TREEGROUP_TREEID_FORMAT,groupID,treeID);
+		Record r = table.find(key);
+		SimpleTree tip = new SimpleTree(this,treeID,r);
+		return tip;
 	}
 	
 	public String newTreeID()
--- a/src/main/java/jungle/impl/SimpleTreeNode.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/impl/SimpleTreeNode.java	Tue Jun 19 23:38:31 2012 +0900
@@ -4,69 +4,44 @@
 import jungle.core.Children;
 import jungle.core.Links;
 import jungle.core.TreeNode;
+import jungle.core.table.Record;
 
 public class SimpleTreeNode implements TreeNode
 {
-	private final Children children;
-	private final Links links;
-	private final Attributes attrs;
+	private final Record record;
 	private final String id;
 	
-	public SimpleTreeNode(String _id)
+	public SimpleTreeNode(String _id,Record _r)
 	{
-		this(_id,new SimpleAttributes(),new SimpleChildren(),new SimpleLinks());
-	}
-	
-	private SimpleTreeNode(String _id,Attributes _attrs,Children _children,Links _links)
-	{
-		if(_id == null || _id.length() == 0){
-			throw new NullPointerException("_id is null or empty.");
+		if(_id == null || _r == null){
+			throw new NullPointerException("_id == null || _r == null");
 		}
 		
 		id = _id;
-		attrs = _attrs;
-		children = _children;
-		links = _links;
+		record = _r;
 	}
 
-	public String get(String _key)
-	{
-		if(_key == null){
-			throw new NullPointerException("_key is null");
-		}
-		
-		return attrs.get(_key);
-	}
-
-	public Children children()
-	{
-		return children;
+	@Override
+	public String get(String _key) {
+		// TODO Auto-generated method stub
+		return null;
 	}
 
-	public Links links()
-	{
-		return links;
-	}
-	
-	public String cid()
-	{
-		return id;
-	}
-	
 	@Override
-	public int hashCode()
-	{
-		return id.hashCode();
-	}
-	
-	@Override
-	public boolean equals(Object _obj)
-	{
-		if(_obj instanceof SimpleTreeNode){
-			SimpleTreeNode node = (SimpleTreeNode)_obj;
-			return id.equals(node.id);
-		}
-		return false;
+	public Children children() {
+		// TODO Auto-generated method stub
+		return null;
 	}
 
+	@Override
+	public Links links() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public String cid() {
+		// TODO Auto-generated method stub
+		return null;
+	}
 }
--- a/src/main/java/jungle/impl/Simples.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/main/java/jungle/impl/Simples.java	Tue Jun 19 23:38:31 2012 +0900
@@ -9,4 +9,14 @@
 	public static final Attributes EMPTY_ATTRIBUTES = new SimpleAttributes();
 	public static final Children EMPTY_CHILDREN = new SimpleChildren();
 	public static final Links EMPTY_LINKS = new SimpleLinks();
+	
+	public static final String PROPERTY_KEY_PREFIX = "@";
+	
+	public static final String TREENODE_CHILDREN_KEY = "CHILDREN";
+	public static final String TREENODE_LINKS_KEY = "LINKS";
+	
+	public static final String LINK_DESTINATION_KEY = "DESTINATION";
+	
+	public static final String TREEGROUP_TIP_TREE_KEY = "TIP";
+	public static final String TREEGROUP_TREEID_FORMAT = "%s@%s";
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/core/graph/AbstractGraphTest.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,68 @@
+package jungle.core.graph;
+
+
+import java.util.HashSet;
+import java.util.Iterator;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public abstract class AbstractGraphTest extends TestCase
+{
+	public abstract Graph newInstance();
+	
+	public void testGraphIsSame()
+	{
+		Graph g1 = newInstance();
+		Graph g2 = newInstance();
+		
+		Assert.assertTrue(g1.isSame(g1));
+		Assert.assertFalse(g1.isSame(g2));
+	}
+	
+	public void testGetVertex()
+	{
+		Graph g = newInstance();
+		Vertex v = g.createVertex("ONE");
+		Assert.assertEquals(v,g.getVertex("ONE"));
+		Assert.assertNull(g.getVertex("TWO"));
+		
+		Vertex v2 = g.createVertex();
+		String id = v2.getID();
+		Assert.assertEquals(v2,g.getVertex(id));
+	}
+	
+	public void testCreateVertex()
+	{
+		Graph g = newInstance();
+		
+		Vertex v1 = g.createVertex("ONE");
+		Vertex v2 = g.createVertex("TWO");
+		Vertex v3 = g.createVertex("THREE");
+		Vertex v4 = g.createVertex();
+		
+		Assert.assertNotNull(v1);
+		Assert.assertNotNull(v2);
+		Assert.assertNotNull(v3);
+		Assert.assertNotNull(v4);
+	}
+	
+	public void testIterateVertex()
+	{
+		Graph g = newInstance();
+		
+		Vertex v1 = g.createVertex("ONE");
+		Vertex v2 = g.createVertex("TWO");
+		Vertex v3 = g.createVertex("THREE");
+		
+		HashSet<Vertex> vs = new HashSet<Vertex>();
+		vs.add(v1);
+		vs.add(v2);
+		vs.add(v3);
+		
+		Iterator<Vertex> itr = g.vertexes();
+		while(itr.hasNext()){
+			Vertex v = itr.next();
+			Assert.assertTrue(vs.remove(v));
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/core/graph/AbstractVertexTest.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,115 @@
+package jungle.core.graph;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public abstract class AbstractVertexTest extends TestCase
+{
+	public abstract Vertex newInstance();
+	
+	public void testProperty()
+	{
+		Vertex v = newInstance();
+		
+		v.setProperty("KEY","VALUE");
+		Assert.assertEquals("VALUE",v.getProperty("KEY"));
+		
+		v.removeProperty("KEY");
+		Assert.assertNull(v.getProperty("KEY"));
+	}
+	
+	public void testGetGraph()
+	{
+		Vertex v = newInstance();
+		Graph g = v.getGraph();
+		
+		Assert.assertNotNull(g);
+	}
+	
+	public void testGetIDAndTryToResolveFromParentGraph()
+	{
+		Vertex v = newInstance();
+		Graph g = v.getGraph();
+		String id = v.getID();
+		
+		Assert.assertNotNull(id);
+		Assert.assertEquals(v,g.getVertex(id));
+	}
+	
+	public void testGetVertexes()
+	{
+		Vertex v = newInstance();
+		Vertexes vs1 = v.getVertexes("RELATIONS");
+		Assert.assertNull("vs1 is null",vs1);
+		
+		v.createVertexes("RELATIONS");
+		vs1 = v.getVertexes("RELATIONS");
+		Assert.assertNotNull(vs1);
+		
+		Vertexes vs2 = v.getVertexes("RELATIONS");
+		Assert.assertEquals(vs1,vs2);
+	}
+	
+	public void testCreateVertexes()
+	{
+		Vertex v = newInstance();
+		Vertexes vs = v.createVertexes("RELATIONS");
+		// check that vs is correctly created.
+		Assert.assertNotNull(vs);
+		Assert.assertEquals(vs.type(),"RELATIONS");
+		
+		// createVertexes must return null , if vertexes is already exist.
+		Assert.assertNull(v.createVertexes("RELATIONS"));
+	}
+	
+	public void testRemoveVertexes()
+	{
+		Vertex v = newInstance();
+		Vertexes vs1 = v.createVertexes("RELATIONS");
+		Assert.assertNotNull("vs1 is null",vs1);
+		
+		v.removeVertexes("RELATIONS");
+		
+		Assert.assertNull("removed Vertexes must be null",v.getVertexes("RELATIONS"));
+	}
+	
+	public void testRemovePropertyRefuseNull()
+	{
+		Vertex v = newInstance();
+		
+		try{
+			v.removeProperty(null);
+		}catch(NullPointerException _e){
+			return;
+		}
+		
+		Assert.fail();
+	}
+	
+	public void testSetPropertyRefuseNull()
+	{
+		Vertex v = newInstance();
+		
+		try{
+			v.setProperty(null,"VALUE");
+			v.setProperty("KEY",null);
+		}catch(NullPointerException _e){
+			return;
+		}
+		
+		Assert.fail();
+	}
+	
+	public void testGetPropertyRefuseNull()
+	{
+		Vertex v = newInstance();
+		
+		try{
+			v.getProperty(null);
+		}catch(NullPointerException _e){
+			return;
+		}
+		
+		Assert.fail();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/core/graph/AbstractVertexesTest.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,191 @@
+package jungle.core.graph;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public abstract class AbstractVertexesTest extends TestCase
+{
+	public abstract Graph newInstance();
+	
+	public void testSize()
+	{
+		Graph g = newInstance();
+		Vertex v = g.createVertex();
+		Vertexes vs = v.createVertexes("RELATIONS");
+		
+		Assert.assertEquals(0,vs.size());
+		
+		Vertex c1 = g.createVertex();
+		vs.add(c1);
+		Assert.assertEquals(1,vs.size());
+		
+		Vertex c2 = g.createVertex();
+		vs.add(c2);
+		Assert.assertEquals(2,vs.size());
+		
+		Vertex c3 = g.createVertex();
+		vs.add(c3);
+		Assert.assertEquals(3,vs.size());
+		
+		vs.remove(c3);
+		Assert.assertEquals(2,vs.size());
+	}
+	
+	public void testAddingDoesNotAcceptOtherGraphVertex()
+	{
+		Graph g1 = newInstance();
+		Graph g2 = newInstance();
+		
+		Vertex v1 = g1.createVertex();
+		Vertex v2 = g2.createVertex();
+		
+		Vertexes vs = v1.createVertexes("RELATIONS");
+		try{
+			// v2 belongs to g2 , but v1 is not belongs to g2
+			vs.add(v2); // should be fail here.
+		}catch(IllegalArgumentException _e){
+			return;
+		}
+		
+		Assert.fail("testing add() does not accept other graph vertex fail.");
+	}
+	
+	public void testAddSingleVertex()
+	{
+		Graph g = newInstance();
+		Vertex v = g.createVertex();
+		Vertex c = g.createVertex();
+		Vertexes vs = v.createVertexes("RELATIONS");
+		
+		vs.add(c);
+		
+		for(Vertex i : vs){
+			Assert.assertEquals(c,i);
+		}
+	}
+	
+	public void testAddRefuseNull()
+	{
+		Graph g = newInstance();
+		Vertex v = g.createVertex();
+		Vertexes vs = v.createVertexes("RELATIONS");
+		
+		try{
+			vs.add((Vertex)null);
+			Assert.fail("vs.add(Vertex) didnt throw null pointer exception");
+		}catch(NullPointerException _e){
+			// do nothing.
+		}
+		
+		try{
+			vs.add((Collection<Vertex>)null);
+		}catch(NullPointerException _e){
+			return;
+		}
+		Assert.fail("vs.add(Collection<Vertex> didnt throw null pointer exception");
+	}
+	
+	public void testAddVertexCollection()
+	{
+		Graph g = newInstance();
+		Vertex v = g.createVertex();
+		Vertexes vs = v.createVertexes("RELATIONS");
+		
+		HashSet<Vertex> set = new HashSet<Vertex>();
+		set.add(g.createVertex());
+		set.add(g.createVertex());
+		set.add(g.createVertex());
+		
+		vs.add(set);
+		Assert.assertEquals(3,vs.size());
+		
+		for(Vertex x : vs){
+			Assert.assertTrue("adding collection to Vertexes , but verification was failed.",set.contains(x));
+		}
+	}
+	
+	public void testRemoveSingleVertex()
+	{
+		Graph g = newInstance();
+		Vertex v = g.createVertex();
+		Vertexes vs = v.createVertexes("RELATIONS");
+		
+		HashSet<Vertex> set = new HashSet<Vertex>();
+		set.add(g.createVertex());
+		set.add(g.createVertex());
+		set.add(g.createVertex());
+		
+		Vertex c = g.createVertex();
+		vs.add(c);
+		Assert.assertEquals(4,vs.size());
+		
+		vs.remove(c);
+		Assert.assertEquals(3,vs.size());
+		
+		for(Vertex x : vs){
+			Assert.assertTrue(set.contains(x));
+		}
+		
+		Assert.assertEquals(0,set.size());
+	}
+	
+	public void testRemoveVertexRefuseNull()
+	{
+		Graph g = newInstance();
+		Vertexes vs = g.createVertex().createVertexes("RELATIONS");
+		
+		try{
+			vs.remove((Vertex)null);
+			Assert.fail("vs.remove(Vertex) didnt throw null pointer exception");
+		}catch(NullPointerException _e){
+			// do nothing.
+		}
+		
+		try{
+			vs.remove((Collection<Vertex>)null);
+		}catch(NullPointerException _e){
+			return;
+		}
+		Assert.fail("vs.remove(Collection<Vertex> didnt throw null pointer exception");
+	}
+	
+	public void testRemoveVertexCollection()
+	{
+		Graph g = newInstance();
+		Vertexes vs = g.createVertex().createVertexes("RELATIONS");
+		
+		HashSet<Vertex> set = new HashSet<Vertex>();
+		set.add(g.createVertex());
+		set.add(g.createVertex());
+		set.add(g.createVertex());
+		
+		vs.add(set);
+		Assert.assertEquals(3,vs.size());
+		
+		vs.remove(set);
+		Assert.assertEquals(0,vs.size());
+	}
+	
+	public void testContains()
+	{
+		Graph g = newInstance();
+		Vertexes vs = g.createVertex().createVertexes("RELATIONS");
+		
+		Vertex v = g.createVertex();
+		vs.add(v);
+		vs.add(g.createVertex());
+		
+		Assert.assertTrue(vs.contains(v));
+	}
+	
+	public void testVertexType()
+	{
+		Graph g = newInstance();
+		Vertexes vs = g.createVertex().createVertexes("RELATIONS");
+		
+		Assert.assertEquals("RELATIONS",vs.type());
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/core/graph/simple/SimpleGraphTest.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,13 @@
+package jungle.core.graph.simple;
+
+import jungle.core.graph.AbstractGraphTest;
+import jungle.core.graph.Graph;
+
+public class SimpleGraphTest extends AbstractGraphTest
+{
+	@Override
+	public Graph newInstance()
+	{
+		return new SimpleGraph();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/core/graph/simple/SimpleVertexTest.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,20 @@
+package jungle.core.graph.simple;
+
+import jungle.core.graph.AbstractVertexTest;
+import jungle.core.graph.Vertex;
+
+public class SimpleVertexTest extends AbstractVertexTest
+{
+	private final SimpleGraph g;
+	
+	public SimpleVertexTest()
+	{
+		g = new SimpleGraph();
+	}
+	
+	@Override
+	public Vertex newInstance()
+	{
+		return g.createVertex();
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/core/graph/simple/SimpleVertexesTest.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,13 @@
+package jungle.core.graph.simple;
+
+import jungle.core.graph.AbstractVertexesTest;
+import jungle.core.graph.Graph;
+
+public class SimpleVertexesTest extends AbstractVertexesTest
+{
+	@Override
+	public Graph newInstance()
+	{
+		return new SimpleGraph();
+	}
+}
--- a/src/test/java/jungle/core/table/AbstractPropertySequenceTestTemplate.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/test/java/jungle/core/table/AbstractPropertySequenceTestTemplate.java	Tue Jun 19 23:38:31 2012 +0900
@@ -27,6 +27,18 @@
 		return seq;
 	}
 	
+	public void testAddIsNotAcceptNullValue()
+	{
+		PropertySequence seq = newInstance();
+		try{
+			seq.add(null);
+			Assert.fail("seq.add(null) does not throw NullPointerException");
+		}catch(NullPointerException _e){
+			Assert.assertTrue(true);
+		}
+		
+	}
+	
 	public void testAdd()
 	{
 		PropertySequence seq = prepare();
--- a/src/test/java/jungle/core/table/AbstractRecordTestTemplate.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/test/java/jungle/core/table/AbstractRecordTestTemplate.java	Tue Jun 19 23:38:31 2012 +0900
@@ -29,6 +29,26 @@
 		return r;
 	}
 	
+	public void testCompareAndSwapProperty()
+	{
+		Record r = newInstance();
+		
+		r.setProperty(ONE,ONE);
+		Assert.assertFalse(r.compareAndSwapProperty(ONE,THREE,THREE));
+		Assert.assertTrue(r.compareAndSwapProperty(ONE,ONE,TWO));
+		Assert.assertEquals(r.getProperty(ONE),TWO);
+	}
+	
+	public void testCreateSequenceIfAbsent()
+	{
+		Record r = newInstance();
+		
+		PropertySequence one = r.createSequence(ONE);
+		Assert.assertEquals(one,r.createSequenceIfAbsent(ONE));
+		Assert.assertNull(r.getProperty(TWO));
+		Assert.assertNotNull(r.createSequenceIfAbsent(TWO));
+	}
+	
 	public void testSetProperty()
 	{
 		Record r = prepare();
@@ -37,6 +57,19 @@
 		Assert.assertEquals(r.getProperty("TEST"),"TEST");
 	}
 	
+	public void testNullProperty()
+	{
+		Record r = newInstance();
+		try{
+			r.setProperty(null,"hoge");
+			r.setProperty("hoge",null);
+			
+			Assert.fail("r.setProperty(null,v) or r.setProperty(k,null) does not throw NullPointerException");
+		}catch(NullPointerException _e){
+			Assert.assertTrue(true);
+		}
+	}
+	
 	public void testGetProperty()
 	{
 		Record r = prepare();
--- a/src/test/java/jungle/core/table/AbstractTableTestTemplate.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/test/java/jungle/core/table/AbstractTableTestTemplate.java	Tue Jun 19 23:38:31 2012 +0900
@@ -22,6 +22,18 @@
 	public static final String TWO = "two";
 	public static final String THREE = "three";
 	
+	public void testFindRecordAndCreateIfNotExist()
+	{
+		Table t = newInstance();
+		
+		Record one = t.create(ONE);
+		Assert.assertEquals(one,t.findAndCreateIfNotExist(ONE));
+		
+		Record four = t.find("four");
+		Assert.assertNull(four);
+		Assert.assertNotNull(t.findAndCreateIfNotExist("four"));
+	}
+	
 	public void testCreateRecord()
 	{
 		Table t = newInstance();
@@ -42,6 +54,7 @@
 		Record one = t.create(ONE);
 		Assert.assertNotNull(one);
 		Assert.assertEquals(one,t.find(ONE));
+		Assert.assertNull(t.find("NOENTRY"));
 	}
 	
 	public void testRemoveRecord()
--- a/src/test/java/jungle/core/table/simple/SimplePropertySequenceTest.java	Wed Jun 13 01:29:02 2012 +0900
+++ b/src/test/java/jungle/core/table/simple/SimplePropertySequenceTest.java	Tue Jun 19 23:38:31 2012 +0900
@@ -1,13 +1,27 @@
 package jungle.core.table.simple;
 
 import jungle.core.table.AbstractPropertySequenceTestTemplate;
-import jungle.core.table.PropertySequence;
+import junit.framework.Assert;
 
 public class SimplePropertySequenceTest extends AbstractPropertySequenceTestTemplate
 {
 	@Override
-	public PropertySequence newInstance()
+	public SimplePropertySequence newInstance()
 	{
 		return new SimplePropertySequence();
 	}
+	
+	public void testSnapshot()
+	{
+		SimplePropertySequence seq = newInstance();
+		
+		seq.add("hoge");
+		
+		SimplePropertySequence ss = seq.snapshot();
+		Assert.assertNotNull(ss);
+		Assert.assertTrue(ss.isSameSequence(seq));
+		
+		ss.add("hoge2");
+		Assert.assertFalse(ss.isSameSequence(seq));
+	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/misc/fj/ImmutableListExample.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,43 @@
+package jungle.misc.fj;
+
+import fj.Equal;
+import fj.F;
+import fj.P2;
+import fj.data.List;
+
+public class ImmutableListExample
+{
+	public static void main(String[] _args)
+	{
+		List<String> first = List.list("1","3","2","3");
+		List<String> two = first.snoc("4");
+		F<String,Boolean> predicate = new F<String,Boolean>(){
+			@Override
+			public Boolean f(String arg0)
+			{
+				return "3".equals(arg0);
+			}
+		};
+		
+		List<String> three = two.removeAll(predicate);
+		List<String> four = two.delete("3",Equal.equal(
+			new F<String,F<String,Boolean>>(){
+				@Override
+				public F<String, Boolean> f(final String _str){
+					return new F<String,Boolean>(){
+						@Override
+						public Boolean f(String _str1){
+							return _str.equals(_str1);
+						}
+					};
+				}
+			}));
+		
+		System.out.println(first.toString());
+		System.out.println(two.toString());
+		P2<List<String>,List<String>> p = two.splitAt(2);
+		System.out.println(p._1().snoc("hey!").append(p._2()).toString());
+		System.out.println(three.toString());
+		System.out.println(four.toString());
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jungle/misc/fj/ImmutableSetExample.java	Tue Jun 19 23:38:31 2012 +0900
@@ -0,0 +1,9 @@
+package jungle.misc.fj;
+
+
+public class ImmutableSetExample
+{
+	public static void main(String _args[])
+	{
+	}
+}