/* * 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); } } }