Dozer deep propery mapping with custom converter

dozermapping

I have deep property mapping in my application (from domain objects to DTO, and the reverse), similar to next example:

...

<field>
    <a>employee.id</a>
    <b>employeeId</a>
</field>

...

When Dozer converts Domain to DTO, it maps employee.id to employeeId, and that is ok.
When Dozer converts DTO to Domain, it maps employeeId to a new Employee instance with id=employeeId.

I want to create some logic for this deep property mapping, but i just can't figure out solution. I tried to implement CustomConverter(or extend DozerConverter) but Dozer passes me Integer type as source and destination class(and expect Integer as result).

EDIT:
More precisely, what i need is to map employee in Domain to null if employeeId in DTO is 0.

Is this possible?

Any advice?

EDIT ACCORDING TO ANSWERS:
I solve problem with field-level custom converter. Instead of earlier, above mentioned, mapping, now i have something like this…

...

<field custom-converter="ManyToOneIdMapper" custom-converter-param="id">
    <a>employee</a>
    <b>employeeId</b>
</field>

...

In ManyToOneIdMapper i have…

public class ManyToOneIdMapper implements ConfigurableCustomConverter{

//...
//parameter field declaration, setParameter and getParameter implementations etc.
//...

public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, 
        Class<?> destinationClass, Class<?> sourceClass) {
    try {

        if(sourceClass.equals(Integer.class)){
            Integer src=(Integer)sourceFieldValue;

            if(src==null || src==0)
                return null;

            String setterName=formatMethodName("set", getParameter());
            Method setterMethod=destinationClass.getMethod(setterName, Integer.class);
            Object instance=destinationClass.newInstance();

            setterMethod.invoke(instance, src);

            return instance;
        }else{    
            if(sourceFieldValue==null)
                return 0;

            String getterName=formatMethodName("get", getParameter());
            Method getterMethod=sourceClass.getMethod(getterName);
            Object instance=getterMethod.invoke(sourceFieldValue);

            return instance;
        }
    } catch (Exception e){}
    return null;
}

/**
 * @return - method name (most often setter or getter)  according to fieldName.
 * For example formatMethodName("get", "id") returns "getId"
 */
protected String formatMethodName(String methodPrefix, String fieldName){
    String trimmedFieldName=fieldName.trim();
    String firstLetter=String.valueOf(trimmedFieldName.charAt(0));
    String capitalizedFirstLetter=firstLetter.toUpperCase();
    String methodName=methodPrefix+""+capitalizedFirstLetter+""+fieldName.substring(1);

    return methodName;
}

custom-converter-param is just name of id-field in Domain object. With that name, i just call setter or getter method in my converter. Probably, it is not the happiest solution, but it works for my problem scenario.

Best Answer

You can either use a CustomConverter (per the other answer), or use a DozerEventListener to set the employee object back to null after the mapping has finished, if the ID is 0.

Related Topic