*/
package org.opendaylight.mdsal.binding.java.api.generator
+import static org.opendaylight.mdsal.binding.model.util.Types.STRING;
import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTATION_FIELD
-import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.AUGMENTABLE_AUGMENTATION_NAME
+import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.BINDING_EQUALS_NAME
+import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.BINDING_HASHCODE_NAME
+import static org.opendaylight.mdsal.binding.spec.naming.BindingMapping.BINDING_TO_STRING_NAME
-import com.google.common.collect.ImmutableMap
-import java.util.Arrays
+import java.util.Collection
import java.util.List
-import java.util.Map
-import java.util.Objects
+import java.util.Optional
+import org.opendaylight.mdsal.binding.model.api.AnnotationType
import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
import org.opendaylight.mdsal.binding.model.api.GeneratedType
+import org.opendaylight.mdsal.binding.model.api.MethodSignature
+import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics
import org.opendaylight.mdsal.binding.model.api.Type
+import org.opendaylight.mdsal.binding.model.util.Types
import org.opendaylight.mdsal.binding.spec.naming.BindingMapping
-import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.AbstractAugmentable
class BuilderImplTemplate extends AbstractBuilderTemplate {
- val Type builderType;
+ val BuilderTemplate builder;
new(BuilderTemplate builder, GeneratedType type) {
super(builder.javaType.getEnclosedType(type.identifier), type, builder.targetType, builder.properties,
builder.augmentType, builder.keyType)
- this.builderType = builder.type
+ this.builder = builder
}
override body() '''
- private static final class «type.name» implements «targetType.importedName» {
+ «targetType.annotations.generateDeprecatedAnnotation»
+ private static final class «type.name»
+ «val impIface = targetType.importedName»
+ «IF augmentType !== null»
+ extends «AbstractAugmentable.importedName»<«impIface»>
+ «ENDIF»
+ implements «impIface» {
«generateFields(true)»
- «generateAugmentField(true)»
+ «generateCopyConstructor(builder.type, type)»
- «generateCopyConstructor(builderType, type)»
-
- @«Override.importedName»
- public «Class.importedName»<«targetType.importedName»> getImplementedInterface() {
- return «targetType.importedName».class;
- }
-
- «generateGetters(true)»
+ «generateGetters()»
«generateHashCode()»
«generateEquals()»
- «generateToString(properties)»
+ «generateToString()»
+ }
+ '''
+
+ override generateDeprecatedAnnotation(AnnotationType ann) {
+ return generateAnnotation(ann)
+ }
+
+ def private generateGetters() '''
+ «IF keyType !== null»
+ @«OVERRIDE.importedName»
+ public «keyType.importedName» «BindingMapping.IDENTIFIABLE_KEY_NAME»() {
+ return key;
+ }
+
+ «ENDIF»
+ «IF !properties.empty»
+ «FOR field : properties SEPARATOR '\n'»
+ «field.getterMethod»
+ «ENDFOR»
+ «ENDIF»
+ '''
+
+ private static def Optional<MethodSignature> findGetter(GeneratedType implType, String getterName) {
+ val getter = getterByName(implType.nonDefaultMethods, getterName);
+ if (getter.isPresent) {
+ return getter;
+ }
+ for (ifc : implType.implements) {
+ if (ifc instanceof GeneratedType) {
+ val getterImpl = findGetter(ifc, getterName)
+ if (getterImpl.isPresent) {
+ return (getterImpl)
+ }
+ }
+ }
+ return Optional.empty
+ }
+
+ override getterMethod(GeneratedProperty field) '''
+ @«OVERRIDE.importedName»
+ public «field.returnType.importedName» «field.getterMethodName»() {
+ «val fieldName = field.fieldName»
+ «IF field.returnType.name.endsWith("[]")»
+ return «fieldName» == null ? null : «fieldName».clone();
+ «ELSE»
+ return «fieldName»;
+ «ENDIF»
}
'''
+ package def findGetter(String getterName) {
+ val ownGetter = getterByName(type.nonDefaultMethods, getterName);
+ if (ownGetter.isPresent) {
+ return ownGetter.get;
+ }
+ for (ifc : type.implements) {
+ if (ifc instanceof GeneratedType) {
+ val getter = findGetter(ifc, getterName)
+ if (getter.isPresent) {
+ return (getter.get)
+ }
+ }
+ }
+ throw new IllegalStateException(
+ String.format("%s should be present in %s type or in one of its ancestors as getter",
+ getterName.propertyNameFromGetter, type));
+ }
+
/**
* Template method which generates the method <code>hashCode()</code>.
*
private int hash = 0;
private volatile boolean hashValid = false;
- @«Override.importedName»
+ @«OVERRIDE.importedName»
public int hashCode() {
if (hashValid) {
return hash;
}
- final int prime = 31;
- int result = 1;
- «FOR property : properties»
- «IF property.returnType.name.contains("[")»
- result = prime * result + «Arrays.importedName».hashCode(«property.fieldName»);
- «ELSE»
- result = prime * result + «Objects.importedName».hashCode(«property.fieldName»);
- «ENDIF»
- «ENDFOR»
- «IF augmentType !== null»
- result = prime * result + «Objects.importedName».hashCode(«AUGMENTATION_FIELD»);
- «ENDIF»
-
+ final int result = «targetType.importedName».«BINDING_HASHCODE_NAME»(this);
hash = result;
hashValid = true;
return result;
*/
def protected generateEquals() '''
«IF !properties.empty || augmentType !== null»
- @«Override.importedName»
- public boolean equals(«Object.importedName» obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof «DataObject.importedName»)) {
- return false;
- }
- if (!«targetType.importedName».class.equals(((«DataObject.importedName»)obj).getImplementedInterface())) {
- return false;
- }
- «targetType.importedName» other = («targetType.importedName»)obj;
- «FOR property : properties»
- «val fieldName = property.fieldName»
- «IF property.returnType.name.contains("[")»
- if (!«Arrays.importedName».equals(«fieldName», other.«property.getterMethodName»())) {
- «ELSE»
- if (!«Objects.importedName».equals(«fieldName», other.«property.getterMethodName»())) {
- «ENDIF»
- return false;
- }
- «ENDFOR»
- «IF augmentType !== null»
- if (getClass() == obj.getClass()) {
- // Simple case: we are comparing against self
- «type.name» otherImpl = («type.name») obj;
- if (!«Objects.importedName».equals(«AUGMENTATION_FIELD», otherImpl.«AUGMENTATION_FIELD»)) {
- return false;
- }
- } else {
- // Hard case: compare our augments with presence there...
- for («Map.importedName».Entry<«Class.importedName»<? extends «augmentType.importedName»>, «augmentType.importedName»> e : «AUGMENTATION_FIELD».entrySet()) {
- if (!e.getValue().equals(other.«AUGMENTABLE_AUGMENTATION_NAME»(e.getKey()))) {
- return false;
- }
- }
- // .. and give the other one the chance to do the same
- if (!obj.equals(this)) {
- return false;
- }
- }
- «ENDIF»
- return true;
+ @«OVERRIDE.importedName»
+ public boolean equals(«Types.objectType().importedName» obj) {
+ return «targetType.importedName».«BINDING_EQUALS_NAME»(this, obj);
}
«ENDIF»
'''
+ /**
+ * Template method which generates the method <code>toString()</code>.
+ *
+ * @return string with the <code>toString()</code> method definition in JAVA format
+ */
+ def protected generateToString() '''
+ @«OVERRIDE.importedName»
+ public «STRING.importedName» toString() {
+ return «targetType.importedName».«BINDING_TO_STRING_NAME»(this);
+ }
+ '''
+
override protected generateCopyKeys(List<GeneratedProperty> keyProps) '''
if (base.«BindingMapping.IDENTIFIABLE_KEY_NAME»() != null) {
this.key = base.«BindingMapping.IDENTIFIABLE_KEY_NAME»();
«ENDFOR»
'''
+ override protected CharSequence generateCopyNonKeys(Collection<BuilderGeneratedProperty> props) '''
+ «FOR field : props»
+ «IF field.mechanics === ValueMechanics.NULLIFY_EMPTY»
+ this.«field.fieldName» = «CODEHELPERS.importedName».emptyToNull(base.«field.getterName»());
+ «ELSE»
+ this.«field.fieldName» = base.«field.getterName»();
+ «ENDIF»
+ «ENDFOR»
+ '''
+
override protected generateCopyAugmentation(Type implType) '''
- this.«AUGMENTATION_FIELD» = «ImmutableMap.importedName».copyOf(base.«AUGMENTATION_FIELD»);
+ super(base.«AUGMENTATION_FIELD»);
'''
}
\ No newline at end of file