Java – custom dozer mapping

dozerjava

I'm trying to use Dozer to convert an instance of

class Source {
  private List<Foo> foos = new ArrayList<Foo>();

  public List<Foo> getFoos() {
    return foos;
  }

  public void setFoos(List<Foo> foos) {
    this.foos = foos;
  }
}

to an instance of:

class Target {
  private List<Foo> foos = new ArrayList<Foo>();

  public List<Foo> getFoos() {
    return foos;
  }
}

In Java code I would preform the converstion like this

Source s = new Source();
Target t = new Target();
t.getFoos().addAll(s.getFoos());

Dozer doesn't perform this conversion by default because Target doesn't have a foos property (just a getter).

In reality, I have lots of properties like this that I need to map. One option is to tell Dozer to map the private fields directly, but this is not entirely satisfactory because:

  • I will need to specify each field to be mapped in this way by name in the Dozer XML config
  • accessing private fields is bad

Is there a better way?

Best Answer

There is no easy way to get around this other than the is-accessible flag. But you could define a custom converter that uses the getter to do:

t.getFoos().addAll(s.getFoos());

This would be very heavy handed and alot of work. You would need to define a custom converter (see http://dozer.sourceforge.net/documentation/customconverter.html) between Source and Target that used the getter instead of the setter:

public class TestCustomConverter implements CustomConverter {

  public Object convert(Object destination, Object source, Class destClass, Class sourceClass) {
    if (source == null) {
      return null;
    }
    if (source instanceof Source) {
      Target dest = null;
      // check to see if the object already exists
      if (destination == null) {
        dest = new Target();
      } else {
        dest = (Target) destination;
      }
      dest.getFoos().addAll(((Source)source).getFoos());
      return dest;
    } else if (source instanceof Target) {
      Source dest = null;
      // check to see if the object already exists
      if (destination == null) {
        dest = new Source();
      } else {
        dest = (Source) destination;
      }
      dest.setFoos(((Target)source).getFoos());
      return dest;
    } else {
      throw new MappingException("Converter TestCustomConverter used incorrectly. Arguments passed in were:"
          + destination + " and " + source);
    }
  } 

I think, good luck

Related Topic