1 /* 2 * Copyright (C) 2016 The Dagger Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package dagger.grpc.server.processor; 18 19 import static com.google.common.base.CaseFormat.LOWER_CAMEL; 20 import static com.google.common.base.CaseFormat.UPPER_CAMEL; 21 import static com.squareup.javapoet.MethodSpec.constructorBuilder; 22 import static com.squareup.javapoet.TypeSpec.classBuilder; 23 import static javax.lang.model.element.Modifier.ABSTRACT; 24 import static javax.lang.model.element.Modifier.FINAL; 25 import static javax.lang.model.element.Modifier.PRIVATE; 26 import static javax.lang.model.element.Modifier.PUBLIC; 27 import static javax.lang.model.element.Modifier.STATIC; 28 29 import com.squareup.javapoet.ClassName; 30 import com.squareup.javapoet.MethodSpec; 31 import com.squareup.javapoet.TypeSpec; 32 import dagger.grpc.server.GrpcService; 33 34 /** 35 * An object that generates the unscoped-proxying service definition module for a {@link 36 * GrpcService}-annotated service implementation. 37 */ 38 final class UnscopedGrpcServiceModuleGenerator extends SourceGenerator { 39 40 private final GrpcServiceModel grpcServiceModel; 41 UnscopedGrpcServiceModuleGenerator(GrpcServiceModel grpcServiceModel)42 UnscopedGrpcServiceModuleGenerator(GrpcServiceModel grpcServiceModel) { 43 super(grpcServiceModel.packageName()); 44 this.grpcServiceModel = grpcServiceModel; 45 } 46 47 @Override createType()48 protected TypeSpec createType() { 49 ClassName unscopedComponentFactory = 50 grpcServiceModel.unscopedServiceModuleName.nestedClass( 51 grpcServiceModel.serviceImplementationClassName.simpleName() + "ComponentFactory"); 52 TypeSpec.Builder unscopedServiceModule = 53 classBuilder(grpcServiceModel.unscopedServiceModuleName) 54 .addJavadoc( 55 "Install this module in the {@link $T @Singleton} server component\n", 56 JavaxInject.singleton().type) 57 .addJavadoc( 58 "if it implements {@link $T}.\n", grpcServiceModel.serviceDefinitionTypeName); 59 grpcServiceModel.generatedAnnotation().ifPresent(unscopedServiceModule::addAnnotation); 60 return unscopedServiceModule 61 .addAnnotation( 62 Dagger.module(grpcServiceModel.proxyModuleName, grpcServiceModel.serviceModuleName)) 63 .addModifiers(PUBLIC, ABSTRACT) 64 .addType(unscopedComponentFactory(unscopedComponentFactory.simpleName())) 65 .addMethod(bindSubcomponentFactory(unscopedComponentFactory)) 66 .addMethod(constructorBuilder().addModifiers(PRIVATE).build()) 67 .build(); 68 } 69 70 /** 71 * Returns the class that implements the component factory type by returning the singleton 72 * component itself. 73 */ unscopedComponentFactory(String simpleName)74 private TypeSpec unscopedComponentFactory(String simpleName) { 75 return TypeSpec.classBuilder(simpleName) 76 .addModifiers(STATIC, FINAL) 77 .addSuperinterface(grpcServiceModel.serviceDefinitionTypeFactoryName) 78 .addField(grpcServiceModel.serviceDefinitionTypeName, "component", PRIVATE, FINAL) 79 .addMethod( 80 MethodSpec.constructorBuilder() 81 .addAnnotation(JavaxInject.inject()) 82 .addParameter(grpcServiceModel.serviceDefinitionTypeName, "component") 83 .addStatement("this.component = component") 84 .build()) 85 .addMethod( 86 MethodSpec.methodBuilder("grpcService") 87 .addAnnotation(Override.class) 88 .addModifiers(PUBLIC) 89 .returns(grpcServiceModel.serviceDefinitionTypeName) 90 .addParameter(Dagger.GrpcServer.GRPC_CALL_METADATA_MODULE, "grpcCallMetadataModule") 91 .addStatement("return component") 92 .build()) 93 .build(); 94 } 95 96 /** 97 * Returns the {@link dagger.Binds @Binds} method that binds the component factory type to the 98 * {@linkplain #unscopedComponentFactory(String) unscoped component factory implementation class}. 99 */ bindSubcomponentFactory(ClassName unscopedComponentFactory)100 private MethodSpec bindSubcomponentFactory(ClassName unscopedComponentFactory) { 101 return MethodSpec.methodBuilder( 102 UPPER_CAMEL.to( 103 LOWER_CAMEL, grpcServiceModel.serviceDefinitionTypeFactoryName.simpleName())) 104 .addAnnotation(Dagger.binds()) 105 .addModifiers(ABSTRACT) 106 .returns(grpcServiceModel.serviceDefinitionTypeFactoryName) 107 .addParameter(unscopedComponentFactory, "factory") 108 .build(); 109 } 110 } 111