changeset 16:bb9760760744

commit
author shoshi
date Sat, 21 May 2011 04:46:00 +0900
parents 22cd920986c5
children 168deb591f21
files CHANGELOG src/treecms/api/Forest.java src/treecms/api/MonotonicTree.java src/treecms/api/NodeAttributesImpl.java src/treecms/api/NodeData.java src/treecms/gui/GUIEditor.java src/treecms/memory/OnMemoryForest.java src/treecms/memory/OnMemoryMonotonicTree.java src/treecms/memory/OnMemoryMonotonicTreeNode.java src/treecms/memory/OnMemoryNode.java src/treecms/memory/test/OnMemoryNodeTest.java src/treecms/test/AbstractForestTest.java src/treecms/test/AbstractMonotonicTreeTest.java src/treecms/test/AbstractNodeTest.java src/treecms/test/AbstractTreeEditorTest.java src/treecms/tree/cassandra/v1/CassandraForest.java src/treecms/tree/cassandra/v1/CassandraNode.java src/treecms/tree/cassandra/v1/CassandraTree.java src/treecms/tree/cassandra/v1/CassandraTreeEditor.java src/treecms/tree/util/NodeAttributesImpl.java src/treecms/tree/util/NodeChildrenImpl.java src/treecms/tree/util/NodeData.java
diffstat 22 files changed, 491 insertions(+), 452 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG	Tue May 17 21:25:17 2011 +0900
+++ b/CHANGELOG	Sat May 21 04:46:00 2011 +0900
@@ -26,6 +26,11 @@
 	
 開発メモ
 
+2011-05-20
+	OnMemoryなのがだいたい完成した
+	テストコード修正中
+	さて、どうやってGenericsで記述するんだろう
+
 2011-05-17
 	NodeAttributes、NodeChildrenを作って分けた.
 	NodeAttributesはノードの要素を保持する。
--- a/src/treecms/api/Forest.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/api/Forest.java	Sat May 21 04:46:00 2011 +0900
@@ -1,5 +1,7 @@
 package treecms.api;
 
+import treecms.tree.util.NodeData;
+
 /**
  * ForestはNodeの集合で、集合に対するアクセスを提供します.クライアントはNodeIDを用いてNodeの取得や作成を行うことが出来ます.
  * @author shoshi
@@ -38,7 +40,7 @@
 	 * @param _tree 対象
 	 * @return TreeEditor
 	 */
-	MonotonicTree getMonotonicTree(SingleNode _root);
+	MonotonicTree getMonotonicTree(Tree _tree);
 	
 	/**
 	 * NodeDataを保持する新しいNodeを作成します.このメソッドで作成されるNodeは新しいUUIDを持ちます.
--- a/src/treecms/api/MonotonicTree.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/api/MonotonicTree.java	Sat May 21 04:46:00 2011 +0900
@@ -38,4 +38,6 @@
 	 * @return この木構造のルートNode
 	 */
 	public MonotonicTreeNode getRoot();
+	
+	public Tree getTree();
 }
--- a/src/treecms/api/NodeAttributesImpl.java	Tue May 17 21:25:17 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-package treecms.api;
-
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-public class NodeAttributesImpl implements NodeAttributes
-{
-	private Map<ByteBuffer,ByteBuffer> m_attrs;
-	
-	public NodeAttributesImpl()
-	{
-		m_attrs = new HashMap<ByteBuffer,ByteBuffer>();
-	}
-	
-	public NodeAttributesImpl(NodeAttributesImpl _attrs)
-	{
-		super();
-		m_attrs.putAll(_attrs.m_attrs);
-	}
-	
-	@Override
-	public Set<ByteBuffer> getKeySet()
-	{
-		return m_attrs.keySet();
-	}
-
-	@Override
-	public void put(ByteBuffer _name, ByteBuffer _value)
-	{
-		m_attrs.put(_name,_value);
-	}
-
-	@Override
-	public void putAll(NodeAttributes _attrs)
-	{
-		m_attrs.putAll(_attrs.asMap());
-	}
-	
-	@Override
-	public Map<ByteBuffer,ByteBuffer> asMap()
-	{
-		return Collections.unmodifiableMap(m_attrs);
-	}
-
-	@Override
-	public ByteBuffer get(ByteBuffer _name)
-	{
-		return m_attrs.get(_name);
-	}
-
-	@Override
-	public NodeAttributes getAll()
-	{
-		return this;
-	}
-
-	@Override
-	public void remove(ByteBuffer _name)
-	{
-		m_attrs.remove(_name);
-	}
-
-	@Override
-	public void removeAll(Set<ByteBuffer> _keySet)
-	{
-		for(ByteBuffer _key : _keySet){
-			remove(_key);
-		}
-	}
-
-	@Override
-	public void clearAttributes()
-	{
-		m_attrs.clear();
-	}
-
-}
--- a/src/treecms/api/NodeData.java	Tue May 17 21:25:17 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-package treecms.api;
-
-import java.nio.ByteBuffer;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import treecms.tree.util.NodeChildrenImpl;
-
-/**
- * Node が保持するデータのスナップショットです.Node を大きく変更するときや新しく作成される場合に使用されます.
- * 通常このクラスのインスタンスを Node から取得した場合,NodeData インスタンスに変更(set,add)を加えても元の Node に変更は反映されません.
- * その様に実装してください.
- * 
- * このクラスは Node が保持するデータのうち 子供ノードのリスト・属性のマップ のみ保持しています.つまり,ノードが持っているはずの ID は保持していません.
- * getID,getForest を呼び出すと UnsupportedOperationException をスローします.
- * @author shoshi
- */
-public class NodeData<T extends Node<T>> implements NodeAttributes , NodeChildren<T>
-{
-	private NodeChildrenImpl<T> m_children;
-	private NodeAttributesImpl m_attrs;
-	
-	public NodeData()
-	{
-		this(null,null);
-	}
-	
-	public NodeData(NodeData<T> _newData)
-	{
-		this(_newData.m_children,_newData.m_attrs);
-	}
-	
-	public NodeData(NodeChildren<T> _children,NodeAttributes _attrs)
-	{
-		m_children = new NodeChildrenImpl<T>(_children);
-		m_attrs = new NodeAttributesImpl();
-	}
-
-	@Override
-	public List<T> getList()
-	{
-		return m_children.getList();
-	}
-
-	@Override
-	public Set<String> getUUIDSet()
-	{
-		return m_children.getUUIDSet();
-	}
-
-	@Override
-	public boolean add(T _child)
-	{
-		return m_children.add(_child);
-	}
-
-	@Override
-	public boolean addAll(NodeChildren<T> _children)
-	{
-		return m_children.addAll(_children);
-	}
-
-	@Override
-	public T get(String _uuid)
-	{
-		return m_children.get(_uuid);
-	}
-
-	@Override
-	public T get(int _index)
-	{
-		return m_children.get(_index);
-	}
-
-	@Override
-	public T remove(String _uuid)
-	{
-		return m_children.remove(_uuid);
-	}
-
-	@Override
-	public T remove(int _index)
-	{
-		return m_children.remove(_index);
-	}
-
-	@Override
-	public T replace(T _newChild)
-	{
-		return m_children.replace(_newChild);
-	}
-
-	@Override
-	public boolean contains(String _id)
-	{
-		return m_children.contains(_id);
-	}
-
-	@Override
-	public boolean swap(String _uuid1, String _uuid2)
-	{
-		return m_children.swap(_uuid1, _uuid2);
-	}
-
-	@Override
-	public void clearChildren()
-	{
-		m_children.clearChildren();
-	}
-
-	@Override
-	public Map<ByteBuffer, ByteBuffer> asMap()
-	{
-		return m_attrs.asMap();
-	}
-
-	@Override
-	public Set<ByteBuffer> getKeySet()
-	{
-		return m_attrs.getKeySet();
-	}
-
-	@Override
-	public void put(ByteBuffer _name, ByteBuffer _value)
-	{
-		m_attrs.put(_name,_value);
-	}
-
-	@Override
-	public void putAll(NodeAttributes _attrs) 
-	{
-		m_attrs.putAll(_attrs);
-	}
-
-	@Override
-	public ByteBuffer get(ByteBuffer _name)
-	{
-		return m_attrs.get(_name);
-	}
-
-	@Override
-	public NodeAttributes getAll()
-	{
-		return m_attrs.getAll();
-	}
-
-	@Override
-	public void remove(ByteBuffer _name)
-	{
-		m_attrs.remove(_name);
-	}
-
-	@Override
-	public void removeAll(Set<ByteBuffer> _keySet)
-	{
-		m_attrs.removeAll(_keySet);
-	}
-
-	@Override
-	public void clearAttributes()
-	{
-		m_attrs.clearAttributes();
-	}
-}
--- a/src/treecms/gui/GUIEditor.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/gui/GUIEditor.java	Sat May 21 04:46:00 2011 +0900
@@ -27,10 +27,10 @@
 import javax.swing.tree.DefaultTreeModel;
 
 import treecms.api.Node;
-import treecms.api.NodeData;
 import treecms.api.Tree;
 import treecms.api.TreeEditor;
 import treecms.memory.OnMemoryForest;
+import treecms.tree.util.NodeData;
 import treecms.tree.util.PathNotFoundException;
 
 public class GUIEditor
--- a/src/treecms/memory/OnMemoryForest.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/memory/OnMemoryForest.java	Sat May 21 04:46:00 2011 +0900
@@ -5,12 +5,12 @@
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import treecms.api.Forest;
-import treecms.api.NodeData;
 import treecms.api.NodeID;
 import treecms.api.SingleNode;
 import treecms.api.Tree;
 import treecms.api.MonotonicTree;
 import treecms.tree.id.AbstractRandomNodeID;
+import treecms.tree.util.NodeData;
 
 /**
  * Forestのオンメモリ上の実装.
@@ -99,14 +99,14 @@
 	 * @return TreeEditor
 	 */
 	@Override
-	public MonotonicTree getMonotonicTree(SingleNode _node)
+	public MonotonicTree getMonotonicTree(Tree _tree)
 	{
-		Forest forest = _node.getForest();
-		if(forest != this){
+		Forest forest = _tree.getRoot().getForest();
+		if(forest != this || !(_tree instanceof OnMemoryTree)){
 			throw new IllegalArgumentException();
 		}
 		
-		return new OnMemoryMonotonicTree((OnMemoryNode)_node);
+		return new OnMemoryMonotonicTree((OnMemoryTree)_tree);
 	}
 	
 	/**
--- a/src/treecms/memory/OnMemoryMonotonicTree.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/memory/OnMemoryMonotonicTree.java	Sat May 21 04:46:00 2011 +0900
@@ -2,30 +2,40 @@
 
 import treecms.api.MonotonicTree;
 import treecms.api.MonotonicTreeNode;
+import treecms.api.Tree;
+import treecms.merger.Merger;
+import treecms.merger.ReplaceMerger;
 
 public class OnMemoryMonotonicTree implements MonotonicTree
 {
-	public OnMemoryMonotonicTree(OnMemoryNode _node)
+	private volatile OnMemoryTree m_tree;
+	private OnMemoryNode m_old;
+	private OnMemoryMonotonicTreeNode m_root;
+	
+	public OnMemoryMonotonicTree(OnMemoryTree _tree)
 	{
-		
+		m_tree = _tree;
+		m_old = (OnMemoryNode)m_tree.getRoot().getNode();
+		m_root = new OnMemoryMonotonicTreeNode((OnMemoryNode)m_old,this);
 	}
 
 	@Override
 	public boolean commit(boolean _force)
 	{
-		return false;
+		return m_tree.compareAndSwapRootNode(m_old,(OnMemoryNode)m_root.getNode(),_force);
 	}
 
 	@Override
 	public boolean pull()
 	{
-		return false;
+		m_old = (OnMemoryNode)m_tree.getRoot().getNode();
+		return true;
 	}
 
 	@Override
 	public boolean check()
 	{
-		return false;
+		return m_tree.compareAndSwapRootNode(m_old,m_old,false);
 	}
 
 	@Override
@@ -37,7 +47,12 @@
 	@Override
 	public MonotonicTreeNode getRoot()
 	{
-		// TODO Auto-generated method stub
-		return null;
+		return this.m_root;
+	}
+
+	@Override
+	public Tree getTree()
+	{
+		return (Tree)m_tree;
 	}
 }
--- a/src/treecms/memory/OnMemoryMonotonicTreeNode.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/memory/OnMemoryMonotonicTreeNode.java	Sat May 21 04:46:00 2011 +0900
@@ -1,20 +1,19 @@
 package treecms.memory;
 
 import java.nio.ByteBuffer;
+
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import treecms.api.Forest;
 import treecms.api.MonotonicTreeNode;
-import treecms.api.Node;
 import treecms.api.NodeAttributes;
 import treecms.api.NodeChildren;
 import treecms.api.NodeID;
 import treecms.api.SingleNode;
-import treecms.api.TreeNode;
 import treecms.tree.util.NodeChildrenImpl;
+import treecms.tree.util.NodeData;
 
 /**
  * SingleLinkedなNodeをラップしたDoubleLinkedなNodeの実装です.
@@ -24,6 +23,7 @@
 {
 	private OnMemoryNode m_node;
 	private OnMemoryMonotonicTreeNode m_parent;
+	private OnMemoryMonotonicTree m_tree;
 	
 	/**
 	 * コンストラクタです.
@@ -33,17 +33,16 @@
 	 */
 	public OnMemoryMonotonicTreeNode(OnMemoryNode _target,OnMemoryMonotonicTreeNode _parent)
 	{
-		if(_target == null){
-			throw new NullPointerException("_target must not be null.");
-		}
-		
 		m_node  = _target;
 		m_parent = _parent;
 	}
 	
-	/*
-	 * 親関連のメソッド
-	 */
+	public OnMemoryMonotonicTreeNode(OnMemoryNode _root,OnMemoryMonotonicTree _tree)
+	{
+		m_node = _root;
+		m_tree = _tree;
+		m_parent = null;
+	}
 	
 	@Override
 	public NodeID getID()
@@ -106,13 +105,26 @@
 	@Override
 	public void removeAll(Set<ByteBuffer> _keys)
 	{
-		m_node.removeAll(_keys);
+		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		d.removeAll(_keys);
+		
+		cloneAndTransmit(d);
 	}
 
 	@Override
 	public void clearAttributes()
 	{
-		m_node.clearAttributes();
+		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		d.clearAttributes();
+		
+		cloneAndTransmit(d);
+	}
+	
+	public void cloneAndTransmit(NodeData<SingleNode> _d)
+	{
+		OnMemoryForest f = (OnMemoryForest)m_node.getForest();
+		OnMemoryNode clone = f.createNode(m_node.getID().update(),_d);
+		transmit(m_node,clone);
 	}
 	
 	/**
@@ -128,15 +140,13 @@
 	public void transmit(OnMemoryNode _orig,OnMemoryNode _edit)
 	{
 		OnMemoryForest f = (OnMemoryForest)m_node.getForest();
-		OnMemoryNode clone = f.createNode(m_node.getID(),null);
-		clone.replaceChild(_orig,_edit);
+		OnMemoryNode clone = f.createNode(m_node.getID().update(),null);
+		clone.replace(_edit);
 		
 		if(m_parent != null){
 			m_parent.transmit(m_node,(OnMemoryNode)clone);
 			return;
 		}
-		
-		//なにかしたい
 	}
 	
 	/*
@@ -185,7 +195,7 @@
 	public MonotonicTreeNode remove(int _index)
 	{
 		SingleNode n = m_node.remove(_index);
-		return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,null);
+		return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,(OnMemoryMonotonicTreeNode)null);
 	}
 
 	@Override
@@ -193,4 +203,55 @@
 	{
 		m_node.clearChildren();
 	}
+
+	@Override
+	public Map<ByteBuffer, ByteBuffer> asMap()
+	{
+		return m_node.asMap();
+	}
+
+	@Override
+	public Set<ByteBuffer> getKeySet()
+	{
+		return m_node.getKeySet();
+	}
+
+	@Override
+	public Set<String> getUUIDSet()
+	{
+		return m_node.getUUIDSet();
+	}
+
+	@Override
+	public MonotonicTreeNode get(String _uuid)
+	{
+		SingleNode n = m_node.get(_uuid);
+		return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,this);
+	}
+
+	@Override
+	public MonotonicTreeNode get(int _index)
+	{
+		SingleNode n = m_node.get(_index);
+		return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,this);
+	}
+
+	@Override
+	public MonotonicTreeNode replace(MonotonicTreeNode _newChild)
+	{
+		SingleNode n = m_node.replace(_newChild.getNode());
+		return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,(OnMemoryMonotonicTreeNode)null);
+	}
+
+	@Override
+	public boolean contains(String _id)
+	{
+		return m_node.contains(_id);
+	}
+
+	@Override
+	public boolean swap(String _uuid1, String _uuid2)
+	{
+		return m_node.swap(_uuid1,_uuid2);
+	}
 }
--- a/src/treecms/memory/OnMemoryNode.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/memory/OnMemoryNode.java	Sat May 21 04:46:00 2011 +0900
@@ -1,9 +1,9 @@
 package treecms.memory;
 
 import treecms.api.Forest;
-import treecms.api.NodeData;
 import treecms.api.NodeID;
 import treecms.api.SingleNode;
+import treecms.tree.util.NodeData;
 
 /**
  * オンメモリ上でのNodeの実装です。 
--- a/src/treecms/memory/test/OnMemoryNodeTest.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/memory/test/OnMemoryNodeTest.java	Sat May 21 04:46:00 2011 +0900
@@ -1,8 +1,7 @@
 package treecms.memory.test;
 
 import org.junit.runner.JUnitCore;
-
-import treecms.api.Node;
+import treecms.api.SingleNode;
 import treecms.memory.OnMemoryForest;
 import treecms.test.AbstractNodeTest;
 
@@ -21,7 +20,7 @@
 	}
 	
 	@Override
-	public Node getInstance()
+	public SingleNode getInstance()
 	{
 		return m_forest.create();
 	}
--- a/src/treecms/test/AbstractForestTest.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/test/AbstractForestTest.java	Sat May 21 04:46:00 2011 +0900
@@ -1,12 +1,10 @@
 package treecms.test;
 
 import junit.framework.Assert;
-
 import org.junit.Test;
-
 import treecms.api.Forest;
-import treecms.api.Node;
 import treecms.api.NodeID;
+import treecms.api.SingleNode;
 import treecms.api.Tree;
 
 /**
@@ -29,7 +27,7 @@
 	public void testCreateNode()
 	{
 		Forest forest = getInstance();
-		Node newNode = forest.create();
+		SingleNode newNode = forest.create();
 		Assert.assertNotNull(newNode);
 	}
 	
@@ -41,10 +39,10 @@
 	public void testGetNode()
 	{
 		Forest forest = getInstance();
-		Node newNode = forest.create();
+		SingleNode newNode = forest.create();
 		NodeID newID = newNode.getID();
 		
-		Node node = forest.get(newID);
+		SingleNode node = forest.get(newID);
 		
 		Assert.assertEquals(newNode,node);
 	}
@@ -57,15 +55,24 @@
 	public void testGetTip()
 	{
 		Forest forest = getInstance();
-		Node newNode = forest.create();
+		SingleNode newNode = forest.create();
 		NodeID newID = newNode.getID();
 		
-		Node tip = forest.getTip(newID.getUUID());
+		SingleNode tip = forest.getTip(newID.getUUID());
 		
 		Assert.assertEquals(newNode,tip);
 	}
 	
 	/**
+	 * NodeIDを更新したものを作成したとき、きちんと登録されているかテスト 
+	 */
+	@Test
+	public void updateTest()
+	{
+		
+	}
+	
+	/**
 	 * MainTreeが取得できるかテストします。
 	 * MainTreeとは、コンテンツ全体を含むツリーです
 	 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/treecms/test/AbstractMonotonicTreeTest.java	Sat May 21 04:46:00 2011 +0900
@@ -0,0 +1,84 @@
+package treecms.test;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import junit.framework.Assert;
+import org.junit.Test;
+import treecms.api.Forest;
+import treecms.api.MonotonicTree;
+import treecms.api.Node;
+import treecms.api.NodeID;
+import treecms.api.SingleNode;
+import treecms.api.Tree;
+import treecms.tree.util.NodeData;
+
+public abstract class AbstractMonotonicTreeTest
+{
+	public abstract Forest getForest();
+	
+	@Test
+	public MonotonicTree testEdit()
+	{
+		Forest forest = getForest();
+		SingleNode root = forest.create();
+		
+		SingleNode n1 = forest.create();
+		SingleNode n11 = forest.create();
+		SingleNode n12 = forest.create();
+		n1.addAll(Arrays.asList(n11,n12));
+		
+		Node n2 = forest.create();
+		Node n21 = forest.create();
+		Node n22 = forest.create();
+		n2.addAll(Arrays.asList(n21,n22));
+		
+		Node n221 = forest.create();
+		n22.add(n221);
+		
+		root.addAll(Arrays.asList(n1,n2));
+		
+		TreeEditor editor = forest.getTreeEditor(forest.getTree(root));
+		
+		//編集開始
+		NodeData data = n221.getData();
+		data.put(ByteBuffer.wrap("name".getBytes()),ByteBuffer.wrap("value".getBytes()));
+		
+		try{
+			Node new221 = editor.updateTree(n221,data); //n221を編集する。パスはroot -> n2 -> n22 -> n221となるはず
+			NodeID oldID = n221.getID();
+			NodeID newID = new221.getID();
+			
+			//編集したノードは同じUUIDを持つはず
+			Assert.assertTrue(oldID.isFamily(newID));
+			
+			Node newRoot = 
+			NodePathFinder finder = new NodePathFinder()
+			
+		}catch(PathNotFoundException _e){
+			Assert.fail(_e.getMessage());
+		}
+		
+		return editor;
+	}
+	
+	@Test
+	public void testForceCommit()
+	{
+		testEdit();
+	}
+	
+	@Test
+	public void testCommitFailsWhenTreeWasUpdated()
+	{
+	}
+	
+	@Test
+	public void testCheck()
+	{
+	}
+	
+	@Test
+	public void testUpdate()
+	{
+	}
+}
--- a/src/treecms/test/AbstractNodeTest.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/test/AbstractNodeTest.java	Sat May 21 04:46:00 2011 +0900
@@ -1,15 +1,13 @@
 package treecms.test;
 
 import java.nio.ByteBuffer;
-import java.util.LinkedList;
 import java.util.List;
-
 import junit.framework.Assert;
-
 import org.junit.Test;
-
-import treecms.api.Node;
+import treecms.api.NodeChildren;
 import treecms.api.NodeID;
+import treecms.api.SingleNode;
+import treecms.tree.util.NodeChildrenImpl;
 
 /**
  * Node実装の基本的なテスト
@@ -21,7 +19,7 @@
 	 * テストに用いるNodeを実装者は返す
 	 * @return Node
 	 */
-	public abstract Node getInstance();
+	public abstract SingleNode getInstance();
 	
 	/**
 	 * NodeID取得のテスト
@@ -38,7 +36,8 @@
 	@Test
 	public void testGetData()
 	{
-		Assert.assertNotNull(getInstance().getData());
+		Assert.assertNotNull(getInstance().getList());
+		Assert.assertNotNull(getInstance().getAll());
 	}
 	
 	/**
@@ -56,21 +55,22 @@
 	@Test
 	public void testAddChildren()
 	{
-		Node node = getInstance();
+		SingleNode node = getInstance();
 		
-		Node ch1 = node.getForest().create();
-		Node ch2 = node.getForest().create();
-		Node ch3 = node.getForest().create();
+		SingleNode ch1 = node.getForest().create();
+		SingleNode ch2 = node.getForest().create();
+		SingleNode ch3 = node.getForest().create();
 		
-		LinkedList<Node> list = new LinkedList<Node>();
+		NodeChildren<SingleNode> list = new NodeChildrenImpl<SingleNode>();
 		list.add(ch1);
 		list.add(ch2);
 		list.add(ch3);
 		
 		node.addAll(list);
 		
-		List<Node> children = node.children();
-		for(int i = 0;i < list.size();i ++){
+		List<SingleNode> children = node.getList();
+		int size = list.getList().size();
+		for(int i = 0;i < size;i ++){
 			NodeID id1 = children.get(i).getID();
 			NodeID id2 = list.get(i).getID();
 			
@@ -84,7 +84,7 @@
 	@Test
 	public void testSetAndGetAttribute()
 	{
-		Node node = getInstance();
+		SingleNode node = getInstance();
 		byte[] name = "test".getBytes();
 		byte[] value = "test".getBytes();
 		
--- a/src/treecms/test/AbstractTreeEditorTest.java	Tue May 17 21:25:17 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-package treecms.test;
-
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-import junit.framework.Assert;
-
-import org.junit.Test;
-import treecms.api.Forest;
-import treecms.api.Node;
-import treecms.api.NodeData;
-import treecms.api.NodeID;
-import treecms.api.Tree;
-import treecms.api.TreeEditor;
-import treecms.tree.util.PathNotFoundException;
-
-public abstract class AbstractTreeEditorTest
-{
-	public abstract Forest getForest();
-	
-	@Test
-	public TreeEditor testEdit()
-	{
-		Forest forest = getForest();
-		Node root = forest.create();
-		
-		Node n1 = forest.create();
-		Node n11 = forest.create();
-		Node n12 = forest.create();
-		n1.addAll(Arrays.asList(n11,n12));
-		
-		Node n2 = forest.create();
-		Node n21 = forest.create();
-		Node n22 = forest.create();
-		n2.addAll(Arrays.asList(n21,n22));
-		
-		Node n221 = forest.create();
-		n22.add(n221);
-		
-		root.addAll(Arrays.asList(n1,n2));
-		
-		TreeEditor editor = forest.getTreeEditor(forest.getTree(root));
-		
-		//編集開始
-		NodeData data = n221.getData();
-		data.put(ByteBuffer.wrap("name".getBytes()),ByteBuffer.wrap("value".getBytes()));
-		
-		try{
-			Node new221 = editor.updateTree(n221,data); //n221を編集する。パスはroot -> n2 -> n22 -> n221となるはず
-			NodeID oldID = n221.getID();
-			NodeID newID = new221.getID();
-			
-			//編集したノードは同じUUIDを持つはず
-			Assert.assertTrue(oldID.isFamily(newID));
-			
-			Node newRoot = 
-			NodePathFinder finder = new NodePathFinder()
-			
-		}catch(PathNotFoundException _e){
-			Assert.fail(_e.getMessage());
-		}
-		
-		return editor;
-	}
-	
-	@Test
-	public void testForceCommit()
-	{
-		testEdit();
-	}
-	
-	@Test
-	public void testCommitFailsWhenTreeWasUpdated()
-	{
-	}
-	
-	@Test
-	public void testCheck()
-	{
-	}
-	
-	@Test
-	public void testUpdate()
-	{
-	}
-}
--- a/src/treecms/tree/cassandra/v1/CassandraForest.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/tree/cassandra/v1/CassandraForest.java	Sat May 21 04:46:00 2011 +0900
@@ -33,10 +33,10 @@
 
 import treecms.api.Forest;
 import treecms.api.Node;
-import treecms.api.NodeData;
 import treecms.api.NodeID;
 import treecms.tree.cassandra.v1.util.CassandraClientThreadFactory;
 import treecms.tree.id.AbstractRandomNodeID;
+import treecms.tree.util.NodeData;
 
 /**
  * Cassandra上で非破壊的木構造を実現するためのForestの実装です。
--- a/src/treecms/tree/cassandra/v1/CassandraNode.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/tree/cassandra/v1/CassandraNode.java	Sat May 21 04:46:00 2011 +0900
@@ -2,8 +2,8 @@
 
 import treecms.api.Forest;
 import treecms.api.Node;
-import treecms.api.NodeData;
 import treecms.api.NodeID;
+import treecms.tree.util.NodeData;
 
 class CassandraNode implements Node
 {
--- a/src/treecms/tree/cassandra/v1/CassandraTree.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/tree/cassandra/v1/CassandraTree.java	Sat May 21 04:46:00 2011 +0900
@@ -4,9 +4,9 @@
 import java.util.concurrent.ConcurrentHashMap;
 import treecms.api.Forest;
 import treecms.api.Node;
-import treecms.api.NodeData;
 import treecms.api.NodeID;
 import treecms.api.Tree;
+import treecms.tree.util.NodeData;
 
 class CassandraTree implements Tree
 {
--- a/src/treecms/tree/cassandra/v1/CassandraTreeEditor.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/tree/cassandra/v1/CassandraTreeEditor.java	Sat May 21 04:46:00 2011 +0900
@@ -3,10 +3,10 @@
 import java.util.LinkedList;
 
 import treecms.api.Node;
-import treecms.api.NodeData;
 import treecms.api.TreeEditor;
 import treecms.merger.Merger;
 import treecms.merger.ReplaceMerger;
+import treecms.tree.util.NodeData;
 
 class CassandraTreeEditor extends CassandraTree implements TreeEditor
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/treecms/tree/util/NodeAttributesImpl.java	Sat May 21 04:46:00 2011 +0900
@@ -0,0 +1,82 @@
+package treecms.tree.util;
+
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import treecms.api.NodeAttributes;
+
+public class NodeAttributesImpl implements NodeAttributes
+{
+	private Map<ByteBuffer,ByteBuffer> m_attrs;
+	
+	public NodeAttributesImpl()
+	{
+		m_attrs = new HashMap<ByteBuffer,ByteBuffer>();
+	}
+	
+	public NodeAttributesImpl(NodeAttributesImpl _attrs)
+	{
+		super();
+		m_attrs.putAll(_attrs.m_attrs);
+	}
+	
+	@Override
+	public Set<ByteBuffer> getKeySet()
+	{
+		return m_attrs.keySet();
+	}
+
+	@Override
+	public void put(ByteBuffer _name, ByteBuffer _value)
+	{
+		m_attrs.put(_name,_value);
+	}
+
+	@Override
+	public void putAll(NodeAttributes _attrs)
+	{
+		m_attrs.putAll(_attrs.asMap());
+	}
+	
+	@Override
+	public Map<ByteBuffer,ByteBuffer> asMap()
+	{
+		return Collections.unmodifiableMap(m_attrs);
+	}
+
+	@Override
+	public ByteBuffer get(ByteBuffer _name)
+	{
+		return m_attrs.get(_name);
+	}
+
+	@Override
+	public NodeAttributes getAll()
+	{
+		return this;
+	}
+
+	@Override
+	public void remove(ByteBuffer _name)
+	{
+		m_attrs.remove(_name);
+	}
+
+	@Override
+	public void removeAll(Set<ByteBuffer> _keySet)
+	{
+		for(ByteBuffer _key : _keySet){
+			remove(_key);
+		}
+	}
+
+	@Override
+	public void clearAttributes()
+	{
+		m_attrs.clear();
+	}
+
+}
--- a/src/treecms/tree/util/NodeChildrenImpl.java	Tue May 17 21:25:17 2011 +0900
+++ b/src/treecms/tree/util/NodeChildrenImpl.java	Sat May 21 04:46:00 2011 +0900
@@ -1,14 +1,11 @@
 package treecms.tree.util;
 
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 import java.util.List;
 import treecms.api.Node;
-import treecms.api.NodeAttributes;
 import treecms.api.NodeChildren;
 
 /**
@@ -16,7 +13,7 @@
  * 子供ノードのリストには リスト内に同じUUIDを持つNodeが存在 してはいけません.
  * @author shoshi
  */
-public class NodeChildrenImpl<T extends Node<T>> implements NodeAttributes , NodeChildren<T>
+public class NodeChildrenImpl<T extends Node<T>> implements NodeChildren<T>
 {
 	private List<T> m_list;
 	private Set<String> m_set;
@@ -33,8 +30,6 @@
 		
 		if(_list != null){
 			addAll(_list);
-		}else{
-			throw new NullPointerException("_list must not be null.");
 		}
 	}
 	
@@ -211,6 +206,7 @@
 		m_list.clear();
 	}
 	
+	@SuppressWarnings("unchecked")
 	@Override
 	public boolean equals(Object _o)
 	{
@@ -226,59 +222,9 @@
 		result = 37*result + m_set.hashCode();
 		return result;
 	}
-
-	@Override
-	public Map<ByteBuffer, ByteBuffer> asMap() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Set<ByteBuffer> getKeySet() {
-		// TODO Auto-generated method stub
+	
+	public static NodeChildren<? extends Node<?>> hoge(Node<?> hoge)
+	{
 		return null;
 	}
-
-	@Override
-	public void put(ByteBuffer _name, ByteBuffer _value) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	@Override
-	public void putAll(NodeAttributes _attrs) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	@Override
-	public ByteBuffer get(ByteBuffer _name) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public NodeAttributes getAll() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void remove(ByteBuffer _name) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	@Override
-	public void removeAll(Set<ByteBuffer> _keySet) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	@Override
-	public void clearAttributes() {
-		// TODO Auto-generated method stub
-		
-	}
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/treecms/tree/util/NodeData.java	Sat May 21 04:46:00 2011 +0900
@@ -0,0 +1,167 @@
+package treecms.tree.util;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import treecms.api.Node;
+import treecms.api.NodeAttributes;
+import treecms.api.NodeChildren;
+
+/**
+ * Node が保持するデータのスナップショットです.Node を大きく変更するときや新しく作成される場合に使用されます.
+ * 通常このクラスのインスタンスを Node から取得した場合,NodeData インスタンスに変更(set,add)を加えても元の Node に変更は反映されません.
+ * その様に実装してください.
+ * 
+ * このクラスは Node が保持するデータのうち 子供ノードのリスト・属性のマップ のみ保持しています.つまり,ノードが持っているはずの ID は保持していません.
+ * getID,getForest を呼び出すと UnsupportedOperationException をスローします.
+ * @author shoshi
+ */
+public class NodeData<T extends Node<T>> implements NodeAttributes , NodeChildren<T>
+{
+	private NodeChildrenImpl<T> m_children;
+	private NodeAttributesImpl m_attrs;
+	
+	public NodeData()
+	{
+		this(null,null);
+	}
+	
+	public NodeData(NodeData<T> _newData)
+	{
+		this(_newData.m_children,_newData.m_attrs);
+	}
+	
+	public NodeData(NodeChildren<T> _children,NodeAttributes _attrs)
+	{
+		m_children = new NodeChildrenImpl<T>(_children);
+		m_attrs = new NodeAttributesImpl();
+	}
+
+	@Override
+	public List<T> getList()
+	{
+		return m_children.getList();
+	}
+
+	@Override
+	public Set<String> getUUIDSet()
+	{
+		return m_children.getUUIDSet();
+	}
+
+	@Override
+	public boolean add(T _child)
+	{
+		return m_children.add(_child);
+	}
+
+	@Override
+	public boolean addAll(NodeChildren<T> _children)
+	{
+		return m_children.addAll(_children);
+	}
+
+	@Override
+	public T get(String _uuid)
+	{
+		return m_children.get(_uuid);
+	}
+
+	@Override
+	public T get(int _index)
+	{
+		return m_children.get(_index);
+	}
+
+	@Override
+	public T remove(String _uuid)
+	{
+		return m_children.remove(_uuid);
+	}
+
+	@Override
+	public T remove(int _index)
+	{
+		return m_children.remove(_index);
+	}
+
+	@Override
+	public T replace(T _newChild)
+	{
+		return m_children.replace(_newChild);
+	}
+
+	@Override
+	public boolean contains(String _id)
+	{
+		return m_children.contains(_id);
+	}
+
+	@Override
+	public boolean swap(String _uuid1, String _uuid2)
+	{
+		return m_children.swap(_uuid1, _uuid2);
+	}
+
+	@Override
+	public void clearChildren()
+	{
+		m_children.clearChildren();
+	}
+
+	@Override
+	public Map<ByteBuffer, ByteBuffer> asMap()
+	{
+		return m_attrs.asMap();
+	}
+
+	@Override
+	public Set<ByteBuffer> getKeySet()
+	{
+		return m_attrs.getKeySet();
+	}
+
+	@Override
+	public void put(ByteBuffer _name, ByteBuffer _value)
+	{
+		m_attrs.put(_name,_value);
+	}
+
+	@Override
+	public void putAll(NodeAttributes _attrs) 
+	{
+		m_attrs.putAll(_attrs);
+	}
+
+	@Override
+	public ByteBuffer get(ByteBuffer _name)
+	{
+		return m_attrs.get(_name);
+	}
+
+	@Override
+	public NodeAttributes getAll()
+	{
+		return m_attrs.getAll();
+	}
+
+	@Override
+	public void remove(ByteBuffer _name)
+	{
+		m_attrs.remove(_name);
+	}
+
+	@Override
+	public void removeAll(Set<ByteBuffer> _keySet)
+	{
+		m_attrs.removeAll(_keySet);
+	}
+
+	@Override
+	public void clearAttributes()
+	{
+		m_attrs.clearAttributes();
+	}
+}