changeset 20:084de6909451

commit
author shoshi
date Wed, 01 Jun 2011 15:35:50 +0900
parents 019ca5abb1f0
children f3150b37f9be
files src/treecms/api/Forest.java src/treecms/api/MonotonicTree.java src/treecms/api/MonotonicTreeNode.java src/treecms/api/Node.java src/treecms/api/NodeChildren.java src/treecms/api/NodeID.java src/treecms/api/SingleNode.java src/treecms/api/Tree.java src/treecms/api/TreeNode.java src/treecms/memory/OnMemoryForest.java src/treecms/memory/OnMemoryMonotonicTreeNode.java src/treecms/memory/OnMemoryNode.java src/treecms/memory/OnMemoryTree.java src/treecms/memory/OnMemoryTreeNode.java src/treecms/tree/id/AbstractRandomNodeID.java src/treecms/tree/util/NodeAttributesImpl.java src/treecms/tree/util/NodeChildrenImpl.java src/treecms/tree/util/NodeData.java src/treecms/tree/util/NodeFinder.java
diffstat 19 files changed, 291 insertions(+), 794 deletions(-) [+]
line wrap: on
line diff
--- a/src/treecms/api/Forest.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/api/Forest.java	Wed Jun 01 15:35:50 2011 +0900
@@ -1,60 +1,9 @@
 package treecms.api;
 
-import treecms.tree.util.NodeData;
-
-/**
- * ForestはNodeの集合で、集合に対するアクセスを提供します.クライアントはNodeIDを用いてNodeの取得や作成を行うことが出来ます.
- * @author shoshi
- */
 public interface Forest
 {
-	/**
-	 * NodeIDで示されるNodeを取得します.
-	 * @param _id Nodeを示すNodeID.
-	 * @return NodeIDと一致するNodeがある場合は,Nodeのインスタンスを返し,見つからない場合はnullを返します.
-	 */
-	SingleNode get(NodeID _id);
-	
-	/**
-	 * 同じUUIDを持つNode中で最新のNodeを取得します.
-	 * @param _uuid NodeIDのUUID
-	 * @return UUIDと一致するNodeが見つからない場合はnullを返します.
-	 */
-	SingleNode getTip(String _uuid);
-	
-	/**
-	 * 新しいNodeを作成します.このメソッドで作成されるNodeは新しいUUIDを持ちます.
-	 * @return 新しいNode
-	 */
-	SingleNode create();
-	
-	/**
-	 * あるNodeを木として返します
-	 * @param _root
-	 * @return Tree あるNodeをルートとした木
-	 */
-	Tree getTree(SingleNode _root);
-	
-	/**
-	 * 木を非破壊的に編集するMonotonicTreeを取得します
-	 * @param _tree 対象
-	 * @return TreeEditor
-	 */
-	MonotonicTree getMonotonicTree(Tree _tree);
-	
-	/**
-	 * NodeDataを保持する新しいNodeを作成します.このメソッドで作成されるNodeは新しいUUIDを持ちます.
-	 * このメソッドはNodeDataをNodeに割り当てるとき防御的コピーを行います.
-	 * @param _data 新しいNodeが保持するNodeData
-	 * @return NodeDataを保持した新しいNode
-	 */
-	SingleNode create(NodeData<SingleNode> _data);
-	
-	/**
-	 * このForestの現在の最新のMainTreeを取得します
-	 * @return このForestのMainTree、最新版
-	 */
-	Tree getMainTree();
-	
-	SingleNode create(NodeID _id,NodeData<SingleNode> _data);
+	MonotonicTree get(NodeID _id);
+	MonotonicTree getTip(String _uuid);
+	MonotonicTree create();
+	MonotonicTree getMainTree();
 }
--- a/src/treecms/api/MonotonicTree.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/api/MonotonicTree.java	Wed Jun 01 15:35:50 2011 +0900
@@ -8,36 +8,9 @@
  */
 public interface MonotonicTree
 {
-	/**
-	 * 非破壊的に更新した木構造を適用します.
-	 * 更新する際に他の方法により木構造がすでに更新されていた場合,commitは失敗します。_forceがtrueの場合,強制的に置き換えます. 
-	 * @param _force 強制コミットフラグ
-	 * @return 成功した場合true,失敗した場合false
-	 */
 	public boolean commit(boolean _force);
-	
-	/**
-	 * 監視している木構造をEditorにキャッシュします.
-	 * @return キャッシュが成功した場合はtrue,失敗した場合はfalse
-	 */
 	public boolean pull();
-	
-	/**
-	 * 監視されている木構造が更新されていないかチェックします.
-	 * @return 更新されていた場合はture,されていない場合はfalse
-	 */
 	public boolean check();
-	
-	/**
-	 * 監視している木構造をキャッシュにマージします.
-	 */
 	public void merge();
-	
-	/**
-	 * この木構造のルートNodeを返します。
-	 * @return この木構造のルートNode
-	 */
 	public MonotonicTreeNode getRoot();
-	
-	public Tree getTree();
 }
--- a/src/treecms/api/MonotonicTreeNode.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/api/MonotonicTreeNode.java	Wed Jun 01 15:35:50 2011 +0900
@@ -5,8 +5,7 @@
  * TreeNodeとは違い、この実装は木を非破壊的に編集します.
  * @author shoshi
  */
-public interface MonotonicTreeNode extends Node<MonotonicTreeNode>
+public interface MonotonicTreeNode extends NodeContext , NodeAttributes , NodeChildren<MonotonicTreeNode>
 {
 	public MonotonicTreeNode getParent();
-	public SingleNode getNode();
 }
--- a/src/treecms/api/Node.java	Tue May 31 15:55:28 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-package treecms.api;
-
-public interface Node<T extends Node<T>> extends NodeContext , NodeAttributes , NodeChildren<T>
-{
-}
--- a/src/treecms/api/NodeChildren.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/api/NodeChildren.java	Wed Jun 01 15:35:50 2011 +0900
@@ -3,18 +3,22 @@
 import java.util.List;
 import java.util.Set;
 
-public interface NodeChildren<T extends Node<T>>
+public interface NodeChildren<T extends NodeContext & NodeChildren<T>>
 {
 	public List<T> getList();
-	public Set<String> getUUIDSet();
+	
 	public boolean add(T _child);
-	public boolean addAll(NodeChildren<T> _children);
+	public boolean addAll(NodeChildren<T> _list);
+	public Set<String> getFamilyIDSet();
+	
 	public T get(String _uuid);
 	public T get(int _index);
 	public T remove(String _uuid);
 	public T remove(int _index);
-	public T replace(T _newChild);
-	public boolean contains(String _id);
-	public boolean swap(String _uuid1,String _uuid2);
+	public T replace(T _new);
+	
+	public boolean contains(NodeID _id);
+	public boolean swap(String _uuid,String _uuid2);
+	
 	public void clearChildren();
 }
--- a/src/treecms/api/NodeID.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/api/NodeID.java	Wed Jun 01 15:35:50 2011 +0900
@@ -1,30 +1,30 @@
 package treecms.api;
 
 /**
- * Nodeに対応するNodeIDです.NodeIDはUUIDとバージョンから構成されており,同じUUIDを持つNodeIDはファミリーと定義します.
- * 木構造で同じUUIDを持つNodeは同一のNodeと判断されます.また,一つの木構造に同じUUIDを持つNodeは存在しません.
- * ファイルのバージョン管理と同じようなものと考えてください.その場合,UUIDがファイルのパスで,バージョンがファイルの更新日時です.
+ * Nodeに対応するNodeIDです.NodeIDはFamilyとVersionから構成されており,同じFamilyを持つNodeIDはファミリーと定義します.
+ * 木構造で同じFamilyを持つNodeは同一のNodeと判断されます.また,一つの木構造に同じFamilyを持つNodeは存在しません.
+ * ファイルのバージョン管理と同じようなものと考えてください.その場合,Familyがファイルのパスで,Versionがファイルの更新日時です.
  * @author shoshi
  */
 public interface NodeID
 {
 	/**
-	 * 新しいNodeIDを作成します.新しいNodeIDは異なるUUIDを持ちます.
-	 * @return 新しいUUIDを持つNodeID
+	 * 新しいNodeIDを作成します.新しいNodeIDは異なるFamilyを持ちます.
+	 * @return 新しいFamilyを持つNodeID
 	 */
 	public NodeID create();
 	
 	/**
-	 * このNodeIDが保持するUUIDを継承した,自分とバージョンの異なるNodeIDを生成します.
-	 * @return UUIDを継承した新しいNodeID
+	 * このNodeIDが保持するFamilyを継承した,自分とバージョンの異なるNodeIDを生成します.
+	 * @return Familyを継承した新しいNodeID
 	 */
 	public NodeID update();
 	
 	/**
-	 * UUIDを取得します.
-	 * @return NodeIDが保持しているUUID
+	 * Familyを取得します.
+	 * @return NodeIDが保持しているFamily
 	 */
-	public String getUUID();
+	public String getFamilyID();
 	
 	/**
 	 * このNodeIDのバージョンを取得します.
@@ -33,7 +33,7 @@
 	public String getVersion();
 	
 	/**
-	 * このNodeIDが同一なUUIDを保持しているか比較します.
+	 * このNodeIDが同一なFamilyを保持しているか比較します.
 	 * @param _id
 	 * @return 同一な場合はtrue,異なる場合はfalse
 	 */
@@ -41,7 +41,7 @@
 	
 	/**
 	 * このNodeIDの文字列表現を返します.
-	 * このメソッドを実装する際に,文字列の表現方法は<b>UUID@Version</b>を採用してください.
+	 * このメソッドを実装する際に,文字列の表現方法は<b>Family@Version</b>を採用してください.
 	 * @return
 	 */
 	public String toString();
--- a/src/treecms/api/SingleNode.java	Tue May 31 15:55:28 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-package treecms.api;
-
-public interface SingleNode extends Node<SingleNode>
-{
-}
--- a/src/treecms/api/Tree.java	Tue May 31 15:55:28 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-package treecms.api;
-
-/**
- * 木構造を表します.
- * @author shoshi
- */
-public interface Tree
-{
-	/**
-	 * この木構造のルートNodeを取得します.
-	 * @return ルートNode
-	 */
-	TreeNode getRoot();
-}
--- a/src/treecms/api/TreeNode.java	Tue May 31 15:55:28 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-package treecms.api;
-
-/**
- * DoubleLinkedなNodeの実装です.SingleLinkedなNodeの実装と違い,親の情報を保持します.
- * 非破壊的木構造の実装では,Nodeは子どもの情報しか持っていません.これは,一つのNodeに対して複数の親が存在するためです.
- * 木構造内のあるNodeへのRootNodeからのパスを検索する手間を省くことが出来ます.
- * 
- * なのでSingleLinkedとDoubleLinkedを分けて,DoubleLinkedはSingleLinkedを内包した形で実装します.
- * TreeNodeがNodeのインターフェイスを継承していないのは,継承するとSingleLinkedなNodeに子供として追加できるようになるからです.
- * 
- * また,TreeNodeを編集したときは非破壊的に編集されず、破壊的に編集されます.
- * @author shoshi
- */
-public interface TreeNode extends Node<TreeNode>
-{
-	public TreeNode getParent();
-	public SingleNode getNode();
-}
--- a/src/treecms/memory/OnMemoryForest.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/memory/OnMemoryForest.java	Wed Jun 01 15:35:50 2011 +0900
@@ -5,9 +5,8 @@
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import treecms.api.Forest;
+import treecms.api.MonotonicTreeNode;
 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;
@@ -19,12 +18,12 @@
 public class OnMemoryForest implements Forest
 {
 	//Nodeのマップ
-	Map<NodeID,OnMemoryNode> m_table;
+	private final Map<NodeID,OnMemoryNode> m_table;
 	//最新版Nodeのマップ
-	Map<String,OnMemoryNode> m_tipTable;
+	private final Map<String,OnMemoryNode> m_tipTable;
 	
 	//MainTreeのUUID
-	String m_mainID;
+	private final String m_mainID;
 	
 	/**
 	 * コンストラクタ
@@ -34,7 +33,7 @@
 		m_table = new ConcurrentHashMap<NodeID,OnMemoryNode>();
 		m_tipTable = new ConcurrentHashMap<String,OnMemoryNode>();
 		
-		m_mainID = createNode(null,null).getID().getUUID();
+		m_mainID = createNode(null,null).getID().getFamilyID();
 	}
 	
 	/**
@@ -43,17 +42,17 @@
 	 * @param _newData Nodeが保持するNodeData
 	 * @return 作成されたOnMemoryNode
 	 */
-	public OnMemoryNode createNode(NodeID _id,NodeData<SingleNode> _newData)
+	public OnMemoryNode createNode(NodeID _id,NodeData<OnMemoryNode> _newData)
 	{
 		NodeID newID = (_id != null) ? _id : createID();
-		NodeData<SingleNode> newData = (_newData != null) ? _newData : new NodeData<SingleNode>();
+		NodeData<OnMemoryNode> newData = (_newData != null) ? _newData : new NodeData<OnMemoryNode>();
 		
 		//newIDとnewDataを元にOnMemoryNodeを生成する.
 		OnMemoryNode newNode = new OnMemoryNode(this,newID,newData);
 		
 		//登録
 		m_table.put(newID,newNode);
-		m_tipTable.put(newID.getUUID(),newNode);
+		m_tipTable.put(newID.getFamilyID(),newNode);
 		
 		return newNode;
 	}
@@ -72,49 +71,17 @@
 	 * @return NodeIDに対応するNode
 	 */
 	@Override
-	public SingleNode get(NodeID _id)
+	public MonotonicTree get(NodeID _id)
 	{
 		return m_table.get(_id);
 	}
 	
 	/**
-	 * あるNodeをルートとしてTreeのオブジェクトを取得します。
-	 * @param _id 木のルートとなるNodeのNodeID
-	 * @return Tree
-	 */
-	@Override
-	public Tree getTree(SingleNode _node)
-	{
-		Forest forest = _node.getForest();
-		if(forest != this){
-			throw new IllegalArgumentException();
-		}
-		
-		return new OnMemoryTree((OnMemoryNode)_node);
-	}
-	
-	/**
-	 * あるNodeをルートとしたTreeを非破壊的に編集するTreeEditorを取得します。
-	 * @param _id 木のルートとなるNodeのNodeID
-	 * @return TreeEditor
-	 */
-	@Override
-	public MonotonicTree getMonotonicTree(Tree _tree)
-	{
-		Forest forest = _tree.getRoot().getForest();
-		if(forest != this || !(_tree instanceof OnMemoryTree)){
-			throw new IllegalArgumentException();
-		}
-		
-		return new OnMemoryMonotonicTree((OnMemoryTree)_tree);
-	}
-	
-	/**
 	 * 新しくNodeを作成します.
 	 * @return 新しいNode
 	 */
 	@Override
-	public SingleNode create()
+	public MonotonicTree create()
 	{
 		return createNode(null,null);
 	}
@@ -144,7 +111,7 @@
 	 * @return このForestのMainTree
 	 */
 	@Override
-	public Tree getMainTree()
+	public MonotonicTree getMainTree()
 	{
 		return new OnMemoryTree(m_tipTable.get(m_mainID));
 	}
--- a/src/treecms/memory/OnMemoryMonotonicTreeNode.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/memory/OnMemoryMonotonicTreeNode.java	Wed Jun 01 15:35:50 2011 +0900
@@ -6,12 +6,14 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
 import treecms.api.Forest;
 import treecms.api.MonotonicTreeNode;
 import treecms.api.NodeAttributes;
 import treecms.api.NodeChildren;
 import treecms.api.NodeID;
-import treecms.api.SingleNode;
 import treecms.tree.util.NodeChildrenImpl;
 import treecms.tree.util.NodeData;
 
@@ -22,18 +24,19 @@
 public class OnMemoryMonotonicTreeNode implements MonotonicTreeNode
 {
 	private OnMemoryNode m_node;
+	
+	private static final AtomicReferenceFieldUpdater<OnMemoryMonotonicTreeNode,OnMemoryMonotonicTreeNode> m_parentUpdater 
+		= AtomicReferenceFieldUpdater.newUpdater(OnMemoryMonotonicTreeNode.class,OnMemoryMonotonicTreeNode.class,"m_parent");
+	
 	private OnMemoryMonotonicTreeNode m_parent;
 	
-	/**
-	 * コンストラクタです.
-	 * @param _target 対象となるSingleLinked Node
-	 * @param _parent このDoubleLinked Nodeの親,RootNodeならnull
-	 * @param _tree このNodeがRootNodeなら,nullではいけない.
-	 */
+	private final Map<NodeID,OnMemoryMonotonicTreeNode> m_cache;
+	
 	public OnMemoryMonotonicTreeNode(OnMemoryNode _target,OnMemoryMonotonicTreeNode _parent)
 	{
 		m_node  = _target;
 		m_parent = _parent;
+		m_cache = new ConcurrentHashMap<NodeID,OnMemoryMonotonicTreeNode>();
 	}
 	
 	@Override
@@ -53,16 +56,6 @@
 	{
 		return m_parent;
 	}
-
-	@Override
-	public SingleNode getNode()
-	{
-		return m_node;
-	}
-	
-	/*
-	 * 属性関連のメソッド
-	 */
 	
 	@Override
 	public ByteBuffer get(ByteBuffer _key)
@@ -77,51 +70,51 @@
 	}
 
 	@Override
-	public void put(ByteBuffer _key, ByteBuffer _value)
+	public synchronized void put(ByteBuffer _key, ByteBuffer _value)
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
 		d.put(_key,_value);
 		
 		cloneAndTransmit(d);
 	}
 
 	@Override
-	public void putAll(NodeAttributes _map)
+	public synchronized void putAll(NodeAttributes _map)
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
 		d.putAll(_map);
 		
 		cloneAndTransmit(d);
 	}
 
 	@Override
-	public void remove(ByteBuffer _key)
+	public synchronized void remove(ByteBuffer _key)
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
 		d.remove(_key);
 		
 		cloneAndTransmit(d);
 	}
 
 	@Override
-	public void removeAll(Set<ByteBuffer> _keys)
+	public synchronized void removeAll(Set<ByteBuffer> _keys)
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
 		d.removeAll(_keys);
 		
 		cloneAndTransmit(d);
 	}
 
 	@Override
-	public void clearAttributes()
+	public synchronized void clearAttributes()
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
 		d.clearAttributes();
 		
 		cloneAndTransmit(d);
 	}
 	
-	public void cloneAndTransmit(NodeData<SingleNode> _d)
+	public synchronized void cloneAndTransmit(NodeData<OnMemoryNode> _d)
 	{
 		OnMemoryForest f = (OnMemoryForest)m_node.getForest();
 		OnMemoryNode clone = f.createNode(m_node.getID().update(),_d);
@@ -140,7 +133,7 @@
 	 * _fromがnullの場合は,自身が編集元であることを示します.
 	 * @param _from 編集元のOnMemoryMonotonicTreeNode
 	 */
-	public void transmit(OnMemoryNode _orig,OnMemoryNode _edit)
+	public synchronized void transmit(OnMemoryNode _orig,OnMemoryNode _edit)
 	{
 		OnMemoryForest f = (OnMemoryForest)m_node.getForest();
 		OnMemoryNode clone = f.createNode(m_node.getID().update(),null);
@@ -152,27 +145,39 @@
 		}
 	}
 	
-	/*
-	 * 子供関連のメソッド
-	 */
+	private synchronized OnMemoryMonotonicTreeNode getCache(OnMemoryNode _node)
+	{
+		NodeID id = _node.getID();
+		OnMemoryMonotonicTreeNode mono;
+		synchronized(m_cache){
+			mono = m_cache.get(id);
+			if(mono == null){
+				//cache not found . create it
+				mono = new OnMemoryMonotonicTreeNode(_node,this);
+			}
+		}
+		return mono;
+	}
+	
 	@Override
-	public List<MonotonicTreeNode> getList()
+	public synchronized List<MonotonicTreeNode> getList()
 	{
 		//NodeのリストよりMonotonicTreeNodeのリストを作成する.
 		NodeChildren<MonotonicTreeNode> res = new NodeChildrenImpl<MonotonicTreeNode>();
-		for(Iterator<SingleNode> it = m_node.getList().iterator();it.hasNext();){
+		for(Iterator<OnMemoryNode> it = m_node.getList().iterator();it.hasNext();){
 			OnMemoryNode n = (OnMemoryNode)it.next();
-			res.add(new OnMemoryMonotonicTreeNode(n,this));
+			res.add(getCache(n));
 		}
 		
 		return res.getList();
 	}
 
 	@Override
-	public boolean add(MonotonicTreeNode _n)
+	public synchronized boolean add(MonotonicTreeNode _n)
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
-		boolean ret = d.add(_n.getNode());
+		OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)_n;
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
+		boolean ret = d.add(mono.m_node);
 		if(ret){
 			cloneAndTransmit(d);
 		}
@@ -181,16 +186,16 @@
 	}
 
 	@Override
-	public boolean addAll(NodeChildren<MonotonicTreeNode> _list)
+	public synchronized boolean addAll(NodeChildren<MonotonicTreeNode> _list)
 	{
 		//MotonicTreeNodeのリストからNodeのリストを作成する.
-		NodeChildren<SingleNode> c = new NodeChildrenImpl<SingleNode>();
+		NodeChildren<OnMemoryNode> c = new NodeChildrenImpl<OnMemoryNode>();
 		for(Iterator<MonotonicTreeNode> it = _list.getList().iterator();it.hasNext();){
-			MonotonicTreeNode mono = (MonotonicTreeNode)it.next();
-			c.add(mono.getNode());
+			OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)it.next();
+			c.add(mono.m_node);
 		}
 		
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
 		boolean ret = d.addAll(c);
 		if(ret){
 			cloneAndTransmit(d);
@@ -200,10 +205,10 @@
 	}
 
 	@Override
-	public MonotonicTreeNode remove(String _uuid)
+	public synchronized MonotonicTreeNode remove(int _index)
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
-		SingleNode n = d.remove(_uuid);
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
+		OnMemoryNode n = d.remove(_index);
 		if(n != null){
 			cloneAndTransmit(d);
 			return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,null);
@@ -213,23 +218,11 @@
 	}
 
 	@Override
-	public MonotonicTreeNode remove(int _index)
+	public synchronized void clearChildren()
 	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
-		SingleNode n = d.remove(_index);
-		if(n != null){
-			cloneAndTransmit(d);
-			return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,null);
-		}
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
+		d.clearChildren();
 		
-		return null;
-	}
-
-	@Override
-	public void clearChildren()
-	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
-		d.clearChildren();
 		cloneAndTransmit(d);
 	}
 
@@ -246,47 +239,62 @@
 	}
 
 	@Override
-	public Set<String> getUUIDSet()
+	public synchronized MonotonicTreeNode get(int _index)
 	{
-		return m_node.getUUIDSet();
-	}
-
-	@Override
-	public MonotonicTreeNode get(String _uuid)
-	{
-		SingleNode n = m_node.get(_uuid);
-		return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,this);
+		OnMemoryNode n = m_node.get(_index);
+		return getCache(n);
 	}
 
 	@Override
-	public MonotonicTreeNode get(int _index)
+	public synchronized MonotonicTreeNode replace(MonotonicTreeNode _newChild)
 	{
-		SingleNode n = m_node.get(_index);
-		return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,this);
-	}
-
-	@Override
-	public MonotonicTreeNode replace(MonotonicTreeNode _newChild)
-	{
-		NodeData<SingleNode> d = new NodeData<SingleNode>(m_node);
-		SingleNode n = d.replace(_newChild.getNode());
+		OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)_newChild;
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
+		OnMemoryNode n = d.replace(mono.m_node);
+		
 		if(n != null){
 			cloneAndTransmit(d);
-			return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,(OnMemoryMonotonicTreeNode)null);
+			return new OnMemoryMonotonicTreeNode(n,null);
 		}
 		
 		return null;
 	}
 
 	@Override
-	public boolean contains(String _id)
+	public boolean contains(NodeID _id)
 	{
 		return m_node.contains(_id);
 	}
 
 	@Override
-	public boolean swap(String _uuid1, String _uuid2)
+	public boolean swap(String _fid1,String _fid2)
+	{
+		return m_node.swap(_fid1,_fid2);
+	}
+
+	@Override
+	public Set<String> getFamilyIDSet()
+	{
+		return m_node.getFamilyIDSet();
+	}
+
+	@Override
+	public synchronized MonotonicTreeNode get(String _fid)
 	{
-		return m_node.swap(_uuid1,_uuid2);
+		OnMemoryNode n = m_node.get(_fid);
+		OnMemoryMonotonicTreeNode mono = getCache(n);
+		
+		return mono;
+	}
+
+	@Override
+	public synchronized MonotonicTreeNode remove(String _fid)
+	{
+		NodeData<OnMemoryNode> d = new NodeData<OnMemoryNode>(m_node);
+		OnMemoryNode n = d.remove(_fid);
+		
+		cloneAndTransmit(d);
+		
+		return new OnMemoryMonotonicTreeNode(n,null);
 	}
 }
--- a/src/treecms/memory/OnMemoryNode.java	Tue May 31 15:55:28 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-package treecms.memory;
-
-import treecms.api.Forest;
-import treecms.api.NodeID;
-import treecms.api.SingleNode;
-import treecms.tree.util.NodeData;
-
-/**
- * オンメモリ上でのNodeの実装です。 
- * @author shoshi
- */
-class OnMemoryNode extends NodeData<SingleNode> implements SingleNode
-{
-	private OnMemoryForest m_forest;
-	private NodeID m_id;
-	
-	/**
-	 * コンストラクタ
-	 * @param _forest このNodeが属するForestです.
-	 * @param _id このNodeのNodeIDです.
-	 * @param _newData このNodeに割り当てるNodeDataです.防御的にコピーします.
-	 */
-	public OnMemoryNode(OnMemoryForest _forest,NodeID _id,NodeData<SingleNode> _newData)
-	{
-		super(_newData);
-		m_id = _id;
-		m_forest = _forest;
-	}
-
-	@Override
-	public NodeID getID()
-	{
-		return m_id;
-	}
-
-	@Override
-	public Forest getForest()
-	{
-		return m_forest;
-	}
-}
--- a/src/treecms/memory/OnMemoryTree.java	Tue May 31 15:55:28 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-package treecms.memory;
-
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-import treecms.api.Tree;
-import treecms.api.TreeNode;
-
-/**
- * オンメモリのTree実装です。
- * 木構造のルートとなるNodeをメンバーとして持ち、操作はすべて転送します。
- * @author shoshi
- */
-public class OnMemoryTree implements Tree
-{
-	private static final AtomicReferenceFieldUpdater<OnMemoryTree,OnMemoryNode> m_refUpdater = AtomicReferenceFieldUpdater.newUpdater(OnMemoryTree.class,OnMemoryNode.class,"m_root");
-	private volatile OnMemoryNode m_root;
-	
-	/**
-	 * コンストラクタです。
-	 * @param _newRoot 木構造のルートノードです。
-	 */
-	public OnMemoryTree(OnMemoryNode _newRoot)
-	{
-		m_root = _newRoot;
-	}
-	
-	/**
-	 * この木構造のルートNodeを取得します.
-	 * @return ルートNode
-	 */	
-	@Override
-	public TreeNode getRoot()
-	{
-		return new OnMemoryTreeNode(m_root,null);
-	}
-	
-	/**
-	 * ルートNodeを比較して置き換えます.
-	 * @param _except 比較する対象 
-	 * @param _newRoot 一致した場合置き換える対象
-	 */
-	public boolean compareAndSwapRootNode(OnMemoryNode _expect,OnMemoryNode _newRoot,boolean _force)
-	{
-		if(_force){
-			m_root = _newRoot;
-		}
-		
-		m_refUpdater.compareAndSet(this,_expect,_newRoot);
-		return true;
-	}
-
-}
--- a/src/treecms/memory/OnMemoryTreeNode.java	Tue May 31 15:55:28 2011 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +0,0 @@
-package treecms.memory;
-
-import java.nio.ByteBuffer;
-import java.util.Collections;
-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.NodeAttributes;
-import treecms.api.NodeChildren;
-import treecms.api.NodeID;
-import treecms.api.SingleNode;
-import treecms.api.TreeNode;
-import treecms.tree.util.NodeChildrenImpl;
-
-/**
- * DoubleLinkedなNodeであるTreeNodeのOnMemory実装です. 
- * @author shoshi
- */
-public class OnMemoryTreeNode implements TreeNode
-{
-	public OnMemoryTreeNode m_parent;
-	public OnMemoryNode m_node;
-	
-	/**
-	 * コンストラクタです.
-	 * @param _node 対象となるSingleLinkedなNode
-	 * @param _parent 親のOnMemoryTreeNode
-	 */
-	public OnMemoryTreeNode(OnMemoryNode _node,OnMemoryTreeNode _parent)
-	{
-		//とりあえず、チェック
-		if(_node == null){
-			throw new NullPointerException();
-		}
-		
-		m_node = _node;
-		
-		//このノードがルートの場合、親はnullで構わない.
-		m_parent = _parent;
-	}
-	
-	/*
-	 * 親関連のメソッド
-	 */
-	
-	@Override
-	public NodeID getID()
-	{
-		return m_node.getID();
-	}
-	
-	@Override
-	public SingleNode getNode()
-	{
-		return m_node;
-	}
-	
-	@Override
-	public  TreeNode getParent()
-	{
-		return m_parent;
-	}
-	
-	@Override
-	public Forest getForest()
-	{
-		return m_node.getForest();
-	}
-	
-	/*
-	 * 子供関連のメソッド
-	 */
-
-	@Override
-	public List<TreeNode> getList()
-	{
-		/* 
-		 * m_node(対象ノード)のリストにはNodeが格納されており、TreeNodeのリストを取得するためにはTreeNodeで要素を構成する必要がある.
-		 */
-		LinkedList<TreeNode> ret = new LinkedList<TreeNode>();
-		for(Iterator<SingleNode> it = m_node.getList().iterator();it.hasNext();){
-			OnMemoryNode n = (OnMemoryNode)it.next();
-			ret.add(new OnMemoryTreeNode(n,this));
-		}
-		
-		return Collections.unmodifiableList(ret);
-	}
-	
-	@Override
-	public boolean add(TreeNode _child)
-	{
-		return m_node.add(_child.getNode());
-	}
-
-	@Override
-	public boolean addAll(NodeChildren<TreeNode> _children)
-	{
-		/*
-		 * TreeNodeのリストからNodeのリストへ変換する
-		 */
-		NodeChildren<SingleNode> res = new NodeChildrenImpl<SingleNode>();
-		for(Iterator<TreeNode> it = _children.getList().iterator();it.hasNext();){
-			TreeNode tn = it.next();
-			res.add(tn.getNode());
-		}
-		
-		return m_node.addAll(res);
-	}
-	
-	@Override
-	public TreeNode remove(String _uuid)
-	{
-		SingleNode n = m_node.remove(_uuid);
-		return new OnMemoryTreeNode((OnMemoryNode)n,this);
-	}
-	
-	@Override
-	public TreeNode remove(int _index)
-	{
-		SingleNode n = m_node.remove(_index);
-		return new OnMemoryTreeNode((OnMemoryNode)n,this);
-	}
-	
-	@Override
-	public void clearChildren()
-	{
-		m_node.clearChildren();
-	}
-	
-	@Override
-	public ByteBuffer get(ByteBuffer _key)
-	{
-		return m_node.get(_key);
-	}
-
-	@Override
-	public NodeAttributes getAll()
-	{
-		return m_node.getAll();
-	}
-
-	@Override
-	public void put(ByteBuffer _key,ByteBuffer _value)
-	{
-		m_node.put(_key,_value);
-	}
-	
-	@Override
-	public void putAll(NodeAttributes _map)
-	{
-		m_node.putAll(_map);
-	}
-	
-	@Override
-	public void remove(ByteBuffer _key)
-	{
-		m_node.remove(_key);
-	}
-	
-	@Override
-	public void removeAll(Set<ByteBuffer> _keySet)
-	{
-		m_node.removeAll(_keySet);
-	}
-	
-	@Override
-	public void clearAttributes()
-	{
-		m_node.clearAttributes();
-	}
-
-	@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 TreeNode get(String _uuid)
-	{
-		SingleNode n = m_node.get(_uuid);
-		return new OnMemoryTreeNode((OnMemoryNode)n,this);
-	}
-
-	@Override
-	public TreeNode get(int _index)
-	{
-		SingleNode n = m_node.get(_index);
-		return new OnMemoryTreeNode((OnMemoryNode)n,this);
-	}
-
-	@Override
-	public TreeNode replace(TreeNode _newChild)
-	{
-		SingleNode n = m_node.replace(_newChild.getNode());
-		return new OnMemoryTreeNode((OnMemoryNode)n,this);
-	}
-
-	@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/tree/id/AbstractRandomNodeID.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/tree/id/AbstractRandomNodeID.java	Wed Jun 01 15:35:50 2011 +0900
@@ -5,12 +5,12 @@
 public abstract class AbstractRandomNodeID extends AbstractNodeID
 {
 	public abstract NodeID create();
-	public abstract String getUUID();
+	public abstract String getFamilyID();
 	public abstract String getVersion();
 	public abstract NodeID update();
 	
 	public boolean isFamily(NodeID _id)
 	{
-		return (_id instanceof AbstractNodeID) ? getUUID().equals(_id.getUUID()) : false;
+		return (_id instanceof AbstractNodeID) ? getFamilyID().equals(_id.getFamilyID()) : false;
 	}
 }
--- a/src/treecms/tree/util/NodeAttributesImpl.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/tree/util/NodeAttributesImpl.java	Wed Jun 01 15:35:50 2011 +0900
@@ -2,10 +2,9 @@
 
 import java.nio.ByteBuffer;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-
+import java.util.concurrent.ConcurrentHashMap;
 import treecms.api.NodeAttributes;
 
 public class NodeAttributesImpl implements NodeAttributes
@@ -14,7 +13,7 @@
 	
 	public NodeAttributesImpl()
 	{
-		m_attrs = new HashMap<ByteBuffer,ByteBuffer>();
+		m_attrs = new ConcurrentHashMap<ByteBuffer,ByteBuffer>();
 	}
 	
 	public NodeAttributesImpl(Map<ByteBuffer,ByteBuffer> _map)
--- a/src/treecms/tree/util/NodeChildrenImpl.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/tree/util/NodeChildrenImpl.java	Wed Jun 01 15:35:50 2011 +0900
@@ -1,35 +1,37 @@
 package treecms.tree.util;
 
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
-import java.util.List;
-import treecms.api.Node;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 import treecms.api.NodeChildren;
+import treecms.api.NodeContext;
+import treecms.api.NodeID;
 
-/**
- * 子供ノードを格納するため専用のリストです.java.util.List<T>は継承しておりません.
- * 子供ノードのリストには リスト内に同じUUIDを持つNodeが存在 してはいけません.
- * @author shoshi
- */
-public class NodeChildrenImpl<T extends Node<T>> implements NodeChildren<T>
+public class NodeChildrenImpl<T extends NodeContext & NodeChildren<T>> implements NodeChildren<T>
 {
-	private List<T> m_list;
-	private Set<String> m_set;
+	private final Map<String,T> m_map;
+	private final List<T> m_list;
+	private final List<T> m_readOnlyList;
 	
 	public NodeChildrenImpl()
 	{
-		m_list = new ArrayList<T>();
-		m_set = new HashSet<String>();
+		m_map = new ConcurrentHashMap<String,T>();
+		m_list = new CopyOnWriteArrayList<T>();
+		m_readOnlyList = Collections.unmodifiableList(m_list);
 	}
 	
 	public NodeChildrenImpl(T... _args)
 	{
 		this();
 		for(T i : _args){
-			if(!add(i)){
-				throw new IllegalArgumentException("duplicate Node UUID at "+i.getID().getUUID());
+			String fid = i.getID().getFamilyID();
+			if(!m_map.containsKey(fid)){
+				m_map.put(fid,i);
+				m_list.add(i);
 			}
 		}
 	}
@@ -40,197 +42,160 @@
 		
 		if(_list != null){
 			addAll(_list);
+		}else{
+			throw new NullPointerException("_list is null");
 		}
 	}
 	
-	public List<T> getList()
+	@Override
+	public synchronized List<T> getList()
 	{
-		return Collections.unmodifiableList(m_list);
-	}
-	
-	public Set<String> getUUIDSet()
-	{
-		return Collections.unmodifiableSet(m_set);
+		return m_readOnlyList;
 	}
 	
 	@Override
-	public T replace(T _newChild)
+	public synchronized T replace(T _node)
 	{
-		String uuid = _newChild.getID().getUUID();
-		int size = m_list.size();
-		for(int i = 0;i < size;i ++){
-			T n = m_list.get(i);
-			if(uuid.equals(n.getID().getUUID())){
-				//_newChildと同一なUUIDを見つけた
-				return m_list.set(i,_newChild);
+		String fid = _node.getID().getFamilyID();
+		
+		T old = m_map.get(fid);
+		
+		if(old != null){
+			m_map.put(fid,_node);
+			
+			//find index of _node , better put index with node in the map?
+			int size = m_list.size();
+			for(int i = 0;i < size;i ++){
+				T n = m_list.get(i);
+				NodeID nid = n.getID();
+				if(nid.isFamily(nid)){
+					m_list.set(i,_node);
+					return old;
+				}
 			}
+			
+			throw new IllegalStateException("FamilyID is found on the map but not found on the list");
 		}
-		//見つからなかった
 		return null;
 	}
 	
-	/**
-	 * このリストに新しく子供を追加します.
-	 * @param _n
-	 * @return 追加に成功した場合true
-	 */
-	public boolean add(T _n)
+	@Override
+	public synchronized boolean add(T _n)
 	{
-		if(m_set.contains(_n.getID().getUUID())){
-			return false;
-		}
-		
-		m_set.add(_n.getID().getUUID());
-		m_list.add(_n);
-		return true;
-	}
-	
-	/**
-	 * _listに含まれている子供がすべてこのリストに含まれない場合にのみ、要素をすべて追加します。
-	 * @param _list
-	 * @return 追加に成功した場合true
-	 */
-	public boolean addAll(NodeChildren<T> _list)
-	{
-		if(Collections.disjoint(m_set,_list.getUUIDSet())){
-			//共通要素がない
-			m_set.addAll(_list.getUUIDSet());
-			m_list.addAll(_list.getList());
-			return true;
+		if(!m_map.containsKey(_n.getID().getFamilyID())){
+			m_map.put(_n.getID().getFamilyID(),_n);
+			return m_list.add(_n);
 		}
 		return false;
 	}
 	
-	/**
-	 * 指定されたNodeID
-	 * @param _id
-	 * @return 子供ノード
-	 */
-	public T get(String _uuid)
+	@Override
+	public synchronized boolean addAll(NodeChildren<T> _list)
 	{
-		for(T n : m_list){
-			String uuid = n.getID().getUUID();
-			if(uuid.equals(_uuid)){
-				return n;
+		if(Collections.disjoint(getFamilyIDSet(),_list.getFamilyIDSet())){
+		
+			HashMap<String,T> map = new HashMap<String,T>();
+			for(T item : _list.getList()){
+				NodeID id = item.getID();
+				map.put(id.getFamilyID(),item);
 			}
+			
+			return m_list.addAll(_list.getList());
 		}
-		
-		return null;
+		return false;
 	}
 	
-	/**
-	 * 指定された_indexの場所に位置する子供を削除します
-	 * @param _index
-	 * @return 消される子供ノード
-	 */
-	public T get(int _index)
+	@Override
+	public synchronized T get(int _index)
 	{
 		return m_list.get(_index);
 	}
 	
-	/**
-	 * 指定されたUUIDを持つ子どもを削除します
-	 * @param _id
-	 * @return 削除される子供ノード
-	 */
-	public T remove(String _uuid)
+	@Override
+	public synchronized T get(String _familyID)
 	{
-		int size = m_list.size();
-		
-		for(int i = 0;i < size;i ++){
-			String uuid = m_list.get(i).getID().getUUID();
-			if(uuid.equals(_uuid)){
-				//NodeIDのUUIDが一致した
-				return m_list.remove(i);
-			}
-		}
-		
-		return null;
-	}
-	
-	/**
-	 * 指定された場所の子供ノードを削除します
-	 * @param _index
-	 * @return 削除された子供ノード
-	 */
-	public T remove(int _index)
-	{
-		return m_list.remove(_index);
-	}
-	
-	/**
-	 * このリストに指定されたUUIDを持つNodeがあるか確認します
-	 * @param _id
-	 * @return 存在する場合true
-	 */
-	public boolean contains(String _uuid)
-	{
-		return m_set.contains(_uuid);
+		return m_map.get(_familyID);
 	}
 	
-	/**
-	 * 指定された二つのUUID(_uuid1,_uuid2)がリスト上に存在する場合、その二つの順番を入れ替えます
-	 * @param _uuid1 String
-	 * @param _uuid2 String
-	 * @return 成功した場合はtrue,NodeIDが見つからなかった場合はfalse
-	 */
-	public boolean swap(String _uuid1,String _uuid2)
+	@Override
+	public synchronized T remove(int _index)
 	{
-		/*
-		 * 二つのNodeIDの位置を求める
-		 */
-		int index1 = -1;
-		int index2 = -1;
-		
-		int size = m_list.size();
-		for(int i = 0;i < size && (index1 == -1 || index2 == 1);i ++){
-			String uuid = m_list.get(i).getID().getUUID();
-			if(uuid.equals(_uuid1)){
-				index1 = i;
-				continue;
-			}
-			
-			if(uuid.equals(_uuid2)){
-				index2 = i;
-				continue;
-			}
+		T n = m_list.remove(_index);
+		NodeID id = n.getID();
+		if(m_map.remove(id.getFamilyID()) != null){
+			return n; 
 		}
 		
-		/*
-		 * Collection.swapを使って入れ替える
-		 */
-		if(index1 != -1 && index2 != -1){
-			Collections.swap(m_list,index1,index2);
-			return true;
-		}
-		
-		//NodeIDがリスト上になかった
-		return false;
+		throw new IllegalStateException("");
 	}
 	
-	/**
-	 * 子供ノードのリストをクリアします
-	 */
-	public void clearChildren()
+	@Override
+	public synchronized boolean contains(NodeID _id)
 	{
-		m_set.clear();
+		T n = m_map.get(_id);
+		NodeID id = n.getID();
+		return id.equals(_id);
+	}
+	
+	@Override
+	public synchronized void clearChildren()
+	{
+		m_map.clear();
 		m_list.clear();
 	}
 	
 	@SuppressWarnings("unchecked")
 	@Override
-	public boolean equals(Object _o)
+	public synchronized boolean equals(Object _o)
 	{
 		NodeChildrenImpl<T> list = (NodeChildrenImpl<T>)_o;
 		return m_list.equals(list.m_list);
 	}
 	
 	@Override
-	public int hashCode()
+	public synchronized int hashCode()
 	{
 		int result = 17;
 		result = 37*result + m_list.hashCode();
-		result = 37*result + m_set.hashCode();
+		result = 37*result + m_map.hashCode();
 		return result;
 	}
+
+	@Override
+	public synchronized Set<String> getFamilyIDSet()
+	{
+		return m_map.keySet();
+	}
+
+	@Override
+	public synchronized T remove(String _fid)
+	{
+		return m_map.remove(_fid);
+	}
+
+	@Override
+	public synchronized boolean swap(String _fid1, String _fid2)
+	{
+		if(m_map.containsKey(_fid1) && m_map.containsKey(_fid2)){
+			int index1,index2;
+			index1 = index2 = -1;
+			int size = m_list.size();
+			for(int i = 0;i < size;i ++){
+				T n = m_list.get(i);
+				String fid = n.getID().getFamilyID();
+				
+				if(fid.equals(_fid1)){
+					index1 = i;
+				}else if(fid.equals(_fid2)){
+					index2 = i;
+				}
+				
+				if(index1 != -1 && index2 != -1){
+					Collections.swap(m_list, index1, index2);
+					return true;
+				}
+			}
+		}
+		return false;
+	}
 }
--- a/src/treecms/tree/util/NodeData.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/tree/util/NodeData.java	Wed Jun 01 15:35:50 2011 +0900
@@ -4,24 +4,15 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
-import treecms.api.Node;
 import treecms.api.NodeAttributes;
 import treecms.api.NodeChildren;
+import treecms.api.NodeContext;
+import treecms.api.NodeID;
 
-/**
- * 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>
+public class NodeData<T extends NodeContext & NodeAttributes & NodeChildren<T>> implements NodeAttributes , NodeChildren<T>
 {
-	private NodeChildrenImpl<T> m_children;
-	private NodeAttributesImpl m_attrs;
+	private final NodeChildrenImpl<T> m_children;
+	private final NodeAttributesImpl m_attrs;
 	
 	public NodeData()
 	{
@@ -46,12 +37,6 @@
 	}
 
 	@Override
-	public Set<String> getUUIDSet()
-	{
-		return m_children.getUUIDSet();
-	}
-
-	@Override
 	public boolean add(T _child)
 	{
 		return m_children.add(_child);
@@ -64,48 +49,30 @@
 	}
 
 	@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)
+	public T remove(int _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)
+	public boolean contains(NodeID _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();
@@ -164,4 +131,28 @@
 	{
 		m_attrs.clearAttributes();
 	}
+
+	@Override
+	public Set<String> getFamilyIDSet()
+	{
+		return m_children.getFamilyIDSet();
+	}
+
+	@Override
+	public T get(String _familyID)
+	{
+		return m_children.get(_familyID);
+	}
+
+	@Override
+	public T remove(String _familyID)
+	{
+		return m_children.get(_familyID);
+	}
+
+	@Override
+	public boolean swap(String _fid1, String _fid2)
+	{
+		return m_children.swap(_fid1,_fid2);
+	}
 }
--- a/src/treecms/tree/util/NodeFinder.java	Tue May 31 15:55:28 2011 +0900
+++ b/src/treecms/tree/util/NodeFinder.java	Wed Jun 01 15:35:50 2011 +0900
@@ -1,9 +1,10 @@
 package treecms.tree.util;
 
-import treecms.api.Node;
+import treecms.api.NodeChildren;
+import treecms.api.NodeContext;
 import treecms.api.NodeID;
 
-public class NodeFinder<T extends Node<T>>
+public class NodeFinder<T extends NodeContext & NodeChildren<T>>
 {
 	private T m_root;
 	public NodeFinder(T _root)
@@ -18,7 +19,7 @@
 			@Override
 			public boolean evaluate(T _target)
 			{
-				if(_target.getID().getUUID().equals(_uuid)){
+				if(_target.getID().getFamilyID().equals(_uuid)){
 					m_res = _target;
 					return true;
 				}