From b14f88cf74dcf705cacc7b1351e00dfe65921c0b Mon Sep 17 00:00:00 2001 From: Jie Han Date: Tue, 30 Jan 2018 16:29:03 +0800 Subject: [PATCH] MDSAL-292: Binding v2 - Pattern attribute ignored for leaf-list/leaf - 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 --- .../javav2/generator/impl/GenHelperUtil.java | 21 ++++ .../generator/yang/types/TypeGenHelper.java | 19 ++- .../api/generator/renderers/BaseRenderer.java | 42 ++----- .../generator/renderers/BuilderRenderer.java | 69 +++++------ .../generator/renderers/ClassRenderer.java | 48 ++++---- .../renderers/InterfaceRenderer.java | 11 +- .../api/generator/builderTemplate.scala.txt | 108 ++++++++++++------ .../api/generator/constantsTemplate.scala.txt | 19 +-- .../src/main/yang/test-pattern.yang | 37 ++++++ 9 files changed, 237 insertions(+), 137 deletions(-) mode change 100644 => 100755 binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BuilderRenderer.java mode change 100644 => 100755 binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/builderTemplate.scala.txt create mode 100755 binding2/mdsal-binding2-test-model/src/main/yang/test-pattern.yang diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java index dc28d500fb..ee592c584d 100755 --- a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java +++ b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/impl/GenHelperUtil.java @@ -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 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 leaf to the getter method which is added to * typeBuilder. @@ -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); diff --git a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/yang/types/TypeGenHelper.java b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/yang/types/TypeGenHelper.java index 9e8f58a0ce..9eb1bdcf28 100755 --- a/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/yang/types/TypeGenHelper.java +++ b/binding2/mdsal-binding2-generator-impl/src/main/java/org/opendaylight/mdsal/binding/javav2/generator/yang/types/TypeGenHelper.java @@ -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 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 resolveRegExpressions(final List patternConstraints) { + if (patternConstraints.isEmpty()) { + return ImmutableMap.of(); + } + final Map regExps = Maps.newHashMapWithExpectedSize(patternConstraints.size()); for (PatternConstraint patternConstraint : patternConstraints) { String regEx = patternConstraint.getJavaPatternString(); diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BaseRenderer.java b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BaseRenderer.java index a35676bfa7..a246fc67d3 100644 --- a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BaseRenderer.java +++ b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BaseRenderer.java @@ -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 importMap; + /** + * list of all imported names for template + */ + private final Map 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 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 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 * diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BuilderRenderer.java b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BuilderRenderer.java old mode 100644 new mode 100755 index d2ef788708..e84cb680a3 --- a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BuilderRenderer.java +++ b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/BuilderRenderer.java @@ -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 importedNamesForProperties = new HashMap<>(); - /** - * list of all imported names for template - */ - private final Map 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 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) { diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/ClassRenderer.java b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/ClassRenderer.java index f0a99cae4d..e4900b8352 100644 --- a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/ClassRenderer.java +++ b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/ClassRenderer.java @@ -53,7 +53,7 @@ public class ClassRenderer extends BaseRenderer { private final List consts; private final List enclosedGeneratedTypes; private final List allProperties; - private final Map 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 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(); } /** diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/InterfaceRenderer.java b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/InterfaceRenderer.java index 63809dd7c9..0b11d400d4 100644 --- a/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/InterfaceRenderer.java +++ b/binding2/mdsal-binding2-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/javav2/java/api/generator/renderers/InterfaceRenderer.java @@ -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 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 innerClasses = new ArrayList<>(getType().getEnclosedTypes().size()); for (GeneratedType innerClass : getType().getEnclosedTypes()) { diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/builderTemplate.scala.txt b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/builderTemplate.scala.txt old mode 100644 new mode 100755 index f9c732b612..5a74bdb55f --- a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/builderTemplate.scala.txt +++ b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/builderTemplate.scala.txt @@ -20,24 +20,29 @@ @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")} 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) { diff --git a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/constantsTemplate.scala.txt b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/constantsTemplate.scala.txt index dc68bb43a7..f9093b0cd8 100644 --- a/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/constantsTemplate.scala.txt +++ b/binding2/mdsal-binding2-java-api-generator/src/main/twirl/org/opendaylight/mdsal/binding/javav2/java/api/generator/constantsTemplate.scala.txt @@ -15,22 +15,23 @@ @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 index 0000000000..43f7f16aef --- /dev/null +++ b/binding2/mdsal-binding2-test-model/src/main/yang/test-pattern.yang @@ -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 -- 2.36.6