KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > reflect > FieldAccessor


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.reflect;
21
22 import java.lang.reflect.Field JavaDoc;
23
24 import org.apache.cayenne.CayenneRuntimeException;
25 import org.apache.cayenne.util.Util;
26
27 /**
28  * A PropertyAccessor that performs direct Field access.
29  *
30  * @since 1.2
31  * @author Andrus Adamchik
32  */

33 public class FieldAccessor implements Accessor {
34
35     protected String JavaDoc propertyName;
36     protected Field JavaDoc field;
37     protected Object JavaDoc nullValue;
38
39     public FieldAccessor(Class JavaDoc objectClass, String JavaDoc propertyName, Class JavaDoc propertyType) {
40         // sanity check
41
if (objectClass == null) {
42             throw new IllegalArgumentException JavaDoc("Null objectClass");
43         }
44
45         if (propertyName == null) {
46             throw new IllegalArgumentException JavaDoc("Null propertyName");
47         }
48
49         this.propertyName = propertyName;
50         this.field = prepareField(objectClass, propertyName, propertyType);
51         this.nullValue = PropertyUtils.defaultNullValueForType(field.getType());
52     }
53
54     public String JavaDoc getName() {
55         return propertyName;
56     }
57
58     public Object JavaDoc getValue(Object JavaDoc object) throws PropertyException {
59         try {
60             return field.get(object);
61         }
62         catch (Throwable JavaDoc th) {
63             throw new PropertyException(
64                     "Error reading field: " + field.getName(),
65                     this,
66                     object,
67                     th);
68         }
69     }
70
71     /**
72      * @since 3.0
73      */

74     public void setValue(Object JavaDoc object, Object JavaDoc newValue) throws PropertyException {
75         // this will take care of primitives.
76
if (newValue == null) {
77             newValue = this.nullValue;
78         }
79
80         try {
81             field.set(object, newValue);
82         }
83         catch (Throwable JavaDoc th) {
84             throw new PropertyException(
85                     "Error writing field: " + field.getName(),
86                     this,
87                     object,
88                     th);
89         }
90     }
91
92     /**
93      * Finds a field for the property, ensuring that direct access via reflection is
94      * possible.
95      */

96     protected Field JavaDoc prepareField(Class JavaDoc beanClass, String JavaDoc propertyName, Class JavaDoc propertyType) {
97         Field JavaDoc field;
98
99         // locate field
100
try {
101             field = lookupFieldInHierarchy(beanClass, propertyName);
102         }
103         catch (SecurityException JavaDoc e) {
104             throw new CayenneRuntimeException("Error accessing field '"
105                     + propertyName
106                     + "' in class: "
107                     + beanClass.getName(), e);
108         }
109         catch (NoSuchFieldException JavaDoc e) {
110             throw new CayenneRuntimeException("No field '"
111                     + propertyName
112                     + "' is defined in class: "
113                     + beanClass.getName(), e);
114         }
115
116         // set accessability
117
if (!Util.isAccessible(field)) {
118             field.setAccessible(true);
119         }
120
121         if (propertyType != null) {
122
123             // check that the field is of expected class...
124
if (!propertyType.isAssignableFrom(field.getType())) {
125
126                 // allow primitive to object conversions...
127
if (!PropertyUtils.normalizeType(propertyType).isAssignableFrom(
128                         PropertyUtils.normalizeType(field.getType()))) {
129                     throw new CayenneRuntimeException("Expected property type '"
130                             + propertyType.getName()
131                             + "', got '"
132                             + field.getType().getName()
133                             + "'. Property: "
134                             + beanClass.getName()
135                             + "."
136                             + propertyName);
137                 }
138             }
139         }
140
141         return field;
142     }
143
144     /**
145      * Recursively looks for a named field in a class hierarchy.
146      */

147     protected Field JavaDoc lookupFieldInHierarchy(Class JavaDoc beanClass, String JavaDoc fieldName)
148             throws SecurityException JavaDoc, NoSuchFieldException JavaDoc {
149
150         // TODO: support property names following other common naming patterns, such as
151
// "_propertyName"
152

153         try {
154             return beanClass.getDeclaredField(fieldName);
155         }
156         catch (NoSuchFieldException JavaDoc e) {
157
158             Class JavaDoc superClass = beanClass.getSuperclass();
159             if (superClass == null || superClass.getName().equals(Object JavaDoc.class.getName())) {
160                 throw e;
161             }
162
163             return lookupFieldInHierarchy(superClass, fieldName);
164         }
165     }
166
167 }
168
Popular Tags