diff src/treecms/tree/util/NodeChildrenImpl.java @ 20:084de6909451

commit
author shoshi
date Wed, 01 Jun 2011 15:35:50 +0900
parents 168deb591f21
children f3150b37f9be
line wrap: on
line diff
--- 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;
+	}
 }