Giter Club home page Giter Club logo

remap's People

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

remap's Issues

Mapping is not applied for Set properties

If a property of type Set<A> needs to be mapped to a property of type List<B>, a mapping from A to B is demanded, but not applied. Elements will be copied 1:1, which means you'll end up with A instances in the destination List<B>

Strict mode

Is it possible to tell mapper to throw an exception if some of the fields is not mentioned in mapping? I am using mapper to copy some fields between objects of the same class and want to detect when a new field is added to the class so that I can decide whether to omit it during copying or not.

Support for properties with capital letter on second place

The mapper creates property names from the get- or set-method transforming the first letter to lower case.

static String toPropertyName(Method method) {
    String name = method.getName();
    if (isBoolGetter(method)) {
      return firstCharacterToLowerCase(name.substring(2, name.length()));
    } else {
      if (isGetterOrSetter(method)) {
        return firstCharacterToLowerCase(name.substring(3, name.length()));
      } else {
        throw new IllegalArgumentException("The specified method is neither a getter nor a setter method.");
      }
    }
  }

In case of properties like 'aProp' with a getter 'getAProp' the PropertyDescripter does not convert the first character to lower case. The rule is no conversion, if the first two characters of the name are both uppercase.
So the mapper failed getting the PropertyDescripter because of no matching property name and the property will be marked as invalid java bean property.

  static PropertyDescriptor getPropertyDescriptorOrFail(Target target, Class<?> type, String propertyName) {
    Optional<PropertyDescriptor> property;
    property = Properties.getProperties(type, target)
        .stream()
        .filter(pd -> pd.getName()
            .equals(propertyName))
        .findFirst();
    if (property.isPresent()) {
      return property.get();
    } else {
      throw notAProperty(type, propertyName);
    }
  }

[JDK 10] Caused by: java.lang.IllegalArgumentException: null

Hi,
Is the latest version of mapper compatible with JDK 10?
Just bumped my project and can see this exception caused by Remap.

Caused by: java.lang.IllegalArgumentException: null
at org.objectweb.asm.ClassReader.(ClassReader.java:160) ~[asm-6.0.jar:6.0]
at org.objectweb.asm.ClassReader.(ClassReader.java:143) ~[asm-6.0.jar:6.0]
at org.objectweb.asm.ClassReader.(ClassReader.java:418) ~[asm-6.0.jar:6.0]
at net.sf.cglib.proxy.BridgeMethodResolver.resolveAll(BridgeMethodResolver.java:69) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.emitMethods(Enhancer.java:1132) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:630) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) ~[cglib-3.2.6.jar:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) ~[cglib-3.2.6.jar:na]
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305) ~[cglib-3.2.6.jar:na]
at com.remondis.remap.InvocationSensor.(InvocationSensor.java:54) ~[remap-4.0.0.jar:na]
at com.remondis.remap.Mapping.getTypedPropertyFromFieldSelector(Mapping.java:353) ~[remap-4.0.0.jar:na]
at com.remondis.remap.Mapping.reassign(Mapping.java:157) ~[remap-4.0.0.jar:na]

Thanks

Implicit and reassing mappings do not support auto(un)boxing

When mapping from boolean to Boolean and vice-versa, then implicit mappings fail initialization due to 'incompatible types'.
This applies to all primitive types, because auto(un)boxing is currently not taken into account when analyzing primitive type mappings.

Possible bug on Boolean field ?

Hello

ReMap throw always exception on Boolean field

Caused by: com.remondis.remap.MappingException: The method 'getNewsletterSubscribed' in type fr.monbanquet.magni.entity.CustomerEntity is not a valid Java Bean property get-method.

private Boolean newsletterSubscribed;

public Boolean getNewsletterSubscribed() {
    return newsletterSubscribed;
}

public void setNewsletterSubscribed(Boolean newsletterSubscribed) {
    this.newsletterSubscribed = newsletterSubscribed;
}

And I use it like that

        Mapping.from(CustomerEntity.class)
                .to(SfContact.class)
                .reassign(CustomerEntity::getMail).to(SfContact::getEmail)
                .omitInSource(CustomerEntity::getNewsletterSubscribed) 
                .mapper();

Regards

Suggestion : custom map function

Hello

Sometime mapping cannot be do, so why not enable a custom mapping like this

Mapper<AccountEntity, SfAccount> mapperToSf =
        Mapping.from(AccountEntity.class)
                .to(SfAccount.class)
                .map((source, destination) -> {
                  if (source.getBillingAddress() != null) {
                      destination.setBillingStreet(source.getBillingAddress().getStreet());
                      destination.setBillingCity(source.getBillingAddress().getCity());
                      destination.setBillingPostalCode(source.getBillingAddress().getZip());
                      destination.setBillingState(source.getBillingAddress().getState());
                      destination.setBillingCountry(source.getBillingAddress().getCountry());
                      if (source.getBillingAddress().getLocation() != null) {
                          destination.setBillingLatitude(source.getBillingAddress().getLocation()[0]);
                          destination.setBillingLongitude(source.getBillingAddress().getLocation()[1]);
                      }
                  }
                })
                .omitInSource(AccountEntity::getBillingAddress)
                .omitInDestination(SfAccount::getBillingStreet)
                .omitInDestination(SfAccount::getBillingCity)
                .omitInDestination(SfAccount::getBillingPostalCode)
                .omitInDestination(SfAccount::getBillingState)
                .omitInDestination(SfAccount::getBillingCountry)
                .omitInDestination(SfAccount::getBillingLatitude)
                .omitInDestination(SfAccount::getBillingLongitude)
                .mapper();

Cannot ignore custom getters while mapping

I have a class with a list of objects:

class Foo {
  private List<Bar> bars;
  // getters and setters
}

Now I add a custom getter to return a filtered part of the bars list:

class Foo {
  private List<Bar> bars;

  public List<Bar> getFilteredBars(){
    return this.bars.stream()
      .filter(...)
      .collect(Collectors.toList());
  }

  // more getters and setters
}

I want this getter to be ignored in mappings.

However, if I use omitInSource(Foo:getBars), I get the following exception:

Caused by: com.remondis.remap.MappingException: The get-method for property '...' in type ... is not a valid Java Bean property.

This makes it impossible to add custom "helper" getters, which is kind of a hard restriction.

Exception when creating mapper for generic type

When creating a mapper for generic type like this:

MyType<R> {
      R getResult();
}

in remap 4.2.0 the following exception is thrown:

Caused by: java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
	at com.remondis.remap.GenericParameterContext.init(GenericParameterContext.java:46)
	at com.remondis.remap.GenericParameterContext.<init>(GenericParameterContext.java:29)
	at com.remondis.remap.ReassignTransformation.validateTransformation(ReassignTransformation.java:182)
	at com.remondis.remap.MappingConfiguration.validateMapping(MappingConfiguration.java:444)
	at com.remondis.remap.MappingConfiguration.mapper(MappingConfiguration.java:365)

It is working without problems in remap 4.1.12

Android Support

Hi! I'm using this to map my Entities and DTOs in the server side.

I'd like to do the same in my Android app.

I've written the code, and test for it all pass. But when I run the app I get this exception:

Caused by: java.lang.UnsupportedOperationException: can't load this type of class file
        at java.lang.ClassLoader.defineClass(ClassLoader.java:591)

Looking over the internet I get to this StackOverflow answer.

Could you please provide a way to make it work on Android?

Thanks!

Replace Collection does not work as expected on a list

The following code produces an exception although it is a valid mapping (the API confirms that):

Mapper<A, AResource> mapper = Mapping.from(A.class)
        .to(AResource.class)
        .replace(A::getStrings, AResource::getStrings)
        .with(list -> {
          List<String> newList = new LinkedList<>();
          for (String s : list) {
            newList.add(s + MODIFIER);
          }
          return newList;
        })
        .mapper();

Produces the following error:

java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List
	at com.remondis.remap.ReplaceTransformation.lambda$2(ReplaceTransformation.java:58)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
	at com.remondis.remap.ReplaceTransformation.performTransformation(ReplaceTransformation.java:59)
	at com.remondis.remap.Transformation.performTransformation(Transformation.java:124)
	at com.remondis.remap.Mapping.map(Mapping.java:503)
	at com.remondis.remap.Mapper.map(Mapper.java:39)
	at com.remondis.remap.test.ReplaceOnCollectionsTest.test(ReplaceOnCollectionsTest.java:35)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)


Improve exception messages

Great work!
Two messages that made it hard to pinpoint the cause:

When a mapper is missing it would be nice to mention the property name for which this is needed:
No mapper found for type mapping from java.lang.Float to java.lang.Double

When the same mapper is accidentally assigned twice by calling mapping.useMapper(mapper):
A mapper mapping the type A to type B was already registered.
(with A and B being the types of the mapping, not of the mapper, which was additionally confusing for me)

Suggestion to use an instantiated objet as "from"

Hello

I have an suggestion because sometime I populate an object that exists before (loaded from database for update operations for exemple)

private static final Mapper<SfContact, CustomerEntity> mapperToEntity =
        Mapping.from(SfContact.class)
                .to(CustomerEntity.class)
                .mapper();

public static CustomerEntity toEntity(CustomerEntity entity, SfContact sfContact) {
    return mapperToEntity.map(sfContact);  <-----
}

I would like to have someting like :

return mapperToEntity.with(entity).map(sfContact); 

or (update)

return mapperToEntity.map(entity, sfContact); 

What do you think about it ?

Reference to `this`

Say that I have one input transfer object, and have to map it to class association, say jpa entities. These will be joined: there is 1 top level object, which has multiple child objects. Child objects has reference to top level object (currently not doable), and top level object will have reference to list of childs(current doable). We can do this by having mapping inside of mapping, but child cannot access toplevel object, because that one did call .mapper() yet. I'm not sure if I'm describing that in understandable manner, but mapping jpa entities association should be self descriptive.

API Improvements

List of possible API Improvements. They are collected in this Issue, because they are breaking changes and should be implemented together in a single release.

  • Methods com.remondis.remap.ReplaceCollectionAssertBuilder.andTest(Transform<RS, RD>) and com.remondis.remap.ReplaceAssertBuilder.andTest(Transform<RS, RD>) should be renamed so that the method name indicates that the test is performed againstnull input.

Support for hierarchy

This is a feature proposal.

I have Pet, Dog and Cat entity classes. Dog and Cat classes extend Pet. I also have the equivalent PetDTO, DogDTO and CatDTO.

I would like to map a PetDTO entity and get a Dog or a Cat entity in return.

Very similar to this in mapstruct: mapstruct/mapstruct#366

Supply parameters to mapper.map method

My use case is:
Source: Person with fields firstName, lastName, languageId
Destination: PersonDto with fields firstName, lastName, languageName

Can I somehow call mapper.map(person, languageNameByLanguageIdHashMap/producer of map) and define mapping for languageId -> languageName to get language name from this HashMap?

I can do it when creating mapping but I in my case, I create mapping when Spring starts and the HashMap needs to be created right before calling mapper.map( ) so that it contains latest data, because I am using it for something more dynamic than language.

ability to define custom mappers

I'm mapping generated AVRO file to say JPA entity. But generated AVRO has Strings as CharSequence, for which there is no Mapper for. OK, so we useMapper:

.useMapper(Mapping.from(CharSequence.class).to(String.class).mapper())

but ... that won't work, since there is not (reasonable) properties to map and string is immutable. So we need to be able to replace whole class to define such mapper. Currently I don't see such option.

Version 4.0.0 requires java 9

remap 4.0.0 pulls asm 6.0 jar which is in java 9 format:
[DEBUG] com.remondis:remap:jar:4.0.0:compile
[DEBUG] cglib:cglib:jar:3.2.6:compile
[DEBUG] org.ow2.asm:asm:jar:6.0:compile

This is causing problems with other tools in our build pipeline, so I just wanted to ask whether java 9 is an official requirement.

How do I convert a List to Set?

I was trying out remap as a replacement for our mappers. The test by specification would be extremely useful to us.

My question is: We've got the case where we want to map a property of type List<ADTO> to a property of type Set<A>. Is this even supported?

I tried a combination of replaceCollection and useMapper(TypeMapping.from(List.class).to(Set.class).applying(HashSet::new)) which results in the exception com.remondis.remap.MappingException: Invoking access method for property....

Suggestion : omitAll

Hello

Sometime I just need to map some fields and I do not matter for the others and new
It's tedious to omit each field

For exemple I create a "little" object with 6 or 7 fields and need to copie them from an object with 30 or 40 fields -> by using ReMap, it's long and boring to write mapping

What do you think about omitAll() ?

Property path support for set would be helpful

Property path mappings can be specified for replace operations. A property path for set operation would be helpful.

Currently a workaround can be used: Use property path as function for set operation.

Possible enhancement for static classes

The following example shows that private getter methods in static classes are not proxied by the InvocationSensor. The call on the proxy object calls the real method:

import org.junit.Test;

import com.remondis.remap.Mapper;
import com.remondis.remap.Mapping;

public class StaticClassMapperTest {

  public static class A {
    public A() {
      super();
    }

    private String getMessage() {
      throw new RuntimeException("Original method was called.");
    }
  }

  public static class B {
    private String message;

    public B() {
      super();
    }

    public String getMessage() {
      return message;
    }

    public void setMessage(String message) {
      this.message = message;
    }
  }

  @Test
  public void multiMapping() {
    Mapper<A, B> mapper = Mapping.from(A.class)
        .to(B.class)
        .reassign(A::getMessage) // This is where the "real" method of the proxy is called.
        .to(B::getMessage)
        .mapper();
    A a = new A();
    B b = mapper.map(a);
  }
}

This effect only ocurrs on static classes (non-static inner classes are not supported due to the missing no-arguments constructor) with private getter-methods.

Possibly this is nothing that must be fixed, but throwing a MappingException pointing out whats happening would be nice.

Support for wrapping a mapper into a class

Currently, we're creating Mapper instances in Spring Java Configurations like this:

@Configuration
public class MapperConfiguration {

  @Bean
  Mapper<MyClass1, MyClass2> myMapper() {
    return Mapping.from(...)
        // ...
        .mapper();
  }
}

We can then inject the mapper into other beans. However, this way, it's hard to find where the mapper is used within the codebase. I would have to search for "Mapper<MyClass1, MyClass2>" to find where it's injected.

It would be great if there was support for wrapping a Mapper into it's own class (or interface). It would look like this:

@Configuration
public class MapperConfiguration {

  @Bean
  MyMapper myMapper() {
    return ...;
  }
}

In the IDE, we could then just search for occurrences of MyMapper to know where it's used.

It would be great if reMap supported "wrapper" classes like MyMapper in the example above.

JDK9: provide Automatic-Module-Name entry in manifest

Hello!

Java 9 introduced the module system. If a non-modular JAR is used in a modular app, Java creates a so-called automatic module from it, whose name is derived from the JAR name (by default).

It is very important for modules to have stable names (just like packages), because changing it later may lead to the compilation errors and module hell. If you don't want to migrate to Java 9 yet, you can add the following entry to the MANIFEST file for forward compatibility:

Automatic-Module-Name: com.remondis.remap

It is neutral for older Java versions, and Java 9 will use it as the name of the automatic module, so that I could do the following thing in my application, without worrying about the future:

module com.example.foo {
   requires com.remondis.remap;
}

(note: the official recommendation is to name the module from the root package, and use reverse-DNS style).

Support for omitAll() in Assert API

Like Mapper.omitAll(), that adds omit declarations for unmapped fields, it may be useful to have this feature also in the Assert API. A method like AssertMapping.expectOthersToBeOmitted() can be implemented to assert that all fields not mentioned by the asserts are expected to be omitted.

Support for Mapping Calendar to Date and vice versa

Sometimes you have fields with types you don't want to 'map' field by field but to 'convert'. For instance, when you have a field of type Calendar that should be mapped to a field of type Date. I.e. when you have fields with types that do not follow the Java Bean conventions.

I currently don't see a way to create a mapper that does that. And I think this is a feature that will be needed sooner than later.

I came upon this while trying to add ReMap to the performace test suite for this blog post. In order to make the mapper competetive, we need this feature. Only when this feature is implemented can we ask to have the mapper included in the blog post :).

Reassing with differen types not supported by Assert API

When having a mapper with a reassing that is used for a type mapping (B -> BResource),...

        .to(AResource.class)
        .reassign(A::getB)
        .to(AResource::getbResource)
        .useMapper(bMapper)
        .mapper();

...then the corresponding test using the Assert API produces a compiler error:

    AssertMapping.of(aMapper)
        .expectReassign(A::getB)
        .to(AResource::getbResource)
        .ensure();

This is because the support for different types for reassing was not reflected in the Assert API.

Mapping of enums not supported

The mapping of enumeration values currently results in an exception because a primitive type mapping is detected and an identity mapping is created. This results in an exception because an enum type does not meet the Java bean requirements.

The method com.remondis.remap.Transformation.isValidPrimitiveMapping(Class<?>, Class<?>) should be renamed to isValidReferenceMapping because it returns true whenever a reference mapping should be used - except of enumerations. This method also should return true of the involved types are enumerations.

Workaround for this issue: Let gender be defines by an enumeration - the following snippet avoids the mapping exception when mapping enums:

.replace(Person::getGender, PersonResource::getGender)
.withSkipWhenNull(g -> g)

Allow mapping of null values optionally

Possible API improvements would be:

  • com.remondis.remap.Mapper.mapOptional(T t) Maps t if non-null, otherwise returns null.
  • com.remondis.remap.Mapper.mapOrDefault(T t, T default) Maps t if non-null, otherwise returns default.

java.lang.NoClassDefFoundError: org/objectweb/asm/Type

Hello

With OpenJDK 11
Remap 4.0.2

When I run my application I have this error :

2018-11-05 11:24:12,255 WARN [main] [] o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext.log | Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'productMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productMapper' defined in file [/home/mario/dev/product/product-app/target/classes/fr/app/product/mapper/ProductMapper.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [fr.app.product.mapper.ProductMapper]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/objectweb/asm/Type

An idea ?

Property path needs update to 0.1.0

Since property path < 0.1.0 is not compatible with JDK8 (due to a JDK 8 bug) ReMap needs an update to the latest version.

TODO: Find out if this could be done backwards-compatible.

Feature request: Allow chained/fluent setters

Hi

I tend to use chained setters quite a lot and was wondering if it would be difficult to allow them, either by default or through configuration.

I wouldn't mind cooking up a PR if i think it would be a good idea (and if it is not too complex).

I did do a search through the issues to see if this is a duplicate, but did not find anything.

Best regards Jens

API extension: Support mapping of iterables

To provide a comfortable way to map results of a Spring JPA Repository it would be nice to overload the method com.remondis.remap.Mapper.map() to support mapping on Iterable<S>.

Resulting API extension would be a method Iterable<D> com.remondis.remap.Mapper.map(Iterable<S>). Under the hood we can use a simple LinkedList to get the resulting iterator from.

Is it possible to update an existing object instead of creating a new one?

I'm implementing reMap in every Entity <-> DTO conversion. I also use a DTO when updating an Entity, and thus I would expect to read the original Entity from the DB and update the values when mapping.

Let me show you a dummy example:

public class User {
   private String name;
   private String lastname;
   private Integer age;
}

public class User_updateDTO {
   private String name;
   private String lastname;
   private Integer age;
}

What I would normally do is (without reMap):

User existingUser = readUserDB();
if (null != dto.getName()){
    existingUser.setName(dto.getName());
}
// ... and the same for the other attributes

I was thinking in something like this:

Mapper< User_updateDTO, User > mapper = Mapping.from(User_updateDTO.class)
                .to(User.class)
                .replace(User_updateDTO::getName, User::getName)
                    .withSkipWhenNull(value -> value)
                .replace(User_updateDTO::getLastname, User::getLastname)
                    .withSkipWhenNull(value -> value)
                .replace(User_updateDTO::getAge, User:: getAge)
                    .withSkipWhenNull(value -> value)
                .mapper;

The problem of course is the mapper creates a new User instance.

Maybe you could guide me in other direction in order to use reMap when updating. I appreciate any guidance. How do you work with updates? My idea of the DTO is to restrict the attributes allowed for update

Suggestion : use all fields from source to set destination

Hello

I have a field that is a generated message from some fields in source object

I would like to do something like this

        Mapping.from(ActivityEntity.class)
                .to(ActivityDto.class)
                .set(ActivityDto::getMessage).with(this::getMessage) 
                .omitInSource(ActivityEntity::getId)
                .mapper();

private String getMessage(ActivityEntity entity) {
    switch (entity.getAction()) {
        case ORDER_SHOP_ADD:
            return "Supplier added " + entity.getShop();
        case ORDER_ATTRIBUTED:
            return "Attributed to " + entity.getAttributeTo();
        case ORDER_CLONED:
            return entity.getClone() == null ? "" : entity.getClone().getFirst() + " clone to " + entity.getClone().getSecond();
    }
}

NPE when omitting field in destination

Given the following scenario:

public class A {

  public String multiMapped;
  // Getters & Setters...
}

public class AResource {

  public String multiMapped1;
  public String multiMapped2;
  public String multiMapped3;
  public String omitted;
}

public class MapperTest {

  @Test
  public void shouldMap() {
    Mapping.from(A.class)
        .to(AResource.class)
        .omitInDestination(AResource::getOmitted)
        .replace(A::getMultiMapped, AResource::getMultiMapped1)
        .withSkipWhenNull(Function.identity())
        .replace(A::getMultiMapped, AResource::getMultiMapped2)
        .withSkipWhenNull(Function.identity())
        .replace(A::getMultiMapped, AResource::getMultiMapped3)
        .withSkipWhenNull(Function.identity())
        .mapper();
  }
}

...the Mapper will throw an NPE. This is because com.remondis.remap.Mapping.denyAlreadyOmittedProperty(PropertyDescriptor) erroneously relies on not having an omitInDestination in the mapping configuration.

Hamcrest not in test scope

Hi

While inspecting the dependency tree in my local project I noticed that you have the hamcrest library as a transitive dependency, should it not be in test scope?

Best regards Jens

Feature: Bidirectional mapper API

It would be nice to have a bidirectional mapper API that allows to bundle two mapper object for easier access. This would reduce the number of auto-wiring dependencies for Spring also.

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.