KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > groovy > ast > ClassNode


1 /*
2  * $Id: ClassNode.java,v 1.43 2004/12/14 00:08:26 spullara Exp $
3  *
4  * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
5  *
6  * Redistribution and use of this software and associated documentation
7  * ("Software"), with or without modification, are permitted provided that the
8  * following conditions are met:
9  * 1. Redistributions of source code must retain copyright statements and
10  * notices. Redistributions must also contain a copy of this document.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. The name "groovy" must not be used to endorse or promote products
15  * derived from this Software without prior written permission of The Codehaus.
16  * For written permission, please contact info@codehaus.org.
17  * 4. Products derived from this Software may not be called "groovy" nor may
18  * "groovy" appear in their names without prior written permission of The
19  * Codehaus. "groovy" is a registered trademark of The Codehaus.
20  * 5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
23  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
26  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32  * DAMAGE.
33  *
34  */

35 package org.codehaus.groovy.ast;
36
37 import groovy.lang.GroovyObject;
38 import groovy.lang.MissingClassException;
39 import groovy.lang.Script;
40 import org.codehaus.groovy.ast.expr.Expression;
41 import org.codehaus.groovy.ast.stmt.BlockStatement;
42 import org.codehaus.groovy.ast.stmt.EmptyStatement;
43 import org.codehaus.groovy.ast.stmt.Statement;
44 import org.objectweb.asm.Constants;
45
46 import java.lang.reflect.Constructor JavaDoc;
47 import java.lang.reflect.Method JavaDoc;
48 import java.security.AccessControlException JavaDoc;
49 import java.util.*;
50 import java.util.logging.Level JavaDoc;
51 import java.util.logging.Logger JavaDoc;
52
53 /**
54  * Represents a class declaration
55  *
56  * @author <a HREF="mailto:james@coredevelopers.net">James Strachan</a>
57  * @version $Revision: 1.43 $
58  */

59 public class ClassNode extends MetadataNode implements Constants {
60
61     private static final String JavaDoc[] defaultImports = {"java.lang", "java.util", "groovy.lang", "groovy.util"};
62
63     private Logger JavaDoc log = Logger.getLogger(getClass().getName());
64
65     private String JavaDoc name;
66     private int modifiers;
67     private String JavaDoc superClass;
68     private String JavaDoc[] interfaces;
69     private MixinNode[] mixins;
70     private List constructors = new ArrayList();
71     private List methods = new ArrayList();
72     private List fields = new ArrayList();
73     private List properties = new ArrayList();
74     private Map fieldIndex = new HashMap();
75     private ModuleNode module;
76     private CompileUnit compileUnit;
77     private boolean staticClass = false;
78     private boolean scriptBody = false;
79     private boolean script;
80     private ClassNode superClassNode;
81
82
83     //br added to track the enclosing method for local inner classes
84
private MethodNode enclosingMethod = null;
85
86     public MethodNode getEnclosingMethod() {
87         return enclosingMethod;
88     }
89
90     public void setEnclosingMethod(MethodNode enclosingMethod) {
91         this.enclosingMethod = enclosingMethod;
92     }
93
94
95     /**
96      * @param name is the full name of the class
97      * @param modifiers the modifiers,
98      * @param superClass the base class name - use "java.lang.Object" if no direct
99      * base class
100      * @see org.objectweb.asm.Constants
101      */

102     public ClassNode(String JavaDoc name, int modifiers, String JavaDoc superClass) {
103         this(name, modifiers, superClass, EMPTY_STRING_ARRAY, MixinNode.EMPTY_ARRAY);
104     }
105
106     /**
107      * @param name is the full name of the class
108      * @param modifiers the modifiers,
109      * @param superClass the base class name - use "java.lang.Object" if no direct
110      * base class
111      * @see org.objectweb.asm.Constants
112      */

113     public ClassNode(String JavaDoc name, int modifiers, String JavaDoc superClass, String JavaDoc[] interfaces, MixinNode[] mixins) {
114         this.name = name;
115         this.modifiers = modifiers;
116         this.superClass = superClass;
117         this.interfaces = interfaces;
118         this.mixins = mixins;
119
120         //br for better JVM comformance
121
if ((modifiers & ACC_SUPER) == 0) {
122             this.modifiers += ACC_SUPER;
123         }
124     }
125
126     public String JavaDoc getSuperClass() {
127         return superClass;
128     }
129
130     public void setSuperClass(String JavaDoc superClass) {
131         this.superClass = superClass;
132     }
133
134     public List getFields() {
135         return fields;
136     }
137
138     public String JavaDoc[] getInterfaces() {
139         return interfaces;
140     }
141
142     public MixinNode[] getMixins() {
143         return mixins;
144     }
145
146     public List getMethods() {
147         return methods;
148     }
149
150     public List getAbstractMethods() {
151
152         List result = new ArrayList();
153         for (Iterator methIt = getAllDeclaredMethods().iterator(); methIt.hasNext();) {
154             MethodNode method = (MethodNode) methIt.next();
155             if (method.isAbstract()) result.add(method);
156         }
157         if (result.size() == 0)
158             return null;
159         else
160             return result;
161     }
162
163     public List getAllDeclaredMethods() {
164         return new ArrayList(getDeclaredMethodsMap().values());
165     }
166
167
168     protected Map getDeclaredMethodsMap() {
169         // Start off with the methods from the superclass.
170
ClassNode parent = getSuperClassNode();
171         Map result = null;
172         if (parent != null)
173             result = parent.getDeclaredMethodsMap();
174         else
175             result = new HashMap();
176
177         // add in unimplemented abstract methods from the interfaces
178
for (int i = 0; i < interfaces.length; i++) {
179             String JavaDoc interfaceName = interfaces[i];
180             ClassNode iface = findClassNode(interfaceName);
181             Map ifaceMethodsMap = iface.getDeclaredMethodsMap();
182             for (Iterator iter = ifaceMethodsMap.keySet().iterator(); iter.hasNext();) {
183                 String JavaDoc methSig = (String JavaDoc) iter.next();
184                 if (!result.containsKey(methSig)) {
185                     MethodNode methNode = (MethodNode) ifaceMethodsMap.get(methSig);
186                     result.put(methSig, methNode);
187                 }
188             }
189         }
190
191         // And add in the methods implemented in this class.
192
for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
193             MethodNode method = (MethodNode) iter.next();
194             String JavaDoc sig = method.getTypeDescriptor();
195             if (result.containsKey(sig)) {
196                 MethodNode inheritedMethod = (MethodNode) result.get(sig);
197                 if (inheritedMethod.isAbstract()) {
198                     result.put(sig, method);
199                 }
200             } else {
201                 result.put(sig, method);
202             }
203         }
204         return result;
205     }
206
207     protected int findMatchingMethodInList(MethodNode method, List methods) {
208         for (int i = 0; i < methods.size(); i++) {
209             MethodNode someMeth = (MethodNode) methods.get(i);
210             if (someMeth.getName().equals(method.getName())
211                     && parametersEqual(someMeth.getParameters(), method.getParameters()))
212                 return i;
213         }
214         return -1;
215     }
216
217     public String JavaDoc getName() {
218         return name;
219     }
220
221     public int getModifiers() {
222         return modifiers;
223     }
224
225     public List getProperties() {
226         return properties;
227     }
228
229     public List getDeclaredConstructors() {
230         return constructors;
231     }
232
233     public ModuleNode getModule() {
234         return module;
235     }
236
237     public void setModule(ModuleNode module) {
238         this.module = module;
239         if (module != null) {
240             this.compileUnit = module.getUnit();
241         }
242     }
243
244     public void addField(FieldNode node) {
245         node.setOwner(getName());
246         fields.add(node);
247         fieldIndex.put(node.getName(), node);
248     }
249
250     public void addProperty(PropertyNode node) {
251         FieldNode field = node.getField();
252         addField(field);
253
254         properties.add(node);
255     }
256
257     public PropertyNode addProperty(String JavaDoc name,
258                                     int modifiers,
259                                     String JavaDoc type,
260                                     Expression initialValueExpression,
261                                     Statement getterBlock,
262                                     Statement setterBlock) {
263         PropertyNode node =
264                 new PropertyNode(name, modifiers, type, getName(), initialValueExpression, getterBlock, setterBlock);
265         addProperty(node);
266         return node;
267     }
268
269     public void addConstructor(ConstructorNode node) {
270         constructors.add(node);
271     }
272
273     public ConstructorNode addConstructor(int modifiers, Parameter[] parameters, Statement code) {
274         ConstructorNode node = new ConstructorNode(modifiers, parameters, code);
275         addConstructor(node);
276         return node;
277     }
278
279     public void addMethod(MethodNode node) {
280         methods.add(node);
281         node.declaringClass = this;
282     }
283
284     /**
285      * IF a method with the given name and parameters is already defined then it is returned
286      * otherwise the given method is added to this node. This method is useful for
287      * default method adding like getProperty() or invokeMethod() where there may already
288      * be a method defined in a class and so the default implementations should not be added
289      * if already present.
290      */

291     public MethodNode addMethod(String JavaDoc name,
292                                 int modifiers,
293                                 String JavaDoc returnType,
294                                 Parameter[] parameters,
295                                 Statement code) {
296         MethodNode other = getDeclaredMethod(name, parameters);
297         // lets not add duplicate methods
298
if (other != null) {
299             return other;
300         }
301         MethodNode node = new MethodNode(name, modifiers, returnType, parameters, code);
302         addMethod(node);
303         return node;
304     }
305
306     /**
307      * Adds a synthetic method as part of the compilation process
308      */

309     public MethodNode addSyntheticMethod(String JavaDoc name,
310                                          int modifiers,
311                                          String JavaDoc returnType,
312                                          Parameter[] parameters,
313                                          Statement code) {
314         MethodNode answer = addMethod(name, modifiers, returnType, parameters, code);
315         answer.setSynthetic(true);
316         return answer;
317     }
318
319     public FieldNode addField(String JavaDoc name, int modifiers, String JavaDoc type, Expression initialValue) {
320         FieldNode node = new FieldNode(name, modifiers, type, getName(), initialValue);
321         addField(node);
322         return node;
323     }
324
325     public void addInterface(String JavaDoc name) {
326         // lets check if it already implements an interface
327
boolean skip = false;
328         for (int i = 0; i < interfaces.length; i++) {
329             if (name.equals(interfaces[i])) {
330                 skip = true;
331             }
332         }
333         if (!skip) {
334             String JavaDoc[] newInterfaces = new String JavaDoc[interfaces.length + 1];
335             System.arraycopy(interfaces, 0, newInterfaces, 0, interfaces.length);
336             newInterfaces[interfaces.length] = name;
337             interfaces = newInterfaces;
338         }
339     }
340
341     public void addMixin(MixinNode mixin) {
342         // lets check if it already uses a mixin
343
boolean skip = false;
344         String JavaDoc mixinName = mixin.getName();
345         for (int i = 0; i < mixins.length; i++) {
346             if (mixinName.equals(mixins[i].getName())) {
347                 skip = true;
348             }
349         }
350         if (!skip) {
351             MixinNode[] newMixins = new MixinNode[mixins.length + 1];
352             System.arraycopy(mixins, 0, newMixins, 0, mixins.length);
353             newMixins[mixins.length] = mixin;
354             mixins = newMixins;
355         }
356     }
357
358     public FieldNode getField(String JavaDoc name) {
359         return (FieldNode) fieldIndex.get(name);
360     }
361
362     /**
363      * @return the field node on the outer class or null if this is not an
364      * inner class
365      */

366     public FieldNode getOuterField(String JavaDoc name) {
367         return null;
368     }
369
370     /**
371      * Helper method to avoid casting to inner class
372      *
373      * @return
374      */

375     public ClassNode getOuterClass() {
376         return null;
377     }
378
379     public void addStaticInitializerStatements(List staticStatements) {
380         MethodNode method = null;
381         List declaredMethods = getDeclaredMethods("<clinit>");
382         if (declaredMethods.isEmpty()) {
383             method =
384                     addMethod("<clinit>", ACC_PUBLIC | ACC_STATIC, "void", Parameter.EMPTY_ARRAY, new BlockStatement());
385         } else {
386             method = (MethodNode) declaredMethods.get(0);
387         }
388         BlockStatement block = null;
389         Statement statement = method.getCode();
390         if (statement == null) {
391             block = new BlockStatement();
392         } else if (statement instanceof BlockStatement) {
393             block = (BlockStatement) statement;
394         } else {
395             block = new BlockStatement();
396             block.addStatement(statement);
397         }
398         block.addStatements(staticStatements);
399     }
400
401     /**
402      * @return a list of methods which match the given name
403      */

404     public List getDeclaredMethods(String JavaDoc name) {
405         List answer = new ArrayList();
406         for (Iterator iter = methods.iterator(); iter.hasNext();) {
407             MethodNode method = (MethodNode) iter.next();
408             if (name.equals(method.getName())) {
409                 answer.add(method);
410             }
411         }
412         return answer;
413     }
414
415     /**
416      * @return a list of methods which match the given name
417      */

418     public List getMethods(String JavaDoc name) {
419         List answer = new ArrayList();
420         ClassNode node = this;
421         do {
422             for (Iterator iter = node.methods.iterator(); iter.hasNext();) {
423                 MethodNode method = (MethodNode) iter.next();
424                 if (name.equals(method.getName())) {
425                     answer.add(method);
426                 }
427             }
428             node = node.getSuperClassNode();
429         } while (node != null);
430         return answer;
431     }
432
433     /**
434      * @return the method matching the given name and parameters or null
435      */

436     public MethodNode getDeclaredMethod(String JavaDoc name, Parameter[] parameters) {
437         for (Iterator iter = methods.iterator(); iter.hasNext();) {
438             MethodNode method = (MethodNode) iter.next();
439             if (name.equals(method.getName()) && parametersEqual(method.getParameters(), parameters)) {
440                 return method;
441             }
442         }
443         return null;
444     }
445
446     /**
447      * @return true if this node is derived from the given class node
448      */

449     public boolean isDerivedFrom(String JavaDoc name) {
450         ClassNode node = getSuperClassNode();
451         while (node != null) {
452             if (name.equals(node.getName())) {
453                 return true;
454             }
455             node = node.getSuperClassNode();
456         }
457         return false;
458     }
459
460     /**
461      * @return true if this class is derived from a groovy object
462      * i.e. it implements GroovyObject
463      */

464     public boolean isDerivedFromGroovyObject() {
465         return implementsInteface(GroovyObject.class.getName());
466     }
467
468     /**
469      * @param name the fully qualified name of the interface
470      * @return true if this class or any base class implements the given interface
471      */

472     public boolean implementsInteface(String JavaDoc name) {
473         ClassNode node = this;
474         do {
475             if (node.declaresInterface(name)) {
476                 return true;
477             }
478             node = node.getSuperClassNode();
479         } while (node != null);
480         return false;
481     }
482
483     /**
484      * @param name the fully qualified name of the interface
485      * @return true if this class declares that it implements the given interface
486      */

487     public boolean declaresInterface(String JavaDoc name) {
488         int size = interfaces.length;
489         for (int i = 0; i < size; i++) {
490             if (name.equals(interfaces[i])) {
491                 return true;
492             }
493         }
494         return false;
495     }
496
497     /**
498      * @return the ClassNode of the super class of this type
499      */

500     public ClassNode getSuperClassNode() {
501         if (superClass != null && superClass.length() > 0 && superClassNode == null && !name.equals("java.lang.Object")) {
502             // lets try find the class in the compile unit
503
String JavaDoc temp = resolveClassName(superClass);
504             if (temp == null) {
505                 throw new MissingClassException(superClass, this, "No such superclass");
506             } else {
507                 superClass = temp;
508             }
509             superClassNode = findClassNode(superClass);
510         }
511         return superClassNode;
512     }
513
514     /**
515      * Attempts to lookup the fully qualified class name in the compile unit or classpath
516      *
517      * @param type fully qulified type name
518      * @return the ClassNode for this type or null if it could not be found
519      */

520     public ClassNode findClassNode(String JavaDoc type) {
521         ClassNode answer = null;
522         CompileUnit theCompileUnit = getCompileUnit();
523         if (theCompileUnit != null) {
524             answer = theCompileUnit.getClass(type);
525             if (answer == null) {
526                 Class JavaDoc theClass;
527                 try {
528                     theClass = theCompileUnit.loadClass(type);
529                     answer = createClassNode(theClass);
530                 } catch (ClassNotFoundException JavaDoc e) {
531                     // lets ignore class not found exceptions
532
log.log(Level.WARNING, "Cannot find class: " + type, e);
533                 }
534             }
535         }
536         return answer;
537     }
538
539     protected ClassNode createClassNode(Class JavaDoc theClass) {
540         Class JavaDoc[] classInterfaces = theClass.getInterfaces();
541         int size = classInterfaces.length;
542         String JavaDoc[] interfaceNames = new String JavaDoc[size];
543         for (int i = 0; i < size; i++) {
544             interfaceNames[i] = classInterfaces[i].getName();
545         }
546
547         String JavaDoc className = null;
548         if (theClass.getSuperclass() != null) {
549             className = theClass.getSuperclass().getName();
550         }
551         ClassNode answer =
552                 new ClassNode(theClass.getName(),
553                         theClass.getModifiers(),
554                         className,
555                         interfaceNames,
556                         MixinNode.EMPTY_ARRAY);
557         answer.compileUnit = getCompileUnit();
558         Method JavaDoc[] declaredMethods = theClass.getDeclaredMethods();
559         for (int i = 0; i < declaredMethods.length; i++) {
560             answer.addMethod(createMethodNode(declaredMethods[i]));
561         }
562         Constructor JavaDoc[] declaredConstructors = theClass.getDeclaredConstructors();
563         for (int i = 0; i < declaredConstructors.length; i++) {
564             answer.addConstructor(createConstructorNode(declaredConstructors[i]));
565         }
566         return answer;
567     }
568
569
570     /**
571      * Factory method to create a new ConstructorNode via reflection
572      */

573     private ConstructorNode createConstructorNode(Constructor JavaDoc constructor) {
574         Parameter[] parameters = createParameters(constructor.getParameterTypes());
575         return new ConstructorNode(constructor.getModifiers(), parameters, EmptyStatement.INSTANCE);
576     }
577
578     /**
579      * Factory method to create a new MethodNode via reflection
580      */

581     protected MethodNode createMethodNode(Method JavaDoc method) {
582         Parameter[] parameters = createParameters(method.getParameterTypes());
583         return new MethodNode(method.getName(), method.getModifiers(), method.getReturnType().getName(), parameters, EmptyStatement.INSTANCE);
584     }
585
586     /**
587      * @param types
588      * @return
589      */

590     protected Parameter[] createParameters(Class JavaDoc[] types) {
591         Parameter[] parameters = Parameter.EMPTY_ARRAY;
592         int size = types.length;
593         if (size > 0) {
594             parameters = new Parameter[size];
595             for (int i = 0; i < size; i++) {
596                 parameters[i] = createParameter(types[i], i);
597             }
598         }
599         return parameters;
600     }
601
602     protected Parameter createParameter(Class JavaDoc parameterType, int idx) {
603         return new Parameter(parameterType.getName(), "param" + idx);
604     }
605
606
607     public String JavaDoc resolveClassName(String JavaDoc type) {
608         String JavaDoc answer = null;
609         if (type != null) {
610             if (getName().equals(type) || getNameWithoutPackage().equals(type)) {
611                 return getName();
612             }
613             // try to resolve Class names
614
answer = tryResolveClassAndInnerClass(type);
615
616             // try to resolve a public static inner class' name
617
String JavaDoc replacedPointType = type;
618             while (answer == null && replacedPointType.indexOf('.') > -1) {
619                 int lastPoint = replacedPointType.lastIndexOf('.');
620                 replacedPointType = new StringBuffer JavaDoc()
621                         .append(replacedPointType.substring(0, lastPoint)).append("$")
622                         .append(replacedPointType.substring(lastPoint + 1)).toString();
623                 answer = tryResolveClassAndInnerClass(replacedPointType);
624             }
625         }
626         return answer;
627     }
628
629     private String JavaDoc tryResolveClassAndInnerClass(String JavaDoc type) {
630         String JavaDoc answer = tryResolveClassFromCompileUnit(type);
631         if (answer == null) {
632             // lets try class in same package
633
String JavaDoc packageName = getPackageName();
634             if (packageName != null && packageName.length() > 0) {
635                 answer = tryResolveClassFromCompileUnit(packageName + "." + type);
636             }
637         }
638         if (answer == null) {
639             // lets try use the packages imported in the module
640
if (module != null) {
641                 //System.out.println("Looking up inside the imported packages: " + module.getImportPackages());
642

643                 for (Iterator iter = module.getImportPackages().iterator(); iter.hasNext();) {
644                     String JavaDoc packageName = (String JavaDoc) iter.next();
645                     answer = tryResolveClassFromCompileUnit(packageName + type);
646                     if (answer != null) {
647                         return answer;
648                     }
649                 }
650             }
651         }
652         if (answer == null) {
653             for (int i = 0, size = defaultImports.length; i < size; i++) {
654                 String JavaDoc packagePrefix = defaultImports[i];
655                 answer = tryResolveClassFromCompileUnit(packagePrefix + "." + type);
656                 if (answer != null) {
657                     return answer;
658                 }
659             }
660         }
661         return answer;
662     }
663
664     /**
665      * @param type
666      * @return
667      */

668     protected String JavaDoc tryResolveClassFromCompileUnit(String JavaDoc type) {
669         CompileUnit theCompileUnit = getCompileUnit();
670         if (theCompileUnit != null) {
671             if (theCompileUnit.getClass(type) != null) {
672                 return type;
673             }
674
675             try {
676                 theCompileUnit.loadClass(type);
677                 return type;
678             } catch (AccessControlException JavaDoc ace) {
679                 //Percolate this for better diagnostic info
680
throw ace;
681             } catch (Throwable JavaDoc e) {
682                 // fall through
683
}
684         }
685         return null;
686     }
687
688     public CompileUnit getCompileUnit() {
689         if (compileUnit == null && module != null) {
690             compileUnit = module.getUnit();
691         }
692         return compileUnit;
693     }
694
695     /**
696      * @return true if the two arrays are of the same size and have the same contents
697      */

698     protected boolean parametersEqual(Parameter[] a, Parameter[] b) {
699         if (a.length == b.length) {
700             boolean answer = true;
701             for (int i = 0; i < a.length; i++) {
702                 if (!a[i].getType().equals(b[i].getType())) {
703                     answer = false;
704                     break;
705                 }
706             }
707             return answer;
708         }
709         return false;
710     }
711
712     /**
713      * @return the name of the class for the given identifier if it is a class
714      * otherwise return null
715      */

716     public String JavaDoc getClassNameForExpression(String JavaDoc identifier) {
717         // lets see if it really is a class name
718
String JavaDoc className = null;
719         if (module != null) {
720             className = module.getImport(identifier);
721             if (className == null) {
722                 if (module.getUnit().getClass(identifier) != null) {
723                     className = identifier;
724                 } else {
725                     // lets prepend the package name to see if its in our
726
// package
727
String JavaDoc packageName = getPackageName();
728                     if (packageName != null) {
729                         String JavaDoc guessName = packageName + "." + identifier;
730                         if (module.getUnit().getClass(guessName) != null) {
731                             className = guessName;
732                         } else if (guessName.equals(name)) {
733                             className = name;
734                         }
735                     }
736                 }
737             }
738         } else {
739             System.out.println("No module for class: " + getName());
740         }
741         return className;
742     }
743
744     /**
745      * @return the package name of this class
746      */

747     public String JavaDoc getPackageName() {
748         int idx = name.lastIndexOf('.');
749         if (idx > 0) {
750             return name.substring(0, idx);
751         }
752         return null;
753     }
754
755     public String JavaDoc getNameWithoutPackage() {
756         int idx = name.lastIndexOf('.');
757         if (idx > 0) {
758             return name.substring(idx + 1);
759         }
760         return name;
761     }
762
763     public void visitContents(GroovyClassVisitor visitor) {
764         // now lets visit the contents of the class
765
for (Iterator iter = getProperties().iterator(); iter.hasNext();) {
766             visitor.visitProperty((PropertyNode) iter.next());
767         }
768
769         for (Iterator iter = getFields().iterator(); iter.hasNext();) {
770             visitor.visitField((FieldNode) iter.next());
771         }
772
773         for (Iterator iter = getDeclaredConstructors().iterator(); iter.hasNext();) {
774             visitor.visitConstructor((ConstructorNode) iter.next());
775         }
776
777         for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
778             visitor.visitMethod((MethodNode) iter.next());
779         }
780     }
781
782     public MethodNode getGetterMethod(String JavaDoc getterName) {
783         for (Iterator iter = methods.iterator(); iter.hasNext();) {
784             MethodNode method = (MethodNode) iter.next();
785             if (getterName.equals(method.getName())
786                     && !"void".equals(method.getReturnType())
787                     && method.getParameters().length == 0) {
788                 return method;
789             }
790         }
791         return null;
792     }
793
794     public MethodNode getSetterMethod(String JavaDoc getterName) {
795         for (Iterator iter = methods.iterator(); iter.hasNext();) {
796             MethodNode method = (MethodNode) iter.next();
797             if (getterName.equals(method.getName())
798                     && "void".equals(method.getReturnType())
799                     && method.getParameters().length == 1) {
800                 return method;
801             }
802         }
803         return null;
804     }
805
806     /**
807      * Is this class delcared in a static method (such as a closure / inner class declared in a static method)
808      *
809      * @return
810      */

811     public boolean isStaticClass() {
812         return staticClass;
813     }
814
815     public void setStaticClass(boolean staticClass) {
816         this.staticClass = staticClass;
817     }
818
819     /**
820      * @return Returns true if this inner class or closure was declared inside a script body
821      */

822     public boolean isScriptBody() {
823         return scriptBody;
824     }
825
826     public void setScriptBody(boolean scriptBody) {
827         this.scriptBody = scriptBody;
828     }
829
830     public boolean isScript() {
831         return script | isDerivedFrom(Script.class.getName());
832     }
833
834     public void setScript(boolean script) {
835         this.script = script;
836     }
837
838     public String JavaDoc toString() {
839         return super.toString() + "[name: " + name + "]";
840     }
841
842 }
843
Popular Tags