001 package org.apache.ojb.broker.metadata.fieldaccess; 002 003 /* Copyright 2003-2005 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 import java.lang.reflect.Field; 019 import java.util.ArrayList; 020 import java.util.List; 021 022 import org.apache.commons.lang.StringUtils; 023 import org.apache.commons.lang.SystemUtils; 024 import org.apache.commons.lang.builder.ToStringBuilder; 025 import org.apache.ojb.broker.metadata.MetadataException; 026 import org.apache.ojb.broker.util.logging.Logger; 027 import org.apache.ojb.broker.util.logging.LoggerFactory; 028 029 /** 030 * Abstract {@link PersistentField} base implementation class. 031 * 032 * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a> 033 * @version $Id: PersistentFieldBase.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $ 034 */ 035 public abstract class PersistentFieldBase implements PersistentField 036 { 037 public static final String PATH_TOKEN = "::"; 038 039 private String fieldName; 040 protected Class rootObjectType; 041 042 /** 043 * For internal use only!! 044 * TODO: Default constructor only needed to support 045 * PersistentFieldFactory#usesAccessorsAndMutators() 046 * method - find a better solution. Make 'public' to 047 * allow helper class to instantiate class. 048 */ 049 public PersistentFieldBase() 050 { 051 } 052 053 public PersistentFieldBase(Class clazz, String fieldname) 054 { 055 this.rootObjectType = clazz; 056 this.fieldName = fieldname; 057 } 058 059 /** 060 * A value of true indicates that this field should 061 * suppress Java language access checking when it is used. 062 */ 063 protected abstract boolean makeAccessible(); 064 065 public String getName() 066 { 067 return fieldName; 068 } 069 070 public Class getDeclaringClass() 071 { 072 return rootObjectType; 073 } 074 075 protected List getFieldGraph(boolean makeAccessible) 076 { 077 List result = new ArrayList(); 078 String[] fields = StringUtils.split(getName(), PATH_TOKEN); 079 Field fld = null; 080 for (int i = 0; i < fields.length; i++) 081 { 082 String fieldName = fields[i]; 083 try 084 { 085 if (fld == null) 086 { 087 fld = getFieldRecursive(rootObjectType, fieldName); 088 } 089 else 090 { 091 fld = getFieldRecursive(fld.getType(), fieldName); 092 } 093 if (makeAccessible) 094 { 095 fld.setAccessible(true); 096 } 097 } 098 catch (NoSuchFieldException e) 099 { 100 throw new MetadataException("Can't find member '" 101 + fieldName + "' in class " + (fld != null ? fld.getDeclaringClass() : rootObjectType), e); 102 } 103 result.add(fld); 104 } 105 return result; 106 } 107 108 /** 109 * try to find a field in class c, recurse through class hierarchy if necessary 110 * 111 * @throws NoSuchFieldException if no Field was found into the class hierarchy 112 */ 113 private Field getFieldRecursive(Class c, String name) throws NoSuchFieldException 114 { 115 try 116 { 117 return c.getDeclaredField(name); 118 } 119 catch (NoSuchFieldException e) 120 { 121 // if field could not be found in the inheritance hierarchy, signal error 122 if ((c == Object.class) || (c.getSuperclass() == null) || c.isInterface()) 123 { 124 throw e; 125 } 126 // if field could not be found in class c try in superclass 127 else 128 { 129 return getFieldRecursive(c.getSuperclass(), name); 130 } 131 } 132 } 133 134 protected Logger getLog() 135 { 136 return LoggerFactory.getLogger("PersistentField"); 137 } 138 139 public String toString() 140 { 141 ToStringBuilder buf = new ToStringBuilder(this); 142 buf.append("rootType", rootObjectType); 143 buf.append("fieldName", fieldName); 144 return buf.toString(); 145 } 146 147 /** 148 * Build a String representation of given arguments. 149 */ 150 protected String buildErrorSetMsg(Object obj, Object value, Field aField) 151 { 152 String eol = SystemUtils.LINE_SEPARATOR; 153 StringBuffer buf = new StringBuffer(); 154 buf 155 .append(eol + "[try to set 'object value' in 'target object'") 156 .append(eol + "target obj class: " + (obj != null ? obj.getClass().getName() : null)) 157 .append(eol + "target field name: " + (aField != null ? aField.getName() : null)) 158 .append(eol + "target field type: " + (aField != null ? aField.getType() : null)) 159 .append(eol + "target field declared in: " + (aField != null ? aField.getDeclaringClass().getName() : null)) 160 .append(eol + "object value class: " + (value != null ? value.getClass().getName() : null)) 161 .append(eol + "object value: " + (value != null ? value : null)) 162 .append(eol + "]"); 163 return buf.toString(); 164 } 165 166 /** 167 * Build a String representation of given arguments. 168 */ 169 protected String buildErrorGetMsg(Object obj, Field aField) 170 { 171 String eol = SystemUtils.LINE_SEPARATOR; 172 StringBuffer buf = new StringBuffer(); 173 buf 174 .append(eol + "[try to read from source object") 175 .append(eol + "source obj class: " + (obj != null ? obj.getClass().getName() : null)) 176 .append(eol + "target field name: " + (aField != null ? aField.getName() : null)) 177 .append(eol + "target field type: " + (aField != null ? aField.getType() : null)) 178 .append(eol + "target field declared in: " + (aField != null ? aField.getDeclaringClass().getName() : null)) 179 .append(eol + "]"); 180 return buf.toString(); 181 } 182 }