77import com .squareup .javapoet .TypeSpec ;
88
99import java .util .ArrayList ;
10+ import java .util .Collections ;
1011import java .util .HashMap ;
12+ import java .util .HashSet ;
1113import java .util .List ;
1214import java .util .Map ;
15+ import java .util .Set ;
1316
1417import javax .annotation .processing .ProcessingEnvironment ;
1518import javax .lang .model .element .Element ;
@@ -35,14 +38,11 @@ static MapperGenerator create(TypeElement element, ProcessingEnvironment env) {
3538
3639 private final TypeElement element ;
3740 private final ProcessingEnvironment processingEnv ;
38- private List <MappingInfo > mappings ;
39- private List <MappingInfo > autoMappings ;
41+ private Set <MappingInfo > mappings ;
4042
4143 private MapperGenerator (TypeElement mapperElement , ProcessingEnvironment processingEnvironment ) {
4244 this .processingEnv = processingEnvironment ;
4345 this .element = mapperElement ;
44- mappings = new ArrayList <>();
45- autoMappings = new ArrayList <>();
4646 }
4747
4848 public TypeSpec generate () {
@@ -57,23 +57,57 @@ public TypeSpec generate() {
5757 implBuilder .addMethod (methodSpec );
5858 }
5959
60- for (MappingInfo autoMapping : autoMappings ) {
61- MethodSpec methodSpec = generateMappingMethod (autoMapping );
62- implBuilder .addMethod (methodSpec );
63- }
64-
65-
6660 return implBuilder .build ();
6761 }
6862
6963 private void collectMappings () {
64+ mappings = new HashSet <>();
7065 for (ExecutableElement method : ElementFilter .methodsIn (element .getEnclosedElements ())) {
7166 try {
7267 mappings .add (new MappingInfo (method ));
7368 } catch (IllegalArgumentException exc ) {
7469 processingEnv .getMessager ().printMessage (Diagnostic .Kind .WARNING , exc .getMessage (), method );
7570 }
7671 }
72+
73+ Set <MappingInfo > lastRow = mappings ;
74+ Set <MappingInfo > nextRow = new HashSet <>();
75+ do {
76+ for (MappingInfo mappingInfo : lastRow ) {
77+ nextRow .addAll (createDependencies (mappingInfo ));
78+ }
79+ mappings .addAll (nextRow );
80+ lastRow = nextRow ;
81+ nextRow = new HashSet <>();
82+ } while (!lastRow .isEmpty ());
83+ }
84+
85+ private List <MappingInfo > createDependencies (MappingInfo info ) {
86+ List <MappingInfo > result = new ArrayList <>();
87+ ExecutableElement constructorElement = getConstructorElement (info .getTargetType ().toString ());
88+ List <? extends VariableElement > constructorParameters = constructorElement .getParameters ();
89+
90+ Map <String , ExecutableElement > argumentGetters = getGetters (info .getSourceType ().toString ());
91+
92+ if (constructorParameters .size () != argumentGetters .size ()) {
93+ processingEnv .getMessager ().printMessage (Diagnostic .Kind .MANDATORY_WARNING , "Target constructor have different arguments count" , info .getMethod ());
94+ }
95+
96+ for (VariableElement parameter : constructorParameters ) {
97+ String sourceFieldName = info .getSourceFieldName (parameter .getSimpleName ().toString ().toLowerCase ());
98+ ExecutableElement getter = argumentGetters .get (sourceFieldName .toLowerCase ());
99+ if (getter == null ) {
100+ processingEnv .getMessager ().printMessage (Diagnostic .Kind .ERROR , "Failed to find getter at source for target field" , parameter );
101+ return Collections .emptyList ();
102+ }
103+ if (!parameter .asType ().equals (getter .getReturnType ())) {
104+ MappingInfo fieldMapping = findMapping (getter .getReturnType (), parameter .asType ());
105+ if (fieldMapping == null ) {
106+ result .add (new MappingInfo (getter .getReturnType (), parameter .asType ()));
107+ }
108+ }
109+ }
110+ return result ;
77111 }
78112
79113 private MethodSpec generateMappingMethod (MappingInfo mapping ) {
@@ -99,16 +133,12 @@ private MethodSpec generateMappingMethod(MappingInfo mapping) {
99133 for (VariableElement constructorParameter : constructorParameters ) {
100134 String sourceFieldName = mapping .getSourceFieldName (constructorParameter .getSimpleName ().toString ().toLowerCase ());
101135 ExecutableElement getter = argumentGetters .get (sourceFieldName .toLowerCase ());
102- if (getter == null ) {
103- processingEnv .getMessager ().printMessage (Diagnostic .Kind .ERROR , "Failed to find getter at source for target field" , constructorParameter );
104- return null ;
105- }
106136 if (!constructorParameter .asType ().equals (getter .getReturnType ())) {
107137 //getter and constructor parameter have different types
108138 MappingInfo depMapping = findMapping (getter .getReturnType (), constructorParameter .asType ());
109139 if (depMapping == null ) {
110- depMapping = new MappingInfo ( getter . getReturnType (), constructorParameter . asType () );
111- autoMappings . add ( depMapping ) ;
140+ processingEnv . getMessager (). printMessage ( Diagnostic . Kind . ERROR , "ERROR 1. Failed to find generated mapping info" , constructorParameter );
141+ return null ;
112142 }
113143 statementBuilder
114144 .append (separator )
0 commit comments