KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javacore > jmiimpl > javamodel > ClassDefinitionImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  *
19  */

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 /**
43  * @author Martin Matula
44  */

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 the superclass has changed, the superClass variable is
84
// initialized -> return its content
85
if (isChanged(CHANGED_EXTENDS)) {
86             if (superClass == null) {
87                 superClass = (JavaClass) ((JavaModelPackage) refImmediatePackage()).getType().resolve("java.lang.Object"); // NOI18N
88
}
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 JavaDoc();
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); // NOI18N
108
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); // NOI18N
123
childrenInited = true;
124     }
125
126     protected void _delete() {
127         // --- delete components -------------------------------------------
128
// delete all contents
129
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 JavaDoc getSourceText() {
152         String JavaDoc origElem;
153         if ((origElem = checkChange()) != null)
154             return origElem;
155         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
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         // contents diff
169
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"); // NOI18N
173
}
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     // --------- Implementation of JMI operations -----------------------------------------------------------
186

187     public Field getField(String JavaDoc name, boolean includeSupertypes) {
188         return getField(this, name, includeSupertypes);
189     }
190     
191     public Method getMethod(String JavaDoc name, List parameters, boolean includeSupertypes) {
192         return getMethod(this, name, parameters, includeSupertypes);
193     }
194     
195     public JavaClass getInnerClass(String JavaDoc 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     // static methods to which we delegate ......................................
204

205     static Field getField (ClassDefinition cd, final String JavaDoc 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 JavaDoc 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 JavaDoc doQuery(ClassDefinition cd);
226     }
227     
228     private static Object JavaDoc 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 JavaDoc 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             // scan interfaces
248
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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc doQuery(ClassDefinition cd) {
308                     return getConstructor(cd, argTypes);
309                 }
310             });
311         } finally {
312             repository.endTrans(false);
313         }
314     }
315     
316     // helper methods ...........................................................
317

318     static Method getMethod (ClassDefinition cd, String JavaDoc name, List argTypes) {
319         Iterator iter = cd.getContents().iterator();
320         while (iter.hasNext()) {
321             Object JavaDoc 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         } // while
328
return null;
329     }
330     
331     static Constructor getConstructor (ClassDefinition cd, List argTypes) {
332         Iterator iter = cd.getContents().iterator();
333         while (iter.hasNext()) {
334             Object JavaDoc obj = iter.next ();
335             if (obj instanceof Constructor) {
336                 Constructor constr = (Constructor) obj;
337                 if (argTypesMatch(constr, argTypes))
338                     return constr;
339             }
340         } // while
341
return null;
342     }
343     
344     static JavaClass getInnerClass (ClassDefinition cd, String JavaDoc name) {
345         Iterator iter = cd.getContents().iterator();
346         while (iter.hasNext()) {
347             Object JavaDoc obj = iter.next ();
348             if (obj instanceof JavaClass) {
349                 JavaClass jc = (JavaClass) obj;
350                 if (name.equals(jc.getSimpleName()))
351                     return jc;
352             }
353         } // while
354
return null;
355     }
356     
357     static Field getField (ClassDefinition cd, String JavaDoc name) {
358         Iterator iter = cd.getFeatures().iterator();
359         while (iter.hasNext()) {
360             Object JavaDoc obj = iter.next ();
361             if (obj instanceof Field) {
362                 Field field = (Field) obj;
363                 if (name.equals(field.getName()))
364                     return field;
365             }
366         } // while
367
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         } // while
385
return true;
386     }
387     
388     /** Initializes interfaces collection */
389     static ReferenceListWrapper initInterfaces(ReferenceListWrapper interfaces, SemiPersistentElement javaClass) {
390         NameRef[] interfaceNames = ((ClassInfo) javaClass.getElementInfo()).interfaces;
391         // list of superinterfaces is transient
392
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); // NOI18N
399
} 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"); // NOI18N
408
} 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"); // NOI18N
415
return list;
416     }
417
418     /**
419      * Prints all class contents to <tt>buf</tt>.
420      *
421      * @param javaClass print contents of this class
422      * @param buf buffer to append contents to
423      * @param braces print the curly braces
424      */

425     static void generateNewFeatures(ClassDefinition javaClass, StringBuffer JavaDoc buf, boolean braces) {
426         MetadataElement cd = (MetadataElement) javaClass;
427         if (!cd.isNew()) {
428             // for the ClassDefinition, which has already tree, print the
429
// whitespaces and comments as they were before
430
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                 // there isn't any feature, do not put semicolon at the end
459
// of constant declaration.
460
buf.append(";\n\n"); // NOI18N
461
} 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 JavaDoc 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 this class was already checked, we know it is not a subtype -> return false immediately
499
if (!visited.add(thisClass)) {
500             return false;
501         }
502         
503         clazz = getRealClassDefinition(clazz);
504
505         // if the names of the classes match, we found the class traversing through supertypes -> it is a subtype
506
if (Utilities.compareObjects(thisClass.getName(), clazz.getName())) {
507             return true;
508         }
509
510         if ((thisClass instanceof JavaClass) && ((JavaClass) thisClass).isInterface()) {
511             // if this class is an interface and class that it should be a subtype of is a class, we know the only case
512
// where that could be true is if the supertype is java.lang.Object
513
if (!((clazz instanceof JavaClass) && ((JavaClass) clazz).isInterface())) {
514                 return "java.lang.Object".equals(clazz.getName()); // NOI18N
515
}
516         } else {
517             // check superclasses only if this class is a class (not interface) - for interface it is handled in the condition above
518
if (isSubTypeOf(getRealClassDefinition(thisClass.getSuperClass()), clazz, visited)) {
519                 return true;
520             }
521             // if clazz is not an interface, we must have found it by traversing through superclasses
522
if (!((clazz instanceof JavaClass) && ((JavaClass) clazz).isInterface())) {
523                 return false;
524             }
525         }
526
527         // iterate through the super interfaces
528
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         // do not hardref parent - this object is transient
550
}
551
552     protected void parentChanged() {
553         // do nothing on parentChanged - this object is transient
554
}
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