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 }