001: /*
002: * Copyright 2005-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package net.sf.dozer.util.mapping.fieldmap;
017:
018: import java.lang.reflect.Method;
019:
020: import net.sf.dozer.util.mapping.classmap.ClassMap;
021: import net.sf.dozer.util.mapping.propertydescriptor.DozerPropertyDescriptorIF;
022: import net.sf.dozer.util.mapping.propertydescriptor.GetterSetterPropertyDescriptor;
023: import net.sf.dozer.util.mapping.propertydescriptor.PropertyDescriptorFactory;
024: import net.sf.dozer.util.mapping.util.MapperConstants;
025: import net.sf.dozer.util.mapping.util.MappingUtils;
026:
027: import org.apache.commons.lang.builder.ToStringBuilder;
028: import org.apache.commons.lang.builder.ToStringStyle;
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031:
032: /**
033: * Internal class that represents a field mapping definition. Holds all of the information about a single field mapping
034: * definition. Only intended for internal use.
035: *
036: * @author garsombke.franz
037: * @author sullins.ben
038: * @author tierney.matt
039: *
040: */
041: public abstract class FieldMap implements Cloneable {
042: private static final Log log = LogFactory.getLog(FieldMap.class);
043:
044: private ClassMap classMap;
045: private DozerField srcField;
046: private DozerField destField;
047: private HintContainer srcHintContainer;
048: private HintContainer destHintContainer;
049: private HintContainer srcDeepIndexHintContainer;
050: private HintContainer destDeepIndexHintContainer;
051: private String type;
052: private boolean copyByReference;
053: private boolean copyByReferenceOveridden;
054: private String mapId;
055: private String customConverter;
056: private String customConverterId;
057: private String relationshipType;
058: private boolean removeOrphans;
059:
060: public FieldMap(ClassMap classMap) {
061: this .classMap = classMap;
062: }
063:
064: public ClassMap getClassMap() {
065: return classMap;
066: }
067:
068: public void setClassMap(ClassMap classMap) {
069: this .classMap = classMap;
070: }
071:
072: public Object getSrcFieldValue(Object runtimeSrcObj) {
073: return getSrcPropertyDescriptor(runtimeSrcObj.getClass())
074: .getPropertyValue(runtimeSrcObj);
075: }
076:
077: public void writeDestValue(Object runtimeDestObj,
078: Object destFieldValue) {
079: if (log.isDebugEnabled()) {
080: log
081: .debug("Getting ready to invoke write method on the destination object. Dest Obj: "
082: + MappingUtils
083: .getClassNameWithoutPackage(runtimeDestObj
084: .getClass())
085: + ", Dest value: " + destFieldValue);
086: }
087: DozerPropertyDescriptorIF propDescriptor = getDestPropertyDescriptor(runtimeDestObj
088: .getClass());
089: propDescriptor.setPropertyValue(runtimeDestObj, destFieldValue,
090: this );
091: }
092:
093: public Class getDestHintType(Class runtimeSrcClass) {
094: if (getDestHintContainer() != null) {
095: if (getSrcHintContainer() != null) {
096: return getDestHintContainer().getHint(runtimeSrcClass,
097: getSrcHintContainer().getHints());
098: } else {
099: return getDestHintContainer().getHint();
100: }
101: } else {
102: return runtimeSrcClass;
103: }
104: }
105:
106: public Class getDestFieldType(Class runtimeDestClass) {
107: Class result = null;
108: if (isDestFieldIndexed()) {
109: result = destHintContainer != null ? destHintContainer
110: .getHint() : null;
111: }
112: if (result == null) {
113: result = getDestPropertyDescriptor(runtimeDestClass)
114: .getPropertyType();
115: }
116: return result;
117: }
118:
119: public Class getSrcFieldType(Class runtimeSrcClass) {
120: return getSrcPropertyDescriptor(runtimeSrcClass)
121: .getPropertyType();
122: }
123:
124: /**
125: * @deprecated As of 3.2 release
126: */
127: public Method getDestFieldWriteMethod(Class runtimeDestClass) {
128: // 4-07 mht: The getWriteMethod was removed from the prop descriptor interface. This was done as part of
129: // refactoring effort to clean up the prop descriptor stuff. The underlying write method should not be exposed.
130: // For now, just explicitly cast to the only prop descriptor(getter/setter) that could have been used in this
131: // context. The other types of prop descriptors would have failed.
132: DozerPropertyDescriptorIF dpd = getDestPropertyDescriptor(runtimeDestClass);
133: Method result = null;
134: try {
135: result = ((GetterSetterPropertyDescriptor) dpd)
136: .getWriteMethod();
137: } catch (Exception e) {
138: MappingUtils.throwMappingException(e);
139: }
140: return result;
141: }
142:
143: public Object getDestValue(Object runtimeDestObj) {
144: return getDestPropertyDescriptor(runtimeDestObj.getClass())
145: .getPropertyValue(runtimeDestObj);
146: }
147:
148: public HintContainer getDestHintContainer() {
149: return destHintContainer;
150: }
151:
152: public void setDestHintContainer(HintContainer destHint) {
153: this .destHintContainer = destHint;
154: }
155:
156: public HintContainer getSrcHintContainer() {
157: return srcHintContainer;
158: }
159:
160: public void setSrcHintContainer(HintContainer sourceHint) {
161: this .srcHintContainer = sourceHint;
162: }
163:
164: public String getSrcFieldMapGetMethod() {
165: return !MappingUtils.isBlankOrNull(srcField.getMapGetMethod()) ? srcField
166: .getMapGetMethod()
167: : classMap.getSrcClassMapGetMethod();
168: }
169:
170: public String getSrcFieldMapSetMethod() {
171: return !MappingUtils.isBlankOrNull(srcField.getMapSetMethod()) ? srcField
172: .getMapSetMethod()
173: : classMap.getSrcClassMapSetMethod();
174: }
175:
176: public String getDestFieldMapGetMethod() {
177: return !MappingUtils.isBlankOrNull(destField.getMapGetMethod()) ? destField
178: .getMapGetMethod()
179: : classMap.getDestClassMapGetMethod();
180: }
181:
182: public String getDestFieldMapSetMethod() {
183: return !MappingUtils.isBlankOrNull(destField.getMapSetMethod()) ? destField
184: .getMapSetMethod()
185: : classMap.getDestClassMapSetMethod();
186: }
187:
188: public String getSrcFieldName() {
189: return srcField.getName();
190: }
191:
192: public String getDestFieldName() {
193: return destField.getName();
194: }
195:
196: public String getDestFieldType() {
197: return destField.getType();
198: }
199:
200: public String getSrcFieldType() {
201: return srcField.getType();
202: }
203:
204: public String getSrcFieldDateFormat() {
205: return getDateFormat();
206: }
207:
208: public String getDestFieldDateFormat() {
209: return getDateFormat();
210: }
211:
212: public String getDateFormat() {
213: if (!MappingUtils.isBlankOrNull(destField.getDateFormat())) {
214: return destField.getDateFormat();
215: } else if (!MappingUtils
216: .isBlankOrNull(srcField.getDateFormat())) {
217: return srcField.getDateFormat();
218: } else {
219: return classMap.getDateFormat();
220: }
221: }
222:
223: public String getDestFieldCreateMethod() {
224: return destField.getCreateMethod();
225: }
226:
227: public String getSrcFieldCreateMethod() {
228: return srcField.getCreateMethod();
229: }
230:
231: public boolean isDestFieldIndexed() {
232: return destField.isIndexed();
233: }
234:
235: public boolean isSrcFieldIndexed() {
236: return srcField.isIndexed();
237: }
238:
239: public int getSrcFieldIndex() {
240: return srcField.getIndex();
241: }
242:
243: public int getDestFieldIndex() {
244: return destField.getIndex();
245: }
246:
247: public String getSrcFieldTheGetMethod() {
248: return srcField.getTheGetMethod();
249: }
250:
251: public String getDestFieldTheGetMethod() {
252: return destField.getTheGetMethod();
253: }
254:
255: public String getSrcFieldTheSetMethod() {
256: return srcField.getTheSetMethod();
257: }
258:
259: public String getDestFieldTheSetMethod() {
260: return destField.getTheSetMethod();
261: }
262:
263: public String getSrcFieldKey() {
264: return srcField.getKey();
265: }
266:
267: public String getDestFieldKey() {
268: return destField.getKey();
269: }
270:
271: public boolean isDestFieldAccessible() {
272: return destField.isAccessible();
273: }
274:
275: public boolean isSrcFieldAccessible() {
276: return srcField.isAccessible();
277: }
278:
279: public void setSrcField(DozerField sourceField) {
280: this .srcField = sourceField;
281: }
282:
283: public void setDestField(DozerField destField) {
284: this .destField = destField;
285: }
286:
287: public HintContainer getDestDeepIndexHintContainer() {
288: return destDeepIndexHintContainer;
289: }
290:
291: public void setDestDeepIndexHintContainer(
292: HintContainer destDeepIndexHintHint) {
293: this .destDeepIndexHintContainer = destDeepIndexHintHint;
294: }
295:
296: public HintContainer getSrcDeepIndexHintContainer() {
297: return srcDeepIndexHintContainer;
298: }
299:
300: public void setSrcDeepIndexHintContainer(
301: HintContainer srcDeepIndexHint) {
302: this .srcDeepIndexHintContainer = srcDeepIndexHint;
303: }
304:
305: public Object clone() {
306: Object result = null;
307: try {
308: result = super .clone();
309: } catch (CloneNotSupportedException e) {
310: MappingUtils.throwMappingException(e);
311: }
312: return result;
313: }
314:
315: public String getType() {
316: return type;
317: }
318:
319: public void setType(String type) {
320: this .type = type;
321: }
322:
323: public boolean isCopyByReference() {
324: return copyByReference;
325: }
326:
327: public void setCopyByReference(boolean copyByReference) {
328: this .copyByReference = copyByReference;
329: this .copyByReferenceOveridden = true;
330: }
331:
332: /**
333: * Return true if is self referencing. Is considered self referencing where no other sources are specified, i.e., no
334: * source properties or #CDATA in the xml def.
335: */
336: protected boolean isSrcSelfReferencing() {
337: return getSrcFieldName().equals(MapperConstants.SELF_KEYWORD);
338: }
339:
340: protected boolean isDestSelfReferencing() {
341: return getDestFieldName().equals(MapperConstants.SELF_KEYWORD);
342: }
343:
344: public boolean isCopyByReferenceOveridden() {
345: return copyByReferenceOveridden;
346: }
347:
348: public String getMapId() {
349: return mapId;
350: }
351:
352: public void setMapId(String mapId) {
353: this .mapId = mapId;
354: }
355:
356: public String getCustomConverter() {
357: return customConverter;
358: }
359:
360: public void setCustomConverter(String customConverter) {
361: this .customConverter = customConverter;
362: }
363:
364: public String getRelationshipType() {
365: return relationshipType != null ? relationshipType : classMap
366: .getRelationshipType();
367: }
368:
369: public void setRelationshipType(String relationshipType) {
370: this .relationshipType = relationshipType;
371: }
372:
373: public void validate() {
374: if (srcField == null) {
375: MappingUtils
376: .throwMappingException("src field must be specified");
377: }
378: if (destField == null) {
379: MappingUtils
380: .throwMappingException("dest field must be specified");
381: }
382: }
383:
384: protected DozerPropertyDescriptorIF getSrcPropertyDescriptor(
385: Class runtimeSrcClass) {
386: //This could possibly be a good place to add caching on prop descriptor for runtime class.
387: return PropertyDescriptorFactory.getPropertyDescriptor(
388: runtimeSrcClass, getSrcFieldTheGetMethod(),
389: getSrcFieldTheSetMethod(), getSrcFieldMapGetMethod(),
390: getSrcFieldMapSetMethod(), isSrcFieldAccessible(),
391: isSrcFieldIndexed(), getSrcFieldIndex(),
392: getSrcFieldName(), getSrcFieldKey(),
393: isSrcSelfReferencing(), getDestFieldName(),
394: getSrcDeepIndexHintContainer(),
395: getDestDeepIndexHintContainer(), classMap
396: .getSrcClassBeanFactory());
397: }
398:
399: protected DozerPropertyDescriptorIF getDestPropertyDescriptor(
400: Class runtimeDestClass) {
401: //This could possibly be a good place to add caching on prop descriptor for runtime class.
402: return PropertyDescriptorFactory.getPropertyDescriptor(
403: runtimeDestClass, getDestFieldTheGetMethod(),
404: getDestFieldTheSetMethod(), getDestFieldMapGetMethod(),
405: getDestFieldMapSetMethod(), isDestFieldAccessible(),
406: isDestFieldIndexed(), getDestFieldIndex(),
407: getDestFieldName(), getDestFieldKey(),
408: isDestSelfReferencing(), getSrcFieldName(),
409: getSrcDeepIndexHintContainer(),
410: getDestDeepIndexHintContainer(), classMap
411: .getDestClassBeanFactory());
412: }
413:
414: protected DozerField getSrcField() {
415: return srcField;
416: }
417:
418: protected DozerField getDestField() {
419: return destField;
420: }
421:
422: public String getCustomConverterId() {
423: return customConverterId;
424: }
425:
426: public void setCustomConverterId(String customConverterId) {
427: this .customConverterId = customConverterId;
428: }
429:
430: public boolean isRemoveOrphans() {
431: return removeOrphans;
432: }
433:
434: public void setRemoveOrphans(boolean removeOrphans) {
435: this .removeOrphans = removeOrphans;
436: }
437:
438: public boolean isDestMapNull() {
439: return classMap.isDestMapNull();
440: }
441:
442: public boolean isDestMapEmptyString() {
443: return classMap.isDestMapEmptyString();
444: }
445:
446: public boolean isTrimStrings() {
447: return classMap.isTrimStrings();
448: }
449:
450: public boolean isStopOnErrors() {
451: return classMap.isTrimStrings();
452: }
453:
454: public String toString() {
455: return new ToStringBuilder(this , ToStringStyle.MULTI_LINE_STYLE)
456: .append("source field", srcField).append(
457: "destination field", destField).append("type",
458: type)
459: .append("customConverter", customConverter).append(
460: "relationshipType", relationshipType).append(
461: "removeOrphans", removeOrphans).append("mapId",
462: mapId).append("copyByReference",
463: copyByReference).append(
464: "copyByReferenceOveridden",
465: copyByReferenceOveridden).append("srcTypeHint",
466: srcHintContainer).append("destTypeHint",
467: destHintContainer).toString();
468: }
469:
470: }
|