Giter Site home page Giter Site logo

expediagroup / bull Goto Github PK

View Code? Open in Web Editor NEW
183.0 183.0 45.0 24.58 MB

BULL - Bean Utils Light Library

Home Page: https://opensource.expediagroup.com/bull

License: Apache License 2.0

Java 100.00%
beancopy beanutils bull hacktoberfest immutable-objects java java-bean mapper mapping mutable oss-portal-featured transformation transformations

bull's People

Contributors

antimoroma avatar dependabot-preview[bot] avatar dependabot[bot] avatar fborriello avatar gitter-badger avatar massdosage avatar mox601 avatar worldtiki 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

bull's Issues

Automatic conversion of basic types

Overview
Make conversion of common object type (e.g. String -> Integer, BigDecimal -> Double, etc.) automatically

Desired solution
The "type" conversion has to be applied before executing the Field Transformation defined by the user.
The conversion should be available for the following types:

  • Byte, byteorbyte[]`
  • Short or short
  • Integer or int
  • Long or long
  • Float or float
  • Double or double
  • BigDecimal
  • BigInteger
  • Character or char
  • Boolean or boolean
  • String

Possible implementation
There should be a ConversionAnalyzer that given the source field type and the destination field type returns a lambda function that handles the conversion.
The lambda function should be added to the transformations related to the field and applied as the first operation

100% Test Coverage

Description
As per today, the test coverage is: 97,3%, the purpose of this task is to reach 100%.

How the coverage is calculated
The plugin in charge of the test coverage calculation are Jacoco along with SonarCloud.
Jacoco it's executed during each build and produces a report inside the target folder of each module.
You can find it at:
[module-name]/target/site/jacoco

instead, the SonarCloud report is updated during each release

The purpose
The purpose is to identify all the "not covered" code areas and implement specific Unit Test for covering them.

Additional context
There are classes and packages excluded from the coverage calculation, such as enum, Java Bean, etc. The whole list of the excluded items are:

Kotlin constructor parameters with default break the transformer

Sample code:

import com.expediagroup.beans.BeanUtils

data class BeanFrom(
    val foo: String
)

data class BeanTo(
    val foo: String = "bar"
)

val beanFrom = BeanFrom("bar")
val beanTo: BeanTo = BeanUtils().transformer.transform(beanFrom, BeanTo::class.java)

This throws:

com.expediagroup.transformer.error.InvalidBeanException: Constructor's parameters name have been removed from the compiled code. This caused a problems during the: BeanTo injection. Consider to use: @ConstructorArg annotation: https://github.com/ExpediaGroup/bull#different-field-names-defining-constructor-args or add the property: <parameters>true</parameters> to your maven-compiler configuration
	at com.expediagroup.beans.transformer.TransformerImpl.handleInjectionException(TransformerImpl.java:201)
	at com.expediagroup.beans.transformer.TransformerImpl.injectValues(TransformerImpl.java:164)
	at com.expediagroup.beans.transformer.TransformerImpl.handleInjectionException(TransformerImpl.java:188)
	at com.expediagroup.beans.transformer.TransformerImpl.injectValues(TransformerImpl.java:164)
	at com.expediagroup.beans.transformer.TransformerImpl.injectValues(TransformerImpl.java:134)
	at com.expediagroup.beans.transformer.TransformerImpl.transform(TransformerImpl.java:69)
	at com.expediagroup.beans.transformer.AbstractBeanTransformer.transform(AbstractBeanTransformer.java:124)
	at Line_4.<init>(Line_4.kts:1)
Caused by: com.expediagroup.transformer.error.InstanceCreationException
	at com.expediagroup.transformer.utils.ClassUtils.getInstance(ClassUtils.java:548)
	at com.expediagroup.beans.transformer.TransformerImpl.injectValues(TransformerImpl.java:162)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
	at com.expediagroup.transformer.utils.ClassUtils.getInstance(ClassUtils.java:546)
Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method Line_2$BeanTo.<init>, parameter foo
	at Line_2$BeanTo.<init>(Line_2.kts)
	at Line_2$BeanTo.<init>(Line_2.kts:1)

The initial message is probably misleading. What happens here is that Kotlin creates an additional constructor with two more parameters (an int and a kotlin.jvm.internal.DefaultConstructorMarker), and BULL assumes that's the "all args" one.
That fails due to receiving the wrong number of arguments, and so BULL falls back to using the no args constructor and injecting fields.
But the no args constructor cannot be used, because the class expects a non-null value for its only field, and that yields the last exception you can see in the stack trace.

Automatic transformation between different Enum types

Description
BULL already transforms enum values of the same type, that is the source and destination fields are of the same type. But when you need to map two different enum types you're forced to write a custom property transformer.
The desired feature is being able to map enum values of different types. Given the following types:

enum A {
    x, y
}

enum B {
    x, y
}

class Source {
    A type;
    // constructor, getters&setters...
}

class Destination {
    B type;
    // constructor, getters&setters...
}

we want the type field to be automatically mapped by the following instruction:

Destination d = new BeanUtils().getTransformer().transform(new Source(A.x), Destination.class);
assert d.getType() == B.x

The default behavior for this feature should be:

  • all enum values should map to constants with the same name
  • if the source enum has more values than destination, it should map to null

JDK8 Compatible version automatic release

Description
All the changes implemented on BULL are released in two different versions: one compatible with jdk8 and the other with compatibility with jdk11.

The jdk11 release is totally automatic and performed by a Travis build, but the jdk8 one is manual.

The purpose is to automatize this process

Use the new "hasPackage" assertion from AssertJ 3.18.0

Is your feature request related to a problem? Please describe.
Since the test dependency on AssertJ has been updated to 3.18.0, a new assertion is available to check a Class package:

Class<?> actual = ...

assertThat(actual).hasPackage("com.foo.bar");

while previously the best you could do was for example

assertThat(actual.getName()).startsWith("com.foo.bar");
// or in Java 9+
assertThat(actual.getPackageName()).equals("com.foo.bar");

Describe the solution you'd like
We should replace the existing usages of assertion on packages with the new one to make the tests more expressive. Currently, the only usages are in TransformerBytecodeAdapterTest, in the "transformer-bytecode-adapter" module.

Dependencies checker

It would be useful to have a an automatic checker that:

  • informs the developer about dependencies updates during the build. It should run during the build with a specific profile: check-for-updates
    e.g.
    maven clean install -P check-for-updates

  • Make the build failing in case of the presence of same dependencies with different versions

Performance improvement

Performance improvement
Reduce the bean transformation time as much as possible.

Purpose
Review and refactor the existing functionalities (where possible) in order to make this library as fast as possible.
This will be an evergreen activity as there's always a margin for improvement

[Core] Transformer model generator - JavaBean -> Mixed

given in input two types A and B, A following the JavaBean convention, B being mixed, that is with an accessible constructor and optional setters, generates the Transformer model through JavaPoet.

The output is: TypeSpec (from JavaPoet library)

Copy on existing destination

It would be useful to add the possibility to copy "source" bean properties to an existing destination bean instance like:
beanUtils.getTransformer().transform(fromBean, toBean);

This can improve flexibility:

  • I can use transformer into my bean constructor
  • I can use properties compositing from multiple sources

Enable one-to-many field mapping and field transformer

Description

As of today, it's possible to define a one-to-one FieldMapping and FieldTransformer between a source field and a destination one.

The purpose of this is to add the possibility to map the same source field to multiple destination fields:

var fieldMapping = new FieldMapping<String, List<String>>("sourceFieldName", "destinationFieldOne", "destinationFieldTwo");
var multipleDestinationFieldTransformer =
                new FieldTransformer<String, String>(List.of("sourceFieldName", "destinationFieldOne"),
                        val -> val.toUpperCase()));

Expected behaviour

Given the following source class:

public class SourceClass {
    private final String name;
    private final int id;
}

the following destination class:

public class DestinationClass {
    private final String name;
    private final int id;
    private final int index;
}

and the following operations:

var sourceObj = new SourceClass("foo", 123);

var multipleFieldMapping = new FieldMapping<>("id", "index", "identifier");

var multipleDestinationFieldTransformer =
                new FieldTransformer<String, String>(List.of("id", "index"),
                        val -> val + 1));

var destObj = new BeanUtils().getBeanTransformer()
                     .withFieldMapping(multipleFieldMapping)
                     .transform(sourceObj, DestinationClass.class);

System.out.println("name = " + destObj.getName());
System.out.println("id = " + destObj.getId());
System.out.println("index = " + destObj.getIndex());

the output will be:

name = foo
id = 124
index = 124

Acceptance Criteria

  • The transformer is mapping the specified source field value into all the specified destinations one

Static transformation with a given transformer

The static transformation became a widely used feature, but, as it is now, it uses a brand new Transformer (dynamically generated) without any custom configuration.

The solution I'd like
Possibility to use the static transformation feature with a given Transformer properly configured.

Describe alternatives you've considered
Alternatively, the same result can be obtained without using static transformation.

Example call

Transformer myCustomTransformer = 
                new BeanUtils().getTransformer()
                        .withFieldMapping(new FieldMapping("name", "differentName"));

Function<FromFooSimple, ImmutableToFooSimple> transformerFunction = BeanUtils.getTransformer(myCustomTransformer, ImmutableToFooSimple.class);
List<ImmutableToFooSimple> actual = fromFooSimpleList.stream()
                .map(transformerFunction)
                .collect(Collectors.toList());

Java Records copy

Description
with the release of Java 16 and the introduction of new class type, such as Records it's required to enhance the library to make it able to copy this kind of objects too.

Outcome of this implementation
After this implementation, the library should be able to copy objects like:

public record Foo(String value, int aNumber, byte[] someBytes) {
}

Additional context
As to have this in place, it's needed to make the project running with the latest Java releases (at least jdk14) the feature will not be available in the BULL jdk11 compatible version

BULL Testing samples

Provide detailed documentation (and samples) of the possible testing methods that can be implemented for checking the lambda function transformation

Replace Hamcrest with AssertJ

Is your feature request related to a problem? Please describe.
At present, the codebase uses the standard Hamcrest matchers for test assertions. While largely adopted, this library hasn't an expressive API, which works fine for simple assertions but falls short for more complex cases making the code difficult to read, often forcing test authors to write helper methods or classes. Moreover, its extension mechanism is clunky, resulting in very few developers writing custom Matchers.

Describe the solution you'd like
A valid alternative exists in the AssertJ library which has a fluent and very expressive API, and covers lots of common complex cases. It's fully compatible with Java 8+ and supports lambdas as assertion callbacks.
The API revolves around static methods assertThat(obj) that let you chain one or more assertions fluidly. To get a feeling of it check out the core features highlight page.

My proposal is to replace existing test assertions in BULL using AssertJ, which will provide a powerful and expressive API for complex assertions on objects/JavaBeans (there are a lot of them as test samples) without requiring extra code.

Disable the default value set for primitive types in case they are null

Description.
as per the current implementation, the Transformer automatically assigns the primitive default value (0 for Integer, false for Boolean, etc..) to all primitive types fields, in the destination object, in case their correspondent field in the source object is null.
It would be good to have the possibility to disable this behaviour.

Possible solution
A solution would be to leave by default the current behaviour and have an additional method setDefaultValueSetEnabled that, if false, disables this mechanism.

Map transformer

Description
Implement a Map Transformer that offers the same features now available for the Java Bean:

  • key mapping: map the value of a given key into another one
  • key name transformation: apply a transformation of a given key name
  • element transformation: apply a transformation on a value for the given key

Desired solution
The ideal solution would have a new maven module (optional) dedicated to the Map transformation, its name should be bull-map-transformer.

  • The module has to be compiled only if the profile: bull-map-transformer is specified.
  • The existing module: bean-utils-library has to be renamed in bull-bean-transformer and has to be compiled when using the default profile but, not when the profile: bull-map-transformer is specified.
    The new transformer has to be retrieved with the instruction: new MapUtils().getTransformer().
    The Map transformer interface must have the same behaviour as the existing Transformer
  • Detailed documentation with examples and maven site section have to be provided

Additional context
Any concern, question or detail, can be discussed on the slack channel: #map-transformer-feature.

Multiple Builder pattern support

Description

As per today, the BeanTransformer is able to transform Java Bean using the following builder pattern:

public class ItemType {
    private final Class<?> objectClass;
    private final Class<?> genericClass;

    ItemType(final Class<?> objectClass, final Class<?> genericClass) {
        this.objectClass = objectClass;
        this.genericClass = genericClass;
    }

    public static ItemTypeBuilder builder() {
        return new ItemType.ItemTypeBuilder();
    }

    // getter methods

    public static class ItemTypeBuilder {
        private Class<?> objectClass;
        private Class<?> genericClass;

        ItemTypeBuilder() {
        }

        public ItemTypeBuilder objectClass(final Class<?> objectClass) {
            this.objectClass = objectClass;
            return this;
        }

        public ItemTypeBuilder genericClass(final Class<?> genericClass) {
            this.genericClass = genericClass;
            return this;
        }

        public com.hotels.transformer.model.ItemType build() {
            return new ItemType(this.objectClass, this.genericClass);
        }
    }
}

The purpose is to support also the following pattern too:

public class ItemType {
    private final Class<?> objectClass;
    private final Class<?> genericClass;

    ItemType(final ItemTypeBuilder builder) {
        this.objectClass = builder.objectClass;
        this.genericClass = builder.genericClass;
    }

    public static ItemTypeBuilder builder() {
        return new ItemType.ItemTypeBuilder();
    }

    // getter methods

    public static class ItemTypeBuilder {
        private Class<?> objectClass;
        private Class<?> genericClass;

        ItemTypeBuilder() {
        }

        public ItemTypeBuilder objectClass(final Class<?> objectClass) {
            this.objectClass = objectClass;
            return this;
        }

        public ItemTypeBuilder genericClass(final Class<?> genericClass) {
            this.genericClass = genericClass;
            return this;
        }

        public com.hotels.transformer.model.ItemType build() {
            return new ItemType(this);
        }
    }
}

Acceptance Criteria

  • The solution must not degrade the performances
  • The BeanTransformer automatically recognized the Builder pattern and use it properly

Java Bean validation skip

It would be useful to have the possibility to configure the transformer in order to skip the Java Bean validation.

Disable override of custom properties

Currently with:

    new com.expediagroup.beans.BeanUtils()
        .getTransformer()
        .skipTransformationForField("field")
        .transform(source, destination);

it sets to null destination field, but I wanted to keep existing value

Exception messages improvement

It would be useful to improve the exception messages in order to be more descriptive in order to facilitate the error debugging

Static "transform" method

Add static "transform" method to BeanUtils class like:

public static <T, R> Function<? extends T, R> getTransformer(Class<R> toBeanClass) {
    return fromBean -> new BeanUtils().getTransformer().transform(fromBean, toBeanClass);
}

This will give the possibility to use your library with streams like:

List<FromType> sourceList = ...

List<ToType> destinationList = sourceList.stream()
      .map(BeanUtils.getTransformer(ToType.class))
      .collect(Collectors.toList());

Generator Source Adapter

The module should take the transformers generated from the Core module and produce source file representations. Those will be compiled as part of the standard build of the client project.
The output could be a JavaFile (from Java Poet library) to be written explicitly by the client, or a Path where the file has been written: this depends if we want the adapter to be free of side-effects.

  • The class package should be customizable or have a default value and it will correspond to a path on disk where the file will be written according to Java convention.
  • A base path, where the package directories will be written, should be customizable or have a default value.
  • In order to be testable and decoupled from the underlying filesystem, the adapter should be injected with a java.nio.file.FileSystem.
  • For testing purposes, an in-memory filesystem library could be used such as https://github.com/google/jimfs

To maintain uniformity in this project, a common interface should be extracted from this adapter and the Bytecode Adapter, to anticipate future adapters and to decouple the module's clients from concrete implementations.

This module is intended as internal usage in Bull and should not be referenced directly by clients.

Transformer generation modules setup

Description.

As part of the Transformer Generation project, it is required to set up the project modules.

Desired solution

The "Transformer generation" modules have to be built on demand, using a specific maven profile.
This will speed up the process and avoid the build of modules not strictly required.

The modules must have the following hierarchy:

  • bull-transformer-generator-parent
    • transformer-generator-core
    • transformer-bytecode-adapter
    • transformer-generator-registry
    • transformer-source-adapter

The module: bull-transformer-generator-parent will have bean-utils-library-parent as a parent.
All the others:

  • transformer-generator-core
  • transformer-bytecode-adapter
  • transformer-generator-registry
  • transformer-source-adapter

will have as a parent: bull-transformer-generator-parent

BULL Step up! Efficiency and performance improval!

Description
Is there a better and efficient way to perform the same operations the application does? Can the algorithms be improved to reduce resource usage and increase the performances?
Well, this is your occasion to start (or continue) your collaboration on the project adding your added value!
BULL wants you!

Ideal solution
The ideal solution:

  • improves the existing algorithms
  • improves the performance and the efficiency
  • reduces the resources usage
  • doesn't change the output
  • doesn't reduce the test coverage

How to get a many to one field mapping for a transformer?

Please see my code.

@Data
@AllArgsConstructor
class Name {
    private String first;
    private String last;
}

@Data
class User {
    private String name;
}

public class TransformerTest {
    @Test
    public void testMultiSourceField() {
        BeanUtils beanUtils = new BeanUtils();
        BeanTransformer t = beanUtils.getTransformer()
                .withFieldMapping(new FieldMapping<>("this?", "name")) //want to map first AND last to name.
                .withFieldTransformer(new FieldTransformer<>("name", (Name object) -> object.getFirst()+ " " + object.getLast())); 
        Name name = new Name("f","l");
        User user = t.transform(name, User.class);
        assertThat(user.getName(),equalTo("f l"));
    }
}

Wildcards types support

Description
As per today, the library is able to transform all the elements inside a Collection or a Map if their type is specified in the generic type, so it's not able to transform object described as following:

private final Collection<? super Object> collection;
private final Collection collection;

private final Map map;
private final Map<?, ?> map;
private final Map<? super Object, ? super Object> map;

The purpose of this issue is to make the library able to transform such objects.

Change Unit Test Language

Description

The purpose of this is to have the Unit Tests written in Kotlin instead of Java

Outcome

  • The library code is written in Java
  • Unit tests are written in Kotlin

Group id rename into ExpediaGroup

Description

As per the transition to the new repository, the project groupId and the packages need to be renamed from hotels to expediagroup.

As a consequence of this change the library can be added inside any maven project by adding this dependency:

<dependency>
    <groupId>com.expediagroup.beans</groupId>
    <artifactId>bull-bom</artifactId>
    <version>x.y,z</version>
</dependency>

Migration to GitHub action

Description

As per the migration to the Expedia Group GitHub, it has been established to adopt GitHub actions as CI/CD

Requested implementation

Replicate the same behaviour previously on Travis to GitHub action

Add possibility to define transformer function without input parameter

It would be useful to have the possibility to create a field transformer function that accepts a Supplier type function.

This feature would be used in case we should set a field value taking it from a constant or from an external object.

e.g.

Given the following source class:

public class SourceClass {
    private final String name;
    private final BigInteger id;
}

and the following destination class:

public class DestinationClass {
    private final String name;
    private final BigInteger id;
    private final Instant creationDate;
}

It should be possible to define the following transformation function for field creationDate>

FieldTransformer<Date> creationDateFieldTransformer =
new FieldTransformer<>("creationDate", () -> Instant.now());

Skip transformation for a given set of fields.

It would be really useful to have the possibility to skip the transformation for a given set of fields.
The perfect scenario for this would be the case of copy on existing destination objects.

Run with JDK8

Is your feature request related to a problem? Please describe.
when I try to import bull by Maven and use it in my project whose compile-level is JDK8, I got an error. Then I find out bull is compiled by JDK11.

Describe the solution you'd like
The features bull provided are really awesome~ So, I hope bull can provide a maven artifact like bean-utils-library-jdk8 which is compiled by JDK8.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
My english is not that good, I hope I have described my problem clearly. WELL DONE, bull !

Bean validation offered as public feature

Bean validation
validate a Java Bean against the defined constraints should be offered as a BeanUtils public feature.

Desired solution
Given the following java bean:

public class Foo {
    @NonNull
    private final String name;
    private final BigInteger id;
    
    // all args constructor
    // getters
}

and an instance of the above object, it would be useful to validate it through the following instruction:
BeanUtils.getValidator().validate(foo);

FieldTransformer is passed a default value instead of the original null

Describe the bug
When translating a Boolean field having a null value, the custom FieldTransformer is passed a default value instead of the value coming from the original bean.

To Reproduce
Steps to reproduce the behavior:

  1. Write a custom FieldTransformer to translate the work field value null to true:
FieldTransformer<Boolean, Boolean> nullToTrue =
                new FieldTransformer<>("work", aBoolean -> aBoolean == null || aBoolean);
  1. Configure it and transform a bean with a null
beanUtils.getTransformer()
                .withFieldTransformer(nullToTrue)
                .transform(fromFooSimpleNullFields, ImmutableToFooSimpleBoolean.class);
  1. The translated bean has a false value instead of the expected true

Expected behavior
FieldTransformer is working on the original value, not on a default one.

"Generics" discover function

Description

A really useful function, this project should offer, is the possibility to figure out the "Generic" type of a Collection or a Map.
This function is also required to complete the implementation of a new Map Transformer (for more details please refer to issue: #88)

Desired solution
The ideal solution would be the implementation of a new method: getGenericType that takes in input any kind of Java Collection or Map and returns its Generic type(s).

e.g.

List<String> v = new ArrayList<String>();
Class<?> genericClazz = getGenericType(v.getClass()); // will return: String

and

Map<String, Integer> v = new HashMap<String, Integer>();
Pair<Class<?>, Class<?>> typeMap = getGenericType(v.getClass()); // will return a Pair Class<?> keyClass = typeMap.getLeft(); // will return: String
Class<?> elemClass = typeMap.getRight(); // will return: Integer

Additional context

The method should be added into the utility class: ReflectionUtil

Fix race condition imposed by Map interface

Describe the bug
CacheManagerFactory. CACHE_MAP should have type ConcurrentMap instead of Map. This would allow the implementation to use the atomic ConcurrentMap.computeIfAbsent method when creating caches instead of Map.get and Map.put.

Generator Core Module

The module should be able, given two Java Beans Types, to analyze the source class and generate a transformer that maps it into the destination one.
The result of this will be available in memory.

Apply lambda function only on a specific field

Not unique field transformation
If anywhere in the destination object there are one or more fields with the same name and a lambda transformation function has been defined on it, the transformation will be applied on each occurrence.

e.g.

Given the following objects:

public class Source {
    private Foo foo;
    private ParentFoo parentFoo;
}

public class Destination {
    private Integer x;
    private ParentFoo parentFoo;
}
public class Foo {
    private Integer x;
}

public class ParentFoo {
    private Foo foo;
}

and the following transformation function:

FieldTransformer<Foo, Integer> fooTransformer = new FieldTransformer<>("x", x -> new Foo().getX());

this would be applied on both Destination.x and to: Destination.parentFoo.foo.x.

It would be useful to have the possibility to specify the full path of the field on which the transformation should be applied.

Thanks @Emi75 for providing this.

Transformation of Java Beans built through Builder

The library should be able to automatically transform classes that use the Builder pattern.
Given a source object:

import java.math.BigInteger;

public class FromFooSimple {
    public String name;
    public BigInteger id;

   // getter and setter
}

and the following destination object:

import java.math.BigInteger;

public class ToFoo {
    private String name;
    private BigInteger id;

    private ToFoo() {}
    
    // getters    

    public static class Builder {
        private String name;
        private BigInteger id;

        public Builder withName(String name) {
            this.name = name;
            return this;
        }

        public Builder withId(BigInteger id) {
            this.id = id;
            return this;
        }

        public ToFoo build() {
            ToFoo toFoo = new ToFoo();
            toFoo.id = this.id;
            toFoo.name = this.name;
            return toFoo;
        }
    }
}

The command:

beanUtils.getTransformer().transform([source obj instance], ToFoo.class);

should retun an instance of ToFoo object with all values set.

Retrieve values from getters if a field does not exists

Description
In case the destination class has a field that does not exist in the source object, but it contains a getter method returning the value, the library should get the field value from that method.

e.g.
Given:

A source object declared as follow:

public class SourceObject {

    public BigInteger getId() {
        return BigInteger.ONE;
    }

    public boolean isActive() {
        return Boolean.TRUE;
    }
}

and a destination object declared as follow:

public class TargetObject {
    private BigInteger id;
    private boolean active;

    public void setId(final BigInteger id) {
        this.id = id;
    }

    public void setActive(final boolean active) {
        this.active = active;
    }
}

The value of TargetObject.id should be retrived from SourceObject.getId() and TargetObject.active should be retrived from SourceObject.isActive()

Transform Map<K1,V> -> Map<K2,V>

In case of multiple distributed services which are exchanging data, in many cases the most generic deserialization format can be a simple Map<String, Object> collection with some LinkedMap or even more concrete/specific implementation. In many cases this helps to reduce the boilerplate code and avoid writing third-party beans.
Would it make sense or possible to add such feature, where map<k1,v> can be deep transformed into map<k2,v>?

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.