2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
10 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.fieldName
11 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.formatDataForJavaDocBuilder
12 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.getSimpleNameForBuilder
13 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.getterMethodName
14 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.getRestrictions
15 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.propertyNameFromGetter
16 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.toFirstUpper
17 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil.wrapToDocumentation
18 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers.BuilderRenderer.getAllIfcs
19 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers.BuilderRenderer.hasImplementsFromUses
20 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers.BuilderRenderer.toListOfNames
21 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.rangeGenerators.AbstractRangeGenerator
22 @import org.opendaylight.mdsal.binding.javav2.java.api.generator.rangeGenerators.LengthGenerator
23 @import org.opendaylight.mdsal.binding.javav2.model.api.ConcreteType
24 @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType
25 @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject
26 @import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty
27 @import org.opendaylight.mdsal.binding.javav2.model.api.Type
28 @import org.opendaylight.yangtools.concepts.Builder
30 @(genType: GeneratedType, properties: Set[GeneratedProperty], importedNames: Map[String, String],
31 ImportedNamesWithProperties: Map[GeneratedProperty, String], augmentField: GeneratedProperty, copyConstructorHelper: String,
32 getterMethods: List[String])
33 @if(genType != null) {
34 @{wrapToDocumentation(formatDataForJavaDocBuilder(importedNames.get("genType")))}
35 public class @{genType.getName}Builder implements @{getSimpleNameForBuilder} <@{importedNames.get("genType")}> {
37 @generateFields(false)
39 @generateAugmentField(false)
41 @generateConstructorsFromIfcs()
43 @generateCopyConstructor(false)
45 @generateMethodFieldsFrom()
47 @generateGetters(false)
51 public @{genType.getName} build() {
52 return new @{genType.getName}Impl(this);
55 private static final class @{genType.getName}Impl implements @{genType.getName} {
57 @implementedInterfaceGetter()
61 @generateAugmentField(true)
63 @generateCopyConstructor(true)
65 @generateGetters(true)
77 * Template method which generates class attributes.
79 * @param isFinal value which specify whether field is|isn't final
80 * @param genType is genType
81 * @return string with class attributes and their types
83 @generateFields(isFinal: Boolean) = {
84 @if(ImportedNamesWithProperties != null) {
85 @for((key, value) <- ImportedNamesWithProperties) {
86 private @if(isFinal) { final}
87 @{value} @{fieldName(key)};
93 * Template method which generates class attributes.
95 * @param boolean value which specify whether field is|isn't final
96 * @return string with class attributes and their types
98 @generateAugmentField(isPrivate: Boolean) = {
99 @if(augmentField != null) {
100 @if(isPrivate) {private }
101 @{importedNames.get("map")}<@{importedNames.get("class")}<? extends @{importedNames.get("augmentFieldReturnType")}>,
102 @{importedNames.get("augmentFieldReturnType")}> @{augmentField.getName} = @{importedNames.get("collections")}.emptyMap();
106 @implementedInterfaceGetter() = {
107 public @{importedNames.get("class")}<@{importedNames.get("genType")}> getImplementedInterface() {
108 return @{importedNames.get("genType")}.class;
113 * Generate default constructor and constructor for every implemented interface from uses statements.
115 @generateConstructorsFromIfcs() = {
116 public @{genType.getName}Builder() {
118 @if(genType.isInstanceOf[GeneratedType] && !genType.isInstanceOf[GeneratedTransferObject]) {
119 @for(impl <- genType.asInstanceOf[GeneratedType].getImplements) {
120 @generateConstructorFromIfc(impl)
125 @generateMethodFieldsFrom() = {
126 @if(genType.isInstanceOf[GeneratedType] && !genType.isInstanceOf[GeneratedTransferObject]) {
127 @if(hasImplementsFromUses(genType.asInstanceOf[GeneratedType])) {
129 *Set fields from given grouping argument. Valid argument is instance of one of following types:
131 @for(impl <- getAllIfcs(genType.asInstanceOf[GeneratedType])) {
132 * <li>@{impl.getFullyQualifiedName}</li>
136 * @@param arg grouping object
137 * @@throws IllegalArgumentException if given argument is none of valid types
140 public void fieldsFrom(@{importedNames.get("treeNode")} arg) {
141 boolean isValidArg = false;
142 @for(impl <- getAllIfcs(genType.asInstanceOf[GeneratedType])) {
143 @if(impl.isInstanceOf[GeneratedType] && !impl.asInstanceOf[GeneratedType].getMethodDefinitions.isEmpty) {
144 if (arg instanceof @{impl.asInstanceOf[GeneratedType].getFullyQualifiedName}) {
145 @if(!impl.isInstanceOf[GeneratedTransferObject]) {
146 @for(getter <- genType.asInstanceOf[GeneratedType].getMethodDefinitions) {
147 this._@{propertyNameFromGetter(getter)} = ((@{impl.asInstanceOf[GeneratedType].getFullyQualifiedName})arg).@{getter.getName}();
155 throw new IllegalArgumentException(
156 "expected one of: @{toListOfNames(getAllIfcs(genType.asInstanceOf[GeneratedType]))} \n" +
166 * Generate constructor with argument of given type.
168 @generateConstructorFromIfc(impl: Type) = {
169 @if(impl.isInstanceOf[GeneratedType]) {
170 @if(!impl.asInstanceOf[GeneratedType].getMethodDefinitions.isEmpty) {
171 public @{genType.getName}Builder(
172 @{impl.getFullyQualifiedName} arg) {
173 @{printConstructorPropertySetter(impl)}
176 @for(implTypeImplement <- impl.asInstanceOf[GeneratedType].getImplements) {
177 @generateConstructorFromIfc(implTypeImplement)
182 @printConstructorPropertySetter(implementedIfc: Type) = {
183 @if(implementedIfc.isInstanceOf[GeneratedType] && !implementedIfc.isInstanceOf[GeneratedTransferObject]) {
184 @for(getter <- implementedIfc.asInstanceOf[GeneratedType].getMethodDefinitions) {
185 this._@{propertyNameFromGetter(getter)} = arg.@{getter.getName}();
187 @for(impl <- implementedIfc.asInstanceOf[GeneratedType].getImplements) {
188 @{printConstructorPropertySetter(impl)}
193 @generateCopyConstructor(impl: Boolean) = {
194 @if(impl) {private} else {public}
196 @if(impl) {Impl} else {Builder}
198 @if(impl) {Builder} base) {
199 @{copyConstructorHelper}
200 @if(augmentField != null) {
202 switch (base.@{augmentField.getName}.size()) {
204 this.@{augmentField.getName} = @{importedNames.get("collections")}.emptyMap();
207 final @{importedNames.get("map")}.Entry<@{importedNames.get("class")}<? extends @{importedNames.get("augmentFieldReturnType")}>, @{importedNames.get("augmentFieldReturnType")}> e = base.@{augmentField.getName}.entrySet().iterator().next();
208 this.@{augmentField.getName} = @{importedNames.get("collections")}.<@{importedNames.get("class")}<? extends @{importedNames.get("augmentFieldReturnType")}>, @{importedNames.get("augmentFieldReturnType")}> singletonMap(e.getKey(), e.getValue());
211 this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>(base.@{augmentField.getName});
214 if (base instanceof @{genType.getName}Impl) {
215 @{genType.getName}Impl impl = (@{genType.getName}Impl) base;
216 if (!impl.@{augmentField.getName}.isEmpty()) {
217 this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>(impl.@{augmentField.getName});
219 } @{"else"} if (base instanceof @{importedNames.get("augmentationHolder")}) {
220 @@SuppressWarnings("unchecked")
221 @{importedNames.get("augmentationHolder")}<@{importedNames.get("genType")}> casted =(@{importedNames.get("augmentationHolder")}<@{importedNames.get("genType")}>) base;
222 if (!casted.augmentations().isEmpty()) {
223 this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>(casted.augmentations());
232 @generateSetters() = {
233 @for(field <- properties) {
234 @if(!field.getReturnType.isInstanceOf[GeneratedType] && getRestrictions(field.getReturnType) != null) {
235 @if(getRestrictions(field.getReturnType).getRangeConstraints != null && !getRestrictions(field.getReturnType).getRangeConstraints.isEmpty) {
236 @{AbstractRangeGenerator.forType(field.getReturnType).generateRangeChecker(toFirstUpper(field.getName),
237 getRestrictions(field.getReturnType).getRangeConstraints)}
239 @if(getRestrictions(field.getReturnType).getLengthConstraints != null && !getRestrictions(field.getReturnType).getLengthConstraints.isEmpty) {
240 @{LengthGenerator.generateLengthChecker(fieldName(field), field.getReturnType,
241 getRestrictions(field.getReturnType).getLengthConstraints)}
244 public @{genType.getName}Builder set@{toFirstUpper(field.getName)}(final @{importedNames.get("augmentFieldReturnType")} value) {
245 @if(!field.getReturnType.isInstanceOf[GeneratedType] && getRestrictions(field.getReturnType) != null) {
247 @if(getRestrictions(field.getReturnType).getRangeConstraints != null && !getRestrictions(field.getReturnType).getRangeConstraints.isEmpty) {
248 @if(field.getReturnType.isInstanceOf[ConcreteType]) {
249 @{AbstractRangeGenerator.forType(field.getReturnType).generateRangeCheckerCall(toFirstUpper(field.getName), "value")}
251 @{AbstractRangeGenerator.forType(field.getReturnType).generateRangeCheckerCall(toFirstUpper(field.getName), "value.getValue()")}
254 @if(getRestrictions(field.getReturnType).getLengthConstraints != null && !getRestrictions(field.getReturnType).getLengthConstraints.isEmpty) {
255 @if(field.getReturnType.isInstanceOf[ConcreteType]) {
256 @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value")}
258 @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value.getValue()")}
263 this.@{fieldName(field)} = value;
267 @if(augmentField != null) {
268 public @{genType.getName}Builder add@{toFirstUpper(augmentField.getName)}(@{importedNames.get("class")}<? extends @{importedNames.get("augmentFieldReturnType")}> augmentationType, @{importedNames.get("augmentFieldReturnType")} augmentation) {
269 if (augmentation == null) {
270 return remove@{toFirstUpper(augmentField.getName)}(augmentationType);
273 if (!(this.@{augmentField.getName} instanceof @{importedNames.get("hashMap")})) {
274 this.@{augmentField.getName} = new @{importedNames.get("hashMap")}<>();
277 this.@{augmentField.getName}.put(augmentationType, augmentation);
281 public @{genType.getName}Builder remove@{toFirstUpper(augmentField.getName)}
282 (@{importedNames.get("class")}<? extends @{importedNames.get("augmentFieldReturnType")}> augmentationType) {
283 if (this.@{augmentField.getName} instanceof @{importedNames.get("hashMap")}) {
284 this.@{augmentField.getName}.remove(augmentationType);
291 @generateGetters(addOverride: Boolean) = {
292 @if(!getterMethods.isEmpty) {
293 @for(property <- getterMethods) {
294 @if(addOverride) {@@Override}
298 @if(augmentField != null) {
299 @@SuppressWarnings("unchecked")
300 @if(addOverride) {@@Override}
301 public <E extends @{importedNames.get("augmentFieldReturnType")}> E get@{toFirstUpper(augmentField.getName)}
302 (@{importedNames.get("class")}<E> augmentationType) {
303 if (augmentationType == null) {
304 throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!");
306 return (E) @{augmentField.getName}.get(augmentationType);
311 @generateHashCode() = {
312 @if(!properties.isEmpty || augmentField != null) {
313 private int hash = 0;
314 private volatile boolean hashValid = false;
317 public int hashCode() {
322 final int prime = 31;
324 @for(property <- properties) {
325 @if(property.getReturnType.getName.contains("[")) {
326 result = prime * result + @{importedNames.get("arrays")}.hashCode(@{fieldName(property)});
328 result = prime * result + @{importedNames.get("objects")}.hashCode(@{fieldName(property)});
331 @if(augmentField != null) {
332 result = prime * result + @{importedNames.get("objects")}.hashCode(@{augmentField.getName});
342 @generateToString() = {
343 @if(properties != null) {
345 public @{importedNames.get("string")} toString() {
346 @{importedNames.get("stringBuilder")} builder = new @{importedNames.get("stringBuilder")} ("@{genType.getName} [");
347 boolean first = true;
348 @for(property <- properties) {
349 if (@{fieldName(property)} != null) {
353 builder.append(", ");
355 builder.append("@{fieldName(property)}=");
356 @if(property.getReturnType.getName.contains("[")) {
357 builder.append(@{importedNames.get("arrays")}.toString(@{fieldName(property)}));
359 builder.append(@{fieldName(property)});
363 @if(augmentField != null) {
367 builder.append(", ");
369 builder.append("@{augmentField.getName}=");
370 builder.append(@{augmentField.getName}.values());
372 return builder.append(']').toString();
377 @generateEquals() = {
378 @if(!properties.isEmpty || augmentField != null) {
380 public boolean equals(@{importedNames.get("object")} obj) {
384 if (!(obj instanceof @{importedNames.get("treeNode")})) {
387 if (!@{importedNames.get("genType")}.class.equals(((@{importedNames.get("treeNode")})obj).getImplementedInterface)) {
390 @{importedNames.get("genType")} other = (@{importedNames.get("genType")})obj;
391 @for(property <- properties) {
392 @if(property.getReturnType.getName.contains("[")) {
393 if (!@{importedNames.get("arrays")}.equals(@{fieldName(property)}, other.@{getterMethodName(property)}()))
395 if (!@{importedNames.get("objects")}.equals(@{fieldName(property)}, other.@{getterMethodName(property)}()))
401 @if(augmentField != null) {
402 if (getClass() == obj.getClass()) {
403 // Simple case: we are comparing against self
404 @{genType.getName}Impl otherImpl = (@{genType.getName}Impl) obj;
405 if (!@{importedNames.get("objects")}.equals(@{augmentField.getName}, otherImpl.@{augmentField.getName})) {
409 // Hard case: compare our augments with presence there...
410 for (@{importedNames.get("map")}.Entry<@{importedNames.get("class")}<? extends @{importedNames.get("augmentFieldReturnType")}>, @{importedNames.get("augmentFieldReturnType")}> e : @{augmentField.getName}.entrySet()) {
411 if (!e.getValue().equals(other.getAugmentation(e.getKey()))) {
415 // .. and give the other one the chance to do the same
416 if (!obj.equals(this)) {