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

commit
author shoshi
date Wed, 01 Jun 2011 15:35:50 +0900
parents 168deb591f21
children f3150b37f9be
comparison
equal deleted inserted replaced
19:019ca5abb1f0 20:084de6909451
1 package treecms.tree.util; 1 package treecms.tree.util;
2 2
3 import java.util.ArrayList;
4 import java.util.Collections; 3 import java.util.Collections;
5 import java.util.HashSet; 4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
6 import java.util.Set; 7 import java.util.Set;
7 import java.util.List; 8 import java.util.concurrent.ConcurrentHashMap;
8 import treecms.api.Node; 9 import java.util.concurrent.CopyOnWriteArrayList;
9 import treecms.api.NodeChildren; 10 import treecms.api.NodeChildren;
10 11 import treecms.api.NodeContext;
11 /** 12 import treecms.api.NodeID;
12 * 子供ノードを格納するため専用のリストです.java.util.List<T>は継承しておりません. 13
13 * 子供ノードのリストには リスト内に同じUUIDを持つNodeが存在 してはいけません. 14 public class NodeChildrenImpl<T extends NodeContext & NodeChildren<T>> implements NodeChildren<T>
14 * @author shoshi
15 */
16 public class NodeChildrenImpl<T extends Node<T>> implements NodeChildren<T>
17 { 15 {
18 private List<T> m_list; 16 private final Map<String,T> m_map;
19 private Set<String> m_set; 17 private final List<T> m_list;
18 private final List<T> m_readOnlyList;
20 19
21 public NodeChildrenImpl() 20 public NodeChildrenImpl()
22 { 21 {
23 m_list = new ArrayList<T>(); 22 m_map = new ConcurrentHashMap<String,T>();
24 m_set = new HashSet<String>(); 23 m_list = new CopyOnWriteArrayList<T>();
24 m_readOnlyList = Collections.unmodifiableList(m_list);
25 } 25 }
26 26
27 public NodeChildrenImpl(T... _args) 27 public NodeChildrenImpl(T... _args)
28 { 28 {
29 this(); 29 this();
30 for(T i : _args){ 30 for(T i : _args){
31 if(!add(i)){ 31 String fid = i.getID().getFamilyID();
32 throw new IllegalArgumentException("duplicate Node UUID at "+i.getID().getUUID()); 32 if(!m_map.containsKey(fid)){
33 m_map.put(fid,i);
34 m_list.add(i);
33 } 35 }
34 } 36 }
35 } 37 }
36 38
37 public NodeChildrenImpl(NodeChildren<T> _list) 39 public NodeChildrenImpl(NodeChildren<T> _list)
38 { 40 {
39 this(); 41 this();
40 42
41 if(_list != null){ 43 if(_list != null){
42 addAll(_list); 44 addAll(_list);
43 } 45 }else{
44 } 46 throw new NullPointerException("_list is null");
45 47 }
46 public List<T> getList() 48 }
47 { 49
48 return Collections.unmodifiableList(m_list); 50 @Override
49 } 51 public synchronized List<T> getList()
50 52 {
51 public Set<String> getUUIDSet() 53 return m_readOnlyList;
52 { 54 }
53 return Collections.unmodifiableSet(m_set); 55
54 } 56 @Override
55 57 public synchronized T replace(T _node)
56 @Override 58 {
57 public T replace(T _newChild) 59 String fid = _node.getID().getFamilyID();
58 { 60
59 String uuid = _newChild.getID().getUUID(); 61 T old = m_map.get(fid);
60 int size = m_list.size(); 62
61 for(int i = 0;i < size;i ++){ 63 if(old != null){
62 T n = m_list.get(i); 64 m_map.put(fid,_node);
63 if(uuid.equals(n.getID().getUUID())){ 65
64 //_newChildと同一なUUIDを見つけた 66 //find index of _node , better put index with node in the map?
65 return m_list.set(i,_newChild); 67 int size = m_list.size();
66 } 68 for(int i = 0;i < size;i ++){
67 } 69 T n = m_list.get(i);
68 //見つからなかった 70 NodeID nid = n.getID();
71 if(nid.isFamily(nid)){
72 m_list.set(i,_node);
73 return old;
74 }
75 }
76
77 throw new IllegalStateException("FamilyID is found on the map but not found on the list");
78 }
69 return null; 79 return null;
70 } 80 }
71 81
72 /** 82 @Override
73 * このリストに新しく子供を追加します. 83 public synchronized boolean add(T _n)
74 * @param _n 84 {
75 * @return 追加に成功した場合true 85 if(!m_map.containsKey(_n.getID().getFamilyID())){
76 */ 86 m_map.put(_n.getID().getFamilyID(),_n);
77 public boolean add(T _n) 87 return m_list.add(_n);
78 {
79 if(m_set.contains(_n.getID().getUUID())){
80 return false;
81 }
82
83 m_set.add(_n.getID().getUUID());
84 m_list.add(_n);
85 return true;
86 }
87
88 /**
89 * _listに含まれている子供がすべてこのリストに含まれない場合にのみ、要素をすべて追加します。
90 * @param _list
91 * @return 追加に成功した場合true
92 */
93 public boolean addAll(NodeChildren<T> _list)
94 {
95 if(Collections.disjoint(m_set,_list.getUUIDSet())){
96 //共通要素がない
97 m_set.addAll(_list.getUUIDSet());
98 m_list.addAll(_list.getList());
99 return true;
100 } 88 }
101 return false; 89 return false;
102 } 90 }
103 91
104 /** 92 @Override
105 * 指定されたNodeID 93 public synchronized boolean addAll(NodeChildren<T> _list)
106 * @param _id 94 {
107 * @return 子供ノード 95 if(Collections.disjoint(getFamilyIDSet(),_list.getFamilyIDSet())){
108 */ 96
109 public T get(String _uuid) 97 HashMap<String,T> map = new HashMap<String,T>();
110 { 98 for(T item : _list.getList()){
111 for(T n : m_list){ 99 NodeID id = item.getID();
112 String uuid = n.getID().getUUID(); 100 map.put(id.getFamilyID(),item);
113 if(uuid.equals(_uuid)){ 101 }
114 return n; 102
115 } 103 return m_list.addAll(_list.getList());
116 } 104 }
117 105 return false;
118 return null; 106 }
119 } 107
120 108 @Override
121 /** 109 public synchronized T get(int _index)
122 * 指定された_indexの場所に位置する子供を削除します
123 * @param _index
124 * @return 消される子供ノード
125 */
126 public T get(int _index)
127 { 110 {
128 return m_list.get(_index); 111 return m_list.get(_index);
129 } 112 }
130 113
131 /** 114 @Override
132 * 指定されたUUIDを持つ子どもを削除します 115 public synchronized T get(String _familyID)
133 * @param _id 116 {
134 * @return 削除される子供ノード 117 return m_map.get(_familyID);
135 */ 118 }
136 public T remove(String _uuid) 119
137 { 120 @Override
138 int size = m_list.size(); 121 public synchronized T remove(int _index)
139 122 {
140 for(int i = 0;i < size;i ++){ 123 T n = m_list.remove(_index);
141 String uuid = m_list.get(i).getID().getUUID(); 124 NodeID id = n.getID();
142 if(uuid.equals(_uuid)){ 125 if(m_map.remove(id.getFamilyID()) != null){
143 //NodeIDのUUIDが一致した 126 return n;
144 return m_list.remove(i); 127 }
145 } 128
146 } 129 throw new IllegalStateException("");
147 130 }
148 return null; 131
149 } 132 @Override
150 133 public synchronized boolean contains(NodeID _id)
151 /** 134 {
152 * 指定された場所の子供ノードを削除します 135 T n = m_map.get(_id);
153 * @param _index 136 NodeID id = n.getID();
154 * @return 削除された子供ノード 137 return id.equals(_id);
155 */ 138 }
156 public T remove(int _index) 139
157 { 140 @Override
158 return m_list.remove(_index); 141 public synchronized void clearChildren()
159 } 142 {
160 143 m_map.clear();
161 /**
162 * このリストに指定されたUUIDを持つNodeがあるか確認します
163 * @param _id
164 * @return 存在する場合true
165 */
166 public boolean contains(String _uuid)
167 {
168 return m_set.contains(_uuid);
169 }
170
171 /**
172 * 指定された二つのUUID(_uuid1,_uuid2)がリスト上に存在する場合、その二つの順番を入れ替えます
173 * @param _uuid1 String
174 * @param _uuid2 String
175 * @return 成功した場合はtrue,NodeIDが見つからなかった場合はfalse
176 */
177 public boolean swap(String _uuid1,String _uuid2)
178 {
179 /*
180 * 二つのNodeIDの位置を求める
181 */
182 int index1 = -1;
183 int index2 = -1;
184
185 int size = m_list.size();
186 for(int i = 0;i < size && (index1 == -1 || index2 == 1);i ++){
187 String uuid = m_list.get(i).getID().getUUID();
188 if(uuid.equals(_uuid1)){
189 index1 = i;
190 continue;
191 }
192
193 if(uuid.equals(_uuid2)){
194 index2 = i;
195 continue;
196 }
197 }
198
199 /*
200 * Collection.swapを使って入れ替える
201 */
202 if(index1 != -1 && index2 != -1){
203 Collections.swap(m_list,index1,index2);
204 return true;
205 }
206
207 //NodeIDがリスト上になかった
208 return false;
209 }
210
211 /**
212 * 子供ノードのリストをクリアします
213 */
214 public void clearChildren()
215 {
216 m_set.clear();
217 m_list.clear(); 144 m_list.clear();
218 } 145 }
219 146
220 @SuppressWarnings("unchecked") 147 @SuppressWarnings("unchecked")
221 @Override 148 @Override
222 public boolean equals(Object _o) 149 public synchronized boolean equals(Object _o)
223 { 150 {
224 NodeChildrenImpl<T> list = (NodeChildrenImpl<T>)_o; 151 NodeChildrenImpl<T> list = (NodeChildrenImpl<T>)_o;
225 return m_list.equals(list.m_list); 152 return m_list.equals(list.m_list);
226 } 153 }
227 154
228 @Override 155 @Override
229 public int hashCode() 156 public synchronized int hashCode()
230 { 157 {
231 int result = 17; 158 int result = 17;
232 result = 37*result + m_list.hashCode(); 159 result = 37*result + m_list.hashCode();
233 result = 37*result + m_set.hashCode(); 160 result = 37*result + m_map.hashCode();
234 return result; 161 return result;
235 } 162 }
163
164 @Override
165 public synchronized Set<String> getFamilyIDSet()
166 {
167 return m_map.keySet();
168 }
169
170 @Override
171 public synchronized T remove(String _fid)
172 {
173 return m_map.remove(_fid);
174 }
175
176 @Override
177 public synchronized boolean swap(String _fid1, String _fid2)
178 {
179 if(m_map.containsKey(_fid1) && m_map.containsKey(_fid2)){
180 int index1,index2;
181 index1 = index2 = -1;
182 int size = m_list.size();
183 for(int i = 0;i < size;i ++){
184 T n = m_list.get(i);
185 String fid = n.getID().getFamilyID();
186
187 if(fid.equals(_fid1)){
188 index1 = i;
189 }else if(fid.equals(_fid2)){
190 index2 = i;
191 }
192
193 if(index1 != -1 && index2 != -1){
194 Collections.swap(m_list, index1, index2);
195 return true;
196 }
197 }
198 }
199 return false;
200 }
236 } 201 }