KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > metadata > fieldaccess > PersistentFieldIntrospectorImpl


1 package org.apache.ojb.broker.metadata.fieldaccess;
2
3 /* Copyright 2003-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * 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
18 import java.beans.BeanInfo JavaDoc;
19 import java.beans.IntrospectionException JavaDoc;
20 import java.beans.Introspector JavaDoc;
21 import java.beans.PropertyDescriptor JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.List JavaDoc;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.ojb.broker.core.proxy.ProxyHelper;
28 import org.apache.ojb.broker.metadata.MetadataException;
29 import org.apache.ojb.broker.util.ClassHelper;
30 import org.apache.ojb.broker.util.logging.Logger;
31
32 /**
33  * A {@link PersistentField} implementation using
34  * JavaBeans compliant calls only to access persistent attributes.
35  * No Reflection is needed. But for each attribute xxx there must be
36  * public getXxx() and setXxx() methods. In metadata the field name must be
37  * the bean compliant 'xxx'.
38  *
39  * @version $Id: PersistentFieldIntrospectorImpl.java,v 1.11.2.2 2005/12/21 22:26:41 tomdz Exp $
40  */

41 public class PersistentFieldIntrospectorImpl extends PersistentFieldBase
42 {
43     private static final long serialVersionUID = 8805309492150404444L;
44     private Class JavaDoc type;
45     private transient List JavaDoc propertyGraph;
46
47     public PersistentFieldIntrospectorImpl()
48     {
49         super();
50     }
51
52     public PersistentFieldIntrospectorImpl(Class JavaDoc aClass, String JavaDoc aPropertyName)
53     {
54         super(aClass, aPropertyName);
55     }
56
57     public Class JavaDoc getType()
58     {
59         if (type == null)
60         {
61             type = getPropertyDescriptor().getPropertyType();
62         }
63         return type;
64     }
65
66     public void set(Object JavaDoc target, Object JavaDoc value) throws MetadataException
67     {
68         if(target == null) return;
69         List JavaDoc propertyDescriptors = getPropertyGraph();
70         int size = propertyDescriptors.size() - 1;
71         PropertyDescriptor JavaDoc pd;
72         for (int i = 0; i < size; i++)
73         {
74             Object JavaDoc attribute;
75             pd = (PropertyDescriptor JavaDoc) propertyDescriptors.get(i);
76             attribute = getValueFrom(pd, target);
77             if (attribute != null || value != null)
78             {
79                 if (attribute == null)
80                 {
81                     try
82                     {
83                         attribute = ClassHelper.newInstance(pd.getPropertyType());
84                     }
85                     catch (Exception JavaDoc e)
86                     {
87                         throw new MetadataException("Can't instantiate nested object of type '"
88                                 + pd.getPropertyType() + "' for field '"
89                                 + pd.getName() + "'", e);
90                     }
91                 }
92                 setValueFor(pd, target, attribute);
93             }
94             else
95             {
96                 return;
97             }
98             target = attribute;
99         }
100         pd = (PropertyDescriptor JavaDoc) propertyDescriptors.get(size);
101         setValueFor(pd, target, value);
102     }
103
104     public Object JavaDoc get(Object JavaDoc target) throws MetadataException
105     {
106         List JavaDoc propertyDescriptors = getPropertyGraph();
107         for (int i = 0; i < propertyDescriptors.size(); i++)
108         {
109             PropertyDescriptor JavaDoc pd = (PropertyDescriptor JavaDoc) propertyDescriptors.get(i);
110             target = getValueFrom(pd, target);
111             if (target == null) break;
112         }
113         return target;
114     }
115
116     private Object JavaDoc getValueFrom(PropertyDescriptor JavaDoc pd, Object JavaDoc target)
117     {
118         if (target == null) return null;
119         Method JavaDoc m = pd.getReadMethod();
120         if (m != null)
121         {
122             try
123             {
124                 return m.invoke(ProxyHelper.getRealObject(target), null);
125             }
126             catch (Throwable JavaDoc e)
127             {
128                 logProblem(pd, target, null, "Can't read value from given object");
129                 throw new MetadataException("Error invoking method:" + m.getName() + " in object " + target.getClass().getName(), e);
130             }
131         }
132         else
133         {
134             throw new MetadataException("Can't get ReadMethod for property:" + pd.getName() + " in object " + target.getClass().getName());
135         }
136     }
137
138     private void setValueFor(PropertyDescriptor JavaDoc pd, Object JavaDoc target, Object JavaDoc value)
139     {
140         Method JavaDoc m = pd.getWriteMethod();
141         Object JavaDoc[] args = {value};
142         if (m != null)
143         {
144             try
145             {
146                 /**
147                  * MBAIRD: it is safe to call getParameterTypes()[0] because this is
148                  * the "set" method and it needs to take one parameter only.
149                  * we need to be able to set values to null. We can only set something to null if
150                  * the type is not a primitive (assignable from Object).
151                  */

152                 if ((value != null) || !m.getParameterTypes()[0].isPrimitive())
153                 {
154                     m.invoke(ProxyHelper.getRealObject(target), args);
155                 }
156             }
157             catch (Throwable JavaDoc e)
158             {
159                 logProblem(pd, target, value, "Can't set value on given object.");
160                 throw new MetadataException("Error invoking method:" + m.getName() + " in object:" + target.getClass().getName(), e);
161             }
162         }
163         else
164         {
165             throw new MetadataException("Can't get WriteMethod for property:" + pd.getName() + " in object:" + target.getClass().getName());
166         }
167     }
168
169     private List JavaDoc getPropertyGraph()
170     {
171         if (propertyGraph == null)
172         {
173             propertyGraph = buildPropertyGraph();
174         }
175         return propertyGraph;
176     }
177
178     private List JavaDoc buildPropertyGraph()
179     {
180         List JavaDoc result = new ArrayList JavaDoc();
181         String JavaDoc[] fields = StringUtils.split(getName(), PATH_TOKEN);
182         PropertyDescriptor JavaDoc pd = null;
183         for (int i = 0; i < fields.length; i++)
184         {
185             String JavaDoc fieldName = fields[i];
186             if (pd == null)
187             {
188                 pd = findPropertyDescriptor(getDeclaringClass(), fieldName);
189             }
190             else
191             {
192                 pd = findPropertyDescriptor(pd.getPropertyType(), fieldName);
193             }
194             result.add(pd);
195         }
196         return result;
197     }
198
199     /**
200      * Get the PropertyDescriptor for aClass and aPropertyName
201      */

202     protected static PropertyDescriptor JavaDoc findPropertyDescriptor(Class JavaDoc aClass, String JavaDoc aPropertyName)
203     {
204         BeanInfo JavaDoc info;
205         PropertyDescriptor JavaDoc[] pd;
206         PropertyDescriptor JavaDoc descriptor = null;
207
208         try
209         {
210             info = Introspector.getBeanInfo(aClass);
211             pd = info.getPropertyDescriptors();
212             for (int i = 0; i < pd.length; i++)
213             {
214                 if (pd[i].getName().equals(aPropertyName))
215                 {
216                     descriptor = pd[i];
217                     break;
218                 }
219             }
220             if (descriptor == null)
221             {
222                 /*
223                  * Daren Drummond: Throw here so we are consistent
224                  * with PersistentFieldDefaultImpl.
225                  */

226                 throw new MetadataException("Can't find property " + aPropertyName + " in " + aClass.getName());
227             }
228             return descriptor;
229         }
230         catch (IntrospectionException JavaDoc ex)
231         {
232             /*
233              * Daren Drummond: Throw here so we are consistent
234              * with PersistentFieldDefaultImpl.
235              */

236             throw new MetadataException("Can't find property " + aPropertyName + " in " + aClass.getName(), ex);
237         }
238     }
239
240     /**
241      * Returns the PropertyDescriptor.
242      *
243      * @return java.beans.PropertyDescriptor
244      */

245     protected PropertyDescriptor JavaDoc getPropertyDescriptor()
246     {
247         return (PropertyDescriptor JavaDoc) getPropertyGraph().get(getPropertyGraph().size() - 1);
248     }
249
250     /**
251      * This implementation returns always 'false'.
252      */

253     public boolean makeAccessible()
254     {
255         return false;
256     }
257
258     /**
259      * Always returns 'false'.
260      *
261      * @see PersistentField#usesAccessorsAndMutators
262      */

263     public boolean usesAccessorsAndMutators()
264     {
265         return true;
266     }
267
268     /**
269      * Let's give the user some hints as to what could be wrong.
270      */

271     protected void logProblem(PropertyDescriptor JavaDoc pd, Object JavaDoc anObject, Object JavaDoc aValue, String JavaDoc msg)
272     {
273         Logger logger = getLog();
274         logger.error("Error in [PersistentFieldPropertyImpl], " + msg);
275         logger.error("Declaring class [" + getDeclaringClass().getName() + "]");
276         logger.error("Property Name [" + getName() + "]");
277         logger.error("Property Type [" + pd.getPropertyType().getName() + "]");
278
279         if (anObject != null)
280         {
281             logger.error("anObject was class [" + anObject.getClass().getName() + "]");
282         }
283         else
284         {
285             logger.error("anObject was null");
286         }
287         if (aValue != null)
288         {
289             logger.error("aValue was class [" + aValue.getClass().getName() + "]");
290         }
291         else
292         {
293             logger.error("aValue was null");
294         }
295     }
296 }
297
Popular Tags