Skip to content

This library is meant to be a mapper based with Java annotations, this way you don't need to configure nothing, only import and use it. This is a need when you are working trying to isolate logical or critical classes from DTO or POJO's for example. This can be useful when you are following architectures or concepts like clean arch

License

Notifications You must be signed in to change notification settings

gfrmoretti/anmap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AnMap (Annotation Mapper)


License Maven Open Source? Yes! Generic badge Javadoc

Coverage Forks Stars Issues Open Issues Closed Follow

Index

Objective

This library is meant to be a mapper based with Java annotations, this way you don't need to configure nothing, only import and use it. This is a need when you are working trying to isolate logical or critical classes from DTO or POJO's for example. This can be useful when you are following architectures or concepts like clean arch, but this can use like any map you want, works fine for simple or complex objects.


Mapper Concept

The main concept to know about this mapper is the source and target concepts. To mapper any object to another always exists the data source object and the target object. The library works considering this concepts. Source is the object with the data to map and target is the object to receive this data.

Annotations

Annotations are useful for customizing mapper actions and telling AnMap what to do with that field when mapped. They can be placed in both object, source or target, it is important to know that when you want to map one object to another, all the annotations must be put only in one side of the relationship, for example, if you put one annotation in the source side, you need to put all in the source side and vice-versa.

The lib auto-detect which side has the annotations, if is the source or target, but can be configured manually. The auto-detection logic is specified bellow.

Auto-Detection Annotations Cases

  • If both classes are annotated, source has the preference.
  • If any classes are annotated, source has preference, but in these case doesn't matter, without annotation the lib will try to match field by field literally.
  • If you need, you can specify on the map method which side use to process the annotations.
  • If you need multiples mapper config to same object, exists one annotation to configure that (@MapperConfig)

Current Annotations:

  • @Map: use to map fields with different names. Ex: id field to uuid field.
  • @IgnoreMap: use to ignore the field.
  • @FunctionMap: use to map a field using a function. Ex: you can convert a type to another like Double to String.
  • @DateMap: use to convert and format dates.
  • @EnumMap: use to convert enums, simple enums can be mapped to string without annotation, but to map string to enum you will need this annotation.
  • @ImplicitMap: use to implicit map an object inside the current mapped object, this means that you can create a hierarchy between objects and call mapper on each element using this annotation.
  • @ConstructorMap: use to configure the priority and null values validation to
  • create any target class. Accept only in constructors.

Inheritance

The library support Inheritance mapper, that means, if you have a source inheritance structure and the target class have the same inheritance structure, the mapper can be made for all the fields. Also, the AnMap can compile all the source inheritance fields to a single target class.

You can find some examples in InheritanceMapperTest class here.


Quick Start

Installing with maven

<dependency>
  <groupId>io.github.gfrmoretti</groupId>
  <artifactId>an-map</artifactId>
  <version>1.1.0</version>
</dependency>

Simple map

@AllArgsConstructor
@Getter
public class User {
    private @NotNull String login;
    private @NotNull String password;
    private @NotNull Integer remainingTrialDays;
    private @NotNull Status status;
    private @NotNull Address address;
}

@Data
public class InsertUserRequest {
    private @NotNull String login;
    private @NotNull String password;
    private @NotNull Integer remainingTrialDays;
    private @NotNull String status;
    private @NotNull Address address;
}

public class QuickStartTest {

    @Test
    @DisplayName("Quick Start: Simple map.")
    void simpleMap() {
        var user = new User("gm123456", "test", 15, Status.ENABLE,
                new Address("Street 14", 444, "Pan City")
        );

        var request = AnMap.map(user, InsertUserRequest.class).orElse(null);

        assertNotNull(request);
        System.out.println(request);
    }
}

Output

InsertUserRequest(login=gm123456, password=test, remainingTrialDays=15, status=ENABLE, address=Address(street=Street 14, number=444, city=Pan City))

The Best of AnMap

@AllArgsConstructor
@Data
public class House {
    private long id;
    @Map("nameOfOwner")
    private String ownerName;
    @ImplicitMap
    private List<Door> doors;
    @Map("valuationStatusRequest")
    @EnumMap(enumMapType = EnumMapType.MAP_ENUM)
    private ValuationStatus valuationStatus;
    @DateMap(formatPattern = "yyyy-MM-dd")
    private Instant acquisitionDate;
    @FunctionMap(BigDecimalToDoubleFunctionMapper.class)
    private BigDecimal value;
}

@AllArgsConstructor
@Data
public class Door {
    private int height;
    private int width;
}

public enum ValuationStatus {
    HIGH,
    MID,
    DOWN
}

// ##### TARGET CLASSES #####

@AllArgsConstructor
@Data
public class HouseRequest {
    private long id;
    private String nameOfOwner;
    private List<DoorRequest> doors;
    private ValuationStatusRequest valuationStatusRequest;
    private String acquisitionDate;
    private double value;
}

@AllArgsConstructor
@Data
public class DoorRequest {
    private int height;
    private int width;
}

public enum ValuationStatusRequest {
    HIGH,
    MID,
    DOWN
}

public class QuickStartTest {

    @Test
    @DisplayName("Quick Start: Best of AnMap")
    void bestOf() {
        var doors = List.of(new Door(120, 130), new Door(120, 90));
        var house = new House(123, "owner", doors, ValuationStatus.HIGH, Instant.now(), new BigDecimal(10000));

        var request = AnMap.map(house, HouseRequest.class).orElse(null);

        assertNotNull(request);
        System.out.println(request);
    }
}

Output

HouseRequest(id=123, nameOfOwner=owner, doors=[DoorRequest(height=120, width=130), DoorRequest(height=120, width=90)], valuationStatusRequest=HIGH, acquisitionDate=2023-03-28, value=10000.0)

More examples

All these samples can be found in the quickstart folder inside the test directory, also you can use all the test in features to learn how to use all the features that this library can do it, these tests are located in the features folder inside the test directory.

Learn more

Learn more about the annotations and how to use.

Learn some important concepts to understand some behaviors.

JavaDoc

About

This library is meant to be a mapper based with Java annotations, this way you don't need to configure nothing, only import and use it. This is a need when you are working trying to isolate logical or critical classes from DTO or POJO's for example. This can be useful when you are following architectures or concepts like clean arch

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages