1 19 20 package org.netbeans.modules.java.bridge; 21 22 import java.beans.*; 23 import java.io.IOException ; 24 import java.util.*; 25 import java.lang.ref.WeakReference ; 26 import org.netbeans.modules.java.JavaEditor; 27 28 import org.openide.nodes.Node; 29 import org.openide.nodes.CookieSet; 30 import org.openide.src.*; 31 import javax.jmi.reflect.RefObject; 32 import javax.jmi.reflect.InvalidObjectException; 33 import org.netbeans.api.mdr.MDRepository; 34 import org.netbeans.api.mdr.events.*; 35 import org.netbeans.jmi.javamodel.Array; 36 import org.netbeans.jmi.javamodel.Feature; 37 import org.netbeans.jmi.javamodel.JavaClass; 38 import org.netbeans.jmi.javamodel.TypeReference; 39 import org.netbeans.jmi.javamodel.ArrayReference; 40 import org.netbeans.jmi.javamodel.JavaModelPackage; 41 import org.netbeans.jmi.javamodel.MultipartId; 42 import org.netbeans.jmi.javamodel.NamedElement; 43 import org.netbeans.jmi.javamodel.ParameterizedType; 44 import org.netbeans.jmi.javamodel.PrimitiveType; 45 import org.netbeans.jmi.javamodel.PrimitiveTypeKind; 46 import org.netbeans.jmi.javamodel.PrimitiveTypeKindEnum; 47 import org.netbeans.jmi.javamodel.TypeParameter; 48 import org.netbeans.jmi.javamodel.UnresolvedClass; 49 import org.netbeans.mdr.handlers.InstanceHandler; 50 import org.netbeans.modules.java.JavaDataObject; 51 import org.netbeans.modules.javacore.ClassIndex; 52 import org.netbeans.modules.javacore.internalapi.JavaMetamodel; 53 import org.netbeans.modules.javacore.jmiimpl.javamodel.TypeClassImpl; 54 import org.openide.ErrorManager; 55 import org.openide.filesystems.FileObject; 56 import org.openide.text.CloneableEditorSupport; 57 import org.openide.util.RequestProcessor; 58 import org.openide.util.Utilities; 59 60 64 public abstract class ElementImpl implements Element.Impl, Element.Impl2, ElementProperties, Node.Cookie, ElementEvents { 65 66 public static final String JAVA_LANG_OBJECT = "java.lang.Object"; 68 protected static final boolean JDK15_CHECKS_DISABLED = "true".equalsIgnoreCase(System.getProperty("org.netbeans.java.bridge.disable_jdk15_checks", "true")); 70 72 private transient Element element; 73 74 77 private transient Collection propListeners; 78 79 83 private transient VetoableChangeSupport vetoSupport; 84 85 88 protected transient Binding binding; 89 90 93 private transient boolean valid; 94 95 99 private CookieSet cookieSet; 100 101 106 protected transient DefaultLangModel model; 107 108 112 private transient boolean inCreation; 113 114 protected JavaDocImpl javadoc; 115 116 119 protected transient org.netbeans.jmi.javamodel.Element javaElement; 120 121 protected transient JavaModelPackage javaModelPackage; 122 123 protected transient MDRepository repository; 124 125 private static final Binding NULL_BINDING = new NullBinding(); 126 127 130 private static final boolean DEBUG_EVENTS = false; 131 132 private static final long serialVersionUID = -6337836874152020892L; 133 134 135 protected ElementImpl(DefaultLangModel model) { 136 this.model = model; 137 this.javaElement = null; 138 this.inCreation = false; 139 this.valid = true; 140 this.repository = JavaMetamodel.getDefaultRepository (); 141 binding = NULL_BINDING; 142 } 143 144 protected ElementImpl(DefaultLangModel model, RefObject javaElement) { 145 this.model = model; 146 this.javaElement = (org.netbeans.jmi.javamodel.Element)javaElement; 147 this.inCreation = false; 148 this.valid = true; 149 this.repository = JavaMetamodel.getDefaultRepository (); 150 binding = NULL_BINDING; 151 repository.beginTrans(false); 152 try { 153 if (this.javaElement.isValid()) 154 javaModelPackage = (JavaModelPackage) javaElement.refImmediatePackage (); 155 } finally { 156 repository.endTrans(); 157 } 158 } 159 160 public RefObject getJavaElement () { 161 return javaElement; 162 } 163 164 public Type descrToType (org.netbeans.jmi.javamodel.Type type) { 165 return descrToType (TypeClassImpl.getRawType(type), null); 166 } 167 168 public Type descrToType (org.netbeans.jmi.javamodel.Type descr, String sourceName) { 169 if (descr == null) 170 return null; 171 if (descr instanceof TypeParameter) { 172 return Type.createClass (createClassIdentifier (JAVA_LANG_OBJECT)); 173 } 174 if (descr instanceof ParameterizedType) { 175 if (((ParameterizedType)descr).getParameters().size() == 0) { 176 descr = ((ParameterizedType)descr).getDefinition(); 177 } else { 178 if (sourceName == null) 179 return Type.createClass (createClassIdentifier (JAVA_LANG_OBJECT)); 180 else 181 return Type.createClass (createClassIdentifier (JAVA_LANG_OBJECT, sourceName)); 182 } 183 } 184 if (descr instanceof Array) { 185 return Type.createArray (descrToType (((Array) descr).getType ())); 186 } else if (descr instanceof JavaClass) { 187 String name = ((JavaClass) descr).getName (); 189 if (sourceName == null) 194 return Type.createClass (createClassIdentifier (name)); 195 else 196 return Type.createClass (createClassIdentifier (name, sourceName)); 197 } else { 198 PrimitiveTypeKind kind = ((PrimitiveType) descr).getKind (); 200 if (PrimitiveTypeKindEnum.BOOLEAN.equals (kind)) 201 return Type.BOOLEAN; 202 if (PrimitiveTypeKindEnum.INT.equals (kind)) 203 return Type.INT; 204 if (PrimitiveTypeKindEnum.CHAR.equals (kind)) 205 return Type.CHAR; 206 if (PrimitiveTypeKindEnum.BYTE.equals (kind)) 207 return Type.BYTE; 208 if (PrimitiveTypeKindEnum.SHORT.equals (kind)) 209 return Type.SHORT; 210 if (PrimitiveTypeKindEnum.LONG.equals (kind)) 211 return Type.LONG; 212 if (PrimitiveTypeKindEnum.FLOAT.equals (kind)) 213 return Type.FLOAT; 214 if (PrimitiveTypeKindEnum.DOUBLE.equals (kind)) 215 return Type.DOUBLE; 216 return descr != null ? Type.VOID : null; } 218 } 219 220 public org.netbeans.jmi.javamodel.Type typeToDescr (Type type) { 222 if (type.isArray ()) { 223 org.netbeans.jmi.javamodel.Type jmiType = typeToDescr(type.getElementType()); 224 JavaModelPackage pck = ((JavaModelPackage)jmiType.refImmediatePackage()); 225 return pck.getArray().resolveArray(jmiType); 226 } else { 227 if (type.isClass()) { 228 return getClassDescriptor(type.getClassName().getFullName()); 229 } else { 230 return (PrimitiveType) javaModelPackage.getType().resolve(type.getFullString()); 232 233 } 255 } 256 } 257 258 public TypeReference typeToTypeReference(Type type) { 259 if (type.isArray ()) { 260 int dimCount = 0; 261 do { 262 dimCount++; 263 type = type.getElementType(); 264 } while (type.isArray()); 265 String name = type.getSourceString(); 266 if (name == null) 267 name = type.getFullString(); 268 MultipartId parent = javaModelPackage.getMultipartId().createMultipartId(name, null, null); 269 return javaModelPackage.getArrayReference().createArrayReference("", parent, dimCount); 270 } else { 271 String name = type.getSourceString(); 272 if (name == null) 273 name = type.getFullString(); 274 return javaModelPackage.getMultipartId().createMultipartId(name, null, null); 275 } 276 } 277 278 public Type stringToType (String name) { 279 return stringToType(name, name); 280 } 281 282 public Type stringToType (String fullName, String sourceName) { 283 if ("boolean".equals(fullName)) return Type.BOOLEAN; 285 if ("int".equals (fullName)) return Type.INT; 287 if ("char".equals (fullName)) return Type.CHAR; 289 if ("byte".equals (fullName)) return Type.BYTE; 291 if ("short".equals (fullName)) return Type.SHORT; 293 if ("long".equals (fullName)) return Type.LONG; 295 if ("float".equals (fullName)) return Type.FLOAT; 297 if ("double".equals (fullName)) return Type.DOUBLE; 299 if ("void".equals (fullName) || fullName == null) return Type.VOID; 301 return Type.createClass (createClassIdentifier(fullName, sourceName)); 302 } 303 304 public Type typeReferenceToType (TypeReference descr) { 305 if (descr == null) 306 return null; 307 Type type = null; 308 if (descr instanceof ArrayReference) { 309 type = multipartIdToType(descr.getParent()); 310 int dimCount = ((ArrayReference) descr).getDimCount(); 311 for (int x = 0; x < dimCount; x++) { 312 type = Type.createArray (type); 313 } 314 } else { 315 type = multipartIdToType((MultipartId)descr); 316 } 317 return type; 318 } 319 320 private Type multipartIdToType(MultipartId id) { 321 String sourceName = multipartIdToName(id); 322 String fullName; 323 NamedElement elem = id.getElement(); 324 int resolved = Identifier.RESOLVED; 325 if (elem instanceof PrimitiveType) 326 return stringToType(sourceName, null); 327 if (JAVA_LANG_OBJECT.equals(sourceName)) { 328 fullName = sourceName; 329 } else { 330 if (elem != null && (elem instanceof JavaClass)) { 331 fullName = ((JavaClass) elem).getName(); 332 } else { 333 fullName = null; 334 } 335 336 if (fullName == null) { 339 fullName = sourceName; 340 resolved = Identifier.UNRESOLVED; 341 } 342 } 343 return Type.createClass(Identifier.create(fullName, sourceName, resolved)); 344 } 345 346 public org.netbeans.jmi.javamodel.Type getClassDescriptor (String fullName) { 349 return javaModelPackage.getType().resolve(fullName); 350 } 353 354 public Identifier createClassIdentifier (MultipartId id) { 355 String sourceName = multipartIdToName(id); 356 String fullName = null; 357 JavaClass jcls = (JavaClass)id.getElement(); 358 if (JAVA_LANG_OBJECT.equals(sourceName)) { 359 fullName = sourceName; 360 } else { 361 fullName = jcls == null ? sourceName : typeToFullName(jcls); 362 } 363 int resolved = Identifier.RESOLVED; 364 365 if (jcls == null || jcls instanceof UnresolvedClass) 366 resolved = Identifier.UNRESOLVED; 367 368 return Identifier.create(fullName, sourceName, resolved); 369 } 370 371 public static String multipartIdToName(MultipartId id) { 372 LinkedList list = new LinkedList(); 373 while (id != null) { 374 375 if (!id.getTypeArguments().isEmpty()) { 376 return JAVA_LANG_OBJECT; 377 } 378 379 list.addFirst(id.getName()); 380 id = id.getParent(); 381 } 382 StringBuffer buf = new StringBuffer (); 383 for (Iterator iter = list.iterator(); iter.hasNext();) { 384 buf.append((String )iter.next()); 385 if (iter.hasNext()) 386 buf.append('.'); 387 } 388 return buf.toString(); 389 } 390 391 public String typeToFullName(JavaClass jc) { 392 if (jc instanceof ParameterizedType) { 393 ParameterizedType p = (ParameterizedType) jc; 394 StringBuffer buf = new StringBuffer (); 395 buf.append(typeToFullName(p.getDefinition())); 396 List pars = p.getParameters(); 397 if (pars.size() > 0) { 398 buf.append('<'); 399 for (Iterator iter = pars.iterator(); iter.hasNext(); ) { 400 JavaClass par = (JavaClass) iter.next(); 401 buf.append(typeToFullName(par)); 402 if (iter.hasNext()) 403 buf.append(','); 404 } 405 buf.append('>'); 406 } 407 return buf.toString(); 408 } else { 409 return jc.getName(); 410 } 411 } 412 413 public Identifier createClassIdentifier (String fullName) { 414 return createClassIdentifier (fullName, fullName); 415 } 416 417 public Identifier createClassIdentifier (String fullName, String sourceName) { 418 420 repository.beginTrans(false); 422 try { 423 setClassPath(); 424 boolean exists = ClassIndex.hasClass(fullName, JavaMetamodel.getManager().getClassPath()); 425 return Identifier.create ( 427 fullName, sourceName, 428 exists ? Identifier.RESOLVED : Identifier.UNRESOLVED 429 ); 430 } finally { 431 repository.endTrans(false); 432 } 433 } 434 435 public void checkIsValid () throws SourceException { 436 if (!javaElement.isValid()) { 437 throwIsInvalid (); 438 } 439 } 440 441 public void throwIsInvalid () throws SourceException { 442 Util.throwException("Element was deleted", "EXC_ElementInvalid"); } 444 445 public abstract void connectListener (); 446 447 451 public void attachedToElement(Element el) { 452 this.element = el; 453 if (!valid) 454 return; 455 repository.beginTrans (false); 456 try { 457 if (!javaElement.isValid()) { 458 setValid(false); 459 } else { 460 connectListener (); 461 setValid (true); 462 } 463 } finally { 464 repository.endTrans (false); 465 } 466 } 467 468 475 public void setBinding(Binding b) { 476 if (this.binding != null) 477 return; 478 if (b instanceof Node.Cookie) { 479 getCookieSet().add((Node.Cookie)b); 480 } 481 binding = b; 482 } 483 484 487 private String describeEvent(PropertyChangeEvent evt) { 488 StringBuffer sb = new StringBuffer (); 489 sb.append(evt.getPropertyName()); 490 Object oldV = evt.getOldValue(); 491 sb.append(" old = " + describeValue(evt.getOldValue())); sb.append(" new = " + describeValue(evt.getNewValue())); return sb.toString(); 494 } 495 496 private String describeValue(Object o) { 497 if (o instanceof Identifier) { 498 Identifier id = (Identifier)o; 499 return id.getSourceName() + "/" + id.getFullName() + "/" + id.getResolutionStatus(); 501 } else if (o instanceof Identifier[]) { 502 StringBuffer sb = new StringBuffer (); 503 sb.append("[ "); Identifier[] ids = (Identifier[])o; 505 for (int i = 0; i < ids.length; i++) { 506 if (i > 0) 507 sb.append(", "); sb.append(describeValue(ids[i])); 509 } 510 sb.append(" ]"); return sb.toString(); 512 } else if (o instanceof MethodParameter[]) { 513 MethodParameter[] pars = (MethodParameter[])o; 514 if (pars.length == 0) 515 return "()"; StringBuffer sb = new StringBuffer (); 517 for (int i = 0; i < pars.length; i++) { 518 if (i > 0) 519 sb.append(", "); sb.append(pars[i].getSourceString()); 521 sb.append("/"); Type t = pars[i].getType(); 523 sb.append(t.getFullString()); 524 while (t.isArray()) 525 t = t.getElementType(); 526 if (t.isClass()) { 527 sb.append('/'); 528 sb.append(new Integer (t.getTypeIdentifier().getResolutionStatus()).toString()); 529 } 530 } 531 return sb.toString(); 532 } else if (o instanceof Type) { 533 Type t = (Type)o; 534 String s = t.getSourceString() + "/" + t.getFullString(); while (t.isArray()) 536 t = t.getElementType(); 537 if (t.isClass()) { 538 s = s + "/" + t.getTypeIdentifier().getResolutionStatus(); } 540 return s; 541 } else if (o != null) { 542 return o.toString(); 543 } else return "null"; } 545 546 548 public void addPropertyChangeListener (PropertyChangeListener l) { 549 if (DEBUG_EVENTS) { 550 System.err.println("[" + this + "] attaching listener " + l); } 552 if (propListeners == null) { 553 synchronized (this) { 554 if (propListeners == null) { 556 propListeners = new LinkedList(); 557 initializeListenerSupport(); 558 } 559 } 560 } 561 synchronized (propListeners) { 562 propListeners.add(l); 563 } 564 } 565 566 570 protected boolean isCreated() { 571 return this.inCreation; 572 } 573 574 575 public void removePropertyChangeListener (PropertyChangeListener l) { 576 if (DEBUG_EVENTS) { 577 System.err.println("[" + this + "] removing listener " + l); } 579 if (propListeners != null) { 580 synchronized (propListeners) { 581 propListeners.remove(l); 582 } 583 } 584 } 585 586 587 public void addVetoableChangeListener (VetoableChangeListener l) { 588 if (DEBUG_EVENTS) { 589 System.err.println("[" + this + "] attaching veto listener " + l); } 591 if (vetoSupport == null) { 592 synchronized (this) { 593 if (vetoSupport == null) { 595 vetoSupport = new VetoableChangeSupport (element); 596 initializeListenerSupport(); 597 } 598 } 599 } 600 vetoSupport.addVetoableChangeListener (l); 601 } 602 603 604 public void removeVetoableChangeListener (VetoableChangeListener l) { 605 if (DEBUG_EVENTS) { 606 System.err.println("[" + this + "] removing veto listener " + l); } 608 if (vetoSupport != null) { 609 vetoSupport.removeVetoableChangeListener (l); 610 } 611 } 612 613 614 public boolean hasVetoableListeners (String propName) { 615 if (vetoSupport == null) 616 return false; 617 else 618 return vetoSupport.hasListeners (propName); 619 } 620 621 623 public void markCurrent(boolean beforeAfter) { 624 } 626 627 629 public final Element getElement() { 630 return element; 631 } 632 633 638 public final CookieSet getCookieSet() { 639 if (cookieSet == null) { 640 synchronized (this) { 641 if (cookieSet == null) { 642 cookieSet = new CookieSet(); 643 initializeCookies(cookieSet); 644 } 645 } 646 } 647 return cookieSet; 648 } 649 650 protected void initializeCookies(CookieSet set) { 651 set.add(this); 652 } 653 654 658 public boolean isValid() { 659 return this.valid; 660 } 661 662 665 671 protected final void firePropertyChange(String name, Object o, Object n) { 672 fireOwnPropertyChange(new PropertyChangeEvent(getElement(), name, o, n)); 673 } 674 675 678 protected final void firePropertyChangeEvent(PropertyChangeEvent evt) { 679 if (DEBUG_EVENTS) { 680 StringBuffer sb = new StringBuffer (); 681 sb.append('['); 682 sb.append(toString()); 683 sb.append("] Dispatching change: "); sb.append(describeEvent(evt)); 685 System.err.println(sb.toString()); 686 } 687 if (propListeners == null) 688 return; 689 690 Vector listeners; 691 synchronized (propListeners) { 692 listeners = new Vector(propListeners); 693 } 694 for (int i = 0; i < listeners.size(); i++) { 695 PropertyChangeListener l = (PropertyChangeListener)listeners.elementAt(i); 696 l.propertyChange(evt); 697 } 698 } 699 700 710 protected final void fireOwnPropertyChange(PropertyChangeEvent evt) { 711 if (evt==null) 712 return; 713 714 723 724 726 firePropertyChangeEvent (evt); 727 734 } 735 736 protected Element cloneSelf() { 737 throw new UnsupportedOperationException ("clone unsupported on " + getClass()); 739 } 740 741 747 public final void addPropertyChange(PropertyChangeEvent evt) { 748 if (isCreated()) 749 return; 750 getModelImpl().getEventQueue().addPropertyChange(this, evt); 751 } 752 753 758 protected final void fireVetoableChange(String name, Object o, Object n) throws PropertyVetoException { 759 if (isCreated()) 760 return; 761 if (vetoSupport != null) { 762 try { 763 getModelImpl().notifyEventsDispatched(true); 764 vetoSupport.fireVetoableChange(name, o, n); 765 } finally { 766 getModelImpl().notifyEventsDispatched(false); 767 } 768 } 769 } 770 771 775 public final void fireVetoableChange(PropertyChangeEvent evt) throws SourceException { 776 if (isCreated()) 777 return; 778 checkVetoablePropertyChange(evt); 779 } 780 781 private void doFireVetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { 782 if (DEBUG_EVENTS) { 783 StringBuffer sb = new StringBuffer (); 784 sb.append('['); 785 sb.append(toString()); 786 sb.append("] Dispatching veto: "); sb.append(describeEvent(evt)); 788 System.err.println(sb.toString()); 789 } 790 if (vetoSupport != null) { 791 try { 792 getModelImpl().notifyEventsDispatched(true); 793 vetoSupport.fireVetoableChange(evt); 794 } finally { 795 getModelImpl().notifyEventsDispatched(false); 796 } 797 } 798 } 799 800 805 protected void checkVetoablePropertyChange(PropertyChangeEvent evt) throws SourceException { 806 if (isCreated() || !isConstrained()) 807 return; 808 809 try { 810 doFireVetoableChange(evt); 811 } catch (SourceVetoException ex) { 812 throw ex.getNestedException(); 814 } catch (PropertyVetoException ex) { 815 throw new SourceException(ex.getMessage()); 818 } 819 } 820 821 832 public final Binding getBinding() { 833 if (isCreated()) 834 return NULL_BINDING; 835 return this.binding; 836 } 837 838 842 public final Binding getRawBinding() { 843 return getBinding (); 844 } 845 846 850 protected void invalidate() { 851 setValid(false); 852 } 853 854 private void setValid(boolean valid) { 855 boolean old = this.valid; 856 if (old == valid) 857 return; 858 this.valid = valid; 859 if (old) 860 fireOwnPropertyChange(new PropertyChangeEvent(getEventSource(), 862 PROP_VALID, 863 valid ? Boolean.FALSE : Boolean.TRUE, 864 valid ? Boolean.TRUE : Boolean.FALSE 865 )); 866 } 867 868 873 protected void checkValid(Object lockToken) throws SourceException { 874 if (isValid()) { 875 return; 876 } 877 releaseLock(lockToken); 878 Util.throwException("Element was deleted", "EXC_ElementInvalid"); } 880 881 public void checkDocument() { 882 JavaDataObject jdo = model.getJavaDataObject(); 883 CloneableEditorSupport edSupport = (CloneableEditorSupport) jdo.getCookie (JavaEditor.class); 884 if (!edSupport.isDocumentLoaded()) { 885 try { 886 edSupport.openDocument(); 887 } catch (IOException e) { 888 ErrorManager.getDefault().notify(e); 889 } 890 } 891 } 892 893 public void setClassPath() { 894 JavaDataObject jdo = model.getJavaDataObject(); 895 FileObject fo = jdo.getPrimaryFile(); 896 JavaMetamodel.getManager().setClassPath(fo); 897 } 898 899 902 protected abstract void checkWritable(boolean unsafeOp) throws SourceException; 903 904 908 public Node.Cookie getCookie(Class desired) { 909 if (desired.isAssignableFrom(getClass())) 911 return this; 912 Node.Cookie ret = getCookieSet().getCookie(desired); 914 if (ret != null) 915 return ret; 916 return getModelImpl().findElementCookie(getElement(), desired); 917 } 918 919 920 922 protected abstract SourceElementImpl findSource(); 923 924 protected void createAfter(Binding.Container cb, Binding refBinding) 927 throws SourceException { 928 inCreation = false; 929 cb.insert(binding, refBinding); 930 setValid(true); 931 } 932 933 protected abstract boolean parentValid(); 934 935 public void notifyConnectionChange (Element old) { 936 getModelImpl().fireElementChanged (old, getElement ()); 937 } 938 939 public void notifyConnectionAdd (Element newElem) { 940 getModelImpl().fireElementAdded (newElem); 941 } 942 943 public void notifyConnectionRemove (Element removedElem) { 944 getModelImpl().fireElementRemoved (removedElem); 945 } 946 947 public void notifyConnectionSet (Element oldElem, Element newElem) { 948 getModelImpl().fireElementSet (oldElem, newElem); 949 } 950 951 protected void notifyCreate() { 952 inCreation = false; 953 setValid(true); 954 if (parentValid()) 955 notifyElementCreated(); 956 } 957 958 protected void notifyElementCreated() { 959 getModelImpl().getEventQueue().elementCreated(getElement()); 960 } 961 962 protected void setJavaDocText(String content, boolean raw) throws SourceException { 963 if (!(javaElement instanceof Feature)) { 964 return; 965 } 966 967 checkWritable(false); 968 checkDocument(); 969 boolean failed = true; 970 repository.beginTrans (true); 971 try { 972 if (javaElement.isValid()) { 973 setClassPath(); 974 String oldContent = raw ? javadoc.getRawText() : javadoc.getText(); 975 if (content == oldContent || (content != null && oldContent != null && 976 content.equals(oldContent))) { 977 failed = false; 978 return; 979 } 980 javadoc.changeJavaDocText(content, raw); 981 ((Feature) javaElement).setJavadocText(javadoc.getRawText ()); 982 failed = false; 983 } else { 984 failed = false; 985 throwIsInvalid (); 986 } 987 } finally { 988 repository.endTrans (failed); 989 } 990 } 991 992 protected void changeJavaDocTags(JavaDocTag[] tags, int action) 993 throws SourceException { 994 995 if (!(javaElement instanceof Feature)) { 996 return; 997 } 998 999 checkWritable(false); 1000 checkDocument(); 1001 boolean failed = true; 1002 repository.beginTrans (true); 1003 try { 1004 if (javaElement.isValid()) { 1005 setClassPath(); 1006 String oldContent = javadoc.getRawText(); 1007 javadoc.changeJavaDocTags(tags, action); 1008 ((Feature) javaElement).setJavadocText(javadoc.getRawText ()); 1009 failed = false; 1010 } else { 1011 failed = false; 1012 throwIsInvalid (); 1013 } 1014 } finally { 1015 repository.endTrans (failed); 1016 } 1017 } 1018 1019 public void fireJavaDocChange () { 1020 fireOwnPropertyChange (new PropertyChangeEvent(getEventSource(), PROP_JAVADOC, null, null)); 1021 } 1022 1023 1026 protected void notifyRemove() { 1027 invalidate(); 1028 getModelImpl().getEventQueue().elementRemoved(getElement()); 1029 } 1030 1031 1035 protected void checkRemove() throws SourceException { 1036 if (isCreated() || !isConstrained()) 1037 return; 1038 PropertyChangeEvent evt = new PropertyChangeEvent(getElement(), 1039 PROP_VALID, Boolean.TRUE, Boolean.FALSE); 1040 checkVetoablePropertyChange(evt); 1041 } 1042 1043 1046 protected boolean hasListeners(String propName) { 1047 if (vetoSupport.hasListeners(propName)) 1048 return true; 1049 if (propListeners == null) 1050 return false; 1051 synchronized (propListeners) { 1052 return !propListeners.isEmpty(); 1053 } 1054 } 1055 1056 1061 protected void runAtomic(ExceptionRunnable r) throws SourceException { 1062 model.runAtomic(r); 1063 } 1064 1065 protected void initializeListenerSupport() { 1066 } 1067 1068 1072 public final Object getEventSource() { 1073 return getElement(); 1074 } 1075 1076 1080 public final ElementImpl getElementImpl() { 1081 return this; 1082 } 1083 1084 protected abstract void setParent(ElementImpl parent); 1085 1086 protected void setParent(Element parent) { 1087 setParent((ElementImpl)parent.getCookie(ElementImpl.class)); 1088 } 1089 1090 1094 protected final DefaultLangModel getModelImpl() { 1095 return this.model; 1096 } 1097 1098 1104 protected final Object takeLock() { 1105 if (isCreated()) 1106 return null; 1107 Object o = getModelImpl().writeLock(); 1108 return o; 1109 } 1110 1111 1116 protected final void releaseLock(Object o){ 1117 if (isCreated()) 1118 return; 1119 getModelImpl().releaseWriteLock(o); 1120 } 1121 1122 protected final void takeReadLock() { 1123 getModelImpl().readLock(); 1124 } 1125 1126 protected final void releaseReadLock() { 1127 getModelImpl().releaseReadLock(); 1128 } 1129 1130 1137 protected final Object takeMasterLock() throws SourceException { 1138 if (isCreated()) 1139 return null; 1140 Object l = getModelImpl().masterWriteLock(); 1141 checkValid(l); 1142 return l; 1143 } 1144 1145 protected abstract void createFromModel(Element model) throws SourceException; 1146 1147 1151 protected final void commit() { 1152 if (!isValid()) 1153 return; 1154 getModelImpl().commitChanges(); 1155 } 1156 1157 1163 protected final boolean isConstrained() { 1164 return getModelImpl().isConstrained(); 1165 } 1166 1167 protected Identifier createLocalIdentifier(Identifier id, int status) { 1168 if (id.getResolutionStatus() == status) 1169 return id; 1170 return Identifier.create(id.getFullName(), id.getSourceName(), status); 1171 } 1172 1173 protected boolean checkIdentifierContext(Identifier id) { 1174 return false; 1175 } 1176 1177 1179 static abstract class ElementListener implements MDRChangeListener { 1180 1181 public static boolean REGISTER_LISTENER = true; 1182 1183 protected RefObject javaElement; 1184 protected LWeakReference ref; 1185 protected ElementImpl impl; 1186 protected Object source; 1187 1188 public boolean isValid = true; 1189 1190 ElementListener (ElementImpl impl) { 1191 javaElement = impl.getJavaElement (); 1192 ref = new LWeakReference (impl, this); 1193 } 1194 1195 public ElementImpl getImpl () { 1196 return (ElementImpl) ref.get(); 1197 } 1198 1199 public RefObject getJavaElement () { 1200 return javaElement; 1201 } 1202 1203 public void connect () { 1204 if (REGISTER_LISTENER) { 1205 for (Iterator iter = ((InstanceHandler) javaElement).getListeners().iterator(); iter.hasNext(); ) { 1206 Object listener = iter.next(); 1207 if (listener instanceof ElementListener) { 1208 ((ElementListener) listener).checkValidity(); 1209 } 1210 } 1211 ((MDRChangeSource) javaElement).addListener (this); 1212 isValid = true; 1213 } 1214 } 1215 1216 public void remove () { 1217 try { 1218 ((MDRChangeSource) javaElement).removeListener (this); 1219 } catch (InvalidObjectException e) { 1220 } 1221 isValid = false; 1222 } 1223 1224 void doRemove() { 1225 MDRepository repository = JavaMetamodel.getDefaultRepository(); 1226 repository.beginTrans(false); 1227 try { 1228 remove (); 1229 } finally { 1230 repository.endTrans(false); 1231 } 1232 } 1233 1234 public void checkValidity() { 1235 if (ref.get() == null) { 1236 doRemove (); 1237 } 1238 } 1239 1240 public final void change(MDRChangeEvent event) { 1241 if (!isValid) 1242 return; 1243 1244 try { 1245 impl = (ElementImpl) ref.get(); 1246 if (impl == null) { 1247 doRemove(); 1248 return; 1249 } 1250 source = event.getSource (); 1251 1252 if (source == javaElement) { 1253 if (event.isOfType (InstanceEvent.EVENT_INSTANCE_DELETE)) { 1254 doRemove (); 1255 impl.setValid (false); 1256 return; 1257 } 1258 } 1259 try{ 1260 doChange (event); 1261 } catch (InvalidObjectException e) { 1262 doRemove(); 1263 impl.setValid(false); 1264 } 1265 impl = null; 1266 source = null; 1267 } catch (RuntimeException e) { 1268 System.out.println("Exception in Listener.change () thrown !!"); e.printStackTrace (); 1270 throw e; 1271 } 1272 } 1273 1274 public void doChange (MDRChangeEvent event) { 1275 if ((source instanceof Feature) && (event instanceof AttributeEvent) && 1276 "javadoc".equals(((AttributeEvent) event).getAttributeName ())) { impl.fireJavaDocChange (); 1278 } 1279 } 1280 1281 } 1282 1283 1285 static class LWeakReference extends WeakReference implements Runnable { 1286 1287 private static RequestProcessor CLEANUP_RP; 1288 1289 private ElementListener listener; 1290 1291 public LWeakReference (Object ref, ElementListener listener) { 1292 super (ref, Utilities.activeReferenceQueue ()); 1293 this.listener = listener; 1294 } 1295 1296 public void run() { 1297 synchronized(LWeakReference.class) { 1298 if (CLEANUP_RP == null) { 1299 CLEANUP_RP = new RequestProcessor("Source hierarchy bridge"); } 1301 } 1302 CLEANUP_RP.post(new Runnable () { 1303 public void run() { 1304 try { 1305 listener.doRemove(); 1306 } catch (InvalidObjectException e) { 1307 } 1308 } 1309 }); 1310 } 1311 1312 } 1313 1314} 1315 | Popular Tags |