From e53579833bb04149fd8d71d6008b7bfdfceef09e Mon Sep 17 00:00:00 2001 From: gilbertg Date: Tue, 6 Oct 2015 18:10:58 +0200 Subject: [PATCH] Implemented CustomFieldValidator to inject a point of prevention before a source field value is fetched during mapping A custom field validator is usually in conjunction with a CustomFieldMapper when implementing the CustomFieldMapperAndValidator interface. Use this when you want logic to prevent source field values being fetched. e.g. when checking lazy loaded relationships in an ORM If a custom field validator is specified, Dozer will invoke this class when performing all field mappings. If false is returned from the call the source field value will never be fetched, and subsequently the field will never be mapped. --- .../dozer/CustomFieldMapperAndValidator.java | 9 +++++ .../java/org/dozer/CustomFieldValidator.java | 20 ++++++++++ .../main/java/org/dozer/MappingProcessor.java | 39 ++++++++++++------- 3 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 core/src/main/java/org/dozer/CustomFieldMapperAndValidator.java create mode 100644 core/src/main/java/org/dozer/CustomFieldValidator.java diff --git a/core/src/main/java/org/dozer/CustomFieldMapperAndValidator.java b/core/src/main/java/org/dozer/CustomFieldMapperAndValidator.java new file mode 100644 index 000000000..17bfd8869 --- /dev/null +++ b/core/src/main/java/org/dozer/CustomFieldMapperAndValidator.java @@ -0,0 +1,9 @@ +package org.dozer; + +/** + * Public custom field validator and mapper interface. + * Implement this interface on your custom field mapper if you want to implement both CustomFieldMapper & CustomFieldValidator functions + * + * @author Gilbert Grant + */ +public interface CustomFieldMapperAndValidator extends CustomFieldMapper, CustomFieldValidator {} diff --git a/core/src/main/java/org/dozer/CustomFieldValidator.java b/core/src/main/java/org/dozer/CustomFieldValidator.java new file mode 100644 index 000000000..b391fb746 --- /dev/null +++ b/core/src/main/java/org/dozer/CustomFieldValidator.java @@ -0,0 +1,20 @@ +package org.dozer; + +import org.dozer.classmap.ClassMap; +import org.dozer.fieldmap.FieldMap; + +/** + * Public custom field validator interface. A custom field validator is usually in conjunction with a CustomFieldMapper + * when implementing the CustomFieldMapperAndValidator interface. + * Use this when you want logic to prevent source field values being fetched + * e.g. when checking lazy loaded relationships in an ORM + * + *

+ * If a custom field validator is specified, Dozer will invoke this class when performing all field mappings. If false is + * returned from the call the source field value will never be fetched, and subsequently the field will never be mapped. + * + * @author Gilbert Grant + */ +public interface CustomFieldValidator { + boolean canMapField(Object source, Object destination, ClassMap classMap, FieldMap fieldMapping); +} diff --git a/core/src/main/java/org/dozer/MappingProcessor.java b/core/src/main/java/org/dozer/MappingProcessor.java index 520d62192..78eb67deb 100644 --- a/core/src/main/java/org/dozer/MappingProcessor.java +++ b/core/src/main/java/org/dozer/MappingProcessor.java @@ -336,22 +336,31 @@ private void mapField(FieldMap fieldMapping, Object srcObj, Object destObj) { // custom field mapper returns false(indicating the // field was not actually mapped by the custom field mapper), proceed as // normal(use Dozer to map the field) - srcFieldValue = fieldMapping.getSrcFieldValue(srcObj); - boolean fieldMapped = false; - if (customFieldMapper != null) { - fieldMapped = customFieldMapper.mapField(srcObj, destObj, srcFieldValue, fieldMapping.getClassMap(), fieldMapping); - } - if (!fieldMapped) { - if (fieldMapping.getDestFieldType() != null && ITERATE.equals(fieldMapping.getDestFieldType())) { - // special logic for iterate feature - mapFromIterateMethodFieldMap(srcObj, destObj, srcFieldValue, fieldMapping); - } else { - // either deep field map or generic map. The is the most likely - // scenario - mapFromFieldMap(srcObj, destObj, srcFieldValue, fieldMapping); - } - } + boolean canMapField = true; + if (customFieldMapper != null && customFieldMapper instanceof CustomFieldMapperAndValidator) { + canMapField = ((CustomFieldMapperAndValidator)customFieldMapper).canMapField(srcObj, destObj, fieldMapping.getClassMap(), fieldMapping); + } + + if (canMapField) { + boolean fieldMapped = false; + + srcFieldValue = fieldMapping.getSrcFieldValue(srcObj); + if (customFieldMapper != null) { + fieldMapped = customFieldMapper.mapField(srcObj, destObj, srcFieldValue, fieldMapping.getClassMap(), fieldMapping); + } + + if (!fieldMapped) { + if (fieldMapping.getDestFieldType() != null && ITERATE.equals(fieldMapping.getDestFieldType())) { + // special logic for iterate feature + mapFromIterateMethodFieldMap(srcObj, destObj, srcFieldValue, fieldMapping); + } else { + // either deep field map or generic map. The is the most likely + // scenario + mapFromFieldMap(srcObj, destObj, srcFieldValue, fieldMapping); + } + } + } statsMgr.increment(StatisticType.FIELD_MAPPING_SUCCESS_COUNT);