1 20 21 package org.netbeans.modules.javacore.jmiimpl.javamodel; 22 23 import org.netbeans.jmi.javamodel.*; 24 import org.netbeans.lib.java.parser.ASTree; 25 import org.netbeans.lib.java.parser.ASTreeTypes; 26 import org.netbeans.lib.java.parser.Token; 27 import org.netbeans.api.mdr.MDRepository; 28 import org.netbeans.mdr.handlers.AttrListWrapper; 29 import org.netbeans.mdr.handlers.BaseObjectHandler; 30 import org.netbeans.mdr.persistence.StorageException; 31 import org.netbeans.mdr.storagemodel.StorableObject; 32 import org.netbeans.modules.javacore.parser.ASTProvider; 33 import org.netbeans.modules.javacore.parser.ClassInfo; 34 import org.netbeans.modules.javacore.parser.ElementInfo; 35 import org.netbeans.modules.javacore.parser.MDRParser; 36 import org.netbeans.modules.javacore.parser.NameRef; 37 import org.openide.ErrorManager; 38 import javax.jmi.reflect.RefObject; 39 import java.util.*; 40 import org.openide.util.Utilities; 41 42 45 public abstract class ClassDefinitionImpl extends SemiPersistentElement implements ClassDefinition { 46 private ReferenceListWrapper interfaces; 47 private JavaClass superClass; 48 private LightAttrList contents; 49 private final List featuresList; 50 51 public ClassDefinitionImpl(StorableObject s) { 52 super(s); 53 this.featuresList = new FeaturesList(this); 54 } 55 56 protected abstract List super_getContents(); 57 58 public List getContents() { 59 if (!childrenInited) { 60 initChildren(); 61 } 62 return contents; 63 } 64 65 public List getFeatures() { 66 return featuresList; 67 } 68 69 public Collection getReferences() { 70 return Collections.EMPTY_LIST; 71 } 72 73 public List getInterfaces() { 74 if (interfaces == null) { 75 interfaces = initInterfaces(interfaces, this); 76 } 77 return interfaces; 78 } 79 80 public JavaClass getSuperClass() { 81 JavaClass result; 82 83 if (isChanged(CHANGED_EXTENDS)) { 86 if (superClass == null) { 87 superClass = (JavaClass) ((JavaModelPackage) refImmediatePackage()).getType().resolve("java.lang.Object"); } 89 result = superClass; 90 } else { 91 NameRef superClassName = ((ClassInfo) getElementInfo()).superclass; 92 result = (JavaClass) resolveType(superClassName); 93 } 94 return result; 95 } 96 97 public void setSuperClass(JavaClass newValue) { 98 throw new UnsupportedOperationException (); 99 } 100 101 protected void initChildren() { 102 initChildren(false); 103 } 104 105 protected void initChildren(boolean rebuild) { 106 childrenInited = false; 107 contents = createChildrenList(contents, "contents", ((ClassInfo) getElementInfo()).features, CHANGED_FEATURES, rebuild); childrenInited = true; 109 } 110 111 protected void matchPersistent(ElementInfo info) { 112 if (childrenInited) { 113 processMembers(getContents(), ((ClassInfo)info).features); 114 } 115 } 116 117 protected void matchElementInfo(ElementInfo newInfo) { 118 super.matchElementInfo(newInfo); 119 } 120 121 void setData(List features) { 122 contents = createChildrenList("contents", features, CHANGED_FEATURES); childrenInited = true; 124 } 125 126 protected void _delete() { 127 if (childrenInited) { 130 deleteChildren(contents); 131 } 132 super._delete(); 133 } 134 135 protected void resetChildren() { 136 super.resetChildren(); 137 if (childrenInited) { 138 initChildren(true); 139 } 140 if (interfaces != null) { 141 interfaces = ClassDefinitionImpl.initInterfaces(interfaces, this); 142 } 143 } 144 145 public List getChildren() { 146 List l=new ArrayList(30); 147 l.addAll(getContents()); 148 return l; 149 } 150 151 public String getSourceText() { 152 String origElem; 153 if ((origElem = checkChange()) != null) 154 return origElem; 155 StringBuffer buf = new StringBuffer (); 156 if (isNew()) 157 formatElementPart(CLASS_OPEN_CURLY, buf); 158 generateNewFeatures(this, buf, false); 159 if (isNew()) 160 formatElementPart(ANON_CLASS_CLOSE_CURLY, buf); 161 return buf.toString(); 162 } 163 164 public void getDiff(List diffList) { 165 ClassInfo astInfo = (ClassInfo) getElementInfo(); 166 ASTProvider parser = getParser(); 167 168 Token closeBrace = parser.getToken(getASTree().getLastToken()); 170 Token[] pad = closeBrace.getPadding(); 171 int endOffset = pad.length > 0 ? pad[0].getStartOffset() : closeBrace.getStartOffset(); 172 getCollectionDiff(diffList, parser, CHANGED_FEATURES, astInfo.features, getContents(), endOffset, "\n"); } 174 175 public void replaceChild(Element oldElement, Element newElement) { 176 if (childrenInited) { 177 if (replaceObject(getContents(), oldElement, newElement)) return; 178 } 179 } 180 181 protected ElementInfo getDefaultInfo() { 182 return JavaClassImpl.DEFAULT_INFO; 183 } 184 185 187 public Field getField(String name, boolean includeSupertypes) { 188 return getField(this, name, includeSupertypes); 189 } 190 191 public Method getMethod(String name, List parameters, boolean includeSupertypes) { 192 return getMethod(this, name, parameters, includeSupertypes); 193 } 194 195 public JavaClass getInnerClass(String simpleName, boolean includeSupertypes) { 196 return getInnerClass(this, simpleName, includeSupertypes); 197 } 198 199 public Constructor getConstructor(List parameters, boolean includeSupertypes) { 200 return getConstructor(this, parameters, includeSupertypes); 201 } 202 203 205 static Field getField (ClassDefinition cd, final String name, boolean includeSuperTypes) { 206 MDRepository repository = ((BaseObjectHandler)cd).repository(); 207 repository.beginTrans(false); 208 try { 209 Field field = getField (cd, name); 210 if ((field != null) || !includeSuperTypes) { 211 return field; 212 } 213 return (Field) traverseSupertypes(cd, true, new Query() { 214 public Object doQuery(ClassDefinition cd) { 215 return getField(cd, name); 216 } 217 }); 218 } finally { 219 repository.endTrans(false); 220 } 221 222 } 223 224 private static interface Query { 225 Object doQuery(ClassDefinition cd); 226 } 227 228 private static Object traverseSupertypes(ClassDefinition cls, boolean includeInterfaces, Query query) { 229 HashSet visited = new HashSet(); 230 LinkedList supers = includeInterfaces ? new LinkedList() : null; 231 visited.add(cls); 232 Object result; 233 234 JavaClass jc = cls.getSuperClass(); 235 while (jc != null && visited.add(jc)) { 236 result = query.doQuery(jc); 237 if (result != null) { 238 return result; 239 } 240 if (includeInterfaces) supers.addAll(jc.getInterfaces()); 241 jc = jc.getSuperClass(); 242 } 243 244 if (includeInterfaces) { 245 supers.addAll(0, cls.getInterfaces()); 246 247 while (!supers.isEmpty()) { 249 ClassDefinition cd = (ClassDefinition) supers.removeFirst(); 250 if (visited.add(cd)) { 251 result = query.doQuery(cd); 252 if (result != null) { 253 return result; 254 } 255 supers.addAll(cd.getInterfaces()); 256 } 257 } 258 } 259 return null; 260 } 261 262 static JavaClass getInnerClass(ClassDefinition cd, final String name, boolean includeSuperTypes) { 263 MDRepository repository = ((BaseObjectHandler)cd).repository(); 264 repository.beginTrans(false); 265 try { 266 JavaClass innerCls = getInnerClass(cd, name); 267 if ((innerCls != null) || !includeSuperTypes) { 268 return innerCls; 269 } 270 return (JavaClass) traverseSupertypes(cd, true, new Query() { 271 public Object doQuery(ClassDefinition cd) { 272 return getInnerClass(cd, name); 273 } 274 }); 275 } finally { 276 repository.endTrans(false); 277 } 278 } 279 280 static Method getMethod (ClassDefinition cd, final String name, final List argTypes, boolean includeSuperTypes) { 281 MDRepository repository = ((BaseObjectHandler)cd).repository(); 282 repository.beginTrans(false); 283 try { 284 Method method = getMethod (cd, name, argTypes); 285 if ((method != null) || !includeSuperTypes) { 286 return method; 287 } 288 return (Method) traverseSupertypes(cd, true, new Query() { 289 public Object doQuery(ClassDefinition cd) { 290 return getMethod(cd, name, argTypes); 291 } 292 }); 293 } finally { 294 repository.endTrans(); 295 } 296 } 297 298 static Constructor getConstructor(ClassDefinition cd, final List argTypes, boolean includeSuperTypes) { 299 MDRepository repository = ((BaseObjectHandler)cd).repository(); 300 repository.beginTrans(false); 301 try { 302 Constructor constructor = getConstructor (cd, argTypes); 303 if ((constructor != null) || !includeSuperTypes) { 304 return constructor; 305 } 306 return (Constructor) traverseSupertypes(cd, false, new Query() { 307 public Object doQuery(ClassDefinition cd) { 308 return getConstructor(cd, argTypes); 309 } 310 }); 311 } finally { 312 repository.endTrans(false); 313 } 314 } 315 316 318 static Method getMethod (ClassDefinition cd, String name, List argTypes) { 319 Iterator iter = cd.getContents().iterator(); 320 while (iter.hasNext()) { 321 Object obj = iter.next (); 322 if (obj instanceof Method) { 323 Method method = (Method) obj; 324 if (name.equals(method.getName()) && argTypesMatch(method, argTypes)) 325 return method; 326 } 327 } return null; 329 } 330 331 static Constructor getConstructor (ClassDefinition cd, List argTypes) { 332 Iterator iter = cd.getContents().iterator(); 333 while (iter.hasNext()) { 334 Object obj = iter.next (); 335 if (obj instanceof Constructor) { 336 Constructor constr = (Constructor) obj; 337 if (argTypesMatch(constr, argTypes)) 338 return constr; 339 } 340 } return null; 342 } 343 344 static JavaClass getInnerClass (ClassDefinition cd, String name) { 345 Iterator iter = cd.getContents().iterator(); 346 while (iter.hasNext()) { 347 Object obj = iter.next (); 348 if (obj instanceof JavaClass) { 349 JavaClass jc = (JavaClass) obj; 350 if (name.equals(jc.getSimpleName())) 351 return jc; 352 } 353 } return null; 355 } 356 357 static Field getField (ClassDefinition cd, String name) { 358 Iterator iter = cd.getFeatures().iterator(); 359 while (iter.hasNext()) { 360 Object obj = iter.next (); 361 if (obj instanceof Field) { 362 Field field = (Field) obj; 363 if (name.equals(field.getName())) 364 return field; 365 } 366 } return null; 368 } 369 370 static boolean argTypesMatch (CallableFeature callable, List argTypes) { 371 List pars = callable.getParameters (); 372 if (argTypes.size () != pars.size ()) { 373 return false; 374 } 375 Map typeParams = null; 376 Iterator parsIter = pars.iterator (); 377 Iterator argsIter = argTypes.iterator (); 378 while (parsIter.hasNext ()) { 379 Type t1 = TypeClassImpl.getRawType(((Parameter) parsIter.next ()).getType ()); 380 Type t2 = TypeClassImpl.getRawType((Type) argsIter.next ()); 381 if (!t1.getName().equals(t2.getName())) { 382 return false; 383 } 384 } return true; 386 } 387 388 389 static ReferenceListWrapper initInterfaces(ReferenceListWrapper interfaces, SemiPersistentElement javaClass) { 390 NameRef[] interfaceNames = ((ClassInfo) javaClass.getElementInfo()).interfaces; 391 TypeList _interfaces = new TypeList(javaClass); 393 for (int i = 0; i<interfaceNames.length; i++) { 394 _interfaces.addTypeRef(interfaceNames[i]); 395 } 396 if (interfaces == null) { 397 ImplementsImpl implementsImpl = (ImplementsImpl)(((JavaModelPackage) javaClass.refImmediatePackage()).getImplements()); 398 interfaces = new ReferenceListWrapper(javaClass._getDelegate().getMdrStorage(), implementsImpl, javaClass, "interfaces", javaClass, CHANGED_IMPLEMENTS, _interfaces); } else { 400 interfaces.setInnerList(_interfaces); 401 } 402 return interfaces; 403 } 404 405 static List getNakedFeatures(SemiPersistentElement javaClass) { 406 try { 407 return (List) ((StorableObject) javaClass._getDelegate()).getAttribute("contents"); } catch (StorageException e) { 409 throw (GeneralException) ErrorManager.getDefault().annotate(new GeneralException(e.getMessage()), e); 410 } 411 } 412 413 static List getPersistentContent(AttrListWrapper list) { 414 list.setAttrName("contents"); return list; 416 } 417 418 425 static void generateNewFeatures(ClassDefinition javaClass, StringBuffer buf, boolean braces) { 426 MetadataElement cd = (MetadataElement) javaClass; 427 if (!cd.isNew()) { 428 ASTree tree = cd.getASTree(); 431 ASTree body; 432 int treeType = tree.getType(); 433 if (treeType == ASTreeTypes.CLASS_BODY_DECLARATIONS) { 434 body = tree; 435 } else if (treeType == ASTreeTypes.ENUM_DECLARATION) { 436 body = tree.getSubTrees()[3]; 437 } else if (treeType == ASTreeTypes.ANNOTATION_TYPE_DECLARATION) { 438 body = tree.getSubTrees()[2]; 439 } else { 440 body = tree.getSubTrees()[5]; 441 } 442 buf.append(IndentUtil.reformatTokenWithPads(cd, body.getFirstToken())); 443 } else { 444 if (braces) 445 ((MetadataElement) javaClass).formatElementPart(CLASS_OPEN_CURLY, buf); 446 } 447 List features = javaClass.getContents(); 448 if (javaClass instanceof JavaEnum) { 449 JavaEnumImpl en = (JavaEnumImpl) javaClass; 450 if (!en.getConstants().isEmpty()) 451 buf.append(getInnerIndentation(2)); 452 for (Iterator it = en.getConstants().iterator(); it.hasNext();) { 453 MetadataElement constant = (MetadataElement) it.next(); 454 buf.append(constant.getSourceText()); 455 if (it.hasNext()) en.formatElementPart(COMMA, buf); 456 } 457 if (!en.getContents().isEmpty()) { 458 buf.append(";\n\n"); } else { 462 if (!en.getConstants().isEmpty()) { 463 buf.append('\n'); 464 } 465 } 466 } 467 if (!features.isEmpty()) { 468 for (Iterator it = features.iterator(); it.hasNext(); ) { 469 MetadataElement me = (MetadataElement) it.next(); 470 buf.append(me.getSourceText()); 471 if (me.isNew()) buf.append('\n'); 472 } 473 } 474 if (!cd.isNew()) { 475 ASTree tree = cd.getASTree(); 476 buf.append(IndentUtil.reformatTokenWithPads(cd, tree.getLastToken())); 477 } else { 478 if (braces) 479 ((MetadataElement) javaClass).formatElementPart(CLASS_CLOSE_CURLY, buf); 480 } 481 } 482 483 protected String getIndentation() { 484 MetadataElement parent = this; 485 do { 486 parent = (MetadataElement) parent.refImmediateComposite(); 487 } while (!(parent instanceof Statement || parent instanceof FieldGroup || (parent instanceof Field && parent.refImmediateComposite() instanceof ClassDefinition))); 488 return parent.getIndentation(); 489 } 490 491 static boolean isSubTypeOf(ClassDefinition thisClass, ClassDefinition clazz) { 492 return isSubTypeOf(thisClass, clazz, new HashSet()); 493 } 494 495 private static boolean isSubTypeOf(ClassDefinition thisClass, ClassDefinition clazz, Set visited) { 496 if (thisClass == null || clazz == null) return false; 497 498 if (!visited.add(thisClass)) { 500 return false; 501 } 502 503 clazz = getRealClassDefinition(clazz); 504 505 if (Utilities.compareObjects(thisClass.getName(), clazz.getName())) { 507 return true; 508 } 509 510 if ((thisClass instanceof JavaClass) && ((JavaClass) thisClass).isInterface()) { 511 if (!((clazz instanceof JavaClass) && ((JavaClass) clazz).isInterface())) { 514 return "java.lang.Object".equals(clazz.getName()); } 516 } else { 517 if (isSubTypeOf(getRealClassDefinition(thisClass.getSuperClass()), clazz, visited)) { 519 return true; 520 } 521 if (!((clazz instanceof JavaClass) && ((JavaClass) clazz).isInterface())) { 523 return false; 524 } 525 } 526 527 for (Iterator it = thisClass.getInterfaces().iterator(); it.hasNext();) { 529 ClassDefinition ifc = getRealClassDefinition((ClassDefinition) it.next()); 530 if (isSubTypeOf(ifc, clazz, visited)) { 531 return true; 532 } 533 } 534 return false; 535 } 536 537 public static ClassDefinition getRealClassDefinition(ClassDefinition cls) { 538 if (cls instanceof ParameterizedType) { 539 return ((ParameterizedType) cls).getDefinition(); 540 } 541 return cls; 542 } 543 544 public boolean isSubTypeOf(ClassDefinition clazz) { 545 return isSubTypeOf(this, clazz); 546 } 547 548 protected void hardRefParent(boolean enabled) { 549 } 551 552 protected void parentChanged() { 553 } 555 556 public Element duplicate(JavaModelPackage targetExtent) { 557 return targetExtent.getClassDefinition().createClassDefinition( 558 getName(), 559 duplicateList(getContents(), targetExtent), 560 (MultipartId) duplicateElement(getSuperClassName(), targetExtent), 561 duplicateList(getInterfaceNames(), targetExtent) 562 ); 563 } 564 } 565 | Popular Tags |