Skip to content
/ zebra Public

DIY objects mapping and use zebra for unified way to inject mappers.

License

Notifications You must be signed in to change notification settings

amgohan/zebra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zebra

DIY objects mapping and use zebra for unified way to inject mappers.

  • for the sake of performance, you do objects mapping manually and don't know how organize your mappers. Zebra come with a simple and unified way to :
    • create your mappers
    • manage one way and reverse mapping in one class
    • register your mappers and reuse them anywhere in your application
    • manage deep mapping

zebra-1.1.0.jar is only 9.1K, require java >= 1.5

See the whole example with unit tests here

Maven

    <dependency>
        <groupId>com.agileasoft</groupId>
        <artifactId>zebra</artifactId>
        <version>1.1.0</version>
    </dependency>

How-to

Create mappers and use zebra to inject them in a simple way to map from a source object to a destination object and vise versa using only java without any other framework.

Assume that we have DTOs UserDto, RoleDto and domain objects User and Role as following :

public class UserDto {

	private String firstName;

	private String lastName;

	private String username;

	private String password;

	private String birthdate;
	
	private List<RoleDto> roles;
	
	// ... getters and setters goes here
}
public enum RoleDto {

	ADMIN("Administrator"),
	USER("Simple User"),
	SUPER_ADMIN("Super User"),
	MANAGER("Team manager");

	private String description;

	RoleDto(final String description) {
		this.description = description;
	}

	public String getDescription() {
		return this.description;
	}
}
public class User {

	private String fullName;

	private String email;

	private String password;

	private Date birthDate;

	private List<Role> roles;
	
	// ... getters and setters goes here
}
public class Role {

	private String code;

	private String label;
	
  // ... getters and setters goes here
}

Now if we want to map UserDto to User and vis versa with deep mapping (that mean also map List to List) we must follow this steps :

1. Create RoleDtoEntityMapper :

public class RoleDtoEntityMapper extends Mapper<RoleDto, Role> {

	@Override
	public Role mapAToB(final RoleDto dto) {
		final Role entity = new Role();
		entity.setCode(dto.name());
		entity.setLabel(dto.getDescription());
		return entity;
	}

	@Override
	public RoleDto mapBToA(final Role entity) {
		return RoleDto.valueOf(entity.getCode());
	}
}

2. Create UserDtoEntityMapper :

public class UserDtoEntityMapper extends Mapper<UserDto, User> {

	private final static String DATE_FORMAT_PATTERN = "yyyy-MM-dd";

	@Override
	public User mapAToB(final UserDto dto) {
		final User entity = new User();

		entity.setFullName(dto.getFirstName() + ", " + dto.getLastName());

		entity.setEmail(dto.getUsername());

		entity.setBirthDate(this.parseDate(dto.getBirthdate()));

		entity.setPassword(dto.getPassword());

		// deep mapping : here we call the mapper to map RoleDto to Role using the injected mapper RoleDtoEntityMapper
		entity.setRoles(this.mapper.map(dto.getRoles(), Role.class));

		return entity;
	}

	@Override
	public UserDto mapBToA(final User entity) {
		final UserDto dto = new UserDto();

		dto.setBirthdate(this.formatDate(entity.getBirthDate()));

		final String[] fullNameSplit = entity.getFullName().split(", ");

		dto.setFirstName(fullNameSplit[0]);

		dto.setLastName(fullNameSplit[1]);

		dto.setUsername(entity.getEmail());

		dto.setPassword(entity.getPassword());

		// deep mapping : here we call the mapper to map Role to RoleDto using the injected mapper RoleDtoEntityMapper
		dto.setRoles(this.mapper.map(entity.getRoles(), RoleDto.class));

		return dto;
	}

	private Date parseDate(final String date) {
		final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_PATTERN);
		try {
			return sdf.parse(date);
		} catch (final ParseException exception) {
			return null;
		}
	}

	private String formatDate(final Date date) {
		final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_PATTERN);
		return sdf.format(date);
	}
}

Every mapper must extend the framework class Mapper<A, B> and override mapAToB and if needed override also mapBToA for reverse mapping. The clean and reusable way to map a complex object inside a mapper is to simply call the mapper attribute this.mapper.map(entity.getRoles(), RoleDto.class) which will inject the right (already registred) mapper and do the mappping. A clean way and reusable anywhere in your code.

3. Register mappers :

a. Pure java :

We will create a MapperFactorySingleton which will register all mappers and build a MapperProcessor :

public class MapperFactorySingleton {

	private static MapperFactorySingleton instance;

	private final MapperProcessor mapper;

	// private constructor
	private MapperFactorySingleton() {

		final MapperFactory factory = new MapperFactory();
		this.mapper = factory.registerAll(this.listMappers()).build();
	}

	public static MapperFactorySingleton getInstance() {

		if (MapperFactorySingleton.instance == null) {
			MapperFactorySingleton.instance = new MapperFactorySingleton();
		}

		return MapperFactorySingleton.instance;
	}

	public MapperProcessor getMapper() {

		return this.mapper;
	}

	@SuppressWarnings("rawtypes")
	private List<Mapper> listMappers() {

		final List<Mapper> listMappers = new ArrayList<>();

		// register manually your mappers here.
		listMappers.add(new UserDtoEntityMapper());
		listMappers.add(new RoleDtoEntityMapper());
		// ... add other mappers here.
		return listMappers;
	}
}
  • MapperFactorySingleton register all your mappers (added manually in listMappers method) and create an instance of MapperProcessor which will be injected wherever you want to do a mapping from a source class A to a destination class B.
  • So wherever you are in your code you can call the entry point of all your mappers by MapperFactorySingleton.getInstance().getMapper() and then call the method map
  • Example :
MapperProcessor mapper = MapperFactorySingleton.getInstance().getMapper();
UserDto userDto = new UserDto();
// call setters here to add some data to the userDto instance.
User user = mapper.map(userDto, User.class);

See the whole example with unit tests here

b. In Spring context :

TODO : coming soon

License

Apache 2.0 License

About

DIY objects mapping and use zebra for unified way to inject mappers.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages