/* * 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.introspect.impl; import static com.alibaba.citrus.generictype.TypeInfo.*; import static com.alibaba.citrus.util.internal.StringUtil.*; import static java.lang.reflect.Modifier.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import com.alibaba.citrus.generictype.MethodInfo; import com.alibaba.citrus.generictype.TypeInfo; import com.alibaba.citrus.generictype.introspect.MappedPropertyInfo; import com.alibaba.citrus.generictype.introspect.PropertyEvaluationFailureException; import com.alibaba.citrus.generictype.introspect.PropertyInfo; /** * 分析mapped的Java Beans属性,也就是: * <ul> * <li>可读属性:<code>PropertyType getPropertyName(String key)</code>。</li> * <li>可写属性: * <code>setPropertyName(String key, PropertyType propertyValue)</code>。</li> * </ul> * <p> * Mapped的Java Beans属性的名称可以为空,换言之,<code>get(String)</code>/ * <code>set(String, Object)</code> 方法将会被看作一个property。 * </p> * * @author Michael Zhou */ public class MappedPropertiesFinder extends AbstractPropertiesFinder { @Override public void visitMethod(Method method) { if (getAccessQualifier(method) != PUBLIC) { return; } String name = method.getName(); Class<?>[] paramTypes = method.getParameterTypes(); Class<?> returnType = method.getReturnType(); int paramCount = paramTypes.length; PropertyInfo prop = null; switch (paramCount) { case 1: if (paramTypes[0] == String.class && name.startsWith(GET_PREFIX)) { if (returnType != void.class) { String propName = uncapitalize(name.substring(GET_PREFIX_LENGTH)); prop = createMappedProperty(method, propName, true, -1); } } break; case 2: if (paramTypes[0] == String.class && name.startsWith(SET_PREFIX)) { String propName = uncapitalize(name.substring(SET_PREFIX_LENGTH)); prop = createMappedProperty(method, propName, false, 1); } break; default: break; } if (prop != null) { addProperty(prop); } } private PropertyInfo createMappedProperty(Method javaMethod, String propName, boolean read, int paramIndex) { MethodInfo method = factory.getMethod(javaMethod, getType()); TypeInfo declaringType = method.getDeclaringType(); TypeInfo type = paramIndex >= 0 ? method.getParameterTypes().get(paramIndex) : method.getReturnType(); MethodInfo readMethod = read ? method : null; MethodInfo writMethod = read ? null : method; return new MappedPropertyImpl(propName, declaringType, type, readMethod, writMethod); } /** 代表一个带key的属性信息。 */ private static class MappedPropertyImpl extends AbstractPropertyInfo implements MappedPropertyInfo { private MappedPropertyImpl(String name, TypeInfo declaringType, TypeInfo type, MethodInfo readMethod, MethodInfo writeMethod) { super(name, declaringType, type, readMethod, writeMethod); } public Object getValue(Object object, String key) { try { return getReadMethod().getMethod().invoke(object, key); } catch (InvocationTargetException e) { throw new PropertyEvaluationFailureException(e.getCause()); } catch (Exception e) { throw new PropertyEvaluationFailureException(e.getCause()); } } @Override public void setValue(Object object, String key, Object value) { } @Override protected String getDescription() { return "MappedProperty"; } } }