2222import javax .lang .model .element .Modifier ;
2323import javax .lang .model .type .TypeMirror ;
2424import java .util .ArrayList ;
25- import java .util .Collection ;
2625import java .util .List ;
2726import java .util .Map ;
2827import java .util .function .Function ;
@@ -39,19 +38,23 @@ public class ComponentImpl {
3938 private final ComponentElement component ;
4039 private final Map <Key , NamedBinding > sorted ;
4140 private final Function <Key , ParameterSpec > names ;
41+ private final MockBuilder mockBuilder ;
42+ private final Modifier [] modifiers ;
4243
4344 private ComponentImpl (
4445 ComponentElement component ,
4546 Map <Key , NamedBinding > sorted ,
46- Function <Key , ParameterSpec > names ) {
47+ Function <Key , ParameterSpec > names ,
48+ MockBuilder mockBuilder ) {
4749 this .component = component ;
4850 this .sorted = sorted ;
4951 this .names = names ;
52+ this .mockBuilder = mockBuilder ;
53+ this .modifiers = component .element ().getModifiers ().stream ()
54+ .filter (m -> m == PUBLIC ).toArray (Modifier []::new );
5055 }
5156
5257 TypeSpec generate () {
53- Modifier [] modifiers = component .element ().getModifiers ().stream ()
54- .filter (m -> m == PUBLIC ).toArray (Modifier []::new );
5558 TypeSpec .Builder spec = TypeSpec .classBuilder (component .generatedClass ())
5659 .addModifiers (modifiers )
5760 .addSuperinterface (component .element ().asType ());
@@ -83,22 +86,21 @@ TypeSpec generate() {
8386 spec .addType (createBuilderImpl (builder ));
8487 });
8588 if (component .factoryElement ().isEmpty () && component .builderElement ().isEmpty ()) {
86- spec .addMethod (generateCreateMethod (modifiers ));
89+ spec .addMethod (generateCreateMethod ());
90+ spec .addMethod (generateMockCreateMethod ());
8791 }
92+ spec .addType (mockBuilder .generate ());
8893 spec .addAnnotation (AnnotationSpec .builder (Generated .class )
8994 .addMember ("value" , CodeBlock .of ("$S" , SimpleComponentProcessor .class .getCanonicalName ()))
9095 .addMember ("comments" , CodeBlock .of ("$S" , "https://github.com/jbock-java/simple-component" ))
9196 .build ());
9297 spec .addModifiers (FINAL );
93- spec .addMethod (generateConstructor ());
94- if (sorted .values ().stream ().anyMatch (binding -> !(binding .binding () instanceof ParameterBinding ))) {
95- spec .addMethod (generateAllParametersConstructor ());
96- }
98+ spec .addMethod (generateAllParametersConstructor ());
9799 spec .addOriginatingElement (component .element ());
98100 return spec .build ();
99101 }
100102
101- private MethodSpec generateCreateMethod (Modifier [] modifiers ) {
103+ private MethodSpec generateCreateMethod () {
102104 List <CodeBlock > constructorParameters = new ArrayList <>();
103105 MethodSpec .Builder method = MethodSpec .methodBuilder ("create" );
104106 for (NamedBinding namedBinding : sorted .values ()) {
@@ -121,24 +123,13 @@ private MethodSpec generateCreateMethod(Modifier[] modifiers) {
121123 .build ();
122124 }
123125
124- private MethodSpec generateConstructor () {
125- MethodSpec .Builder constructor = MethodSpec .constructorBuilder ().addModifiers (PRIVATE );
126- for (NamedBinding namedBinding : sorted .values ()) {
127- Binding b = namedBinding .binding ();
128- Key key = b .key ();
129- String name = namedBinding .name ();
130- if (namedBinding .isComponentRequest ()) {
131- FieldSpec field = FieldSpec .builder (key .typeName (), name , PRIVATE , FINAL ).build ();
132- constructor .addStatement ("this.$N = $L" , field , b .invocation (names ));
133- } else if (!(b instanceof ParameterBinding )) {
134- ParameterSpec param = names .apply (key );
135- constructor .addStatement ("$T $N = $L" , key .typeName (), param , b .invocation (names ));
136- }
137- if (b instanceof ParameterBinding ) {
138- constructor .addParameter (names .apply (key ));
139- }
140- }
141- return constructor .build ();
126+ MethodSpec generateMockCreateMethod () {
127+ MethodSpec .Builder method = MethodSpec .methodBuilder ("mockBuilder" );
128+ method .addJavadoc ("Visible for testing. Do not call this method from production code." );
129+ method .addStatement ("return new $T()" , mockBuilder .getClassName ());
130+ method .returns (mockBuilder .getClassName ());
131+ method .addModifiers (STATIC );
132+ return method .build ();
142133 }
143134
144135 private List <FieldSpec > getFields () {
@@ -168,7 +159,6 @@ private MethodSpec generateAllParametersConstructor() {
168159 }
169160
170161 private TypeSpec createFactoryImpl (FactoryElement factory ) {
171- Collection <ParameterBinding > parameterBindings = component .parameterBindings ();
172162 TypeSpec .Builder spec = TypeSpec .classBuilder (factory .generatedClass ());
173163 spec .addModifiers (PRIVATE , STATIC , FINAL );
174164 spec .addSuperinterface (factory .element ().asType ());
@@ -178,58 +168,85 @@ private TypeSpec createFactoryImpl(FactoryElement factory) {
178168 method .addModifiers (abstractMethod .getModifiers ().stream ()
179169 .filter (m -> m == PUBLIC || m == PROTECTED ).collect (Collectors .toList ()));
180170 method .returns (TypeName .get (component .element ().asType ()));
181- method .addStatement ("return new $T($L)" , component .generatedClass (), parameterBindings .stream ()
182- .map (b -> CodeBlock .of ("$N" , names .apply (b .key ())))
183- .collect (CodeBlock .joining (", " )));
184- for (ParameterBinding b : parameterBindings ) {
185- method .addParameter (names .apply (b .key ()));
171+ List <CodeBlock > constructorParameters = new ArrayList <>();
172+ for (NamedBinding namedBinding : sorted .values ()) {
173+ Binding b = namedBinding .binding ();
174+ Key key = b .key ();
175+ CodeBlock invocation = b .invocation (names );
176+ ParameterSpec param = names .apply (key );
177+ if (namedBinding .isComponentRequest ()) {
178+ constructorParameters .add (CodeBlock .of ("$N" , names .apply (key )));
179+ }
180+ if (b instanceof ParameterBinding ) {
181+ method .addParameter (names .apply (b .key ()));
182+ } else {
183+ method .addStatement ("$T $N = $L" , key .typeName (), param , invocation );
184+ }
186185 }
186+ method .addStatement ("return new $T($L)" , component .generatedClass (), constructorParameters .stream ()
187+ .collect (CodeBlock .joining (", " )));
187188 spec .addMethod (method .build ());
188189 return spec .build ();
189190 }
190191
191192 private TypeSpec createBuilderImpl (BuilderElement builder ) {
192- Collection <ParameterBinding > parameterBindings = component .parameterBindings ();
193193 TypeMirror builderType = builder .element ().asType ();
194194 TypeSpec .Builder spec = TypeSpec .classBuilder (builder .generatedClass ());
195- for (ParameterBinding b : parameterBindings ) {
196- spec .addField (FieldSpec .builder (b .key ().typeName (), names .apply (b .key ()).name ).build ());
197- MethodSpec .Builder setterMethod = MethodSpec .methodBuilder (b .element ().getSimpleName ().toString ());
198- setterMethod .addAnnotation (Override .class );
199- setterMethod .addParameter (names .apply (b .key ()));
200- setterMethod .addStatement ("this.$N = $N" , names .apply (b .key ()), names .apply (b .key ()));
201- setterMethod .addStatement ("return this" );
202- setterMethod .returns (TypeName .get (builderType ));
203- setterMethod .addModifiers (b .element ().getModifiers ().stream ()
204- .filter (m -> m == PUBLIC || m == PROTECTED ).collect (Collectors .toList ()));
205- spec .addMethod (setterMethod .build ());
195+ MethodSpec .Builder buildMethod = MethodSpec .methodBuilder (builder .buildMethod ().getSimpleName ().toString ());
196+ List <CodeBlock > constructorParameters = new ArrayList <>();
197+ for (NamedBinding namedBinding : sorted .values ()) {
198+ Binding b = namedBinding .binding ();
199+ Key key = b .key ();
200+ CodeBlock invocation = b .invocation (names );
201+ ParameterSpec param = names .apply (key );
202+ if (namedBinding .isComponentRequest ()) {
203+ constructorParameters .add (CodeBlock .of ("$N" , names .apply (key )));
204+ }
205+ if (b instanceof ParameterBinding ) {
206+ spec .addField (FieldSpec .builder (b .key ().typeName (), names .apply (b .key ()).name ).build ());
207+ MethodSpec .Builder setterMethod = MethodSpec .methodBuilder (b .element ().getSimpleName ().toString ());
208+ setterMethod .addAnnotation (Override .class );
209+ setterMethod .addParameter (names .apply (b .key ()));
210+ setterMethod .addStatement ("this.$N = $N" , names .apply (b .key ()), names .apply (b .key ()));
211+ setterMethod .addStatement ("return this" );
212+ setterMethod .returns (TypeName .get (builderType ));
213+ setterMethod .addModifiers (b .element ().getModifiers ().stream ()
214+ .filter (m -> m == PUBLIC || m == PROTECTED ).collect (Collectors .toList ()));
215+ spec .addMethod (setterMethod .build ());
216+ } else {
217+ buildMethod .addStatement ("$T $N = $L" , key .typeName (), param , invocation );
218+ }
206219 }
207220 spec .addModifiers (PRIVATE , STATIC , FINAL );
208221 spec .addSuperinterface (builderType );
209- MethodSpec .Builder buildMethod = MethodSpec .methodBuilder (builder .buildMethod ().getSimpleName ().toString ());
210222 buildMethod .addAnnotation (Override .class );
211223 buildMethod .addModifiers (builder .buildMethod ().getModifiers ().stream ()
212224 .filter (m -> m == PUBLIC || m == PROTECTED ).collect (Collectors .toList ()));
213225 buildMethod .returns (TypeName .get (component .element ().asType ()));
214- buildMethod .addStatement ("return new $T($L)" , component .generatedClass (), parameterBindings .stream ()
215- .map (b -> CodeBlock .of ("$N" , names .apply (b .key ())))
226+ buildMethod .addStatement ("return new $T($L)" , component .generatedClass (), constructorParameters .stream ()
216227 .collect (CodeBlock .joining (", " )));
217228 spec .addMethod (buildMethod .build ());
218229 return spec .build ();
219230 }
220231
221232 public static final class Factory {
222233 private final ComponentElement component ;
234+ private final MockBuilder .Factory mockBuilderFactory ;
223235
224236 @ Inject
225- public Factory (ComponentElement component ) {
237+ public Factory (ComponentElement component , MockBuilder . Factory mockBuilderFactory ) {
226238 this .component = component ;
239+ this .mockBuilderFactory = mockBuilderFactory ;
227240 }
228241
229242 ComponentImpl create (
230243 Map <Key , NamedBinding > sorted ,
231244 Function <Key , ParameterSpec > names ) {
232- return new ComponentImpl (component , sorted , names );
245+ return new ComponentImpl (
246+ component ,
247+ sorted ,
248+ names ,
249+ mockBuilderFactory .create (sorted , names ));
233250 }
234251 }
235252}
0 commit comments