Mercurial > hg > Members > shoshi > TreeCMSv2
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; + } }