Skip to content
This repository was archived by the owner on Jun 11, 2023. It is now read-only.

Commit d5902ee

Browse files
committed
<feature/nested_field> Implemented mapping generation for nested fields
1 parent 7cd2c71 commit d5902ee

File tree

4 files changed

+95
-41
lines changed

4 files changed

+95
-41
lines changed

processor/src/main/java/com/devindi/mapper/MapperGenerator.java

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.squareup.javapoet.ClassName;
44
import com.squareup.javapoet.MethodSpec;
5+
import com.squareup.javapoet.ParameterSpec;
6+
import com.squareup.javapoet.TypeName;
57
import com.squareup.javapoet.TypeSpec;
68

79
import java.util.ArrayList;
@@ -34,11 +36,13 @@ static MapperGenerator create(TypeElement element, ProcessingEnvironment env) {
3436
private final TypeElement element;
3537
private final ProcessingEnvironment processingEnv;
3638
private List<MappingInfo> mappings;
39+
private List<MappingInfo> autoMappings;
3740

3841
private MapperGenerator(TypeElement mapperElement, ProcessingEnvironment processingEnvironment) {
3942
this.processingEnv = processingEnvironment;
4043
this.element = mapperElement;
4144
mappings = new ArrayList<>();
45+
autoMappings = new ArrayList<>();
4246
}
4347

4448
public TypeSpec generate() {
@@ -53,6 +57,12 @@ public TypeSpec generate() {
5357
implBuilder.addMethod(methodSpec);
5458
}
5559

60+
for (MappingInfo autoMapping : autoMappings) {
61+
MethodSpec methodSpec = generateMappingMethod(autoMapping);
62+
implBuilder.addMethod(methodSpec);
63+
}
64+
65+
5666
return implBuilder.build();
5767
}
5868

@@ -77,7 +87,8 @@ private MethodSpec generateMappingMethod(MappingInfo mapping) {
7787
processingEnv.getMessager().printMessage(Diagnostic.Kind.MANDATORY_WARNING, "Target constructor have different arguments count", mapping.getMethod());
7888
}
7989

80-
MethodSpec.Builder methodBuilder = MethodSpec.overriding(mapping.getMethod());
90+
91+
MethodSpec.Builder methodBuilder = createMethodBuilder(mapping);
8192
StringBuilder statementBuilder = new StringBuilder();
8293
statementBuilder
8394
.append("return new ")
@@ -86,19 +97,7 @@ private MethodSpec generateMappingMethod(MappingInfo mapping) {
8697

8798
String separator = "";
8899
for (VariableElement constructorParameter : constructorParameters) {
89-
String sourceFieldName = constructorParameter.getSimpleName().toString().toLowerCase();
90-
com.devindi.mapper.Mapping annotation = mapping.getMethod().getAnnotation(com.devindi.mapper.Mapping.class);
91-
if (annotation != null && annotation.target().toLowerCase().equals(constructorParameter.getSimpleName().toString().toLowerCase())) {
92-
sourceFieldName = annotation.source();
93-
}
94-
Mappings mappings = mapping.getMethod().getAnnotation(Mappings.class);
95-
if (mappings != null) {
96-
for (com.devindi.mapper.Mapping fieldMapping : mappings.value()) {
97-
if (fieldMapping != null && fieldMapping.target().toLowerCase().equals(constructorParameter.getSimpleName().toString().toLowerCase())) {
98-
sourceFieldName = fieldMapping.source();
99-
}
100-
}
101-
}
100+
String sourceFieldName = mapping.getSourceFieldName(constructorParameter.getSimpleName().toString().toLowerCase());
102101
ExecutableElement getter = argumentGetters.get(sourceFieldName.toLowerCase());
103102
if (getter == null) {
104103
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Failed to find getter at source for target field", constructorParameter);
@@ -108,27 +107,26 @@ private MethodSpec generateMappingMethod(MappingInfo mapping) {
108107
//getter and constructor parameter have different types
109108
MappingInfo depMapping = findMapping(getter.getReturnType(), constructorParameter.asType());
110109
if (depMapping == null) {
111-
// TODO: 06.09.17 generate method
112-
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Getter return type and constructor argument type are different", mapping.getMethod());
113-
} else {
114-
statementBuilder
115-
.append(separator)
116-
.append('\n')
117-
.append("this.")
118-
.append(depMapping.getMethod().getSimpleName())
119-
.append("(")
120-
.append(mapping.getMethod().getParameters().get(0).getSimpleName())
121-
.append(".")
122-
.append(getter.getSimpleName())
123-
.append("()")
124-
.append(")");
125-
separator = ",";
110+
depMapping = new MappingInfo(getter.getReturnType(), constructorParameter.asType());
111+
autoMappings.add(depMapping);
126112
}
113+
statementBuilder
114+
.append(separator)
115+
.append('\n')
116+
.append("this.")
117+
.append(depMapping.getMethodName())
118+
.append("(")
119+
.append(mapping.getSourceName())
120+
.append(".")
121+
.append(getter.getSimpleName())
122+
.append("()")
123+
.append(")");
124+
separator = ",";
127125
} else {
128126
statementBuilder
129127
.append(separator)
130128
.append('\n')
131-
.append(mapping.getMethod().getParameters().get(0).getSimpleName())
129+
.append(mapping.getSourceName())
132130
.append(".")
133131
.append(getter.getSimpleName())
134132
.append("()");
@@ -141,8 +139,6 @@ private MethodSpec generateMappingMethod(MappingInfo mapping) {
141139
.append(")");
142140
methodBuilder.addStatement(statementBuilder.toString());
143141

144-
145-
146142
return methodBuilder.build();
147143
}
148144

@@ -175,7 +171,15 @@ private MappingInfo findMapping(TypeMirror source, TypeMirror target) {
175171
return null;
176172
}
177173

178-
private MappingInfo generateMapping(TypeMirror source, TypeMirror target) {
179-
return null;
174+
private MethodSpec.Builder createMethodBuilder(MappingInfo info) {
175+
ExecutableElement method = info.getMethod();
176+
if (method == null) {
177+
MethodSpec.Builder builder = MethodSpec.methodBuilder(info.getMethodName().toString());
178+
builder.addModifiers(Modifier.PRIVATE);
179+
builder.returns(TypeName.get(info.getTargetType()));
180+
builder.addParameter(ParameterSpec.builder(TypeName.get(info.getSourceType()), "source").build());
181+
return builder;
182+
}
183+
return MethodSpec.overriding(method);
180184
}
181185
}

processor/src/main/java/com/devindi/mapper/MappingInfo.java

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ public class MappingInfo {
1313
private final TypeMirror sourceType;
1414
private final TypeMirror targetType;
1515
private final ExecutableElement method;
16-
private final Name sourceName;
17-
private final Name mappingName;
16+
private final CharSequence sourceName;
17+
private final CharSequence mappingName;
1818

1919
public MappingInfo(ExecutableElement method) {
2020
targetType = method.getReturnType();
@@ -31,6 +31,14 @@ public MappingInfo(ExecutableElement method) {
3131
this.method = method;
3232
}
3333

34+
public MappingInfo(TypeMirror source, TypeMirror target) {
35+
sourceType = source;
36+
targetType = target;
37+
this.sourceName = "source";
38+
mappingName = "convert";
39+
method = null;
40+
}
41+
3442
public TypeMirror getSourceType() {
3543
return sourceType;
3644
}
@@ -39,15 +47,34 @@ public TypeMirror getTargetType() {
3947
return targetType;
4048
}
4149

42-
public Name getSourceName() {
43-
return sourceName;
50+
public ExecutableElement getMethod() {
51+
return method;
4452
}
4553

46-
public Name getMappingName() {
54+
public CharSequence getMethodName() {
4755
return mappingName;
4856
}
4957

50-
public ExecutableElement getMethod() {
51-
return method;
58+
public CharSequence getSourceName() {
59+
return sourceName;
60+
}
61+
62+
public String getSourceFieldName(String defaultName) {
63+
if (method == null) {
64+
return defaultName;
65+
}
66+
com.devindi.mapper.Mapping annotation = method.getAnnotation(com.devindi.mapper.Mapping.class);
67+
if (annotation != null && annotation.target().toLowerCase().equals(defaultName)) {
68+
return annotation.source();
69+
}
70+
Mappings mappings = method.getAnnotation(Mappings.class);
71+
if (mappings != null) {
72+
for (com.devindi.mapper.Mapping fieldMapping : mappings.value()) {
73+
if (fieldMapping != null && fieldMapping.target().toLowerCase().equals(defaultName)) {
74+
return fieldMapping.source();
75+
}
76+
}
77+
}
78+
return defaultName;
5279
}
5380
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.example.nested;
2+
3+
import com.devindi.mapper.Mapper;
4+
import com.devindi.mapper.Mapping;
5+
6+
@Mapper
7+
public interface AutoDriverMapper {
8+
@Mapping(source = "license", target = "licenseDto")
9+
DriverDto toDto(Driver d);
10+
}

sample/src/test/java/com/example/nested/DriverMapperTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,17 @@ public void testNestedMapping() {
2020
assertNull(driverDto.getLicenseDto().getPhotoUrl());
2121
assertEquals(date, driverDto.getLicenseDto().getValidUntil());
2222
}
23+
24+
@Test
25+
public void testAutoMapping() {
26+
Date date = new Date();
27+
Driver d = new Driver(25, "John Doe", new DriverLicense("42", null, date));
28+
AutoDriverMapper driverMapper = new AutoDriverMapperImpl();
29+
DriverDto driverDto = driverMapper.toDto(d);
30+
assertEquals(25, driverDto.getAge());
31+
assertEquals("John Doe", driverDto.getName());
32+
assertEquals("42", driverDto.getLicenseDto().getId());
33+
assertNull(driverDto.getLicenseDto().getPhotoUrl());
34+
assertEquals(date, driverDto.getLicenseDto().getValidUntil());
35+
}
2336
}

0 commit comments

Comments
 (0)