Library for converting from one Java class to a dissimilar Java class with similar names based on the Bean convention

Overview

Build Status Codacy Badge BCH compliance codecov Maven Central Javadocs Apache 2

Beanmapper

Beanmapper is a Java library for mapping dissimilar Java classes with similar names. The use cases for Beanmapper are the following:

  • mapping from forms to entities, because:
    • for security reasons you want to accept only a limited number of fields as input
    • the form fields are simplified to support frontend processing
  • mapping from entities to results, because:
    • you want to simplify the result for frontend processing
    • you want to expose a limited number of fields for security reasons

Maven dependency

In order to use Beanmapper in your project, simply add the following Maven dependency:

<dependency>
    <groupId>io.beanmapper</groupId>
    <artifactId>beanmapper</artifactId>
    <version>3.1.0</version>
</dependency>

Getting started

You want to map two dissimilar classes with no hierarchical relation (save java.lang.Object), but with a fairly similar naming schema for the fields.

Basic use case for Beanmapper

public class SourceClass {
   public Long id;
   public String name;
   public LocalDate date;
}
public class TargetClass {
   public String name;
   public LocalDate date;
}
BeanMapper beanMapper = new BeanMapper();
SourceClass source = new SourceClass();
source.id = 42L;
source.name = "Henk";
source.date = LocalDate.of(2015, 4, 1));
TargetClass target = beanMapper.map(source, TargetClass.class);

What's more?

The library can help you with the following situations:

  • nested dissimilar classes
  • ignoring parts
  • mapping to fields with other names, even if nested
  • settings defaults if no value is found
  • unwrapping class layers in order to flatten the structure
  • works directly on the bean, no getters/setters required
  • supports a combination of automated and manual processing
  • adding conversion modules for data types

What Beanmapper is not for

Beanmapper is not a library for deep-copying classes. Whenever Beanmapper can get away with a shallow copy, it will do so. Deep-copying is reserved for dissimilar classes.

Want to know more?

Find the rest of the documentation on beanmapper.io.

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Comments
  • The name field from an enum is not mapped to target field

    The name field from an enum is not mapped to target field

    When beanmapper tries to map a field from the source's superclass to a field of the target with the same fieldname a strict mapping exception is thrown. When strict mapping is turned off, the field is not mapped; the target field remains null.

    Test code (UserRole is an enum and RoleResult is a class with public 'name' field):

        @Test
        public void beanMapper_shouldMapFieldsFromSuperclass() {
            BeanMapper beanMapper = new BeanMapperBuilder().build();
            RoleResult result = beanMapper.map(UserRole.ADMIN, RoleResult.class);
            Assert.assertEquals(UserRole.ADMIN.name(), result.name);
        }
    

    Results in a BeanStrictMappingRequirementsException.

        @Test
        public void beanMapper_shouldMapFieldsFromSuperclass() {
            BeanMapper beanMapper = new BeanMapperBuilder().setApplyStrictMappingConvention(false).build();
            RoleResult result = beanMapper.map(UserRole.ADMIN, RoleResult.class);
            Assert.assertEquals(UserRole.ADMIN.name(), result.name);
        }
    

    Results in an assertion failure.

    opened by sptdevos 4
  • Bump jackson-databind from 2.13.4 to 2.13.4.1

    Bump jackson-databind from 2.13.4 to 2.13.4.1

    Bumps jackson-databind from 2.13.4 to 2.13.4.1.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 3
  • Support for java.util.Optional source mappings

    Support for java.util.Optional source mappings

    Optionals are a common usage pattern in JPA Entities to indicate the possibility of a field being null and so replacing null checks with a niceish api.

    Currently if an Entity has an java.util.Optional getter which needs to be mapped to a non optional Result field BeanMapper:

    • in strict mode fails with Missing matching properties for source [java.util.Optional] > target [EntityResult]
    • in non-strict mode fails by not mapping any fields to the entity.

    The following example demonstrates the problem: (note the mandatory package prefix)

    package nl.optionalexample;
    
    public class OptionalMappingExample {
    
        public static class MyEntity {
            private String value = "42";
            private MyEntity child;
            public String getValue() {
                return value;
            }
            public Optional<MyEntity> getChild() {
                return Optional.ofNullable(child);
            }
        }
        
        public static class MyEntityResult {
            public String value;
            public MyEntityResult child;
        }
        
        public static void main(String[] args) {
            BeanMapper mapper = new BeanMapperBuilder()
                    .addPackagePrefix("nl")
                    .setApplyStrictMappingConvention(true)
                    .build();
            mapper.map(new MyEntity(), MyEntityResult.class);
        }
    }
    

    The error thrown:

    11:46:54.418 [main] DEBUG io.beanmapper.strategy.MapToClassStrategy -     {
    11:46:54.422 [main] ERROR io.beanmapper.core.BeanStrictMappingRequirementsException - Missing matching properties for source [java.util.Optional] > target [nl.videma.repartitie.rightsholder.OptionalMappingExample.MyEntityResult]* for fields:
    11:46:54.423 [main] ERROR io.beanmapper.core.BeanStrictMappingRequirementsException - > MyEntityResult.child
    11:46:54.423 [main] ERROR io.beanmapper.core.BeanStrictMappingRequirementsException - > MyEntityResult.value
    Exception in thread "main" io.beanmapper.core.BeanStrictMappingRequirementsException
    	at io.beanmapper.core.BeanMatch.validateBeanMatchValidity(BeanMatch.java:75)
    	at io.beanmapper.core.BeanMatch.validateMappingRequirements(BeanMatch.java:68)
    
    opened by ctrl-alt-dev 3
  • Feature/114 class of property

    Feature/114 class of property

    #114 Beanfield class determined by how it will be accessed

    Currently, the field property always determines the class of a BeanProperty. This leads to confusing and faulty behaviour when the method accessors differentiate from the field, leading, for example, to the wrong BeanConverters being chosen or the wrong casts being made. The behaviour should be legitimate, since the developer may choose to map within a class. BeanMapper must make use of the access knowledge to determine the class of the BeanProperty.

    A BeanProperty will have a notion of how it will be accessed for its role (either source or target). The possibilities are: field, getter, setter or no access. The access type will have an influence on the reported class of the beanfield.

    When a BeanProperty is created, it will immediately build up its understanding of the way its property will be accessed and the class it must return upon being queried.

    The creation process for BeanProperty instances has been abstracted into its own class. The set of static methods was hard to test and convoluted with its relatively large number of parameters that is being passed around.

    Structural use of BeanField has been renamed to BeanProperty; a bean field is one of the two ways a property may be accessed, the other is through its method accessor (get/set). The property is the combination of its field and method accessors.

    A collection list will no longer be offered for clear/reuse when the class type of the accessor method differs from the class type of the field.

    opened by robert-bor 3
  • Fixed IllegalAccessExceptions that occurred after JMV garbage collection

    Fixed IllegalAccessExceptions that occurred after JMV garbage collection

    An error sometimes occurred in the BeanMapper when it attempted to invoke a getter method in the PropertyDescriptorPropertyAccessor.

    The short version of the solution:

    The setAccessible method should be called very soon prior to calling
    the invoke method rather than only once at the creation of the
    PropertyDescriptorPropertyAccessor.
    

    For the long version of the solution, let me take you down the rabbit hole:

    The error occurred in the following piece of code, when the 'invoke'
    method was called:
    
    @Override
    public Object getValue(Object instance) {
        if (!isReadable()) {
            throw new BeanGetFieldException(instance.getClass(), getName());
        }
    
        try {
            return descriptor.getReadMethod().invoke(instance);
        } catch (IllegalAccessException e) {
            throw new BeanGetFieldException(instance.getClass(), getName(), e);
        } catch (InvocationTargetException e) {
            throw new BeanGetFieldException(instance.getClass(), getName(), e);
        }
    }
    
    This read method was made accessible in the constructor of the
    PropertyDescriptorPropertyAccessor:
    
    public PropertyDescriptorPropertyAccessor(PropertyDescriptor descriptor) {
        this.descriptor = descriptor;
        makeAccessable(descriptor.getReadMethod());
        makeAccessable(descriptor.getWriteMethod());
    }
    
    private void makeAccessable(Method method) {
        if (method != null) {
            method.setAccessible(true);
        }
    }
    
    And the PropertyDescriptorPropertyAccessor is only created once for each
    method and afterwards the same instance is used to retrieve the value
    from the appropriate method. This can be verified by checking its memory
    address.
    
    When the getReadMethod() is called on the descriptor, the same instance
    is returned from the memory. Or so it seems.
    
    When you step into the getReadMethod() you can see that it retrieves the
    read method from a reference:
    
    Method readMethod = this.readMethodRef.get();
    
    When we step into the get() method on the readMethodRef field,
    we see the following body:
    
     Method get() {
        if (this.methodRef == null) {
            return null;
        }
        Method method = this.methodRef.get();
        if (method == null) {
            method = find(this.typeRef.get(), this.signature);
            if (method == null) {
                this.signature = null;
                this.methodRef = null;
                this.typeRef = null;
            }
            else {
                this.methodRef = new SoftReference<>(method);
            }
        }
        return isPackageAccessible(method.getDeclaringClass()) ? method : null;
    }
    
    A SoftReference is created if the current value of methodRef is null,
    the next time the same SoftReference instance is returned. On this
    SoftReference's referent object (which is an instance of Method)
    a setAccessible(true) call is done when the PropertyDescriptorPropertyAccessor
    is created.
    
    In the JavaDoc of a SoftReference, the following comment is shown:
    
     * Soft reference objects, which are cleared at the discretion of the garbage
     * collector in response to memory demand.  Soft references are most often used
     * to implement memory-sensitive caches.
    
    It seems that at some point in time the reference is deleted when the garbage
    collector decides it is time. Then, a new reference is created for which the
    setAccessible method has NOT been called. This results in an
    IllegalAccessException and halts the mapping.
    
    When we call setAccessible just before we call the invoke, we set the accessibility
    on the SoftReference we just got back or created. The garbage collector can not clean
    this up in the meantime as we still have a reference to it.
    
    The same fix was performed for both field and and method accessors.
    
    opened by SanderBenschop 3
  • The name field from an enum is not mapped to target field

    The name field from an enum is not mapped to target field

    Issue #83 In the resolution of issue #78 the definition of getter fields has been tightened, because previously all private fields were tagged as available as well. One project made use of this loophole by reading the name field of an enumeration class to a String field. With the new fix this is no longer possible, since the name field is private.

    This fix makes an exception for the name field of an enum class. It will be considered available for reading.

    opened by robert-bor 3
  • exception in beanmapper class DefaultBeanUnproxy: ArrayIndexOutOfBoundsException

    exception in beanmapper class DefaultBeanUnproxy: ArrayIndexOutOfBoundsException

    Stacktrace:

    apr 05, 2016 7:45:36 AM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/api] threw exception [Request processing failed; nested exception is java.lang.ArrayIndexOutOfBoundsException: 0] with root cause
    java.lang.ArrayIndexOutOfBoundsException: 0
        at io.beanmapper.core.unproxy.DefaultBeanUnproxy.unproxy(DefaultBeanUnproxy.java:21)
        at io.beanmapper.core.unproxy.SkippingBeanUnproxy.unproxy(SkippingBeanUnproxy.java:36)
        at io.beanmapper.BeanMapper.getBeanMatch(BeanMapper.java:176)
        at io.beanmapper.BeanMapper.matchSourceToTarget(BeanMapper.java:166)
        at io.beanmapper.BeanMapper.map(BeanMapper.java:149)
        at io.beanmapper.BeanMapper.map(BeanMapper.java:114)
        at io.beanmapper.BeanMapper.map(BeanMapper.java:90)
        at nl.mad.voliere.buizerd.model.website.WebsiteService.checkNow(WebsiteService.java:269)
        at nl.mad.voliere.buizerd.model.website.WebsiteService$$FastClassBySpringCGLIB$$11439aa7.invoke(<generated>)
    

    code of DefaultBeanUnproxy:

    public class DefaultBeanUnproxy implements BeanUnproxy {
        public DefaultBeanUnproxy() {
        }
        public Class<?> unproxy(Class<?> beanClass) {
            String name = beanClass.getName();
    ==>     return name.contains("$")?beanClass.getInterfaces()[0]:beanClass;
        }
    }
    

    name is: nl.mad.voliere.buizerd.checker.WebsiteCheckerExecutor$UrlTestResult UrlTestResult is an inner class of WebsiteCheckerExecutor. There are no interfaces.

    opened by ailbertriksen 3
  • Support mapping of JDK 16+ records to classes.

    Support mapping of JDK 16+ records to classes.

    Records use a different style of getter-methods, specifically, they use the exact name of the parameter passed to the record's definition. While it is possible to map records to classes if you write your own beanmapper-compliant getters, that defeats at least some of the purpose of records.

    By using the following the record and tests, we receive different exceptions based on the strictness set in the BeanMapper.

    public record PersonRecord(String name, String place) {
    
    }
    
    @Test
    void mapPersonRecordToPersonResultStrict() {
        beanMapper = new BeanMapperBuilder().setApplyStrictMappingConvention(true).build();
        PersonRecord personRecord = new PersonRecord("Henk", "Zoetermeer");
        PersonResult personResult = beanMapper.map(personRecord, PersonResult.class);
        assertEquals(personRecord.name(), personResult.name);
        assertEquals(personRecord.place(), personResult.place);
    }
    
    @Test
    void mapPersonRecordToPersonResultNotStrict() {
        beanMapper = new BeanMapperBuilder().setApplyStrictMappingConvention(false).build();
        PersonRecord personRecord = new PersonRecord("Henk", "Zoetermeer");
        PersonResult personResult = beanMapper.map(personRecord, PersonResult.class);
        assertEquals(personRecord.name(), personResult.name);
        assertEquals(personRecord.place(), personResult.place);
    }
    
    Screenshot 2022-09-16 at 16 24 39 Screenshot 2022-09-16 at 16 25 21

    As stated earlier, these tests will pass if you write getters for them like so:

    public record PersonRecord(String name, String place) {
    
        public String getName() {
            return this.name;
        }
    
        public String getPlace() {
            return this.place;
        }
    
    }
    

    Records are somewhat likely to become commonplace, so this would be a worthwhile addition to BeanMapper.

    enhancement fix-developed 
    opened by marcus-talbot42 2
  • @MergedForm with

    @MergedForm with "patch=true" in java 17 throws an InaccessibleObjectException

    When using @MergedForm with the patch option it throws an error because of the new java 17 Reflection rules. This doesn't seem to be "form dependant" as I've been able to successfully reproduce the error on any @MergedForm when I've added the patch=true option to it.

    FormDefinitionResult update(@Valid @MergedForm(value = FormDefinitionForm.class, patch = true, mergeId = "id") FormDefinition formDefinition) {

    error: Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @5a4aa2f2

    I've also tried to manually patch it according to the beanmapper.io docs, however this also throws the same error. As far as I can tell it has something to do with the downsizeSource(...), as it looks like the @MergedForm patch also uses that function.

    image

    opened by benjaminparkinson42 2
  • Bump jackson-databind from 2.11.3 to 2.12.6.1

    Bump jackson-databind from 2.11.3 to 2.12.6.1

    Bumps jackson-databind from 2.11.3 to 2.12.6.1.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 2
  • Added value alias for @BeanProperty

    Added value alias for @BeanProperty

    @BeanProperty could only be used with a name property. Adding a value alias allows this annotation to be used without any prefix and just the name of the property.

    Also corrected all warnings about javadoc (missing returns).

    Fixes #122

    opened by arjanvlek 2
  • Refactor data-carriers to record-classes.

    Refactor data-carriers to record-classes.

    Various classes exist that function - or should function - solely as a data-carrier.

    An example of such a class is the BeanPair-class:

    public class BeanPair {
    
        private final Class<?> sourceClass;
        private final Class<?> targetClass;
        private boolean sourceStrict = false;
        private boolean targetStrict = false;
    
        public BeanPair(Class sourceClass, Class targetClass) {
            this.sourceClass = sourceClass;
            this.targetClass = targetClass;
        }
    
        public BeanPair withStrictSource() {
            this.sourceStrict = true;
            return this;
        }
    
        public BeanPair withStrictTarget() {
            this.targetStrict = true;
            return this;
        }
    
        public boolean isSourceStrict() {
            return sourceStrict;
        }
    
        public boolean isTargetStrict() {
            return targetStrict;
        }
    
        public Class getSourceClass() {
            return sourceClass;
        }
    
        public Class getTargetClass() {
            return targetClass;
        }
    
        public boolean matches(Class<?> currentSourceClass, Class<?> currentTargetClass) {
            return
                    currentSourceClass.isAssignableFrom(sourceClass) &&
                            currentTargetClass.isAssignableFrom(targetClass);
        }
    
    }
    

    A more elegant solution could look something like the following:

    public record BeanPair<S, T>(Class<S> sourceClass, Class<T> targetClass) {
    
        private static final String INSTANTIATION_FAILURE_MESSAGE = "Could not instantiate BeanPair. %s is null.";
    
        public BeanPair {
            Objects.requireNonNull(sourceClass, () -> INSTANTIATION_FAILURE_MESSAGE.formatted("Source-class"));
            Objects.requireNonNull(targetClass, () -> INSTANTIATION_FAILURE_MESSAGE.formatted("Target-class"));
        }
    
        public <U, V> boolean matches(Class<U> currentSourceClass, Class<V> currentTargetClass) {
            return
                    currentSourceClass.isAssignableFrom(sourceClass) &&
                            currentTargetClass.isAssignableFrom(targetClass);
        }
    }
    

    Using this approach would cut down on boilerplate, introduce serialization-safety through the validation in the record-class' constructor, and adhere to the single-purpose principle. This would, however, require a different actor to hold the information regarding the strictness of the source and target. A good candidate for this responsibility would be the StrictMappingProperties-class. Incidentally, that class is also a candidate for refactoring to a record.

    enhancement 
    opened by marcus-talbot42 0
  • Support bean-initialisation through static factory methods.

    Support bean-initialisation through static factory methods.

    Complex classes are often provided with a static factory method, used to instantiate an object of the complex class. Furthermore, it would be beneficial for the use of Singletons to support such methods.

    A fairly simple method of supporting static factory methods could be achieved through a new annotation BeanFactoryMethod.

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface BeanFactoryMethod {
        String[] value();
    }
    

    This annotation would accept a String-array, containing the names of the fields that would need to be provided to the method as arguments, in the correct order.

    In order to process the BeanFactoryMethod, a new implementation of the BeanInitializer-interface could be provided, to properly invoke the factory method.

    It is important to note that, as this process runs before a target-object has been initialized, there is no object of the target type available for use in reflection. As such, the factory method MUST be static, as the call to it will use Method#invoke(Object, Object...). As no object of the target type is available, we would be forced to pass null as the first parameter. This is only possible for static methods.

    enhancement 
    opened by marcus-talbot42 0
  • RecordToAnyConverter#copyFieldsToIntermediary(Object, Map) throws a NPE if Map contains an Entry where the value is null.

    RecordToAnyConverter#copyFieldsToIntermediary(Object, Map) throws a NPE if Map contains an Entry where the value is null.

    Whenever a source-object contains a null-value for a field that must be mapped to a record, the RecordToAnyConverter#copyFieldsToIntermediary(Object, Map)-method will throw a NPE. This is due to an unsafe call to Object#getClass().

    The solution would be to check for a null value in the RecordToAnyConverter#copyFieldsToIntermediary(Object, Map)-method. Tests should also be added for this situation.

    bug fix-developed 
    opened by marcus-talbot42 0
  • [Proposal] Replace DefaultValues-class with Provider

    [Proposal] Replace DefaultValues-class with Provider

    I came up with a different proposal than the ticket suggests because I was a little bit confused with DefaultValueProvider accepting 2 different Types. Like, which type will the DefaultValue have? I could not make sense out of it, if I get the issue correctly.

    Although it's a bit too many classes with the suggested way, it is both extendable for new Types as well as for new Providers. As an example I added a secondary provider and called it Maximum.

    opened by berkayerten 0
  • [Proposal] Replace DefaultValues-class with Provider.

    [Proposal] Replace DefaultValues-class with Provider.

    The DefaultValues-class is rather rigid, and extensions of the class are inherently invasive.

    I propose to replace the DefaultValues-class with a Provider-interface, and an implementation DefaultValuesProvider. Please find the example implementation below.

    @FunctionalInterface
    public interface Provider<S, T> {
    
        T get(S source);
    
    }
    

    An implementation for the Provider-interface, that would offer roughly the same functionality as the DefaultValues-class, could look like this:

    public class DefaultValueProvider<S, T extends S> implements Provider<Class<S>, T> {
    
        private static final Map<Class<?>, ?> DEFAULT_VALUES = Map.ofEntries(
                Map.entry(boolean.class, false),
                Map.entry(byte.class, (byte) 0),
                Map.entry(short.class, (short) 0),
                Map.entry(int.class, 0),
                Map.entry(long.class, 0L),
                Map.entry(float.class, 0.0F),
                Map.entry(double.class, 0.0),
                Map.entry(List.class, Collections.emptyList()),
                Map.entry(Set.class, Collections.emptySet()),
                Map.entry(Map.class, Collections.emptyMap()),
                Map.entry(Optional.class, Optional.empty())
        );
    
        @Override
        public T get(Class<S> source) {
            if (source == null)
                return null;
            return (T) DEFAULT_VALUES.get(source);
        }
    }
    

    It could also be implemented as a record:

    public record DefaultValuesProviderRecord<S, T extends S>(Map<Object, Object> defaultValues) implements Provider<S, T> {
    
        private static final Map<Object, Object> DEFAULT_VALUES = Map.ofEntries(
                Map.entry(boolean.class, false),
                Map.entry(byte.class, (byte) 0),
                Map.entry(short.class, (short) 0),
                Map.entry(int.class, 0),
                Map.entry(long.class, 0L),
                Map.entry(float.class, 0.0F),
                Map.entry(double.class, 0.0),
                Map.entry(List.class, Collections.emptyList()),
                Map.entry(Set.class, Collections.emptySet()),
                Map.entry(Map.class, Collections.emptyMap()),
                Map.entry(Optional.class, Optional.empty())
        );
    
        public DefaultValuesProviderRecord() {
            this(DEFAULT_VALUES);
        }
    
        @Override
        public Map<Object, Object> defaultValues() {
            return Collections.unmodifiableMap(this.defaultValues);
        }
    
        @Override
        public T get(S source) {
            return (T) this.defaultValues().get(source);
        }
    }
    

    Aside from the benefits for extensibility of the Provider itself, this will also positively impact testing, and the composition of Form - and Result-classes.

    I also propose to allow, not one, but any number of providers for any given mapping, by modifying the Configuration to include a Collection of Provider-objects. This would allow users a greater degree of control over the mapping of their objects, and would be especially easy to use, due to the Provider-interface being a functional interface.

    enhancement good-first-issue 
    opened by marcus-talbot42 2
Releases(4.1.0)
  • 4.1.0(Nov 10, 2022)

    • Fixed #130 , #132 , #166 , #168
    • Implemented BeanRecordConstruct-annotation and BeanRecordConstructMode-enum, to assist in mapping record-classes. Please read the documentation for the proper usage.
    • Implemented mapping to and from JDK16 record-classes (#149).
    • Implemented convenience map-methods for Queues, Arrays, and Collections, and ParameterizedTypes in BeanMapper-class.
    • Added setting default values for classes through Configuration#addCustomDefaultValueForClass(Class, Object).
    • Updated Optional-mapping. Please read documentation in OptionalToObjectConverter and ObjectToOptionalConverter.
    • Various methods in OverrideConfiguration now throw an Exception, rather than performing NOP. While this may cause issues if you were using any of those methods, those methods weren't doing anything, so they should be safe to delete.

    For a full list of changes, please read the CHANGELOG.md

    Source code(tar.gz)
    Source code(zip)
  • v4.0.1(Sep 22, 2022)

    • Implemented fix for issue #121
    • Added support for Optional-returning getters #137
    • Fix for issue with dynamic class generation failing due to the ClassLoader returning null for a resource stream.
    Source code(tar.gz)
    Source code(zip)
  • v4.0.0(Sep 15, 2022)

  • v3.1.0(Dec 20, 2020)

    @BeanProperty could only be used with a name property. Adding a value alias allows this annotation to be used without any prefix and just the name of the property.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.2(May 24, 2017)

    • @BeanCollection.targetCollectionType (#74); @BeanCollection offers the possibility to supply your own collection class to construct when the bean usage is set to CONSTRUCT.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(May 9, 2017)

    • global converterChoosable; possibility to set converterChoosable on the root of BeanMapper (ie, CoreConfiguration)
    • info on converters chosen during collection processing; print information to the log on the BeanConverter that is chosen to map elements in collections.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Jun 29, 2016)

  • v0.2.19(Nov 19, 2015)

  • v0.2.18(Nov 18, 2015)

  • v0.2.16(Nov 13, 2015)

    Version v0.2.16 stable

    • Support for no args constructor. This resolves #34
    • Added new annotation: BeanAlias.
    • Added extra map argument FieldsToMap. Only the given fields would mapped. This resolves #36
    • Nested objects bugfix. This resolves #35
    Source code(tar.gz)
    Source code(zip)
  • v0.2.15(Oct 8, 2015)

  • v0.2.14(Sep 1, 2015)

  • v0.2.13(Aug 23, 2015)

  • v0.2.12(Aug 22, 2015)

  • v0.2.11(Aug 18, 2015)

  • v0.2.10(Jul 27, 2015)

  • v0.2.9(Jul 22, 2015)

  • v0.2.8(Jun 30, 2015)

  • v0.2.4(Jun 1, 2015)

    Bug:

    • Fixed bug so the BeanMapper only checkes if there where matches for the source class, but also what matches are available. If neither of these matches match the desired target class, a new match is added to the BeanMatchStore. This ensures the same source can be mapped to different target classes.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.3(May 28, 2015)

  • v0.2.2(May 27, 2015)

  • v0.2.1(May 20, 2015)

Library to programatically return the name of fields similar to the C# nameof operator

nameof() A Java library to programmatically return the name of fields similar to the C# nameof expression How to use? The library is part of the Centr

MoebiusCode 12 Aug 10, 2022
Translating texts via Youdao eco-freely in only one class

Youdao4J Translating texts via Youdao Translator by one class. Need GSON. Usage Youdao4J did lots of works in the background. DO NOT create morr Youda

iceBear 8 Dec 11, 2022
Magic Bean: A very basic library which will generate POJOs.

Magic Bean: A very basic library which will generate POJOs.

Ethan McCue 48 Dec 27, 2022
CIRCUS - a Java and Spring Boot application for creating rooms with the purpose of watching YouTube videos together, similar to Watch2Gether

CIRCUS Video rooms application built using Apache Kafka, Java, Spring Boot, Spring Security and PostgreSQL About CIRCUS is a Java and Spring Boot appl

Castanho Correia 1 Jun 5, 2022
Similar to the minimap application, this program gets information from the center of the screen and displays information about that creature from a database.

New-World-CreatureInfo Similar to the minimap application, this program gets information from the center of the screen and displays information about

Mal Ball 2 Sep 21, 2022
Spring Bean 容器创建

Spring手撸专栏:small-spring-step-01 作者: 小傅哥,Java Developer, ✏️ 虫洞 · 科技栈,博主, ?? 《重学Java设计模式》图书作者 本仓库以 Spring 源码学习为目的,通过手写简化版 Spring 框架,了解 Spring 核心原理。 在手写的

Spring 手撸专栏 13 Jul 18, 2021
Java-Programs---For-Practice is one of the Java Programming Practice Series By Shaikh Minhaj ( minhaj-313 ). This Series will help you to level up your Programming Skills. This Java Programs are very much helpful for Beginners.

Java-Programs---For-Practice is one of the Java Programming Practice Series By Shaikh Minhaj ( minhaj-313 ). This Series will help you to level up your Programming Skills. This Java Programs are very much helpful for Beginners. If You Have any doubt or query you can ask me here or you can also ask me on My LinkedIn Profile

Shaikh Minhaj 3 Nov 8, 2022
Desafios-bootcamps-dio - Desafios em C#, Java, JavaScript, Kotlin, Python e Ruby dos Bootcamps da Digital Innovation One

Desafios dos Bootcamps da Digital Innovation One Aqui você vai encontrar todos os desafios dos bootcamps que realizei da Digital Innovation One. Os có

Pleiterson Amorim 443 Dec 31, 2022
This is the java/Maven application we are building to solve one real world problem.

timly This is the java/Maven application we are building to solve one real world problem. As in MLH we are working with fellows across the globe and e

Osakpolor Obaseki 3 Feb 16, 2022
Spring Cloud Alibaba provides a one-stop solution for application development for the distributed solutions of Alibaba middleware.

Spring Cloud Alibaba A project maintained by Alibaba. See the 中文文档 for Chinese readme. Spring Cloud Alibaba provides a one-stop solution for distribut

Alibaba 24.4k Jan 1, 2023
APIKit:Discovery, Scan and Audit APIs Toolkit All In One.

APIKit:Discovery, Scan and Audit APIs Toolkit All In One.

APISecurity Community 976 Jan 9, 2023
The all-in-one cosmetics solution created by HibiscusMC Staff, for HibiscusMC.

HMCCosmetics Table of Contents Description Installation Download Description HMCCosmetics is a free, open source cosmetics plugin which allows you to

HibiscusMC 44 Dec 12, 2022
One of the groups in Arpia Tecnologia's Internship program.

Eagles Integrantes: Allan Quiterio Carlos Eduardo Gustavo Priscila Ramos Pedro Florêncio Yan Stivaletti Tarefas Deverá ser desenvolvido 5 itens: Usuár

Carlos Eduardo Rocha Miranda 3 Jan 19, 2022
During a machine coding round of the company, I designed the Conference Room System in a given one hour.

DesignConferenceRoom DESIGN A CONFERENCE ROOM One of the core problems which people face at every company is the unavailability of conference rooms. S

Shubham Thakur 2 Dec 23, 2022
There are two challenges one is to create a backend api the other is to create a frontend application to consume the public data api devall.

Sobre | Desafio | Resolução | Tecnologias | Execução | Itexto desafio tecnico Sobre os Desafios existem dois desafios um é criar uma api backend o out

fabricio S Miranda 1 Oct 18, 2021
A MOTD plugin for Velocity that caches network packets. This helps it be the fastest one of the MOTD plugins.

FastMOTD A MOTD plugin for Velocity that catches network packets. This helps it be the fastest one of the MOTD plugins. Test server: ely.su Features F

Elytrium 19 Dec 24, 2022
An All-In-One Macro for Hypixel Skyblock. Includes numerous features for Quality of Life that do NOT abide by the Hypixel Rules.

AIOMacro An All-In-One Macro for Hypixel Skyblock. Includes numerous features for Quality of Life that do NOT abide by the Hypixel Rules. Installation

Jackson 18 Dec 19, 2022
This repository is an example of one of my biggest object-oriented projects

COO - Project This repository belongs to Lounès Meddahi. This project was realized in collaboration with Matthieu Medeng Essia Computer Science and Ma

Lounès Mh 2 Sep 11, 2022
Proj that contains code for merging files' data into one

Merge System Program that's written on Java for merging data (int or string types) of files (preferably .txt) into one file. Merge System Note: progra

Akane Koro 2 Nov 27, 2022