001 /* 002 * Copyright 2002-2004 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.clazz.reflect.common; 017 018 import java.lang.reflect.Method; 019 import java.util.Map; 020 021 import org.apache.commons.clazz.reflect.ReflectedClazz; 022 023 /** 024 * A ReflectedPropertyIntrospector that discovers scalar properties. 025 * 026 * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a> 027 * @version $Id: ReflectedScalarPropertyIntrospector.java 155436 2005-02-26 13:17:48Z dirkv $ 028 */ 029 public class ReflectedScalarPropertyIntrospector 030 extends ReflectedPropertyIntrospectorSupport 031 { 032 protected static final AccessorMethodParser READ_METHOD_PARSER = 033 new JBReadAccessorMethodParser(); 034 035 protected static final AccessorMethodParser WRITE_METHOD_PARSER = 036 new WriteAccessorMethodParser(); 037 038 public void introspectProperties( 039 ReflectedClazz clazz, 040 Class javaClass, 041 Map parseResultMap) 042 { 043 Method methods[] = javaClass.getMethods(); 044 ReflectedScalarPropertyParseResults parseResults; 045 AccessorMethodParseResults results; 046 for (int i = 0; i < methods.length; i++) { 047 Method method = methods[i]; 048 if (method.getDeclaringClass().equals(Object.class)) { 049 continue; 050 } 051 052 results = getReadAccessorMethodParser().parse(method); 053 if (results != null) { 054 parseResults = 055 getParseResults( 056 clazz, 057 parseResultMap, 058 results.getPropertyName()); 059 parseResults.setReadMethodParseResults(results); 060 continue; 061 } 062 063 results = getWriteAccessorMethodParser().parse(method); 064 if (results != null) { 065 parseResults = 066 getParseResults( 067 clazz, 068 parseResultMap, 069 results.getPropertyName()); 070 parseResults.setWriteMethodParseResults(results); 071 continue; 072 } 073 } 074 } 075 076 /** 077 * Override to return an alternative parser for the read accessor method. 078 */ 079 protected AccessorMethodParser getReadAccessorMethodParser() { 080 return READ_METHOD_PARSER; 081 } 082 083 protected AccessorMethodParser getWriteAccessorMethodParser() { 084 return WRITE_METHOD_PARSER; 085 } 086 087 /** 088 * Finds a ReflectedScalarPropertyParseResults for the given 089 * propertyName or creates a new one and puts it in the map. 090 */ 091 protected ReflectedScalarPropertyParseResults getParseResults( 092 ReflectedClazz clazz, 093 Map parseResultMap, 094 String propertyName) 095 { 096 ReflectedScalarPropertyParseResults parseResults = 097 (ReflectedScalarPropertyParseResults) parseResultMap.get( 098 propertyName); 099 if (parseResults == null) { 100 parseResults = 101 new ReflectedScalarPropertyParseResults(clazz, propertyName); 102 parseResultMap.put(propertyName, parseResults); 103 } 104 return parseResults; 105 } 106 107 /** 108 * Creates a new ReflectedAccessorPairProperty based on parse results. 109 */ 110 protected ReflectedAccessorPairProperty createProperty( 111 ReflectedClazz clazz, 112 ReflectedPropertyParseResults parseResults) 113 { 114 ReflectedScalarProperty property = 115 new ReflectedScalarProperty(clazz, parseResults.getPropertyName()); 116 117 property.setType(parseResults.getPropertyType()); 118 property.setReadMethod(parseResults.getReadMethod()); 119 property.setWriteMethod(parseResults.getWriteMethod()); 120 return property; 121 } 122 123 /** 124 * Parser for the <code>getFoo()</code> method: 125 * <ul> 126 * <li>Return type not void</li> 127 * <li>Name starts with "get" followed by capitalized property name. 128 * <li>No parameters</li> 129 * </ul> 130 */ 131 public static class ReadAccessorMethodParser extends AccessorMethodParser { 132 protected boolean testReturnType(Class returnType) { 133 return !returnType.equals(Void.TYPE); 134 } 135 protected int requiredParameterCount() { 136 return 0; 137 } 138 protected String requiredPrefix() { 139 return "get"; 140 } 141 protected Class getValueType(Method method) { 142 return method.getReturnType(); 143 } 144 } 145 146 /** 147 * Parser for the <code>getFoo()</code> method: 148 * <ul> 149 * <li>Return type not void</li> 150 * <li>Name starts with "get" followed by capitalized property name. 151 * If the property is boolean the name may also start with "is".</li> 152 * <li>No parameters</li> 153 * </ul> 154 */ 155 public static class JBReadAccessorMethodParser 156 extends ReadAccessorMethodParser 157 { 158 protected String getPropertyName(Method method) { 159 String name = method.getName(); 160 String propertyName = null; 161 if (name.startsWith("get")) { 162 if (name.length() <= 3) { 163 return null; 164 } 165 if (!testFirstCharacterOfPropertyName(name.charAt(3))) { 166 return null; 167 } 168 propertyName = decapitalize(name.substring(3)); 169 } 170 else if (method.getReturnType().equals(Boolean.TYPE) 171 && name.startsWith("is")) { 172 if (name.length() <= 2) { 173 return null; 174 } 175 if (!testFirstCharacterOfPropertyName(name.charAt(2))) { 176 return null; 177 } 178 propertyName = decapitalize(name.substring(2)); 179 } 180 return propertyName; 181 } 182 }; 183 184 /** 185 * Parser for the <code>setFoo(value)</code> method: 186 * <ul> 187 * <li>Return type void</li> 188 * <li>Name starts with "set" followed by capitalized property name</li> 189 * <li>One parameter</li> 190 * </ul> 191 */ 192 public static class WriteAccessorMethodParser extends AccessorMethodParser { 193 protected int requiredParameterCount() { 194 return 1; 195 } 196 protected String requiredPrefix() { 197 return "set"; 198 } 199 protected boolean testReturnType(Class returnType) { 200 return returnType.equals(Void.TYPE); 201 } 202 protected Class getValueType(Method method) { 203 return method.getParameterTypes()[0]; 204 } 205 } 206 207 }