MDSAL-292: Binding v2 - Pattern attribute ignored for leaf-list/leaf 09/67709/16
authorJie Han <han.jie@zte.com.cn>
Tue, 30 Jan 2018 08:29:03 +0000 (16:29 +0800)
committerRobert Varga <nite@hq.sk>
Mon, 19 Mar 2018 22:06:29 +0000 (22:06 +0000)
- Support pattern constraint for leaf of type string,
  add suffix with leaf name to avoid conflicts of constant name
  from multiple patterns of different leaf/leaf-lists.

Change-Id: Iafc6f94c08300b19439adbf2dc714a4cd96c9afc
Signed-off-by: Jie Han <han.jie@zte.com.cn>
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java
binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/yang/types/TypeGenHelper.java
binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BaseRenderer.java
binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BuilderRenderer.java [changed mode: 0644->0755]
binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/ClassRenderer.java
binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/InterfaceRenderer.java
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/builderTemplate.scala.txt [changed mode: 0644->0755]
binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/constantsTemplate.scala.txt
binding2/mdsal-binding2-test-model/src/main/yang/test-pattern.yang [new file with mode: 0755]

index dc28d500fb414639f09c3388e0e11150c74220d9..ee592c584daf9d01f4433d74cd843364371d528f 100755 (executable)
@@ -27,6 +27,7 @@ import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.NOTIFICATION;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.parameterizedTypeFor;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.wildcardTypeFor;
+import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.resolveRegExpressions;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
 
 import com.google.common.annotations.Beta;
@@ -49,6 +50,7 @@ import org.opendaylight.mdsal.binding.javav2.generator.util.TypeComments;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.mdsal.binding.javav2.generator.yang.types.BaseYangTypes;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.GroupingDefinitionDependencySort;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
@@ -91,6 +93,7 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
@@ -828,6 +831,18 @@ final class GenHelperUtil {
         }
     }
 
+    private static void addPatternConstant(final GeneratedTypeBuilder typeBuilder, final String leafName,
+            final List<PatternConstraint> patternConstraints) {
+        if (!patternConstraints.isEmpty()) {
+            final StringBuilder field = new StringBuilder();
+            field.append(BindingMapping.PATTERN_CONSTANT_NAME).append("_")
+                .append(JavaIdentifierNormalizer.normalizeSpecificIdentifier(leafName, JavaIdentifier.CLASS)
+                    .toUpperCase());
+            typeBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), field.toString(),
+                resolveRegExpressions(patternConstraints));
+        }
+    }
+
     /**
      * Converts <code>leaf</code> to the getter method which is added to
      * <code>typeBuilder</code>.
@@ -913,10 +928,12 @@ final class GenHelperUtil {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
                         restrictions, genCtx.get(module));
+                addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
+            addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
         }
 
         if (returnType == null) {
@@ -995,10 +1012,14 @@ final class GenHelperUtil {
             } else {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+
+                addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+
+            addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
         }
 
         final ParameterizedType listType = Types.listTypeFor(returnType);
index 9e8f58a0ce5561dd70d4136eb31b59d8dcf2c588..9eb1bdcf28227678847cba0be2043a8c98096d45 100755 (executable)
@@ -68,7 +68,7 @@ import org.slf4j.LoggerFactory;
  * Auxiliary util class for {@link TypeProviderImpl} class
  */
 @Beta
-final class TypeGenHelper {
+public final class TypeGenHelper {
     private static final Logger LOG = LoggerFactory.getLogger(TypeGenHelper.class);
 
     private TypeGenHelper() {
@@ -224,7 +224,22 @@ final class TypeGenHelper {
         }
 
         // TODO: run diff against base ?
-        final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) typedef).getPatternConstraints();
+        return resolveRegExpressions(((StringTypeDefinition) typedef).getPatternConstraints());
+    }
+
+    /**
+     * Converts the pattern constraints to the list of
+     * the strings which represents these constraints.
+     *
+     * @param patternConstraints
+     *            list of pattern constraints
+     * @return list of strings which represents the constraint patterns
+     */
+    public static Map<String, String> resolveRegExpressions(final List<PatternConstraint> patternConstraints) {
+        if (patternConstraints.isEmpty()) {
+            return ImmutableMap.of();
+        }
+
         final Map<String, String> regExps = Maps.newHashMapWithExpectedSize(patternConstraints.size());
         for (PatternConstraint patternConstraint : patternConstraints) {
             String regEx = patternConstraint.getJavaPatternString();
index a35676bfa77e133242d8f2f3f30ed9a4ea45e01a..a246fc67d3ec44ecda8989673c984955f737e59c 100644 (file)
@@ -9,15 +9,19 @@
 package org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static org.opendaylight.mdsal.binding.javav2.util.BindingMapping.PATTERN_CONSTANT_NAME;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import org.apache.commons.text.StringEscapeUtils;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil;
@@ -38,6 +42,10 @@ public abstract class BaseRenderer {
 
     private final GeneratedType type;
     private final Map<String, String> importMap;
+    /**
+     * list of all imported names for template
+     */
+    private final Map<String, String> importedNames = new HashMap<>();
 
     protected BaseRenderer(final GeneratedType type) {
         this.type = Preconditions.checkNotNull(type);
@@ -54,6 +62,10 @@ public abstract class BaseRenderer {
         return type;
     }
 
+    protected Map<String, String> getImportedNames() {
+        return importedNames;
+    }
+
     protected String getFromImportMap(@NonNull final String typeName) {
         return importMap.get(typeName);
     }
@@ -246,36 +258,6 @@ public abstract class BaseRenderer {
         return null;
     }
 
-    //FIXME: this should be deprecated in favor of contantsTemplate
-    /**
-     * @param constant constant to emit
-     * @return string with constant wrapped in code
-     */
-    protected String emitConstant(final Constant constant) {
-        final StringBuilder sb = new StringBuilder();
-        final Object value = constant.getValue();
-        sb.append("public static final ")
-                .append(importedName(constant.getType()))
-                .append(' ')
-                .append(constant.getName())
-                .append(" = ");
-        if (value instanceof QName) {
-            final QName qname = (QName) value;
-            sb.append(QName.class.getName()).append(".create(\"").append(qname.getNamespace()).append("\", ");
-            final Optional<Revision> rev = qname.getRevision();
-            if (rev.isPresent()) {
-                sb.append('"').append(rev.get()).append('"');
-            } else {
-                sb.append("null");
-            }
-            sb.append(", \"").append(qname.getLocalName()).append("\").intern()");
-        } else {
-            sb.append(value);
-        }
-        sb.append(";\n");
-        return sb.toString();
-    }
-
     /**
      * Generates the string with all actual type parameters from
      *
old mode 100644 (file)
new mode 100755 (executable)
index d2ef788..e84cb68
@@ -16,6 +16,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ClassToInstanceMap;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedSet;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -29,12 +30,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.regex.Pattern;
 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
 import org.opendaylight.mdsal.binding.javav2.generator.util.ReferencedTypeImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.builderConstructorHelperTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.builderTemplate;
+import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.constantsTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.AlphabeticallyTypeMemberComparator;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
@@ -67,11 +70,6 @@ public class BuilderRenderer extends BaseRenderer {
      */
     private final Map<GeneratedProperty, String> importedNamesForProperties = new HashMap<>();
 
-    /**
-     * list of all imported names for template
-     */
-    private final Map<String, String> importedNames = new HashMap<>();
-
     /**
      * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME
      */
@@ -200,17 +198,17 @@ public class BuilderRenderer extends BaseRenderer {
                             generatedTOBuilder.addMethod(method.getName()).setReturnType(parametrizedReturnType);
                             augmentField = propertyFromGetter(generatedTOBuilder.toInstance().getMethodDefinitions()
                                 .get(0));
-                            importedNames.put("map", importedName(Map.class));
-                            importedNames.put("hashMap", importedName(HashMap.class));
-                            importedNames.put("class", importedName(Class.class));
+                            getImportedNames().put("map", importedName(Map.class));
+                            getImportedNames().put("hashMap", importedName(HashMap.class));
+                            getImportedNames().put("class", importedName(Class.class));
 //                            To do This is for third party, is it needed ?
-                            importedNames.put("augmentationHolder", importedName(AugmentationHolder.class));
-                            importedNames.put("collections", importedName(Collections.class));
-                            importedNames.put("augmentFieldReturnType", importedName(augmentField.getReturnType()));
+                            getImportedNames().put("augmentationHolder", importedName(AugmentationHolder.class));
+                            getImportedNames().put("collections", importedName(Collections.class));
+                            getImportedNames().put("augmentFieldReturnType", importedName(augmentField.getReturnType()));
                         }
                     }
                 } else if (Instantiable.class.getName().equals(implementedIfc.getFullyQualifiedName())) {
-                    importedNames.put("class", importedName(Class.class));
+                    getImportedNames().put("class", importedName(Class.class));
                     instantiable = true;
                 }
             }
@@ -278,24 +276,27 @@ public class BuilderRenderer extends BaseRenderer {
     @Override
     protected String body() {
         final String parentTypeForBuilderName;
-        importedNames.put("genType", importedName(getType()));
-        importedNames.put("objects", importedName(Objects.class));
-        importedNames.put("object", importedName(Object.class));
-        importedNames.put("string", importedName(String.class));
-        importedNames.put("arrays", importedName(Arrays.class));
-        importedNames.put("stringBuilder", importedName(StringBuilder.class));
-        importedNames.put("treeNode", importedName(TreeNode.class));
-        importedNames.put("instantiable", importedName(Instantiable.class));
-        importedNames.put("item", importedName(Item.class));
-        importedNames.put("identifiableItem", importedName(IdentifiableItem.class));
-        importedNames.put("qname", importedName(QName.class));
-        importedNames.put("codeHelpers", importedName(CodeHelpers.class));
+        getImportedNames().put("genType", importedName(getType()));
+        getImportedNames().put("objects", importedName(Objects.class));
+        getImportedNames().put("object", importedName(Object.class));
+        getImportedNames().put("string", importedName(String.class));
+        getImportedNames().put("arrays", importedName(Arrays.class));
+        getImportedNames().put("stringBuilder", importedName(StringBuilder.class));
+        getImportedNames().put("treeNode", importedName(TreeNode.class));
+        getImportedNames().put("instantiable", importedName(Instantiable.class));
+        getImportedNames().put("item", importedName(Item.class));
+        getImportedNames().put("identifiableItem", importedName(IdentifiableItem.class));
+        getImportedNames().put("qname", importedName(QName.class));
+        getImportedNames().put("codeHelpers", importedName(CodeHelpers.class));
+        getImportedNames().put("list", importedName(List.class));
+        getImportedNames().put("immutableList", importedName(ImmutableList.class));
+        getImportedNames().put("pattern", importedName(Pattern.class));
 
         if (getType().getParentType() != null) {
-            importedNames.put("parent", importedName(getType().getParentType()));
+            getImportedNames().put("parent", importedName(getType().getParentType()));
             parentTypeForBuilderName = getType().getParentType().getFullyQualifiedName();
         } else if (getType().getParentTypeForBuilder() != null) {
-            importedNames.put("parentTypeForBuilder", importedName(getType().getParentTypeForBuilder()));
+            getImportedNames().put("parentTypeForBuilder", importedName(getType().getParentTypeForBuilder()));
             parentTypeForBuilderName = getType().getParentTypeForBuilder().getFullyQualifiedName();
         } else {
             parentTypeForBuilderName = null;
@@ -314,16 +315,18 @@ public class BuilderRenderer extends BaseRenderer {
             }
         }
 
-        importedNames.put("augmentation", importedName(Augmentation.class));
-        importedNames.put("classInstMap", importedName(ClassToInstanceMap.class));
+        getImportedNames().put("augmentation", importedName(Augmentation.class));
+        getImportedNames().put("classInstMap", importedName(ClassToInstanceMap.class));
+
+        final String constants = constantsTemplate.render(getType(), getImportedNames(), this::importedName, false).body();
 
         // list for generate copy constructor
         final String copyConstructorHelper = generateListForCopyConstructor();
         List<String> getterMethods = new ArrayList<>(Collections2.transform(properties, this::getterMethod));
 
-        return builderTemplate.render(getType(), properties, importedNames, importedNamesForProperties, augmentField,
+        return builderTemplate.render(getType(), properties, getImportedNames(), importedNamesForProperties, augmentField,
             copyConstructorHelper, getterMethods, parentTypeForBuilderName, childTreeNode, childTreeNodeIdent,
-            keyTypeName, instantiable).body();
+            keyTypeName, instantiable, constants).body();
     }
 
     private String generateListForCopyConstructor() {
@@ -337,11 +340,11 @@ public class BuilderRenderer extends BaseRenderer {
                 removeProperty(allProps, keyProp.getName());
             }
             removeProperty(allProps, "key");
-            importedNames.put("keyTypeConstructor", importedName(keyType));
-            return builderConstructorHelperTemplate.render(allProps, keyProps, importedNames, getPropertyList(keyProps))
+            getImportedNames().put("keyTypeConstructor", importedName(keyType));
+            return builderConstructorHelperTemplate.render(allProps, keyProps, getImportedNames(), getPropertyList(keyProps))
                     .body();
         }
-        return builderConstructorHelperTemplate.render(allProps, null, importedNames, null).body();
+        return builderConstructorHelperTemplate.render(allProps, null, getImportedNames(), null).body();
     }
 
     private Type getKey(final GeneratedType genType) {
index f0a99cae4d57ef82e4379ad56224055f5f4aab22..e4900b8352ae42f31ebb14908f70d18dcf824536 100644 (file)
@@ -53,7 +53,7 @@ public class ClassRenderer extends BaseRenderer {
     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) {
@@ -131,20 +131,20 @@ public class ClassRenderer extends BaseRenderer {
     }
 
     protected String generateBody(final boolean isInnerClass) {
-        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));
-        importedNames.put("qname", importedName(QName.class));
+        getImportedNames().put("type", importedName(getType()));
+        getImportedNames().put("arrays", importedName(Arrays.class));
+        getImportedNames().put("objects", importedName(Objects.class));
+        getImportedNames().put("string", importedName(String.class));
+        getImportedNames().put("byte", importedName(Byte.class));
+        getImportedNames().put("short", importedName(Short.class));
+        getImportedNames().put("integer", importedName(Integer.class));
+        getImportedNames().put("long", importedName(Long.class));
+        getImportedNames().put("stringBuilder", importedName(StringBuilder.class));
+        getImportedNames().put("list", importedName(List.class));
+        getImportedNames().put("lists", importedName(Lists.class));
+        getImportedNames().put("illegalArgumentException", importedName(IllegalArgumentException.class));
+        getImportedNames().put("boolean", importedName(Boolean.class));
+        getImportedNames().put("qname", importedName(QName.class));
 
         final List<String> implementsListBuilder = new LinkedList<>();
         if (!getType().getImplements().isEmpty()) {
@@ -172,14 +172,14 @@ public class ClassRenderer extends BaseRenderer {
         }
         final String enumerations = String.join("\n", enumList);
 
-        final String constants = constantsTemplate.render(getType(), importedNames, this::importedName).body();
+        final String constants = constantsTemplate.render(getType(), getImportedNames(), this::importedName, false).body();
 
         if (genTO.getSuperType() != null) {
-            importedNames.put("superType", importedName(genTO.getSuperType()));
+            getImportedNames().put("superType", importedName(genTO.getSuperType()));
         }
 
         for (GeneratedProperty property : properties) {
-            importedNames.put(property.getReturnType().toString(), importedName(property.getReturnType()));
+            getImportedNames().put(property.getReturnType().toString(), importedName(property.getReturnType()));
         }
 
         final String constructors = generateConstructors();
@@ -212,9 +212,9 @@ public class ClassRenderer extends BaseRenderer {
             }
         }
         final String fields = sb2.toString();
-        importedNames.put("baseEncoding", importedName(BaseEncoding.class));
+        getImportedNames().put("baseEncoding", importedName(BaseEncoding.class));
         if (!allProperties.isEmpty()) {
-            importedNames.put("defProp", importedName(((GeneratedProperty)((List) allProperties).get(0)).getReturnType()));
+            getImportedNames().put("defProp", importedName(((GeneratedProperty)((List) allProperties).get(0)).getReturnType()));
         }
 
         final StringBuilder sb3 = new StringBuilder();
@@ -227,14 +227,14 @@ public class ClassRenderer extends BaseRenderer {
         }
         final String propertyMethod = sb3.toString();
 
-        return classTemplate.render(getType(), genTO, importedNames, implementsList, innerClasses, enumerations,
+        return classTemplate.render(getType(), genTO, getImportedNames(), implementsList, innerClasses, enumerations,
                 constants, constructors, lengthRangeChecker, fields, allProperties, propertyMethod,
                 isInnerClass).body();
     }
 
     protected String generateConstructors() {
-        importedNames.put("constructorProperties", importedName(ConstructorProperties.class));
-        importedNames.put("preconditions", importedName(Preconditions.class));
+        getImportedNames().put("constructorProperties", importedName(ConstructorProperties.class));
+        getImportedNames().put("preconditions", importedName(Preconditions.class));
 
         final StringBuilder sb1 = new StringBuilder();
         for (GeneratedProperty allProperty : allProperties) {
@@ -257,7 +257,7 @@ public class ClassRenderer extends BaseRenderer {
 
         final String argumentsDeclaration = asArgumentsDeclaration(allProperties);
         return classTemplateConstructors.render(genTO, allProperties, properties, parentProperties,
-                importedNames, argumentsDeclaration, unionConstructor, genRestrictions).body();
+                getImportedNames(), argumentsDeclaration, unionConstructor, genRestrictions).body();
     }
 
     /**
index 63809dd7c9fba4b2c4780e74d38830a64b13e8ae..0b11d400d4c2f8240eb498c0717f3d3950e65494 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.mdsal.binding.javav2.java.api.generator.renderers;
 import com.google.common.base.Preconditions;
 import java.util.ArrayList;
 import java.util.List;
+import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.constantsTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.enumTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.txt.interfaceTemplate;
 import org.opendaylight.mdsal.binding.javav2.java.api.generator.util.TextTemplateUtil;
@@ -21,6 +22,7 @@ import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.MethodSignature;
 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
+import org.opendaylight.yangtools.yang.common.QName;
 
 public class InterfaceRenderer extends BaseRenderer {
 
@@ -69,13 +71,10 @@ public class InterfaceRenderer extends BaseRenderer {
         final String enums = sb2.toString();
 
         final String generatedImports = generateImports(getType().getImplements());
-        // generatedConstants list of constants
-        final List<String> strings = new ArrayList<>(getType().getConstantDefinitions().size());
-        for (Constant constant : getType().getConstantDefinitions()) {
-            strings.add(emitConstant(constant));
-        }
 
-        final String generatedConstants = String.join("\n", strings);
+        getImportedNames().put("qname", importedName(QName.class));
+        final String generatedConstants = constantsTemplate.render(getType(), getImportedNames(),
+            this::importedName, true).body();
 
         final List<String> innerClasses = new ArrayList<>(getType().getEnclosedTypes().size());
         for (GeneratedType innerClass : getType().getEnclosedTypes()) {
old mode 100644 (file)
new mode 100755 (executable)
index f9c732b..5a74bdb
 @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.util.BindingMapping
+@import org.opendaylight.mdsal.binding.javav2.generator.util.Types
 @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.GeneratedTypeForBuilder
 @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.mdsal.binding.javav2.model.api.ParameterizedType
 @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], parentTypeForBuilderName: String, childTreeNode: Boolean, childTreeNodeIdent: Boolean,
-keyTypeName: String, instantiable: Boolean)
+keyTypeName: String, instantiable: Boolean, constants: String)
 @if(genType != null) {
 @{wrapToDocumentation(formatDataForJavaDocBuilder(importedNames.get("genType")))}
 public class @{genType.getName}Builder implements @{getSimpleNameForBuilder} <@{importedNames.get("genType")}> {
 
     @generateFields(false)
 
+    @{constants}
+
     @generateAugmentField(false)
 
     @generateConstructorsFromIfcs()
@@ -251,40 +256,14 @@ public class @{genType.getName}Builder implements @{getSimpleNameForBuilder} <@{
 
 @generateSetters() = {
     @for(field <- properties) {
-        @if(!field.getReturnType.isInstanceOf[GeneratedType] && getRestrictions(field.getReturnType) != null) {
-            @if(getRestrictions(field.getReturnType).getRangeConstraint.isPresent) {
-                @{AbstractRangeGenerator.forType(field.getReturnType).generateRangeChecker(toFirstUpper(field.getName),
-                getRestrictions(field.getReturnType).getRangeConstraint.get)}
-            }
-            @if(getRestrictions(field.getReturnType).getLengthConstraint.isPresent) {
-                @{LengthGenerator.generateLengthChecker(fieldName(field), field.getReturnType,
-                getRestrictions(field.getReturnType).getLengthConstraint.get)}
-            }
-        }
-
-        public @{genType.getName}Builder set@{toFirstUpper(field.getName)}(final @{field.getReturnType.getFullyQualifiedName} value) {
-        @if(!field.getReturnType.isInstanceOf[GeneratedType] && getRestrictions(field.getReturnType) != null) {
-            if (value != null) {
-            @if(getRestrictions(field.getReturnType).getRangeConstraint.isPresent) {
-                @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).getLengthConstraint.isPresent) {
-                @if(field.getReturnType.isInstanceOf[ConcreteType]) {
-                    @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value")}
-                } else {
-                    @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value.getValue()")}
-                }
-            }
-            }
-        }
-            this.@{fieldName(field)} = value;
-            return this;
+        @if(field.getReturnType.isInstanceOf[ParameterizedType]
+            && field.getReturnType.asInstanceOf[ParameterizedType].getRawType.equals(Types.typeForClass(classOf[List[_]]))) {
+          @generateSetter(field, field.getReturnType.asInstanceOf[ParameterizedType].getActualTypeArguments()(0), true)
+        } else {
+          @generateSetter(field, field.getReturnType, false)
         }
     }
+
     @if(augmentField != null) {
         public @{genType.getName}Builder add@{toFirstUpper(augmentField.getName)}(@{importedNames.get("class")}<? extends @{importedNames.get("augmentFieldReturnType")}> augmentationType, @{importedNames.get("augmentFieldReturnType")} augmentation) {
             if (augmentation == null) {
@@ -309,6 +288,69 @@ public class @{genType.getName}Builder implements @{getSimpleNameForBuilder} <@{
     }
 }
 
+@generateSetter(field: GeneratedProperty, actualType: Type, isList: Boolean) = {
+    @if(!actualType.isInstanceOf[GeneratedType] && getRestrictions(actualType) != null) {
+        @if(getRestrictions(actualType).getRangeConstraint.isPresent) {
+            @{AbstractRangeGenerator.forType(actualType).generateRangeChecker(toFirstUpper(field.getName),
+            getRestrictions(actualType).getRangeConstraint.get)}
+        }
+        @if(getRestrictions(actualType).getLengthConstraint.isPresent) {
+            @{LengthGenerator.generateLengthChecker(fieldName(field), actualType,
+            getRestrictions(actualType).getLengthConstraint.get)}
+        }
+    }
+
+    @if(isList) {
+        public @{genType.getName}Builder set@{toFirstUpper(field.getName)}(final @{ImportedNamesWithProperties.get(field)} values) {
+            @if(!actualType.isInstanceOf[GeneratedType] && getRestrictions(actualType) != null) {
+                if (values != null) {
+                    for (@{actualType.getFullyQualifiedName} value : values) {
+                        @checkArgument(field, actualType)
+                    }
+                }
+            }
+            this.@{fieldName(field)} = values;
+            return this;
+        }
+    } else {
+        public @{genType.getName}Builder set@{toFirstUpper(field.getName)}(final @{ImportedNamesWithProperties.get(field)} value) {
+            @if(!actualType.isInstanceOf[GeneratedType] && getRestrictions(actualType) != null) {
+                if (value != null) {
+                    @checkArgument(field, actualType)
+                }
+            }
+            this.@{fieldName(field)} = value;
+            return this;
+        }
+    }
+}
+
+@checkArgument(field: GeneratedProperty, actualType: Type) = {
+    @if(getRestrictions(actualType).getRangeConstraint.isPresent) {
+        @if(actualType.isInstanceOf[ConcreteType]) {
+            @{AbstractRangeGenerator.forType(actualType).generateRangeCheckerCall(toFirstUpper(field.getName), "value")}
+        } else {
+            @{AbstractRangeGenerator.forType(actualType).generateRangeCheckerCall(toFirstUpper(field.getName), "value.getValue()")}
+        }
+    }
+    @if(getRestrictions(actualType).getLengthConstraint.isPresent) {
+        @if(actualType.isInstanceOf[ConcreteType]) {
+            @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value")}
+        } else {
+            @{LengthGenerator.generateLengthCheckerCall(fieldName(field), "value.getValue()")}
+        }
+    }
+    @for(currentConstant <- genType.getConstantDefinitions) {
+        @defining(fieldName(field)) { suffix =>
+        @if(currentConstant.getName.startsWith(BindingMapping.PATTERN_CONSTANT_NAME)
+                && suffix.toUpperCase().equals(currentConstant.getName.substring(BindingMapping.PATTERN_CONSTANT_NAME.length))
+                && currentConstant.getValue.isInstanceOf[List[_]]) {
+            @{importedNames.get("codeHelpers")}.checkPattern(value, @{BindingMapping.MEMBER_PATTERN_LIST}@{suffix}, @{BindingMapping.MEMBER_REGEX_LIST}@{suffix};
+        }
+        }
+    }
+}
+
 @generateGetters(addOverride: Boolean) = {
     @if(!getterMethods.isEmpty) {
         @for(property <- getterMethods) {
index dc68bb43a7d6fb75810543456afa29b5604b940f..f9093b0cd8e1c7159a17ac3141ccf621b4951760 100644 (file)
 @import org.opendaylight.yangtools.yang.common.QName;
 @import org.opendaylight.yangtools.yang.common.Revision;
 
-@(genType: GeneratedType, importedNames: Map[String, String], importedName: Function[Type, String])
+@(genType: GeneratedType, importedNames: Map[String, String], importedName: Function[Type, String], qnameOnly: Boolean)
 @for(c <- genType.getConstantDefinitions) {
-    @if(c.getName == BindingMapping.PATTERN_CONSTANT_NAME) {
+    @if(c.getName.startsWith(BindingMapping.PATTERN_CONSTANT_NAME)) {
+    @if(!qnameOnly) {
+        @defining(c.getName.substring(BindingMapping.PATTERN_CONSTANT_NAME.length).toLowerCase) { suffix =>
         @defining(c.getValue.asInstanceOf[Map[String, String]]) { cValue =>
-        public static final @{importedNames.get("list")}<@{importedNames.get("string")}> @{BindingMapping.PATTERN_CONSTANT_NAME} = @{importedNames.get("immutableList")}.of(
+        public static final @{importedNames.get("list")}<@{importedNames.get("string")}> @{c.getName} = @{importedNames.get("immutableList")}.of(
             @{(cValue.keySet map {escapeJava}).mkString("\"", "\", \"", "\"")});
         @if(cValue.size == 1) {
-            private static final @{importedNames.get("pattern")} @{BindingMapping.MEMBER_PATTERN_LIST} = @{importedNames.get("pattern")}.compile(@{BindingMapping.PATTERN_CONSTANT_NAME}.get(0));
-            private static final String @{BindingMapping.MEMBER_REGEX_LIST} = "@{escapeJava(cValue.values.stream.findFirst.get)}";
+            private static final @{importedNames.get("pattern")} @{BindingMapping.MEMBER_PATTERN_LIST}@{suffix} = @{importedNames.get("pattern")}.compile(@{c.getName}.get(0));
+            private static final String @{BindingMapping.MEMBER_REGEX_LIST}@{suffix} = "@{escapeJava(cValue.values.stream.findFirst.get)}";
         } else {
-            private static final @{importedNames.get("pattern")}[] @{BindingMapping.MEMBER_PATTERN_LIST} = @{importedNames.get("codeHelpers")}.compilePatterns(@{BindingMapping.PATTERN_CONSTANT_NAME});
-            private static final String[] @{BindingMapping.MEMBER_REGEX_LIST} = {
+            private static final @{importedNames.get("pattern")}[] @{BindingMapping.MEMBER_PATTERN_LIST}@{suffix} = @{importedNames.get("codeHelpers")}.compilePatterns(@{c.getName});
+            private static final String[] @{BindingMapping.MEMBER_REGEX_LIST}@{suffix} = {
                 @{(cValue.keySet map {escapeJava}).mkString("\"", "\", \"", "\"")}
             };
-        }
-        }
+        }}}}
     } else {
         public static final @{importedName(c.getType())} @{c.getName} =
         @if(c.getValue.isInstanceOf[QName]) {
diff --git a/binding2/mdsal-binding2-test-model/src/main/yang/test-pattern.yang b/binding2/mdsal-binding2-test-model/src/main/yang/test-pattern.yang
new file mode 100755 (executable)
index 0000000..43f7f16
--- /dev/null
@@ -0,0 +1,37 @@
+module test-pattern {
+    yang-version 1.1;
+    namespace "urn:test:pattern";
+    prefix pattern;
+    revision 2017-01-01;
+
+    container cont {
+        leaf test {
+            type string {
+              pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*';
+              pattern '[xX][mM][lL].*';
+            }
+        }
+
+        leaf test2 {
+            type string {
+              pattern '[0-9]*';
+            }
+        }
+
+
+        leaf-list test3 {
+            type string {
+              pattern '[a-zA-Z_]*';
+              pattern '[xX][mM][lL].*' {
+                modifier invert-match;
+              }
+            }
+        }
+
+        leaf-list test4 {
+            type string {
+              pattern '[a-z]*';
+            }
+        }
+    }
+}
\ No newline at end of file