X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-java-api-generator%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fjava%2Fapi%2Fgenerator%2FBuilderTemplate.xtend;h=79567d51bcbf6a8088bed8b6c7c967e1302955a4;hb=938a70d61dc8948d65e8c7ca64ffcbf4e6162b68;hp=f70787d07d48e5d998d14e997b9d7c1fcac4a767;hpb=8d8bc1f301843ffe57d344b4c64bb26e45954e28;p=mdsal.git diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend index f70787d07d..79567d51bc 100644 --- a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend +++ b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend @@ -8,10 +8,10 @@ package org.opendaylight.mdsal.binding.java.api.generator import static extension org.apache.commons.text.StringEscapeUtils.escapeJava -import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_OBJECT +import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.DATA_OBJECT import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTABLE_AUGMENTATION_NAME import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTATION_FIELD -import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME +import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.BINDING_CONTRACT_IMPLEMENTED_INTERFACE_NAME import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableSet @@ -30,22 +30,14 @@ import org.opendaylight.mdsal.binding.model.api.JavaTypeName import org.opendaylight.mdsal.binding.model.api.MethodSignature; import org.opendaylight.mdsal.binding.model.api.ParameterizedType import org.opendaylight.mdsal.binding.model.api.Type -import org.opendaylight.mdsal.binding.model.util.TypeConstants -import org.opendaylight.mdsal.binding.model.util.Types +import org.opendaylight.mdsal.binding.model.ri.TypeConstants +import org.opendaylight.mdsal.binding.model.ri.Types import org.opendaylight.mdsal.binding.spec.naming.BindingMapping -import org.opendaylight.yangtools.concepts.Builder /** * Template for generating JAVA builder classes. */ class BuilderTemplate extends AbstractBuilderTemplate { - /** - * Constant used as suffix for builder name. - */ - package static val BUILDER_STR = "Builder"; - - static val BUILDER = JavaTypeName.create(Builder) - val BuilderImplTemplate implTemplate /** @@ -71,18 +63,33 @@ class BuilderTemplate extends AbstractBuilderTemplate { «wrapToDocumentation(formatDataForJavaDoc(targetType))» «targetType.annotations.generateDeprecatedAnnotation» «generatedAnnotation» - public class «type.name» implements «BUILDER.importedName»<«targetType.importedName»> { + public class «type.name» { «generateFields(false)» «constantsDeclarations()» «IF augmentType !== null» - «generateAugmentField()» + «val augmentTypeRef = augmentType.importedName» + «val mapTypeRef = JU_MAP.importedName» + «mapTypeRef»<«CLASS.importedName», «augmentTypeRef»> «AUGMENTATION_FIELD» = «mapTypeRef».of(); «ENDIF» + /** + * Construct an empty builder. + */ + public «type.name»() { + // No-op + } + «generateConstructorsFromIfcs()» + «val targetTypeName = targetType.importedName» + /** + * Construct a builder initialized with state from specified {@link «targetTypeName»}. + * + * @param base «targetTypeName» from which the builder should be initialized + */ public «generateCopyConstructor(targetType, type.enclosedTypes.get(0))» «generateMethodFieldsFrom()» @@ -95,8 +102,12 @@ class BuilderTemplate extends AbstractBuilderTemplate { «generateSetters» - @«OVERRIDE.importedName» - public «targetType.name» build() { + /** + * A new {@link «targetTypeName»} instance. + * + * @return A new {@link «targetTypeName»} instance. + */ + public «targetType.importedNonNull» build() { return new «type.enclosedTypes.get(0).importedName»(this); } @@ -116,9 +127,6 @@ class BuilderTemplate extends AbstractBuilderTemplate { * 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)» @@ -132,9 +140,16 @@ class BuilderTemplate extends AbstractBuilderTemplate { def private Object generateConstructorFromIfc(Type impl) ''' «IF (impl instanceof GeneratedType)» «IF impl.hasNonDefaultMethods» - public «type.name»(«impl.fullyQualifiedName» arg) { + «val typeName = impl.importedName» + /** + * Construct a new builder initialized from specified {@link «typeName»}. + * + * @param arg «typeName» from which the builder should be initialized + */ + public «type.name»(«typeName» arg) { «printConstructorPropertySetter(impl)» } + «ENDIF» «FOR implTypeImplement : impl.implements» «generateConstructorFromIfc(implTypeImplement)» @@ -206,7 +221,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { * Set fields from given grouping argument. Valid argument is instance of one of following types: * * @@ -231,7 +246,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { def private generateIfCheck(Type impl, List done) ''' «IF (impl instanceof GeneratedType && (impl as GeneratedType).hasNonDefaultMethods)» «val implType = impl as GeneratedType» - if (arg instanceof «implType.fullyQualifiedName») { + if (arg instanceof «implType.importedName») { «printPropertySetter(implType)» isValidArg = true; } @@ -243,7 +258,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { «val ifc = implementedIfc as GeneratedType» «FOR getter : ifc.nonDefaultMethods» «IF BindingMapping.isGetterMethodName(getter.name) && !hasOverrideAnnotation(getter)» - «printPropertySetter(getter, '''((«ifc.fullyQualifiedName»)arg).«getter.name»()''', getter.propertyNameFromGetter)»; + «printPropertySetter(getter, '''((«ifc.importedName»)arg).«getter.name»()''', getter.propertyNameFromGetter)»; «ENDIF» «ENDFOR» «ENDIF» @@ -255,15 +270,21 @@ class BuilderTemplate extends AbstractBuilderTemplate { if (Types.strictTypeEquals(getter.returnType, ownGetterType)) { return "this._" + propertyName + " = " + retrieveProperty } - if (Types.isListType(ownGetterType)) { - val itemType = (ownGetterType as ParameterizedType).actualTypeArguments.get(0) - return ''' - this._«propertyName» = «CODEHELPERS.importedName».checkListFieldCast(«itemType.fullyQualifiedName».class, "«propertyName»", «retrieveProperty»)''' + if (ownGetterType instanceof ParameterizedType) { + val itemType = ownGetterType.actualTypeArguments.get(0) + if (Types.isListType(ownGetterType)) { + return printPropertySetter(retrieveProperty, propertyName, "checkListFieldCast", itemType.importedName) + } + if (Types.isSetType(ownGetterType)) { + return printPropertySetter(retrieveProperty, propertyName, "checkSetFieldCast", itemType.importedName) + } } - return ''' - this._«propertyName» = «CODEHELPERS.importedName».checkFieldCast(«ownGetter.returnType.fullyQualifiedName».class, "«propertyName»", «retrieveProperty»)''' + return printPropertySetter(retrieveProperty, propertyName, "checkFieldCast", ownGetterType.importedName) } + def private printPropertySetter(String retrieveProperty, String propertyName, String checkerName, String className) ''' + this._«propertyName» = «CODEHELPERS.importedName».«checkerName»(«className».class, "«propertyName»", «retrieveProperty»)''' + private def List getBaseIfcs(GeneratedType type) { val List baseIfcs = new ArrayList(); for (ifc : type.implements) { @@ -291,7 +312,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { private def List toListOfNames(Collection types) { val List names = new ArrayList for (type : types) { - names.add(type.fullyQualifiedName) + names.add(type.importedName) } return names } @@ -321,7 +342,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { def private generateSetter(GeneratedProperty field) { val returnType = field.returnType if (returnType instanceof ParameterizedType) { - if (Types.isListType(returnType)) { + if (Types.isListType(returnType) || Types.isSetType(returnType)) { val arguments = returnType.actualTypeArguments if (arguments.isEmpty) { return generateListSetter(field, Types.objectType) @@ -353,18 +374,15 @@ class BuilderTemplate extends AbstractBuilderTemplate { ''' - // FIXME: MDSAL-540: remove the migration setter def private generateMapSetter(GeneratedProperty field, Type actualType) ''' «val restrictions = restrictionsForSetter(actualType)» - «val actualTypeRef = actualType.importedName» - «val setterName = "set" + field.name.toFirstUpper» «IF restrictions !== null» «generateCheckers(field, restrictions, actualType)» «ENDIF» - public «type.getName» «setterName»(final «field.returnType.importedName» values) { + public «type.getName» set«field.name.toFirstUpper»(final «field.returnType.importedName» values) { «IF restrictions !== null» if (values != null) { - for («actualTypeRef» value : values.values()) { + for («actualType.importedName» value : values.values()) { «checkArgument(field, restrictions, actualType, "value")» } } @@ -372,24 +390,6 @@ class BuilderTemplate extends AbstractBuilderTemplate { this.«field.fieldName» = values; return this; } - - /** - * Utility migration setter. - * - * IMPORTANT NOTE: This method does not completely match previous mechanics, as the list is processed as - * during this method's execution. Any future modifications of the list are NOT - * reflected in this builder nor its products. - * - * @param values Legacy List of values - * @return this builder - * @throws IllegalArgumentException if the list contains entries with the same key - * @throws NullPointerException if the list contains a null entry - * @deprecated Use {#link #«setterName»(«JU_MAP.importedName»)} instead. - */ - @«DEPRECATED.importedName»(forRemoval = true) - public «type.getName» «setterName»(final «JU_LIST.importedName»<«actualTypeRef»> values) { - return «setterName»(«CODEHELPERS.importedName».compatMap(values)); - } ''' def private generateSimpleSetter(GeneratedProperty field, Type actualType) ''' @@ -409,21 +409,6 @@ class BuilderTemplate extends AbstractBuilderTemplate { this.«field.fieldName» = value; return this; } - «val uintType = UINT_TYPES.get(field.returnType)» - «IF uintType !== null» - - /** - * Utility migration setter. - * - * @param value field value in legacy type - * @return this builder - * @deprecated Use {#link «setterName»(«field.returnType.importedJavadocName»)} instead. - */ - @Deprecated(forRemoval = true) - public «type.getName» «setterName»(final «uintType.importedName» value) { - return «setterName»(«CODEHELPERS.importedName».compatUint(value)); - } - «ENDIF» ''' /** @@ -444,7 +429,6 @@ class BuilderTemplate extends AbstractBuilderTemplate { «IF augmentType !== null» «val augmentTypeRef = augmentType.importedName» - «val jlClassRef = CLASS.importedName» «val hashMapRef = JU_HASHMAP.importedName» /** * Add an augmentation to this builder's product. @@ -454,12 +438,11 @@ class BuilderTemplate extends AbstractBuilderTemplate { * @throws NullPointerException if {@code augmentation} is null */ public «type.name» addAugmentation(«augmentTypeRef» augmentation) { - «jlClassRef» augmentationType = augmentation.«DATA_CONTAINER_IMPLEMENTED_INTERFACE_NAME»(); if (!(this.«AUGMENTATION_FIELD» instanceof «hashMapRef»)) { this.«AUGMENTATION_FIELD» = new «hashMapRef»<>(); } - this.«AUGMENTATION_FIELD».put(augmentationType, augmentation); + this.«AUGMENTATION_FIELD».put(augmentation.«BINDING_CONTRACT_IMPLEMENTED_INTERFACE_NAME»(), augmentation); return this; } @@ -470,7 +453,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { * @param augmentationType augmentation type to be removed * @return this builder */ - public «type.name» removeAugmentation(«jlClassRef» augmentationType) { + public «type.name» removeAugmentation(«CLASS.importedName» augmentationType) { if (this.«AUGMENTATION_FIELD» instanceof «hashMapRef») { this.«AUGMENTATION_FIELD».remove(augmentationType); } @@ -480,7 +463,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { ''' private def createDescription(GeneratedType targetType) { - val target = type.importedName + val target = targetType.importedName return ''' Class that builds {@link «target»} instances. Overall design of the class is that of a fluent interface, where method chaining is used. @@ -489,7 +472,7 @@ class BuilderTemplate extends AbstractBuilderTemplate { In general, this class is supposed to be used like this template:
           
-            «target» createTarget(int fooXyzzy, int barBaz) {
+            «target» create«target»(int fooXyzzy, int barBaz) {
                 return new «target»Builder()
                     .setFoo(new FooBuilder().setXyzzy(fooXyzzy).build())
                     .setBar(new BarBuilder().setBaz(barBaz).build())
@@ -510,14 +493,13 @@ class BuilderTemplate extends AbstractBuilderTemplate {
               invocation, which is terminated by {@link #build()}, which is then returned from the method
           
  • better understanding by humans, as the scope of mutable state (the builder) is kept to a minimum and is very localized
  • -
  • better optimization oportunities, as the object scope is minimized in terms of invocation (rather than +
  • better optimization opportunities, as the object scope is minimized in terms of invocation (rather than method) stack, making escape analysis a lot easier. Given enough compiler (JIT/AOT) prowess, the cost of th builder object can be completely eliminated
  • @see «target» - @see «BUILDER.importedName» ''' } @@ -532,6 +514,14 @@ class BuilderTemplate extends AbstractBuilderTemplate { } private def generateAugmentation() ''' + /** + * Return the specified augmentation, if it is present in this builder. + * + * @param augmentation type + * @param augmentationType augmentation type class + * @return Augmentation object from this builder, or {@code null} if not present + * @throws «NPE.importedName» if {@code augmentType} is {@code null} + */ @«SUPPRESS_WARNINGS.importedName»({ "unchecked", "checkstyle:methodTypeParameterName"}) public E$$ «AUGMENTABLE_AUGMENTATION_NAME»(«CLASS.importedName» augmentationType) { return (E$$) «AUGMENTATION_FIELD».get(«JU_OBJECTS.importedName».requireNonNull(augmentationType));