Git Product home page Git Product logo

modelmapper's Introduction

ModelMapper

CI Maven Central License

ModelMapper is an intelligent object mapping library that automatically maps objects to each other. It uses a convention based approach while providing a simple refactoring safe API for handling specific use cases.

Visit modelmapper.org to learn more.

Modules

In v2.0, ModelMapper provides modules for 3rd library integration you can easily register by modelMapper.registerModule(new TheModule()).

Related Projects

Contributing

Bug reports and feature requests are welcome via the issue tracker. Fixes and enhancements are also welcome via pull requests. If you're unsure about a contribution idea, feel free to contact me.

modelmapper's People

Contributors

chhsiao90 avatar christophgr avatar codehumane avatar da-z avatar devnied avatar dreamking60 avatar ehmkah avatar flet avatar hadri3n avatar i3nakadj avatar jhalterman avatar jmbreuer avatar kbakaras avatar kregoslup avatar mdzhigarov avatar ncjones avatar nfalco79 avatar niccccccccer avatar nthalk avatar peter-catalin avatar ryeon9445 avatar s1mm0t avatar sergey-soloviov avatar sskrla avatar surajdhamecha avatar sventorben avatar taher-ghaleb avatar vignesh-ideas avatar vincemann avatar wangzw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

modelmapper's Issues

Add configuration setting for fail-fast matching/mapping

This is a marker. We'll wait and see if there's interest in this...

By default ModelMapper will not throw an exception if destination members are unmapped unless validate is called. A fail-fast configuration setting can be added to allow this behavior.

matches multiple source property hierarchies problem

Hi, I'm using JPA(with Hibernate) and wish to convert some composite domain to view layer, So I'm using ModelMapper also.

At first, I defined some domain and DTO classes.

@Entity
public class User {
    ...
    @Id
    String id;

    @OneToOne
    Preference preference;
    ...
}

@Entity
public class Preference {
    ...
    @Id
    String id;

    @OneToOne
    User user;

    BigDecimal money;
    ...
}

public class UserDto {
    ...
    String id;
    BigDecimal preferenceMoney;
    ...
}

then, I've tried to mapping DTO object instance to domain object instance.

UserDto userDto = new UserDto();
userDto.setPreferenceMoney(1000.0);
mapper.map(userDto, User.class);

this code returns error

1) The destination property User.setPreference()/Preference.setUser() matches multiple source property hierarchies:

Skipping to set user to Preference class suppress this error, but when saving data to persist returned exception that preference object instance couldn't get user property. :(

Is this an another case of circular reference problem? I've dig circular reference test cases, but I can't find a solution.

Add support for combined token matching

Look into whether combined token matching support can be added to the matching strategies. This would allow customermailingaddress to match customerMailingAddress.

Map mocked objects

Hi,

Mocked objects (e.g. with Mockito) are not handled correctly by Modelmapper. Following unit test fails:

import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.modelmapper.ModelMapper;
import org.modelmapper.PropertyMap;

public class SklTest {

@Test
public void test() {
    ModelMapper mapper = new ModelMapper();
    mapper.addMappings(new Mapper());

    A a = Mockito.mock(A.class);
    Mockito.when(a.getName()).thenReturn("hello");
    B b = mapper.map(a, B.class);

    Assert.assertEquals("hello", b.getNameProp());

}

public static class Mapper extends PropertyMap<A, B> {

    @Override
    protected void configure() {
        map().setNameProp(source.getName());
    }
}

public static class A {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public static class B {

    private String nameProp;

    public String getNameProp() {
        return nameProp;
    }

    public void setNameProp(String nameProp) {
        this.nameProp = nameProp;
    }
}

}

Converter not given appropriate concrete type when mapping to generic interface implementing objects

The following assertion will fail when trying to map the objects as the context only sees the upperbound of the TreeElement type instead of the actual type.

DomainObject.java

public class DomainObject implements Converter<String, DomainObject> {
    public DomainObject convert(MappingContext<Long, DomainObject> context) {
        assert !context.getMapping().getLastDestinationProperty().getType().equals(Object.class);

    return ..;
    }
}

SomeThingXML.java

@Getter @Setter
@XmlRootElement
public class SomeThingXML {
    private someThingId;
}

TreeElement.java

public interface TreeElement<P> {
    public void setParent(P parent):
    public P    getParent();
}

SomeThing.java

@Getter @Setter
public class SomeThing extends DomainObject, TreeElement<SomeThing> {
    private SomeThing parent;
}

SomethingPropertyMap.java

public class SomethingPropertyMap extends PropertyMap<SomeThingXML, SomeThing> {
    public void configure() {
        using(resolver).map(source.getSomeThingId()).setParent(null);
    }
}

Support mapping from non-Beans

Creates SPI that adds support for mapping from non-Beans such as Maps (and Map of Maps) Jackson JsonNodes, jOOQ Records, etc.

Support for enum types

I think should be easy method/way to map enums in modelmapper. Now I try to map few enums in my classes and I'm sitting on it couple hours.

Support mapping to/from unknown types

When mapping to/from a ParameterizedType, a property type can be unknown until actual mapping takes place. Ex:

class Src {
String value;
}

class Dst<T> {
T value;
}

These fields will not match since we cannot verify that value will be convertable to whatever T ends up being.

The values of destination fields are ignored in map operation

I want to execute an arithmetical operation between a source value and a destination value in mapping operation.

I have a source object and I load a destination object to execute the map method of ModelMapper class. I use a converter class for this particular fields but when I get the destination for the mapping context (MappingContext.getDestination()) I always get a null value.

I've searched into code and i've seen this line (MappingEngineImpl.propertyContextFor(MappingEngineImpl:296)):


return new MappingContextImpl(context, source, sourceType, null, destinationType, mapping, !cyclic);

Why not pass the destination object?

Bad detection of circular refs by source object values

Modelmapper release 0.5.1 store source and destination mapped object in HashMap MappingContextImpl.sourceToDestination. Because source (key) is identified by value, there is oportunity to incorrectly detect another source object with same value as circular reference.

Possible fix is use IdentityHashMap instead of HashMap.

Unable to create custom Mapping

Mapping from a String to a date

Given the code snippet below :

PropertyMap<TransactionLoadDTO, Transaction> transMap = new PropertyMap<TransactionLoadDTO, Transaction>() {

                protected void configure() {
                    try {
                        Date date = new SimpleDateFormat().parse(source.getDate());
                        map().setTransactionDate(date);
                    } catch (ParseException e) {
                        e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                    }

                }
            };

It creates the exception below :

  1. An error occured while building mappings

1 error
org.modelmapper.ConfigurationException: ModelMapper configuration errors:

  1. An error occured while building mappings

1 error
at org.modelmapper.internal.Errors.throwConfigurationExceptionIfErrorsExist(Errors.java:224)
at org.modelmapper.internal.MappingBuilderImpl.build(MappingBuilderImpl.java:138)
at org.modelmapper.internal.TypeMapImpl.addMappings(TypeMapImpl.java:69)
at org.modelmapper.internal.TypeMapStore.getOrCreate(TypeMapStore.java:93)
at org.modelmapper.ModelMapper.addMappings(ModelMapper.java:90)
at controllers.Account.uploadTransactions(Account.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:557)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:508)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:484)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:479)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
at play.server.PlayHandler$NettyInvocation.execute(PlayHandler.java:251)
at play.Invoker$Invocation.run(Invoker.java:278)
at play.server.PlayHandler$NettyInvocation.run(PlayHandler.java:229)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.NoSuchMethodException: controllers.Account$1.getSource()
at java.lang.Class.getMethod(Class.java:1607)
at play.classloading.enhancers.PropertiesEnhancer$FieldAccessor.invokeReadProperty(PropertiesEnhancer.java:220)
at controllers.Account$1.configure(Account.java:81)
at org.modelmapper.PropertyMap.configure(PropertyMap.java:270)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.modelmapper.internal.MappingBuilderImpl.build(MappingBuilderImpl.java:123)

Add support of circular reference.

These classes have corresponding dtoยดs:

public class Book {
private String id;
private String name;
private List authors;
/* getters and setters */
}

public class Author {
private String id;
private String firstName;
private String lastName;
private String middleName;
private List books;
/* getters and setters */
}

public class Library {
private String id;
private List books;
private List authors;
/* getters and setters */
}

Implement Eventing

Start wit 4 events: preMap and postMap, which would be called before and after a particular object is mapped, and prePropertyMap and postPropertyMap which would be called before and after each property on a destination object is mapped from a source object. The event object itself would look something like the MappingContext.

Add support for TypeTokens

List<ProductDto> productDtos = modelMapper.map(products, new TypeToken<List<ProductDto>>(){}.getType());

Mapping creates instances for null objects

If both source and destination have a matching property that is a complex object, when the property on source is null mapping causes the property on the destination to be created by the default constructor.

public class Source
{
    private SourceProperty property;

    ...
}

public class Destination
{
    private DestinationProperty property;

    ...
}

// source.getProperty() is null
Source source = new Source ();

// this results in destination.getProperty() not null
Destination destination = mapper.map(source, Destination.class);

PropertyMapping added to TypeMap ignored when mapping a structure

If try to map data from two related objects to two other related objects. Unfortunately TypeMap is ignored in this case.

First structure is a ProjectType having one project manager of type UserType. On the other hand there is a Project having one Person that is in role project manager. Flat mapping looks as follows:

  • ProjetType -> Project
  • UserType -> User

One field of UserType differ from Person. UserType has a userId whereas Person has a userName. For mapping I thus created a TypeMap and added a custom mapping for just this single field.

As long as I do a flat mapping as described above the TypeMap with custom mapping is used by model mapper and thus the mapped User has userName != null. Fine!

But if I try to map a ProjectType with UserType set the custom mapping was not applied. Is this correct or a bug? I would expect that once a TypeMap was specified modelmapper uses it whenever possible.

I could provide you with a JUnit test to reproduce this. If you want it, please let me know.

Can't get String->custom Enum conversion working

I cannot get a custom Enum class property mapped from a String without some really weird configuration. The Enum class has a static .fromString method that I want used for any conversions but so far the recommended ways of doing this don't seem to work.. Here goes..

ServiceOperation class with a 'cmd' field. Command is a custom Enum class (the one I'm having issues with)

public class ServiceOperation
{
      private String target;
      private Command cmd;

...get and set for both fields...
}

ServiceOperationDTO class, which has all String fields.... mapping the .cmdStr of this class this back to ServiceOperation.cmd is the issue

public class ServiceOperationDTO
{
   private String target;
   private String cmdStr;

...get and set for both fields...
}

Command Enum class that has custom string mappings and static .fromString method
to convert back from strings

public enum Command
{
   Up, Down, Once, Pause, Cont, Hup, Alarm, Interrupt, Quit, Usr1("1"), Usr2(
         "2"), Term, Kill, Exit, Status, Start, Stop, Restart, Shutdown, ForceStop(
         "force-stop"), ForceReload("force-reload"), ForceRestart(
         "force-restart"), ForceShutdown("force-shutdown"), Check, Invalid;

   private static final Map<String,Command> lookup = new HashMap<String,Command>();

   static {
      for(Command c : EnumSet.allOf(Command.class))
         lookup.put(c.toString(), c);
   }

   Command()
   {
      this.value = this.name().toLowerCase();
   }

   Command(String svCmd)
   {
      this.value = svCmd;
   }

   @Override
   public String toString()
   {
      return value;
   }

   public static Command fromString(String cmd) { 
        return lookup.get(cmd); 
   }

   private final String value;
}

Going from ServiceOperation -> ServiceOpertationDTO works fine... However going from ServiceOperationDTO -> ServiceOperation fails except in one case. Here's the sample code that invokes the mapper and asserts whether the mapping worked.

      ServiceOperationDTO dto = new ServiceOperationDTO();
      dto.setCmd("force-stop");
      dto.setTarget("myService");
      ServiceOperation domainObj  = mapper.map(dto, ServiceOperation.class);
      System.out.format("DOMAIN target=%s cmd=%s\n", domainObj.getTarget(),
            domainObj.getCmd());
      assertTrue(domainObj.getCmd() == Command.ForceStop);

by default the .cmd field ends up as null since modelmapper doesn't know how to convert from String-> Command (which is expected).
The assertion fails since domainObj.cmd ends up being null. mapper.validate()
confirms with a validation exception saying...

Unmapped destination properties found in
TypeMap[ServiceOperationDTO -> ServiceOperation]:
ServiceOperation.setCmd(

Below are various ways I've tried to get things working (i.e. have modelmapper use Command.fromString to convert String->Command)..

  1. Tried adding an explicit Converter that goes from String->Command.. seemed easy enough from the docs. This doesn't work, the code doesn't get called at all. Stepping through the modelmapper code where it iterates through getMappings() showed there was no mapping for String->Command. However adding another Converter for String->String did work for all String fields. So I guess there's something about the Command class that makes modelmapper not add the mapping
      mapper.addConverter(new Converter<String, Command>()
      {
         @Override
         public Command convert(MappingContext<String, Command> context)
         {
            String source = context.getSource();
            return source == null ? null : Command.fromString(source);
         }
      });
  1. Tried using createTypeMap, as shown in the example at #10
    Same as before the code doesn't get called at all.
      mapper.createTypeMap(String.class, Command.class).setConverter(
            new Converter<String, Command>() {
               public Command convert(MappingContext<String, Command> context)
               {  
                  String source = context.getSource();
                  return source == null ? null : Command.fromString(source);
               }
        });
  1. Tried adding a PropertyMap along with mapper.addMappings(), but still doesn't work
      final Converter<String, Command> cmdToString = new AbstractConverter<String, Command>() {
         protected Command convert(String source)
         {
            return source == null ? null : Command.fromString(source);
         }
      };
      mapper.addMappings(new PropertyMap<ServiceOperationDTO, ServiceOperation>()
      {
         @Override
         protected void configure()
         {
            using(cmdToString).map(source).setCmd(null);
         }
      });

...this code throws a MappingException....

Exception in thread "main" org.modelmapper.MappingException: ModelMapper mapping errors:

  1. Converter Main$1@7a763f5d failed to convert ServiceOperationDTO to Command.

1 error
at org.modelmapper.internal.Errors.throwMappingExceptionIfErrorsExist(Errors.java:338)
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:77)
at org.modelmapper.ModelMapper.map(ModelMapper.java:185)
at Main.main(Main.java:97)
Caused by: java.lang.ClassCastException: ServiceOperationDTO cannot be cast to java.lang.String
at Main$1.convert(Main.java:1)
at org.modelmapper.AbstractConverter.convert(AbstractConverter.java:33)
at org.modelmapper.internal.MappingEngineImpl.convert(MappingEngineImpl.java:302)
at org.modelmapper.internal.MappingEngineImpl.propertyMap(MappingEngineImpl.java:175)
at org.modelmapper.internal.MappingEngineImpl.typeMap(MappingEngineImpl.java:134)
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:99)
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:68)
... 2 more

  1. Tried using addMappings with a PropertyMap that just called the Command.fromString directly in the configure
      mapper.addMappings(new PropertyMap<ServiceOperationDTO, ServiceOperation>()
      {
         @Override
         protected void configure()
         {
            map().setCmd(Command.fromString(source.getCmd()));
         }
      });

this again doesn't end up getting called at all.

  1. By chance combined #1 (addConverter) and #4 (addMappings)
      mapper.addMappings(new PropertyMap<ServiceOperationDTO, ServiceOperation>()
      {
         @Override
         protected void configure()
         {
            map().setCmd(Command.fromString(source.getCmd()));
         }
      });

      mapper.addConverter(new Converter<String, Command>()
      {
         @Override
         public Command convert(MappingContext<String, Command> context)
         {
            String source = context.getSource();
            return source == null ? null : Command.fromString(source);
         }
      });

this works, but both the code the configure and the convert get called, which is redundant. So the only way the converter gets called is if the map() is done in the configure. So it's kind of like a hacked way of getting the same behaviour you'd expected from #4. However I would have thought adding a generic converter from String->Command would handle all mappings of that type without requiring a specific PropertyMap<ServiceOperationDTO, ServiceOperation>

Seems to be a bug here if a String->String to converter works but not a String->Command. Are Enums being handled in a special way ? Is this a bug or do I need to mod my Command class to make it work ?

Multiple source property hierarchies matching problem

Hello,

I have chosen to use modelmapper because I have noticed that it handles in a better way generics super type (cf. Class MyClass) and inheritance of these types.
I have nevertheless noticed a behavior which prevents me from having a correct mapping.

My model is in this way but more complex. Example is at the end.
I have two kind of bussiness abstract objects (Product and Catalog) which have a bidirectional dependency between them. (Cf. Product knows Catalog and reversely).
Each of these two abstract types can have multiple implementation.

When I realize the mapping with Model Mapper, I get the exception :

1) The destination property model.Catalog.setLabel() matches multiple source property hierarchies:
    model.Produit.getCatalog()/model.Produit.getLabel()
    model.Produit.getCatalog()/model.Catalog.getLabel()

where 'model' is the package name.

If I don't use MatchingStrategies.STRICT, it's worst : all the fields which are near syntactically are display in the exception (for example : labelFull, labelBrand, ...)
I have tried many things since yesterday but no result. My Best try is MatchingStrategies.STRICT for the moment.
If someone has a suggestion, i am listening.
Important : This simple example doesn't fail. When i rename the label field in "name" or "id", no problem ! Weird...

Code :

  1. Two Bussiness abstract objects :
public abstract class Catalog<PRODUCT extends Product> {

    private PRODUCT product;

    private String label;

    public PRODUCT getProduct() {
        return product;
    }

    public void setProduct(PRODUCT product) {
        this.product = product;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String babar) {
        this.label = babar;
    }

}


public abstract class Product<CATALOG extends Catalog> {

    private String label;

    private CATALOG catalog;

    public CATALOG getCatalog() {
        return catalog;
    }

    public void setCatalog(CATALOG catalog) {
        this.catalog = catalog;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

}
  1. Two Couples of Implementations
public class CatalogOne extends Catalog<ProduitOne> {
....
}

public class ProduitOne extends Product<CatalogOne> {
....
}




public class CatalogTwo extends Catalog<ProduitTwo> {
....
}

public class ProduitTwo extends Product<CatalogTwo> {

}

Support for mapping interfaces

(Apologies for x-posting this from code.google)

Hi, I'm not sure if this is covered in the documentation anywhere but I have not been able to map from an interface to an object.

public class UserAccountMap extends
    PropertyMap<UserModel, UserAccount> {

    @Override
    protected void configure() {
    ...
    }
}

In this example, "UserModel" is an interface with relevant getters/setters and UserAccount is a bean. Modelmapper will allow you to create this with no compile errors, but it seems to ignore the "UserModel" interface and look at the underlying class that is implementing the interface.

Alternative to a fix, is there a way around this so I don't have to implement a map for every object that the interface specifies?

Don't try to proxy enums

When using the mapping DSL, modelmapper tries to create a proxy for an Enum, which causes a big explosion. This can be avoided by added an additional check to the proxyForm method in ProxyFactory (I can't be bothered to create a fork and pull request for this simple issue)

  static <T> T proxyFor(Class<T> type, MappingProgress<?> mappingProgress) throws ErrorsException {
    if (Modifier.isFinal(type.getModifiers()) || type.isEnum())
      return null;

skip() messes up mappings if not last in configure()

If you call skip() before map() in a PropertyMap.configure(), the mappings (both automatic and explicit) get somewhat misaligned and messed up. You can avoid the problem by calling skip() later, but nevertheless this seems a bug.

public class ModelMapperTest {

    static class ObjectA {
        String one;
        String two;
        String three;
        String four;

        public String getOne() {
            return one;
        }

        public void setOne(String one) {
            this.one = one;
        }

        public String getTwo() {
            return two;
        }

        public void setTwo(String two) {
            this.two = two;
        }

        public String getThree() {
            return three;
        }

        public void setThree(String three) {
            this.three = three;
        }

        public String getFour() {
            return four;
        }

        public void setFour(String four) {
            this.four = four;
        }

    }

    static class ObjectB {
        String one;
        String two;

        String v3;
        String v4;

        public String getOne() {
            return one;
        }

        public void setOne(String one) {
            this.one = one;
        }

        public String getTwo() {
            return two;
        }

        public void setTwo(String two) {
            this.two = two;
        }

        public String getV3() {
            return v3;
        }

        public void setV3(String v3) {
            this.v3 = v3;
        }

        public String getV4() {
            return v4;
        }

        public void setV4(String v4) {
            this.v4 = v4;
        }

    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        ModelMapper modelMapper = new ModelMapper();

        PropertyMap<ObjectA, ObjectB> map = new PropertyMap<ObjectA, ObjectB>() {
            protected void configure() {
                skip().setOne(null);
                map(source.getThree()).setV3(null);
                map(source.getFour()).setV4(null);
            }
        };

        modelMapper.addMappings(map);

        for (Object o : modelMapper.getTypeMap(ObjectA.class, ObjectB.class)
                .getMappings())
            System.out.println(o);

        ObjectA a = new ObjectA();
        a.setOne("1");
        a.setTwo("2");
        a.setThree("3");
        a.setFour("4");

        ObjectB b = modelMapper.map(a, ObjectB.class);

        System.out.println("b.one=" + b.getOne());
        System.out.println("b.two=" + b.getTwo());
        System.out.println("b.v3=" + b.getV3());
        System.out.println("b.v4=" + b.getV4());
    }

}

OUTPUT

PropertyMapping[ObjectA.three -> ObjectB.one]
PropertyMapping[ObjectA.two -> ObjectB.two]
PropertyMapping[ObjectA.four -> ObjectB.v3]
ConstantMapping[null -> ObjectB.v4]
b.one=null
b.two=2
b.v3=4
b.v4=null

Bio directional object within list does not map object.

I am mapping a given object to a object of the same type. One of the sets within the source has a object that references the original object (if that is clear?).

Example:
class A {
Set bs;
}

class B {
A a;
}

The problem is after mapping a instance of A to A, say a1 to a2. we can get b2 but that sub object in the set has a reference to a1 and not its parent a2.

Auto generate asserts on Mappings

ModelMapper saves a lot of time writing mappers however, we need tests to verify all the mappings. Can model mapper generate asserts at a field level automatically too? I think this could be an intellij/eclipse plugin. Happy to contribute if this doesn't exist.

Strict strategy break by addMapping

Hello,
in our (so complex) mapping we found mismatched mapings in STRICT mapping strategy after addMapping.
If no manual mapping is used then I not see this bad behaviour.

A test project for this issue I will send by email.

Maybe this issue has some commons with another problem: our unit tests works differently when a unit test runs alone or in a test suite. We found that ts is caused by cached mappings in: org.modelmapper.internal.MappingEngineImpl#typeMapStore
in previous runs.

Thanks
Jan

Add support for ConstructorProperties when populating property values

If no mutators exist on the destination type then use the ConstructorProperties values to represent the mutator names. Also ensure that partial population through the constructor and partial population through mutators is supported.

Note: ConstructorProperties is a JDK 1.6 annotation. ModelMapper is currently on 1.5.

OSGi: NoClassDefFoundError on "org/modelmapper/internal/cglib/core/ReflectUtils"

Hi.

I want to deploy an application that uses latest version of ModelMapper in a Karaf 2.3.0, and I'm getting the following error:


Caused by: java.lang.NoClassDefFoundError: org/modelmapper/internal/cglib/core/ReflectUtils
        at com.young.mknot.dto.FactProduced$$EnhancerByModelMapper$$fd8844e.CGLIB$STATICHOOK2()
        at com.young.mknot.dto.FactProduced$$EnhancerByModelMapper$$fd8844e.()
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:247)
        at org.modelmapper.internal.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:386)
        at org.modelmapper.internal.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
        at org.modelmapper.internal.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
        at org.modelmapper.internal.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
        ...

I have not seen the export package "org.modelmapper.internal.cglib.core" in your manifest file and i don't know how to import (or ignore, if any) that in my manifest.

Use maven-bundle-plugin to generate MANIFEST.MF files with OSGi Metadata

This is related to issue #18, which is closed, and wasn't quite solved by the merge. I'm working on a patch that will fix this issue for good going forward.

The problem I was having was that javax.xml.* was not found by the bundle classloader when used in an OSGi platform such as Apache Karaf (which uses Apache Felix as the OSGi container). This was because the template-driven version of the MANIFEST.MF didn't specify any imports required, so the classloader could not find them.

The maven-bundle-plugin is the way to go here; it "just works", for the most part. See the Apache Maven Bundle Plugin page for more information.

mapping mismatch, is there any way to fix this ?

The attribute is covered by another attribute with the same name and type, but not at the same level.

Is there any way to fix this by config or ?

given :

//*packA**

package packA;

import java.util.Date;

public class Down {

DownPk pk;
Date updateDate;

Up up;


public Up getUp() {
    return up;
}
public void setUp(Up up) {
    this.up = up;
}
public DownPk getPk() {
    return pk;
}
public void setPk(DownPk pk) {
    this.pk = pk;
}
public Date getUpdateDate() {
    return updateDate;
}
public void setUpdateDate(Date updateDate) {
    this.updateDate = updateDate;
}
@Override
public String toString() {
    return "Down [pk=" + pk + ", updateDate=" + updateDate + "]";
}

}

//----

package packA;

public class DownPk {

String upId;

public String getUpId() {
    return upId;
}

public void setUpId(String upId) {
    this.upId = upId;
}

@Override
public String toString() {
    return "DownPk [upId=" + upId + "]";
}

}

//----

package packA;

import java.util.Date;

public class Up {

String id;
Date updateDate;
public String getId() {
    return id;
}
public void setId(String id) {
    this.id = id;
}
public Date getUpdateDate() {
    return updateDate;
}
public void setUpdateDate(Date updateDate) {
    this.updateDate = updateDate;
}
@Override
public String toString() {
    return "Up [id=" + id + ", updateDate=" + updateDate + "]";
}

}

//****packB****

package packB;

import java.util.Date;

public class Down {

DownPk pk;
Date updateDate;
public DownPk getPk() {
    return pk;
}
public void setPk(DownPk pk) {
    this.pk = pk;
}
public Date getUpdateDate() {
    return updateDate;
}
public void setUpdateDate(Date updateDate) {
    this.updateDate = updateDate;
}
@Override
public String toString() {
    return "Down [pk=" + pk + ", updateDate=" + updateDate + "]";
}

}

//---
package packB;

public class DownPk {
Up up;

public Up getUp() {
    return up;
}

public void setUp(Up up) {
    this.up = up;
}

@Override
public String toString() {
    return "DownPk [up=" + up + "]";
}

}

//---
package packB;

import java.util.Date;

public class Up {

@Override
public String toString() {
    return "Up [id=" + id + ", updateDate=" + updateDate + "]";
}
String id;
Date updateDate;
public String getId() {
    return id;
}
public void setId(String id) {
    this.id = id;
}
public Date getUpdateDate() {
    return updateDate;
}
public void setUpdateDate(Date updateDate) {
    this.updateDate = updateDate;
}

}

//_test_**

@test
public void testMap()
{
ModelMapper m = new ModelMapper();
m.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

    packA.Up aUp = new packA.Up();
    packA.Down aDown = new packA.Down();

    aDown.setUpdateDate(new Date(3333-1900,3,3));
    aUp.setUpdateDate(new Date(4444-1900,4,4));

    aDown.setUp(aUp);

    packB.Down bDown = m.map(aDown, packB.Down.class);

    System.out.println(bDown);
}

and the result :

Down [pk=null, updateDate=Fri Apr 03 00:00:00 CST 3333]

configuration problem

how to configure skip copy object not single property when some condition matches
like
A{
id:1
name:'data1'
status:'new'
}
B{
id
name
}
i want to copy a to b when status='updated'
other wise i want to skip entire object
how can i configure this
when coping list

Feature request: Map maps to beans and vice-versa

I am giving the following test as a simple specification of what I want:

@Test(groups = "functional")
public class SimpleMapMapping extends AbstractTest {
  static class Bean {
    String prop1;
    String prop2;
  }

  public void shouldMapBeanToMap() {

    Bean b = new Bean();
    b.prop1 = "valueA";
    b.prop2 = "valueA";
    Map map = modelMapper.map(b, LinkedHashMap.class);

    modelMapper.validate();
    assertEquals(b.prop1, map.get("prop1"));
    assertEquals(b.prop2, map.get("prop2"));
  }

  public void shouldMapMapToBean() {

    Map<String, Object> map = new HashMap<String, Object>();
    map.put("prop1", "valueA");
    map.put("prop2", "valueA");

    Bean b = modelMapper.map(map, Bean.class);

    modelMapper.validate();
    assertEquals(map.get("prop1"), b.prop1);
    assertEquals(map.get("prop2"), b.prop2);
  }
}

This is the simple mapping test case. Expected behaviour: Mapping should be strict-only as mapping to a map does not have any properties to match. And if mapping from a map would be loose then mapping back would not yield the original results.
For nested mapping I would expect that the map side of the mapping is fixed. Means: Maps in the bean are treated as values, never as 'maps' in the sense of this feature request.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.