2013-05-16 33 views
1

我正在使用推土機版本5.4.0。爲什麼推土機將空源對象傳遞給我的可配置自定義轉換器?

我有一個類,其中包含一個Map,另一個類有一個List。我正在嘗試編寫一個自定義轉換器,它將採用地圖的值並將其放入列表中。但問題是,即使父源具有填充的Map,轉換器也始終會傳遞Map的空源對象。我無法弄清楚爲什麼會發生這種情況,我認爲轉換器應該傳遞一個填充的Map對象。

這裏是編譯和展示了運行中的一些問題的源代碼:

package com.sandbox; 

import org.dozer.DozerBeanMapper; 
import org.dozer.loader.api.BeanMappingBuilder; 
import org.dozer.loader.api.FieldsMappingOptions; 

public class Sandbox { 

    public static void main(String[] args) { 
     DozerBeanMapper mapper = new DozerBeanMapper(); 
     mapper.addMapping(new MappingConfig()); 

     ClassWithMap parentSource = new ClassWithMap(); 
     ClassWithList parentDestination = mapper.map(parentSource, ClassWithList.class); 

     int sourceMapSize = parentSource.getMyField().size(); 
     assert sourceMapSize == 1; 
     assert parentDestination.getMyField().size() == 1; //this assertion fails! 
    } 

    private static class MappingConfig extends BeanMappingBuilder { 

     @Override 
     protected void configure() { 
      mapping(ClassWithMap.class, ClassWithList.class) 
        .fields("myField", "myField", 
          FieldsMappingOptions.customConverter(MapToListConverter.class, "com.sandbox.MyMapValue")); 
     } 
    } 


} 

正如你所看到的,第二個斷言失敗。以下是我正在使用的其他課程。

MapToListConverter.java:

package com.sandbox; 

import org.dozer.DozerConverter; 
import org.dozer.Mapper; 
import org.dozer.MapperAware; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.Map; 

public class MapToListConverter extends DozerConverter<Map, List> implements MapperAware { 

    private Mapper mapper; 

    public MapToListConverter() { 
     super(Map.class, List.class); 
    } 

    @Override 
    public List convertTo(Map source, List destination) { //source is always null, why?! 
     List convertedList = new ArrayList(); 
     if (source != null) { 
      for (Object object : source.values()) { 
       Object mappedItem = mapper.map(object, getDestinationClass()); 
       convertedList.add(mappedItem); 
      } 
     } 
     return convertedList; 
    } 

    private Class<?> getDestinationClass() { 
     try { 
      return Class.forName(getParameter()); 
     } catch (ClassNotFoundException e) { 
      throw new IllegalArgumentException(e); 
     } 
    } 

    @Override 
    public Map convertFrom(List source, Map destination) { 
     throw new UnsupportedOperationException(); 
    } 

    @Override 
    public void setMapper(Mapper mapper) { 
     this.mapper = mapper; 
    } 
} 

ClassWithMap.java:

package com.sandbox; 

import java.util.HashMap; 
import java.util.Map; 

public class ClassWithMap { 

    private Map<String, MyMapValue> myField; 

    public Map<String, MyMapValue> getMyField() { //this method gets called by dozer, I've tested that with a break point 
     if (myField == null) { 
      myField = new HashMap<String, MyMapValue>(); 
      myField.put("1", new MyMapValue()); 
     } 
     return myField; //myField has an entry in it when called by dozer 
    } 

    public void setMyField(Map<String, MyMapValue> myField) { 
     this.myField = myField; 
    } 

} 

ClassWithList.java:

package com.sandbox; 

import java.util.List; 

public class ClassWithList { 

    private List<MyMapValue> myField; 

    public List<MyMapValue> getMyField() { 
     return myField; 
    } 

    public void setMyField(List<MyMapValue> myField) { 
     this.myField = myField; 
    } 
} 

MyMapValue.java

package com.sandbox; 

public class MyMapValue { 

} 

這個問題似乎出現在推土機的MapFieldMap.getSrcFieldValue方法中。這些評論是由我加上:

@Override 
    public Object getSrcFieldValue(Object srcObj) { 
    DozerPropertyDescriptor propDescriptor; 
    Object targetObject = srcObj; 

    if (getSrcFieldName().equals(DozerConstants.SELF_KEYWORD)) { 
     propDescriptor = super.getSrcPropertyDescriptor(srcObj.getClass()); 
    } else { 
     Class<?> actualType = determineActualPropertyType(getSrcFieldName(), isSrcFieldIndexed(), getSrcFieldIndex(), srcObj, false); 
     if ((getSrcFieldMapGetMethod() != null) 
      || (this.getMapId() == null && MappingUtils.isSupportedMap(actualType) && getSrcHintContainer() == null)) { 
     // Need to dig out actual map object by using getter on the field. Use actual map object to get the field value 
     targetObject = super.getSrcFieldValue(srcObj); 

     String setMethod = MappingUtils.isSupportedMap(actualType) ? "put" : getSrcFieldMapSetMethod(); 
     String getMethod = MappingUtils.isSupportedMap(actualType) ? "get" : getSrcFieldMapGetMethod(); 
     String key = getSrcFieldKey() != null ? getSrcFieldKey() : getDestFieldName(); 

     propDescriptor = new MapPropertyDescriptor(actualType, getSrcFieldName(), isSrcFieldIndexed(), getDestFieldIndex(), 
       setMethod, getMethod, key, getSrcDeepIndexHintContainer(), getDestDeepIndexHintContainer()); 
     } else { 
     propDescriptor = super.getSrcPropertyDescriptor(srcObj.getClass()); 
     } 
    } 

    Object result = null; 
    if (targetObject != null) { 
     result = propDescriptor.getPropertyValue(targetObject); //targetObject is my source map, but the result == null 
    } 

    return result; 

    } 
+0

我認爲這可能是一個錯誤,所以我提出一個問題,他們的問題跟蹤:https://github.com/DozerMapper /推土機/問題/ 103 –

回答

2

我想出瞭如何解決這個問題。仍然不確定這是否是一個錯誤,但我認爲它是。解決辦法是將我的配置更改爲:

 mapping(ClassWithMap.class, ClassWithList.class, TypeMappingOptions.oneWay()) 
       .fields("myFields", "myFields" 
         , FieldsMappingOptions.customConverter(MapToListConverter.class, "com.sandbox.MyMapValue") 
       ); 

修復程序位於TypeMappingOptions.oneWay()。當它是雙向的,MappingsParser試圖推土機使用MapFieldMap這會導致我的問題:

// iterate through the fields and see wether or not they should be mapped 
    // one way class mappings we do not need to add any fields 
    if (!MappingDirection.ONE_WAY.equals(classMap.getType())) { 
     for (FieldMap fieldMap : fms.toArray(new FieldMap[]{})) { 
     fieldMap.validate(); 

     // If we are dealing with a Map data type, transform the field map into a MapFieldMap type 
     // only apply transformation if it is map to non-map mapping. 
     if (!(fieldMap instanceof ExcludeFieldMap)) { 
      if ((isSupportedMap(classMap.getDestClassToMap()) 
        && !isSupportedMap(classMap.getSrcClassToMap())) 
       || (isSupportedMap(classMap.getSrcClassToMap()) 
        && !isSupportedMap(classMap.getDestClassToMap())) 
       || (isSupportedMap(fieldMap.getDestFieldType(classMap.getDestClassToMap())) 
        && !isSupportedMap(fieldMap.getSrcFieldType(classMap.getSrcClassToMap()))) 
       || (isSupportedMap(fieldMap.getSrcFieldType(classMap.getSrcClassToMap()))) 
        && !isSupportedMap(fieldMap.getDestFieldType(classMap.getDestClassToMap()))) { 
      FieldMap fm = new MapFieldMap(fieldMap); 
      classMap.removeFieldMapping(fieldMap); 
      classMap.addFieldMapping(fm); 
      fieldMap = fm; 
      } 
     } 
相關問題