001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.beans;
019:
020: import java.lang.reflect.Constructor;
021: import java.lang.reflect.Method;
022: import java.lang.reflect.Modifier;
023:
024: import org.apache.harmony.beans.BeansUtils;
025: import org.apache.harmony.beans.internal.nls.Messages;
026:
027: public class PropertyDescriptor extends FeatureDescriptor {
028: private Method getter;
029:
030: private Method setter;
031:
032: private Class<?> propertyEditorClass;
033:
034: boolean constrained;
035:
036: boolean bound;
037:
038: public PropertyDescriptor(String propertyName, Class<?> beanClass,
039: String getterName, String setterName)
040: throws IntrospectionException {
041: super ();
042: if (beanClass == null) {
043: throw new IntrospectionException(Messages
044: .getString("beans.03")); //$NON-NLS-1$
045: }
046: if (propertyName == null || propertyName.length() == 0) {
047: throw new IntrospectionException(Messages
048: .getString("beans.04")); //$NON-NLS-1$
049: }
050: this .setName(propertyName);
051: if (getterName != null) {
052: if (getterName.length() == 0) {
053: throw new IntrospectionException(
054: "read or write method cannot be empty."); //$NON-NLS-1$
055: }
056: try {
057: setReadMethod(beanClass, getterName);
058: } catch (IntrospectionException e) {
059: setReadMethod(beanClass, createDefaultMethodName(
060: propertyName, "get")); //$NON-NLS-1$
061: }
062: }
063: if (setterName != null) {
064: if (setterName.length() == 0) {
065: throw new IntrospectionException(
066: "read or write method cannot be empty."); //$NON-NLS-1$
067: }
068: setWriteMethod(beanClass, setterName);
069: }
070: }
071:
072: public PropertyDescriptor(String propertyName, Method getter,
073: Method setter) throws IntrospectionException {
074: super ();
075: if (propertyName == null || propertyName.length() == 0) {
076: throw new IntrospectionException(Messages
077: .getString("beans.04")); //$NON-NLS-1$
078: }
079: this .setName(propertyName);
080: setReadMethod(getter);
081: setWriteMethod(setter);
082: }
083:
084: public PropertyDescriptor(String propertyName, Class<?> beanClass)
085: throws IntrospectionException {
086: if (beanClass == null) {
087: throw new IntrospectionException(Messages
088: .getString("beans.03")); //$NON-NLS-1$
089: }
090: if (propertyName == null || propertyName.length() == 0) {
091: throw new IntrospectionException(Messages
092: .getString("beans.04")); //$NON-NLS-1$
093: }
094: this .setName(propertyName);
095: try {
096: setReadMethod(beanClass, createDefaultMethodName(
097: propertyName, "is")); //$NON-NLS-1$
098: } catch (Exception e) {
099: setReadMethod(beanClass, createDefaultMethodName(
100: propertyName, "get")); //$NON-NLS-1$
101: }
102:
103: setWriteMethod(beanClass, createDefaultMethodName(propertyName,
104: "set")); //$NON-NLS-1$
105: }
106:
107: public void setWriteMethod(Method setter)
108: throws IntrospectionException {
109: if (setter != null) {
110: int modifiers = setter.getModifiers();
111: if (!Modifier.isPublic(modifiers)) {
112: throw new IntrospectionException(Messages
113: .getString("beans.05")); //$NON-NLS-1$
114: }
115: Class<?>[] parameterTypes = setter.getParameterTypes();
116: if (parameterTypes.length != 1) {
117: throw new IntrospectionException(Messages
118: .getString("beans.06")); //$NON-NLS-1$
119: }
120: Class<?> parameterType = parameterTypes[0];
121: Class<?> propertyType = getPropertyType();
122: if (propertyType != null
123: && !propertyType.equals(parameterType)) {
124: throw new IntrospectionException(Messages
125: .getString("beans.07")); //$NON-NLS-1$
126: }
127: }
128: this .setter = setter;
129: }
130:
131: public void setReadMethod(Method getter)
132: throws IntrospectionException {
133: if (getter != null) {
134: int modifiers = getter.getModifiers();
135: if (!Modifier.isPublic(modifiers)) {
136: throw new IntrospectionException(Messages
137: .getString("beans.0A")); //$NON-NLS-1$
138: }
139: Class<?>[] parameterTypes = getter.getParameterTypes();
140: if (parameterTypes.length != 0) {
141: throw new IntrospectionException(Messages
142: .getString("beans.08")); //$NON-NLS-1$
143: }
144: Class<?> returnType = getter.getReturnType();
145: if (returnType.equals(Void.TYPE)) {
146: throw new IntrospectionException(Messages
147: .getString("beans.33")); //$NON-NLS-1$
148: }
149: Class<?> propertyType = getPropertyType();
150: if ((propertyType != null)
151: && !returnType.equals(propertyType)) {
152: throw new IntrospectionException(Messages
153: .getString("beans.09")); //$NON-NLS-1$
154: }
155: }
156: this .getter = getter;
157: }
158:
159: public Method getWriteMethod() {
160: return setter;
161: }
162:
163: public Method getReadMethod() {
164: return getter;
165: }
166:
167: @Override
168: public boolean equals(Object object) {
169: boolean result = object instanceof PropertyDescriptor;
170: if (result) {
171: PropertyDescriptor pd = (PropertyDescriptor) object;
172: boolean gettersAreEqual = (this .getter == null)
173: && (pd.getReadMethod() == null)
174: || (this .getter != null)
175: && (this .getter.equals(pd.getReadMethod()));
176: boolean settersAreEqual = (this .setter == null)
177: && (pd.getWriteMethod() == null)
178: || (this .setter != null)
179: && (this .setter.equals(pd.getWriteMethod()));
180: boolean propertyTypesAreEqual = this .getPropertyType() == pd
181: .getPropertyType();
182: boolean propertyEditorClassesAreEqual = this
183: .getPropertyEditorClass() == pd
184: .getPropertyEditorClass();
185: boolean boundPropertyAreEqual = this .isBound() == pd
186: .isBound();
187: boolean constrainedPropertyAreEqual = this .isConstrained() == pd
188: .isConstrained();
189: result = gettersAreEqual && settersAreEqual
190: && propertyTypesAreEqual
191: && propertyEditorClassesAreEqual
192: && boundPropertyAreEqual
193: && constrainedPropertyAreEqual;
194: }
195: return result;
196: }
197:
198: @Override
199: public int hashCode() {
200: return BeansUtils.getHashCode(getter)
201: + BeansUtils.getHashCode(setter)
202: + BeansUtils.getHashCode(getPropertyType())
203: + BeansUtils.getHashCode(getPropertyEditorClass())
204: + BeansUtils.getHashCode(isBound())
205: + BeansUtils.getHashCode(isConstrained());
206: }
207:
208: public void setPropertyEditorClass(Class<?> propertyEditorClass) {
209: this .propertyEditorClass = propertyEditorClass;
210: }
211:
212: public Class<?> getPropertyType() {
213: Class<?> result = null;
214: if (getter != null) {
215: result = getter.getReturnType();
216: } else if (setter != null) {
217: Class<?>[] parameterTypes = setter.getParameterTypes();
218: result = parameterTypes[0];
219: }
220: return result;
221: }
222:
223: public Class<?> getPropertyEditorClass() {
224: return propertyEditorClass;
225: }
226:
227: public void setConstrained(boolean constrained) {
228: this .constrained = constrained;
229: }
230:
231: public void setBound(boolean bound) {
232: this .bound = bound;
233: }
234:
235: public boolean isConstrained() {
236: return constrained;
237: }
238:
239: public boolean isBound() {
240: return bound;
241: }
242:
243: String createDefaultMethodName(String propertyName, String prefix) {
244: String result = null;
245: if (propertyName != null) {
246: String bos = propertyName.substring(0, 1).toUpperCase();
247: String eos = propertyName.substring(1, propertyName
248: .length());
249: result = prefix + bos + eos;
250: }
251: return result;
252: }
253:
254: void setReadMethod(Class<?> beanClass, String getterName)
255: throws IntrospectionException {
256: try {
257: Method readMethod = beanClass.getMethod(getterName,
258: new Class[] {});
259: setReadMethod(readMethod);
260: } catch (Exception e) {
261: throw new IntrospectionException(e.getLocalizedMessage());
262: }
263: }
264:
265: void setWriteMethod(Class<?> beanClass, String setterName)
266: throws IntrospectionException {
267: Method writeMethod = null;
268: try {
269: if (getter != null) {
270: writeMethod = beanClass.getMethod(setterName,
271: new Class[] { getter.getReturnType() });
272: } else {
273: Method[] methods = beanClass.getMethods();
274: for (Method method : methods) {
275: if (method.getName().equals(setterName)) {
276: if (method.getParameterTypes().length == 1) {
277: writeMethod = method;
278: break;
279: }
280: }
281: }
282: }
283: } catch (Exception e) {
284: throw new IntrospectionException(e.getLocalizedMessage());
285: }
286: setWriteMethod(writeMethod);
287: }
288:
289: public PropertyEditor createPropertyEditor(Object bean) {
290: PropertyEditor editor;
291: if (propertyEditorClass == null) {
292: return null;
293: }
294: if (!PropertyEditor.class.isAssignableFrom(propertyEditorClass)) {
295: // beans.48=Property editor is not assignable from the
296: // PropertyEditor interface
297: throw new ClassCastException(Messages.getString("beans.48")); //$NON-NLS-1$
298: }
299: try {
300: Constructor<?> constr;
301: try {
302: // try to look for the constructor with single Object argument
303: constr = propertyEditorClass
304: .getConstructor(Object.class);
305: editor = (PropertyEditor) constr.newInstance(bean);
306: } catch (NoSuchMethodException e) {
307: // try no-argument constructor
308: constr = propertyEditorClass.getConstructor();
309: editor = (PropertyEditor) constr.newInstance();
310: }
311: } catch (Exception e) {
312: // beans.47=Unable to instantiate property editor
313: RuntimeException re = new RuntimeException(Messages
314: .getString("beans.47"), e); //$NON-NLS-1$
315: throw re;
316: }
317: return editor;
318: }
319: }
|