MDSAL-292: Binding v1 - Pattern attribute ignored for leaf-list/leaf 51/67851/27
authorJie Han <han.jie@zte.com.cn>
Fri, 2 Feb 2018 03:11:34 +0000 (11:11 +0800)
committerRobert Varga <nite@hq.sk>
Mon, 19 Mar 2018 12:09:51 +0000 (12:09 +0000)
- Support pattern constraint for leaf-list/leaf

- support modifier statement for pattern of yang 1.1

- Add test yang

Change-Id: I1a2f2b24a023479dee8ee9de08374386d38ba17a
Signed-off-by: Jie Han <han.jie@zte.com.cn>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
12 files changed:
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/CodegenTypeProvider.java
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/RuntimeTypeProvider.java
binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/TypeConstants.java
binding/mdsal-binding-generator-util/src/main/java/org/opendaylight/mdsal/binding/model/util/Types.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/ClassTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/Constants.java
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/InterfaceTemplate.xtend
binding/mdsal-binding-java-api-generator/src/test/java/org/opendaylight/mdsal/binding/java/api/generator/BuilderGeneratorTest.java
binding/mdsal-binding-test-model/src/main/yang/test-pattern.yang [new file with mode: 0755]

index 4f5815f6d2964e45778d5da958ad7f24969fe562..bebf87e6fd68ac3d2a094980f395759d424eeb22 100644 (file)
@@ -58,10 +58,12 @@ import org.opendaylight.mdsal.binding.model.api.type.builder.TypeMemberBuilder;
 import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
 import org.opendaylight.mdsal.binding.model.util.BindingTypes;
 import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl;
+import org.opendaylight.mdsal.binding.model.util.TypeConstants;
 import org.opendaylight.mdsal.binding.model.util.Types;
 import org.opendaylight.mdsal.binding.model.util.generated.type.builder.CodegenGeneratedTOBuilder;
 import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedPropertyBuilderImpl;
 import org.opendaylight.mdsal.binding.yang.types.AbstractTypeProvider;
+import org.opendaylight.mdsal.binding.yang.types.BaseYangTypes;
 import org.opendaylight.mdsal.binding.yang.types.GroupingDefinitionDependencySort;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
@@ -98,6 +100,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
 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.DataNodeIterator;
 import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort;
@@ -1301,6 +1304,16 @@ abstract class AbstractTypeGenerator {
         return false;
     }
 
+    private void addPatternConstant(final GeneratedTypeBuilder typeBuilder, final String leafName,
+            final List<PatternConstraint> patternConstraints) {
+        if (!patternConstraints.isEmpty()) {
+            final StringBuilder field = new StringBuilder().append(TypeConstants.PATTERN_CONSTANT_NAME).append("_")
+                .append(BindingMapping.getPropertyName(leafName).toUpperCase());
+            typeBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), field.toString(),
+                typeProvider.resolveRegExpressions(patternConstraints));
+        }
+    }
+
     /**
      * Converts <code>leaf</code> to the getter method which is added to
      * <code>typeBuilder</code>.
@@ -1359,10 +1372,12 @@ abstract class AbstractTypeGenerator {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
                         restrictions);
+                addPatternConstant(typeBuilder, leaf.getQName().getLocalName(), restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions);
+            addPatternConstant(typeBuilder, leaf.getQName().getLocalName(), restrictions.getPatternConstraints());
         }
 
         if (returnType == null) {
@@ -1560,10 +1575,12 @@ abstract class AbstractTypeGenerator {
             } else {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions);
+                addPatternConstant(typeBuilder, node.getQName().getLocalName(), restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions);
+            addPatternConstant(typeBuilder, node.getQName().getLocalName(), restrictions.getPatternConstraints());
         }
 
         final ParameterizedType listType = Types.listTypeFor(returnType);
index 6cb6ff926e493cd5c10fd7895f4bf46817f33228..d4e9603d77dc5b004fd231793583756cdb8dbf9c 100644 (file)
@@ -77,6 +77,7 @@ import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort;
@@ -708,6 +709,14 @@ public abstract class AbstractTypeProvider implements TypeProvider {
 
     public abstract GeneratedTypeBuilder newGeneratedTypeBuilder(String packageName, String name);
 
+    /**
+     * 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 abstract Map<String, String> resolveRegExpressions(List<PatternConstraint> patternConstraints);
+
     abstract void addCodegenInformation(GeneratedTypeBuilderBase<?> genTOBuilder, TypeDefinition<?> typeDef);
 
     /**
@@ -721,7 +730,14 @@ public abstract class AbstractTypeProvider implements TypeProvider {
      *             if <code>typedef</code> equals null
      *
      */
-    abstract Map<String, String> resolveRegExpressionsFromTypedef(TypeDefinition<?> typedef);
+    private Map<String, String> resolveRegExpressionsFromTypedef(final TypeDefinition<?> typedef) {
+        if (!(typedef instanceof StringTypeDefinition)) {
+            return ImmutableMap.of();
+        }
+
+        // TODO: run diff against base ?
+        return resolveRegExpressions(((StringTypeDefinition) typedef).getPatternConstraints());
+    }
 
     /**
      * Converts <code>dataNode</code> to JAVA <code>Type</code>.
index 5525120328a8a796438257d4f09695a69bbc49d2..f9f4ee34ff6adaf3ab383d2ee6f165ec059da750 100644 (file)
@@ -29,7 +29,6 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.ModifierKind;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
-import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,14 +68,20 @@ public class CodegenTypeProvider extends AbstractTypeProvider {
         typeDef.getReference().ifPresent(genTOBuilder::setReference);
     }
 
+    /**
+     * 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
+     */
     @Override
-    Map<String, String> resolveRegExpressionsFromTypedef(final TypeDefinition<?> typedef) {
-        if (!(typedef instanceof StringTypeDefinition)) {
+    public Map<String, String> resolveRegExpressions(final List<PatternConstraint> patternConstraints) {
+        if (patternConstraints.isEmpty()) {
             return ImmutableMap.of();
         }
 
-        // TODO: run diff against base ?
-        final List<PatternConstraint> patternConstraints = ((StringTypeDefinition) typedef).getPatternConstraints();
         final Map<String, String> regExps = Maps.newHashMapWithExpectedSize(patternConstraints.size());
         for (PatternConstraint patternConstraint : patternConstraints) {
             String regEx = patternConstraint.getJavaPatternString();
index 8e872a25cf10a5e4789df1003b862d6bb579626e..4e47f540b5da3a3f25d604f6295cda2bd338842f 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.mdsal.binding.yang.types;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableMap;
+import java.util.List;
 import java.util.Map;
 import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder;
@@ -21,6 +22,7 @@ import org.opendaylight.mdsal.binding.model.util.generated.type.builder.RuntimeG
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 
 /**
  * {@link AbstractTypeProvider} which generates enough type information for runtime support. For a codegen-compatible
@@ -43,7 +45,7 @@ public final class RuntimeTypeProvider extends AbstractTypeProvider {
     }
 
     @Override
-    Map<String, String> resolveRegExpressionsFromTypedef(final TypeDefinition<?> typedef) {
+    public Map<String, String> resolveRegExpressions(final List<PatternConstraint> patternConstraints) {
         return ImmutableMap.of();
     }
 
index 9cd5ec3a279b3bc40b32b54aeecb69dbbac7397f..d3550d721bc3575fd1e16ac143d6d0a42979b674 100644 (file)
@@ -13,8 +13,11 @@ package org.opendaylight.mdsal.binding.model.util;
 public final class TypeConstants {
 
     /**
-     * Name of the class constant which holds the map of regular expressions that need to be enforced on the string
-     * value. The map is keyed by Pattern-compatible string and values are XSD-compatible strings.
+     * Name or prefix (multiple patterns in builder class as composed with '_'
+     * and upper case of the field name) of the class constant which holds the map
+     * of regular expressions that need to be enforced on the string value.
+     * The map is keyed by Pattern-compatible string and values are XSD-compatible
+     * strings.
      */
     public static final String PATTERN_CONSTANT_NAME = "PATTERN_CONSTANTS";
 
index 70a7db6d77522aa92393bf682bab176fcd5ac611..f16ed9cf5a303478a58748705c5ce697aa9eb968 100644 (file)
@@ -47,9 +47,9 @@ public final class Types {
     private static final LoadingCache<Class<?>, ConcreteType> TYPE_CACHE =
             CacheBuilder.newBuilder().weakKeys().build(TYPE_LOADER);
 
-    private static final Type SET_TYPE = typeForClass(Set.class);
-    private static final Type LIST_TYPE = typeForClass(List.class);
-    private static final Type MAP_TYPE = typeForClass(Map.class);
+    public static final Type SET_TYPE = typeForClass(Set.class);
+    public static final Type LIST_TYPE = typeForClass(List.class);
+    public static final Type MAP_TYPE = typeForClass(Map.class);
 
     public static final ConcreteType BOOLEAN = typeForClass(Boolean.class);
     public static final ConcreteType FUTURE = typeForClass(Future.class);
index 12e975c2681117ff01a5425747d6d2a93f5d1cec..9ef7618476f772e3a25732733e5ba65d381ed0e6 100644 (file)
@@ -7,9 +7,12 @@
  */
 package org.opendaylight.mdsal.binding.java.api.generator
 
+import static extension org.apache.commons.text.StringEscapeUtils.escapeJava;
+
 import com.google.common.base.MoreObjects
 import com.google.common.collect.ImmutableMap
 import com.google.common.collect.ImmutableSortedSet
+import com.google.common.collect.ImmutableList
 import java.util.ArrayList
 import java.util.Arrays
 import java.util.Collection
@@ -21,15 +24,19 @@ 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.model.api.ConcreteType
 import org.opendaylight.mdsal.binding.model.api.GeneratedProperty
 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject
 import org.opendaylight.mdsal.binding.model.api.GeneratedType
 import org.opendaylight.mdsal.binding.model.api.MethodSignature
 import org.opendaylight.mdsal.binding.model.api.Type
+import org.opendaylight.mdsal.binding.model.api.ParameterizedType
+import org.opendaylight.mdsal.binding.model.api.Restrictions
 import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl
 import org.opendaylight.mdsal.binding.model.util.Types
 import org.opendaylight.mdsal.binding.model.util.generated.type.builder.CodegenGeneratedTOBuilder
+import org.opendaylight.mdsal.binding.model.util.TypeConstants
 import org.opendaylight.yangtools.concepts.Builder
 import org.opendaylight.yangtools.yang.binding.Augmentable
 import org.opendaylight.yangtools.yang.binding.AugmentationHolder
@@ -229,6 +236,8 @@ class BuilderTemplate extends BaseTemplate {
 
             «generateFields(false)»
 
+            «constantsDeclarations()»
+
             «generateAugmentField(false)»
 
             «generateConstructorsFromIfcs(type)»
@@ -428,54 +437,125 @@ class BuilderTemplate extends BaseTemplate {
         «ENDIF»
     '''
 
+    def private constantsDeclarations() '''
+        «FOR c : type.getConstantDefinitions»
+            «IF c.getName.startsWith(TypeConstants.PATTERN_CONSTANT_NAME)»
+                «val cValue = c.value as Map<String, String>»
+                «val String fieldSuffix = c.getName.substring(TypeConstants.PATTERN_CONSTANT_NAME.length).toLowerCase»
+                public static final «List.importedName»<String> «c.getName» = «ImmutableList.importedName».of(
+                «FOR v : cValue.keySet SEPARATOR ", "»"«v.escapeJava»"«ENDFOR»);
+                «IF cValue.size == 1»
+                   private static final «Pattern.importedName» «Constants.MEMBER_PATTERN_LIST»«fieldSuffix» = «Pattern.importedName».compile(«c.getName».get(0));
+                   private static final String «Constants.MEMBER_REGEX_LIST»«fieldSuffix» = "«cValue.values.get(0).escapeJava»";
+                «ELSE»
+                   private static final «Pattern.importedName»[] «Constants.MEMBER_PATTERN_LIST»«fieldSuffix» = «CodeHelpers.importedName».compilePatterns(«c.getName»);
+                   private static final String[] «Constants.MEMBER_REGEX_LIST»«fieldSuffix» = { «
+                   FOR v : cValue.values SEPARATOR ", "»"«v.escapeJava»"«ENDFOR» };
+                «ENDIF»
+            «ELSE»
+                «emitConstant(c)»
+            «ENDIF»
+        «ENDFOR»
+    '''
+
+    def private generateCheckers(GeneratedProperty field, Restrictions restrictions, Type actualType) '''
+       «IF restrictions.rangeConstraint.present»
+           «AbstractRangeGenerator.forType(actualType).generateRangeChecker(field.name.toFirstUpper,
+               restrictions.rangeConstraint.get, this)»
+       «ENDIF»
+       «IF restrictions.lengthConstraint.present»
+           «LengthGenerator.generateLengthChecker(field.fieldName.toString, actualType, restrictions.lengthConstraint.get, this)»
+       «ENDIF»
+    '''
+
+    def private checkArgument(GeneratedProperty property, Restrictions restrictions, Type actualType) '''
+       «IF restrictions.getRangeConstraint.isPresent»
+           «IF actualType instanceof ConcreteType»
+               «AbstractRangeGenerator.forType(actualType).generateRangeCheckerCall(property.getName.toFirstUpper, "value")»
+           «ELSE»
+               «AbstractRangeGenerator.forType(actualType).generateRangeCheckerCall(property.getName.toFirstUpper, "value.getValue()")»
+           «ENDIF»
+       «ENDIF»
+       «IF restrictions.getLengthConstraint.isPresent»
+           «IF actualType instanceof ConcreteType»
+               «LengthGenerator.generateLengthCheckerCall(property.fieldName.toString, "value")»
+           «ELSE»
+               «LengthGenerator.generateLengthCheckerCall(property.fieldName.toString, "value.getValue()")»
+           «ENDIF»
+       «ENDIF»
+
+       «val fieldUpperCase = property.fieldName.toString.toUpperCase()»
+       «FOR currentConstant : type.getConstantDefinitions»
+           «IF currentConstant.getName.startsWith(TypeConstants.PATTERN_CONSTANT_NAME)
+               && fieldUpperCase.equals(currentConstant.getName.substring(TypeConstants.PATTERN_CONSTANT_NAME.length))»
+           «CodeHelpers.importedName».checkPattern(value, «Constants.MEMBER_PATTERN_LIST»«property.fieldName», «Constants.MEMBER_REGEX_LIST»«property.fieldName»);
+           «ENDIF»
+       «ENDFOR»
+    '''
+
+    def private Restrictions restrictionsForSetter(Type actualType) {
+        if (actualType instanceof GeneratedType) {
+            return null;
+        }
+        return actualType.restrictions;
+    }
+
+    def private generateListSetter(GeneratedProperty field, Type actualType) '''
+        «val restrictions = restrictionsForSetter(actualType)»
+        «IF restrictions !== null»
+            «generateCheckers(field, restrictions, actualType)»
+        «ENDIF»
+        public «type.getName»Builder set«field.getName.toFirstUpper»(final «field.returnType.importedName» values) {
+        «IF restrictions !== null»
+            if (values != null) {
+               for («actualType.getFullyQualifiedName» value : values) {
+                   «checkArgument(field, restrictions, actualType)»
+               }
+            }
+        «ENDIF»
+            this.«field.fieldName.toString» = values;
+            return this;
+        }
+
+    '''
+
+    def private generateSetter(GeneratedProperty field, Type actualType) '''
+        «val restrictions = restrictionsForSetter(actualType)»
+        «IF restrictions !== null»
+            «generateCheckers(field, restrictions, actualType)»
+        «ENDIF»
+
+        public «type.getName»Builder set«field.getName.toFirstUpper»(final «field.returnType.importedName» value) {
+        «IF restrictions !== null»
+            if (value != null) {
+                «checkArgument(field, restrictions, actualType)»
+            }
+        «ENDIF»
+            this.«field.fieldName.toString» = value;
+            return this;
+        }
+    '''
+
+    private def Type getActualType(ParameterizedType ptype) {
+        return ptype.getActualTypeArguments.get(0)
+    }
+
     /**
      * Template method which generates setter methods
      *
      * @return string with the setter methods
      */
     def private generateSetters() '''
-        «FOR field : properties SEPARATOR '\n'»
-             «/* FIXME: generate checkers as simple blocks and embed them directly in setters  */»
-             «val restrictions = field.returnType.restrictions»
-             «IF !(field.returnType instanceof GeneratedType) && restrictions !== null»
-                    «IF restrictions.rangeConstraint.present»
-                        «val rangeGenerator = AbstractRangeGenerator.forType(field.returnType)»
-                        «rangeGenerator.generateRangeChecker(field.name.toFirstUpper, restrictions.rangeConstraint.get, this)»
-
-                    «ENDIF»
-                    «IF restrictions.lengthConstraint.present»
-                    «LengthGenerator.generateLengthChecker(field.fieldName.toString, field.returnType, restrictions.lengthConstraint.get, this)»
-
-                    «ENDIF»
+        «FOR property : properties»
+            «IF property.returnType instanceof ParameterizedType
+                    && (property.returnType as ParameterizedType).rawType.equals(Types.LIST_TYPE)»
+                «generateListSetter(property, getActualType(property.returnType as ParameterizedType))»
+            «ELSE»
+                «generateSetter(property, property.returnType)»
             «ENDIF»
-            public «type.name»«BUILDER» set«field.name.toFirstUpper»(final «field.returnType.importedName» value) {
-            «IF !(field.returnType instanceof GeneratedType) && restrictions !== null»
-                «IF restrictions !== null && (restrictions.rangeConstraint.present || restrictions.lengthConstraint.present)»
-                if (value != null) {
-                    «IF restrictions.rangeConstraint.present»
-                        «val rangeGenerator = AbstractRangeGenerator.forType(field.returnType)»
-                        «IF field.returnType instanceof ConcreteType»
-                            «rangeGenerator.generateRangeCheckerCall(field.name.toFirstUpper, "value")»
-                        «ELSE»
-                            «rangeGenerator.generateRangeCheckerCall(field.name.toFirstUpper, "value.getValue()")»
-                        «ENDIF»
-                    «ENDIF»
-                    «IF restrictions.lengthConstraint.present»
-                        «IF field.returnType instanceof ConcreteType»
-                            «LengthGenerator.generateLengthCheckerCall(field.fieldName.toString, "value")»
-                         «ELSE»
-                            «LengthGenerator.generateLengthCheckerCall(field.fieldName.toString, "value.getValue()")»
-                        «ENDIF»
-                    «ENDIF»
-                }
-                «ENDIF»
-            «ENDIF»
-                this.«field.fieldName» = value;
-                return this;
-            }
         «ENDFOR»
-        «IF augmentField !== null»
 
+        «IF augmentField !== null»
             public «type.name»«BUILDER» add«augmentField.name.toFirstUpper»(«Class.importedName»<? extends «augmentField.returnType.importedName»> augmentationType, «augmentField.returnType.importedName» augmentationValue) {
                 if (augmentationValue == null) {
                     return remove«augmentField.name.toFirstUpper»(augmentationType);
@@ -706,7 +786,7 @@ class BuilderTemplate extends BaseTemplate {
                     «CodeHelpers.importedName».appendValue(helper, "«property.fieldName»", «property.fieldName»);
                 «ENDFOR»
                 «IF augmentField !== null»
-                    «CodeHelpers.importedName».appendValue(helper, "«augmentField.name»", «augmentField.name».values()); 
+                    «CodeHelpers.importedName».appendValue(helper, "«augmentField.name»", «augmentField.name».values());
                 «ENDIF»
                 return helper.toString();
             }
index f79213bb53f441d51cf0d0aa32eb7a449819d2f3..9b82cd1374709d3676acf9ebaa9f64a1768394f8 100644 (file)
@@ -280,7 +280,7 @@ class ClassTemplate extends BaseTemplate {
     }
 
     def private generateRestrictions(Type type, String paramName, Type returnType) '''
-        «val restrictions = type.getRestrictions»
+        «val restrictions = type.restrictions»
         «IF restrictions !== null»
             «IF restrictions.lengthConstraint.present || restrictions.rangeConstraint.present»
             if («paramName» != null) {
index 0e00bcdb59757c4b70116ac317ac05edc281e819..c6bfc35ec2edd91b591772c8e25876a95ad0e638 100644 (file)
@@ -18,15 +18,19 @@ final class Constants {
     public static final String DOT = ".";
 
     /**
-     * Name of the class constant which contains list of <code>Pattern</code> instances. The type of this constant
-     * is Pattern[] for more than one pattern, or Pattern if there is only a single one.
+     * Name or prefix (multiple patterns in builder class as composed with '_'
+     * and upper case of the field name) of the class constant which contains list
+     * of <code>Pattern</code> instances. The type of this constant is Pattern[]
+     * for more than one pattern, or Pattern if there is only a single one.
      */
     public static final String MEMBER_PATTERN_LIST = "patterns";
 
     /**
-     * Name of the class constant which contains a list of XSD regular expression strings. The type of this constant
-     * is String[] (or String for single strings) and it corresponds to {@link #MEMBER_PATTERN_LIST} in both size and
-     * ordering.
+     * Name or prefix (multiple patterns in builder class as composed with '_'
+     * and upper case of the field name) of the class constant which contains a list
+     * of XSD regular expression strings. The type of this constant is String[]
+     * (or String for single strings) and it corresponds to {@link #MEMBER_PATTERN_LIST}
+     * in both size and ordering.
      */
     public static final String MEMBER_REGEX_LIST = "regexes";
 
index 28f8adaee3c3e2c50f0983510bf5aad23f4cc47d..2d70587e06ac8d095be90b2c33c128a3bac1c188 100644 (file)
@@ -160,7 +160,7 @@ class InterfaceTemplate extends BaseTemplate {
     def private generateConstants() '''
         «IF !consts.empty»
             «FOR c : consts»
-                «IF c.name != TypeConstants.PATTERN_CONSTANT_NAME»
+                «IF !c.name.startsWith(TypeConstants.PATTERN_CONSTANT_NAME)»
                     «emitConstant(c)»
                 «ENDIF»
             «ENDFOR»
index 16f1b1df91e384c176b3bed2eefae9985fd06a15..c90ccaad3bb75e1c0441ed8f16e5c3fc02af2a61 100644 (file)
@@ -69,7 +69,7 @@ public class BuilderGeneratorTest {
         assertEquals("@Override\n" +
                 "public java.lang.String toString() {\n" +
                 "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n" +
-                "    CodeHelpers.appendValue(helper, \"augmentation\", augmentation.values()); \n" +
+                "    CodeHelpers.appendValue(helper, \"augmentation\", augmentation.values());\n" +
                 "    return helper.toString();\n" +
                 "}\n", genToString(mockAugment(mockGenType(TEST))).toString());
     }
@@ -80,7 +80,7 @@ public class BuilderGeneratorTest {
                 "public java.lang.String toString() {\n" +
                 "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n" +
                 "    CodeHelpers.appendValue(helper, \"_test\", _test);\n" +
-                "    CodeHelpers.appendValue(helper, \"augmentation\", augmentation.values()); \n" +
+                "    CodeHelpers.appendValue(helper, \"augmentation\", augmentation.values());\n" +
                 "    return helper.toString();\n" +
                 "}\n", genToString(mockAugment(mockGenType("get" + TEST))).toString());
     }
@@ -92,7 +92,7 @@ public class BuilderGeneratorTest {
                 "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n" +
                 "    CodeHelpers.appendValue(helper, \"_test1\", _test1);\n" +
                 "    CodeHelpers.appendValue(helper, \"_test2\", _test2);\n" +
-                "    CodeHelpers.appendValue(helper, \"augmentation\", augmentation.values()); \n" +
+                "    CodeHelpers.appendValue(helper, \"augmentation\", augmentation.values());\n" +
                 "    return helper.toString();\n" +
                 "}\n", genToString(mockAugment(mockGenTypeMoreMeth("get" + TEST))).toString());
     }
diff --git a/binding/mdsal-binding-test-model/src/main/yang/test-pattern.yang b/binding/mdsal-binding-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