tags:

views:

595

answers:

3

Is there a way to map collection size in dozer?

class Source {
    Collection<String> images;
}

class Destination {
  int numOfImages;
}
+1  A: 

EDIT: I've updated my answer to use a custom converter at the field level instead of at the class level.

There might be other solutions but one way to do this would be to use a Custom Converter. I've added getters and setters to your classes and wrote the following converter:

package com.mycompany.samples.dozer;

import java.util.Collection;

import org.dozer.DozerConverter;

public class TestCustomFieldConverter extends 
        DozerConverter<Collection, Integer> {

    public TestCustomFieldConverter() {
        super(Collection.class, Integer.class);
    }

    @Override
    public Integer convertTo(Collection source, Integer destination) {
        if (source != null) {
            return source.size();
        } else {
            return 0;
        }
    }

    @Override
    public Collection convertFrom(Integer source, Collection destination) {
        throw new IllegalStateException("Unknown value!");
    }
}

Then, declare it in a custom XML mapping file:

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozer.sourceforge.net
          http://dozer.sourceforge.net/schema/beanmapping.xsd"&gt;
  <mapping>
    <class-a>com.mycompany.samples.dozer.Source</class-a>
    <class-b>com.mycompany.samples.dozer.Destination</class-b>
    <field custom-converter="com.mycompany.samples.dozer.TestCustomFieldConverter">
      <a>images</a>
      <b>numOfImages</b>
    </field>
  </mapping>        
</mappings>

With this setup, the following test passes successfully:

@Test
public void testCollectionToIntMapping() {
    List<String> mappingFiles = new ArrayList<String>();
    mappingFiles.add("com/mycompany/samples/dozer/somedozermapping.xml");
    Mapper mapper = new DozerBeanMapper(mappingFiles);

    Source sourceObject = new Source();
    sourceObject.setImages(Arrays.asList( "a", "b", "C" ));

    Destination destObject = mapper.map(sourceObject, Destination.class);

    assertEquals(3, destObject.getNumOfImages());
}
Pascal Thivent
Thanks for answer. But by using custom converter at class level I wouldn't benefit from dozer automatic conversion of other fields (my real 'Source' and 'Destination' are richer). Nevertheless using your example I implemented the 'CollectionSizeConverter' which maybe specified at the field level:<mapping type="one-way">....<field custom-converter="my.CollectionSizeConverter"> <a>images</a> <b>numOfImages</b></field>
Gennady Shumakher
Indeed, it may be better to use a field converter in your case. But, well, I guess you get the idea :)
Pascal Thivent
A: 

The above example giving the exception like

Type: null Source parent class: dozerPackage.Source Source field name: images Source field type: class java.util.ArrayList Source field value: [www, eee] Dest parent class: dozerPackage.Destination Dest field name: numOfImages Dest field type: int org.dozer.MappingException: Destination Type (int) is not accepted by this Custom Converter (dozerPackage.TestCustomFieldConverter)!

is there any way to use custom convertor for primitive types.

koti
A: 

Hi, thanks.

But when i run the test, it throws an exception

org.dozer.MappingException: java.lang.InstantiationException: ... Caused by: java.lang.InstantiationException: com.mycompany.TestCustomFieldConverter

any help to instanciate it?

Kitop