1 19 20 package org.netbeans.modules.xml.xam; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Collections ; 27 import java.util.List ; 28 29 36 public abstract class AbstractComponent<C extends Component<C>> implements Component<C> { 37 private C parent; 38 private List <C> children = null; 39 private AbstractModel model; 40 41 public AbstractComponent(AbstractModel model) { 42 this.model = model; 43 } 44 45 protected abstract void appendChildQuietly(C component, List <C> children); 46 47 protected abstract void insertAtIndexQuietly(C newComponent, List <C> children, int index); 48 49 protected abstract void removeChildQuietly(C component, List <C> children); 50 51 protected abstract void populateChildren(List <C> children); 52 53 public final void removePropertyChangeListener(java.beans.PropertyChangeListener pcl) { 54 model.removePropertyChangeListener(pcl); 55 } 56 57 public final void addPropertyChangeListener(java.beans.PropertyChangeListener pcl) { 58 model.addPropertyChangeListener(new DelegateListener(pcl)); 59 } 60 61 public void removeComponentListener(ComponentListener cl) { 63 if (getModel() != null) { 64 getModel().removeComponentListener(cl); 65 } 66 } 67 68 public synchronized C getParent() { 69 return parent; 70 } 71 72 protected synchronized void setParent(C component) { 73 parent = component; 74 } 75 76 protected synchronized void setModel(AbstractModel aModel) { 77 model = aModel; 78 if (isChildrenInitialized()) { 79 for (C component : getChildren()) { 80 ((AbstractComponent)component).setModel(aModel); 81 } 82 } 83 } 84 85 private void _appendChildQuietly(C component, List <C> children) { 86 if (component.getModel() == null) { 87 throw new IllegalStateException ("Cannot add a removed component, should use a fresh or a copy component."); 88 } 89 appendChildQuietly(component, children); 90 ((AbstractComponent)component).setModel(getModel()); 91 ((AbstractComponent)component).setParent(this); 92 } 93 94 private void _insertAtIndexQuietly(C component, List <C> children, int index) { 95 if (component.getModel() == null) { 96 throw new IllegalStateException ("Cannot add a removed component, should use a fresh or a copy component."); 97 } 98 insertAtIndexQuietly(component, children, index); 99 ((AbstractComponent)component).setModel(getModel()); 100 ((AbstractComponent)component).setParent(this); 101 } 102 103 private void _removeChildQuietly(C component, List <C> children) { 104 removeChildQuietly(component, children); 105 ((AbstractComponent)component).setModel(null); 106 ((AbstractComponent)component).setParent(null); 107 } 108 109 113 public List <C> getChildren() { 114 _getChildren(); 115 return Collections.unmodifiableList(children); 116 } 117 118 123 protected final boolean isChildrenInitialized() { 124 return children != null; 125 } 126 127 private synchronized List <C> _getChildren() { 128 if (!isChildrenInitialized()) { 129 children = new ArrayList <C>(); 130 populateChildren(children); 131 for (C child : children) { 132 ((AbstractComponent)child).setParent(this); 133 } 134 } 135 return children; 136 } 137 138 145 public <T extends C>List <T> getChildren(Class <T> type) { 146 List <T> result = new ArrayList <T>(_getChildren().size()); 147 for (C child : _getChildren()) { 148 if (type.isAssignableFrom(child.getClass())) { 149 result.add(type.cast(child)); 150 } 151 } 152 return Collections.unmodifiableList(result); 153 } 154 155 162 public List <C> getChildren(Collection <Class <? extends C>> typeList) { 163 List <C> comps = new ArrayList <C>(); 164 for(Class <? extends C> type : typeList) { 167 comps.addAll(getChildren(type)); 168 } 169 return Collections.unmodifiableList(comps); 170 } 171 172 public synchronized AbstractModel getModel() { 173 return model; 174 } 175 176 protected void verifyWrite() { 177 getModel().validateWrite(); 178 } 179 180 protected void firePropertyChange(String propName, Object oldValue, Object newValue) { 181 PropertyChangeEvent event = 182 new PropertyChangeEvent (this,propName,oldValue,newValue); 183 getModel().firePropertyChangeEvent(event); 184 } 185 186 protected void fireValueChanged() { 187 getModel().fireComponentChangedEvent(new ComponentEvent(this, 188 ComponentEvent.EventType.VALUE_CHANGED)); 189 } 190 191 protected void fireChildRemoved() { 192 getModel().fireComponentChangedEvent(new ComponentEvent(this, 193 ComponentEvent.EventType.CHILD_REMOVED)); 194 } 195 196 protected void fireChildAdded() { 197 getModel().fireComponentChangedEvent(new ComponentEvent(this, 198 ComponentEvent.EventType.CHILD_ADDED)); 199 } 200 201 protected <T extends C> T getChild(Class <T> type) { 202 List <T> result = getChildren(type); 203 T value = null; 204 if (!result.isEmpty()) { 205 value = result.get(0); 206 } 207 return value; 208 } 209 210 213 protected synchronized void addBefore(String propertyName, C component, 214 Collection <Class <? extends C>> typeList){ 215 verifyWrite(); 216 checkNullOrDuplicateChild(component); 217 addChild(propertyName, component, typeList, true); 218 firePropertyChange(propertyName, null, component); 219 fireChildAdded(); 220 } 221 222 225 protected synchronized void addAfter(String propertyName, C component, 226 Collection <Class <? extends C>> typeList){ 227 verifyWrite(); 228 checkNullOrDuplicateChild(component); 229 addChild(propertyName, component, typeList, false); 230 firePropertyChange(propertyName, null, component); 231 fireChildAdded(); 232 } 233 234 242 private void addChild(String propertyName, C component, 243 Collection <Class <? extends C>> typeList, boolean before) { 244 assert(component != null); 245 246 if (typeList == null) { 247 throw new IllegalArgumentException ("typeList == null"); } 249 250 List <? extends C> childnodes = getChildren(); 251 if (typeList.isEmpty() || childnodes.isEmpty()) { 252 _appendChildQuietly(component, _getChildren()); 253 } else { 254 int lastIndex = before ? childnodes.size() : -1; 255 for (Class <? extends C> type : typeList) { 256 for (C child : childnodes) { 257 if (type.isAssignableFrom(child.getClass())) { 258 int i = childnodes.indexOf(child); 259 if (!before) { 260 if (i > lastIndex) lastIndex = i; 261 } else { 262 if (i < lastIndex) lastIndex = i; 263 } 264 } 265 } 266 } 267 if (!before) { 268 lastIndex++; 269 for (int i=lastIndex ; i<childnodes.size() ; i++) { 270 if (childnodes.get(i).getClass().equals(component.getClass())) { 271 lastIndex++; 272 } else { 273 break; 274 } 275 } 276 } 277 _insertAtIndexQuietly(component, _getChildren(), lastIndex); 278 } 279 } 280 281 protected void checkNullOrDuplicateChild(C child) { 282 if (child == null) { 283 throw new IllegalArgumentException ("child == null"); } 285 if (_getChildren().contains(child)) { 286 throw new IllegalArgumentException ("child already in children list"); } 288 } 289 290 protected synchronized void appendChild(String propertyName, C child) { 291 verifyWrite(); 292 checkNullOrDuplicateChild(child); 293 _appendChildQuietly(child, _getChildren()); 294 firePropertyChange(propertyName, null, child); 295 fireChildAdded(); 296 } 297 298 307 protected synchronized void insertAtIndex(String propertyName, 308 C component, int index, 309 Class <? extends C> type) { 310 verifyWrite(); 311 checkNullOrDuplicateChild(component); 312 if (type != null) { 313 int trueIndex = 0; 314 for (C child: getChildren()) { 315 if (type.isAssignableFrom(child.getClass())) { 316 break; 317 } 318 trueIndex++; 319 } 320 index += trueIndex; 321 } 322 _insertAtIndexQuietly(component, _getChildren(), index); 323 firePropertyChange(propertyName, null, component); 324 fireChildAdded(); 325 } 326 327 public synchronized void insertAtIndex(String propertyName, C component, int index) { 328 insertAtIndex(propertyName, component, index, null); 329 } 330 331 public synchronized void removeChild(String propertyName, C component) { 332 verifyWrite(); 333 if (component == null) { 334 throw new IllegalArgumentException ("component == null"); } 336 if (! _getChildren().contains(component)) { 337 throw new IllegalArgumentException ("component to be deleted is not a child"); } 339 _removeChildQuietly(component, _getChildren()); 340 firePropertyChange(propertyName, component, null); 341 fireChildRemoved(); 342 } 343 344 356 protected void setChild(Class <? extends C> classType, String propertyName, 357 C newComponent, Collection <Class <? extends C>> typeList){ 358 setChildAfter(classType, propertyName, newComponent, typeList); 359 } 360 361 protected void setChildAfter(Class <? extends C> classType, String propertyName, 362 C newComponent, Collection <Class <? extends C>> typeList){ 363 setChild(classType, propertyName, newComponent, typeList, false); 364 } 365 366 protected void setChildBefore(Class <? extends C> classType, String propertyName, 367 C newComponent, Collection <Class <? extends C>> typeList){ 368 setChild(classType, propertyName, newComponent, typeList, true); 369 } 370 371 protected synchronized void setChild(Class <? extends C> classType, String propertyName, 372 C newComponent, Collection <Class <? extends C>> typeList, boolean before){ 373 verifyWrite(); 375 List <? extends C> childComponents = getChildren(classType); 376 if (childComponents.contains(newComponent)) { 377 return; } 379 C old = childComponents.isEmpty() ? null : childComponents.get(childComponents.size()-1); 380 for (C child : childComponents) { 381 _removeChildQuietly(child, _getChildren()); 382 fireChildRemoved(); 383 } 384 if (newComponent != null) { 385 addChild(propertyName, newComponent, typeList, before); 386 fireChildAdded(); 387 } 388 389 firePropertyChange(propertyName, old, newComponent); 390 } 391 392 private class DelegateListener implements PropertyChangeListener { 393 private final PropertyChangeListener delegate; 394 395 public DelegateListener(PropertyChangeListener pcl) { 396 delegate = pcl; 397 } 398 399 public void propertyChange(PropertyChangeEvent evt) { 400 if (evt.getSource() == AbstractComponent.this) { 401 delegate.propertyChange(evt); 402 } 403 } 404 405 public boolean equals(Object obj) { 406 return delegate == obj; 407 } 408 409 public int hashCode() { 410 return delegate.hashCode(); 411 } 412 } 413 414 415 418 public boolean canPaste(Component child) { 419 return true; 420 } 421 } 422 423 | Popular Tags |