@* * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html *@ @import java.util.List @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.fieldName @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.formatDataForJavaDocBuilder @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.getSimpleNameForBuilder @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.getterMethodName @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.getRestrictions @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.propertyNameFromGetter @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.toFirstUpper @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.wrapToDocumentation @import org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers.BuilderRenderer.getAllIfcs @import org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers.BuilderRenderer.hasImplementsFromUses @import org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers.BuilderRenderer.toListOfNames @import org.opendaylight.mdsal.binding.javav2.java.api.generator.rangeGenerators.AbstractRangeGenerator @import org.opendaylight.mdsal.binding.javav2.java.api.generator.rangeGenerators.LengthGenerator @import org.opendaylight.mdsal.binding.javav2.model.api.ConcreteType @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty @import org.opendaylight.mdsal.binding.javav2.model.api.Type @import org.opendaylight.yangtools.concepts.Builder @(genType: GeneratedType, properties: Set[GeneratedProperty], importedNames: Map[String, String], ImportedNamesWithProperties: Map[GeneratedProperty, String], augmentField: GeneratedProperty, copyConstructorHelper: String, getterMethods: List[String]) @if(genType != null) { @{wrapToDocumentation(formatDataForJavaDocBuilder(importedNames.get("genType")))} public class @{genType.getName}Builder implements @{getSimpleNameForBuilder} <@{importedNames.get("genType")}> { @generateFields(false) @generateAugmentField(false) @generateConstructorsFromIfcs() @generateCopyConstructor(false) @generateMethodFieldsFrom() @generateGetters(false) @generateSetters() public @{genType.getName} build() { return new @{genType.getName}Impl(this); } private static final class @{genType.getName}Impl implements @{genType.getName} { @implementedInterfaceGetter() @generateFields(true) @generateAugmentField(true) @generateCopyConstructor(true) @generateGetters(true) @generateHashCode() @generateEquals() @generateToString() } } } @** * Template method which generates class attributes. * * @param isFinal value which specify whether field is|isn't final * @param genType is genType * @return string with class attributes and their types *@ @generateFields(isFinal: Boolean) = { @if(ImportedNamesWithProperties != null) { @for((key, value) <- ImportedNamesWithProperties) { private @if(isFinal) { final} @{value} @{fieldName(key)}; } } } @** * Template method which generates class attributes. * * @param boolean value which specify whether field is|isn't final * @return string with class attributes and their types *@ @generateAugmentField(isPrivate: Boolean) = { @if(augmentField != null) { @if(isPrivate) {private } @{importedNames.get("map")}<@{importedNames.get("class")}, @{importedNames.get("augmentFieldReturnType")}> @{augmentField.getName} = @{importedNames.get("collections")}.emptyMap(); } } @implementedInterfaceGetter() = { public @{importedNames.get("class")}<@{importedNames.get("genType")}> getImplementedInterface() { return @{importedNames.get("genType")}.class; } } @** * Generate default constructor and constructor for every implemented interface from uses statements. *@ @generateConstructorsFromIfcs() = { public @{genType.getName}Builder() { } @if(genType.isInstanceOf[GeneratedType] && !genType.isInstanceOf[GeneratedTransferObject]) { @for(impl <- genType.asInstanceOf[GeneratedType].getImplements) { @generateConstructorFromIfc(impl) } } } @generateMethodFieldsFrom() = { @if(genType.isInstanceOf[GeneratedType] && !genType.isInstanceOf[GeneratedTransferObject]) { @if(hasImplementsFromUses(genType.asInstanceOf[GeneratedType])) { /** *Set fields from given grouping argument. Valid argument is instance of one of following types: * * * @@param arg grouping object * @@throws IllegalArgumentException if given argument is none of valid types */ public void fieldsFrom(@{importedNames.get("treeNode")} arg) { boolean isValidArg = false; @for(impl <- getAllIfcs(genType.asInstanceOf[GeneratedType])) { @if(impl.isInstanceOf[GeneratedType] && !impl.asInstanceOf[GeneratedType].getMethodDefinitions.isEmpty) { if (arg instanceof @{impl.asInstanceOf[GeneratedType].getFullyQualifiedName}) { @if(!impl.isInstanceOf[GeneratedTransferObject]) { @for(getter <- genType.asInstanceOf[GeneratedType].getMethodDefinitions) { this._@{propertyNameFromGetter(getter)} = ((@{impl.asInstanceOf[GeneratedType].getFullyQualifiedName})arg).@{getter.getName}(); } } isValidArg = true; } } } if (!isValidArg) { throw new IllegalArgumentException( "expected one of: @{toListOfNames(getAllIfcs(genType.asInstanceOf[GeneratedType]))} \n" + "but was: " + arg ); } } } } } @** * Generate constructor with argument of given type. *@ @generateConstructorFromIfc(impl: Type) = { @if(impl.isInstanceOf[GeneratedType]) { @if(!impl.asInstanceOf[GeneratedType].getMethodDefinitions.isEmpty) { public @{genType.getName}Builder( @{impl.getFullyQualifiedName} arg) { @{printConstructorPropertySetter(impl)} } } @for(implTypeImplement <- impl.asInstanceOf[GeneratedType].getImplements) { @generateConstructorFromIfc(implTypeImplement) } } } @printConstructorPropertySetter(implementedIfc: Type) = { @if(implementedIfc.isInstanceOf[GeneratedType] && !implementedIfc.isInstanceOf[GeneratedTransferObject]) { @for(getter <- implementedIfc.asInstanceOf[GeneratedType].getMethodDefinitions) { this._@{propertyNameFromGetter(getter)} = arg.@{getter.getName}(); } @for(impl <- implementedIfc.asInstanceOf[GeneratedType].getImplements) { @{printConstructorPropertySetter(impl)} } } } @generateCopyConstructor(impl: Boolean) = { @if(impl) {private} else {public} @{genType.getName} @if(impl) {Impl} else {Builder} (@{genType.getName} @if(impl) {Builder} base) { @{copyConstructorHelper} @if(augmentField != null) { @if(impl) { switch (base.@{augmentField.getName}.size()) { case 0: this.@{augmentField.getName} = @{importedNames.get("collections")}.emptyMap(); break; case 1: final @{importedNames.get("map")}.Entry<@{importedNames.get("class")}, @{importedNames.get("augmentFieldReturnType")}> e = base.@{augmentField.getName}.entrySet().iterator().next(); this.@{augmentField.getName} = @{importedNames.get("collections")}.<@{importedNames.get("class")}, @{importedNames.get("augmentFieldReturnType")}> singletonMap(e.getKey(), e.getValue()); break; default : this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>(base.@{augmentField.getName}); } } else { if (base instanceof @{genType.getName}Impl) { @{genType.getName}Impl impl = (@{genType.getName}Impl) base; if (!impl.@{augmentField.getName}.isEmpty()) { this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>(impl.@{augmentField.getName}); } } @{"else"} if (base instanceof @{importedNames.get("augmentationHolder")}) { @@SuppressWarnings("unchecked") @{importedNames.get("augmentationHolder")}<@{importedNames.get("genType")}> casted =(@{importedNames.get("augmentationHolder")}<@{importedNames.get("genType")}>) base; if (!casted.augmentations().isEmpty()) { this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>(casted.augmentations()); } } } } } } @generateSetters() = { @for(field <- properties) { @if(!field.getReturnType.isInstanceOf[GeneratedType] && getRestrictions(field.getReturnType) != null) { @if(getRestrictions(field.getReturnType).getRangeConstraints != null && !getRestrictions(field.getReturnType).getRangeConstraints.isEmpty) { @{AbstractRangeGenerator.forType(field.getReturnType).generateRangeChecker(toFirstUpper(field.getName), getRestrictions(field.getReturnType).getRangeConstraints)} } @if(getRestrictions(field.getReturnType).getLengthConstraints != null && !getRestrictions(field.getReturnType).getLengthConstraints.isEmpty) { @{LengthGenerator.generateLengthChecker(fieldName(field), field.getReturnType, getRestrictions(field.getReturnType).getLengthConstraints)} } } public @{genType.getName}Builder set@{toFirstUpper(field.getName)}(final @{importedNames.get("augmentFieldReturnType")} value) { @if(!field.getReturnType.isInstanceOf[GeneratedType] && getRestrictions(field.getReturnType) != null) { if (value != null) { @if(getRestrictions(field.getReturnType).getRangeConstraints != null && !getRestrictions(field.getReturnType).getRangeConstraints.isEmpty) { @if(field.getReturnType.isInstanceOf[ConcreteType]) { @{AbstractRangeGenerator.forType(field.getReturnType).generateRangeCheckerCall(toFirstUpper(field.getName), "value")} } else { @{AbstractRangeGenerator.forType(field.getReturnType).generateRangeCheckerCall(toFirstUpper(field.getName), "value.getValue()")} } } @if(getRestrictions(field.getReturnType).getLengthConstraints != null && !getRestrictions(field.getReturnType).getLengthConstraints.isEmpty) { @if(field.getReturnType.isInstanceOf[ConcreteType]) { @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value")} } else { @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value.getValue()")} } } } } this.@{fieldName(field)} = value; return this; } } @if(augmentField != null) { public @{genType.getName}Builder add@{toFirstUpper(augmentField.getName)}(@{importedNames.get("class")} augmentationType, @{importedNames.get("augmentFieldReturnType")} augmentation) { if (augmentation == null) { return remove@{toFirstUpper(augmentField.getName)}(augmentationType); } if (!(this.@{augmentField.getName} instanceof @{importedNames.get("hashMap")})) { this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>(); } this.@{augmentField.getName}.put(augmentationType, augmentation); return this; } public @{genType.getName}Builder remove@{toFirstUpper(augmentField.getName)} (@{importedNames.get("class")} augmentationType) { if (this.@{augmentField.getName} instanceof @{importedNames.get("hashMap")}) { this.@{augmentField.getName}.remove(augmentationType); } return this; } } } @generateGetters(addOverride: Boolean) = { @if(!getterMethods.isEmpty) { @for(property <- getterMethods) { @if(addOverride) {@@Override} @{property} } } @if(augmentField != null) { @@SuppressWarnings("unchecked") @if(addOverride) {@@Override} public E get@{toFirstUpper(augmentField.getName)} (@{importedNames.get("class")} augmentationType) { if (augmentationType == null) { throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!"); } return (E) @{augmentField.getName}.get(augmentationType); } } } @generateHashCode() = { @if(!properties.isEmpty || augmentField != null) { private int hash = 0; private volatile boolean hashValid = false; @@Override public int hashCode() { if (hashValid) { return hash; } final int prime = 31; int result = 1; @for(property <- properties) { @if(property.getReturnType.getName.contains("[")) { result = prime * result + @{importedNames.get("arrays")}.hashCode(@{fieldName(property)}); } else { result = prime * result + @{importedNames.get("objects")}.hashCode(@{fieldName(property)}); } } @if(augmentField != null) { result = prime * result + @{importedNames.get("objects")}.hashCode(@{augmentField.getName}); } hash = result; hashValid = true; return result; } } } @generateToString() = { @if(properties != null) { @@Override public @{importedNames.get("string")} toString() { @{importedNames.get("string")} name = "@{genType.getName} ["; @{importedNames.get("stringBuilder")} builder = new @{importedNames.get("stringBuilder")}(name); @for((property, index) <- properties.zipWithIndex) { if (@{fieldName(property)} != null) { builder.append("@{fieldName(property)}="); @if(property.getReturnType.getName.contains("[")) { builder.append(@{importedNames.get("arrays")}.toString(@{fieldName(property)})); } else { builder.append(@{fieldName(property)}); } @if(properties.size() > 1 && index < properties.size()-1){ builder.append(", "); } } } @if(augmentField != null) { @if(!properties.isEmpty()){ final int builderLength = builder.length(); final int builderAdditionalLength = builder.substring(name.length(), builderLength).length(); if (builderAdditionalLength > 2 && !builder.substring(builderLength - 2, builderLength).equals(", ")) { builder.append(", "); } } builder.append("@{augmentField.getName}="); builder.append(@{augmentField.getName}.values()); return builder.append(']').toString(); } else { @if(properties.isEmpty()){ return builder.append(']').toString(); } else { return builder.append(']').toString(); } } } } } @generateEquals() = { @if(!properties.isEmpty || augmentField != null) { @@Override public boolean equals(@{importedNames.get("object")} obj) { if (this == obj) { return true; } if (!(obj instanceof @{importedNames.get("treeNode")})) { return false; } if (!@{importedNames.get("genType")}.class.equals(((@{importedNames.get("treeNode")})obj).getImplementedInterface)) { return false; } @{importedNames.get("genType")} other = (@{importedNames.get("genType")})obj; @for(property <- properties) { @if(property.getReturnType.getName.contains("[")) { if (!@{importedNames.get("arrays")}.equals(@{fieldName(property)}, other.@{getterMethodName(property)}())) } else { if (!@{importedNames.get("objects")}.equals(@{fieldName(property)}, other.@{getterMethodName(property)}())) } { return false; } } @if(augmentField != null) { if (getClass() == obj.getClass()) { // Simple case: we are comparing against self @{genType.getName}Impl otherImpl = (@{genType.getName}Impl) obj; if (!@{importedNames.get("objects")}.equals(@{augmentField.getName}, otherImpl.@{augmentField.getName})) { return false; } } @{"else"} { // Hard case: compare our augments with presence there... for (@{importedNames.get("map")}.Entry<@{importedNames.get("class")}, @{importedNames.get("augmentFieldReturnType")}> e : @{augmentField.getName}.entrySet()) { if (!e.getValue().equals(other.getAugmentation(e.getKey()))) { return false; } } // .. and give the other one the chance to do the same if (!obj.equals(this)) { return false; } } } return true; } } }