1 package org.apache.ojb.broker.metadata.fieldaccess; 2 3 17 18 import java.lang.reflect.Field ; 19 20 import org.apache.commons.lang.SystemUtils; 21 import org.apache.ojb.broker.core.proxy.ProxyHelper; 22 import org.apache.ojb.broker.metadata.MetadataException; 23 import org.apache.ojb.broker.util.logging.Logger; 24 import org.apache.ojb.broker.util.logging.LoggerFactory; 25 26 32 public abstract class AbstractPersistentField implements PersistentField 33 { 34 public static final String PATH_TOKEN = "::"; 35 public static final Class PERSISTENT_FIELD_IMPL_FOR_NESTED = PersistentFieldDirectAccessImpl.class; 36 37 private static final int UNKNOWN_FIELD = 0; 38 private static final int NORMAL_FIELD = 1; 39 private static final int NESTED_FIELD = 2; 40 41 protected transient Field field; 42 protected String fieldName; 43 protected Class rootObjectType; 44 49 private int isNestedField = UNKNOWN_FIELD; 50 51 58 public AbstractPersistentField() 59 { 60 } 61 62 public AbstractPersistentField(Class clazz, String fieldname) 63 { 64 this.rootObjectType = clazz; 65 this.fieldName = fieldname; 66 } 67 68 71 public abstract void doSet(Object targetObject, Object value); 72 73 76 public abstract Object doGet(Object targetObject); 77 78 82 public abstract boolean makeAccessible(); 83 84 87 public void set(Object targetObject, Object value) throws MetadataException 88 { 89 if(targetObject == null) return; 90 if (isNestedField()) 91 { 92 if (value != null || !getField().getType().isPrimitive()) 93 { 94 setNestedObject(targetObject, fieldName, value); 95 } 96 } 97 else 98 { 99 doSet(targetObject, value); 100 } 101 } 102 103 106 public Object get(Object targetObject) throws MetadataException 107 { 108 if(targetObject == null) return null; 109 if (isNestedField()) 110 { 111 return getNestedObject(targetObject, fieldName); 112 } 113 else 114 { 115 return doGet(targetObject); 116 } 117 } 118 119 protected Logger getLog() 120 { 121 return LoggerFactory.getLogger("PersistentField"); 122 } 123 124 129 protected Field getField() 130 { 131 if (field == null) 132 { 133 field = computeField(rootObjectType, fieldName, isNestedField(), makeAccessible()); 134 } 135 return field; 136 } 137 138 146 protected static Field computeField(Class c, String fieldname, boolean isNested, boolean makeAccessible) 147 { 148 try 149 { 150 Field f; 151 if (isNested) 152 { 153 f = getNestedRecursiveField(c, fieldname); 154 } 155 else 156 { 157 f = getFieldRecursive(c, fieldname); 158 } 159 160 if (makeAccessible) 161 { 162 f.setAccessible(true); 163 } 164 return f; 165 } 166 catch (NoSuchFieldException e) 167 { 168 throw new MetadataException("Can't find member '" + fieldname + "' in " + c.getName(), e); 169 } 170 } 171 172 176 private static Field getFieldRecursive(Class c, String name) throws NoSuchFieldException 177 { 178 try 179 { 180 Field f = c.getDeclaredField(name); 181 return f; 182 } 183 catch (NoSuchFieldException e) 184 { 185 if ((c == Object .class) || (c.getSuperclass() == null) || c.isInterface()) 187 { 188 throw e; 189 } 190 else 192 { 193 return getFieldRecursive(c.getSuperclass(), name); 194 } 195 } 196 } 197 198 201 private static Field getNestedRecursiveField(Class c, String aFieldName) throws NoSuchFieldException 202 { 203 Field result = null; 204 int index = aFieldName.indexOf(PATH_TOKEN); 205 if (index >= 0) 206 { 207 String pathName = aFieldName.substring(0, index); 208 Field path = getFieldRecursive(c, pathName); result = getNestedRecursiveField(path.getType(), aFieldName.substring(index + PATH_TOKEN.length())); 210 } 211 else 212 { 213 result = getFieldRecursive(c, aFieldName); 214 } 215 return result; 216 } 217 218 protected boolean isNestedField() 219 { 220 if (isNestedField == UNKNOWN_FIELD) { 222 if (fieldName == null) 223 { 224 throw new MetadataException( 225 "Unexpected behaviour: fieldName is null, can not calculate field rootObjectType"); 226 } 227 if (fieldName.indexOf(PATH_TOKEN) >= 0) 228 { 229 isNestedField = NESTED_FIELD; 230 } 231 else 232 { 233 isNestedField = NORMAL_FIELD; 234 } 235 } 236 return isNestedField == NESTED_FIELD; 237 } 238 239 245 protected Object getNestedObject(Object obj, String aFieldName) 246 { 247 Object result = null; 248 int index = aFieldName.indexOf(PATH_TOKEN); 249 Object realObj = ProxyHelper.getRealObject(obj); 251 Class realClass = ProxyHelper.getRealClass(obj); 252 if (index >= 0) 253 { 254 String name = aFieldName.substring(0, index); 255 PersistentField pField = createInternPersistentField(realClass, name); 256 Object attrib = pField.get(realObj); 257 258 if (attrib != null) 259 { 260 String nestedName = aFieldName.substring(index + PATH_TOKEN.length()); 261 result = getNestedObject(attrib, nestedName); 262 } 263 } 264 else 265 { 266 PersistentField pField = createInternPersistentField(realClass, aFieldName); 267 result = pField.get(realObj); 268 } 269 return result; 270 } 271 272 278 protected void setNestedObject(Object obj, String fieldName, Object value) 279 { 280 int index = fieldName.indexOf(PATH_TOKEN); 281 Class realClass = ProxyHelper.getRealClass(obj); 282 Object realObj = ProxyHelper.getRealObject(obj); 283 if (index >= 0) 284 { 285 String name = fieldName.substring(0, index); 286 PersistentField pField = createInternPersistentField(realClass, name); 287 Object attrib = pField.get(realObj); 288 289 if (attrib != null || value != null) 290 { 291 if (attrib == null) 292 { 293 try 294 { 295 attrib = createNestedFieldValue(pField); 296 } 297 catch (InstantiationException e) 298 { 299 throw new MetadataException("Error instantiate field: " 300 + name + " in object:" + realClass.getName(), e); 301 } 302 catch (IllegalAccessException e) 303 { 304 throw new MetadataException("Error getting field:" 305 + name + " in object:" + realClass.getName(), e); 306 } 307 308 312 if (pField instanceof AbstractPersistentField) 313 { 314 ((AbstractPersistentField) pField).doSet(realObj, attrib); 315 } 316 else 317 { 318 pField.set(realObj, attrib); 319 } 320 } 321 String nestedName = fieldName.substring(index + PATH_TOKEN.length()); 322 setNestedObject(attrib, nestedName, value); 323 } 324 } 325 else 326 { 327 PersistentField pField = createInternPersistentField(realClass, fieldName); 328 pField.set(realObj, value); 329 } 330 331 } 332 333 protected Object createNestedFieldValue(PersistentField nestedField) throws InstantiationException , IllegalAccessException 334 { 335 return nestedField.getType().newInstance(); 336 } 337 338 private PersistentField createInternPersistentField(Class fieldType, String aFieldName) 339 { 340 try 341 { 342 return PersistentFieldFactory.createPersistentField(fieldType, aFieldName); 343 } 344 catch (Exception e) 345 { 346 throw new MetadataException("Cannot create PersistentField for field '" + aFieldName + "' of class " + 347 fieldType.getName(), e); 348 } 349 } 350 351 public String toString() 352 { 353 StringBuffer buf = new StringBuffer (); 354 buf.append("fieldName="); 355 buf.append(fieldName); 356 buf.append(", field ["); 357 buf.append(field); 358 buf.append("]"); 359 return buf.toString(); 360 } 361 362 public String getName() 363 { 364 return fieldName; 365 } 366 367 public Class getType() 368 { 369 return getField().getType(); 370 } 371 372 public Class getDeclaringClass() 373 { 374 return getField().getDeclaringClass(); 375 } 376 377 380 public String buildMessageString(Object obj, Object value, Field aField) 381 { 382 String eol = SystemUtils.LINE_SEPARATOR; 383 StringBuffer buf = new StringBuffer (); 384 buf 385 .append(eol + "[try to set 'object value' in 'target object'") 386 .append(eol + "target obj class: " + (obj != null ? obj.getClass().getName() : null)) 387 .append(eol + "target field name: " + (aField != null ? aField.getName() : null)) 388 .append(eol + "target field type: " + (aField != null ? aField.getType() : null)) 389 .append(eol + "object value class: " + (value != null ? value.getClass().getName() : null)) 390 .append(eol + "object value: " + (value != null ? value : null)) 391 .append(eol + "]"); 392 return buf.toString(); 393 } 394 } 395 | Popular Tags |