1010import io .jbock .simple .Inject ;
1111import io .jbock .simple .processor .SimpleComponentProcessor ;
1212import io .jbock .simple .processor .binding .Binding ;
13+ import io .jbock .simple .processor .binding .BuilderElement ;
1314import io .jbock .simple .processor .binding .ComponentElement ;
1415import io .jbock .simple .processor .binding .DependencyRequest ;
1516import io .jbock .simple .processor .binding .FactoryElement ;
1819
1920import javax .annotation .processing .Generated ;
2021import javax .lang .model .element .ExecutableElement ;
22+ import javax .lang .model .type .TypeMirror ;
2123import java .util .Collection ;
2224import java .util .Map ;
2325import java .util .function .Function ;
@@ -73,20 +75,29 @@ TypeSpec generate() {
7375 .collect (Collectors .toList ()));
7476 spec .addMethod (method .build ());
7577 }
76- component .factoryElement ().ifPresentOrElse (factory -> {
78+ component .factoryElement ().ifPresent (factory -> {
7779 spec .addMethod (MethodSpec .methodBuilder ("factory" )
7880 .addModifiers (STATIC )
7981 .returns (TypeName .get (factory .element ().asType ()))
8082 .addStatement ("return new $T()" , factory .generatedClass ())
8183 .build ());
82- spec .addType (createFactory (factory , names ));
83- }, () -> {
84+ spec .addType (createFactoryImpl (factory ));
85+ });
86+ component .builderElement ().ifPresent (builder -> {
87+ spec .addMethod (MethodSpec .methodBuilder ("builder" )
88+ .addModifiers (STATIC )
89+ .returns (TypeName .get (builder .element ().asType ()))
90+ .addStatement ("return new $T()" , builder .generatedClass ())
91+ .build ());
92+ spec .addType (createBuilderImpl (builder ));
93+ });
94+ if (component .factoryElement ().isEmpty () && component .builderElement ().isEmpty ()) {
8495 spec .addMethod (MethodSpec .methodBuilder ("create" )
8596 .addModifiers (STATIC )
8697 .returns (TypeName .get (component .element ().asType ()))
8798 .addStatement ("return new $T()" , component .generatedClass ())
8899 .build ());
89- });
100+ }
90101 spec .addAnnotation (AnnotationSpec .builder (Generated .class )
91102 .addMember ("value" , CodeBlock .of ("$S" , SimpleComponentProcessor .class .getCanonicalName ()))
92103 .addMember ("comments" , CodeBlock .of ("$S" , "https://github.com/jbock-java/simple-component" ))
@@ -97,9 +108,7 @@ TypeSpec generate() {
97108 return spec .build ();
98109 }
99110
100- private TypeSpec createFactory (
101- FactoryElement factory ,
102- Function <Key , ParameterSpec > names ) {
111+ private TypeSpec createFactoryImpl (FactoryElement factory ) {
103112 Collection <ParameterBinding > parameterBindings = component .parameterBindings ();
104113 TypeSpec .Builder spec = TypeSpec .classBuilder (factory .generatedClass ());
105114 spec .addModifiers (PRIVATE , STATIC , FINAL );
@@ -120,6 +129,36 @@ private TypeSpec createFactory(
120129 return spec .build ();
121130 }
122131
132+ private TypeSpec createBuilderImpl (BuilderElement builder ) {
133+ Collection <ParameterBinding > parameterBindings = component .parameterBindings ();
134+ TypeMirror builderType = builder .element ().asType ();
135+ TypeSpec .Builder spec = TypeSpec .classBuilder (builder .generatedClass ());
136+ for (ParameterBinding b : parameterBindings ) {
137+ spec .addField (FieldSpec .builder (b .key ().typeName (), names .apply (b .key ()).name ).build ());
138+ MethodSpec .Builder setterMethod = MethodSpec .methodBuilder (b .element ().getSimpleName ().toString ());
139+ setterMethod .addAnnotation (Override .class );
140+ setterMethod .addParameter (names .apply (b .key ()));
141+ setterMethod .addStatement ("this.$N = $N" , names .apply (b .key ()), names .apply (b .key ()));
142+ setterMethod .addStatement ("return this" );
143+ setterMethod .returns (TypeName .get (builderType ));
144+ setterMethod .addModifiers (b .element ().getModifiers ().stream ()
145+ .filter (m -> m == PUBLIC || m == PROTECTED ).collect (Collectors .toList ()));
146+ spec .addMethod (setterMethod .build ());
147+ }
148+ spec .addModifiers (PRIVATE , STATIC , FINAL );
149+ spec .addSuperinterface (builderType );
150+ MethodSpec .Builder buildMethod = MethodSpec .methodBuilder (builder .buildMethod ().getSimpleName ().toString ());
151+ buildMethod .addAnnotation (Override .class );
152+ buildMethod .addModifiers (builder .buildMethod ().getModifiers ().stream ()
153+ .filter (m -> m == PUBLIC || m == PROTECTED ).collect (Collectors .toList ()));
154+ buildMethod .returns (TypeName .get (component .element ().asType ()));
155+ buildMethod .addStatement ("return new $T($L)" , component .generatedClass (), parameterBindings .stream ()
156+ .map (b -> CodeBlock .of ("$N" , names .apply (b .key ())))
157+ .collect (CodeBlock .joining (", " )));
158+ spec .addMethod (buildMethod .build ());
159+ return spec .build ();
160+ }
161+
123162 public static final class Factory {
124163 private final ComponentElement component ;
125164
0 commit comments