最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - ModelMapper and mappic specific types - Stack Overflow

programmeradmin0浏览0评论

I want to limit types mapped by my ModelMapper in case when I'm mapping from dto model to entity.

I've defined ModelMapper like this:

    var modelMapper = new ModelMapper();
    modelMapper.getConfiguration()
            .setMatchingStrategy(MatchingStrategies.STRICT)
            .setPreferNestedProperties(false)
            .setFullTypeMatchingRequired(true)
            .setPropertyCondition(
                    Conditions.or(Conditions.isType(String.class),
                    Conditions.or(Conditions.isType(Integer.class),
                    Conditions.or(Conditions.isType(Long.class)))));

Unfortunatly it doesn't work. During compilation I got an error:

method or in class org.modelmapper.Conditions cannot be applied to given types;

What is wrong? Is there any other method to do that?

I want to limit types mapped by my ModelMapper in case when I'm mapping from dto model to entity.

I've defined ModelMapper like this:

    var modelMapper = new ModelMapper();
    modelMapper.getConfiguration()
            .setMatchingStrategy(MatchingStrategies.STRICT)
            .setPreferNestedProperties(false)
            .setFullTypeMatchingRequired(true)
            .setPropertyCondition(
                    Conditions.or(Conditions.isType(String.class),
                    Conditions.or(Conditions.isType(Integer.class),
                    Conditions.or(Conditions.isType(Long.class)))));

Unfortunatly it doesn't work. During compilation I got an error:

method or in class org.modelmapper.Conditions cannot be applied to given types;

What is wrong? Is there any other method to do that?

Share Improve this question asked Feb 6 at 11:47 OlekOlek 35911 silver badges24 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

The error is caused when Java resolves the actual type arguments of the isType calls to determine the corresponding ones for the or call. This is an issue with the usage of Java generics in this specific case.

As we can see in the signature of or method it accepts two Conditions, which have the same type parameters (ie S and D). But isType returns wildcard type parameters (ie both are ?). Wildcard type parameters here mean that any type is acceptable. But or expects two arguments with the same type parameters. Since type parameters of both arguments to or can be anything (as returned by the two isType calls) then they can be different too, hence the error.

For example, the following code:

public class Main {

    private static interface Condition<A, B> {
    }

    private static <S, D> Condition<S, D> or(final Condition<S,D> condition1,
                                             final Condition<S,D> condition2) {
        return null; //Doesn't matter to have an actual instance here.
    }

    public static void main(final String[] args) {
        final Condition<?, ?> c1 = null, //Doesn't matter to have an actual instance here.
                              c2 = null; //Doesn't matter to have an actual instance here.
        or(c1, c2); //Compilation error here.
    }
}

... produces the following full compilation error message:

method or in class Main cannot be applied to given types;
  required: Condition,Condition
  found: Condition,Condition
  reason: inference variable S has incompatible equality constraints CAP#3,CAP#1
  where S,D are type-variables:
    S extends Object declared in method or(Condition,Condition)
    D extends Object declared in method or(Condition,Condition)
  where CAP#1,CAP#2,CAP#3,CAP#4 are fresh type-variables:
    CAP#1 extends Object from capture of ?
    CAP#2 extends Object from capture of ?
    CAP#3 extends Object from capture of ?
    CAP#4 extends Object from capture of ?

As you can see for example CAP#1 extends Object, but so does CAP#3. The same is true for CAP#2 vs CAP#4. Since all of these extend Object, but no other constraint is in place, then they can be different subclasses of Object, but or requires the same S for both its arguments, and the same D for both its arguments.

For example CAP#1 can be (say) an Integer and CAP#3 (say) a String. So while they would satisfy the wildcard, they cannot satisfy S (which is required to be the same for both or's arguments) since Integer and String are not the same.

Also, the last call to or is missing its second argument entirely, but that's not the error questioned here.


I am not familiar with ModelMapper, but (according to its documentation and source code) it seems that the following method may help to workaround the issue:

public static <S, D> Condition<S, D> isAnyTypeOf(final Class<? extends S>... sourceTypes) {
    final List<Class<?>> testTypes = Collections.unmodifiableList(Arrays.asList(sourceTypes.clone()));
    return (final MappingContext<S, D> context) -> {
        final Class<S> srcType = context.getSourceType();
        return testTypes.stream().anyMatch(testType -> testType.isAssignableFrom(srcType));
    };
}

And use it like:

var modelMapper = new ModelMapper();
modelMapper.getConfiguration()
        .setMatchingStrategy(MatchingStrategies.STRICT)
        .setPreferNestedProperties(false)
        .setFullTypeMatchingRequired(true)
        .setPropertyCondition(isAnyTypeOf(String.class, Integer.class, Long.class));
发布评论

评论列表(0)

  1. 暂无评论