Source Code Cross Referenced for ClassNode.java in  » Scripting » groovy-1.0 » org » codehaus » groovy » ast » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » groovy 1.0 » org.codehaus.groovy.ast 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: ClassNode.java 4216 2006-11-13 16:04:23Z blackdrag $
0003:         * 
0004:         * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
0005:         * 
0006:         * Redistribution and use of this software and associated documentation
0007:         * ("Software"), with or without modification, are permitted provided that the
0008:         * following conditions are met:
0009:         *  1. Redistributions of source code must retain copyright statements and
0010:         * notices. Redistributions must also contain a copy of this document.
0011:         *  2. Redistributions in binary form must reproduce the above copyright
0012:         * notice, this list of conditions and the following disclaimer in the
0013:         * documentation and/or other materials provided with the distribution.
0014:         *  3. The name "groovy" must not be used to endorse or promote products
0015:         * derived from this Software without prior written permission of The Codehaus.
0016:         * For written permission, please contact info@codehaus.org.
0017:         *  4. Products derived from this Software may not be called "groovy" nor may
0018:         * "groovy" appear in their names without prior written permission of The
0019:         * Codehaus. "groovy" is a registered trademark of The Codehaus.
0020:         *  5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
0021:         * 
0022:         * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
0023:         * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0024:         * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0025:         * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
0026:         * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0027:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0028:         * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
0029:         * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0030:         * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0031:         * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
0032:         * DAMAGE.
0033:         *  
0034:         */
0035:        package org.codehaus.groovy.ast;
0036:
0037:        import groovy.lang.GroovyObject;
0038:
0039:        import org.codehaus.groovy.GroovyBugError;
0040:        import org.codehaus.groovy.ast.expr.Expression;
0041:        import org.codehaus.groovy.ast.expr.TupleExpression;
0042:        import org.codehaus.groovy.ast.stmt.BlockStatement;
0043:        import org.codehaus.groovy.ast.stmt.EmptyStatement;
0044:        import org.codehaus.groovy.ast.stmt.Statement;
0045:        import org.objectweb.asm.Opcodes;
0046:
0047:        import java.lang.reflect.Array;
0048:        import java.lang.reflect.Constructor;
0049:        import java.lang.reflect.Field;
0050:        import java.lang.reflect.Method;
0051:        import java.util.ArrayList;
0052:        import java.util.HashMap;
0053:        import java.util.HashSet;
0054:        import java.util.Iterator;
0055:        import java.util.List;
0056:        import java.util.Map;
0057:
0058:        /**
0059:         * Represents a class in the AST.<br/>
0060:         * A ClassNode should be created using the methods in ClassHelper. 
0061:         * This ClassNode may be used to represent a class declaration or
0062:         * any other type. This class uses a proxy meschanism allowing to
0063:         * create a class for a plain name at ast creation time. In another 
0064:         * phase of the compiler the real ClassNode for the plain name may be
0065:         * found. To avoid the need of exchanging this ClassNode with an 
0066:         * instance of the correct ClassNode the correct ClassNode is set as 
0067:         * redirect. All method calls are then redirected to that ClassNode.
0068:         * <br>
0069:         * Note: the proxy mechanism is only allowed for classes being marked
0070:         * as primary ClassNode which means they represent no actual class. 
0071:         * The redirect itself can be any type of ClassNode
0072:         *
0073:         * @see org.codehaus.groovy.ast.ClassHelper
0074:         * 
0075:         * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
0076:         * @author Jochen Theodorou
0077:         * @version $Revision: 4216 $
0078:         */
0079:        public class ClassNode extends AnnotatedNode implements  Opcodes {
0080:
0081:            public static ClassNode[] EMPTY_ARRAY = new ClassNode[0];
0082:
0083:            public static ClassNode THIS = new ClassNode(Object.class);
0084:            public static ClassNode SUPER = new ClassNode(Object.class);
0085:
0086:            private String name;
0087:            private int modifiers;
0088:            private ClassNode[] interfaces;
0089:            private MixinNode[] mixins;
0090:            private List constructors = new ArrayList();
0091:            private List objectInitializers = new ArrayList();
0092:            private List methods = new ArrayList();
0093:            private List fields = new ArrayList();
0094:            private List properties = new ArrayList();
0095:            private Map fieldIndex = new HashMap();
0096:            private ModuleNode module;
0097:            private CompileUnit compileUnit;
0098:            private boolean staticClass = false;
0099:            private boolean scriptBody = false;
0100:            private boolean script;
0101:            private ClassNode super Class;
0102:            boolean isPrimaryNode;
0103:
0104:            // use this to synchronize access for the lazy intit
0105:            protected Object lazyInitLock = new Object();
0106:
0107:            // clazz!=null when resolved
0108:            protected Class clazz;
0109:            // only false when this classNode is constructed from a class 
0110:            private boolean lazyInitDone = true;
0111:            // not null if if the ClassNode is an array 
0112:            private ClassNode componentType = null;
0113:            // if not null this instance is handled as proxy 
0114:            // for the redirect
0115:            private ClassNode redirect = null;
0116:
0117:            /**
0118:             * Returns the ClassNode this ClassNode is redirecting to.
0119:             */
0120:            protected ClassNode redirect() {
0121:                if (redirect == null)
0122:                    return this ;
0123:                return redirect.redirect();
0124:            }
0125:
0126:            /**
0127:             * Sets this instance as proxy for the given ClassNode. 
0128:             * @param cn the class to redirect to. If set to null the redirect will be removed
0129:             */
0130:            public void setRedirect(ClassNode cn) {
0131:                if (isPrimaryNode)
0132:                    throw new GroovyBugError(
0133:                            "tried to set a redirect for a primary ClassNode ("
0134:                                    + getName() + "->" + cn.getName() + ").");
0135:                if (cn != null)
0136:                    cn = cn.redirect();
0137:                redirect = cn;
0138:            }
0139:
0140:            /**
0141:             * Returns a ClassNode representing an array of the class
0142:             * represented by this ClassNode
0143:             */
0144:            public ClassNode makeArray() {
0145:                if (redirect != null)
0146:                    return redirect().makeArray();
0147:                ClassNode cn;
0148:                if (clazz != null) {
0149:                    Class ret = Array.newInstance(clazz, 0).getClass();
0150:                    // don't use the ClassHelper here!
0151:                    cn = new ClassNode(ret, this );
0152:                } else {
0153:                    cn = new ClassNode(this );
0154:                }
0155:                return cn;
0156:            }
0157:
0158:            /**
0159:             * Returns if this instance is a primary ClassNode
0160:             */
0161:            public boolean isPrimaryClassNode() {
0162:                return redirect().isPrimaryNode
0163:                        || (componentType != null && componentType
0164:                                .isPrimaryClassNode());
0165:            }
0166:
0167:            /**
0168:             * Constructor used by makeArray() if no real class is available
0169:             */
0170:            private ClassNode(ClassNode componentType) {
0171:                this (componentType.getName() + "[]", ACC_PUBLIC,
0172:                        ClassHelper.OBJECT_TYPE);
0173:                this .componentType = componentType.redirect();
0174:                isPrimaryNode = false;
0175:            }
0176:
0177:            /**
0178:             * Constructor used by makeArray() if a real class is available
0179:             */
0180:            private ClassNode(Class c, ClassNode componentType) {
0181:                this (c);
0182:                this .componentType = componentType;
0183:                isPrimaryNode = false;
0184:            }
0185:
0186:            /**
0187:             * Creates a ClassNode from a real class. The resulting 
0188:             * ClassNode will be no primary ClassNode.
0189:             */
0190:            public ClassNode(Class c) {
0191:                this (c.getName(), c.getModifiers(), null, null,
0192:                        MixinNode.EMPTY_ARRAY);
0193:                clazz = c;
0194:                lazyInitDone = false;
0195:                CompileUnit cu = getCompileUnit();
0196:                if (cu != null)
0197:                    cu.addClass(this );
0198:                isPrimaryNode = false;
0199:            }
0200:
0201:            /**
0202:             * The complete class structure will be initialized only when really
0203:             * needed to avoid having too much objects during compilation
0204:             */
0205:            private void lazyClassInit() {
0206:                synchronized (lazyInitLock) {
0207:                    if (lazyInitDone)
0208:                        return;
0209:
0210:                    Field[] fields = clazz.getDeclaredFields();
0211:                    for (int i = 0; i < fields.length; i++) {
0212:                        addField(fields[i].getName(), fields[i].getModifiers(),
0213:                                this , null);
0214:                    }
0215:                    Method[] methods = clazz.getDeclaredMethods();
0216:                    for (int i = 0; i < methods.length; i++) {
0217:                        Method m = methods[i];
0218:                        MethodNode mn = new MethodNode(m.getName(), m
0219:                                .getModifiers(), ClassHelper.make(m
0220:                                .getReturnType()), createParameters(m
0221:                                .getParameterTypes()), ClassHelper.make(m
0222:                                .getExceptionTypes()), null);
0223:                        addMethod(mn);
0224:                    }
0225:                    Constructor[] constructors = clazz
0226:                            .getDeclaredConstructors();
0227:                    for (int i = 0; i < constructors.length; i++) {
0228:                        Constructor ctor = constructors[i];
0229:                        addConstructor(ctor.getModifiers(),
0230:                                createParameters(ctor.getParameterTypes()),
0231:                                ClassHelper.make(ctor.getExceptionTypes()),
0232:                                null);
0233:                    }
0234:                    Class sc = clazz.getSuperclass();
0235:                    if (sc != null)
0236:                        super Class = ClassHelper.make(sc);
0237:                    buildInterfaceTypes(clazz);
0238:                    lazyInitDone = true;
0239:                }
0240:            }
0241:
0242:            private void buildInterfaceTypes(Class c) {
0243:                Class[] interfaces = c.getInterfaces();
0244:                ClassNode[] ret = new ClassNode[interfaces.length];
0245:                for (int i = 0; i < interfaces.length; i++) {
0246:                    ret[i] = ClassHelper.make(interfaces[i]);
0247:                }
0248:                this .interfaces = ret;
0249:            }
0250:
0251:            // added to track the enclosing method for local inner classes
0252:            private MethodNode enclosingMethod = null;
0253:
0254:            public MethodNode getEnclosingMethod() {
0255:                return redirect().enclosingMethod;
0256:            }
0257:
0258:            public void setEnclosingMethod(MethodNode enclosingMethod) {
0259:                redirect().enclosingMethod = enclosingMethod;
0260:            }
0261:
0262:            /**
0263:             * @param name       is the full name of the class
0264:             * @param modifiers  the modifiers,
0265:             * @param superClass the base class name - use "java.lang.Object" if no direct
0266:             *                   base class
0267:             * @see org.objectweb.asm.Opcodes
0268:             */
0269:            public ClassNode(String name, int modifiers, ClassNode super Class) {
0270:                this (name, modifiers, super Class, ClassHelper.EMPTY_TYPE_ARRAY,
0271:                        MixinNode.EMPTY_ARRAY);
0272:            }
0273:
0274:            /**
0275:             * @param name       is the full name of the class
0276:             * @param modifiers  the modifiers,
0277:             * @param superClass the base class name - use "java.lang.Object" if no direct
0278:             *                   base class
0279:             * @see org.objectweb.asm.Opcodes
0280:             */
0281:            public ClassNode(String name, int modifiers, ClassNode super Class,
0282:                    ClassNode[] interfaces, MixinNode[] mixins) {
0283:                this .name = name;
0284:                this .modifiers = modifiers;
0285:                this .super Class = super Class;
0286:                this .interfaces = interfaces;
0287:                this .mixins = mixins;
0288:                isPrimaryNode = true;
0289:            }
0290:
0291:            /**
0292:             * Sets the superclass of this ClassNode
0293:             */
0294:            public void setSuperClass(ClassNode super Class) {
0295:                redirect().super Class = super Class;
0296:            }
0297:
0298:            /**
0299:             * Returns a list containing FieldNode objects for
0300:             * each field in the class represented by this ClassNode
0301:             */
0302:            public List getFields() {
0303:                if (!lazyInitDone) {
0304:                    lazyClassInit();
0305:                }
0306:                if (redirect != null)
0307:                    return redirect().getFields();
0308:                return fields;
0309:            }
0310:
0311:            /**
0312:             * Returns an array of ClassNodes representing the
0313:             * interfaces the class implements
0314:             */
0315:            public ClassNode[] getInterfaces() {
0316:                if (!lazyInitDone) {
0317:                    lazyClassInit();
0318:                }
0319:                if (redirect != null)
0320:                    return redirect().getInterfaces();
0321:                return interfaces;
0322:            }
0323:
0324:            public MixinNode[] getMixins() {
0325:                return redirect().mixins;
0326:            }
0327:
0328:            /**
0329:             * Returns a list containing MethodNode objects for
0330:             * each method in the class represented by this ClassNode
0331:             */
0332:            public List getMethods() {
0333:                if (!lazyInitDone) {
0334:                    lazyClassInit();
0335:                }
0336:                if (redirect != null)
0337:                    return redirect().getMethods();
0338:                return methods;
0339:            }
0340:
0341:            /**
0342:             * Returns a list containing MethodNode objects for
0343:             * each abstract method in the class represented by 
0344:             * this ClassNode
0345:             */
0346:            public List getAbstractMethods() {
0347:
0348:                HashSet abstractNodes = new HashSet();
0349:                // let us collect the abstract super classes and stop at the
0350:                // first non abstract super class. If such a class still 
0351:                // contains abstract methods, then loading that class will fail.
0352:                // No need to be extra carefull here for that.
0353:                ClassNode parent = this .redirect();
0354:                do {
0355:                    abstractNodes.add(parent);
0356:                    ClassNode[] interfaces = parent.getInterfaces();
0357:                    for (int i = 0; i < interfaces.length; i++) {
0358:                        abstractNodes.add(interfaces[i].redirect());
0359:                    }
0360:                    parent = parent.getSuperClass().redirect();
0361:                } while (parent != null
0362:                        && ((parent.getModifiers() & Opcodes.ACC_ABSTRACT) != 0));
0363:
0364:                List result = new ArrayList();
0365:                for (Iterator methIt = getAllDeclaredMethods().iterator(); methIt
0366:                        .hasNext();) {
0367:                    MethodNode method = (MethodNode) methIt.next();
0368:                    // add only abstract methods from abtract classes that
0369:                    // are not overwritten
0370:                    if (abstractNodes.contains(method.getDeclaringClass()
0371:                            .redirect())
0372:                            && (method.getModifiers() & Opcodes.ACC_ABSTRACT) != 0) {
0373:                        result.add(method);
0374:                    }
0375:                }
0376:                if (result.size() == 0) {
0377:                    return null;
0378:                } else {
0379:                    return result;
0380:                }
0381:            }
0382:
0383:            public List getAllDeclaredMethods() {
0384:                return new ArrayList(getDeclaredMethodsMap().values());
0385:            }
0386:
0387:            protected Map getDeclaredMethodsMap() {
0388:                // Start off with the methods from the superclass.
0389:                ClassNode parent = getSuperClass();
0390:                Map result = null;
0391:                if (parent != null) {
0392:                    result = parent.getDeclaredMethodsMap();
0393:                } else {
0394:                    result = new HashMap();
0395:                }
0396:
0397:                // add in unimplemented abstract methods from the interfaces
0398:                ClassNode[] interfaces = getInterfaces();
0399:                for (int i = 0; i < interfaces.length; i++) {
0400:                    ClassNode iface = interfaces[i];
0401:                    Map ifaceMethodsMap = iface.getDeclaredMethodsMap();
0402:                    for (Iterator iter = ifaceMethodsMap.keySet().iterator(); iter
0403:                            .hasNext();) {
0404:                        String methSig = (String) iter.next();
0405:                        if (!result.containsKey(methSig)) {
0406:                            MethodNode methNode = (MethodNode) ifaceMethodsMap
0407:                                    .get(methSig);
0408:                            result.put(methSig, methNode);
0409:                        }
0410:                    }
0411:                }
0412:
0413:                // And add in the methods implemented in this class.
0414:                for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
0415:                    MethodNode method = (MethodNode) iter.next();
0416:                    String sig = method.getTypeDescriptor();
0417:                    result.put(sig, method);
0418:                }
0419:                return result;
0420:            }
0421:
0422:            public String getName() {
0423:                return redirect().name;
0424:            }
0425:
0426:            public String setName(String name) {
0427:                return redirect().name = name;
0428:            }
0429:
0430:            public int getModifiers() {
0431:                return redirect().modifiers;
0432:            }
0433:
0434:            public List getProperties() {
0435:                return redirect().properties;
0436:            }
0437:
0438:            public List getDeclaredConstructors() {
0439:                if (!lazyInitDone) {
0440:                    lazyClassInit();
0441:                }
0442:                return redirect().constructors;
0443:            }
0444:
0445:            public ModuleNode getModule() {
0446:                return redirect().module;
0447:            }
0448:
0449:            public void setModule(ModuleNode module) {
0450:                redirect().module = module;
0451:                if (module != null) {
0452:                    redirect().compileUnit = module.getUnit();
0453:                }
0454:            }
0455:
0456:            public void addField(FieldNode node) {
0457:                node.setDeclaringClass(redirect());
0458:                node.setOwner(redirect());
0459:                redirect().fields.add(node);
0460:                redirect().fieldIndex.put(node.getName(), node);
0461:            }
0462:
0463:            public void addProperty(PropertyNode node) {
0464:                node.setDeclaringClass(redirect());
0465:                FieldNode field = node.getField();
0466:                addField(field);
0467:
0468:                redirect().properties.add(node);
0469:            }
0470:
0471:            public PropertyNode addProperty(String name, int modifiers,
0472:                    ClassNode type, Expression initialValueExpression,
0473:                    Statement getterBlock, Statement setterBlock) {
0474:                for (Iterator iter = getProperties().iterator(); iter.hasNext();) {
0475:                    PropertyNode pn = (PropertyNode) iter.next();
0476:                    if (pn.getName().equals(name))
0477:                        return pn;
0478:                }
0479:                PropertyNode node = new PropertyNode(name, modifiers, type,
0480:                        redirect(), initialValueExpression, getterBlock,
0481:                        setterBlock);
0482:                addProperty(node);
0483:                return node;
0484:            }
0485:
0486:            public void addConstructor(ConstructorNode node) {
0487:                node.setDeclaringClass(this );
0488:                redirect().constructors.add(node);
0489:            }
0490:
0491:            public ConstructorNode addConstructor(int modifiers,
0492:                    Parameter[] parameters, ClassNode[] exceptions,
0493:                    Statement code) {
0494:                ConstructorNode node = new ConstructorNode(modifiers,
0495:                        parameters, exceptions, code);
0496:                addConstructor(node);
0497:                return node;
0498:            }
0499:
0500:            public void addMethod(MethodNode node) {
0501:                node.setDeclaringClass(this );
0502:                redirect().methods.add(node);
0503:            }
0504:
0505:            /**
0506:             * IF a method with the given name and parameters is already defined then it is returned
0507:             * otherwise the given method is added to this node. This method is useful for
0508:             * default method adding like getProperty() or invokeMethod() where there may already
0509:             * be a method defined in a class and  so the default implementations should not be added
0510:             * if already present.
0511:             */
0512:            public MethodNode addMethod(String name, int modifiers,
0513:                    ClassNode returnType, Parameter[] parameters,
0514:                    ClassNode[] exceptions, Statement code) {
0515:                MethodNode other = getDeclaredMethod(name, parameters);
0516:                // lets not add duplicate methods
0517:                if (other != null) {
0518:                    return other;
0519:                }
0520:                MethodNode node = new MethodNode(name, modifiers, returnType,
0521:                        parameters, exceptions, code);
0522:                addMethod(node);
0523:                return node;
0524:            }
0525:
0526:            /**
0527:             * Adds a synthetic method as part of the compilation process
0528:             */
0529:            public MethodNode addSyntheticMethod(String name, int modifiers,
0530:                    ClassNode returnType, Parameter[] parameters,
0531:                    ClassNode[] exceptions, Statement code) {
0532:                MethodNode answer = addMethod(name, modifiers, returnType,
0533:                        parameters, exceptions, code);
0534:                answer.setSynthetic(true);
0535:                return answer;
0536:            }
0537:
0538:            public FieldNode addField(String name, int modifiers,
0539:                    ClassNode type, Expression initialValue) {
0540:                FieldNode node = new FieldNode(name, modifiers, type,
0541:                        redirect(), initialValue);
0542:                addField(node);
0543:                return node;
0544:            }
0545:
0546:            public void addInterface(ClassNode type) {
0547:                // lets check if it already implements an interface
0548:                boolean skip = false;
0549:                ClassNode[] interfaces = redirect().interfaces;
0550:                for (int i = 0; i < interfaces.length; i++) {
0551:                    if (type.equals(interfaces[i])) {
0552:                        skip = true;
0553:                    }
0554:                }
0555:                if (!skip) {
0556:                    ClassNode[] newInterfaces = new ClassNode[interfaces.length + 1];
0557:                    System.arraycopy(interfaces, 0, newInterfaces, 0,
0558:                            interfaces.length);
0559:                    newInterfaces[interfaces.length] = type;
0560:                    redirect().interfaces = newInterfaces;
0561:                }
0562:            }
0563:
0564:            public boolean equals(Object o) {
0565:                if (redirect != null)
0566:                    return redirect().equals(o);
0567:                ClassNode cn = (ClassNode) o;
0568:                return (cn.getName().equals(getName()));
0569:            }
0570:
0571:            public void addMixin(MixinNode mixin) {
0572:                // lets check if it already uses a mixin
0573:                MixinNode[] mixins = redirect().mixins;
0574:                boolean skip = false;
0575:                for (int i = 0; i < mixins.length; i++) {
0576:                    if (mixin.equals(mixins[i])) {
0577:                        skip = true;
0578:                    }
0579:                }
0580:                if (!skip) {
0581:                    MixinNode[] newMixins = new MixinNode[mixins.length + 1];
0582:                    System.arraycopy(mixins, 0, newMixins, 0, mixins.length);
0583:                    newMixins[mixins.length] = mixin;
0584:                    redirect().mixins = newMixins;
0585:                }
0586:            }
0587:
0588:            public FieldNode getField(String name) {
0589:                return (FieldNode) redirect().fieldIndex.get(name);
0590:            }
0591:
0592:            /**
0593:             * @return the field node on the outer class or null if this is not an
0594:             *         inner class
0595:             */
0596:            public FieldNode getOuterField(String name) {
0597:                return null;
0598:            }
0599:
0600:            /**
0601:             * Helper method to avoid casting to inner class
0602:             */
0603:            public ClassNode getOuterClass() {
0604:                return null;
0605:            }
0606:
0607:            public void addObjectInitializerStatements(Statement statements) {
0608:                objectInitializers.add(statements);
0609:            }
0610:
0611:            public List getObjectInitializerStatements() {
0612:                return objectInitializers;
0613:            }
0614:
0615:            public void addStaticInitializerStatements(List staticStatements,
0616:                    boolean fieldInit) {
0617:                MethodNode method = null;
0618:                List declaredMethods = getDeclaredMethods("<clinit>");
0619:                if (declaredMethods.isEmpty()) {
0620:                    method = addMethod("<clinit>", ACC_PUBLIC | ACC_STATIC,
0621:                            ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY,
0622:                            ClassNode.EMPTY_ARRAY, new BlockStatement());
0623:                    method.setSynthetic(true);
0624:                } else {
0625:                    method = (MethodNode) declaredMethods.get(0);
0626:                }
0627:                BlockStatement block = null;
0628:                Statement statement = method.getCode();
0629:                if (statement == null) {
0630:                    block = new BlockStatement();
0631:                } else if (statement instanceof  BlockStatement) {
0632:                    block = (BlockStatement) statement;
0633:                } else {
0634:                    block = new BlockStatement();
0635:                    block.addStatement(statement);
0636:                }
0637:
0638:                // while anything inside a static initializer block is appended 
0639:                // we don't want to append in the case we have a initialization
0640:                // expression of a static field. In that case we want to add
0641:                // before the other statements
0642:                if (!fieldInit) {
0643:                    block.addStatements(staticStatements);
0644:                } else {
0645:                    List blockStatements = block.getStatements();
0646:                    staticStatements.addAll(blockStatements);
0647:                    blockStatements.clear();
0648:                    blockStatements.addAll(staticStatements);
0649:                }
0650:            }
0651:
0652:            /**
0653:             * @return a list of methods which match the given name
0654:             */
0655:            public List getDeclaredMethods(String name) {
0656:                List answer = new ArrayList();
0657:                for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
0658:                    MethodNode method = (MethodNode) iter.next();
0659:                    if (name.equals(method.getName())) {
0660:                        answer.add(method);
0661:                    }
0662:                }
0663:                return answer;
0664:            }
0665:
0666:            /**
0667:             * @return a list of methods which match the given name
0668:             */
0669:            public List getMethods(String name) {
0670:                List answer = new ArrayList();
0671:                ClassNode node = this ;
0672:                do {
0673:                    for (Iterator iter = node.getMethods().iterator(); iter
0674:                            .hasNext();) {
0675:                        MethodNode method = (MethodNode) iter.next();
0676:                        if (name.equals(method.getName())) {
0677:                            answer.add(method);
0678:                        }
0679:                    }
0680:                    node = node.getSuperClass();
0681:                } while (node != null);
0682:                return answer;
0683:            }
0684:
0685:            /**
0686:             * @return the method matching the given name and parameters or null
0687:             */
0688:            public MethodNode getDeclaredMethod(String name,
0689:                    Parameter[] parameters) {
0690:                for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
0691:                    MethodNode method = (MethodNode) iter.next();
0692:                    if (name.equals(method.getName())
0693:                            && parametersEqual(method.getParameters(),
0694:                                    parameters)) {
0695:                        return method;
0696:                    }
0697:                }
0698:                return null;
0699:            }
0700:
0701:            /**
0702:             * @return true if this node is derived from the given class node
0703:             */
0704:            public boolean isDerivedFrom(ClassNode type) {
0705:                ClassNode node = this ;
0706:                while (node != null) {
0707:                    if (type.equals(node)) {
0708:                        return true;
0709:                    }
0710:                    node = node.getSuperClass();
0711:                }
0712:                return false;
0713:            }
0714:
0715:            /**
0716:             * @return true if this class is derived from a groovy object
0717:             *         i.e. it implements GroovyObject
0718:             */
0719:            public boolean isDerivedFromGroovyObject() {
0720:                return implements Interface(GroovyObject.class.getName());
0721:            }
0722:
0723:            /**
0724:             * @param name the fully qualified name of the interface
0725:             * @return true if this class or any base class implements the given interface
0726:             */
0727:            public boolean implements Interface(String name) {
0728:                ClassNode node = redirect();
0729:                do {
0730:                    if (node.declaresInterface(name)) {
0731:                        return true;
0732:                    }
0733:                    node = node.getSuperClass();
0734:                } while (node != null);
0735:                return false;
0736:            }
0737:
0738:            /**
0739:             * @param name the fully qualified name of the interface
0740:             * @return true if this class declares that it implements the given interface
0741:             */
0742:            public boolean declaresInterface(String name) {
0743:                ClassNode[] interfaces = redirect().getInterfaces();
0744:                int size = interfaces.length;
0745:                for (int i = 0; i < size; i++) {
0746:                    if (interfaces[i].getName().equals(name)) {
0747:                        return true;
0748:                    }
0749:                }
0750:                return false;
0751:            }
0752:
0753:            /**
0754:             * @return the ClassNode of the super class of this type
0755:             */
0756:            public ClassNode getSuperClass() {
0757:                if (!lazyInitDone && !isResolved()) {
0758:                    throw new GroovyBugError("Classnode#getSuperClass for "
0759:                            + getName() + " called before class resolving");
0760:                }
0761:                return redirect().getUnresolvedSuperClass();
0762:            }
0763:
0764:            public ClassNode getUnresolvedSuperClass() {
0765:                if (!lazyInitDone) {
0766:                    lazyClassInit();
0767:                }
0768:                return redirect().super Class;
0769:            }
0770:
0771:            /**
0772:             * Factory method to create a new MethodNode via reflection
0773:             */
0774:            protected MethodNode createMethodNode(Method method) {
0775:                Parameter[] parameters = createParameters(method
0776:                        .getParameterTypes());
0777:                return new MethodNode(method.getName(), method.getModifiers(),
0778:                        ClassHelper.make(method.getReturnType()), parameters,
0779:                        ClassHelper.make(method.getExceptionTypes()),
0780:                        EmptyStatement.INSTANCE);
0781:            }
0782:
0783:            /**
0784:             * @param types
0785:             */
0786:            protected Parameter[] createParameters(Class[] types) {
0787:                Parameter[] parameters = Parameter.EMPTY_ARRAY;
0788:                int size = types.length;
0789:                if (size > 0) {
0790:                    parameters = new Parameter[size];
0791:                    for (int i = 0; i < size; i++) {
0792:                        parameters[i] = createParameter(types[i], i);
0793:                    }
0794:                }
0795:                return parameters;
0796:            }
0797:
0798:            protected Parameter createParameter(Class parameterType, int idx) {
0799:                return new Parameter(ClassHelper.make(parameterType), "param"
0800:                        + idx);
0801:            }
0802:
0803:            public CompileUnit getCompileUnit() {
0804:                if (redirect != null)
0805:                    return redirect().getCompileUnit();
0806:                if (compileUnit == null && module != null) {
0807:                    compileUnit = module.getUnit();
0808:                }
0809:                return compileUnit;
0810:            }
0811:
0812:            protected void setCompileUnit(CompileUnit cu) {
0813:                if (redirect != null)
0814:                    redirect().setCompileUnit(cu);
0815:                if (compileUnit != null)
0816:                    compileUnit = cu;
0817:            }
0818:
0819:            /**
0820:             * @return true if the two arrays are of the same size and have the same contents
0821:             */
0822:            protected boolean parametersEqual(Parameter[] a, Parameter[] b) {
0823:                if (a.length == b.length) {
0824:                    boolean answer = true;
0825:                    for (int i = 0; i < a.length; i++) {
0826:                        if (!a[i].getType().equals(b[i].getType())) {
0827:                            answer = false;
0828:                            break;
0829:                        }
0830:                    }
0831:                    return answer;
0832:                }
0833:                return false;
0834:            }
0835:
0836:            /**
0837:             * @return the package name of this class
0838:             */
0839:            public String getPackageName() {
0840:                int idx = getName().lastIndexOf('.');
0841:                if (idx > 0) {
0842:                    return getName().substring(0, idx);
0843:                }
0844:                return null;
0845:            }
0846:
0847:            public String getNameWithoutPackage() {
0848:                int idx = getName().lastIndexOf('.');
0849:                if (idx > 0) {
0850:                    return getName().substring(idx + 1);
0851:                }
0852:                return getName();
0853:            }
0854:
0855:            public void visitContents(GroovyClassVisitor visitor) {
0856:
0857:                // now lets visit the contents of the class
0858:                for (Iterator iter = getProperties().iterator(); iter.hasNext();) {
0859:                    PropertyNode pn = (PropertyNode) iter.next();
0860:                    visitor.visitProperty(pn);
0861:                }
0862:
0863:                for (Iterator iter = getFields().iterator(); iter.hasNext();) {
0864:                    FieldNode fn = (FieldNode) iter.next();
0865:                    visitor.visitField(fn);
0866:                }
0867:
0868:                for (Iterator iter = getDeclaredConstructors().iterator(); iter
0869:                        .hasNext();) {
0870:                    ConstructorNode cn = (ConstructorNode) iter.next();
0871:                    visitor.visitConstructor(cn);
0872:                }
0873:
0874:                for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
0875:                    MethodNode mn = (MethodNode) iter.next();
0876:                    visitor.visitMethod(mn);
0877:                }
0878:            }
0879:
0880:            public MethodNode getGetterMethod(String getterName) {
0881:                for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
0882:                    MethodNode method = (MethodNode) iter.next();
0883:                    if (getterName.equals(method.getName())
0884:                            && ClassHelper.VOID_TYPE != method.getReturnType()
0885:                            && method.getParameters().length == 0) {
0886:                        return method;
0887:                    }
0888:                }
0889:                return null;
0890:            }
0891:
0892:            public MethodNode getSetterMethod(String getterName) {
0893:                for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
0894:                    MethodNode method = (MethodNode) iter.next();
0895:                    if (getterName.equals(method.getName())
0896:                            && ClassHelper.VOID_TYPE == method.getReturnType()
0897:                            && method.getParameters().length == 1) {
0898:                        return method;
0899:                    }
0900:                }
0901:                return null;
0902:            }
0903:
0904:            /**
0905:             * Is this class delcared in a static method (such as a closure / inner class declared in a static method)
0906:             */
0907:            public boolean isStaticClass() {
0908:                return redirect().staticClass;
0909:            }
0910:
0911:            public void setStaticClass(boolean staticClass) {
0912:                redirect().staticClass = staticClass;
0913:            }
0914:
0915:            /**
0916:             * @return Returns true if this inner class or closure was declared inside a script body
0917:             */
0918:            public boolean isScriptBody() {
0919:                return redirect().scriptBody;
0920:            }
0921:
0922:            public void setScriptBody(boolean scriptBody) {
0923:                redirect().scriptBody = scriptBody;
0924:            }
0925:
0926:            public boolean isScript() {
0927:                return redirect().script
0928:                        || isDerivedFrom(ClassHelper.SCRIPT_TYPE);
0929:            }
0930:
0931:            public void setScript(boolean script) {
0932:                redirect().script = script;
0933:            }
0934:
0935:            public String toString() {
0936:                return super .toString() + "[name: " + getName() + "]";
0937:            }
0938:
0939:            /**
0940:             * Returns true if the given method has a possibly matching method with the given name and arguments
0941:             */
0942:            public boolean hasPossibleMethod(String name, Expression arguments) {
0943:                int count = 0;
0944:
0945:                if (arguments instanceof  TupleExpression) {
0946:                    TupleExpression tuple = (TupleExpression) arguments;
0947:                    // TODO this won't strictly be true when using list expension in argument calls
0948:                    count = tuple.getExpressions().size();
0949:                }
0950:                ClassNode node = this ;
0951:                do {
0952:                    for (Iterator iter = getMethods().iterator(); iter
0953:                            .hasNext();) {
0954:                        MethodNode method = (MethodNode) iter.next();
0955:                        if (name.equals(method.getName())
0956:                                && method.getParameters().length == count) {
0957:                            return true;
0958:                        }
0959:                    }
0960:                    node = node.getSuperClass();
0961:                } while (node != null);
0962:                return false;
0963:            }
0964:
0965:            public boolean isInterface() {
0966:                return (getModifiers() & Opcodes.ACC_INTERFACE) > 0;
0967:            }
0968:
0969:            public boolean isResolved() {
0970:                return redirect().clazz != null
0971:                        || (componentType != null && componentType.isResolved());
0972:            }
0973:
0974:            public boolean isArray() {
0975:                return componentType != null;
0976:            }
0977:
0978:            public ClassNode getComponentType() {
0979:                return componentType;
0980:            }
0981:
0982:            public Class getTypeClass() {
0983:                Class c = redirect().clazz;
0984:                if (c != null)
0985:                    return c;
0986:                ClassNode component = redirect().componentType;
0987:                if (component != null && component.isResolved()) {
0988:                    ClassNode cn = component.makeArray();
0989:                    setRedirect(cn);
0990:                    return redirect().clazz;
0991:                }
0992:                throw new GroovyBugError("ClassNode#getTypeClass for "
0993:                        + getName()
0994:                        + " is called before the type class is set ");
0995:            }
0996:
0997:            public boolean hasPackageName() {
0998:                return redirect().name.indexOf('.') > 0;
0999:            }
1000:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.