- Copy and paste the following code: BuilderPropertyResolver
/**
* This class is used to map from an object to a builder who follows Builder Pattern.
*
* <pre>
* MapperFactory factory = new DefaultMapperFactory.Builder()
* .propertyResolverStrategy(new BuilderPropertyResolver())
* .build();
* factory.registerObjectFactory((Object o, MappingContext mappingContext)
* -> new MyBuilder(), TypeFactory.valueOf(MyBuilder.class));
* </pre>
*/
public class BuilderPropertyResolver extends IntrospectorPropertyResolver {
private static final Logger logger = LoggerFactory.getLogger(BuilderPropertyResolver.class);
@Override
protected void collectProperties(Class<?> type, Type<?> referenceType, Map<String, Property> properties) {
super.collectProperties(type, referenceType, properties);
if (StringUtils.endsWith(type.getName(), "Builder")) {
Set<String> fieldNames = Arrays.stream(type.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet());
Arrays.stream(type.getDeclaredMethods())
.filter(method -> fieldNames.contains(method.getName()))
.filter(method -> isWriteMethodInBuilder(type, method))
.forEach(method -> {
Property.Builder builder = new Property.Builder();
builder.expression(method.getName());
builder.name(method.getName());
builder.setter(method.getName() + "(%s)");
Class<?> fieldType = method.getParameterTypes()[0];
builder.type(this.resolvePropertyType(null, fieldType, type, referenceType));
Property property = builder.build(this);
properties.put(method.getName(), property);
});
}
}
private boolean isWriteMethodInBuilder(Class<?> type, Method method) {
try {
Class<?> returnType = method.getReturnType();
Class<?> fieldType = type.getDeclaredField(method.getName()).getType();
boolean onlyOneParameter = method.getParameterTypes().length == 1;
boolean methodReturnBuilderType = returnType.equals(type);
Class<?> methodParamType = method.getParameterTypes()[0];
boolean isFieldSetter = fieldType.equals(methodParamType);
return methodReturnBuilderType && onlyOneParameter && isFieldSetter;
} catch (NoSuchFieldException e) {
e.printStackTrace();
return false;
}
}
}
- Leverage this object
public class Mapper {
public static void main(String[] params) {
MapperFactory factory = new DefaultMapperFactory.Builder()
.propertyResolverStrategy(new BuilderPropertyResolver())
.build();
factory.registerObjectFactory((Object o, MappingContext mappingContext)
-> Person.builder(), TypeFactory.valueOf(Person.PersonBuilder.class));
PersonBO bo = new PersonBO();
bo.setName("TEST");
factory.classMap(PersonBO.class, Person.class);
System.out.println(factory.getMapperFacade().map(bo, Person.PersonBuilder.class).build());
Person.PersonBuilder builder = Person.builder().list(Arrays.asList("A"));
factory.getMapperFacade().map(bo, builder);
System.out.println(builder);
}
@Data
public static class PersonBO {
private String name;
private List<String> list;
}
@ToString
@Builder
public static class Person {
private String name;
private List<String> list;
}
}