1 19 package org.netbeans.modules.xml.axi; 20 21 import java.beans.PropertyChangeEvent ; 22 import java.beans.PropertyChangeListener ; 23 import java.beans.PropertyChangeSupport ; 24 import java.util.ArrayList ; 25 import java.util.Arrays ; 26 import java.util.Collections ; 27 import java.util.List ; 28 import java.util.Set ; 29 import java.util.WeakHashMap ; 30 import org.netbeans.modules.xml.axi.Compositor.CompositorType; 31 import org.netbeans.modules.xml.axi.impl.AXIDocumentImpl; 32 import org.netbeans.modules.xml.axi.impl.AXIModelBuilder; 33 import org.netbeans.modules.xml.axi.impl.AXIModelImpl; 34 import org.netbeans.modules.xml.axi.impl.Util; 35 import org.netbeans.modules.xml.axi.visitor.AXIVisitor; 36 import org.netbeans.modules.xml.schema.model.Documentation; 37 import org.netbeans.modules.xml.schema.model.SchemaComponent; 38 import org.netbeans.modules.xml.xam.AbstractComponent; 39 import org.openide.util.WeakListeners; 40 41 46 public abstract class AXIComponent extends AbstractComponent<AXIComponent> 47 implements Cloneable , PropertyChangeListener { 48 49 53 public static enum ComponentType { 54 LOCAL, 55 SHARED, 56 PROXY, 57 REFERENCE 58 } 59 60 63 public AXIComponent(AXIModel model) { 64 super(model); 65 } 66 67 70 public AXIComponent(AXIModel model, SchemaComponent schemaComponent) { 71 super(model); 72 setPeer(schemaComponent); 73 } 74 75 78 public AXIComponent(AXIModel model, AXIComponent sharedComponent) { 79 super(model); 80 setSharedComponent(sharedComponent); 81 } 82 83 86 public abstract void accept(AXIVisitor visitor); 87 88 89 94 public int getIndex() { 95 return getIndex(true); 96 } 97 98 105 public int getIndex(boolean absolute) { 106 AXIComponent parent = getParent(); 107 if(parent == null || !isInModel()) 108 return -1; 109 List <AXIComponent> childs = Collections.emptyList(); 110 if(absolute) 111 childs = parent.getChildren(); 112 else 113 childs = parent.getChildren((Class <AXIComponent>)this.getClass()); 114 for(int i=0; i<childs.size(); i++) { 115 if(childs.get(i) == this) { 116 return i; 117 } 118 } 119 return -1; 120 } 121 122 130 public AXIComponent getOriginal() { 131 if(getComponentType() == ComponentType.REFERENCE) 132 return this; 133 134 if(getComponentType() == ComponentType.PROXY) 135 return getSharedComponent().getOriginal(); 136 137 return this; 138 } 139 140 143 public AXIComponent getSharedComponent() { 144 return sharedComponent; 145 } 146 147 150 public boolean isGlobal() { 151 return (getParent() instanceof AXIDocument); 152 } 153 154 157 protected void setSharedComponent(AXIComponent sharedComponent) { 158 this.sharedComponent = sharedComponent; 159 if(sharedComponent == null) { 160 return; 161 } 162 AXIModelImpl thisModel = (AXIModelImpl)getModel(); 163 if(thisModel == sharedComponent.getModel()) { 164 sharedComponent.addListener(this); 165 return; 166 } 167 168 thisModel.listenToReferencedModel(sharedComponent.getModel()); 170 } 171 172 175 public void addListener(AXIComponent proxy) { 176 if(getModel() != proxy.getModel()) 177 return; 178 179 if(pcs == null) 180 pcs = new PropertyChangeSupport (this); 181 182 PropertyChangeListener l = getWeakListener(proxy, false); 183 if(l != null) 184 pcs.addPropertyChangeListener(l); 185 } 186 187 190 public void removeListener(AXIComponent proxy) { 191 if(pcs == null) 192 return; 193 194 pcs.removePropertyChangeListener(getWeakListener(proxy, true)); 195 } 196 197 private void removeAllListeners() { 198 if(pcs == null) 199 return; 200 201 for(AXIComponent listener: getRefSet()) { 202 removeListener(listener); 203 } 204 } 205 206 209 public List <AXIComponent> getRefSet() { 210 if(pcs == null || listenerMap == null) 211 return null; 212 Set <AXIComponent> keySet = listenerMap.keySet(); 213 return Collections.unmodifiableList( 214 Arrays.asList(keySet.toArray(new AXIComponent[keySet.size()]))); 215 } 216 217 private PropertyChangeListener getWeakListener(AXIComponent proxy, boolean remove) { 218 if(listenerMap == null) { 219 listenerMap = new WeakHashMap <AXIComponent, PropertyChangeListener >(); 220 } 221 if(remove) 222 return listenerMap.remove(proxy); 223 224 if(proxy.getComponentType() != ComponentType.PROXY) { 225 Set <AXIComponent> keySet = listenerMap.keySet(); 226 for(AXIComponent key : keySet) { 227 if(key.getPeer() == proxy.getPeer()) 228 return null; 229 } 230 } 231 232 PropertyChangeListener listener = listenerMap.get(proxy); 233 if(listener == null) { 234 listener = (PropertyChangeListener )WeakListeners. 235 create(PropertyChangeListener .class, proxy, this); 236 listenerMap.put(proxy, listener); 237 return listener; 238 } 239 240 return null; 242 } 243 244 247 public String getDocumentation() { 248 if(getPeer() == null || 249 getPeer().getAnnotation() == null || 250 getPeer().getAnnotation().getDocumentationElements() == null) { 251 return null; 252 } 253 254 StringBuilder buffer = new StringBuilder (); 255 for(Documentation doc : getPeer().getAnnotation().getDocumentationElements()) { 256 buffer.append(doc.getContent()); 257 } 258 259 return buffer.toString(); 260 } 261 262 267 public boolean isReadOnly() { 268 if(!isInModel()) 269 return false; 270 271 return (getModel().isReadOnly() || getModel() != getOriginal().getModel()); 272 } 273 274 278 public boolean supportsCardinality() { 279 return (getParent() instanceof AXIDocument) ? false: true; 280 } 281 282 285 public boolean canVisitChildren() { 286 return super.isChildrenInitialized(); 287 } 288 289 292 public boolean isShared() { 293 ComponentType type = getComponentType(); 294 if(type == ComponentType.PROXY || type == ComponentType.REFERENCE) 295 return true; 296 297 return false; 298 } 299 300 305 public ComponentType getComponentType() { 306 if(getParent() instanceof AXIDocument) 307 return ComponentType.SHARED; 308 309 return ComponentType.LOCAL; 310 } 311 312 316 public ContentModel getContentModel() { 317 if(getComponentType() == ComponentType.PROXY) { 318 return getOriginal().getContentModel(); 319 } 320 321 if(this instanceof ContentModel) 322 return (ContentModel)this; 323 324 AXIComponent parent = getParent(); 325 if(parent == null || 326 parent instanceof AXIDocument || 327 parent instanceof Element) 328 return null; 329 330 return parent.getContentModel(); 331 } 332 333 336 public String getTargetNamespace() { 337 if(getComponentType() == ComponentType.PROXY) { 338 return getOriginal().getTargetNamespace(); 339 } 340 341 SchemaComponent peer = getPeer(); 342 return peer.getModel().getEffectiveNamespace(peer); 343 } 344 345 349 public AXIModel getModel() { 350 return (AXIModel)super.getModel(); 351 } 352 353 359 public Element getParentElement() { 360 AXIComponent parent = (AXIComponent)getParent(); 361 if(parent == null) 362 return null; 363 364 if(parent instanceof Element) 365 return (Element)parent; 366 367 return parent.getParentElement(); 368 } 369 370 373 public List <AbstractElement> getChildElements() { 374 List <AbstractElement> childrenElements = new ArrayList <AbstractElement>(); 375 populateChildElements(childrenElements, this); 376 return Collections.unmodifiableList(childrenElements); 377 } 378 379 private void populateChildElements(List <AbstractElement> childrenElements, 380 AXIComponent component) { 381 for(AXIComponent child : component.getChildren()) { 382 if( child instanceof ContentModel ) 383 continue; 384 385 if( child instanceof AbstractElement ) { 386 childrenElements.add((AbstractElement)child); 387 continue; 388 } 389 populateChildElements(childrenElements, child); 390 } 391 } 392 393 397 public final SchemaComponent getPeer() { 398 if(getComponentType() == ComponentType.REFERENCE) { 399 return peer; 400 } 401 402 if(getSharedComponent() != null) { 403 return getSharedComponent().getPeer(); 404 } 405 return peer; 406 } 407 408 411 public final void setPeer(SchemaComponent peer) { 412 if(getComponentType() == ComponentType.REFERENCE) { 413 this.peer = peer; 414 return; 415 } 416 417 if(getSharedComponent() != null) { 418 getSharedComponent().setPeer(peer); 419 return; 420 } 421 422 this.peer = peer; 423 } 424 425 protected void appendChildQuietly(AXIComponent newComponent, List <AXIComponent> children) { 429 if(getComponentType() == ComponentType.PROXY) { 430 getOriginal().appendChildQuietly(newComponent, children); 431 return; 432 } 433 434 children.add(newComponent); 435 } 436 437 protected void insertAtIndexQuietly(AXIComponent newComponent, List <AXIComponent> children, int index) { 438 if(getComponentType() == ComponentType.PROXY) { 439 getOriginal().insertAtIndexQuietly(newComponent, children, index); 440 return; 441 } 442 children.add(index, newComponent); 443 } 444 445 protected void removeChildQuietly(AXIComponent component, List <AXIComponent> children) { 446 if(getComponentType() == ComponentType.PROXY) { 447 getOriginal().removeChildQuietly(component, children); 448 return; 449 } 450 children.remove(component); 451 } 452 453 458 public void populateChildren(List <AXIComponent> children) { 459 if(getSharedComponent() != null) { 460 Util.addProxyChildren(this, getSharedComponent(), children); 461 return; 462 } 463 464 if(getPeer() == null) 466 return; 467 468 AXIModelBuilder builder = new AXIModelBuilder(this); 469 builder.populateChildren(getPeer(), true, children); 470 } 471 472 protected Object clone() throws CloneNotSupportedException { 473 return super.clone(); 474 } 475 476 public AXIComponent copy(AXIComponent parent) { 477 AXIComponentFactory f = parent.getModel().getComponentFactory(); 478 return f.copy(this); 479 } 480 481 485 protected boolean isInModel() { 486 if(this instanceof AXIDocument) 488 return getModel() != null; 489 490 return ( (getParent() != null) && (getModel() != null) ); 492 } 493 494 497 protected void firePropertyChangeEvent(String property, Object oldVal, Object newVal) { 498 if (!isInModel()) 499 return; 500 501 fireValueChanged(); 502 if(property != null) 503 firePropertyChange(property, oldVal, newVal); 504 if(pcs != null) 505 pcs.firePropertyChange(property, oldVal, newVal); 506 } 507 508 511 protected void appendChild(String property, AXIComponent child) { 512 if(getModel() != child.getModel()) 513 return; 514 515 super.appendChild(property, child); 516 if(pcs != null) 517 pcs.firePropertyChange(PROP_CHILD_ADDED, null, child); 518 519 if(this instanceof AXIDocumentImpl) 520 ((AXIDocumentImpl)this).addToCache(child); 521 } 522 523 526 public void insertAtIndex(String property, AXIComponent child, int index) { 527 if(getModel() != child.getModel()) 528 return; 529 530 super.insertAtIndex(property, child, index); 531 if(pcs != null) 532 pcs.firePropertyChange(PROP_CHILD_ADDED, null, child); 533 534 if(this instanceof AXIDocumentImpl) 535 ((AXIDocumentImpl)this).addToCache(child); 536 } 537 538 541 public void removeChild(String property, AXIComponent child) { 542 if(getModel() != child.getModel()) 543 return; 544 545 super.removeChild(property, child); 546 if(pcs != null) { 547 pcs.firePropertyChange(PROP_CHILD_REMOVED, child, null); 549 child.removeAllListeners(); 551 } 552 if(this instanceof AXIDocumentImpl) 553 ((AXIDocumentImpl)this).removeFromCache(child); 554 } 555 556 560 public final void appendChild(AXIComponent child) { 561 if(getComponentType() == ComponentType.PROXY && !getModel().inSync()) { 562 getOriginal().appendChild(child); 563 return; 564 } 565 566 appendChild(Util.getProperty(child), child); 567 } 568 569 573 public final void addChildAtIndex(AXIComponent child, int index) { 574 if(getComponentType() == ComponentType.PROXY && !getModel().inSync()) { 575 getOriginal().addChildAtIndex(child, index); 576 return; 577 } 578 579 insertAtIndex(Util.getProperty(child), child, index); 580 } 581 582 586 public final void removeChild(AXIComponent child) { 587 if(child.getComponentType() == ComponentType.REFERENCE) { 588 removeChild(Util.getProperty(child), child); 589 return; 590 } 591 592 if(child.getComponentType() == ComponentType.PROXY && 594 !getModel().inSync()) { 595 AXIComponent oChild = child.getOriginal(); 596 oChild.getParent().removeChild(oChild); 597 return; 598 } 599 600 removeChild(Util.getProperty(child), child); 601 } 602 603 607 public void removeAllChildren() { 608 List <AXIComponent> removedChildren = new ArrayList <AXIComponent>(); 609 for(AXIComponent child : getChildren()) { 610 removedChildren.add(child); 611 } 612 for(AXIComponent child : removedChildren) { 613 removeChild(Util.getProperty(child), child); 614 } 615 } 616 617 623 public void propertyChange(PropertyChangeEvent evt) { 624 AXIComponent source = (AXIComponent)evt.getSource(); 625 String property = evt.getPropertyName(); 626 if(!isInModel()) { 627 source.removeListener(this); 630 return; 632 } 633 if(PROP_CHILD_ADDED.equals(property)) { 635 onChildAdded(evt); 636 return; 637 } 638 if(PROP_CHILD_REMOVED.equals(property)) { 640 onChildDeleted(evt); 641 return; 642 } 643 644 firePropertyChangeEvent(evt.getPropertyName(), 645 evt.getOldValue(), evt.getNewValue()); 646 } 647 648 private void onChildAdded(PropertyChangeEvent evt) { 649 if(!isChildrenInitialized()) 650 return; 651 AXIComponent parent = (AXIComponent)evt.getSource(); 652 AXIComponent child = (AXIComponent)evt.getNewValue(); 653 int index = -1; 654 for(int i=0; i<parent.getChildren().size(); i++) { 655 if(parent.getChildren().get(i) == child) { 656 index = i; 657 break; 658 } 659 } 660 if(index == -1) 661 return; 662 663 AXIComponentFactory factory = getModel().getComponentFactory(); 664 AXIComponent proxy = factory.createProxy(child); 665 insertAtIndex(Util.getProperty(child), proxy, index); 666 } 667 668 private void onChildDeleted(PropertyChangeEvent evt) { 669 AXIComponent parent = (AXIComponent)evt.getSource(); 670 AXIComponent child = (AXIComponent)evt.getOldValue(); 671 if(child instanceof ContentModel) { 672 onContentModelDeleted((ContentModel)child); 673 return; 674 } 675 AXIComponent deletedChild = null; 676 for(AXIComponent c : getChildren()) { 677 if(c.getSharedComponent() == child) { 678 deletedChild = c; 679 break; 680 } 681 } 682 if(deletedChild == null) 683 return; 684 685 removeChild(Util.getProperty(deletedChild), deletedChild); 686 } 687 688 693 private void onContentModelDeleted(ContentModel contentModel) { 694 List <AXIComponent> removeList = new ArrayList <AXIComponent>(); 695 for(AXIComponent child : getChildren()) { 696 if(child.getContentModel() == contentModel) { 697 removeList.add(child); 698 } 699 } 700 for(AXIComponent child: removeList) { 701 child.getParent().removeChild(Util.getProperty(child), child); 702 } 703 } 704 705 711 private SchemaComponent peer; 712 713 716 protected AXIComponent sharedComponent; 717 private PropertyChangeSupport pcs; 718 private WeakHashMap <AXIComponent, PropertyChangeListener > listenerMap; 719 720 private static final String PROP_CHILD_ADDED = "child_added"; 721 private static final String PROP_CHILD_REMOVED = "child_removed"; 722 } 723 | Popular Tags |