/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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 groovy.lang;

import org.apache.groovy.internal.util.UncheckedThrow;
import org.apache.groovy.util.BeanUtils;
import org.apache.groovy.util.SystemUtil;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.Phases;
import org.codehaus.groovy.reflection.CacheAccessControlException;
import org.codehaus.groovy.reflection.CachedClass;
import org.codehaus.groovy.reflection.CachedConstructor;
import org.codehaus.groovy.reflection.CachedField;
import org.codehaus.groovy.reflection.CachedMethod;
import org.codehaus.groovy.reflection.ClassInfo;
import org.codehaus.groovy.reflection.GeneratedMetaMethod;
import org.codehaus.groovy.reflection.ParameterTypes;
import org.codehaus.groovy.reflection.ReflectionCache;
import org.codehaus.groovy.reflection.android.AndroidSupport;
import org.codehaus.groovy.runtime.ArrayTypeUtils;
import org.codehaus.groovy.runtime.ConvertedClosure;
import org.codehaus.groovy.runtime.CurriedClosure;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.GroovyCategorySupport;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.codehaus.groovy.runtime.InvokerInvocationException;
import org.codehaus.groovy.runtime.MetaClassHelper;
import org.codehaus.groovy.runtime.MethodClosure;
import org.codehaus.groovy.runtime.callsite.AbstractCallSite;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.codehaus.groovy.runtime.callsite.ConstructorSite;
import org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite;
import org.codehaus.groovy.runtime.callsite.PogoMetaClassSite;
import org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite;
import org.codehaus.groovy.runtime.callsite.PojoMetaClassSite;
import org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite;
import org.codehaus.groovy.runtime.callsite.StaticMetaClassSite;
import org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite;
import org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod;
import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
import org.codehaus.groovy.runtime.metaclass.MetaMethodIndex;
import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty;
import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty;
import org.codehaus.groovy.runtime.metaclass.MethodSelectionException;
import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
import org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed;
import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod;
import org.codehaus.groovy.runtime.metaclass.MultipleSetterProperty;
import org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod;
import org.codehaus.groovy.runtime.metaclass.NewMetaMethod;
import org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod;
import org.codehaus.groovy.runtime.metaclass.TransformMetaMethod;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.codehaus.groovy.runtime.typehandling.NumberMathModificationInfo;
import org.codehaus.groovy.runtime.wrappers.Wrapper;
import org.codehaus.groovy.util.ComplexKeyHashMap;
import org.codehaus.groovy.util.FastArray;
import org.codehaus.groovy.util.SingleKeyHashMap;
import org.codehaus.groovy.vmplugin.VMPlugin;
import org.codehaus.groovy.vmplugin.VMPluginFactory;

import javax.annotation.Nullable;
import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static org.apache.groovy.util.Arrays.concat;
import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
import static org.codehaus.groovy.reflection.ReflectionCache.isAssignableFrom;

/**
 * Allows methods to be dynamically added to existing classes at runtime
 *
 * @see groovy.lang.MetaClass
 */
public class MetaClassImpl implements MetaClass, MutableMetaClass {

    public static final Object[] EMPTY_ARGUMENTS = {};

    protected static final String STATIC_METHOD_MISSING = "$static_methodMissing";
    protected static final String STATIC_PROPERTY_MISSING = "$static_propertyMissing";
    protected static final String METHOD_MISSING = "methodMissing";
    protected static final String PROPERTY_MISSING = "propertyMissing";
    protected static final String INVOKE_METHOD_METHOD = "invokeMethod";

    private static final String CLOSURE_CALL_METHOD = "call";
    private static final String CLOSURE_DO_CALL_METHOD = "doCall";
    private static final String GET_PROPERTY_METHOD = "getProperty";
    private static final String SET_PROPERTY_METHOD = "setProperty";
    private static final Class[] METHOD_MISSING_ARGS = new Class[]{String.class, Object.class};
    private static final Class[] GETTER_MISSING_ARGS = new Class[]{String.class};
    private static final Class[] SETTER_MISSING_ARGS = METHOD_MISSING_ARGS;
    private static final MetaMethod AMBIGUOUS_LISTENER_METHOD = new DummyMetaMethod();
    private static final Comparator<CachedClass> CACHED_CLASS_NAME_COMPARATOR = Comparator.comparing(CachedClass::getName);
    private static final boolean PERMISSIVE_PROPERTY_ACCESS = SystemUtil.getBooleanSafe("groovy.permissive.property.access");
    private static final VMPlugin VM_PLUGIN = VMPluginFactory.getPlugin();

    protected final Class theClass;
    protected final CachedClass theCachedClass;
    protected final boolean isGroovyObject;
    protected final boolean isMap;
    protected final MetaMethodIndex metaMethodIndex;

    private final Index classPropertyIndex = new MethodIndex();
    private final SingleKeyHashMap staticPropertyIndex = new SingleKeyHashMap();
    private final Map<String, MetaMethod> listeners = new HashMap<>();
    private final List<MetaMethod> allMethods = new ArrayList<>();
    // we only need one of these that can be reused over and over.
    private final MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
    private final Index classPropertyIndexForSuper = new MethodIndex();
    private final Set<MetaMethod> newGroovyMethodsSet = new HashSet<>();
    private final MetaMethod[] myNewMetaMethods;
    private final MetaMethod[] additionalMetaMethods;

    protected MetaMethod getPropertyMethod;
    protected MetaMethod invokeMethodMethod;
    protected MetaMethod setPropertyMethod;
    protected MetaClassRegistry registry;
    private ClassNode classNode;
    private FastArray constructors;
    private volatile boolean initialized;
    private MetaMethod genericGetMethod;
    private MetaMethod genericSetMethod;
    private MetaMethod propertyMissingGet;
    private MetaMethod propertyMissingSet;
    private MetaMethod methodMissing;
    private MetaMethodIndex.Header mainClassMethodHeader;
    private boolean permissivePropertyAccess = PERMISSIVE_PROPERTY_ACCESS;

    /**
     * Constructor
     *
     * @param theClass The class this is the metaclass dor
     * @param add      The methods for this class
     */
    public MetaClassImpl(final Class theClass, MetaMethod[] add) {
        this.theClass = theClass;
        theCachedClass = ReflectionCache.getCachedClass(theClass);
        this.isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
        this.isMap = Map.class.isAssignableFrom(theClass);
        this.registry = GroovySystem.getMetaClassRegistry();
        metaMethodIndex = new MetaMethodIndex(theCachedClass);
        final MetaMethod[] metaMethods = theCachedClass.getNewMetaMethods();
        if (add != null && add.length != 0) {
            myNewMetaMethods = concat(metaMethods, add);
            additionalMetaMethods = metaMethods;
        } else {
            myNewMetaMethods = metaMethods;
            additionalMetaMethods = MetaMethod.EMPTY_ARRAY;
        }
    }

    /**
     * Constructor that sets the methods to null
     *
     * @param theClass The class this is the metaclass dor
     */
    public MetaClassImpl(final Class theClass) {
        this(theClass, null);
    }

    /**
     * Constructor with registry
     *
     * @param registry The metaclass registry for this MetaClass
     * @param theClass The class
     * @param add      The methods
     */
    public MetaClassImpl(MetaClassRegistry registry, final Class theClass, MetaMethod[] add) {
        this(theClass, add);
        this.registry = registry;
        this.constructors = new FastArray(theCachedClass.getConstructors());
    }

    /**
     * Constructor with registry setting methods to null
     *
     * @param registry The metaclass registry for this MetaClass
     * @param theClass The class
     */
    public MetaClassImpl(MetaClassRegistry registry, final Class theClass) {
        this(registry, theClass, null);
    }

    /**
     * Returns the cached class for this metaclass
     *
     * @return The cached class.
     */
    public final CachedClass getTheCachedClass() {
        return theCachedClass;
    }

    /**
     * Returns the registry for this metaclass
     *
     * @return The resgistry
     */
    public MetaClassRegistry getRegistry() {
        return registry;
    }

    /**
     * @see MetaObjectProtocol#respondsTo(Object, String, Object[])
     */
    public List respondsTo(Object obj, String name, Object[] argTypes) {
        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
        MetaMethod m = getMetaMethod(name, classes);
        if (m != null) {
            return Collections.singletonList(m);
        }
        return Collections.emptyList();
    }

    /**
     * @see MetaObjectProtocol#respondsTo(Object, String)
     */
    public List respondsTo(final Object obj, final String name) {
        final Object o = getMethods(getTheClass(), name, false);
        if (o instanceof FastArray) {
            return ((FastArray) o).toList();
        }
        return Collections.singletonList(o);
    }

    /**
     * @see MetaObjectProtocol#hasProperty(Object, String)
     */
    public MetaProperty hasProperty(Object obj, String name) {
        return getMetaProperty(name);
    }

    /**
     * @see MetaObjectProtocol#getMetaProperty(String)
     */
    public MetaProperty getMetaProperty(String name) {
        MetaProperty metaProperty = null;

        SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
        metaProperty = (MetaProperty) propertyMap.get(name);
        if (metaProperty == null) {
            metaProperty = (MetaProperty) staticPropertyIndex.get(name);
            if (metaProperty == null) {
                propertyMap = classPropertyIndexForSuper.getNotNull(theCachedClass);
                metaProperty = (MetaProperty) propertyMap.get(name);
                if (metaProperty == null) {
                    CachedClass superClass = theCachedClass;
                    while (superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
                        MetaBeanProperty property = findPropertyInClassHierarchy(name, superClass);
                        if (property != null) {
                            onSuperPropertyFoundInHierarchy(property);
                            metaProperty = property;
                            break;
                        }
                        superClass = superClass.getCachedSuperClass();
                    }
                }
            }
        }

        return metaProperty;
    }

    /**
     * @see MetaObjectProtocol#getStaticMetaMethod(String, Object[])
     */
    public MetaMethod getStaticMetaMethod(String name, Object[] argTypes) {
        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
        return pickStaticMethod(name, classes);
    }

    /**
     * @see MetaObjectProtocol#getMetaMethod(String, Object[])
     */
    public MetaMethod getMetaMethod(String name, Object[] argTypes) {
        Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
        return pickMethod(name, classes);
    }

    /**
     * Returns the class this object this is the metaclass of.
     *
     * @return The class contained by this metaclass
     */
    public Class getTheClass() {
        return this.theClass;
    }

    /**
     * Return wether the class represented by this metaclass instance is an instance of the GroovyObject class
     *
     * @return true if this is a groovy class, false otherwise.
     */
    public boolean isGroovyObject() {
        return isGroovyObject;
    }

    /**
     * Fills the method index
     */
    private void fillMethodIndex() {
        mainClassMethodHeader = metaMethodIndex.getHeader(theClass);
        LinkedList<CachedClass> superClasses = getSuperClasses();
        CachedClass firstGroovySuper = calcFirstGroovySuperClass(superClasses);

        Set<CachedClass> interfaces = theCachedClass.getInterfaces();
        addInterfaceMethods(interfaces);

        populateMethods(superClasses, firstGroovySuper);

        inheritInterfaceNewMetaMethods(interfaces);
        if (isGroovyObject) {
            metaMethodIndex.copyMethodsToSuper();

            connectMultimethods(superClasses, firstGroovySuper);
            removeMultimethodsOverloadedWithPrivateMethods();

            replaceWithMOPCalls(theCachedClass.mopMethods);
        }
    }

    private void populateMethods(LinkedList<CachedClass> superClasses, CachedClass firstGroovySuper) {

        MetaMethodIndex.Header header = metaMethodIndex.getHeader(firstGroovySuper.getTheClass());
        CachedClass c;
        Iterator<CachedClass> iter = superClasses.iterator();
        while (iter.hasNext()) {
            c = iter.next();

            CachedMethod[] cachedMethods = c.getMethods();
            for (CachedMethod metaMethod : cachedMethods) {
                addToAllMethodsIfPublic(metaMethod);
                if (!metaMethod.isPrivate() || c == firstGroovySuper)
                    addMetaMethodToIndex(metaMethod, header);
            }

            MetaMethod[] cachedMethods1 = getNewMetaMethods(c);
            for (final MetaMethod method : cachedMethods1) {
                if (!newGroovyMethodsSet.contains(method)) {
                    newGroovyMethodsSet.add(method);
                    addMetaMethodToIndex(method, header);
                }
            }

            if (c == firstGroovySuper)
                break;
        }

        MetaMethodIndex.Header last = header;
        while (iter.hasNext()) {
            c = iter.next();
            header = metaMethodIndex.getHeader(c.getTheClass());

            if (last != null) {
                metaMethodIndex.copyNonPrivateMethods(last, header);
            }
            last = header;

            for (CachedMethod metaMethod : c.getMethods()) {
                addToAllMethodsIfPublic(metaMethod);
                addMetaMethodToIndex(metaMethod, header);
            }

            for (final MetaMethod method : getNewMetaMethods(c)) {
                if (method.getName().equals("<init>") && !method.getDeclaringClass().equals(theCachedClass)) continue;
                if (!newGroovyMethodsSet.contains(method)) {
                    newGroovyMethodsSet.add(method);
                    addMetaMethodToIndex(method, header);
                }
            }
        }
    }

    private MetaMethod[] getNewMetaMethods(CachedClass c) {
        if (theCachedClass != c)
            return c.getNewMetaMethods();

        return myNewMetaMethods;
    }

    private void addInterfaceMethods(Set<CachedClass> interfaces) {
        MetaMethodIndex.Header header = metaMethodIndex.getHeader(theClass);
        for (CachedClass c : interfaces) {
            final CachedMethod[] m = c.getMethods();
            for (int i = 0; i != m.length; ++i) {
                MetaMethod method = m[i];
                addMetaMethodToIndex(method, header);
            }
        }
    }

    protected LinkedList<CachedClass> getSuperClasses() {
        LinkedList<CachedClass> superClasses = new LinkedList<>();

        if (theClass.isInterface()) {
            superClasses.addFirst(ReflectionCache.OBJECT_CLASS);
        } else {
            for (CachedClass c = theCachedClass; c != null; c = c.getCachedSuperClass()) {
                superClasses.addFirst(c);
            }
            if (theCachedClass.isArray && theClass != Object[].class && !theClass.getComponentType().isPrimitive()) {
                superClasses.addFirst(ReflectionCache.OBJECT_ARRAY_CLASS);
            }
        }
        return superClasses;
    }

    private void removeMultimethodsOverloadedWithPrivateMethods() {
        MethodIndexAction mia = new MethodIndexAction() {
            public boolean skipClass(Class clazz) {
                return clazz == theClass;
            }

            public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
                if (e.methods == null)
                    return;

                boolean hasPrivate = false;
                if (e.methods instanceof FastArray) {
                    FastArray methods = (FastArray) e.methods;
                    final int len = methods.size();
                    final Object[] data = methods.getArray();
                    for (int i = 0; i != len; ++i) {
                        MetaMethod method = (MetaMethod) data[i];
                        if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
                            hasPrivate = true;
                            break;
                        }
                    }
                } else {
                    MetaMethod method = (MetaMethod) e.methods;
                    if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
                        hasPrivate = true;
                    }
                }

                if (!hasPrivate) return;

                // We have private methods for that name, so remove the
                // multimethods. That is the same as in our index for
                // super, so just copy the list from there. It is not
                // possible to use a pointer here, because the methods
                // in the index for super are replaced later by MOP
                // methods like super$5$foo
                final Object o = e.methodsForSuper;
                if (o instanceof FastArray) {
                    e.methods = ((FastArray) o).copy();
                } else {
                    e.methods = o;
                }
            }
        };
        mia.iterate();
    }

    private void replaceWithMOPCalls(final CachedMethod[] mopMethods) {
        // no MOP methods if not a child of GroovyObject
        if (!isGroovyObject) return;

        class MOPIter extends MethodIndexAction {
            boolean useThis;

            @Override
            public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
                if (useThis) {
                    if (e.methods == null)
                        return;

                    if (e.methods instanceof FastArray) {
                        FastArray methods = (FastArray) e.methods;
                        processFastArray(methods);
                    } else {
                        MetaMethod method = (MetaMethod) e.methods;
                        if (method instanceof NewMetaMethod)
                            return;
                        if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
                        String mopName = method.getMopName();
                        int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                        if (index >= 0) {
                            int matchingMethod = findMatchingMethod(method, mopName, index, mopMethods);
                            if (matchingMethod != -1) {
                                e.methods = mopMethods[matchingMethod];
                            }
                        }
                    }
                } else {
                    if (e.methodsForSuper == null)
                        return;

                    if (e.methodsForSuper instanceof FastArray) {
                        FastArray methods = (FastArray) e.methodsForSuper;
                        processFastArray(methods);
                    } else {
                        MetaMethod method = (MetaMethod) e.methodsForSuper;
                        if (method instanceof NewMetaMethod)
                            return;
                        if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
                        String mopName = method.getMopName();
                        // GROOVY-4922: Due to a numbering scheme change, we must find the super$X$method which exists
                        // with the highest number. If we don't, no method may be found, leading to a stack overflow
                        String[] decomposedMopName = decomposeMopName(mopName);
                        int distance = Integer.parseInt(decomposedMopName[1]);
                        while (distance > 0) {
                            String fixedMopName = decomposedMopName[0] + distance + decomposedMopName[2];
                            int index = Arrays.binarySearch(mopMethods, fixedMopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                            if (index >= 0) {
                                int matchingMethod = findMatchingMethod(method, fixedMopName, index, mopMethods);
                                if (matchingMethod != -1) {
                                    e.methodsForSuper = mopMethods[matchingMethod];
                                    distance = 0;
                                }
                            }
                            distance--;
                        }
                    }
                }
            }

            private String[] decomposeMopName(final String mopName) {
                int idx = mopName.indexOf('$');
                if (idx > 0) {
                    int eidx = mopName.indexOf('$', idx + 1);
                    if (eidx > 0) {
                        return new String[]{
                                mopName.substring(0, idx + 1),
                                mopName.substring(idx + 1, eidx),
                                mopName.substring(eidx)
                        };
                    }
                }
                return new String[]{"", "0", mopName};
            }

            private void processFastArray(FastArray methods) {
                final int len = methods.size();
                final Object[] data = methods.getArray();
                for (int i = 0; i != len; ++i) {
                    MetaMethod method = (MetaMethod) data[i];
                    if (method instanceof NewMetaMethod) continue;
                    boolean isPrivate = Modifier.isPrivate(method.getModifiers());
                    if (useThis ^ isPrivate) continue;
                    String mopName = method.getMopName();
                    int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                    if (index >= 0) {
                        int matchingMethod = findMatchingMethod(method, mopName, index, mopMethods);
                        if (matchingMethod != -1) {
                            methods.set(i, mopMethods[matchingMethod]);
                        }
                    }
                }
            }
        }
        MOPIter iter = new MOPIter();

        // replace all calls for super with the correct MOP method
        iter.useThis = false;
        iter.iterate();
        // replace all calls for this with the correct MOP method
        iter.useThis = true;
        iter.iterate();
    }

    private int findMatchingMethod(MetaMethod method, String mopName, int index, CachedMethod[] mopMethods) {
        int from = index;
        while (from > 0 && mopMethods[from - 1].getName().equals(mopName))
            from--;
        int to = index;
        while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(mopName))
            to++;

        return findMatchingMethod(mopMethods, from, to, method);
    }

    private void inheritInterfaceNewMetaMethods(Set<CachedClass> interfaces) {
        // add methods declared by DGM for interfaces
        for (CachedClass cls : interfaces) {
            MetaMethod[] methods = getNewMetaMethods(cls);
            for (MetaMethod method : methods) {
                boolean skip = false;
                // skip DGM methods on an interface if the class already has the method
                // but don't skip for GroovyObject-related methods as it breaks things :-(
                if (method instanceof GeneratedMetaMethod && !isAssignableFrom(GroovyObject.class, method.getDeclaringClass().getTheClass())) {
                    for (Method m : theClass.getMethods()) {
                        if (method.getName().equals(m.getName())
                                // below not true for DGM#push and also co-variant return scenarios
                                //&& method.getReturnType().equals(m.getReturnType())
                                && MetaMethod.equal(method.getParameterTypes(), m.getParameterTypes())) {
                            skip = true;
                            break;
                        }
                    }
                }
                if (!skip) {
                    newGroovyMethodsSet.add(method);
                    addMetaMethodToIndex(method, mainClassMethodHeader);
                }
            }
        }
    }

    private void connectMultimethods(List<CachedClass> superClasses, CachedClass firstGroovyClass) {
        superClasses = DefaultGroovyMethods.reverse(superClasses);
        MetaMethodIndex.Header last = null;
        for (final CachedClass c : superClasses) {
            MetaMethodIndex.Header methodIndex = metaMethodIndex.getHeader(c.getTheClass());
            // We don't copy DGM methods to superclasses' indexes
            // The reason we can do that is particular set of DGM methods in use,
            // if at some point we will define DGM method for some Groovy class or
            // for a class derived from such, we will need to revise this condition.
            // It saves us a lot of space and some noticeable time
            if (last != null) metaMethodIndex.copyNonPrivateNonNewMetaMethods(last, methodIndex);
            last = methodIndex;

            if (c == firstGroovyClass)
                break;
        }
    }

    private CachedClass calcFirstGroovySuperClass(Collection superClasses) {
        if (theCachedClass.isInterface)
            return ReflectionCache.OBJECT_CLASS;

        CachedClass firstGroovy = null;
        Iterator iter = superClasses.iterator();
        while (iter.hasNext()) {
            CachedClass c = (CachedClass) iter.next();
            if (GroovyObject.class.isAssignableFrom(c.getTheClass())) {
                firstGroovy = c;
                break;
            }
        }

        if (firstGroovy == null) {
            firstGroovy = theCachedClass;
        } else {
            if (firstGroovy.getTheClass() == GroovyObjectSupport.class && iter.hasNext()) {
                firstGroovy = (CachedClass) iter.next();
                if (firstGroovy.getTheClass() == Closure.class && iter.hasNext()) {
                    firstGroovy = (CachedClass) iter.next();
                }
            }
        }

        return GroovyObject.class.isAssignableFrom(firstGroovy.getTheClass()) ? firstGroovy.getCachedSuperClass() : firstGroovy;
    }

    /**
     * Gets all instance methods available on this class for the given name
     *
     * @return all the normal instance methods available on this class for the
     * given name
     */
    private Object getMethods(Class sender, String name, boolean isCallToSuper) {
        Object answer;

        final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
        if (entry == null) {
            answer = FastArray.EMPTY_LIST;
        } else if (isCallToSuper) {
            answer = entry.methodsForSuper;
        } else {
            answer = entry.methods;
        }

        if (answer == null) answer = FastArray.EMPTY_LIST;

        if (!isCallToSuper) {
            List used = GroovyCategorySupport.getCategoryMethods(name);
            if (used != null) {
                FastArray arr;
                if (answer instanceof MetaMethod) {
                    arr = new FastArray();
                    arr.add(answer);
                } else {
                    arr = ((FastArray) answer).copy();
                }
                for (Object o : used) {
                    MetaMethod element = (MetaMethod) o;
                    if (!element.getDeclaringClass().getTheClass().isAssignableFrom(sender))
                        continue;
                    filterMatchingMethodForCategory(arr, element);
                }
                answer = arr;
            }
        }
        return answer;
    }

    /**
     * Returns all the normal static methods on this class for the given name
     *
     * @return all the normal static methods available on this class for the
     * given name
     */
    private Object getStaticMethods(Class sender, String name) {
        final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
        if (entry == null)
            return FastArray.EMPTY_LIST;
        Object answer = entry.staticMethods;
        if (answer == null)
            return FastArray.EMPTY_LIST;
        return answer;
    }

    /**
     * Returns whether this MetaClassImpl has been modified. Since MetaClassImpl
     * is not designed for modification this method always returns false
     *
     * @return false
     */
    public boolean isModified() {
        return false;  // MetaClassImpl not designed for modification, just return false
    }

    /**
     * Adds an instance method to this metaclass.
     *
     * @param method The method to be added
     */
    public void addNewInstanceMethod(Method method) {
        final CachedMethod cachedMethod = CachedMethod.find(method);
        NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(cachedMethod);
        final CachedClass declaringClass = newMethod.getDeclaringClass();
        addNewInstanceMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
    }

    private void addNewInstanceMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
        if (!newGroovyMethodsSet.contains(newMethod)) {
            newGroovyMethodsSet.add(newMethod);
            addMetaMethodToIndex(newMethod, header);
        }
    }

    /**
     * Adds a static method to this metaclass.
     *
     * @param method The method to be added
     */
    public void addNewStaticMethod(Method method) {
        final CachedMethod cachedMethod = CachedMethod.find(method);
        NewStaticMetaMethod newMethod = new NewStaticMetaMethod(cachedMethod);
        final CachedClass declaringClass = newMethod.getDeclaringClass();
        addNewStaticMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
    }

    private void addNewStaticMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
        if (!newGroovyMethodsSet.contains(newMethod)) {
            newGroovyMethodsSet.add(newMethod);
            addMetaMethodToIndex(newMethod, header);
        }
    }

    /**
     * Invoke a method on the given object with the given arguments.
     *
     * @param object     The object the method should be invoked on.
     * @param methodName The name of the method to invoke.
     * @param arguments  The arguments to the invoked method as null, a Tuple, an array or a single argument of any type.
     * @return The result of the method invocation.
     */
    public Object invokeMethod(Object object, String methodName, Object arguments) {
        if (arguments == null) {
            return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
        }
        if (arguments instanceof Tuple) {
            Tuple tuple = (Tuple) arguments;
            return invokeMethod(object, methodName, tuple.toArray());
        }
        if (arguments instanceof Object[]) {
            return invokeMethod(object, methodName, (Object[]) arguments);
        }
        return invokeMethod(object, methodName, new Object[]{arguments});
    }

    /**
     * Invoke a missing method on the given object with the given arguments.
     *
     * @param instance   The object the method should be invoked on.
     * @param methodName The name of the method to invoke.
     * @param arguments  The arguments to the invoked method.
     * @return The result of the method invocation.
     */
    public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
        return invokeMissingMethod(instance, methodName, arguments, null, false);
    }

    /**
     * Invoke a missing property on the given object with the given arguments.
     *
     * @param instance      The object the method should be invoked on.
     * @param propertyName  The name of the property to invoke.
     * @param optionalValue The (optional) new value for the property
     * @param isGetter      Wether the method is a getter
     * @return The result of the method invocation.
     */
    public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
        Class theClass = instance instanceof Class ? (Class) instance : instance.getClass();
        CachedClass superClass = theCachedClass;
        while (superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
            final MetaBeanProperty property = findPropertyInClassHierarchy(propertyName, superClass);
            if (property != null) {
                onSuperPropertyFoundInHierarchy(property);
                if (!isGetter) {
                    property.setProperty(instance, optionalValue);
                    return null;
                }
                return property.getProperty(instance);
            }
            superClass = superClass.getCachedSuperClass();
        }
        // got here to property not found, look for getProperty or setProperty overrides
        if (isGetter) {
            final Class[] getPropertyArgs = {String.class};
            final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), GET_PROPERTY_METHOD, getPropertyArgs, this);
            if (method instanceof ClosureMetaMethod) {
                onGetPropertyFoundInHierarchy(method);
                return method.invoke(instance, new Object[]{propertyName});
            }
        } else {
            final Class[] setPropertyArgs = {String.class, Object.class};
            final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), SET_PROPERTY_METHOD, setPropertyArgs, this);
            if (method instanceof ClosureMetaMethod) {
                onSetPropertyFoundInHierarchy(method);
                return method.invoke(instance, new Object[]{propertyName, optionalValue});
            }
        }

        try {
            if (!(instance instanceof Class)) {
                if (isGetter) {
                    if (propertyMissingGet != null) {
                        return propertyMissingGet.invoke(instance, new Object[]{propertyName});
                    }
                } else {
                    if (propertyMissingSet != null) {
                        return propertyMissingSet.invoke(instance, new Object[]{propertyName, optionalValue});
                    }
                }
            }
        } catch (InvokerInvocationException iie) {
            boolean shouldHandle = isGetter && propertyMissingGet != null;
            if (!shouldHandle) shouldHandle = !isGetter && propertyMissingSet != null;
            if (shouldHandle && iie.getCause() instanceof MissingPropertyException) {
                throw (MissingPropertyException) iie.getCause();
            }
            throw iie;
        }

        if (instance instanceof Class && theClass != Class.class) {
            final MetaProperty metaProperty = InvokerHelper.getMetaClass(Class.class).hasProperty(instance, propertyName);
            if (metaProperty != null) {
                if (isGetter) {
                    return metaProperty.getProperty(instance);
                }
                metaProperty.setProperty(instance, optionalValue);
                return null;
            }
        }
        throw new MissingPropertyExceptionNoStack(propertyName, theClass);
    }

    private Object invokeMissingMethod(Object instance, String methodName, Object[] arguments, RuntimeException original, boolean isCallToSuper) {
        if (isCallToSuper) {
            MetaClass metaClass = InvokerHelper.getMetaClass(theClass.getSuperclass());
            return metaClass.invokeMissingMethod(instance, methodName, arguments);
        }

        Class instanceKlazz = instance.getClass();
        if (theClass != instanceKlazz && theClass.isAssignableFrom(instanceKlazz))
            instanceKlazz = theClass;

        Class[] argClasses = MetaClassHelper.castArgumentsToClassArray(arguments);

        MetaMethod method = findMixinMethod(methodName, argClasses);
        if (method != null) {
            onMixinMethodFound(method);
            return method.invoke(instance, arguments);
        }

        method = findMethodInClassHierarchy(instanceKlazz, methodName, argClasses, this);
        if (method != null) {
            onSuperMethodFoundInHierarchy(method);
            return method.invoke(instance, arguments);
        }

        // still not method here, so see if there is an invokeMethod method up the hierarchy
        final Class[] invokeMethodArgs = {String.class, Object[].class};
        method = findMethodInClassHierarchy(instanceKlazz, INVOKE_METHOD_METHOD, invokeMethodArgs, this);
        if (method instanceof ClosureMetaMethod) {
            onInvokeMethodFoundInHierarchy(method);
            return method.invoke(instance, invokeMethodArgs);
        }

        // last resort look in the category
        if (method == null && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            method = getCategoryMethodMissing(instanceKlazz);
            if (method != null) {
                return method.invoke(instance, new Object[]{methodName, arguments});
            }
        }

        if (methodMissing != null) {
            try {
                return methodMissing.invoke(instance, new Object[]{methodName, arguments});
            } catch (InvokerInvocationException iie) {
                if (methodMissing instanceof ClosureMetaMethod && iie.getCause() instanceof MissingMethodException) {
                    MissingMethodException mme = (MissingMethodException) iie.getCause();
                    throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(),
                            mme.getArguments(), mme.isStatic(), mme);
                }
                throw iie;
            } catch (MissingMethodException mme) {
                if (methodMissing instanceof ClosureMetaMethod) {
                    throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(),
                            mme.getArguments(), mme.isStatic(), mme);
                } else {
                    throw mme;
                }
            }
        } else if (original != null) {
            throw original;
        } else {
            throw new MissingMethodExceptionNoStack(methodName, theClass, arguments, false);
        }
    }

    protected void onSuperPropertyFoundInHierarchy(MetaBeanProperty property) {
    }

    protected void onMixinMethodFound(MetaMethod method) {
    }

    protected void onSuperMethodFoundInHierarchy(MetaMethod method) {
    }

    protected void onInvokeMethodFoundInHierarchy(MetaMethod method) {
    }

    protected void onSetPropertyFoundInHierarchy(MetaMethod method) {
    }

    protected void onGetPropertyFoundInHierarchy(MetaMethod method) {
    }

    /**
     * Hook to deal with the case of MissingProperty for static properties. The method will look attempt to look up
     * "propertyMissing" handlers and invoke them otherwise thrown a MissingPropertyException
     *
     * @param instance      The instance
     * @param propertyName  The name of the property
     * @param optionalValue The value in the case of a setter
     * @param isGetter      True if its a getter
     * @return The value in the case of a getter or a MissingPropertyException
     */
    protected Object invokeStaticMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
        MetaClass mc = instance instanceof Class ? registry.getMetaClass((Class) instance) : this;
        if (isGetter) {
            MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, GETTER_MISSING_ARGS);
            if (propertyMissing != null) {
                return propertyMissing.invoke(instance, new Object[]{propertyName});
            }
        } else {
            MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, SETTER_MISSING_ARGS);
            if (propertyMissing != null) {
                return propertyMissing.invoke(instance, new Object[]{propertyName, optionalValue});
            }
        }

        if (instance instanceof Class) {
            throw new MissingPropertyException(propertyName, (Class) instance);
        }
        throw new MissingPropertyException(propertyName, theClass);
    }

    /**
     * Invokes a method on the given receiver for the specified arguments.
     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
     *
     * @param object            The object which the method was invoked on
     * @param methodName        The name of the method
     * @param originalArguments The arguments to the method
     * @return The return value of the method
     * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
     */
    public Object invokeMethod(Object object, String methodName, Object[] originalArguments) {
        return invokeMethod(theClass, object, methodName, originalArguments, false, false);
    }

    private Object invokeMethodClosure(Object object, Object[] arguments) {
        final MethodClosure mc = (MethodClosure) object;
        final Object owner = mc.getOwner();

        String methodName = mc.getMethod();
        final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
        final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);

        // To conform to "Least Surprise" principle, try to invoke method with original arguments first, which can match most of use cases
        try {
            return ownerMetaClass.invokeMethod(ownerClass, owner, methodName, arguments, false, false);
        } catch (MissingMethodExceptionNoStack | InvokerInvocationException e) {
            // CONSTRUCTOR REFERENCE
            if (owner instanceof Class && MethodClosure.NEW.equals(methodName)) {
                if (ownerClass.isArray()) {
                    if (0 == arguments.length) {
                        throw new GroovyRuntimeException("The arguments(specifying size) are required to create array[" + ownerClass.getCanonicalName() + "]");
                    }

                    int arrayDimension = ArrayTypeUtils.dimension(ownerClass);

                    if (arguments.length > arrayDimension) {
                        throw new GroovyRuntimeException("The length[" + arguments.length + "] of arguments should not be greater than the dimensions[" + arrayDimension + "] of array[" + ownerClass.getCanonicalName() + "]");
                    }

                    int[] sizeArray = new int[arguments.length];

                    for (int i = 0, n = sizeArray.length; i < n; i++) {
                        Object argument = arguments[i];

                        if (argument instanceof Integer) {
                            sizeArray[i] = (Integer) argument;
                        } else {
                            sizeArray[i] = Integer.parseInt(String.valueOf(argument));
                        }
                    }

                    Class arrayType =
                            arguments.length == arrayDimension
                                    ? ArrayTypeUtils.elementType(ownerClass) // Just for better performance, though we can use reduceDimension only
                                    : ArrayTypeUtils.elementType(ownerClass, (arrayDimension - arguments.length));
                    return Array.newInstance(arrayType, sizeArray);
                }

                return ownerMetaClass.invokeConstructor(arguments);
            }

            // METHOD REFERENCE
            // if and only if the owner is a class and the method closure can be related to some instance methods,
            // try to invoke method with adjusted arguments(first argument is the actual owner) again.
            // otherwise throw the MissingMethodExceptionNoStack.
            if (!(owner instanceof Class
                    && (Boolean) mc.getProperty(MethodClosure.ANY_INSTANCE_METHOD_EXISTS))) {

                throw e;
            }

            if (arguments.length <= 0 || !(arguments[0].getClass().equals(ownerClass))) {
                return invokeMissingMethod(object, methodName, arguments);
            }

            Object newOwner = arguments[0];
            Object[] newArguments = Arrays.copyOfRange(arguments, 1, arguments.length);
            return ownerMetaClass.invokeMethod(ownerClass, newOwner, methodName, newArguments, false, false);
        }
    }

    /**
     * <p>Invokes a method on the given receiver for the specified arguments. The sender is the class that invoked the method on the object.
     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
     *
     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
     * to the super class if necessary
     *
     * @param sender            The java.lang.Class instance that invoked the method
     * @param object            The object which the method was invoked on
     * @param methodName        The name of the method
     * @param originalArguments The arguments to the method
     * @param isCallToSuper     Whether the method is a call to a super class method
     * @param fromInsideClass   Whether the call was invoked from the inside or the outside of the class
     * @return The return value of the method
     * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
     */
    public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
        checkInitalised();
        if (object == null) {
            throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
        }

        final Object[] arguments = originalArguments == null ? EMPTY_ARGUMENTS : originalArguments;
//        final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
//
//        unwrap(arguments);

        MetaMethod method = getMetaMethod(sender, object, methodName, isCallToSuper, arguments);

        final boolean isClosure = object instanceof Closure;
        if (isClosure) {
            final Closure closure = (Closure) object;
            final Object owner = closure.getOwner();

            if (CLOSURE_CALL_METHOD.equals(methodName) || CLOSURE_DO_CALL_METHOD.equals(methodName)) {
                final Class objectClass = object.getClass();
                if (objectClass == MethodClosure.class) {
                    return this.invokeMethodClosure(object, arguments);
                } else if (objectClass == CurriedClosure.class) {
                    final CurriedClosure cc = (CurriedClosure) object;
                    // change the arguments for an uncurried call
                    final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
                    final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
                    final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
                    return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
                }
                if (method == null) invokeMissingMethod(object, methodName, arguments);
            }

            final Object delegate = closure.getDelegate();
            final boolean isClosureNotOwner = owner != closure;
            final int resolveStrategy = closure.getResolveStrategy();

            final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);

            switch (resolveStrategy) {
                case Closure.TO_SELF:
                    method = closure.getMetaClass().pickMethod(methodName, argClasses);
                    if (method != null) return method.invoke(closure, arguments);
                    break;
                case Closure.DELEGATE_ONLY:
                    if (method == null && delegate != closure && delegate != null) {
                        MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
                        method = delegateMetaClass.pickMethod(methodName, argClasses);
                        if (method != null) {
                            return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
                        } else if (delegate != closure && (delegate instanceof GroovyObject)) {
                            return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
                        }
                    }
                    break;
                case Closure.OWNER_ONLY:
                    if (method == null && owner != closure) {
                        MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
                        return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
                    }
                    break;
                case Closure.DELEGATE_FIRST:
                    Tuple2<Object, MetaMethod> tuple = invokeMethod(method, delegate, closure, methodName, argClasses, originalArguments, owner);
                    Object result = tuple.getV1();
                    method = tuple.getV2();
                    if (InvokeMethodResult.NONE != result) {
                        return result;
                    }

                    if (method == null && resolveStrategy != Closure.TO_SELF) {
                        // still no methods found, test if delegate or owner are GroovyObjects
                        // and invoke the method on them if so.
                        MissingMethodException last = null;
                        if (delegate != closure && (delegate instanceof GroovyObject)) {
                            try {
                                return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
                            } catch (MissingMethodException mme) {
                                if (last == null) last = mme;
                            }
                        }
                        if (isClosureNotOwner && (owner instanceof GroovyObject)) {
                            try {
                                return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
                            } catch (MissingMethodException mme) {
                                last = mme;
                            }
                        }
                        if (last != null)
                            return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
                    }

                    break;
                default:
                    Tuple2<Object, MetaMethod> t = invokeMethod(method, delegate, closure, methodName, argClasses, originalArguments, owner);
                    Object r = t.getV1();
                    method = t.getV2();
                    if (InvokeMethodResult.NONE != r) {
                        return r;
                    }

                    if (method == null && resolveStrategy != Closure.TO_SELF) {
                        // still no methods found, test if delegate or owner are GroovyObjects
                        // and invoke the method on them if so.
                        MissingMethodException last = null;
                        if (isClosureNotOwner && (owner instanceof GroovyObject)) {
                            try {
                                return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
                            } catch (MissingMethodException mme) {
                                if (methodName.equals(mme.getMethod())) {
                                    if (last == null) last = mme;
                                } else {
                                    throw mme;
                                }
                            } catch (InvokerInvocationException iie) {
                                if (iie.getCause() instanceof MissingMethodException) {
                                    MissingMethodException mme = (MissingMethodException) iie.getCause();
                                    if (methodName.equals(mme.getMethod())) {
                                        if (last == null) last = mme;
                                    } else {
                                        throw iie;
                                    }
                                } else {
                                    throw iie;
                                }
                            }
                        }
                        if (delegate != closure && (delegate instanceof GroovyObject)) {
                            try {
                                return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
                            } catch (MissingMethodException mme) {
                                last = mme;
                            } catch (InvokerInvocationException iie) {
                                if (iie.getCause() instanceof MissingMethodException) {
                                    last = (MissingMethodException) iie.getCause();
                                } else {
                                    throw iie;
                                }
                            }
                        }
                        if (last != null)
                            return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
                    }
            }
        }

        if (method != null) {
            MetaMethod transformedMetaMethod = VM_PLUGIN.transformMetaMethod(this, method);
            return transformedMetaMethod.doMethodInvoke(object, arguments);
        } else {
            return invokePropertyOrMissing(object, methodName, originalArguments, fromInsideClass, isCallToSuper);
        }
    }

    private MetaMethod getMetaMethod(Class sender, Object object, String methodName, boolean isCallToSuper, Object... arguments) {
        MetaMethod method = null;
        if (CLOSURE_CALL_METHOD.equals(methodName) && object instanceof GeneratedClosure) {
            method = getMethodWithCaching(sender, "doCall", arguments, isCallToSuper);
        }
        if (method == null) {
            method = getMethodWithCaching(sender, methodName, arguments, isCallToSuper);
        }
        MetaClassHelper.unwrap(arguments);

        if (method == null)
            method = tryListParamMetaMethod(sender, methodName, isCallToSuper, arguments);
        return method;
    }

    private MetaMethod tryListParamMetaMethod(Class sender, String methodName, boolean isCallToSuper, Object[] arguments) {
        MetaMethod method = null;
        if (arguments.length == 1 && arguments[0] instanceof List) {
            Object[] newArguments = ((List) arguments[0]).toArray();
            method = createTransformMetaMethod(getMethodWithCaching(sender, methodName, newArguments, isCallToSuper));
        }
        return method;
    }

    protected MetaMethod createTransformMetaMethod(MetaMethod method) {
        if (method == null) {
            return null;
        }

        return new TransformMetaMethod(method) {
            public Object invoke(Object object, Object[] arguments) {
                Object firstArgument = arguments[0];
                List list = (List) firstArgument;
                arguments = list.toArray();
                return super.invoke(object, arguments);
            }
        };
    }

    private Object invokePropertyOrMissing(Object object, String methodName, Object[] originalArguments, boolean fromInsideClass, boolean isCallToSuper) {
        // if no method was found, try to find a closure defined as a field of the class and run it
        Object value = null;
        final MetaProperty metaProperty = this.getMetaProperty(methodName, false);
        if (metaProperty != null) {
            value = metaProperty.getProperty(object);
        } else {
            if (object instanceof Map)
                value = ((Map) object).get(methodName);
        }

        if (value instanceof Closure) {  // This test ensures that value != this If you ever change this ensure that value != this
            Closure closure = (Closure) value;
            MetaClass delegateMetaClass = closure.getMetaClass();
            return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, fromInsideClass);
        }

        if (object instanceof Script) {
            Object bindingVar = ((Script) object).getBinding().getVariables().get(methodName);
            if (bindingVar != null) {
                MetaClass bindingVarMC = ((MetaClassRegistryImpl) registry).getMetaClass(bindingVar);
                return bindingVarMC.invokeMethod(bindingVar, CLOSURE_CALL_METHOD, originalArguments);
            }
        }
        return invokeMissingMethod(object, methodName, originalArguments, null, isCallToSuper);
    }

    private MetaClass lookupObjectMetaClass(Object object) {
        if (object instanceof GroovyObject) {
            GroovyObject go = (GroovyObject) object;
            return go.getMetaClass();
        }
        Class ownerClass = object.getClass();
        if (ownerClass == Class.class) ownerClass = (Class) object;
        MetaClass metaClass = registry.getMetaClass(ownerClass);
        return metaClass;
    }

    private static Object invokeMethodOnGroovyObject(String methodName, Object[] originalArguments, Object owner) {
        GroovyObject go = (GroovyObject) owner;
        return go.invokeMethod(methodName, originalArguments);
    }

    public MetaMethod getMethodWithCaching(Class sender, String methodName, Object[] arguments, boolean isCallToSuper) {
        // let's try use the cache to find the method
        if (!isCallToSuper && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            return getMethodWithoutCaching(sender, methodName, MetaClassHelper.convertToTypeArray(arguments), isCallToSuper);
        }
        final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, methodName);
        if (e == null) {
            return null;
        }

        return isCallToSuper ? getSuperMethodWithCaching(arguments, e) : getNormalMethodWithCaching(arguments, e);
    }

    private static boolean sameClasses(Class[] params, Class[] arguments) {
        // we do here a null check because the params field might not have been set yet
        if (params == null) return false;

        if (params.length != arguments.length)
            return false;

        for (int i = params.length - 1; i >= 0; i--) {
            Object arg = arguments[i];
            if (arg != null) {
                if (params[i] != arguments[i]) return false;
            } else {
                return false;
            }
        }

        return true;
    }

    // This method should be called by CallSite only
    private MetaMethod getMethodWithCachingInternal(Class sender, CallSite site, Class[] params) {
        if (GroovyCategorySupport.hasCategoryInCurrentThread())
            return getMethodWithoutCaching(sender, site.getName(), params, false);

        final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, site.getName());
        if (e == null) {
            return null;
        }

        MetaMethodIndex.CacheEntry cacheEntry;
        final Object methods = e.methods;
        if (methods == null)
            return null;

        cacheEntry = e.cachedMethod;
        if (cacheEntry != null && (sameClasses(cacheEntry.params, params))) {
            return cacheEntry.method;
        }

        cacheEntry = new MetaMethodIndex.CacheEntry(params, (MetaMethod) chooseMethod(e.name, methods, params));
        e.cachedMethod = cacheEntry;
        return cacheEntry.method;
    }

    private MetaMethod getSuperMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
        MetaMethodIndex.CacheEntry cacheEntry;
        if (e.methodsForSuper == null)
            return null;

        cacheEntry = e.cachedMethodForSuper;

        if (cacheEntry != null &&
                MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.methodsForSuper instanceof MetaMethod)) {
            MetaMethod method = cacheEntry.method;
            if (method != null) return method;
        }

        final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
        MetaMethod method = (MetaMethod) chooseMethod(e.name, e.methodsForSuper, classes);
        cacheEntry = new MetaMethodIndex.CacheEntry(classes, method.isAbstract() ? null : method);

        e.cachedMethodForSuper = cacheEntry;

        return cacheEntry.method;
    }

    private MetaMethod getNormalMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
        MetaMethodIndex.CacheEntry cacheEntry;
        final Object methods = e.methods;
        if (methods == null)
            return null;

        cacheEntry = e.cachedMethod;

        if (cacheEntry != null &&
                MetaClassHelper.sameClasses(cacheEntry.params, arguments, methods instanceof MetaMethod)) {
            MetaMethod method = cacheEntry.method;
            if (method != null) return method;
        }

        final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
        cacheEntry = new MetaMethodIndex.CacheEntry(classes, (MetaMethod) chooseMethod(e.name, methods, classes));

        e.cachedMethod = cacheEntry;

        return cacheEntry.method;
    }

    public Constructor retrieveConstructor(Class[] arguments) {
        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
        if (constructor != null) {
            return constructor.getCachedConstructor();
        }
        constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
        if (constructor != null) {
            return constructor.getCachedConstructor();
        }
        return null;
    }

    public MetaMethod retrieveStaticMethod(String methodName, Object[] arguments) {
        final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(theClass, methodName);
        MetaMethodIndex.CacheEntry cacheEntry;
        if (e != null) {
            cacheEntry = e.cachedStaticMethod;

            if (cacheEntry != null &&
                    MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.staticMethods instanceof MetaMethod)) {
                return cacheEntry.method;
            }

            final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
            cacheEntry = new MetaMethodIndex.CacheEntry(classes, pickStaticMethod(methodName, classes));

            e.cachedStaticMethod = cacheEntry;

            return cacheEntry.method;
        }
        return pickStaticMethod(methodName, MetaClassHelper.convertToTypeArray(arguments));
    }

    public MetaMethod getMethodWithoutCaching(Class sender, String methodName, Class[] arguments, boolean isCallToSuper) {
        MetaMethod method = null;
        Object methods = getMethods(sender, methodName, isCallToSuper);
        if (methods != null) {
            method = (MetaMethod) chooseMethod(methodName, methods, arguments);
        }
        return method;
    }

    public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
        checkInitalised();

        final Class sender = object instanceof Class ? (Class) object : object.getClass();
        if (sender != theClass) {
            MetaClass mc = registry.getMetaClass(sender);
            return mc.invokeStaticMethod(sender, methodName, arguments);
        }
        if (sender == Class.class) {
            return invokeMethod(object, methodName, arguments);
        }

        if (arguments == null) arguments = EMPTY_ARGUMENTS;
//        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);

        MetaMethod method = retrieveStaticMethod(methodName, arguments);
        // let's try use the cache to find the method

        if (method != null) {
            MetaClassHelper.unwrap(arguments);
            return method.doMethodInvoke(object, arguments);
        }
        Object prop = null;
        try {
            prop = getProperty(theClass, theClass, methodName, false, false);
        } catch (MissingPropertyException mpe) {
            // ignore
        }

        if (prop instanceof Closure) {
            return invokeStaticClosureProperty(arguments, prop);
        }

        Object[] originalArguments = arguments.clone();
        MetaClassHelper.unwrap(arguments);

        Class superClass = sender.getSuperclass();
        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
        while (superClass != Object.class && superClass != null) {
            MetaClass mc = registry.getMetaClass(superClass);
            method = mc.getStaticMetaMethod(methodName, argClasses);
            if (method != null) return method.doMethodInvoke(object, arguments);

            try {
                prop = mc.getProperty(superClass, superClass, methodName, false, false);
            } catch (MissingPropertyException mpe) {
                // ignore
            }

            if (prop instanceof Closure) {
                return invokeStaticClosureProperty(originalArguments, prop);
            }

            superClass = superClass.getSuperclass();
        }

        if (prop != null) {
            MetaClass propMC = registry.getMetaClass(prop.getClass());
            return propMC.invokeMethod(prop, CLOSURE_CALL_METHOD, arguments);
        }

        return invokeStaticMissingMethod(sender, methodName, arguments);
    }

    private static Object invokeStaticClosureProperty(Object[] originalArguments, Object prop) {
        Closure closure = (Closure) prop;
        MetaClass delegateMetaClass = closure.getMetaClass();
        return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, false);
    }

    private Object invokeStaticMissingMethod(Class sender, String methodName, Object[] arguments) {
        MetaMethod metaMethod = getStaticMetaMethod(STATIC_METHOD_MISSING, METHOD_MISSING_ARGS);
        if (metaMethod != null) {
            return metaMethod.invoke(sender, new Object[]{methodName, arguments});
        }
        throw new MissingMethodException(methodName, sender, arguments, true);
    }

    private MetaMethod pickStaticMethod(String methodName, Class[] arguments) {
        MetaMethod method = null;
        MethodSelectionException mse = null;
        Object methods = getStaticMethods(theClass, methodName);

        if (!(methods instanceof FastArray) || !((FastArray) methods).isEmpty()) {
            try {
                method = (MetaMethod) chooseMethod(methodName, methods, arguments);
            } catch (MethodSelectionException msex) {
                mse = msex;
            }
        }
        if (method == null && theClass != Class.class) {
            MetaClass classMetaClass = registry.getMetaClass(Class.class);
            method = classMetaClass.pickMethod(methodName, arguments);
        }
        if (method == null) {
            method = (MetaMethod) chooseMethod(methodName, methods, MetaClassHelper.convertToTypeArray(arguments));
        }

        if (method == null && mse != null) {
            throw mse;
        } else {
            return method;
        }
    }

    public Object invokeConstructor(Object[] arguments) {
        return invokeConstructor(theClass, arguments);
    }

    public int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments) {
        if (numberOfConstructors == -1) {
            return selectConstructorAndTransformArguments1(arguments);
        }
        // falling back to pre 2.1.9 selection algorithm
        // in practice this branch will only be reached if the class calling this code is a Groovy class
        // compiled with an earlier version of the Groovy compiler
        return selectConstructorAndTransformArguments0(numberOfConstructors, arguments);
    }

    private int selectConstructorAndTransformArguments0(final int numberOfConstructors, Object[] arguments) {
        //TODO: that is just a quick prototype, not the real thing!
        if (numberOfConstructors != constructors.size()) {
            throw new IncompatibleClassChangeError("the number of constructors during runtime and compile time for " +
                    this.theClass.getName() + " do not match. Expected " + numberOfConstructors + " but got " + constructors.size());
        }

        CachedConstructor constructor = createCachedConstructor(arguments);
        List l = new ArrayList(constructors.toList());
        Comparator comp = (arg0, arg1) -> {
            CachedConstructor c0 = (CachedConstructor) arg0;
            CachedConstructor c1 = (CachedConstructor) arg1;
            String descriptor0 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c0.getNativeParameterTypes());
            String descriptor1 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c1.getNativeParameterTypes());
            return descriptor0.compareTo(descriptor1);
        };
        l.sort(comp);
        int found = -1;
        for (int i = 0; i < l.size(); i++) {
            if (l.get(i) != constructor) continue;
            found = i;
            break;
        }
        // NOTE: must be changed to "1 |" if constructor was vargs
        return (found << 8);
    }

    private CachedConstructor createCachedConstructor(Object[] arguments) {
        if (arguments == null) arguments = EMPTY_ARGUMENTS;
        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
        MetaClassHelper.unwrap(arguments);
        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
        if (constructor == null) {
            constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
        }
        if (constructor == null) {
            throw new GroovyRuntimeException(
                    "Could not find matching constructor for: "
                            + theClass.getName()
                            + "(" + InvokerHelper.toTypeString(arguments) + ")");
        }
        return constructor;
    }

    /**
     * Constructor selection algorithm for Groovy 2.1.9+.
     * This selection algorithm was introduced as a workaround for GROOVY-6080. Instead of generating an index between
     * 0 and N where N is the number of super constructors at the time the class is compiled, this algorithm uses
     * a hash of the constructor descriptor instead.
     * <p>
     * This has the advantage of letting the super class add new constructors while being binary compatible. But there
     * are still problems with this approach:
     * <ul>
     *     <li>There's a risk of hash collision, even if it's very low (two constructors of the same class must have the same hash)</li>
     *     <li>If the super class adds a new constructor which takes as an argument a superclass of an existing constructor parameter and
     *     that this new constructor is selected at runtime, it would not find it.</li>
     * </ul>
     * <p>
     * Hopefully in the last case, the error message is much nicer now since it explains that it's a binary incompatible change.
     *
     * @param arguments the actual constructor call arguments
     * @return a hash used to identify the constructor to be called
     * @since 2.1.9
     */
    private int selectConstructorAndTransformArguments1(Object[] arguments) {
        CachedConstructor constructor = createCachedConstructor(arguments);
        final String methodDescriptor = BytecodeHelper.getMethodDescriptor(Void.TYPE, constructor.getNativeParameterTypes());
        // keeping 3 bits for additional information such as vargs
        return BytecodeHelper.hashCode(methodDescriptor);
    }

    /**
     * checks if the initialisation of the class id complete.
     * This method should be called as a form of assert, it is no
     * way to test if there is still initialisation work to be done.
     * Such logic must be implemented in a different way.
     *
     * @throws IllegalStateException if the initialisation is incomplete yet
     */
    protected void checkInitalised() {
        if (!isInitialized())
            throw new IllegalStateException(
                    "initialize must be called for meta " +
                            "class of " + theClass +
                            "(" + this.getClass() + ") " +
                            "to complete initialisation process " +
                            "before any invocation or field/property " +
                            "access can be done");
    }

    /**
     * This is a helper class introduced in Groovy 2.1.0, which is used only by
     * indy. This class is for internal use only.
     *
     * @since Groovy 2.1.0
     */
    public static final class MetaConstructor extends MetaMethod {
        private final CachedConstructor cc;
        private final boolean beanConstructor;

        private MetaConstructor(CachedConstructor cc, boolean bean) {
            super(cc.getNativeParameterTypes());
            this.setParametersTypes(cc.getParameterTypes());
            this.cc = cc;
            this.beanConstructor = bean;
        }

        @Override
        public int getModifiers() {
            return cc.getModifiers();
        }

        @Override
        public String getName() {
            return "<init>";
        }

        @Override
        public Class getReturnType() {
            return cc.getCachedClass().getTheClass();
        }

        @Override
        public CachedClass getDeclaringClass() {
            return cc.getCachedClass();
        }

        @Override
        public Object invoke(Object object, Object[] arguments) {
            return cc.doConstructorInvoke(arguments);
        }

        public CachedConstructor getCachedConstrcutor() {
            return cc;
        }

        public boolean isBeanConstructor() {
            return beanConstructor;
        }
    }

    /**
     * This is a helper method added in Groovy 2.1.0, which is used only by indy.
     * This method is for internal use only.
     *
     * @since Groovy 2.1.0
     */
    public MetaMethod retrieveConstructor(Object[] arguments) {
        checkInitalised();
        if (arguments == null) arguments = EMPTY_ARGUMENTS;
        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
        MetaClassHelper.unwrap(arguments);
        Object res = chooseMethod("<init>", constructors, argClasses);
        if (res instanceof MetaMethod) return (MetaMethod) res;
        CachedConstructor constructor = (CachedConstructor) res;
        if (constructor != null) return new MetaConstructor(constructor, false);
        if (arguments.length == 1 && arguments[0] instanceof Map) {
            res = chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
        } else if (
                arguments.length == 2 && arguments[1] instanceof Map &&
                        theClass.getEnclosingClass() != null &&
                        theClass.getEnclosingClass().isAssignableFrom(argClasses[0])) {
            res = chooseMethod("<init>", constructors, new Class[]{argClasses[0]});
        }
        if (res instanceof MetaMethod) return (MetaMethod) res;
        constructor = (CachedConstructor) res;
        if (constructor != null) return new MetaConstructor(constructor, true);

        return null;
    }

    private Object invokeConstructor(Class at, Object[] arguments) {
        checkInitalised();
        if (arguments == null) arguments = EMPTY_ARGUMENTS;
        Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
        MetaClassHelper.unwrap(arguments);
        CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
        if (constructor != null) {
            return constructor.doConstructorInvoke(arguments);
        }

        if (arguments.length == 1) {
            Object firstArgument = arguments[0];
            if (firstArgument instanceof Map) {
                constructor = (CachedConstructor) chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
                if (constructor != null) {
                    Object bean = constructor.doConstructorInvoke(MetaClassHelper.EMPTY_ARRAY);
                    setProperties(bean, ((Map) firstArgument));
                    return bean;
                }
            }
        }
        throw new GroovyRuntimeException(
                "Could not find matching constructor for: "
                        + theClass.getName()
                        + "(" + InvokerHelper.toTypeString(arguments) + ")");
    }

    /**
     * Sets a number of bean properties from the given Map where the keys are
     * the String names of properties and the values are the values of the
     * properties to set
     */
    public void setProperties(Object bean, Map map) {
        checkInitalised();
        for (Object o : map.entrySet()) {
            Map.Entry entry = (Map.Entry) o;
            String key = entry.getKey().toString();

            Object value = entry.getValue();
            setProperty(bean, key, value);
        }
    }

    /**
     * @return the given property's value on the object
     */
    public Object getProperty(Class sender, Object object, String name, boolean useSuper, boolean fromInsideClass) {

        //----------------------------------------------------------------------
        // handling of static
        //----------------------------------------------------------------------
        boolean isStatic = theClass != Class.class && object instanceof Class;
        if (isStatic && object != theClass) {
            MetaClass mc = registry.getMetaClass((Class) object);
            return mc.getProperty(sender, object, name, useSuper, false);
        }

        checkInitalised();

        //----------------------------------------------------------------------
        // turn getProperty on a Map to get on the Map itself
        //----------------------------------------------------------------------
        if (!isStatic && this.isMap) {
            return ((Map) object).get(name);
        }

        Tuple2<MetaMethod, MetaProperty> methodAndProperty = createMetaMethodAndMetaProperty(sender, sender, name, useSuper, isStatic);
        MetaMethod method = methodAndProperty.getV1();

        //----------------------------------------------------------------------
        // getter
        //----------------------------------------------------------------------
        MetaProperty mp = methodAndProperty.getV2();

        //----------------------------------------------------------------------
        // field
        //----------------------------------------------------------------------
        if (method == null && mp != null) {
            try {
                return mp.getProperty(object);
            } catch (IllegalArgumentException | CacheAccessControlException e) {
                // can't access the field directly but there may be a getter
                mp = null;
            }
        }

        // check for propertyMissing provided through a category
        Object[] arguments = EMPTY_ARGUMENTS;
        if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            method = getCategoryMethodGetter(sender, "propertyMissing", true);
            if (method != null) arguments = new Object[]{name};
        }


        //----------------------------------------------------------------------
        // generic get method
        //----------------------------------------------------------------------
        // check for a generic get method provided through a category
        if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            method = getCategoryMethodGetter(sender, "get", true);
            if (method != null) arguments = new Object[]{name};
        }

        // the generic method is valid, if available (!=null), if static or
        // if it is not static and we do no static access
        if (method == null && genericGetMethod != null && !(!genericGetMethod.isStatic() && isStatic)) {
            arguments = new Object[]{name};
            method = genericGetMethod;
        }

        //----------------------------------------------------------------------
        // special cases
        //----------------------------------------------------------------------
        if (method == null) {
            /* todo these special cases should be special MetaClasses maybe */
            if (theClass != Class.class && object instanceof Class) {
                MetaClass mc = registry.getMetaClass(Class.class);
                return mc.getProperty(Class.class, object, name, useSuper, false);
            }
            if (object instanceof Collection) {
                return DefaultGroovyMethods.getAt((Collection) object, name);
            }
            if (object instanceof Object[]) {
                return DefaultGroovyMethods.getAt(Arrays.asList((Object[]) object), name);
            }
            MetaMethod addListenerMethod = listeners.get(name);
            if (addListenerMethod != null) {
                //TODO: one day we could try return the previously registered Closure listener for easy removal
                return null;
            }
        } else {
            //----------------------------------------------------------------------
            // executing the getter method
            //----------------------------------------------------------------------
            MetaMethod transformedMetaMethod = VM_PLUGIN.transformMetaMethod(this, method);
            return transformedMetaMethod.doMethodInvoke(object, arguments);
        }

        //----------------------------------------------------------------------
        // error due to missing method/field
        //----------------------------------------------------------------------
        if (isStatic || object instanceof Class) {
            return invokeStaticMissingProperty(object, name, null, true);
        }
        return invokeMissingProperty(object, name, null, true);
    }

    public MetaProperty getEffectiveGetMetaProperty(final Class sender, final Object object, String name, final boolean useSuper) {

        //----------------------------------------------------------------------
        // handling of static
        //----------------------------------------------------------------------
        boolean isStatic = theClass != Class.class && object instanceof Class;
        if (isStatic && object != theClass) {
            return new MetaProperty(name, Object.class) {
                final MetaClass mc = registry.getMetaClass((Class) object);

                public Object getProperty(Object object) {
                    return mc.getProperty(sender, object, name, useSuper, false);
                }

                public void setProperty(Object object, Object newValue) {
                    throw new UnsupportedOperationException();
                }
            };
        }

        checkInitalised();

        //----------------------------------------------------------------------
        // turn getProperty on a Map to get on the Map itself
        //----------------------------------------------------------------------
        if (!isStatic && this.isMap) {
            return new MetaProperty(name, Object.class) {
                public Object getProperty(Object object) {
                    return ((Map) object).get(name);
                }

                public void setProperty(Object object, Object newValue) {
                    throw new UnsupportedOperationException();
                }
            };
        }

        Tuple2<MetaMethod, MetaProperty> methodAndProperty = createMetaMethodAndMetaProperty(sender, theClass, name, useSuper, isStatic);
        MetaMethod method = methodAndProperty.getV1();

        //----------------------------------------------------------------------
        // getter
        //----------------------------------------------------------------------
        MetaProperty mp = methodAndProperty.getV2();

        //----------------------------------------------------------------------
        // field
        //----------------------------------------------------------------------
        if (method != null) {
            MetaMethod transformedMetaMethod = VM_PLUGIN.transformMetaMethod(this, method);
            return new GetBeanMethodMetaProperty(name, transformedMetaMethod);
        }

        if (mp != null) {
            return mp;
//            try {
//                return mp.getProperty(object);
//            } catch (IllegalArgumentException e) {
//                // can't access the field directly but there may be a getter
//                mp = null;
//            }
        }

        //----------------------------------------------------------------------
        // generic get method
        //----------------------------------------------------------------------
        // check for a generic get method provided through a category
        if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            method = getCategoryMethodGetter(sender, "get", true);
            if (method != null) {
                MetaMethod transformedMetaMethod = VM_PLUGIN.transformMetaMethod(this, method);
                return new GetMethodMetaProperty(name, transformedMetaMethod);
            }

        }

        // the generic method is valid, if available (!=null), if static or
        // if it is not static and we do no static access
        if (genericGetMethod != null && !(!genericGetMethod.isStatic() && isStatic)) {
            method = genericGetMethod;
            MetaMethod transformedMetaMethod = VM_PLUGIN.transformMetaMethod(this, method);
            return new GetMethodMetaProperty(name, transformedMetaMethod);
        }

        //----------------------------------------------------------------------
        // special cases
        //----------------------------------------------------------------------
        /* todo these special cases should be special MetaClasses maybe */
        if (theClass != Class.class && object instanceof Class) {
            return new MetaProperty(name, Object.class) {
                public Object getProperty(Object object) {
                    MetaClass mc = registry.getMetaClass(Class.class);
                    return mc.getProperty(Class.class, object, name, useSuper, false);
                }

                public void setProperty(Object object, Object newValue) {
                    throw new UnsupportedOperationException();
                }
            };
        }
        if (object instanceof Collection) {
            return new MetaProperty(name, Object.class) {
                public Object getProperty(Object object) {
                    return DefaultGroovyMethods.getAt((Collection) object, name);
                }

                public void setProperty(Object object, Object newValue) {
                    throw new UnsupportedOperationException();
                }
            };
        }
        if (object instanceof Object[]) {
            return new MetaProperty(name, Object.class) {
                public Object getProperty(Object object) {
                    return DefaultGroovyMethods.getAt(Arrays.asList((Object[]) object), name);
                }

                public void setProperty(Object object, Object newValue) {
                    throw new UnsupportedOperationException();
                }
            };
        }
        MetaMethod addListenerMethod = listeners.get(name);
        if (addListenerMethod != null) {
            //TODO: one day we could try return the previously registered Closure listener for easy removal
            return new MetaProperty(name, Object.class) {
                public Object getProperty(Object object) {
                    return null;
                }

                public void setProperty(Object object, Object newValue) {
                    throw new UnsupportedOperationException();
                }
            };
        }

        //----------------------------------------------------------------------
        // error due to missing method/field
        //----------------------------------------------------------------------
        if (isStatic || object instanceof Class) {
            return new MetaProperty(name, Object.class) {
                public Object getProperty(Object object) {
                    return invokeStaticMissingProperty(object, name, null, true);
                }

                public void setProperty(Object object, Object newValue) {
                    throw new UnsupportedOperationException();
                }
            };
        }
        return new MetaProperty(name, Object.class) {
            public Object getProperty(Object object) {
                return invokeMissingProperty(object, name, null, true);
            }

            public void setProperty(Object object, Object newValue) {
                throw new UnsupportedOperationException();
            }
        };
    }

    private Tuple2<MetaMethod, MetaProperty> createMetaMethodAndMetaProperty(final Class senderForMP, final Class senderForCMG, final String name, final boolean useSuper, final boolean isStatic) {
        MetaMethod method = null;
        MetaProperty mp = getMetaProperty(senderForMP, name, useSuper, isStatic);
        if (mp != null) {
            if (mp instanceof MetaBeanProperty) {
                MetaBeanProperty mbp = (MetaBeanProperty) mp;
                method = mbp.getGetter();
                mp = mbp.getField();
            }
        }

        // check for a category method named like a getter
        if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            String getterName = GroovyCategorySupport.getPropertyCategoryGetterName(name);
            if (getterName != null) {
                MetaMethod categoryMethod = getCategoryMethodGetter(senderForCMG, getterName, false);
                if (categoryMethod != null)
                    method = categoryMethod;
            }
        }

        return new Tuple2<>(method, mp);
    }

    private static MetaMethod getCategoryMethodMissing(Class sender) {
        List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods("methodMissing");
        if (possibleGenericMethods != null) {
            for (Object possibleGenericMethod : possibleGenericMethods) {
                MetaMethod mmethod = (MetaMethod) possibleGenericMethod;
                if (!mmethod.getDeclaringClass().getTheClass().isAssignableFrom(sender))
                    continue;

                CachedClass[] paramTypes = mmethod.getParameterTypes();
                if (paramTypes.length == 2 && paramTypes[0].getTheClass() == String.class) {
                    return mmethod;
                }
            }
        }
        return null;
    }

    private static MetaMethod getCategoryMethodGetter(Class sender, String name, boolean useLongVersion) {
        List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods(name);
        if (possibleGenericMethods != null) {
            for (Object possibleGenericMethod : possibleGenericMethods) {
                MetaMethod mmethod = (MetaMethod) possibleGenericMethod;
                if (!mmethod.getDeclaringClass().getTheClass().isAssignableFrom(sender))
                    continue;

                CachedClass[] paramTypes = mmethod.getParameterTypes();
                if (useLongVersion) {
                    if (paramTypes.length == 1 && paramTypes[0].getTheClass() == String.class) {
                        return mmethod;
                    }
                } else {
                    if (paramTypes.length == 0) return mmethod;
                }
            }
        }
        return null;
    }

    private static MetaMethod getCategoryMethodSetter(Class sender, String name, boolean useLongVersion) {
        List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods(name);
        if (possibleGenericMethods != null) {
            for (Object possibleGenericMethod : possibleGenericMethods) {
                MetaMethod mmethod = (MetaMethod) possibleGenericMethod;
                if (!mmethod.getDeclaringClass().getTheClass().isAssignableFrom(sender))
                    continue;

                CachedClass[] paramTypes = mmethod.getParameterTypes();
                if (useLongVersion) {
                    if (paramTypes.length == 2 && paramTypes[0].getTheClass() == String.class) {
                        return mmethod;
                    }
                } else {
                    if (paramTypes.length == 1) return mmethod;
                }
            }
        }
        return null;
    }

    /**
     * Get all the properties defined for this type
     *
     * @return a list of MetaProperty objects
     */
    public List<MetaProperty> getProperties() {
        checkInitalised();
        SingleKeyHashMap propertyMap = classPropertyIndex.getNullable(theCachedClass);
        if (propertyMap == null) {
            // GROOVY-6903: May happen in some special environment, like under Android, due
            // to classloading issues
            propertyMap = new SingleKeyHashMap();
        }
        // simply return the values of the metaproperty map as a List
        List ret = new ArrayList(propertyMap.size());
        for (ComplexKeyHashMap.EntryIterator iter = propertyMap.getEntrySetIterator(); iter.hasNext(); ) {
            MetaProperty element = (MetaProperty) ((SingleKeyHashMap.Entry) iter.next()).value;
            if (element instanceof CachedField) continue;
            // filter out DGM beans
            if (element instanceof MetaBeanProperty) {
                MetaBeanProperty mp = (MetaBeanProperty) element;
                boolean setter = true;
                boolean getter = true;
                MetaMethod getterMetaMethod = mp.getGetter();
                if (getterMetaMethod == null || getterMetaMethod instanceof GeneratedMetaMethod || getterMetaMethod instanceof NewInstanceMetaMethod) {
                    getter = false;
                }
                MetaMethod setterMetaMethod = mp.getSetter();
                if (setterMetaMethod == null || setterMetaMethod instanceof GeneratedMetaMethod || setterMetaMethod instanceof NewInstanceMetaMethod) {
                    setter = false;
                }
                if (!setter && !getter) continue;
//  TODO: I (ait) don't know why these strange tricks needed and comment following as it effects some Grails tests
//                if (!setter && mp.getSetter() != null) {
//                    element = new MetaBeanProperty(mp.getName(), mp.getType(), mp.getGetter(), null);
//                }
//                if (!getter && mp.getGetter() != null) {
//                    element = new MetaBeanProperty(mp.getName(), mp.getType(), null, mp.getSetter());
//                }
            }

            if (!permissivePropertyAccess) {
                if (element instanceof MetaBeanProperty) {
                    MetaBeanProperty mbp = (MetaBeanProperty) element;
                    boolean getterAccessible = canAccessLegally(mbp.getGetter());
                    boolean setterAccessible = canAccessLegally(mbp.getSetter());

                    if (!(getterAccessible && setterAccessible)) continue;
                }
            }

            ret.add(element);
        }
        return ret;
    }

    private static boolean canAccessLegally(MetaMethod accessor) {
        boolean accessible = true;
        if (accessor instanceof CachedMethod) {
            CachedMethod cm = (CachedMethod) accessor;
            accessible = cm.canAccessLegally(MetaClassImpl.class);
        }

        return accessible;
    }

    /**
     * return null if nothing valid has been found, a MetaMethod (for getter always the case if not null) or
     * a LinkedList&lt;MetaMethod&gt; if there are multiple setter
     */
    private static Object filterPropertyMethod(Object methodOrList, boolean isGetter, boolean booleanGetter) {
        // Method has been optimized to reach a target of 325 bytecode size, making it JIT'able
        Object ret = null;

        if (methodOrList instanceof MetaMethod) {
            MetaMethod element = (MetaMethod) methodOrList;
            int parameterCount = element.getParameterTypes().length;
            if (!isGetter &&
                    //(element.getReturnType() == Void.class || element.getReturnType() == Void.TYPE) &&
                    parameterCount == 1) {
                ret = element;
            }
            Class returnType = element.getReturnType();
            if (isGetter &&
                    !(returnType == Void.class || returnType == Void.TYPE) &&
                    (!booleanGetter || returnType == Boolean.class || returnType == Boolean.TYPE) &&
                    parameterCount == 0) {
                ret = element;
            }
        }
        if (methodOrList instanceof FastArray) {
            FastArray methods = (FastArray) methodOrList;
            final int len = methods.size();
            final Object[] data = methods.getArray();
            for (int i = 0; i != len; ++i) {
                MetaMethod element = (MetaMethod) data[i];
                int parameterCount = element.getParameterTypes().length;
                if (!isGetter &&
                        //(element.getReturnType() == Void.class || element.getReturnType() == Void.TYPE) &&
                        parameterCount == 1) {
                    ret = addElementToList(ret, element);
                }
                Class returnType = element.getReturnType();
                if (isGetter &&
                        !(returnType == Void.class || returnType == Void.TYPE) &&
                        parameterCount == 0) {
                    ret = addElementToList(ret, element);
                }
            }
        }

        if (ret == null
                || (ret instanceof MetaMethod)
                || !isGetter) {
            return ret;
        }

        // we found multiple matching methods
        // this is a problem, because we can use only one
        // if it is a getter, then use the most general return
        // type to decide which method to use. If it is a setter
        // we use the type of the first parameter
        MetaMethod method = null;
        int distance = -1;
        for (final Object o : ((List) ret)) {
            MetaMethod element = (MetaMethod) o;
            int localDistance = distanceToObject(element.getReturnType());
            //TODO: maybe implement the case localDistance==distance
            if (distance == -1 || distance > localDistance) {
                distance = localDistance;
                method = element;
            }
        }
        return method;
    }

    private static Object addElementToList(Object ret, MetaMethod element) {
        if (ret == null) {
            ret = element;
        } else if (ret instanceof List) {
            ((List) ret).add(element);
        } else {
            List list = new LinkedList();
            list.add(ret);
            list.add(element);
            ret = list;
        }
        return ret;
    }

    private static int distanceToObject(Class c) {
        int count;
        for (count = 0; c != null; count++) {
            c = c.getSuperclass();
        }
        return count;
    }

    /**
     * This will build up the property map (Map of MetaProperty objects, keyed on
     * property name).
     *
     * @param propertyDescriptors the property descriptors
     */
    @SuppressWarnings("unchecked")
    private void setupProperties(PropertyDescriptor[] propertyDescriptors) {
        if (theCachedClass.isInterface) {
            LinkedList<CachedClass> superClasses = new LinkedList<>();
            superClasses.add(ReflectionCache.OBJECT_CLASS);
            Set interfaces = theCachedClass.getInterfaces();

            LinkedList<CachedClass> superInterfaces = new LinkedList<CachedClass>(interfaces);
            // sort interfaces so that we may ensure a deterministic behaviour in case of
            // ambiguous fields (class implementing two interfaces using the same field)
            if (superInterfaces.size() > 1) {
                superInterfaces.sort(CACHED_CLASS_NAME_COMPARATOR);
            }

            SingleKeyHashMap iPropertyIndex = classPropertyIndex.getNotNull(theCachedClass);
            for (CachedClass iclass : superInterfaces) {
                SingleKeyHashMap sPropertyIndex = classPropertyIndex.getNotNull(iclass);
                copyNonPrivateFields(sPropertyIndex, iPropertyIndex, null);
                addFields(iclass, iPropertyIndex);
            }
            addFields(theCachedClass, iPropertyIndex);

            applyPropertyDescriptors(propertyDescriptors);
            applyStrayPropertyMethods(superClasses, classPropertyIndex, true);

            makeStaticPropertyIndex();
        } else {
            LinkedList<CachedClass> superClasses = getSuperClasses();
            LinkedList<CachedClass> interfaces = new LinkedList<>(theCachedClass.getInterfaces());
            // sort interfaces so that we may ensure a deterministic behaviour in case of
            // ambiguous fields (class implementing two interfaces using the same field)
            if (interfaces.size() > 1) {
                interfaces.sort(CACHED_CLASS_NAME_COMPARATOR);
            }

            // if this an Array, then add the special read-only "length" property
            if (theCachedClass.isArray) {
                SingleKeyHashMap map = new SingleKeyHashMap();
                map.put("length", arrayLengthProperty);
                classPropertyIndex.put(theCachedClass, map);
            }

            inheritStaticInterfaceFields(superClasses, new LinkedHashSet(interfaces));
            inheritFields(superClasses);

            applyPropertyDescriptors(propertyDescriptors);

            applyStrayPropertyMethods(superClasses, classPropertyIndex, true);
            applyStrayPropertyMethods(superClasses, classPropertyIndexForSuper, false);

            copyClassPropertyIndexForSuper(classPropertyIndexForSuper);
            makeStaticPropertyIndex();
        }
    }

    private void makeStaticPropertyIndex() {
        SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
        for (ComplexKeyHashMap.EntryIterator iter = propertyMap.getEntrySetIterator(); iter.hasNext(); ) {
            SingleKeyHashMap.Entry entry = ((SingleKeyHashMap.Entry) iter.next());

            MetaProperty mp = (MetaProperty) entry.getValue();
            if (mp instanceof CachedField) {
                CachedField mfp = (CachedField) mp;
                if (!mfp.isStatic()) continue;
            } else if (mp instanceof MetaBeanProperty) {
                MetaProperty result = establishStaticMetaProperty(mp);
                if (result == null) continue;
                else {
                    mp = result;
                }
            } else if (mp instanceof MultipleSetterProperty) {
                MultipleSetterProperty msp = (MultipleSetterProperty) mp;
                mp = msp.createStaticVersion();
            } else {
                continue; // ignore all other types
            }
            staticPropertyIndex.put(entry.getKey(), mp);
        }

    }

    private static MetaProperty establishStaticMetaProperty(MetaProperty mp) {
        MetaBeanProperty mbp = (MetaBeanProperty) mp;
        MetaProperty result = null;
        final MetaMethod getterMethod = mbp.getGetter();
        final MetaMethod setterMethod = mbp.getSetter();
        final CachedField metaField = mbp.getField();

        boolean getter = getterMethod == null || getterMethod.isStatic();
        boolean setter = setterMethod == null || setterMethod.isStatic();
        boolean field = metaField == null || metaField.isStatic();

        if (!getter && !setter && !field) {
            return result;
        } else {
            final String propertyName = mbp.getName();
            final Class propertyType = mbp.getType();

            if (setter && getter) {
                if (field) {
                    result = mbp; // nothing to do
                } else {
                    result = new MetaBeanProperty(propertyName, propertyType, getterMethod, setterMethod);
                }
            } else if (getter && !setter) {
                if (getterMethod == null) {
                    result = metaField;
                } else {
                    MetaBeanProperty newmp = new MetaBeanProperty(propertyName, propertyType, getterMethod, null);
                    if (field) newmp.setField(metaField);
                    result = newmp;
                }
            } else if (setter && !getter) {
                if (setterMethod == null) {
                    result = metaField;
                } else {
                    MetaBeanProperty newmp = new MetaBeanProperty(propertyName, propertyType, null, setterMethod);
                    if (field) newmp.setField(metaField);
                    result = newmp;
                }
            } else {
                result = metaField;
            }
        }
        return result;
    }

    private void copyClassPropertyIndexForSuper(Index dest) {
        for (ComplexKeyHashMap.EntryIterator iter = classPropertyIndex.getEntrySetIterator(); iter.hasNext(); ) {
            SingleKeyHashMap.Entry entry = (SingleKeyHashMap.Entry) iter.next();
            SingleKeyHashMap newVal = new SingleKeyHashMap();
            dest.put((CachedClass) entry.getKey(), newVal);
        }
    }

    private void inheritStaticInterfaceFields(LinkedList superClasses, Set interfaces) {
        for (Object anInterface : interfaces) {
            CachedClass iclass = (CachedClass) anInterface;
            SingleKeyHashMap iPropertyIndex = classPropertyIndex.getNotNull(iclass);
            addFields(iclass, iPropertyIndex);
            for (Object superClass : superClasses) {
                CachedClass sclass = (CachedClass) superClass;
                if (!iclass.getTheClass().isAssignableFrom(sclass.getTheClass())) continue;
                SingleKeyHashMap sPropertyIndex = classPropertyIndex.getNotNull(sclass);
                copyNonPrivateFields(iPropertyIndex, sPropertyIndex, null);
            }
        }
    }

    private void inheritFields(LinkedList<CachedClass> superClasses) {
        SingleKeyHashMap last = null;
        for (CachedClass klass : superClasses) {
            SingleKeyHashMap propertyIndex = classPropertyIndex.getNotNull(klass);
            if (last != null) {
                copyNonPrivateFields(last, propertyIndex, klass);
            }
            last = propertyIndex;
            addFields(klass, propertyIndex);
        }
    }

    private static void addFields(CachedClass klass, SingleKeyHashMap propertyIndex) {
        for (CachedField field : klass.getFields()) {
            propertyIndex.put(field.getName(), field);
        }
    }

    private static void copyNonPrivateFields(SingleKeyHashMap from, SingleKeyHashMap to, @Nullable CachedClass klass) {
        for (ComplexKeyHashMap.EntryIterator it = from.getEntrySetIterator(); it.hasNext(); ) {
            SingleKeyHashMap.Entry entry = (SingleKeyHashMap.Entry) it.next();
            CachedField field = (CachedField) entry.getValue();
            int modifiers = field.getModifiers();
            if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers) || (!Modifier.isPrivate(modifiers)
                    && klass != null && inSamePackage(field.getDeclaringClass(), klass.getTheClass()))) {
                to.put(entry.getKey(), field);
            }
        }
    }

    private void applyStrayPropertyMethods(LinkedList<CachedClass> superClasses, Index classPropertyIndex, boolean isThis) {
        // now look for any stray getters that may be used to define a property
        for (CachedClass klass : superClasses) {
            MetaMethodIndex.Header header = metaMethodIndex.getHeader(klass.getTheClass());
            SingleKeyHashMap propertyIndex = classPropertyIndex.getNotNull(klass);
            for (MetaMethodIndex.Entry e = header.head; e != null; e = e.nextClassEntry) {
                String methodName = e.name;
                // name too short?
                if (methodName.length() < 3 ||
                        (!methodName.startsWith("is") && methodName.length() < 4)) continue;
                // possible getter/setter?
                boolean isGetter = methodName.startsWith("get") || methodName.startsWith("is");
                boolean isBooleanGetter = methodName.startsWith("is");
                boolean isSetter = methodName.startsWith("set");
                if (!isGetter && !isSetter) continue;

                Object propertyMethods = filterPropertyMethod(isThis ? e.methods : e.methodsForSuper, isGetter, isBooleanGetter);
                if (propertyMethods == null) continue;

                String propName = getPropName(methodName);
                if (propertyMethods instanceof MetaMethod) {
                    createMetaBeanProperty(propertyIndex, propName, isGetter, (MetaMethod) propertyMethods);
                } else {
                    LinkedList<MetaMethod> methods = (LinkedList<MetaMethod>) propertyMethods;
                    for (MetaMethod m : methods) {
                        createMetaBeanProperty(propertyIndex, propName, isGetter, m);
                    }
                }
            }
        }
    }

    private static final ConcurrentMap<String, String> PROP_NAMES = new ConcurrentHashMap<>(1024);

    private static String getPropName(String methodName) {
        return PROP_NAMES.computeIfAbsent(methodName, k -> {
            // assume "is" or "[gs]et"
            return BeanUtils.decapitalize(methodName.startsWith("is")
                    ? methodName.substring(2) : methodName.substring(3));
        });
    }

    private static MetaProperty makeReplacementMetaProperty(MetaProperty mp, String propName, boolean isGetter, MetaMethod propertyMethod) {
        if (mp == null) {
            if (isGetter) {
                return new MetaBeanProperty(propName,
                        propertyMethod.getReturnType(),
                        propertyMethod, null);
            } else {
                //isSetter
                return new MetaBeanProperty(propName,
                        propertyMethod.getParameterTypes()[0].getTheClass(),
                        null, propertyMethod);
            }
        }

        if (mp instanceof CachedField) {
            CachedField mfp = (CachedField) mp;
            MetaBeanProperty mbp = new MetaBeanProperty(propName, mfp.getType(),
                    isGetter ? propertyMethod : null,
                    isGetter ? null : propertyMethod);
            mbp.setField(mfp);
            return mbp;
        } else if (mp instanceof MultipleSetterProperty) {
            MultipleSetterProperty msp = (MultipleSetterProperty) mp;
            if (isGetter) {
                msp.setGetter(propertyMethod);
            }
            return msp;
        } else if (mp instanceof MetaBeanProperty) {
            MetaBeanProperty mbp = (MetaBeanProperty) mp;
            if (isGetter) {
                mbp.setGetter(propertyMethod);
                return mbp;
            } else if (mbp.getSetter() == null || mbp.getSetter() == propertyMethod) {
                mbp.setSetter(propertyMethod);
                return mbp;
            } else {
                MultipleSetterProperty msp = new MultipleSetterProperty(propName);
                msp.setField(mbp.getField());
                msp.setGetter(mbp.getGetter());
                return msp;
            }
        } else {
            throw new GroovyBugError("unknown MetaProperty class used. Class is " + mp.getClass());
        }
    }

    private static void createMetaBeanProperty(SingleKeyHashMap propertyIndex, String propName, boolean isGetter, MetaMethod propertyMethod) {
        // check if property is already accounted for
        MetaProperty oldMP = (MetaProperty) propertyIndex.get(propName);
        if (oldMP == null && propName.length() == 1 && propertyMethod.isStatic()) {
            oldMP = (MetaProperty) propertyIndex.get(propName.toUpperCase());
            if (oldMP != null) propName = propName.toUpperCase();
        }

        MetaProperty newMP = makeReplacementMetaProperty(oldMP, propName, isGetter, propertyMethod);
        if (newMP != oldMP) {
            propertyIndex.put(propName, newMP);
        }
    }

    protected void applyPropertyDescriptors(PropertyDescriptor[] propertyDescriptors) {
        // now iterate over the map of property descriptors and generate
        // MetaBeanProperty objects
        for (PropertyDescriptor pd : propertyDescriptors) {
            // skip if the property type is unknown (this seems to be the case if the
            // property descriptor is based on a setX() method that has two parameters,
            // which is not a valid property)
            if (pd.getPropertyType() == null)
                continue;

            // get the getter method
            Method method = pd.getReadMethod();
            MetaMethod getter;

            if (method != null) {
                CachedMethod cachedGetter = CachedMethod.find(method);
                getter = cachedGetter == null ? null : findMethod(cachedGetter);
            } else {
                getter = null;
            }

            // get the setter method
            MetaMethod setter;
            method = pd.getWriteMethod();
            if (method != null) {
                CachedMethod cachedSetter = CachedMethod.find(method);
                setter = cachedSetter == null ? null : findMethod(cachedSetter);
            } else {
                setter = null;
            }

            // now create the MetaProperty object
            MetaBeanProperty mp = new MetaBeanProperty(pd.getName(), pd.getPropertyType(), getter, setter);
            addMetaBeanProperty(mp);
        }
    }

    /**
     * Adds a new MetaBeanProperty to this MetaClass
     *
     * @param mp The MetaBeanProperty
     */
    public void addMetaBeanProperty(MetaBeanProperty mp) {
        MetaProperty staticProperty = establishStaticMetaProperty(mp);
        if (staticProperty != null) {
            staticPropertyIndex.put(mp.getName(), mp);
        } else {
            SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
            //keep field
            CachedField field;
            MetaProperty old = (MetaProperty) propertyMap.get(mp.getName());
            if (old != null) {
                if (old instanceof MetaBeanProperty) {
                    field = ((MetaBeanProperty) old).getField();
                } else if (old instanceof MultipleSetterProperty) {
                    field = ((MultipleSetterProperty) old).getField();
                } else {
                    field = (CachedField) old;
                }
                mp.setField(field);
            }

            // put it in the list
            // this will overwrite a possible field property
            propertyMap.put(mp.getName(), mp);
        }
    }

    /**
     * <p>Retrieves a property on the given receiver for the specified arguments. The sender is the class that is requesting the property from the object.
     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
     *
     * <p>The useSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
     * to the super class if necessary
     *
     * @param sender          The java.lang.Class instance that is mutating the property
     * @param object          The Object which the property is being set on
     * @param name            The name of the property
     * @param newValue        The new value of the property to set
     * @param useSuper        Whether the call is to a super class property
     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class.
     */
    public void setProperty(Class sender, Object object, String name, Object newValue, boolean useSuper, boolean fromInsideClass) {
        checkInitalised();

        //----------------------------------------------------------------------
        // handling of static
        //----------------------------------------------------------------------
        boolean isStatic = theClass != Class.class && object instanceof Class;
        if (isStatic && object != theClass) {
            MetaClass mc = registry.getMetaClass((Class) object);
            mc.getProperty(sender, object, name, useSuper, fromInsideClass);
            return;
        }

        //----------------------------------------------------------------------
        // Unwrap wrapped values fo now - the new MOP will handle them properly
        //----------------------------------------------------------------------
        if (newValue instanceof Wrapper) newValue = ((Wrapper) newValue).unwrap();

        MetaMethod method = null;
        Object[] arguments = null;

        //----------------------------------------------------------------------
        // setter
        //----------------------------------------------------------------------
        MetaProperty mp = getMetaProperty(sender, name, useSuper, isStatic);
        MetaProperty field = null;
        if (mp != null) {
            if (mp instanceof MetaBeanProperty) {
                MetaBeanProperty mbp = (MetaBeanProperty) mp;
                method = mbp.getSetter();
                MetaProperty f = mbp.getField();
                if (method != null || (f != null && !Modifier.isFinal(f.getModifiers()))) {
                    arguments = new Object[]{newValue};
                    field = f;
                }
            } else {
                field = mp;
            }
        }

        // check for a category method named like a setter
        if (!useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()
                && name.length() > 0) {
            String getterName = GroovyCategorySupport.getPropertyCategorySetterName(name);
            if (getterName != null) {
                MetaMethod categoryMethod = getCategoryMethodSetter(sender, getterName, false);
                if (categoryMethod != null) {
                    method = categoryMethod;
                    arguments = new Object[]{newValue};
                }
            }
        }

        //----------------------------------------------------------------------
        // listener method
        //----------------------------------------------------------------------
        boolean ambiguousListener = false;
        if (method == null) {
            method = listeners.get(name);
            ambiguousListener = method == AMBIGUOUS_LISTENER_METHOD;
            if (method != null &&
                    !ambiguousListener &&
                    newValue instanceof Closure) {
                // let's create a dynamic proxy
                Object proxy = Proxy.newProxyInstance(
                        theClass.getClassLoader(),
                        new Class[]{method.getParameterTypes()[0].getTheClass()},
                        new ConvertedClosure((Closure) newValue, name));
                arguments = new Object[]{proxy};
                newValue = proxy;
            } else {
                method = null;
            }
        }

        //----------------------------------------------------------------------
        // field
        //----------------------------------------------------------------------
        if (method == null && field != null) {
            int modifiers = field.getModifiers();
            if (Modifier.isFinal(modifiers)) {
                // GROOVY-5985
                if (!isStatic && this.isMap) {
                    ((Map) object).put(name, newValue);
                    return;
                }
                throw new ReadOnlyPropertyException(name, theClass);
            }
            if (!this.isMap || Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
                field.setProperty(object, newValue);
                return;
            }
        }

        //----------------------------------------------------------------------
        // generic set method
        //----------------------------------------------------------------------
        // check for a generic get method provided through a category
        if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
            method = getCategoryMethodSetter(sender, "set", true);
            if (method != null) arguments = new Object[]{name, newValue};
        }

        // the generic method is valid, if available (!=null), if static or
        // if it is not static and we do no static access
        if (method == null && genericSetMethod != null && !(!genericSetMethod.isStatic() && isStatic)) {
            arguments = new Object[]{name, newValue};
            method = genericSetMethod;
        }

        //----------------------------------------------------------------------
        // executing the setter method
        //----------------------------------------------------------------------
        if (method != null) {
            if (arguments.length == 1) {
                newValue = DefaultTypeTransformation.castToType(
                        newValue,
                        method.getParameterTypes()[0].getTheClass());
                arguments[0] = newValue;
            } else {
                newValue = DefaultTypeTransformation.castToType(
                        newValue,
                        method.getParameterTypes()[1].getTheClass());
                arguments[1] = newValue;
            }

            MetaMethod transformedMetaMethod = VM_PLUGIN.transformMetaMethod(this, method);
            transformedMetaMethod.doMethodInvoke(object, arguments);
            return;
        }

        //----------------------------------------------------------------------
        // turn setProperty on a Map to put on the Map itself
        //----------------------------------------------------------------------
        if (method == null && !isStatic && this.isMap) {
            ((Map) object).put(name, newValue);
            return;
        }

        //----------------------------------------------------------------------
        // error due to missing method/field
        //----------------------------------------------------------------------
        if (ambiguousListener) {
            throw new GroovyRuntimeException("There are multiple listeners for the property " + name + ". Please do not use the bean short form to access this listener.");
        }
        if (mp != null) {
            throw new ReadOnlyPropertyException(name, theClass);
        }

        if ((isStatic || object instanceof Class) && !"metaClass".equals(name)) {
            invokeStaticMissingProperty(object, name, newValue, false);
        } else {
            invokeMissingProperty(object, name, newValue, false);
        }
    }

    private MetaProperty getMetaProperty(Class _clazz, String name, boolean useSuper, boolean useStatic) {
        if (_clazz == theClass)
            return getMetaProperty(name, useStatic);

        CachedClass clazz = ReflectionCache.getCachedClass(_clazz);
        while (true) {
            SingleKeyHashMap propertyMap;
            if (useStatic) {
                propertyMap = staticPropertyIndex;
            } else if (useSuper) {
                propertyMap = classPropertyIndexForSuper.getNullable(clazz);
            } else {
                propertyMap = classPropertyIndex.getNullable(clazz);
            }
            if (propertyMap == null) {
                if (clazz != theCachedClass) {
                    clazz = theCachedClass;
                    continue;
                } else {
                    return null;
                }
            }
            return (MetaProperty) propertyMap.get(name);
        }
    }

    private MetaProperty getMetaProperty(String name, boolean useStatic) {
        CachedClass clazz = theCachedClass;
        SingleKeyHashMap propertyMap;
        if (useStatic) {
            propertyMap = staticPropertyIndex;
        } else {
            propertyMap = classPropertyIndex.getNullable(clazz);
        }
        if (propertyMap == null) {
            return null;
        }
        return (MetaProperty) propertyMap.get(name);
    }

    /**
     * Retrieves the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
     *
     * @param sender      The class of the object that requested the attribute
     * @param object      The instance
     * @param attribute   The name of the attribute
     * @param useSuper    Whether to look-up on the super class or not
     * @return The attribute value
     */
    public Object getAttribute(final Class sender, final Object object, final String attribute, final boolean useSuper) {
        return getAttribute(sender, object, attribute, useSuper, false);
    }

    /**
     * Retrieves the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
     *
     * @param sender          The class of the object that requested the attribute
     * @param object          The instance the attribute is to be retrieved from
     * @param attribute       The name of the attribute
     * @param useSuper        Whether to look-up on the super class or not
     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class.
     * @return The attribute value
     */
    public Object getAttribute(final Class sender, final Object object, final String attribute, final boolean useSuper, final boolean fromInsideClass) {
        checkInitalised();

        boolean isStatic = theClass != Class.class && object instanceof Class;
        if (isStatic && object != theClass) {
            MetaClass mc = registry.getMetaClass((Class) object);
            return mc.getAttribute(sender, object, attribute, useSuper);
        }

        MetaProperty mp = getMetaProperty(sender, attribute, useSuper, isStatic);

        if (mp != null) {
            if (mp instanceof MetaBeanProperty) {
                MetaBeanProperty mbp = (MetaBeanProperty) mp;
                mp = mbp.getField();
            }
            try {
                // delegate the get operation to the metaproperty
                if (mp != null) return mp.getProperty(object);
            } catch (Exception e) {
                throw new GroovyRuntimeException("Cannot read field: " + attribute, e);
            }
        }

        throw new MissingFieldException(attribute, !useSuper ? theClass : theClass.getSuperclass());
    }

    /**
     * <p>Sets an attribute on the given receiver for the specified arguments. The sender is the class that is setting the attribute from the object.
     * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
     *
     * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
     * to the super class if necessary
     *
     * @param sender          The java.lang.Class instance that is mutating the property
     * @param object          The Object which the property is being set on
     * @param attribute       The name of the attribute,
     * @param newValue        The new value of the attribute to set
     * @param useSuper        Whether the call is to a super class property
     * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
     */
    public void setAttribute(final Class sender, final Object object, final String attribute, final Object newValue, final boolean useSuper, final boolean fromInsideClass) {
        checkInitalised();

        boolean isStatic = theClass != Class.class && object instanceof Class;
        if (isStatic && object != theClass) {
            MetaClass mc = registry.getMetaClass((Class) object);
            mc.setAttribute(sender, object, attribute, newValue, useSuper, fromInsideClass);
            return;
        }

        MetaProperty mp = getMetaProperty(sender, attribute, useSuper, isStatic);

        if (mp != null) {
            if (mp instanceof MetaBeanProperty) {
                MetaBeanProperty mbp = (MetaBeanProperty) mp;
                mp = mbp.getField();
            }
            if (mp != null) {
                mp.setProperty(object, newValue);
                return;
            }
        }

        throw new MissingFieldException(attribute, !useSuper ? theClass : theClass.getSuperclass());
    }

    /**
     * Obtains a reference to the original AST for the MetaClass if it is available at runtime
     *
     * @return The original AST or null if it cannot be returned
     */
    public ClassNode getClassNode() {
        if (classNode == null && GroovyObject.class.isAssignableFrom(theClass)) {
            // let's try load it from the classpath
            String groovyFile = theClass.getName();
            int idx = groovyFile.indexOf('$');
            if (idx > 0) {
                groovyFile = groovyFile.substring(0, idx);
            }
            groovyFile = groovyFile.replace('.', '/') + ".groovy";

            //System.out.println("Attempting to load: " + groovyFile);
            URL url = theClass.getClassLoader().getResource(groovyFile);
            if (url == null) {
                url = Thread.currentThread().getContextClassLoader().getResource(groovyFile);
            }
            if (url != null) {
                try {

                    /*
                     * todo there is no CompileUnit in scope so class name
                     * checking won't work but that mostly affects the bytecode
                     * generation rather than viewing the AST
                     */
                    CompilationUnit.ClassgenCallback search = (writer, node) -> {
                        if (node.getName().equals(theClass.getName())) {
                            MetaClassImpl.this.classNode = node;
                        }
                    };

                    CompilationUnit unit = new CompilationUnit();
                    unit.setClassgenCallback(search);
                    unit.addSource(url);
                    unit.compile(Phases.CLASS_GENERATION);
                } catch (Exception e) {
                    throw new GroovyRuntimeException("Exception thrown parsing: " + groovyFile + ". Reason: " + e, e);
                }
            }

        }
        return classNode;
    }

    /**
     * Returns a string representation of this metaclass
     */
    public String toString() {
        return super.toString() + "[" + theClass + "]";
    }

    // Implementation methods
    //--------------------------------------------------------------------------

    /**
     * adds a MetaMethod to this class. WARNING: this method will not
     * do the neccessary steps for multimethod logic and using this
     * method doesn't mean, that a method added here is replacing another
     * method from a parent class completely. These steps are usually done
     * by initialize, which means if you need these steps, you have to add
     * the method before running initialize the first time.
     *
     * @param method the MetaMethod
     * @see #initialize()
     */
    public void addMetaMethod(MetaMethod method) {
        if (isInitialized()) {
            throw new RuntimeException("Already initialized, cannot add new method: " + method);
        }

        final CachedClass declaringClass = method.getDeclaringClass();
        addMetaMethodToIndex(method, metaMethodIndex.getHeader(declaringClass.getTheClass()));
    }

    protected void addMetaMethodToIndex(MetaMethod method, MetaMethodIndex.Header header) {
        checkIfStdMethod(method);

        String name = method.getName();
        MetaMethodIndex.Entry e = metaMethodIndex.getOrPutMethods(name, header);
        if (method.isStatic()) {
            e.staticMethods = metaMethodIndex.addMethodToList(e.staticMethods, method);
        }
        e.methods = metaMethodIndex.addMethodToList(e.methods, method);
    }

    /**
     * Checks if the metaMethod is a method from the GroovyObject interface such as setProperty, getProperty and invokeMethod
     *
     * @param metaMethod The metaMethod instance
     * @see GroovyObject
     */
    protected final void checkIfGroovyObjectMethod(MetaMethod metaMethod) {
        if (metaMethod instanceof ClosureMetaMethod || metaMethod instanceof MixinInstanceMetaMethod) {
            if (isGetPropertyMethod(metaMethod)) {
                getPropertyMethod = metaMethod;
            } else if (isInvokeMethod(metaMethod)) {
                invokeMethodMethod = metaMethod;
            } else if (isSetPropertyMethod(metaMethod)) {
                setPropertyMethod = metaMethod;
            }
        }
    }

    private static boolean isSetPropertyMethod(MetaMethod metaMethod) {
        return SET_PROPERTY_METHOD.equals(metaMethod.getName()) && metaMethod.getParameterTypes().length == 2;
    }

    private static boolean isGetPropertyMethod(MetaMethod metaMethod) {
        return GET_PROPERTY_METHOD.equals(metaMethod.getName());
    }

    private static boolean isInvokeMethod(MetaMethod metaMethod) {
        return INVOKE_METHOD_METHOD.equals(metaMethod.getName()) && metaMethod.getParameterTypes().length == 2;
    }

    private void checkIfStdMethod(MetaMethod method) {
        checkIfGroovyObjectMethod(method);

        if (isGenericGetMethod(method) && genericGetMethod == null) {
            genericGetMethod = method;
        } else if (MetaClassHelper.isGenericSetMethod(method) && genericSetMethod == null) {
            genericSetMethod = method;
        }
        if (method.getName().equals(PROPERTY_MISSING)) {
            CachedClass[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 1) {
                propertyMissingGet = method;
            }
        }
        if (propertyMissingSet == null && method.getName().equals(PROPERTY_MISSING)) {
            CachedClass[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 2) {
                propertyMissingSet = method;
            }
        }
        if (method.getName().equals(METHOD_MISSING)) {
            CachedClass[] parameterTypes = method.getParameterTypes();
            if (parameterTypes.length == 2
                    && parameterTypes[0].getTheClass() == String.class
                    && parameterTypes[1].getTheClass() == Object.class) {
                methodMissing = method;
            }
        }

        if (theCachedClass.isNumber) {
            NumberMathModificationInfo.instance.checkIfStdMethod(method);
        }
    }

    protected boolean isInitialized() {
        return initialized;
    }

    protected void setInitialized(boolean initialized) {
        this.initialized = initialized;
    }

    /**
     * @return {@code false}: add method
     *         {@code null} : ignore method
     *         {@code true} : replace
     */
    private static Boolean getMatchKindForCategory(MetaMethod aMethod, MetaMethod categoryMethod) {
        CachedClass[] params1 = aMethod.getParameterTypes();
        CachedClass[] params2 = categoryMethod.getParameterTypes();
        if (params1.length != params2.length) return Boolean.FALSE;

        for (int i = 0; i < params1.length; i++) {
            if (params1[i] != params2[i]) return Boolean.FALSE;
        }

        Class aMethodClass = aMethod.getDeclaringClass().getTheClass();
        Class categoryMethodClass = categoryMethod.getDeclaringClass().getTheClass();

        if (aMethodClass == categoryMethodClass) return Boolean.TRUE;
        boolean match = aMethodClass.isAssignableFrom(categoryMethodClass);
        if (match) return Boolean.TRUE;
        return null;
    }

    private static void filterMatchingMethodForCategory(FastArray list, MetaMethod method) {
        int len = list.size();
        if (len == 0) {
            list.add(method);
            return;
        }

        Object[] data = list.getArray();
        for (int j = 0; j != len; ++j) {
            MetaMethod aMethod = (MetaMethod) data[j];
            Boolean match = getMatchKindForCategory(aMethod, method);
            // true == replace
            if (Boolean.TRUE.equals(match)) {
                list.set(j, method);
                return;
                // null == ignore (we have a better method already)
            } else if (match == null) {
                return;
            }
        }
        // the casese true and null for a match are through, the
        // remaining case is false and that means adding the method
        // to our list
        list.add(method);
    }

    private int findMatchingMethod(CachedMethod[] data, int from, int to, MetaMethod method) {
        for (int j = from; j <= to; ++j) {
            CachedMethod aMethod = data[j];
            CachedClass[] params1 = aMethod.getParameterTypes();
            CachedClass[] params2 = method.getParameterTypes();
            if (params1.length == params2.length) {
                boolean matches = true;
                for (int i = 0; i < params1.length; i++) {
                    if (params1[i] != params2[i]) {
                        matches = false;
                        break;
                    }
                }
                if (matches) {
                    return j;
                }
            }
        }
        return -1;
    }

    /**
     * @return the matching method which should be found
     */
    private MetaMethod findMethod(CachedMethod aMethod) {
        Object methods = getMethods(theClass, aMethod.getName(), false);
        if (methods instanceof FastArray) {
            FastArray m = (FastArray) methods;
            final int len = m.size;
            final Object[] data = m.getArray();
            for (int i = 0; i != len; ++i) {
                MetaMethod method = (MetaMethod) data[i];
                if (method.isMethod(aMethod)) {
                    return method;
                }
            }
        } else {
            MetaMethod method = (MetaMethod) methods;
            if (method.getName().equals(aMethod.getName())
//                    TODO: should be better check for case when only diff in modifiers can be SYNTHETIC flag
//                    && method.getModifiers() == aMethod.getModifiers()
                    && method.getReturnType().equals(aMethod.getReturnType())
                    && MetaMethod.equal(method.getParameterTypes(), aMethod.getParameterTypes())) {
                return method;
            }
        }
        return aMethod;
    }

    /**
     * Chooses the correct method to use from a list of methods which match by
     * name.
     *
     * @param methodOrList the possible methods to choose from
     * @param arguments    the arguments
     */
    protected Object chooseMethod(String methodName, Object methodOrList, Class[] arguments) {
        Object method = chooseMethodInternal(methodName, methodOrList, arguments);
        if (method instanceof GeneratedMetaMethod.Proxy)
            return ((GeneratedMetaMethod.Proxy) method).proxy();
        return method;
    }

    private Object chooseMethodInternal(String methodName, Object methodOrList, Class[] arguments) {
        if (methodOrList instanceof MetaMethod) {
            if (((ParameterTypes) methodOrList).isValidMethod(arguments)) {
                return methodOrList;
            }
            return null;
        }

        FastArray methods = (FastArray) methodOrList;
        if (methods == null) return null;
        int methodCount = methods.size();
        if (methodCount <= 0) {
            return null;
        } else if (methodCount == 1) {
            Object method = methods.get(0);
            if (((ParameterTypes) method).isValidMethod(arguments)) {
                return method;
            }
            return null;
        }
        Object answer;
        if (arguments == null || arguments.length == 0) {
            answer = MetaClassHelper.chooseEmptyMethodParams(methods);
        } else {
            Object matchingMethods = null;

            final int len = methods.size;
            Object[] data = methods.getArray();
            for (int i = 0; i != len; ++i) {
                Object method = data[i];

                // making this false helps find matches
                if (((ParameterTypes) method).isValidMethod(arguments)) {
                    if (matchingMethods == null) {
                        matchingMethods = method;
                    } else if (matchingMethods instanceof ArrayList) {
                        ((ArrayList) matchingMethods).add(method);
                    } else {
                        List arr = new ArrayList(4);
                        arr.add(matchingMethods);
                        arr.add(method);
                        matchingMethods = arr;
                    }
                }
            }
            if (matchingMethods == null) {
                return null;
            } else if (!(matchingMethods instanceof ArrayList)) {
                return matchingMethods;
            }
            return chooseMostSpecificParams(methodName, (List) matchingMethods, arguments);

        }
        if (answer != null) {
            return answer;
        }
        throw new MethodSelectionException(methodName, methods, arguments);
    }

    private Object chooseMostSpecificParams(String name, List matchingMethods, Class[] arguments) {
        return doChooseMostSpecificParams(theClass.getName(), name, matchingMethods, arguments, false);
    }

    protected static Object doChooseMostSpecificParams(String theClassName, String name, List matchingMethods, Class[] arguments, boolean checkParametersCompatible) {
        long matchesDistance = -1;
        LinkedList matches = new LinkedList();
        for (Object method : matchingMethods) {
            final ParameterTypes parameterTypes = (ParameterTypes) method;
            if (checkParametersCompatible && !MetaClassHelper.parametersAreCompatible(arguments, parameterTypes.getNativeParameterTypes()))
                continue;
            long dist = MetaClassHelper.calculateParameterDistance(arguments, parameterTypes);
            if (dist == 0) return method;
            matchesDistance = handleMatches(matchesDistance, matches, method, dist);
        }

        int size = matches.size();
        if (1 == size) {
            return matches.getFirst();
        }
        if (0 == size) {
            return null;
        }

        //more than one matching method found --> ambiguous!
        throw new GroovyRuntimeException(createErrorMessageForAmbiguity(theClassName, name, arguments, matches));
    }

    protected static String createErrorMessageForAmbiguity(String theClassName, String name, Class[] arguments, LinkedList matches) {
        StringBuilder msg = new StringBuilder("Ambiguous method overloading for method ");
        msg.append(theClassName).append("#").append(name)
                .append(".\nCannot resolve which method to invoke for ")
                .append(InvokerHelper.toString(arguments))
                .append(" due to overlapping prototypes between:");
        for (final Object match : matches) {
            CachedClass[] types = ((ParameterTypes) match).getParameterTypes();
            msg.append("\n\t").append(InvokerHelper.toString(types));
        }
        return msg.toString();
    }

    protected static long handleMatches(long matchesDistance, LinkedList matches, Object method, long dist) {
        if (matches.isEmpty()) {
            matches.add(method);
            matchesDistance = dist;
        } else if (dist < matchesDistance) {
            matchesDistance = dist;
            matches.clear();
            matches.add(method);
        } else if (dist == matchesDistance) {
            matches.add(method);
        }
        return matchesDistance;
    }

    private static boolean isGenericGetMethod(MetaMethod method) {
        if (method.getName().equals("get")) {
            CachedClass[] parameterTypes = method.getParameterTypes();
            return parameterTypes.length == 1 && parameterTypes[0].getTheClass() == String.class;
        }
        return false;
    }

    /**
     * Complete the initialisation process. After this method
     * is called no methods should be added to the meta class.
     * Invocation of methods or access to fields/properties is
     * forbidden unless this method is called. This method
     * should contain any initialisation code, taking a longer
     * time to complete. An example is the creation of the
     * Reflector. It is suggested to synchronize this
     * method.
     */
    public synchronized void initialize() {
        if (!isInitialized()) {
            fillMethodIndex();
            try {
                addProperties();
            } catch (Throwable e) {
                if (!AndroidSupport.isRunningAndroid()) {
                    UncheckedThrow.rethrow(e);
                }
                // Introspection failure...
                // May happen in Android
            }
            setInitialized(true);
        }
    }

    private void addProperties() {
        BeanInfo info;
        //     introspect
        try {
            if (isBeanDerivative(theClass)) {
                info = (BeanInfo) AccessController.doPrivileged((PrivilegedExceptionAction) () -> Introspector.getBeanInfo(theClass, Introspector.IGNORE_ALL_BEANINFO));
            } else {
                info = (BeanInfo) AccessController.doPrivileged((PrivilegedExceptionAction) () -> Introspector.getBeanInfo(theClass));
            }
        } catch (PrivilegedActionException pae) {
            throw new GroovyRuntimeException("exception during bean introspection", pae.getException());
        }
        PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
        // build up the metaproperties based on the public fields, property descriptors,
        // and the getters and setters
        setupProperties(descriptors);

        EventSetDescriptor[] eventDescriptors = info.getEventSetDescriptors();
        for (EventSetDescriptor descriptor : eventDescriptors) {
            Method[] listenerMethods = descriptor.getListenerMethods();
            for (Method listenerMethod : listenerMethods) {
                final MetaMethod metaMethod = CachedMethod.find(descriptor.getAddListenerMethod());
                // GROOVY-5202
                // there might be a non public listener of some kind
                // we skip that here
                if (metaMethod == null) continue;
                addToAllMethodsIfPublic(metaMethod);
                String name = listenerMethod.getName();
                if (listeners.containsKey(name)) {
                    listeners.put(name, AMBIGUOUS_LISTENER_METHOD);
                } else {
                    listeners.put(name, metaMethod);
                }
            }
        }
    }

    private static boolean isBeanDerivative(Class theClass) {
        Class next = theClass;
        while (next != null) {
            if (Arrays.asList(next.getInterfaces()).contains(BeanInfo.class)) return true;
            next = next.getSuperclass();
        }
        return false;
    }

    private void addToAllMethodsIfPublic(MetaMethod metaMethod) {
        if (Modifier.isPublic(metaMethod.getModifiers()))
            allMethods.add(metaMethod);
    }

    /**
     * Retrieves the list of MetaMethods held by the class. This list does not include MetaMethods added by groovy.lang.ExpandoMetaClass.
     *
     * @return A list of MetaMethods
     */
    public List<MetaMethod> getMethods() {
        return allMethods;
    }

    /**
     * Retrieves the list of MetaMethods held by this class. This list includes MetaMethods added by groovy.lang.ExpandoMetaClass.
     *
     * @return A list of MetaMethods
     */
    public List<MetaMethod> getMetaMethods() {
        return new ArrayList<>(newGroovyMethodsSet);
    }

    protected void dropStaticMethodCache(String name) {
        metaMethodIndex.clearCaches(name);
    }

    protected void dropMethodCache(String name) {
        metaMethodIndex.clearCaches(name);
    }

    /**
     * Create a CallSite
     */
    public CallSite createPojoCallSite(CallSite site, Object receiver, Object[] args) {
        if (!(this instanceof AdaptingMetaClass)) {
            Class[] params = MetaClassHelper.convertToTypeArray(args);
            MetaMethod metaMethod = getMethodWithCachingInternal(getTheClass(), site, params);
            if (metaMethod != null)
                return PojoMetaMethodSite.createPojoMetaMethodSite(site, this, metaMethod, params, receiver, args);
        }
        return new PojoMetaClassSite(site, this);
    }

    /**
     * Create a CallSite
     */
    public CallSite createStaticSite(CallSite site, Object[] args) {
        if (!(this instanceof AdaptingMetaClass)) {
            Class[] params = MetaClassHelper.convertToTypeArray(args);
            MetaMethod metaMethod = retrieveStaticMethod(site.getName(), args);
            if (metaMethod != null)
                return StaticMetaMethodSite.createStaticMetaMethodSite(site, this, metaMethod, params, args);
        }
        return new StaticMetaClassSite(site, this);
    }

    /**
     * Create a CallSite
     */
    public CallSite createPogoCallSite(CallSite site, Object[] args) {
        if (!GroovyCategorySupport.hasCategoryInCurrentThread() && !(this instanceof AdaptingMetaClass)) {
            Class[] params = MetaClassHelper.convertToTypeArray(args);
            CallSite tempSite = site;
            if (site.getName().equals("call") && GeneratedClosure.class.isAssignableFrom(theClass)) {
                // here, we want to point to a method named "doCall" instead of "call"
                // but we don't want to replace the original call site name, otherwise
                // we loose the fact that the original method name was "call" so instead
                // we will point to a metamethod called "doCall"
                // see GROOVY-5806 for details
                tempSite = new AbstractCallSite(site.getArray(), site.getIndex(), "doCall");
            }
            MetaMethod metaMethod = getMethodWithCachingInternal(theClass, tempSite, params);
            if (metaMethod != null)
                return PogoMetaMethodSite.createPogoMetaMethodSite(site, this, metaMethod, params, args);
        }
        return new PogoMetaClassSite(site, this);
    }

    /**
     * Create a CallSite
     */
    public CallSite createPogoCallCurrentSite(CallSite site, Class sender, Object[] args) {
        if (!GroovyCategorySupport.hasCategoryInCurrentThread() && !(this instanceof AdaptingMetaClass)) {
            Class[] params = MetaClassHelper.convertToTypeArray(args);
            MetaMethod metaMethod = getMethodWithCachingInternal(sender, site, params);
            if (metaMethod != null)
                return PogoMetaMethodSite.createPogoMetaMethodSite(site, this, metaMethod, params, args);
        }
        return new PogoMetaClassSite(site, this);
    }

    /**
     * Create a CallSite
     */
    public CallSite createConstructorSite(CallSite site, Object[] args) {
        if (!(this instanceof AdaptingMetaClass)) {
            Class[] params = MetaClassHelper.convertToTypeArray(args);
            CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, params);
            if (constructor != null) {
                return ConstructorSite.createConstructorSite(site, this, constructor, params, args);
            } else {
                if (args.length == 1 && args[0] instanceof Map) {
                    constructor = (CachedConstructor) chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
                    if (constructor != null) {
                        return new ConstructorSite.NoParamSite(site, this, constructor, params);
                    }
                } else if (args.length == 2 && theClass.getEnclosingClass() != null && args[1] instanceof Map) {
                    Class enclosingClass = theClass.getEnclosingClass();
                    String enclosingInstanceParamType = args[0] != null ? args[0].getClass().getName() : "";
                    if (enclosingClass.getName().equals(enclosingInstanceParamType)) {
                        constructor = (CachedConstructor) chooseMethod("<init>", constructors, new Class[]{enclosingClass});
                        if (constructor != null) {
                            return new ConstructorSite.NoParamSiteInnerClass(site, this, constructor, params);
                        }
                    }
                }
            }
        }
        return new MetaClassConstructorSite(site, this);
    }

    /**
     * Returns the ClassInfo for the contained Class
     *
     * @return The ClassInfo for the contained class.
     */
    public ClassInfo getClassInfo() {
        return theCachedClass.classInfo;
    }

    /**
     * Returns version of the contained Class
     *
     * @return The version of the contained class.
     */
    public int getVersion() {
        return theCachedClass.classInfo.getVersion();
    }

    /**
     * Increments version of the contained Class
     */
    public void incVersion() {
        theCachedClass.classInfo.incVersion();
    }

    /**
     * Retrieves a list of additional MetaMethods held by this class
     *
     * @return A list of MetaMethods
     */
    public MetaMethod[] getAdditionalMetaMethods() {
        return additionalMetaMethods;
    }

    protected MetaBeanProperty findPropertyInClassHierarchy(String propertyName, CachedClass theClass) {
        MetaBeanProperty property = null;
        if (theClass == null)
            return null;

        final CachedClass superClass = theClass.getCachedSuperClass();
        if (superClass == null)
            return null;

        MetaClass metaClass = this.registry.getMetaClass(superClass.getTheClass());
        if (metaClass instanceof MutableMetaClass) {
            property = getMetaPropertyFromMutableMetaClass(propertyName, metaClass);
            if (property == null) {
                if (superClass != ReflectionCache.OBJECT_CLASS) {
                    property = findPropertyInClassHierarchy(propertyName, superClass);
                }
                if (property == null) {
                    final Class[] interfaces = theClass.getTheClass().getInterfaces();
                    property = searchInterfacesForMetaProperty(propertyName, interfaces);
                }
            }
        }
        return property;

    }

    private MetaBeanProperty searchInterfacesForMetaProperty(String propertyName, Class[] interfaces) {
        MetaBeanProperty property = null;
        for (Class anInterface : interfaces) {
            MetaClass metaClass = registry.getMetaClass(anInterface);
            if (metaClass instanceof MutableMetaClass) {
                property = getMetaPropertyFromMutableMetaClass(propertyName, metaClass);
                if (property != null) break;
            }
            Class[] superInterfaces = anInterface.getInterfaces();
            if (superInterfaces.length > 0) {
                property = searchInterfacesForMetaProperty(propertyName, superInterfaces);
                if (property != null) break;
            }

        }
        return property;
    }

    private static MetaBeanProperty getMetaPropertyFromMutableMetaClass(String propertyName, MetaClass metaClass) {
        final boolean isModified = ((MutableMetaClass) metaClass).isModified();
        if (isModified) {
            final MetaProperty metaProperty = metaClass.getMetaProperty(propertyName);
            if (metaProperty instanceof MetaBeanProperty)
                return (MetaBeanProperty) metaProperty;
        }
        return null;
    }

    protected MetaMethod findMixinMethod(String methodName, Class[] arguments) {
        return null;
    }

    protected static MetaMethod findMethodInClassHierarchy(Class instanceKlazz, String methodName, Class[] arguments, MetaClass metaClass) {

        if (metaClass instanceof MetaClassImpl) {
            boolean check = false;
            for (ClassInfo ci : ((MetaClassImpl) metaClass).theCachedClass.getHierarchy()) {
                final MetaClass aClass = ci.getStrongMetaClass();
                if (aClass instanceof MutableMetaClass && ((MutableMetaClass) aClass).isModified()) {
                    check = true;
                    break;
                }
            }

            if (!check)
                return null;
        }

        MetaMethod method = null;

        Class superClass;
        if (metaClass.getTheClass().isArray() && !metaClass.getTheClass().getComponentType().isPrimitive() && metaClass.getTheClass().getComponentType() != Object.class) {
            superClass = Object[].class;
        } else {
            superClass = metaClass.getTheClass().getSuperclass();
        }

        if (superClass != null) {
            MetaClass superMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(superClass);
            method = findMethodInClassHierarchy(instanceKlazz, methodName, arguments, superMetaClass);
        } else {
            if (metaClass.getTheClass().isInterface()) {
                MetaClass superMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(Object.class);
                method = findMethodInClassHierarchy(instanceKlazz, methodName, arguments, superMetaClass);
            }
        }

        method = findSubClassMethod(instanceKlazz, methodName, arguments, metaClass, method);

        method = getMetaMethod(instanceKlazz, methodName, arguments, metaClass, method);

        method = findOwnMethod(instanceKlazz, methodName, arguments, metaClass, method);

        return method;
    }

    private static MetaMethod getMetaMethod(Class instanceKlazz, String methodName, Class[] arguments, MetaClass metaClass, MetaMethod method) {
        MetaMethod infMethod = searchInterfacesForMetaMethod(instanceKlazz, methodName, arguments, metaClass);
        if (infMethod != null) {
            method = (method == null ? infMethod : mostSpecific(method, infMethod, instanceKlazz));
        }
        return method;
    }

    private static MetaMethod findSubClassMethod(Class instanceKlazz, String methodName, Class[] arguments, MetaClass metaClass, MetaMethod method) {
        if (metaClass instanceof MetaClassImpl) {
            Object list = ((MetaClassImpl) metaClass).getSubclassMetaMethods(methodName);
            if (list != null) {
                if (list instanceof MetaMethod) {
                    MetaMethod m = (MetaMethod) list;
                    method = findSubClassMethod(instanceKlazz, arguments, method, m);
                } else {
                    FastArray arr = (FastArray) list;
                    for (int i = 0; i != arr.size(); ++i) {
                        MetaMethod m = (MetaMethod) arr.get(i);
                        method = findSubClassMethod(instanceKlazz, arguments, method, m);
                    }
                }
            }
        }
        return method;
    }

    private static MetaMethod findSubClassMethod(Class instanceKlazz, Class[] arguments, MetaMethod method, MetaMethod m) {
        if (m.getDeclaringClass().getTheClass().isAssignableFrom(instanceKlazz) && m.isValidExactMethod(arguments)) {
            method = (method == null ? m : mostSpecific(method, m, instanceKlazz));
        }
        return method;
    }

    private static MetaMethod mostSpecific(MetaMethod method, MetaMethod newMethod, Class instanceKlazz) {
        Class newMethodC = newMethod.getDeclaringClass().getTheClass();
        Class methodC = method.getDeclaringClass().getTheClass();

        if (!newMethodC.isAssignableFrom(instanceKlazz))
            return method;

        if (newMethodC == methodC)
            return newMethod;

        if (newMethodC.isAssignableFrom(methodC)) {
            return method;
        }

        if (methodC.isAssignableFrom(newMethodC)) {
            return newMethod;
        }

        return newMethod;
    }

    private static MetaMethod searchInterfacesForMetaMethod(Class instanceKlazz, String methodName, Class[] arguments, MetaClass metaClass) {
        Class[] interfaces = metaClass.getTheClass().getInterfaces();

        MetaMethod method = null;
        for (Class anInterface : interfaces) {
            MetaClass infMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(anInterface);
            method = getMetaMethod(instanceKlazz, methodName, arguments, infMetaClass, method);
        }

        method = findSubClassMethod(instanceKlazz, methodName, arguments, metaClass, method);

        method = findOwnMethod(instanceKlazz, methodName, arguments, metaClass, method);

        return method;
    }

    protected static MetaMethod findOwnMethod(Class instanceKlazz, String methodName, Class[] arguments, MetaClass metaClass, MetaMethod method) {
        // we trick ourselves here
        if (instanceKlazz != metaClass.getTheClass()) {
            MetaMethod ownMethod = metaClass.pickMethod(methodName, arguments);
            if (ownMethod != null) {
                method = (method == null ? ownMethod : mostSpecific(method, ownMethod, instanceKlazz));
            }
        }
        return method;
    }

    protected Object getSubclassMetaMethods(String methodName) {
        return null;
    }

    private abstract class MethodIndexAction {
        public void iterate() {
            final ComplexKeyHashMap.Entry[] table = metaMethodIndex.methodHeaders.getTable();
            int len = table.length;
            for (int i = 0; i != len; ++i) {
                for (SingleKeyHashMap.Entry classEntry = (SingleKeyHashMap.Entry) table[i];
                     classEntry != null;
                     classEntry = (SingleKeyHashMap.Entry) classEntry.next) {

                    Class clazz = (Class) classEntry.getKey();

                    if (skipClass(clazz)) continue;

                    MetaMethodIndex.Header header = (MetaMethodIndex.Header) classEntry.getValue();
                    for (MetaMethodIndex.Entry nameEntry = header.head; nameEntry != null; nameEntry = nameEntry.nextClassEntry) {
                        methodNameAction(clazz, nameEntry);
                    }
                }
            }
        }

        public abstract void methodNameAction(Class clazz, MetaMethodIndex.Entry methods);

        public boolean skipClass(Class clazz) {
            return false;
        }
    }

    /**
     * <p>Retrieves a property on the given object for the specified arguments.
     *
     * @param object   The Object which the property is being retrieved from
     * @param property The name of the property
     * @return The properties value
     */
    public Object getProperty(Object object, String property) {
        return getProperty(theClass, object, property, false, false);
    }

    /**
     * <p>Sets a property on the given object for the specified arguments.
     *
     * @param object   The Object which the property is being retrieved from
     * @param property The name of the property
     * @param newValue The new value
     */
    public void setProperty(Object object, String property, Object newValue) {
        setProperty(theClass, object, property, newValue, false, false);
    }

    /**
     * Retrieves the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
     *
     * @param object    The object to get the attribute from
     * @param attribute The name of the attribute
     * @return The attribute value
     */
    public Object getAttribute(final Object object, final String attribute) {
        return getAttribute(theClass, object, attribute, false, false);
    }

    /**
     * Sets the value of an attribute (field). This method is to support the Groovy runtime and not for general client API usage.
     *
     * @param object    The object to get the attribute from
     * @param attribute The name of the attribute
     * @param newValue  The new value of the attribute
     */
    public void setAttribute(final Object object, final String attribute, final Object newValue) {
        setAttribute(theClass, object, attribute, newValue, false, false);
    }

    /**
     * Selects a method by name and argument classes. This method
     * does not search for an exact match, it searches for a compatible
     * method. For this the method selection mechanism is used as provided
     * by the implementation of this MetaClass. pickMethod may or may
     * not be used during the method selection process when invoking a method.
     * There is no warranty for that.
     *
     * @param methodName the name of the method to pick
     * @param arguments  the method arguments
     * @return a matching MetaMethod or null
     * @throws GroovyRuntimeException if there is more than one matching method
     */
    public MetaMethod pickMethod(String methodName, Class[] arguments) {
        return getMethodWithoutCaching(theClass, methodName, arguments, false);
    }

    /**
     * indicates is the meta class method invocation for non-static methods is done
     * through a custom invoker object.
     *
     * @return true - if the method invocation is not done by the meta class itself
     */
    public boolean hasCustomInvokeMethod() {
        return invokeMethodMethod != null;
    }

    /**
     * indicates is the meta class method invocation for static methods is done
     * through a custom invoker object.
     *
     * @return true - if the method invocation is not done by the meta class itself
     */
    public boolean hasCustomStaticInvokeMethod() {
        return false;
    }

    /**
     * remove all method call cache entries. This should be done if a
     * method is added during runtime, but not by using a category.
     */
    protected void clearInvocationCaches() {
        metaMethodIndex.clearCaches();
    }

    private static final SingleKeyHashMap.Copier NAME_INDEX_COPIER = value -> {
        if (value instanceof FastArray) {
            return ((FastArray) value).copy();
        } else {
            return value;
        }
    };

    private static final SingleKeyHashMap.Copier METHOD_INDEX_COPIER = value -> SingleKeyHashMap.copy(new SingleKeyHashMap(false), (SingleKeyHashMap) value, NAME_INDEX_COPIER);

    static class MethodIndex extends Index {
        public MethodIndex(boolean b) {
            super(false);
        }

        public MethodIndex(int size) {
            super(size);
        }

        public MethodIndex() {
            super();
        }

        MethodIndex copy() {
            return (MethodIndex) SingleKeyHashMap.copy(new MethodIndex(false), this, METHOD_INDEX_COPIER);
        }

        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

    public static class Index extends SingleKeyHashMap {

        public Index(int size) {
        }

        public Index() {
        }

        public Index(boolean size) {
            super(false);
        }

        public SingleKeyHashMap getNotNull(CachedClass key) {
            Entry res = getOrPut(key);
            if (res.value == null) {
                res.value = new SingleKeyHashMap();
            }
            return (SingleKeyHashMap) res.value;
        }

        public void put(CachedClass key, SingleKeyHashMap value) {
            getOrPut(key).value = value;
        }

        public SingleKeyHashMap getNullable(CachedClass clazz) {
            return (SingleKeyHashMap) get(clazz);
        }

        public boolean checkEquals(ComplexKeyHashMap.Entry e, Object key) {
            return ((Entry) e).key.equals(key);
        }
    }

    private static class DummyMetaMethod extends MetaMethod {

        public int getModifiers() {
            return 0;
        }

        public String getName() {
            return null;
        }

        public Class getReturnType() {
            return null;
        }

        public CachedClass getDeclaringClass() {
            return null;
        }

        public ParameterTypes getParamTypes() {
            return null;
        }

        public Object invoke(Object object, Object[] arguments) {
            return null;
        }
    }

    private Tuple2<Object, MetaMethod> invokeMethod(MetaMethod method,
                                                    Object delegate,
                                                    Closure closure,
                                                    String methodName,
                                                    Class[] argClasses,
                                                    Object[] originalArguments,
                                                    Object owner) {
        if (method == null && delegate != closure && delegate != null) {
            MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
            method = delegateMetaClass.pickMethod(methodName, argClasses);
            if (method != null)
                return new Tuple2<>(delegateMetaClass.invokeMethod(delegate, methodName, originalArguments), method);
        }
        if (method == null && owner != closure) {
            MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
            method = ownerMetaClass.pickMethod(methodName, argClasses);
            if (method != null)
                return new Tuple2<>(ownerMetaClass.invokeMethod(owner, methodName, originalArguments), method);
        }

        return new Tuple2<>(InvokeMethodResult.NONE, method);
    }

    private enum InvokeMethodResult {
        NONE
    }

    public boolean isPermissivePropertyAccess() {
        return permissivePropertyAccess;
    }

    public void setPermissivePropertyAccess(boolean permissivePropertyAccess) {
        this.permissivePropertyAccess = permissivePropertyAccess;
    }
}
