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,59 @@ 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+ System .out .println ("mappings = " + mappings );
85+ }
86+
87+ private List <MappingInfo > createDependencies (MappingInfo info ) {
88+ List <MappingInfo > result = new ArrayList <>();
89+ ExecutableElement constructorElement = getConstructorElement (info .getTargetType ().toString ());
90+ List <? extends VariableElement > constructorParameters = constructorElement .getParameters ();
91+
92+ Map <String , ExecutableElement > argumentGetters = getGetters (info .getSourceType ().toString ());
93+
94+ if (constructorParameters .size () != argumentGetters .size ()) {
95+ processingEnv .getMessager ().printMessage (Diagnostic .Kind .MANDATORY_WARNING , "Target constructor have different arguments count" , info .getMethod ());
96+ }
97+
98+ for (VariableElement parameter : constructorParameters ) {
99+ String sourceFieldName = info .getSourceFieldName (parameter .getSimpleName ().toString ().toLowerCase ());
100+ ExecutableElement getter = argumentGetters .get (sourceFieldName .toLowerCase ());
101+ if (getter == null ) {
102+ processingEnv .getMessager ().printMessage (Diagnostic .Kind .ERROR , "Failed to find getter at source for target field" , parameter );
103+ return Collections .emptyList ();
104+ }
105+ if (!parameter .asType ().equals (getter .getReturnType ())) {
106+ MappingInfo fieldMapping = findMapping (getter .getReturnType (), parameter .asType ());
107+ if (fieldMapping == null ) {
108+ result .add (new MappingInfo (getter .getReturnType (), parameter .asType ()));
109+ }
110+ }
111+ }
112+ return result ;
77113 }
78114
79115 private MethodSpec generateMappingMethod (MappingInfo mapping ) {
@@ -99,16 +135,14 @@ private MethodSpec generateMappingMethod(MappingInfo mapping) {
99135 for (VariableElement constructorParameter : constructorParameters ) {
100136 String sourceFieldName = mapping .getSourceFieldName (constructorParameter .getSimpleName ().toString ().toLowerCase ());
101137 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- }
138+ System .out .println ("constructorParameter = " + constructorParameter );
139+ System .out .println ("getter = " + getter );
106140 if (!constructorParameter .asType ().equals (getter .getReturnType ())) {
107141 //getter and constructor parameter have different types
108142 MappingInfo depMapping = findMapping (getter .getReturnType (), constructorParameter .asType ());
109143 if (depMapping == null ) {
110- depMapping = new MappingInfo ( getter . getReturnType (), constructorParameter . asType () );
111- autoMappings . add ( depMapping ) ;
144+ processingEnv . getMessager (). printMessage ( Diagnostic . Kind . ERROR , "ERROR 1. Failed to find generated mapping info" , constructorParameter );
145+ return null ;
112146 }
113147 statementBuilder
114148 .append (separator )
@@ -143,6 +177,7 @@ private MethodSpec generateMappingMethod(MappingInfo mapping) {
143177 }
144178
145179 private ExecutableElement getConstructorElement (String className ) {
180+ System .out .println ("finding constructor for = " + className );
146181 TypeElement element = processingEnv .getElementUtils ().getTypeElement (className );
147182 List <? extends Element > enclosedElements = element .getEnclosedElements ();
148183 List <ExecutableElement > constructors = ElementFilter .constructorsIn (enclosedElements );
0 commit comments