blob: 93891525aa219d16e36ac2d1ff8ebc141fb6faf5 [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package java.beans;
19
20import java.lang.reflect.Constructor;
21import java.lang.reflect.Method;
22import java.lang.reflect.Modifier;
23import java.util.Vector;
24import org.apache.harmony.beans.internal.nls.Messages;
25
26public class PropertyDescriptor extends FeatureDescriptor {
27 private Method getter;
28
29 private Method setter;
30
31 private Class<?> propertyEditorClass;
32
33 private boolean constrained;
34
35 private boolean bound;
36
37 public PropertyDescriptor(String propertyName, Class<?> beanClass, String getterName,
38 String setterName) throws IntrospectionException {
39 super();
40 if (beanClass == null) {
41 throw new IntrospectionException(Messages.getString("beans.03")); //$NON-NLS-1$
42 }
43 if (propertyName == null || propertyName.length() == 0) {
44 throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
45 }
46 this.setName(propertyName);
47 this.setDisplayName(propertyName);
48 if (setterName != null) {
49 if (hasMethod(beanClass, setterName)) {
50 setWriteMethod(beanClass, setterName);
51 } else {
52 throw new IntrospectionException(Messages.getString("beans.20")); //$NON-NLS-1$
53 }
54 }
55 if (getterName != null) {
56 if (hasMethod(beanClass, getterName)) {
57 setReadMethod(beanClass, getterName);
58 } else {
59 throw new IntrospectionException(Messages.getString("beans.1F")); //$NON-NLS-1$
60 }
61 }
62 }
63
64 public PropertyDescriptor(String propertyName, Method getter, Method setter)
65 throws IntrospectionException {
66 super();
67 if (propertyName == null || propertyName.length() == 0) {
68 throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
69 }
70 this.setName(propertyName);
71 this.setDisplayName(propertyName);
72 setWriteMethod(setter);
73 setReadMethod(getter);
74 }
75
76 public PropertyDescriptor(String propertyName, Class<?> beanClass)
77 throws IntrospectionException {
78 String getterName;
79 String setterName;
80 if (beanClass == null) {
81 throw new IntrospectionException(Messages.getString("beans.03")); //$NON-NLS-1$
82 }
83 if (propertyName == null || propertyName.length() == 0) {
84 throw new IntrospectionException(Messages.getString("beans.04")); //$NON-NLS-1$
85 }
86 this.setName(propertyName);
87 this.setDisplayName(propertyName);
88 getterName = createDefaultMethodName(propertyName, "is"); //$NON-NLS-1$
89 if (hasMethod(beanClass, getterName)) {
90 setReadMethod(beanClass, getterName);
91 } else {
92 getterName = createDefaultMethodName(propertyName, "get"); //$NON-NLS-1$
93 if (hasMethod(beanClass, getterName)) {
94 setReadMethod(beanClass, getterName);
95 }
96 }
97 setterName = createDefaultMethodName(propertyName, "set"); //$NON-NLS-1$
98 if (hasMethod(beanClass, setterName)) {
99 setWriteMethod(beanClass, setterName);
100 }
101 if (getter == null && setter == null) {
102 throw new IntrospectionException(Messages.getString("beans.01", propertyName)); //$NON-NLS-1$
103 }
104 }
105
106 public void setWriteMethod(Method setter) throws IntrospectionException {
107 if (setter != null) {
108 int modifiers = setter.getModifiers();
109 if (!Modifier.isPublic(modifiers)) {
110 throw new IntrospectionException(Messages.getString("beans.05")); //$NON-NLS-1$
111 }
112 Class<?>[] parameterTypes = setter.getParameterTypes();
113 if (parameterTypes.length != 1) {
114 throw new IntrospectionException(Messages.getString("beans.06")); //$NON-NLS-1$
115 }
116 Class<?> parameterType = parameterTypes[0];
117 Class<?> propertyType = getPropertyType();
118 if (propertyType != null && !propertyType.equals(parameterType)) {
119 throw new IntrospectionException(Messages.getString("beans.07")); //$NON-NLS-1$
120 }
121 }
122 this.setter = setter;
123 }
124
125 public void setReadMethod(Method getter) throws IntrospectionException {
126 if (getter != null) {
127 int modifiers = getter.getModifiers();
128 if (!Modifier.isPublic(modifiers)) {
129 throw new IntrospectionException(Messages.getString("beans.0A")); //$NON-NLS-1$
130 }
131 Class<?>[] parameterTypes = getter.getParameterTypes();
132 if (parameterTypes.length != 0) {
133 throw new IntrospectionException(Messages.getString("beans.08")); //$NON-NLS-1$
134 }
135 Class<?> returnType = getter.getReturnType();
136 if (returnType.equals(Void.TYPE)) {
137 throw new IntrospectionException(Messages.getString("beans.33")); //$NON-NLS-1$
138 }
139 Class<?> propertyType = getPropertyType();
140 if ((propertyType != null) && !returnType.equals(propertyType)) {
141 throw new IntrospectionException(Messages.getString("beans.09")); //$NON-NLS-1$
142 }
143 }
144 this.getter = getter;
145 }
146
147 public Method getWriteMethod() {
148 return setter;
149 }
150
151 public Method getReadMethod() {
152 return getter;
153 }
154
155 @Override
156 public boolean equals(Object object) {
157 boolean result = (object != null && object instanceof PropertyDescriptor);
158 if (result) {
159 PropertyDescriptor pd = (PropertyDescriptor) object;
160 boolean gettersAreEqual = (this.getter == null) && (pd.getReadMethod() == null)
161 || (this.getter != null) && (this.getter.equals(pd.getReadMethod()));
162 boolean settersAreEqual = (this.setter == null) && (pd.getWriteMethod() == null)
163 || (this.setter != null) && (this.setter.equals(pd.getWriteMethod()));
164 boolean propertyTypesAreEqual = this.getPropertyType() == pd.getPropertyType();
165 boolean propertyEditorClassesAreEqual = this.getPropertyEditorClass() == pd
166 .getPropertyEditorClass();
167 boolean boundPropertyAreEqual = this.isBound() == pd.isBound();
168 boolean constrainedPropertyAreEqual = this.isConstrained() == pd.isConstrained();
169 result = gettersAreEqual && settersAreEqual && propertyTypesAreEqual
170 && propertyEditorClassesAreEqual && boundPropertyAreEqual
171 && constrainedPropertyAreEqual;
172 }
173 return result;
174 }
175
176 public void setPropertyEditorClass(Class<?> propertyEditorClass) {
177 this.propertyEditorClass = propertyEditorClass;
178 }
179
180 public Class<?> getPropertyType() {
181 Class<?> result = null;
182 if (getter != null) {
183 result = getter.getReturnType();
184 } else if (setter != null) {
185 Class<?>[] parameterTypes = setter.getParameterTypes();
186 result = parameterTypes[0];
187 }
188 return result;
189 }
190
191 public Class<?> getPropertyEditorClass() {
192 return propertyEditorClass;
193 }
194
195 public void setConstrained(boolean constrained) {
196 this.constrained = constrained;
197 }
198
199 public void setBound(boolean bound) {
200 this.bound = bound;
201 }
202
203 public boolean isConstrained() {
204 return constrained;
205 }
206
207 public boolean isBound() {
208 return bound;
209 }
210
211 boolean hasMethod(Class<?> beanClass, String methodName) {
212 Method[] methods = findMethods(beanClass, methodName);
213 return (methods.length > 0);
214 }
215
216 String createDefaultMethodName(String propertyName, String prefix) {
217 String result = null;
218 if (propertyName != null) {
219 String bos = propertyName.substring(0, 1).toUpperCase();
220 String eos = propertyName.substring(1, propertyName.length());
221 result = prefix + bos + eos;
222 }
223 return result;
224 }
225
226 Method[] findMethods(Class<?> aClass, String methodName) {
227 Method[] allMethods = aClass.getMethods();
228 Vector<Method> matchedMethods = new Vector<Method>();
229 Method[] result;
230 for (Method method : allMethods) {
231 if (method.getName().equals(methodName)) {
232 matchedMethods.add(method);
233 }
234 }
235 result = new Method[matchedMethods.size()];
236 for (int j = 0; j < matchedMethods.size(); ++j) {
237 result[j] = matchedMethods.elementAt(j);
238 }
239 return result;
240 }
241
242 void setReadMethod(Class<?> beanClass, String getterName) {
243 boolean result = false;
244 Method[] getters = findMethods(beanClass, getterName);
245 for (Method element : getters) {
246 try {
247 setReadMethod(element);
248 result = true;
249 } catch (IntrospectionException ie) {
250 }
251 if (result) {
252 break;
253 }
254 }
255 }
256
257 void setWriteMethod(Class<?> beanClass, String setterName) throws IntrospectionException {
258 boolean result = false;
259 Method[] setters = findMethods(beanClass, setterName);
260 for (Method element : setters) {
261 try {
262 setWriteMethod(element);
263 result = true;
264 } catch (IntrospectionException ie) {
265 }
266 if (result) {
267 break;
268 }
269 }
270 }
271
272 public PropertyEditor createPropertyEditor(Object bean) {
273 PropertyEditor editor;
274 if (propertyEditorClass == null) {
275 return null;
276 }
277 if (!PropertyEditor.class.isAssignableFrom(propertyEditorClass)) {
278 // beans.48=Property editor is not assignable from the
279 // PropertyEditor interface
280 throw new ClassCastException(Messages.getString("beans.48")); //$NON-NLS-1$
281 }
282 try {
283 Constructor<?> constr;
284 try {
285 // try to look for the constructor with single Object argument
286 constr = propertyEditorClass.getConstructor(Object.class);
287 editor = (PropertyEditor) constr.newInstance(bean);
288 } catch (NoSuchMethodException e) {
289 // try no-argument constructor
290 constr = propertyEditorClass.getConstructor();
291 editor = (PropertyEditor) constr.newInstance();
292 }
293 } catch (Exception e) {
294 // beans.47=Unable to instantiate property editor
295 RuntimeException re = new RuntimeException(Messages.getString("beans.47"), e); //$NON-NLS-1$
296 throw re;
297 }
298 return editor;
299 }
300}