Package com.alibaba.citrus.generictype.impl

Source Code of com.alibaba.citrus.generictype.impl.MethodImpl

/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* 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 com.alibaba.citrus.generictype.impl;

import static com.alibaba.citrus.generictype.codegen.TypeUtil.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static java.lang.reflect.Modifier.*;
import static java.util.Collections.*;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.alibaba.citrus.generictype.ClassTypeInfo;
import com.alibaba.citrus.generictype.GenericDeclarationInfo;
import com.alibaba.citrus.generictype.MethodInfo;
import com.alibaba.citrus.generictype.TypeInfo;
import com.alibaba.citrus.generictype.TypeVariableInfo;
import com.alibaba.citrus.generictype.codegen.MethodSignature;

/**
* 对{@link MethodInfo}的实现。
*
* @author Michael Zhou
*/
class MethodImpl extends AbstractGenericDeclarationInfo implements MethodInfo {
    private final static int MODIFIERS_MASK = PRIVATE | PUBLIC | PROTECTED | STATIC;
    private final MethodSignature signature;
    private final int             modifiers;
    private       ClassTypeInfo   declaringType;
    private       TypeInfo        returnType;
    private       List<TypeInfo>  parameterTypes;
    private       List<TypeInfo>  exceptionTypes;
    private       List<TypeInfo>  effectiveExceptionTypes;

    MethodImpl(Method method) {
        super(method);

        this.signature = getMethodSignature(method);
        this.modifiers = method.getModifiers() & MODIFIERS_MASK;
    }

    MethodImpl(Constructor<?> constructor) {
        super(constructor);

        this.signature = getConstructorSignature(constructor);
        this.modifiers = constructor.getModifiers() & MODIFIERS_MASK;
    }

    void init(TypeVariableInfo[] vars, TypeInfo returnType, TypeInfo[] parameterTypes, TypeInfo[] exceptionTypes,
              ClassTypeInfo declaringType) {
        super.init(vars);

        this.declaringType = declaringType;
        this.returnType = returnType;
        this.parameterTypes = unmodifiableList(asList(parameterTypes));
        this.exceptionTypes = unmodifiableList(asList(exceptionTypes));
        this.effectiveExceptionTypes = getEffectiveExceptionTypes(exceptionTypes);
    }

    /**
     * 忽略unchecked exception:RuntimeException, Error,<br>
     * 排除异常的子类,例如:Exception和IOException同时出现,则删除IOException。
     */
    private List<TypeInfo> getEffectiveExceptionTypes(TypeInfo[] exceptionTypes) {
        ArrayList<TypeInfo> effectiveExceptions = createArrayList(exceptionTypes.length);

        for (TypeInfo exception : exceptionTypes) {
            if (RuntimeException.class.isAssignableFrom(exception.getRawType())
                || Error.class.isAssignableFrom(exception.getRawType())) {
                continue;
            }

            for (Iterator<TypeInfo> j = effectiveExceptions.iterator(); j.hasNext(); ) {
                TypeInfo existing = j.next();

                if (exception.getRawType().isAssignableFrom(existing.getRawType())) {
                    j.remove();
                } else if (existing.getRawType().isAssignableFrom(exception.getRawType())) {
                    exception = null;
                    break;
                }
            }

            if (exception != null) {
                effectiveExceptions.add(exception);
            }
        }

        effectiveExceptions.trimToSize();

        return unmodifiableList(effectiveExceptions);
    }

    public boolean isConstructor() {
        return declaration instanceof Constructor<?>;
    }

    public Constructor<?> getConstructor() {
        if (isConstructor()) {
            return (Constructor<?>) declaration;
        }

        return null;
    }

    public Method getMethod() {
        if (!isConstructor()) {
            return (Method) declaration;
        }

        return null;
    }

    public TypeInfo getDeclaringType() {
        return declaringType;
    }

    public MethodSignature getSignature() {
        return signature;
    }

    public int getModifiers() {
        return modifiers;
    }

    public TypeInfo getReturnType() {
        return returnType;
    }

    public String getName() {
        return signature.getName();
    }

    public List<TypeInfo> getParameterTypes() {
        return parameterTypes;
    }

    public List<TypeInfo> getExceptionTypes() {
        return exceptionTypes;
    }

    public List<TypeInfo> getEffectiveExceptionTypes() {
        return effectiveExceptionTypes;
    }

    public MethodInfo resolve(GenericDeclarationInfo context) {
        return resolve(context, true);
    }

    public MethodInfo resolve(GenericDeclarationInfo context, boolean includeBaseType) {
        if (context == null) {
            context = declaringType;
        }

        boolean changed = false;

        TypeInfo[] parameterTypes = new TypeInfo[this.parameterTypes.size()];
        TypeInfo[] exceptionTypes = new TypeInfo[this.exceptionTypes.size()];

        changed |= resolveTypes(this.parameterTypes, parameterTypes, context, includeBaseType);
        changed |= resolveTypes(this.exceptionTypes, exceptionTypes, context, includeBaseType);

        TypeInfo returnType = this.returnType.resolve(context, includeBaseType);

        if (returnType != this.returnType) {
            changed = true;
        }

        MethodImpl resolvedMethod;

        if (changed) {
            if (isConstructor()) {
                resolvedMethod = new MethodImpl(getConstructor());
            } else {
                resolvedMethod = new MethodImpl(getMethod());
            }

            TypeVariableInfo[] vars = getTypeParameters().toArray(new TypeVariableInfo[getTypeParameters().size()]);

            resolvedMethod.init(vars, returnType, parameterTypes, exceptionTypes, declaringType);
        } else {
            resolvedMethod = this;
        }

        return resolvedMethod;
    }

    private boolean resolveTypes(List<TypeInfo> types, TypeInfo[] resolvedTypes, GenericDeclarationInfo context,
                                 boolean includeBaseType) {
        boolean changed = false;

        for (int i = 0; i < resolvedTypes.length; i++) {
            TypeInfo type = types.get(i);
            TypeInfo resolvedType = type.resolve(context, includeBaseType);

            if (type != resolvedType) {
                changed = true;
            }

            resolvedTypes[i] = resolvedType;
        }

        return changed;
    }

    @Override
    public String toString() {
        StringBuilder buf = new StringBuilder();

        appendIfNotEmpty(buf, Modifier.toString(modifiers), " ");

        if (appendTypeParameters(buf) > 0) {
            buf.append(" ");
        }

        if (!isConstructor()) {
            buf.append(returnType).append(" ");
            buf.append(declaringType.getSimpleName());
            buf.append(".").append(getName());
        } else {
            buf.append(declaringType.getSimpleName());
        }

        buf.append("(");
        join(buf, parameterTypes, ", ");
        buf.append(")");

        if (!effectiveExceptionTypes.isEmpty()) {
            buf.append(" throws ");
            join(buf, effectiveExceptionTypes, ", ");
        }

        return buf.toString();
    }

    private void appendIfNotEmpty(StringBuilder buf, String str, String sep) {
        if (str.length() > 0) {
            buf.append(str).append(sep);
        }
    }
}
TOP

Related Classes of com.alibaba.citrus.generictype.impl.MethodImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.