KickJava   Java API By Example, From Geeks To Geeks.

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


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 package org.netbeans.modules.javacore.jmiimpl.javamodel;
20
21 import java.lang.reflect.Modifier JavaDoc;
22 import java.util.*;
23 import org.netbeans.jmi.javamodel.*;
24 import org.netbeans.lib.java.parser.ASTree;
25 import org.netbeans.mdr.handlers.AttrListWrapper;
26 import org.netbeans.mdr.storagemodel.StorableObject;
27 import org.netbeans.modules.javacore.JMManager;
28 import org.netbeans.modules.javacore.parser.ElementInfo;
29 import org.netbeans.modules.javacore.parser.MethodInfo;
30 import org.netbeans.modules.javacore.parser.MDRParser;
31 import org.netbeans.modules.javacore.parser.TypeRef;
32 import org.openide.util.Utilities;
33
34
35 /**
36  * Superclass for the MethodImpl and ConstructorImpl classes.
37  *
38  * @author Martin Matula
39  * @author Vladimir Hudec
40  * @author Pavel Flaska
41  */

42 public abstract class CallableFeatureImpl extends BehavioralFeatureImpl implements CallableFeature {
43     public static final String JavaDoc PARAMETERS_ATTR = "parameters"; // NOI18N
44

45     protected boolean elementsInited = false;
46
47     protected LightAttrList parameters;
48
49     /** List of exceptions */
50     protected ReferenceListWrapper exceptions = null;
51     /** List of exception names */
52     private LightAttrList excNames = null;
53     private LightAttrList typeParameters = null;
54
55     /** Creates a new instance of ConstructorImpl */
56     public CallableFeatureImpl(StorableObject s) {
57         super(s);
58     }
59
60     protected void matchPersistent(ElementInfo newInfo) {
61         super.matchPersistent(newInfo);
62         
63         MethodInfo info = (MethodInfo) newInfo;
64         
65         if (!isPersisted()) {
66             setPersisted(true);
67             persist();
68             setTypeRef(info.type);
69             setExceptionRefs(Arrays.asList(info.exceptions));
70             persistChildren(getPersistentList("annotations", super_getAnnotations()), info.annotations);
71             persistChildren(getPersistentList(TYPE_PARAMETERS_ATTR, super_getTypeParameters()), info.typeParams);
72             persistChildren(getPersistentList(PARAMETERS_ATTR, super_getParameters()), info.parameters);
73         } else {
74             if (!Utilities.compareObjects(info.type, getTypeRef())) {
75                 setType(resolveType(info.type));
76             }
77             processMembers(getAnnotations(), info.annotations);
78             processMembers(getTypeParameters(), info.typeParams);
79             processMembers(getExceptions(), info.exceptions);
80             processMembers(getParameters(), info.parameters);
81         }
82     }
83     
84     /** The method has to make sure that the AST infos of children are also updated.
85      */

86     protected void matchElementInfo(ElementInfo newInfo) {
87         super.matchElementInfo(newInfo);
88         resetASTElements();
89     }
90
91     protected void resetChildren() {
92         super.resetChildren();
93         if (parameters != null) parameters.setInnerList(getPersistentList(PARAMETERS_ATTR, super_getParameters()));
94         if (typeParameters != null) typeParameters.setInnerList(getPersistentList(TYPE_PARAMETERS_ATTR, super_getTypeParameters()));
95         if (childrenInited) {
96             resetASTElements();
97             initChildren();
98         }
99         if (exceptions != null) {
100             initExceptions();
101         }
102     }
103
104     protected void resetASTElements() {
105         if (elementsInited) {
106             if (excNames != null) {
107                 deleteChildren(excNames);
108                 excNames = null;
109             }
110             elementsInited = false;
111         }
112         if (bodyInited) {
113             resetBody();
114         }
115     }
116
117     protected void initASTElements() {
118         elementsInited = false;
119         if (!childrenInited) {
120             initChildren();
121         }
122         MethodInfo info = (MethodInfo) getElementInfo();
123         ASTree[] namesAST = info.getExceptionsAST(this);
124         excNames = createChildrenList(excNames, "exceptionNames", namesAST, CHANGED_THROWS, false); // NOI18N
125
elementsInited = true;
126     }
127
128     protected ASTree getBodyAST() {
129         return getASTree().getSubTrees()[5];
130     }
131
132     /**
133      * Returns the value of attribute parameters.
134      * @return Value of parameters attribute.
135      */

136     public List getParameters() {
137         checkUpToDate();
138         if (parameters == null) {
139             parameters = createChildrenList(PARAMETERS_ATTR, (AttrListWrapper) super_getParameters(), null, CHANGED_PARAMETERS);
140         }
141         return parameters;
142     }
143
144     public List getTypeParameters() {
145         checkUpToDate();
146         if (typeParameters == null) {
147             typeParameters = createChildrenList(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), null, CHANGED_TYPE_PARAMETERS);
148         }
149         return typeParameters;
150     }
151
152     boolean hasTypeParameters() {
153         checkUpToDate();
154         return !super_getTypeParameters().isEmpty();
155     }
156     
157     protected void initChildren() {
158         childrenInited = false;
159         MethodInfo info = (MethodInfo) getElementInfo();
160         parameters = createChildrenList(parameters, PARAMETERS_ATTR, (AttrListWrapper) super_getParameters(), info.parameters, CHANGED_PARAMETERS);
161         typeParameters = createChildrenList(typeParameters, TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), info.typeParams, CHANGED_TYPE_PARAMETERS);
162         super.initChildren();
163         childrenInited = true;
164         
165         if (elementsInited) {
166             initASTElements();
167         }
168
169         StatementBlock body = retrieveBody();
170         if (bodyInited) {
171             JMManager.getTransactionMutex().addBFeatureToInitQueue(this);
172         }
173     }
174     
175     protected abstract List super_getParameters();
176     protected abstract List super_getTypeParameters();
177
178     protected void setData(List annotations, String JavaDoc javadocText, JavaDoc javadoc, StatementBlock body, String JavaDoc bodyText, List typeParameters, List parameters, List exceptionNames) {
179         super.setData(annotations, javadocText, javadoc, body, bodyText);
180         this.typeParameters = createChildrenList(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters(), typeParameters, CHANGED_TYPE_PARAMETERS); // NOI18N
181
this.parameters = createChildrenList(PARAMETERS_ATTR, (AttrListWrapper) super_getParameters(), parameters, CHANGED_PARAMETERS); // NOI18N
182
this.excNames = createChildrenList("exceptionNames", exceptionNames, CHANGED_THROWS); // NOI18N
183
elementsInited = true;
184     }
185
186     /**
187      * Returns the value of reference exceptions.
188      * @return Value of reference exceptions.
189      */

190     public List getExceptions() {
191         checkUpToDate();
192         if (exceptions == null) {
193             initExceptions();
194         }
195         return exceptions;
196     }
197
198     public List getExceptionNames() {
199         if (!elementsInited) {
200             initASTElements();
201         }
202         return excNames;
203     }
204
205     public List getChildren() {
206         List list = new ArrayList();
207         list.addAll(getTypeParameters());
208         list.addAll(getParameters());
209         list.addAll(getExceptionNames());
210         list.addAll(super.getChildren());
211         return list;
212     }
213
214     public void fixImports(Element scope, Element original) {
215         CallableFeature feature=(CallableFeature)original;
216         fixImports(scope,getTypeParameters(),feature.getTypeParameters());
217         fixImports(scope,getParameters(),feature.getParameters());
218         fixImportsInClassList(scope,getExceptionNames(),feature.getExceptions());
219         super.fixImports(scope,original);
220     }
221
222     protected List getInitedChildren() {
223         List list = super.getInitedChildren();
224         if (childrenInited) {
225             list.addAll(typeParameters);
226             list.addAll(parameters);
227         }
228         if (elementsInited) {
229             list.addAll(excNames);
230         }
231         return list;
232     }
233     
234     public void replaceChild(Element oldElement, Element newElement) {
235         if (replaceObject(getParameters(), oldElement, newElement)) return;
236         if (replaceObject(getTypeParameters(), oldElement, newElement)) return;
237         if (elementsInited) {
238             if (replaceObject(excNames, oldElement, newElement)) return;
239         }
240         super.replaceChild(oldElement, newElement);
241     }
242     
243     public Collection findDependencies(boolean findUsages, boolean fromBaseClass, boolean findOverridingMethods) {
244         Resource[] res = findReferencedResources();
245         
246         if (!fromBaseClass || (fromBaseClass && !isOverriden())) {
247             Element cd = getDeclaringClass();
248             boolean isPrivate = false;
249             while (cd != null && !(cd instanceof Resource)) {
250                 if (cd instanceof JavaClass) {
251                     int m = ((JavaClass) cd).getModifiers();
252                     if (!Modifier.isPublic(m) && !Modifier.isProtected(m)) {
253                         isPrivate = true;
254                         break;
255                     }
256                 }
257                 cd = (Element) cd.refImmediateComposite();
258             }
259             if (isPrivate) {
260                 res = filterResourcesFromThisPackage(res);
261             }
262         }
263
264         UsageFinder finder = new UsageFinder(this, findUsages, fromBaseClass, findOverridingMethods);
265         return finder.getUsers(res);
266     }
267     
268     private boolean isOverriden() {
269         if (!(this instanceof Method))
270             return false;
271         
272         ClassDefinition declaringClass = getDeclaringClass();
273         
274         List params = new ArrayList();
275         for (Iterator i = getParameters().iterator(); i.hasNext(); params.add(((Parameter)i.next()).getType()));
276         
277         ClassDefinition parent = declaringClass.getSuperClass();
278         Method m = parent.getMethod(getName(), params, true);
279         if (m!=null) {
280             return true;
281         }
282         Iterator i = declaringClass.getInterfaces().iterator();
283         while (i.hasNext()) {
284             ClassDefinition jc = (ClassDefinition) i.next();
285             m = jc.getMethod(getName(), params, true);
286             if (m!=null) {
287                 return true;
288             }
289         }
290         return false;
291     }
292     
293     private void initExceptions() {
294         List exceptionNames = getExceptionRefs();
295         if (exceptionNames == null) {
296             exceptionNames = new ArrayList();
297         } else if (!(exceptionNames instanceof ArrayList)) {
298             exceptionNames = new ArrayList(exceptionNames);
299         }
300         TypeList innerExceptions = new TypeList(this, (ArrayList) exceptionNames) {
301             protected void updateParent() {
302                 setExceptionRefs(innerList);
303             }
304
305             protected void fireChange(int attrType, TypeRef newTR, int position) {
306                 Object JavaDoc newValue, oldValue;
307                 if (elementsInited) {
308                     newValue = typeRefToTypeReference(newTR, 0);
309                     // [TODO] pass a correct oldValue
310
oldValue = null;
311                 } else {
312                     newValue = oldValue = null;
313                 }
314                 fireAttrChange("exceptionNames", oldValue, newValue, position); // NOI18N
315
}
316         };
317         if (exceptions == null) {
318             ThrowsImpl throwsImpl = (ThrowsImpl)(((JavaModelPackage) refImmediatePackage()).getThrows());
319             exceptions = new ReferenceListWrapper(_getDelegate().getMdrStorage(), throwsImpl, this, "exceptions", this, CHANGED_THROWS, innerExceptions); // NOI18N
320
} else {
321             exceptions.setInnerList(innerExceptions);
322         }
323     }
324
325     // .........................................................................
326
// printing and formatting functionality
327
// .........................................................................
328

329     /**
330      * Generates callable feature header, i.e. Constructor or Method. Subclasses
331      * have to provide generateTypeAndName() method.
332      *
333      * @param buf buffer to append header to
334      */

335     void generateHeader(StringBuffer JavaDoc buf) {
336         boolean nju = isNew();
337         if (nju)
338             generateNewJavaDoc(buf);
339         generateNewModifiers(buf);
340         generateNewTypeParameters(buf);
341         generateTypeAndName(buf);
342         generateNewParameters(buf);
343         generateNewExceptions(buf);
344     }
345
346     /**
347      * Provided by constructor and method elements.
348      *
349      * @param buf buffer to append type and name to
350      */

351     abstract void generateTypeAndName(StringBuffer JavaDoc buf);
352
353     /**
354      * Method is used by subclasses to generate 'parameters' part of the
355      * element.
356      *
357      * @param buf append parameters to this parameter
358      */

359     void generateNewParameters(StringBuffer JavaDoc buf) {
360         formatElementPart(PAR_OPEN_BRACKET, buf);
361         List parameters = getParameters();
362         if (!parameters.isEmpty()) {
363             Iterator it = parameters.iterator();
364             ParameterImpl impl = (ParameterImpl) it.next();
365             buf.append(impl.getSourceText());
366             while (it.hasNext()) {
367                 formatElementPart(COMMA, buf);
368                 impl = (ParameterImpl) it.next();
369                 buf.append(impl.getSourceText());
370             }
371         }
372         formatElementPart(PAR_CLOSE_BRACKET, buf);
373     }
374
375     /**
376      * Method is used by subclasses to generate 'throws clause' of the
377      * element.
378      *
379      * @param buf append throws clause to this param
380      */

381     void generateNewExceptions(StringBuffer JavaDoc buf) {
382         Collection exceptions = getExceptionNames();
383         if (!exceptions.isEmpty()) {
384             formatElementPart(THROWS_KEYWORD, buf);
385             Iterator it = exceptions.iterator();
386             MultipartIdImpl id = (MultipartIdImpl) it.next();
387             buf.append(id.getSourceText());
388             while (it.hasNext()) {
389                 formatElementPart(COMMA, buf);
390                 id = (MultipartIdImpl) it.next();
391                 buf.append(id.getSourceText());
392             }
393         }
394     }
395
396     private void generateNewTypeParameters(StringBuffer JavaDoc buf) {
397         Collection typeParameters = getTypeParameters();
398         if (!typeParameters.isEmpty()) {
399             buf.append('<');
400             Iterator it = typeParameters.iterator();
401             while (it.hasNext()) {
402                 buf.append(((TypeParameterImpl) it.next()).getSourceText());
403                 if (it.hasNext()) {
404                     formatElementPart(COMMA, buf);
405                 }
406             }
407             buf.append("> ");
408         }
409     }
410
411     protected void getTypeParamsDiff(List diffList) {
412         MethodInfo astInfo = (MethodInfo) getElementInfo();
413         MDRParser parser = getParser();
414         ASTree[] children = getASTree().getSubTrees();
415         if (astInfo.typeParams.length == 0) {
416             if (isChanged(CHANGED_TYPE_PARAMETERS)) {
417                 StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
418                 generateNewTypeParameters(buf);
419                 int endOffset = getStartOffset(parser, children[2], false);
420                 diffList.add(new DiffElement(endOffset, endOffset, buf.toString()));
421             }
422         } else if (getTypeParameters().isEmpty()) {
423             if (isChanged(CHANGED_TYPE_PARAMETERS)) {
424                 int endOffset = getStartOffset(parser, children[2], true);
425                 int startOffset = getStartOffset(parser, children[1], true);
426                 diffList.add(new DiffElement(startOffset, endOffset, ""));
427             }
428         } else {
429             getCollectionDiff(diffList, parser, CHANGED_TYPE_PARAMETERS, astInfo.typeParams, getTypeParameters(), parser.getToken(children[1].getLastToken()).getStartOffset(), ", "); // NOI18N
430
}
431     }
432
433     protected void _delete() {
434         // --- delete components -------------------------------------------
435
if (elementsInited) {
436             deleteChildren(excNames);
437         }
438         // delete all parameters (if initialized)
439
deleteChildren(PARAMETERS_ATTR, (AttrListWrapper) super_getParameters());
440         deleteChildren(TYPE_PARAMETERS_ATTR, (AttrListWrapper) super_getTypeParameters());
441         // --- delete links -----------------------------------------------
442
// no links to delete
443
// [TODO] should Throws association be notified?
444
// --- call super -------------------------------------------------
445
super._delete();
446     }
447     
448     protected void setExceptionRefs(List excs) {
449         _getDelegate().setSlot2(excs);
450     }
451     
452     public List getExceptionRefs() {
453         return (List) _getDelegate().getSlot2();
454     }
455
456     protected ASTree getPartEndTree(ElementPartKind part) {
457         if (ElementPartKindEnum.HEADER.equals(part)) {
458             ASTree[] headerParts = getASTree().getSubTrees();
459             for (int i = 4; true; i--) {
460                 ASTree result = headerParts[i];
461                 if (result != null) {
462                     return result;
463                 }
464             }
465         }
466         return super.getPartEndTree(part);
467     }
468 }
469
Popular Tags