Bug 1411-5 #7: MDSAL Binding2 Java API Generator 97/46897/22
authorMartin Ciglan <mciglan@cisco.com>
Wed, 23 Nov 2016 10:46:36 +0000 (11:46 +0100)
committerRobert Varga <nite@hq.sk>
Tue, 10 Jan 2017 21:46:35 +0000 (21:46 +0000)
- class renderer, templates this is parent for more renderers
- minor do comment fix
- reworked method call
- bit of a cleanup, review comments implemented

Change-Id: I66cbf521b3be36e7278b6026fd02353a337c12b4
Signed-off-by: Filip Gregor <fgregor@cisco.com>
Signed-off-by: Martin Ciglan <mciglan@cisco.com>
binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding2/java/api/generator/renderers/ClassRenderer.java [new file with mode: 0644]
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplate.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateConstructors.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateInitBlock.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateRestrictions.scala.txt [new file with mode: 0644]
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateUnionConstr.scala.txt [new file with mode: 0644]

diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding2/java/api/generator/renderers/ClassRenderer.java b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding2/java/api/generator/renderers/ClassRenderer.java
new file mode 100644 (file)
index 0000000..c459c12
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * 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
+ */
+
+package org.opendaylight.mdsal.binding2.java.api.generator.renderers;
+
+import static org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.MEMBER_PATTERN_LIST;
+import static org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.PATTERN_CONSTANT_NAME;
+import static org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.fieldName;
+import static org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.setterMethod;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.io.BaseEncoding;
+import java.beans.ConstructorProperties;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Pattern;
+import org.opendaylight.mdsal.binding2.java.api.generator.rangeGenerators.AbstractRangeGenerator;
+import org.opendaylight.mdsal.binding2.java.api.generator.rangeGenerators.LengthGenerator;
+import org.opendaylight.mdsal.binding2.model.api.Constant;
+import org.opendaylight.mdsal.binding2.model.api.Enumeration;
+import org.opendaylight.mdsal.binding2.model.api.GeneratedProperty;
+import org.opendaylight.mdsal.binding2.model.api.GeneratedTransferObject;
+import org.opendaylight.mdsal.binding2.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding2.model.api.Restrictions;
+import org.opendaylight.mdsal.binding2.model.api.Type;
+import org.opendaylight.mdsal.binding2.txt.classTemplate;
+import org.opendaylight.mdsal.binding2.txt.classTemplateConstructors;
+import org.opendaylight.mdsal.binding2.txt.classTemplateInitBlock;
+import org.opendaylight.mdsal.binding2.txt.classTemplateRestrictions;
+import org.opendaylight.mdsal.binding2.txt.classTemplateUnionConstr;
+
+public class ClassRenderer extends BaseRenderer {
+    protected final GeneratedTransferObject genTO;
+    protected final Restrictions restrictions;
+    private final List<GeneratedProperty> properties;
+    private final List<GeneratedProperty> finalProperties;
+    private final List<GeneratedProperty> parentProperties;
+    private final List<Enumeration> enums;
+    private final List<Constant> consts;
+    private final List<GeneratedType> enclosedGeneratedTypes;
+    private final List<GeneratedProperty> allProperties;
+    private final Map<String, String> importedNames = new HashMap<>();
+    private final AbstractRangeGenerator<?> rangeGenerator;
+
+    public ClassRenderer(final GeneratedTransferObject genType) {
+        super(genType);
+        genTO = genType;
+        properties = ImmutableList.copyOf(genTO.getProperties());
+        finalProperties = ImmutableList.copyOf(resolveReadOnlyPropertiesFromTO(genTO.getProperties()));
+        parentProperties = ImmutableList.copyOf(getPropertiesOfAllParents(genTO));
+        enums = ImmutableList.copyOf(genTO.getEnumerations());
+        consts = ImmutableList.copyOf(genTO.getConstantDefinitions());
+        enclosedGeneratedTypes = ImmutableList.copyOf(genTO.getEnclosedTypes());
+        restrictions = genTO.getRestrictions();
+
+        final List<GeneratedProperty> sorted = new ArrayList<>();
+        sorted.addAll(properties);
+        sorted.addAll(parentProperties);
+        final Comparator<GeneratedProperty> function = (GeneratedProperty p1, GeneratedProperty p2) -> {
+            final String name = p1.getName();
+            final String name1 = p2.getName();
+            return name.compareTo(name1);
+        };
+        Collections.sort(sorted, function);
+        allProperties = ImmutableList.copyOf(sorted);
+
+        if (restrictions != null && !(restrictions.getRangeConstraints() != null && !restrictions.getLengthConstraints
+                ().isEmpty())) {
+            rangeGenerator = AbstractRangeGenerator.forType(findProperty(genType, "value").getReturnType());
+            Preconditions.checkNotNull(rangeGenerator);
+        } else {
+            rangeGenerator = null;
+        }
+    }
+
+    protected List<GeneratedProperty> getProperties() {
+        return properties;
+    }
+
+    protected List<GeneratedProperty> getFinalProperties() {
+        return finalProperties;
+    }
+
+    protected List<GeneratedProperty> getParentProperties() {
+        return parentProperties;
+    }
+
+    protected List<Enumeration> getEnums() {
+        return enums;
+    }
+
+    protected List<Constant> getConsts() {
+        return consts;
+    }
+
+    protected List<GeneratedType> getEnclosedGeneratedTypes() {
+        return enclosedGeneratedTypes;
+    }
+
+    protected Collection<GeneratedProperty> getAllProperties() {
+        return allProperties;
+    }
+
+    protected String generateAsInnerClass() {
+        return generateBody(true);
+    }
+
+    @Override
+    protected String body() {
+        return generateBody(false);
+    }
+
+    protected String generateBody(final boolean isInnerClass) {
+        importedNames.put("genTypeSuper", importedName(genTO.getSuperType()));
+        importedNames.put("type", importedName(getType()));
+        importedNames.put("arrays", importedName(Arrays.class));
+        importedNames.put("objects", importedName(Objects.class));
+        importedNames.put("string", importedName(String.class));
+        importedNames.put("byte", importedName(Byte.class));
+        importedNames.put("short", importedName(Short.class));
+        importedNames.put("integer", importedName(Integer.class));
+        importedNames.put("long", importedName(Long.class));
+        importedNames.put("stringBuilder", importedName(StringBuilder.class));
+        importedNames.put("list", importedName(List.class));
+        importedNames.put("lists", importedName(Lists.class));
+        importedNames.put("illegalArgumentException", importedName(IllegalArgumentException.class));
+        importedNames.put("boolean", importedName(Boolean.class));
+
+        final List<String> implementsListBuilder = new LinkedList<>();
+        if (!getType().getImplements().isEmpty()) {
+            for (Type impl : getType().getImplements()) {
+                implementsListBuilder.add((importedName(impl)));
+            }
+        }
+        final String implementsList = String.join(", ", implementsListBuilder);
+
+        final List<String> classTemplateBuilder = new LinkedList<>();
+        if (!enclosedGeneratedTypes.isEmpty()) {
+            for (GeneratedType innerClass : enclosedGeneratedTypes) {
+                if (innerClass instanceof GeneratedTransferObject) {
+                    classTemplateBuilder.add(new ClassRenderer((GeneratedTransferObject) innerClass).generateAsInnerClass());
+                }
+            }
+        }
+        final String innerClasses = String.join("\n", classTemplateBuilder);
+
+        final List<String> enumList = new LinkedList<>();
+        if (!enums.isEmpty()) {
+            for (Enumeration enumeration : enums) {
+                enumList.add(new EnumRenderer(enumeration).body());
+            }
+        }
+        final String enumerations = String.join("\n", enumList);
+
+        final StringBuilder sb1 = new StringBuilder();
+        final String initBlock = classTemplateInitBlock.render(importedName(Pattern.class)).body();
+        if (!consts.isEmpty()) {
+            for (Constant constant : consts) {
+                if (PATTERN_CONSTANT_NAME.equals(constant.getName())) {
+                    if (constant.getValue() instanceof List<?>) {
+                        sb1.append("private static final ")
+                            .append(importedName(Pattern.class))
+                            .append("[] ")
+                            .append(MEMBER_PATTERN_LIST)
+                            .append(";\npublic static final ")
+                            .append(importedName(List.class))
+                            .append("<String> ")
+                            .append(PATTERN_CONSTANT_NAME)
+                            .append(" = ")
+                            .append(importedName(ImmutableList.class))
+                            .append(".of(");
+                        final List<String> constantList = new LinkedList<>();
+                        for (Object item : (List) constant.getValue()) {
+                            if (item instanceof String) {
+                                constantList.add("\"" + item + "\"");
+                            }
+                        }
+                        sb1.append(String.join(", ", constantList));
+                        sb1.append(");")
+                                .append(initBlock);
+                    }
+                } else {
+                    sb1.append(emitConstant(constant));
+                }
+            }
+        }
+        final String constants = sb1.toString();
+
+        if (genTO.getSuperType() != null) {
+            importedNames.put("superType", importedName(genTO.getSuperType()));
+        }
+
+        for (GeneratedProperty property : properties) {
+            importedNames.put(property.getReturnType().toString(), importedName(property.getReturnType()));
+        }
+
+        final String constructors = generateConstructors();
+
+        final StringBuilder lengthRangeCheckerBuilder = new StringBuilder();
+        if (restrictions != null) {
+            if (restrictions.getLengthConstraints() != null && !restrictions.getLengthConstraints().isEmpty()) {
+                lengthRangeCheckerBuilder.append(LengthGenerator.generateLengthChecker("_value", findProperty(genTO,
+                        "value").getReturnType(), restrictions.getLengthConstraints()))
+                        .append("\n");
+            }
+            if (restrictions.getRangeConstraints() != null && !restrictions.getRangeConstraints().isEmpty()) {
+                lengthRangeCheckerBuilder.append(rangeGenerator.generateRangeChecker("_value", restrictions
+                        .getRangeConstraints()))
+                        .append("\n");
+            }
+        }
+        final String lengthRangeChecker = lengthRangeCheckerBuilder.toString();
+
+        final StringBuilder sb2 = new StringBuilder();
+        if (!properties.isEmpty()) {
+            for (GeneratedProperty property : properties) {
+                final String isFinal = property.isReadOnly() ? " final " : " ";
+                sb2.append("private")
+                        .append(isFinal)
+                        .append(importedName(property.getReturnType()))
+                        .append(' ')
+                        .append(fieldName(property))
+                        .append(';');
+            }
+        }
+        final String fields = sb2.toString();
+        importedNames.put("baseEncoding", importedName(BaseEncoding.class));
+        importedNames.put("defProp", importedName(((GeneratedProperty)((List) allProperties).get(0)).getReturnType()));
+
+        final StringBuilder sb3 = new StringBuilder();
+        for (GeneratedProperty property : properties) {
+            sb3.append(getterMethod(property));
+            if (!property.isReadOnly()) {
+                sb3.append(setterMethod(property, getType().getName(), importedName(property
+                        .getReturnType())));
+            }
+        }
+        final String propertyMethod = sb3.toString();
+
+        return classTemplate.render(getType(), genTO, importedNames, implementsList, innerClasses, enumerations,
+                constants, constructors, lengthRangeChecker, fields, (List) allProperties, propertyMethod,
+                isInnerClass).body();
+    }
+
+    protected String generateConstructors() {
+        importedNames.put("constructorProperties", importedName(ConstructorProperties.class));
+        importedNames.put("preconditions", importedName(Preconditions.class));
+
+        final StringBuilder sb1 = new StringBuilder();
+        for (GeneratedProperty allProperty : allProperties) {
+            sb1.append(classTemplateRestrictions.render(getType(), fieldName(allProperty), allProperty
+                    .getReturnType(), rangeGenerator).body());
+        }
+        final String genRestrictions = sb1.toString();
+
+        final StringBuilder sb2 = new StringBuilder();
+        if (genTO.isUnionType()) {
+            for (GeneratedProperty allProperty : allProperties) {
+                final List other = new ArrayList<>(properties);
+                if (other.remove(allProperty)) {
+                    sb2.append(classTemplateUnionConstr.render(getType(), parentProperties, allProperty,
+                        other, importedName(allProperty.getReturnType()), genRestrictions).body());
+                }
+            }
+        }
+        final String unionConstructor = sb2.toString();
+
+        final String argumentsDeclaration = asArgumentsDeclaration(allProperties);
+        return classTemplateConstructors.render(genTO, (List) allProperties, properties, parentProperties,
+                importedNames, argumentsDeclaration, unionConstructor, genRestrictions).body();
+    }
+
+    /**
+     * Selects from input list of properties only those which have read only
+     * attribute set to true.
+     *
+     * @param properties
+     *            list of properties of generated transfer object
+     * @return subset of <code>properties</code> which have read only attribute
+     *         set to true
+     */
+    private List<GeneratedProperty> resolveReadOnlyPropertiesFromTO(final List<GeneratedProperty> properties) {
+        return new ArrayList(Collections2.transform(properties, GeneratedProperty::isReadOnly));
+    }
+
+    /**
+     * Returns the list of the read only properties of all extending generated
+     * transfer object from <code>genTO</code> to highest parent generated
+     * transfer object
+     *
+     * @param genTO
+     *            generated transfer object for which is the list of read only
+     *            properties generated
+     * @return list of all read only properties from actual to highest parent
+     *         generated transfer object. In case when extension exists the
+     *         method is recursive called.
+     */
+    private List<GeneratedProperty> getPropertiesOfAllParents(final GeneratedTransferObject genTO) {
+        final List<GeneratedProperty> propertiesOfAllParents = new ArrayList<>();
+        if (genTO.getSuperType() != null) {
+            final List<GeneratedProperty> allPropertiesOfTO = genTO.getSuperType().getProperties();
+            List<GeneratedProperty> readOnlyPropertiesOfTO = resolveReadOnlyPropertiesFromTO(allPropertiesOfTO);
+            propertiesOfAllParents.addAll(readOnlyPropertiesOfTO);
+            propertiesOfAllParents.addAll(getPropertiesOfAllParents(genTO.getSuperType()));
+        }
+        return propertiesOfAllParents;
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplate.scala.txt b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplate.scala.txt
new file mode 100644 (file)
index 0000000..43d46ea
--- /dev/null
@@ -0,0 +1,193 @@
+@*
+ * 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 org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.formatDataForJavaDoc
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.fieldName
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.propsAsArgs
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.propsAsList
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.valueForBits
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.wrapToDocumentation
+@import org.opendaylight.mdsal.binding2.model.api.GeneratedTransferObject
+@import org.opendaylight.mdsal.binding2.model.api.GeneratedType
+@import org.opendaylight.mdsal.binding2.model.api.GeneratedProperty
+@import org.opendaylight.yangtools.yang.model.api.`type`.BitsTypeDefinition
+
+@(genType: GeneratedType, genTo: GeneratedTransferObject, importedNames: Map[String, String], implementsList: String,
+innerClasses: String, enumerations: String, constants: String, constructors: String, lengthRangeChecker: String,
+fields: String, allProperties: List[GeneratedProperty], propertyMethod: String, isInnerClass: Boolean)
+@if(genTo != null) {
+@{wrapToDocumentation(formatDataForJavaDoc(genType))}
+@annotationDeclaration()
+@generateClassDeclaration(isInnerClass)
+    {
+    @if(genTo.getSUID != null) {private static final long serialVersionUID = @{genTo.getSUID.getValue}L;}
+    @{innerClasses}
+    @{enumerations}
+    @{constants}
+    @{fields}
+    @{lengthRangeChecker}
+
+    @{constructors}
+
+    @defaultInstance()
+
+    @{propertyMethod}
+
+    @if(genTo.isTypedef && genTo.getBaseType.isInstanceOf[BitsTypeDefinition]) {
+    public boolean[] getValue() {
+        return new boolean[]{
+            @{valueForBits(genTo.getProperties)}
+            };
+        }
+    }
+
+    @generateHashCode()
+
+    @generateEquals()
+
+    @generateToString(genTo.getToStringIdentifiers)
+    }
+}
+
+@annotationDeclaration() = {
+@if(genTo.getAnnotations != null) {
+    @for(annotation <- genTo.getAnnotations) {
+        @@@{annotation.getName}
+    }
+}
+}
+
+@generateClassDeclaration(isInnerCLass: Boolean) = {
+public @{if (isInnerCLass) " static final "
+else if(genType.isAbstract) " abstract "
+else " "
+}
+class @{genType.getName}
+@if(genTo.getSuperType != null) { extends @{importedNames.get("genTypeSuper")}}
+@if(!implementsList.isEmpty) { implements @{implementsList}}
+}
+
+@generateHashCode() = {
+@if(!genTo.getHashCodeIdentifiers.isEmpty) {
+    @@Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        @for(property <- genTo.getHashCodeIdentifiers) {
+            @if(property.getReturnType.getName.contains("[")) {
+                result = prime * result + @{importedNames.get("arrays")}.hashCode(@{fieldName(property)});
+            } else {
+                result = prime * result + @{importedNames.get("objects")}.hashCode(@{fieldName(property)});
+            }
+        }
+        return result;
+    }
+}
+}
+
+@generateEquals() = {
+@if(!genTo.getEqualsIdentifiers.isEmpty) {
+    @@Override
+    public boolean equals(java.lang.Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        @{genTo.getName} other = (@{genTo.getName}) obj;
+        @for(property <- genTo.getEqualsIdentifiers) {
+            @if(property.getReturnType.getName.contains("[")) {
+                if (!@{importedNames.get("arrays")}.equals(@{fieldName(property)}, other.@{fieldName(property)}))
+            } else {
+                if (!@{importedNames.get("objects")}.equals(@{fieldName(property)}, other.@{fieldName(property)}))
+            }
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+}
+
+@generateToString(properties: List[GeneratedProperty]) = {
+@if(properties != null) {
+    @@Override
+    public @{importedNames.get("string")} toString() {
+        @{importedNames.get("stringBuilder")} builder = new @{importedNames.get("stringBuilder")} (@{importedNames.get("type")}.class.getSimpleName()).append(" [");
+        boolean first = true;
+
+        @for(property <- properties) {
+            if (@{fieldName(property)} != null) {
+                if (first) {
+                    first = false;
+                } else {
+                    builder.append(", ");
+                }
+                builder.append("@{fieldName(property)}=");
+                @if(property.getReturnType.getName.contains("[")) {
+                    builder.append(@{importedNames.get("arrays")}.toString(@{fieldName(property)}));
+                } else {
+                    builder.append(@{fieldName(property)});
+                }
+            }
+        }
+        return builder.append(']').toString();
+    }
+}
+}
+
+@defaultInstance() = {
+@if(genTo.isTypedef && !allProperties.isEmpty && !genTo.isUnionType) {
+    @if(!"org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(allProperties.get(0).getReturnType.getFullyQualifiedName)) {
+        public static @{genTo.getName} getDefaultInstance(String defaultValue) {
+            @if("byte[]".equals(allProperties.get(0).getReturnType.getName)) {
+                @{importedNames.get("baseEncoding")} baseEncoding = @{importedNames.get("baseEncoding")}.base64();
+                return new @{genTo.getName}(baseEncoding.decode(defaultValue));
+            } else {
+                @allProperties.get(0).getReturnType.getFullyQualifiedName match {
+                case "java.lang.String" => {
+                    return new @{genTo.getName}(defaultValue);
+                }
+                case "java.lang.Boolean" => {
+                    return new @{genTo.getName}(@{importedNames.get("boolean")}.valueOf(defaultValue));
+                }
+                case "java.lang.Byte" => {
+                    return new @{genTo.getName}(@{importedNames.get("byte")}.valueOf(defaultValue));
+                }
+                case "java.lang.Short" => {
+                    return new @{genTo.getName}(@{importedNames.get("short")}.valueOf(defaultValue));
+                }
+                case "java.lang.Integer" => {
+                    return new @{genTo.getName}(@{importedNames.get("integer")}.valueOf(defaultValue));
+                }
+                case "java.lang.Long" => {
+                    return new @{genTo.getName}(@{importedNames.get("long")}.valueOf(defaultValue));
+                }
+                case _ => {
+                    @if(allProperties.size > 1) {
+                        @{importedNames.get("list")}<@{importedNames.get("string")}> properties = @{importedNames.get("lists")}.newArrayList(@{propsAsArgs(allProperties)});
+                        if (!properties.contains(defaultValue)) {
+                            throw new @{importedNames.get("illegalArgumentException")}("invalid default parameter");
+                        }
+                        int i = 0;
+                        return new @{genTo.getName}(propsAsList(allProperties, importedNames.get("boolean")));
+                    } else {
+                        return new @{genTo.getName}(@{importedNames.get("defProp")}.valueOf(defaultValue));
+                    }
+                }
+                }
+            }
+        }
+        }
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateConstructors.scala.txt b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateConstructors.scala.txt
new file mode 100644 (file)
index 0000000..6d4918d
--- /dev/null
@@ -0,0 +1,78 @@
+@*
+ * 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 org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.PATTERN_CONSTANT_NAME
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.asArguments
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.fieldName
+@import org.opendaylight.mdsal.binding2.model.api.GeneratedTransferObject
+@import org.opendaylight.mdsal.binding2.model.api.GeneratedProperty
+
+@(genTo: GeneratedTransferObject, allProperties: List[GeneratedProperty], properties: List[GeneratedProperty],
+parentProperties: List[GeneratedProperty], importedNames: Map[String, String], argumentsDeclaration: String,
+unionConstructor: String, genRestrictions: String)
+@if(unionConstructor != null) {
+@{unionConstructor}
+} else {
+    @if(genTo.isTypedef && !allProperties.isEmpty && allProperties.size == 1 && allProperties.get(0).getName.equals("value")) {
+        @@@{importedNames.get("constructorProperties")}("value")
+    }
+    public @{genTo.getName}(@{argumentsDeclaration}) {
+        @if(!parentProperties.isEmpty) {
+            super(@{asArguments(parentProperties)});
+        }
+
+        @{genRestrictions}
+
+        @if(genTo.isTypedef && !allProperties.isEmpty && allProperties.size == 1 && allProperties.get(0).getName.equals("value")) {
+        @{importedNames.get("preconditions")}.checkNotNull(_value, "Supplied value may not be null");
+            @for(currentConstant <- genTo.getConstantDefinitions) {
+                @if(PATTERN_CONSTANT_NAME.equals(currentConstant.getName) && currentConstant.getValue.isInstanceOf[List[_]]) {
+                    for (Pattern p : patterns) {
+                        @{importedNames.get("preconditions")}.checkArgument(p.matcher(_value).matches(), "Supplied value \"%s\" does not match required pattern \"%s\"", _value, p);
+                    }
+                }
+            }
+        }
+        @for(prop <- properties) {
+            @if(importedNames.get(prop.getReturnType.toString).contains("[]")) {
+                @if(genTo.isTypedef && !allProperties.isEmpty && allProperties.size == 1 && allProperties.get(0).getName.equals("value")) {
+                    this.@{fieldName(prop)} = @{fieldName(prop)}.clone();
+                } else {
+                    this.@{fieldName(prop)} = @{fieldName(prop)} == null ? null : @{fieldName(prop)}.clone();
+                }
+            } else {
+                this.@{fieldName(prop)} = this.@{fieldName(prop)};
+            }
+        }
+    }
+}
+@if(!allProperties.isEmpty) {
+    /**
+     * Creates a copy from Source Object.
+     *
+     * @@param source Source object
+     */
+    public @{genTo.getName}(@{genTo.getName} source) {
+        @if(!parentProperties.isEmpty) {
+            super(source);
+        }
+        @for(property <- properties) {
+            this.@{fieldName(property)} = source.@{fieldName(property)};
+        }
+    }
+}
+@if(properties.isEmpty && !parentProperties.isEmpty) {
+    /**
+     * Creates a new instance from @{importedNames.get("superType")}
+     *
+     * @@param source Source object
+     */
+    public @{genTo.getName}(@{importedNames.get("superType")} source) {
+            super(source);
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateInitBlock.scala.txt b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateInitBlock.scala.txt
new file mode 100644 (file)
index 0000000..de003a8
--- /dev/null
@@ -0,0 +1,21 @@
+@*
+ * 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 org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.PATTERN_CONSTANT_NAME
+@import org.opendaylight.mdsal.binding2.generator.util.Binding2Mapping.MEMBER_PATTERN_LIST
+
+@(patterName: String)
+static {
+    final @{patterName} a[] = new @{patterName}[@{PATTERN_CONSTANT_NAME}.size()];
+    int i = 0;
+    for (String regEx : @{PATTERN_CONSTANT_NAME}) {
+        a[i++] = Pattern.compile(regEx);
+    }
+
+    @{MEMBER_PATTERN_LIST} = a;
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateRestrictions.scala.txt b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateRestrictions.scala.txt
new file mode 100644 (file)
index 0000000..1c9af5d
--- /dev/null
@@ -0,0 +1,27 @@
+@*
+ * 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 org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.getRestrictions
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.paramValue
+@import org.opendaylight.mdsal.binding2.java.api.generator.rangeGenerators.AbstractRangeGenerator
+@import org.opendaylight.mdsal.binding2.java.api.generator.rangeGenerators.LengthGenerator
+@import org.opendaylight.mdsal.binding2.model.api.Type
+
+@(currentType: Type, paramName: String, returnType: Type, rangeGenerator: AbstractRangeGenerator[_])
+@if(getRestrictions(currentType) != null) {
+    @if(!getRestrictions(currentType).getLengthConstraints.isEmpty || !getRestrictions(currentType).getRangeConstraints.isEmpty) {
+    if (@{paramName} != null) {
+        @if(!getRestrictions(currentType).getLengthConstraints.isEmpty) {
+            @{LengthGenerator.generateLengthCheckerCall(paramName, paramValue(returnType, paramName))}
+        }
+        @if(!getRestrictions(currentType).getRangeConstraints.isEmpty) {
+            @{rangeGenerator.generateRangeCheckerCall(paramName, paramValue(returnType, paramName))}
+        }
+    }
+    }
+}
\ No newline at end of file
diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateUnionConstr.scala.txt b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding2/classTemplateUnionConstr.scala.txt
new file mode 100644 (file)
index 0000000..3e801c7
--- /dev/null
@@ -0,0 +1,27 @@
+@*
+ * 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 org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.asArguments
+@import org.opendaylight.mdsal.binding2.java.api.generator.util.TextTemplateUtil.fieldName
+@import org.opendaylight.mdsal.binding2.model.api.GeneratedProperty
+@import org.opendaylight.mdsal.binding2.model.api.GeneratedType
+
+@(genType: GeneratedType, parentProperties: List[GeneratedProperty], allProperty: GeneratedProperty, other: List[GeneratedProperty],
+importedName: String, genRestrictions: String)
+public @{genType.getName}(@{importedName} @{allProperty.getName}) {
+    @if(!parentProperties.isEmpty) {
+        super(@{asArguments(parentProperties)});
+    }
+
+    @{genRestrictions}
+
+    this.@{fieldName(allProperty)} = @{allProperty.getName};
+    @for(item <- other) {
+        this.@{fieldName(item)} = null;
+    }
+}
\ No newline at end of file