org.codehaus.groovy.grails.commons.metaclass.BaseApiProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.groovy.grails.commons.metaclass.BaseApiProvider.java

Source

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

import groovy.lang.GString;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.codehaus.groovy.grails.commons.GrailsClassUtils;
import org.codehaus.groovy.reflection.CachedClass;
import org.codehaus.groovy.reflection.CachedMethod;
import org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod;

/**
 * @author Graeme Rocher
 * @since 2.0
 */
public abstract class BaseApiProvider {

    private static List<String> EXCLUDED_METHODS = Arrays.asList("setMetaClass", "getMetaClass");

    public static final String CONSTRUCTOR_METHOD = "initialize";
    public static final String CTOR_GROOVY_METHOD = "<ctor>";

    @SuppressWarnings("rawtypes")
    protected List instanceMethods = new ArrayList();
    protected List<Method> staticMethods = new ArrayList<Method>();
    protected List<Method> constructors = new ArrayList<Method>();

    @SuppressWarnings("unchecked")
    public void addApi(final Object apiInstance) {
        if (apiInstance == null) {
            return;
        }

        Class<?> currentClass = apiInstance.getClass();
        while (currentClass != Object.class) {
            final Method[] declaredMethods = currentClass.getDeclaredMethods();

            for (final Method javaMethod : declaredMethods) {
                final int modifiers = javaMethod.getModifiers();
                if (!isNotExcluded(javaMethod, modifiers)) {
                    continue;
                }

                if (Modifier.isStatic(modifiers)) {
                    if (isConstructorCallMethod(javaMethod)) {
                        constructors.add(javaMethod);
                    } else {
                        staticMethods.add(javaMethod);
                    }
                } else {
                    instanceMethods.add(new ReflectionMetaMethod(new CachedMethod(javaMethod)) {
                        @Override
                        public String getName() {

                            String methodName = super.getName();
                            if (isConstructorCallMethod(javaMethod)) {
                                return CTOR_GROOVY_METHOD;
                            }
                            return methodName;
                        }

                        @Override
                        public Object invoke(Object object, Object[] arguments) {
                            if (arguments.length == 0) {
                                return super.invoke(apiInstance, new Object[] { object });
                            }
                            return super.invoke(apiInstance,
                                    ArrayUtils.add(checkForGStrings(arguments), 0, object));
                        }

                        private Object[] checkForGStrings(Object[] arguments) {
                            for (int i = 0; i < arguments.length; i++) {
                                if (arguments[i] instanceof GString) {
                                    arguments[i] = arguments[i].toString();
                                }
                            }
                            return arguments;
                        }

                        @Override
                        public CachedClass[] getParameterTypes() {
                            final CachedClass[] paramTypes = method.getParameterTypes();
                            if (paramTypes.length > 0) {
                                return (CachedClass[]) ArrayUtils.subarray(paramTypes, 1, paramTypes.length);
                            }
                            return paramTypes;
                        }
                    });
                }
            }
            currentClass = currentClass.getSuperclass();
        }
    }

    private boolean isConstructorCallMethod(Method method) {
        return method != null && Modifier.isStatic(method.getModifiers())
                && Modifier.isPublic(method.getModifiers()) && method.getName().equals(CONSTRUCTOR_METHOD)
                && method.getParameterTypes().length > 0;
    }

    private boolean isNotExcluded(Method method, final int modifiers) {
        final String name = method.getName();

        if (EXCLUDED_METHODS.contains(name))
            return false;

        boolean isStatic = Modifier.isStatic(modifiers);

        // skip plain setters/getters by default for instance methods (non-static)
        if (!isStatic && (GrailsClassUtils.isSetter(name, method.getParameterTypes())
                || GrailsClassUtils.isGetter(name, method.getParameterTypes()))) {
            return false;
        }

        int minParameters = isStatic ? 0 : 1;

        return Modifier.isPublic(modifiers) && !(method.isSynthetic() || method.isBridge())
                && !Modifier.isAbstract(modifiers) && !name.contains("$")
                && (method.getParameterTypes().length >= minParameters);
    }
}