1 package org.oddjob.structural; 2 3 import java.util.ArrayList ; 4 import java.util.Iterator ; 5 import java.util.List ; 6 7 import org.oddjob.Resetable; 8 import org.oddjob.Stoppable; 9 import org.oddjob.Structural; 10 import org.oddjob.arooa.Lifecycle; 11 12 18 19 public class ChildHelper { 20 21 22 private final List jobList = new ArrayList (); 23 24 25 private final List listeners = new ArrayList (); 26 27 private final Object source; 28 29 34 public ChildHelper(Object source) { 35 this.source = source; 36 } 37 43 public void addChild(Object child) { 44 if (child == null) { 45 throw new NullPointerException ("Attempt to add a null child."); 46 } 47 48 int newIndex = 0; 49 synchronized (jobList) { 50 newIndex = jobList.size(); 51 jobList.add(child); 52 } 53 StructuralEvent event = new StructuralEvent(source, child, newIndex); 54 notifyChildAdded(event); 55 } 56 57 63 public void insertChild(int index, Object child) { 64 if (child == null) { 65 throw new NullPointerException ("Attempt to add a null child."); 66 } 67 68 synchronized (jobList) { 69 jobList.add(index, child); 70 } 71 StructuralEvent event = new StructuralEvent(source, child, index); 72 notifyChildAdded(event); 73 } 74 75 80 public void addChildren(Object [] children) { 81 for (int i = 0; i < children.length; ++i) { 82 addChild(children[i]); 83 } 84 } 85 86 93 public Object removeChildAt(int index) { 94 Object child = null; 95 96 synchronized (jobList) { 97 child = jobList.remove(index); 98 } 99 StructuralEvent event = new StructuralEvent(source, child, index); 100 101 notifyChildRemoved(event); 102 return child; 103 } 104 105 111 public void removeChild(Object child) { 112 int oldIndex = 0; 113 114 synchronized (jobList) { 115 oldIndex = jobList.indexOf(child); 116 if (oldIndex == -1) { 117 return; 118 } 119 jobList.remove(oldIndex); 120 } 121 StructuralEvent event = new StructuralEvent(source, child, oldIndex); 122 notifyChildRemoved(event); 123 } 124 125 132 public void replaceChild(Object child, Object replacement) { 133 int oldIndex = 0; 134 135 synchronized (jobList) { 136 oldIndex = jobList.indexOf(child); 137 if (oldIndex == -1) { 138 return; 139 } 140 removeChildAt(oldIndex); 141 insertChild(oldIndex, replacement); 142 } 143 } 144 145 152 public void removeAllChildren() { 153 while (true) { 154 int size = jobList.size(); 155 if (size == 0) { 156 break; 157 } 158 removeChildAt(size - 1); 159 } 160 } 161 162 166 public void stopChildren() { 167 Object [] children = getChildren(); 168 for (int i = 0; i < children.length; ++i) { 169 if (children[i] instanceof Stoppable) { 170 ((Stoppable)children[i]).stop(); 171 } 172 } 173 } 174 175 179 public void softResetChildren() { 180 Object [] children = getChildren(); 181 for (int i = 0; i < children.length; ++i) { 182 if (children[i] instanceof Resetable) { 183 ((Resetable)children[i]).softReset(); 184 } 185 } 186 } 187 188 192 public void hardResetChildren() { 193 Object [] children = getChildren(); 194 for (int i = 0; i < children.length; ++i) { 195 if (children[i] instanceof Resetable) { 196 ((Resetable)children[i]).hardReset(); 197 } 198 } 199 } 200 201 206 public Object [] getChildren() { 207 synchronized (jobList) { 208 return jobList.toArray(); 209 } 210 } 211 212 217 public Object getChildAt(int index) { 218 synchronized (jobList) { 219 return jobList.get(index); 220 } 221 } 222 223 228 public Object getChild() { 229 synchronized (jobList) { 230 if (jobList.size() == 0) { 231 return null; 232 } 233 if (jobList.size() > 1) { 234 throw new IllegalStateException ("Can't use getChild with more than one child!"); 235 } 236 return jobList.get(0); 237 } 238 } 239 240 244 public void addStructuralListener(StructuralListener listener) { 245 synchronized (listeners) { 248 Object [] children = getChildren(); 249 for (int i = 0; i < children.length; ++i) { 250 StructuralEvent event = new StructuralEvent(source, children[i], i); 251 listener.childAdded(event); 252 } 253 listeners.add(listener); 254 } 255 } 256 257 261 public void removeStructuralListener(StructuralListener listener) { 262 synchronized (listeners) { 263 listeners.remove(listener); 264 } 265 } 266 267 272 public int size() { 273 synchronized (jobList) { 274 return jobList.size(); 275 } 276 } 277 278 283 private void notifyChildAdded(StructuralEvent event) { 284 List copy = null; 285 synchronized (listeners) { 286 copy = new ArrayList (listeners); 287 } 288 for (Iterator it = copy.iterator(); it.hasNext() ;) { 289 ((StructuralListener)it.next()).childAdded(event); 290 } 291 } 292 293 298 private void notifyChildRemoved(StructuralEvent event) { 299 List copy = null; 300 synchronized (listeners) { 301 copy = new ArrayList (listeners); 302 } 303 for (Iterator it = copy.iterator(); it.hasNext() ;) { 304 ((StructuralListener)it.next()).childRemoved(event); 305 } 306 } 307 308 312 public void destroyAll() { 313 Lifecycle.destroy(getChildren()); 316 removeAllChildren(); 317 } 318 319 public static Object [] getChildren(Structural structural) { 320 class ChildCatcher implements StructuralListener { 321 List results = new ArrayList (); 322 public void childAdded(StructuralEvent event) { 323 synchronized (results) { 324 results.add(event.getIndex(), event.getChild()); 325 } 326 } 327 public void childRemoved(StructuralEvent event) { 328 synchronized (results) { 329 results.remove(event.getIndex()); 330 } 331 } 332 } 333 ChildCatcher cc = new ChildCatcher(); 334 structural.addStructuralListener(cc); 335 structural.removeStructuralListener(cc); 336 return cc.results.toArray(); 337 } 338 } 339 | Popular Tags |