genType
equals null
*/
new(GeneratedType genType, GeneratedType targetType, Type keyType) {
super(genType, targetType, keyType)
implTemplate = new BuilderImplTemplate(this, type.enclosedTypes.get(0))
}
override isLocalInnerClass(JavaTypeName name) {
// Builders do not have inner types
return false;
}
/**
* Template method which generates JAVA class body for builder class and for IMPL class.
*
* @return string with JAVA source code
*/
override body() '''
«wrapToDocumentation(formatDataForJavaDoc(targetType))»
«targetType.annotations.generateDeprecatedAnnotation»
«generatedAnnotation»
public class «type.name» {
«generateFields(false)»
«constantsDeclarations()»
«IF augmentType !== null»
«generateAugmentField()»
«ENDIF»
«generateConstructorsFromIfcs()»
public «generateCopyConstructor(targetType, type.enclosedTypes.get(0))»
«generateMethodFieldsFrom()»
«generateGetters(false)»
«IF augmentType !== null»
«generateAugmentation()»
«ENDIF»
«generateSetters»
/**
* A new {@link «targetType.name»} instance.
*
* @return A new {@link «targetType.name»} instance.
*/
public «targetType.name» build() {
return new «type.enclosedTypes.get(0).importedName»(this);
}
«implTemplate.body»
}
'''
override generateDeprecatedAnnotation(AnnotationType ann) {
val forRemoval = ann.getParameter("forRemoval")
if (forRemoval !== null) {
return "@" + DEPRECATED.importedName + "(forRemoval = " + forRemoval.value + ")"
}
return "@" + SUPPRESS_WARNINGS.importedName + "(\"deprecation\")"
}
/**
* Generate default constructor and constructor for every implemented interface from uses statements.
*/
def private generateConstructorsFromIfcs() '''
public «type.name»() {
}
«IF (!(targetType instanceof GeneratedTransferObject))»
«FOR impl : targetType.implements SEPARATOR "\n"»
«generateConstructorFromIfc(impl)»
«ENDFOR»
«ENDIF»
'''
/**
* Generate constructor with argument of given type.
*/
def private Object generateConstructorFromIfc(Type impl) '''
«IF (impl instanceof GeneratedType)»
«IF impl.hasNonDefaultMethods»
public «type.name»(«impl.importedName» arg) {
«printConstructorPropertySetter(impl)»
}
«ENDIF»
«FOR implTypeImplement : impl.implements»
«generateConstructorFromIfc(implTypeImplement)»
«ENDFOR»
«ENDIF»
'''
def private Object printConstructorPropertySetter(Type implementedIfc) '''
«IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»
«val ifc = implementedIfc as GeneratedType»
«FOR getter : ifc.nonDefaultMethods»
«IF BindingMapping.isGetterMethodName(getter.name)»
«val propertyName = getter.propertyNameFromGetter»
«printPropertySetter(getter, '''arg.«getter.name»()''', propertyName)»;
«ENDIF»
«ENDFOR»
«FOR impl : ifc.implements»
«printConstructorPropertySetter(impl, getSpecifiedGetters(ifc))»
«ENDFOR»
«ENDIF»
'''
def private Object printConstructorPropertySetter(Type implementedIfc, SetIn general, this class is supposed to be used like this template:
«target» create«target»(int fooXyzzy, int barBaz) {
return new «target»Builder()
.setFoo(new FooBuilder().setXyzzy(fooXyzzy).build())
.setBar(new BarBuilder().setBaz(barBaz).build())
.build();
}
This pattern is supported by the immutable nature of «target», as instances can be freely passed around without worrying about synchronization issues.
As a side note: method chaining results in: