/*
 * Copyright 2003-2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.codehaus.groovy.ast;

import groovy.lang.GroovyObject;

import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.EmptyStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.objectweb.asm.Opcodes;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Represents a class in the AST.<br/>
 * A ClassNode should be created using the methods in ClassHelper. 
 * This ClassNode may be used to represent a class declaration or
 * any other type. This class uses a proxy meschanism allowing to
 * create a class for a plain name at ast creation time. In another 
 * phase of the compiler the real ClassNode for the plain name may be
 * found. To avoid the need of exchanging this ClassNode with an 
 * instance of the correct ClassNode the correct ClassNode is set as 
 * redirect. Most method calls are then redirected to that ClassNode.
 * <br>
 * <b>Note:</b> the proxy mechanism is only allowed for classes being marked
 * as primary ClassNode which means they represent no actual class. 
 * The redirect itself can be any type of ClassNode
 * <br>
 * To descirbe generic type signature see {@link #getGenericsTypes()} and
 * {@link #setGenericsTypes(GenericsType[])}. These emthods are not proxied,
 * they describe the type signature used at the point of declaration or the
 * type signatures provided by the class. If the type signatures provided
 * by the class are needed, then a call to {@link #redirect()} will help.
 *
 * @see org.codehaus.groovy.ast.ClassHelper
 * 
 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
 * @author Jochen Theodorou
 * @version $Revision$
 */
public class ClassNode extends AnnotatedNode implements Opcodes {

    public static ClassNode[] EMPTY_ARRAY = new ClassNode[0];
    
    public static ClassNode THIS = new ClassNode(Object.class);
    public static ClassNode SUPER = new ClassNode(Object.class);
    
    private String name;
    private final int modifiers;
    private ClassNode[] interfaces;
    private MixinNode[] mixins;
    private List constructors = new ArrayList();
    private List  objectInitializers = new ArrayList();
    private List methods = new ArrayList();
    private List fields = new ArrayList();
    private List properties = new ArrayList();
    private Map fieldIndex = new HashMap();
    private ModuleNode module;
    private CompileUnit compileUnit;
    private boolean staticClass = false;
    private boolean scriptBody = false;
    private boolean script;
    private ClassNode superClass;
    boolean isPrimaryNode;
    
    // use this to synchronize access for the lazy intit
    protected Object lazyInitLock = new Object();

    // clazz!=null when resolved
    protected Class clazz;
    // only false when this classNode is constructed from a class 
    private boolean lazyInitDone=true;
    // not null if if the ClassNode is an array 
    private ClassNode componentType = null;
    // if not null this instance is handled as proxy 
    // for the redirect
    private ClassNode redirect=null; 
    // flag if the classes or its members are annotated
    private boolean annotated;
    
    // type spec for generics
    private GenericsType[] genericsTypes=null;
    private boolean usesGenerics=false;
    
    // if set tot true the name getGenericsTypes consists
    // of 1 element describing the name of the placeholder
    private boolean placeholder;
    
    /**
     * Returns the ClassNode this ClassNode is redirecting to.
     */
    protected ClassNode redirect(){
        if (redirect==null) return this;
        return redirect.redirect();
    }
    
    /**
     * Sets this instance as proxy for the given ClassNode. 
     * @param cn the class to redirect to. If set to null the redirect will be removed
     */
    public void setRedirect(ClassNode cn) {
        if (isPrimaryNode) throw new GroovyBugError("tried to set a redirect for a primary ClassNode ("+getName()+"->"+cn.getName()+").");
        if (cn!=null) cn = cn.redirect();
        if (cn==this) return;
        redirect = cn;
    }
    
    /**
     * Returns a ClassNode representing an array of the class
     * represented by this ClassNode
     */
    public ClassNode makeArray() {
        if (redirect!=null) return redirect().makeArray();
        ClassNode cn;
        if (clazz!=null) {
            Class ret = Array.newInstance(clazz,0).getClass();
            // don't use the ClassHelper here!
            cn = new ClassNode(ret,this);
        } else {
            cn = new ClassNode(this);
        }
        return cn;
    }
    
    /**
     * Returns if this instance is a primary ClassNode
     */
    public boolean isPrimaryClassNode(){
    	return redirect().isPrimaryNode || (componentType!= null && componentType.isPrimaryClassNode());
    }
    
    /**
     * Constructor used by makeArray() if no real class is available
     */
    private ClassNode(ClassNode componentType) {
        this(componentType.getName()+"[]", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
        this.componentType = componentType.redirect();
        isPrimaryNode=false;
    }
    
    /**
     * Constructor used by makeArray() if a real class is available
     */
    private ClassNode(Class c, ClassNode componentType) {
        this(c);
        this.componentType = componentType;
        isPrimaryNode=false;
    }
    
    /**
     * Creates a ClassNode from a real class. The resulting 
     * ClassNode will be no primary ClassNode.
     */
    public ClassNode(Class c) {
        this(c.getName(), c.getModifiers(), null, null ,MixinNode.EMPTY_ARRAY);
        clazz=c;
        lazyInitDone=false;
        CompileUnit cu = getCompileUnit();
        if (cu!=null) cu.addClass(this);
        isPrimaryNode=false;
    }    
    
    /**
     * The complete class structure will be initialized only when really
     * needed to avoid having too much objects during compilation
     */
    private void lazyClassInit() {       
        synchronized (lazyInitLock) {
            if (lazyInitDone) return;
            
            Field[] fields = clazz.getDeclaredFields();
            for (int i=0;i<fields.length;i++){
                addField(fields[i].getName(),fields[i].getModifiers(),this,null);
            }
            Method[] methods = clazz.getDeclaredMethods();
            for (int i=0;i<methods.length;i++){
                Method m = methods[i];
                MethodNode mn = new MethodNode(m.getName(), m.getModifiers(), ClassHelper.make(m.getReturnType()), createParameters(m.getParameterTypes()), ClassHelper.make(m.getExceptionTypes()), null);
                addMethod(mn);
            }
            Constructor[] constructors = clazz.getDeclaredConstructors();
            for (int i=0;i<constructors.length;i++){
                Constructor ctor = constructors[i];
                addConstructor(ctor.getModifiers(),createParameters(ctor.getParameterTypes()),ClassHelper.make(ctor.getExceptionTypes()),null);
            }
            Class sc = clazz.getSuperclass();
            if (sc!=null) superClass = ClassHelper.make(sc);
            buildInterfaceTypes(clazz);       
            lazyInitDone=true;
        }
    }
    
    private void buildInterfaceTypes(Class c) {
        Class[] interfaces = c.getInterfaces();
        ClassNode[] ret = new ClassNode[interfaces.length];
        for (int i=0;i<interfaces.length;i++){
            ret[i] = ClassHelper.make(interfaces[i]);
        }
        this.interfaces = ret;
    }
    
    
    // added to track the enclosing method for local inner classes
    private MethodNode enclosingMethod = null;

    public MethodNode getEnclosingMethod() {
        return redirect().enclosingMethod;
    }

    public void setEnclosingMethod(MethodNode enclosingMethod) {
        redirect().enclosingMethod = enclosingMethod;
    }


    /**
     * @param name       is the full name of the class
     * @param modifiers  the modifiers,
     * @param superClass the base class name - use "java.lang.Object" if no direct
     *                   base class
     * @see org.objectweb.asm.Opcodes
     */
    public ClassNode(String name, int modifiers, ClassNode superClass) {
        this(name, modifiers, superClass, EMPTY_ARRAY, MixinNode.EMPTY_ARRAY);
    }

    /**
     * @param name       is the full name of the class
     * @param modifiers  the modifiers,
     * @param superClass the base class name - use "java.lang.Object" if no direct
     *                   base class
     * @see org.objectweb.asm.Opcodes
     */
    public ClassNode(String name, int modifiers, ClassNode superClass, ClassNode[] interfaces, MixinNode[] mixins) {
        this.name = name;
        this.modifiers = modifiers;
        this.superClass = superClass;
        this.interfaces = interfaces;
        this.mixins = mixins;
        isPrimaryNode = true;
        if (superClass!=null) {
            usesGenerics = superClass.isUsingGenerics();
        }
        if (!usesGenerics && interfaces!=null) {
            for (int i = 0; i < interfaces.length; i++) {
                usesGenerics = usesGenerics || interfaces[i].isUsingGenerics();
            }
        }
    }

    
    /**
     * Sets the superclass of this ClassNode
     */
    public void setSuperClass(ClassNode superClass) {
        redirect().superClass = superClass;
    }

    /**
     * Returns a list containing FieldNode objects for
     * each field in the class represented by this ClassNode
     */
    public List getFields() {
        if (!lazyInitDone) {
            lazyClassInit();
        }
        if (redirect!=null) return redirect().getFields();
        return fields;
    }

    /**
     * Returns an array of ClassNodes representing the
     * interfaces the class implements
     */
    public ClassNode[] getInterfaces() {
        if (!lazyInitDone) {
            lazyClassInit();
        }
        if (redirect!=null) return redirect().getInterfaces();
        return interfaces;
    }

    public MixinNode[] getMixins() {
        return redirect().mixins;
    }

    /**
     * Returns a list containing MethodNode objects for
     * each method in the class represented by this ClassNode
     */    
    public List getMethods() {
        if (!lazyInitDone) {
            lazyClassInit();
        }
        if (redirect!=null) return redirect().getMethods();
        return methods;
    }

    /**
     * Returns a list containing MethodNode objects for
     * each abstract method in the class represented by 
     * this ClassNode
     */   
    public List getAbstractMethods() {
        
        HashSet abstractNodes = new HashSet();
        // let us collect the abstract super classes and stop at the
        // first non abstract super class. If such a class still 
        // contains abstract methods, then loading that class will fail.
        // No need to be extra carefull here for that.
        ClassNode parent = this.redirect();
        do {
            abstractNodes.add(parent);
            ClassNode[] interfaces = parent.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
                abstractNodes.add(interfaces[i].redirect());
            }
            parent = parent.getSuperClass().redirect();
        } while (parent!=null && ((parent.getModifiers() & Opcodes.ACC_ABSTRACT) != 0));
        
        List result = new ArrayList();
        for (Iterator methIt = getAllDeclaredMethods().iterator(); methIt.hasNext();) {
            MethodNode method = (MethodNode) methIt.next();
            // add only abstract methods from abtract classes that
            // are not overwritten
            if ( abstractNodes.contains(method.getDeclaringClass().redirect()) && 
                 (method.getModifiers() & Opcodes.ACC_ABSTRACT) != 0
               ) {
                result.add(method);
            }
        }
        if (result.isEmpty()) {
            return null;
        }
        else {
            return result;
        }
    }

    public List getAllDeclaredMethods() {
        return new ArrayList(getDeclaredMethodsMap().values());
    }


    protected Map getDeclaredMethodsMap() {
        // Start off with the methods from the superclass.
        ClassNode parent = getSuperClass();
        Map result = null;
        if (parent != null) {
            result = parent.getDeclaredMethodsMap();
        }
        else {
            result = new HashMap();
        }

        // add in unimplemented abstract methods from the interfaces
        ClassNode[] interfaces = getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            ClassNode iface = interfaces[i];
            Map ifaceMethodsMap = iface.getDeclaredMethodsMap();
            for (Iterator iter = ifaceMethodsMap.keySet().iterator(); iter.hasNext();) {
                String methSig = (String) iter.next();
                if (!result.containsKey(methSig)) {
                    MethodNode methNode = (MethodNode) ifaceMethodsMap.get(methSig);
                    result.put(methSig, methNode);
                }
            }
        }

        // And add in the methods implemented in this class.
        for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
            MethodNode method = (MethodNode) iter.next();
            String sig = method.getTypeDescriptor();
            result.put(sig, method);
        }
        return result;
    }

    public String getName() {
        return redirect().name;
    }
    
    public String setName(String name) {
        return redirect().name=name;
    }

    public int getModifiers() {
        return redirect().modifiers;
    }

    public List getProperties() {
        return redirect().properties;
    }

    public List getDeclaredConstructors() {
        if (!lazyInitDone) {
            lazyClassInit();
        }
        return redirect().constructors;
    }

    public ModuleNode getModule() {
        return redirect().module;
    }

    public void setModule(ModuleNode module) {
        redirect().module = module;
        if (module != null) {
            redirect().compileUnit = module.getUnit();
        }
    }

    public void addField(FieldNode node) {
        node.setDeclaringClass(redirect());
        node.setOwner(redirect());
        redirect().fields.add(node);
        redirect().fieldIndex.put(node.getName(), node);
    }

    public void addProperty(PropertyNode node) {
        node.setDeclaringClass(redirect());
        FieldNode field = node.getField();
        addField(field);

        redirect().properties.add(node);
    }

    public PropertyNode addProperty(String name,
                                    int modifiers,
                                    ClassNode type,
                                    Expression initialValueExpression,
                                    Statement getterBlock,
                                    Statement setterBlock) {
    	for (Iterator iter = getProperties().iterator(); iter.hasNext();) {
            PropertyNode pn = (PropertyNode) iter.next();
            if (pn.getName().equals(name)) return pn;
        }
        PropertyNode node =
                new PropertyNode(name, modifiers, type, redirect(), initialValueExpression, getterBlock, setterBlock);
        addProperty(node);
        return node;
    }

    public void addConstructor(ConstructorNode node) {
        node.setDeclaringClass(this);
        redirect().constructors.add(node);
    }

    public ConstructorNode addConstructor(int modifiers, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
        ConstructorNode node = new ConstructorNode(modifiers, parameters, exceptions, code);
        addConstructor(node);
        return node;
    }

    public void addMethod(MethodNode node) {
        node.setDeclaringClass(this);
        redirect().methods.add(node);
    }

    /**
     * IF a method with the given name and parameters is already defined then it is returned
     * otherwise the given method is added to this node. This method is useful for
     * default method adding like getProperty() or invokeMethod() where there may already
     * be a method defined in a class and  so the default implementations should not be added
     * if already present.
     */
    public MethodNode addMethod(String name,
                                int modifiers,
                                ClassNode returnType,
                                Parameter[] parameters,
                                ClassNode[] exceptions,
                                Statement code) {
        MethodNode other = getDeclaredMethod(name, parameters);
        // lets not add duplicate methods
        if (other != null) {
            return other;
        }
        MethodNode node = new MethodNode(name, modifiers, returnType, parameters, exceptions, code);
        addMethod(node);
        return node;
    }

    /**
     * Adds a synthetic method as part of the compilation process
     */
    public MethodNode addSyntheticMethod(String name,
                                         int modifiers,
                                         ClassNode returnType,
                                         Parameter[] parameters,
                                         ClassNode[] exceptions,
                                         Statement code) {
        MethodNode answer = addMethod(name, modifiers, returnType, parameters, exceptions, code);
        answer.setSynthetic(true);
        return answer;
    }

    public FieldNode addField(String name, int modifiers, ClassNode type, Expression initialValue) {
        FieldNode node = new FieldNode(name, modifiers, type, redirect(), initialValue);
        addField(node);
        return node;
    }

    public void addInterface(ClassNode type) {
        // lets check if it already implements an interface
        boolean skip = false;
        ClassNode[] interfaces = redirect().interfaces;
        for (int i = 0; i < interfaces.length; i++) {
            if (type.equals(interfaces[i])) {
                skip = true;
            }
        }
        if (!skip) {
            ClassNode[] newInterfaces = new ClassNode[interfaces.length + 1];
            System.arraycopy(interfaces, 0, newInterfaces, 0, interfaces.length);
            newInterfaces[interfaces.length] = type;
            redirect().interfaces = newInterfaces;
        }
    }
    
    public boolean equals(Object o) {
        if (redirect!=null) return redirect().equals(o);
        ClassNode cn = (ClassNode) o;        
        return (cn.getName().equals(getName()));
    }

    public void addMixin(MixinNode mixin) {
        // lets check if it already uses a mixin
        MixinNode[] mixins = redirect().mixins;
        boolean skip = false;
        for (int i = 0; i < mixins.length; i++) {
            if (mixin.equals(mixins[i])) {
                skip = true;
            }
        }
        if (!skip) {
            MixinNode[] newMixins = new MixinNode[mixins.length + 1];
            System.arraycopy(mixins, 0, newMixins, 0, mixins.length);
            newMixins[mixins.length] = mixin;
            redirect().mixins = newMixins;
        }
    }

    public FieldNode getField(String name) {
        return (FieldNode) redirect().fieldIndex.get(name);
    }

    /**
     * @return the field node on the outer class or null if this is not an
     *         inner class
     */
    public FieldNode getOuterField(String name) {
        return null;
    }

    /**
     * Helper method to avoid casting to inner class
     */
    public ClassNode getOuterClass() {
        return null;
    }
    
    public void addObjectInitializerStatements(Statement statements) {
        objectInitializers.add(statements);
    }
    
    public List getObjectInitializerStatements() {
        return objectInitializers;
    }

    public void addStaticInitializerStatements(List staticStatements, boolean fieldInit) {
        MethodNode method = null;
        List declaredMethods = getDeclaredMethods("<clinit>");
        if (declaredMethods.isEmpty()) {
            method =
                    addMethod("<clinit>", ACC_STATIC, ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BlockStatement());
            method.setSynthetic(true);
        }
        else {
            method = (MethodNode) declaredMethods.get(0);
        }
        BlockStatement block = null;
        Statement statement = method.getCode();
        if (statement == null) {
            block = new BlockStatement();
        }
        else if (statement instanceof BlockStatement) {
            block = (BlockStatement) statement;
        }
        else {
            block = new BlockStatement();
            block.addStatement(statement);
        }
        
        // while anything inside a static initializer block is appended 
        // we don't want to append in the case we have a initialization
        // expression of a static field. In that case we want to add
        // before the other statements
        if (!fieldInit) {
            block.addStatements(staticStatements);
        } else {
            List blockStatements = block.getStatements();
            staticStatements.addAll(blockStatements);
            blockStatements.clear();
            blockStatements.addAll(staticStatements);
        }
    }

    /**
     * @return a list of methods which match the given name
     */
    public List getDeclaredMethods(String name) {
        List answer = new ArrayList();
        for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
            MethodNode method = (MethodNode) iter.next();
            if (name.equals(method.getName())) {
                answer.add(method);
            }
        }
        return answer;
    }

    /**
     * @return a list of methods which match the given name
     */
    public List getMethods(String name) {
        List answer = new ArrayList();
        ClassNode node = this;
        do {
            for (Iterator iter = node.getMethods().iterator(); iter.hasNext();) {
                MethodNode method = (MethodNode) iter.next();
                if (name.equals(method.getName())) {
                    answer.add(method);
                }
            }
            node = node.getSuperClass();
        }
        while (node != null);
        return answer;
    }

    /**
     * @return the method matching the given name and parameters or null
     */
    public MethodNode getDeclaredMethod(String name, Parameter[] parameters) {
        for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
            MethodNode method = (MethodNode) iter.next();
            if (name.equals(method.getName()) && parametersEqual(method.getParameters(), parameters)) {
                return method;
            }
        }
        return null;
    }

    /**
     * @return true if this node is derived from the given class node
     */
    public boolean isDerivedFrom(ClassNode type) {
        ClassNode node = this;
        while (node != null) {
            if (type.equals(node)) {
                return true;
            }
            node = node.getSuperClass();
        }
        return false;
    }

    /**
     * @return true if this class is derived from a groovy object
     *         i.e. it implements GroovyObject
     */
    public boolean isDerivedFromGroovyObject() {
        return implementsInterface(GroovyObject.class.getName());
    }

    /**
     * @param name the fully qualified name of the interface
     * @return true if this class or any base class implements the given interface
     */
    public boolean implementsInterface(String name) {
        ClassNode node = redirect();
        do {
            if (node.declaresInterface(name)) {
                return true;
            }
            node = node.getSuperClass();
        }
        while (node != null);
        return false;
    }

    /**
     * @param name the fully qualified name of the interface
     * @return true if this class declares that it implements the given interface
     */
    public boolean declaresInterface(String name) {
        ClassNode[] interfaces = redirect().getInterfaces();
        int size = interfaces.length;
        for (int i = 0; i < size; i++) {
            if (interfaces[i].getName().equals(name)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return the ClassNode of the super class of this type
     */
    public ClassNode getSuperClass() {
        if (!lazyInitDone && !isResolved()) {
            throw new GroovyBugError("Classnode#getSuperClass for "+getName()+" called before class resolving");
        }
        return redirect().getUnresolvedSuperClass();
    }
    
    public ClassNode getUnresolvedSuperClass() {
        return getUnresolvedSuperClass(true);
    }

    public ClassNode getUnresolvedSuperClass(boolean useRedirect) {
        if (!useRedirect) return superClass;
        if (!lazyInitDone) {
            lazyClassInit();
        }
        return redirect().superClass;
    }
    
    /**
     * Factory method to create a new MethodNode via reflection
     */
    protected MethodNode createMethodNode(Method method) {
        Parameter[] parameters = createParameters(method.getParameterTypes());
        return new MethodNode(method.getName(), method.getModifiers(), ClassHelper.make(method.getReturnType()), parameters, ClassHelper.make(method.getExceptionTypes()), EmptyStatement.INSTANCE);
    }

    /**
     * @param types
     */
    protected Parameter[] createParameters(Class[] types) {
        Parameter[] parameters = Parameter.EMPTY_ARRAY;
        int size = types.length;
        if (size > 0) {
            parameters = new Parameter[size];
            for (int i = 0; i < size; i++) {
                parameters[i] = createParameter(types[i], i);
            }
        }
        return parameters;
    }

    protected Parameter createParameter(Class parameterType, int idx) {
        return new Parameter(ClassHelper.make(parameterType), "param" + idx);
    }

    public CompileUnit getCompileUnit() {
        if (redirect!=null) return redirect().getCompileUnit();
        if (compileUnit == null && module != null) {
            compileUnit = module.getUnit();
        }
        return compileUnit;
    }
    
    protected void setCompileUnit(CompileUnit cu) {
        if (redirect!=null) redirect().setCompileUnit(cu);
        if (compileUnit!= null) compileUnit = cu;
    }

    /**
     * @return true if the two arrays are of the same size and have the same contents
     */
    protected boolean parametersEqual(Parameter[] a, Parameter[] b) {
        if (a.length == b.length) {
            boolean answer = true;
            for (int i = 0; i < a.length; i++) {
                if (!a[i].getType().equals(b[i].getType())) {
                    answer = false;
                    break;
                }
            }
            return answer;
        }
        return false;
    }

    /**
     * @return the package name of this class
     */
    public String getPackageName() {
        int idx = getName().lastIndexOf('.');
        if (idx > 0) {
            return getName().substring(0, idx);
        }
        return null;
    }

    public String getNameWithoutPackage() {
        int idx = getName().lastIndexOf('.');
        if (idx > 0) {
            return getName().substring(idx + 1);
        }
        return getName();
    }

    public void visitContents(GroovyClassVisitor visitor) {
        
        // now lets visit the contents of the class
        for (Iterator iter = getProperties().iterator(); iter.hasNext();) {
            PropertyNode pn = (PropertyNode) iter.next();
            visitor.visitProperty(pn);
        }

        for (Iterator iter = getFields().iterator(); iter.hasNext();) {
            FieldNode fn = (FieldNode) iter.next();
            visitor.visitField(fn);
        }

        for (Iterator iter = getDeclaredConstructors().iterator(); iter.hasNext();) {
            ConstructorNode cn = (ConstructorNode) iter.next();
            visitor.visitConstructor(cn);
        }

        for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
            MethodNode mn = (MethodNode) iter.next();
            visitor.visitMethod(mn);
        }
    }

    public MethodNode getGetterMethod(String getterName) {
        for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
            MethodNode method = (MethodNode) iter.next();
            if (getterName.equals(method.getName())
                    && ClassHelper.VOID_TYPE!=method.getReturnType()
                    && method.getParameters().length == 0) {
                return method;
            }
        }
        return null;
    }

    public MethodNode getSetterMethod(String getterName) {
        for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
            MethodNode method = (MethodNode) iter.next();
            if (getterName.equals(method.getName())
                    && ClassHelper.VOID_TYPE==method.getReturnType()
                    && method.getParameters().length == 1) {
                return method;
            }
        }
        return null;
    }

    /**
     * Is this class delcared in a static method (such as a closure / inner class declared in a static method)
     */
    public boolean isStaticClass() {
        return redirect().staticClass;
    }

    public void setStaticClass(boolean staticClass) {
        redirect().staticClass = staticClass;
    }

    /**
     * @return Returns true if this inner class or closure was declared inside a script body
     */
    public boolean isScriptBody() {
        return redirect().scriptBody;
    }

    public void setScriptBody(boolean scriptBody) {
        redirect().scriptBody = scriptBody;
    }

    public boolean isScript() {
        return redirect().script || isDerivedFrom(ClassHelper.SCRIPT_TYPE);
    }

    public void setScript(boolean script) {
        redirect().script = script;
    }

    public String toString() {
        String ret = getName(); 
        if (genericsTypes!=null) {
            ret += " <";
            for (int i = 0; i < genericsTypes.length; i++) {
                if (i!=0) ret+=", ";
                ret += genericsTypes[i];
            }
            ret += ">";
        }
        if (redirect!=null) {
            ret += " -> "+redirect().toString();
        }
        return ret;
    }

    /**
     * Returns true if the given method has a possibly matching method with the given name and arguments
     */
    public boolean hasPossibleMethod(String name, Expression arguments) {
        int count = 0;

        if (arguments instanceof TupleExpression) {
            TupleExpression tuple = (TupleExpression) arguments;
            // TODO this won't strictly be true when using list expansion in argument calls
            count = tuple.getExpressions().size();
        }
        ClassNode node = this;
        do {
            for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
                MethodNode method = (MethodNode) iter.next();
                if (name.equals(method.getName()) && method.getParameters().length == count) {
                    return true;
                }
            }
            node = node.getSuperClass();
        }
        while (node != null);
        return false;
    }
    
    /**
     * Returns true if the given method has a possibly matching static method with the given name and arguments
     */
    public boolean hasPossibleStaticMethod(String name, Expression arguments) {
        int count = 0;

        if (arguments instanceof TupleExpression) {
            TupleExpression tuple = (TupleExpression) arguments;
            // TODO this won't strictly be true when using list expansion in argument calls
            count = tuple.getExpressions().size();
        }
        for (Iterator iter = getMethods().iterator(); iter.hasNext();) {
            MethodNode method = (MethodNode) iter.next();
            if (name.equals(method.getName()) && method.getParameters().length == count && method.isStatic()) {
                return true;
            }
            // handle varargs case
            if (name.equals(method.getName()) && method.isStatic() && method.getParameters().length > 0 &&
                    method.getParameters()[method.getParameters().length - 1].getType().getTypeClass() == Object[].class) {
                if (count >= method.getParameters().length - 1) return true;
            }
        }
        return false;
    }

    public boolean isInterface(){
        return (getModifiers() & Opcodes.ACC_INTERFACE) > 0; 
    }
    
    public boolean isResolved(){
        return redirect().clazz!=null || (componentType != null && componentType.isResolved());
    }
    
    public boolean isArray(){
        return componentType!=null;
    }
    
    public ClassNode getComponentType() {
        return componentType;
    }
    
    public Class getTypeClass(){
        Class c = redirect().clazz;
        if (c!=null) return c;
        ClassNode component = redirect().componentType;
        if (component!=null && component.isResolved()){
            ClassNode cn = component.makeArray();
            setRedirect(cn);
            return redirect().clazz;
        }
        throw new GroovyBugError("ClassNode#getTypeClass for "+getName()+" is called before the type class is set ");
    }
    
    public boolean hasPackageName(){
        return redirect().name.indexOf('.')>0;
    }

    /**
     * Marks if the current class uses annotations or not
     * @param flag
     */
    public void setAnnotated(boolean flag) {
        this.annotated = flag;
    }
    
    public boolean isAnnotated() {
        return this.annotated;
    }

    public GenericsType[] getGenericsTypes() {
        return genericsTypes;
    }

    public void setGenericsTypes(GenericsType[] genericsTypes) {
        usesGenerics = usesGenerics || genericsTypes!=null;
        this.genericsTypes = genericsTypes;
    }

    public void setGenericsPlaceHolder(boolean b) {
        usesGenerics = usesGenerics || b;
        placeholder = b;
    }
    
    public boolean isGenericsPlaceHolder() {
        return placeholder;
    }
    
    public boolean isUsingGenerics() {
        return usesGenerics;
    }
    
    public void setUsingGenerics(boolean b) {
        usesGenerics = b;
    }
    
}
