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.2.2.3 2005/12/21 22:26:41 tomdz Exp $
034: */
035: public abstract class PersistentFieldBase implements PersistentField {
036: public static final String PATH_TOKEN = "::";
037:
038: private String fieldName;
039: protected Class rootObjectType;
040:
041: /**
042: * For internal use only!!
043: * TODO: Default constructor only needed to support
044: * PersistentFieldFactory#usesAccessorsAndMutators()
045: * method - find a better solution. Make 'public' to
046: * allow helper class to instantiate class.
047: */
048: public PersistentFieldBase() {
049: }
050:
051: public PersistentFieldBase(Class clazz, String fieldname) {
052: this .rootObjectType = clazz;
053: this .fieldName = fieldname;
054: }
055:
056: /**
057: * A value of true indicates that this field should
058: * suppress Java language access checking when it is used.
059: */
060: protected abstract boolean makeAccessible();
061:
062: public String getName() {
063: return fieldName;
064: }
065:
066: public Class getDeclaringClass() {
067: return rootObjectType;
068: }
069:
070: protected List getFieldGraph(boolean makeAccessible) {
071: List result = new ArrayList();
072: String[] fields = StringUtils.split(getName(), PATH_TOKEN);
073: Field fld = null;
074: for (int i = 0; i < fields.length; i++) {
075: String fieldName = fields[i];
076: try {
077: if (fld == null) {
078: fld = getFieldRecursive(rootObjectType, fieldName);
079: } else {
080: fld = getFieldRecursive(fld.getType(), fieldName);
081: }
082: if (makeAccessible) {
083: fld.setAccessible(true);
084: }
085: } catch (NoSuchFieldException e) {
086: throw new MetadataException("Can't find member '"
087: + fieldName
088: + "' in class "
089: + (fld != null ? fld.getDeclaringClass()
090: : rootObjectType), e);
091: }
092: result.add(fld);
093: }
094: return result;
095: }
096:
097: /**
098: * try to find a field in class c, recurse through class hierarchy if necessary
099: *
100: * @throws NoSuchFieldException if no Field was found into the class hierarchy
101: */
102: private Field getFieldRecursive(Class c, String name)
103: throws NoSuchFieldException {
104: try {
105: return c.getDeclaredField(name);
106: } catch (NoSuchFieldException e) {
107: // if field could not be found in the inheritance hierarchy, signal error
108: if ((c == Object.class) || (c.getSuperclass() == null)
109: || c.isInterface()) {
110: throw e;
111: }
112: // if field could not be found in class c try in superclass
113: else {
114: return getFieldRecursive(c.getSuperclass(), name);
115: }
116: }
117: }
118:
119: protected Logger getLog() {
120: return LoggerFactory.getLogger("PersistentField");
121: }
122:
123: public String toString() {
124: ToStringBuilder buf = new ToStringBuilder(this );
125: buf.append("rootType", rootObjectType);
126: buf.append("fieldName", fieldName);
127: return buf.toString();
128: }
129:
130: /**
131: * Build a String representation of given arguments.
132: */
133: protected String buildErrorSetMsg(Object obj, Object value,
134: Field aField) {
135: String eol = SystemUtils.LINE_SEPARATOR;
136: StringBuffer buf = new StringBuffer();
137: buf.append(
138: eol + "[try to set 'object value' in 'target object'")
139: .append(
140: eol
141: + "target obj class: "
142: + (obj != null ? obj.getClass()
143: .getName() : null)).append(
144: eol
145: + "target field name: "
146: + (aField != null ? aField.getName()
147: : null)).append(
148: eol
149: + "target field type: "
150: + (aField != null ? aField.getType()
151: : null)).append(
152: eol
153: + "target field declared in: "
154: + (aField != null ? aField
155: .getDeclaringClass().getName()
156: : null)).append(
157: eol
158: + "object value class: "
159: + (value != null ? value.getClass()
160: .getName() : null)).append(
161: eol + "object value: "
162: + (value != null ? value : null))
163: .append(eol + "]");
164: return buf.toString();
165: }
166:
167: /**
168: * Build a String representation of given arguments.
169: */
170: protected String buildErrorGetMsg(Object obj, Field aField) {
171: String eol = SystemUtils.LINE_SEPARATOR;
172: StringBuffer buf = new StringBuffer();
173: buf.append(eol + "[try to read from source object").append(
174: eol
175: + "source obj class: "
176: + (obj != null ? obj.getClass().getName()
177: : null)).append(
178: eol + "target field name: "
179: + (aField != null ? aField.getName() : null))
180: .append(
181: eol
182: + "target field type: "
183: + (aField != null ? aField.getType()
184: : null)).append(
185: eol
186: + "target field declared in: "
187: + (aField != null ? aField
188: .getDeclaringClass().getName()
189: : null)).append(eol + "]");
190: return buf.toString();
191: }
192: }
|