View Javadoc

1   /*
2    * Copyright 2005, 2007 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package net.sf.morph.reflect.support;
17  
18  import java.beans.Introspector;
19  import java.lang.reflect.InvocationTargetException;
20  import java.lang.reflect.Method;
21  import java.lang.reflect.Modifier;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import net.sf.morph.util.NumberUtils;
26  
27  /**
28   * Provides easy access to the property information for a class.
29   *
30   * @author Matt Sgarlata
31   * @author Alexander Volanis
32   * @since Feb 3, 2005
33   */
34  public class ReflectionInfo {
35  	private Map propertyAccessMethods = new HashMap();
36  	private String[] propertyNames;
37  
38  	public ReflectionInfo(Class clazz) {
39  		String propertyName;
40  		Method[] methods = clazz.getMethods();
41  		for (int i = 0; i < methods.length; i++) {
42  			String methodName = methods[i].getName();
43              Class[] parameterTypes = methods[i].getParameterTypes();
44  			if (!Modifier.isStatic(methods[i].getModifiers())) {
45  				// if setter method detected
46  				if (methodName.length() > 3 &&
47  					methodName.indexOf("set") == 0 &&
48  					Character.isUpperCase(methodName.charAt(3))) {
49  					propertyName = Introspector.decapitalize(methodName.substring(3));
50                      // check for number of arguments
51                      if (parameterTypes.length == 1) {
52                          registerMutator(propertyName, methods[i]);
53                      }
54                      // check for indexed mutator
55                      else if (parameterTypes.length == 2 &&
56  						NumberUtils.isNumber(parameterTypes[0])) {
57                          registerIndexedMutator(propertyName, methods[i]);
58                      }
59  				}
60  				// if normal getter method detected
61  				else if (methodName.length() > 3 &&
62  					methodName.indexOf("get") == 0 &&
63  					Character.isUpperCase(methodName.charAt(3))) {
64  					propertyName = Introspector.decapitalize(methodName.substring(3));
65                      // check for standard accesor
66                      if (parameterTypes.length == 0) {
67                          registerAccessor(propertyName, methods[i]);
68                      }
69                      // special case for indexed accessor
70                      else if (parameterTypes.length == 1 &&
71                      	NumberUtils.isNumber(parameterTypes[0])) {
72                          registerIndexedAccessor(propertyName, methods[i]);
73                      }
74  				}
75  				// if boolean getter method detected - PRIMITIVE ONLY like java.beans!
76  				else if (methodName.length() > 2 &&
77  					methods[i].getReturnType().equals(Boolean.TYPE) &&
78                      parameterTypes.length == 0 &&
79  					methodName.indexOf("is") == 0 &&
80  					Character.isUpperCase(methodName.charAt(2))) {
81  					propertyName = Introspector.decapitalize(methodName.substring(2));
82  					registerAccessor(propertyName, methods[i]);
83  				}
84  			}
85  		}
86  		propertyNames = (String[]) propertyAccessMethods.keySet().toArray(
87  			new String[propertyAccessMethods.size()]);
88  	}
89  
90  	protected MethodHolder createOrRetrieveMethodHolder(String propertyName) {
91  		MethodHolder holder = (MethodHolder) propertyAccessMethods.get(propertyName);
92  		if (holder == null) {
93  			holder = new MethodHolder();
94  			propertyAccessMethods.put(propertyName, holder);
95  		}
96  		return holder;
97  	}
98  
99      protected void registerAccessor(String propertyName, Method method) {
100         createOrRetrieveMethodHolder(propertyName).setAccessor(method);
101     }
102 
103     protected void registerMutator(String propertyName, Method method) {
104         createOrRetrieveMethodHolder(propertyName).setMutator(method);
105     }
106 
107     protected void registerIndexedAccessor(String propertyName, Method method) {
108         createOrRetrieveMethodHolder(propertyName).setIndexedAccessor(method);
109     }
110 
111     protected void registerIndexedMutator(String propertyName, Method method) {
112         createOrRetrieveMethodHolder(propertyName).setIndexedMutator(method);
113     }
114 
115 	public MethodHolder getMethodHolder(String propertyName) {
116 		return (MethodHolder) propertyAccessMethods.get(propertyName);
117 	}
118 
119 	public void set(Object bean, String propertyName, Object value)
120 		throws IllegalArgumentException, IllegalAccessException,
121 		InvocationTargetException {
122 		getMethodHolder(propertyName).invokeMutator(bean, value);
123 	}
124 
125     public void set(Object bean, String propertyName, Object index,
126 		Object value) throws IllegalArgumentException,
127 		IllegalAccessException, InvocationTargetException {
128 		getMethodHolder(propertyName).invokeIndexedMutator(bean, index,
129 			value);
130 	}
131 
132 	public boolean isWriteable(String propertyName) {
133 		return
134 			getMethodHolder(propertyName) != null &&
135 			(
136 				getMethodHolder(propertyName).getMutator() != null ||
137 				getMethodHolder(propertyName).getIndexedMutator() != null
138 			);
139 	}
140 
141 	public boolean isReadable(String propertyName) {
142 		return
143 			getMethodHolder(propertyName) != null &&
144 			(
145 				getMethodHolder(propertyName).getAccessor() != null ||
146 				getMethodHolder(propertyName).getIndexedAccessor() != null
147 			);
148 	}
149 
150 	public String[] getPropertyNames() {
151 		return propertyNames;
152 	}
153 
154     public Object get(Object bean, String propertyName) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
155         return getMethodHolder(propertyName).invokeAccessor(bean);
156     }
157 
158     public Object get(Object bean, String propertyName, Object index) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
159         return getMethodHolder(propertyName).invokeIndexedAccessor(bean, index);
160     }
161 
162 }