From 8b71c6e0f1e0531cbc17183a0dfe133d3598abe5 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sat, 16 Oct 2021 15:16:03 +0200 Subject: [PATCH 1/1] Migrate ConfigTypeProvider tests There are a few remaining tests, migrate them and inhume AbstractTypeProvider et al. Change-Id: I1aa96547dfa67ef7dc48f8ef948656fab0405ca4 Signed-off-by: Robert Varga --- .../yang/types/AbstractTypeProvider.java | 927 ------------------ .../yang/types/CodegenTypeProvider.java | 114 --- .../binding/yang/types/TypedefResolver.java | 68 -- .../impl/DefaultBindingGeneratorTest.java | 109 +- .../binding/yang/types/TypeProviderTest.java | 202 ---- 5 files changed, 88 insertions(+), 1332 deletions(-) delete mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java delete mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/CodegenTypeProvider.java delete mode 100644 binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/TypedefResolver.java delete mode 100644 binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/yang/types/TypeProviderTest.java diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java deleted file mode 100644 index 23c177d872..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java +++ /dev/null @@ -1,927 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.mdsal.binding.yang.types; - -import static java.util.Objects.requireNonNull; -import static org.opendaylight.mdsal.binding.model.ri.BindingTypes.TYPE_OBJECT; - -import com.google.common.base.CharMatcher; -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.TreeMap; -import org.opendaylight.mdsal.binding.generator.BindingGeneratorUtil; -import org.opendaylight.mdsal.binding.generator.impl.reactor.SerialVersionHelper; -import org.opendaylight.mdsal.binding.model.api.AccessModifier; -import org.opendaylight.mdsal.binding.model.api.ConcreteType; -import org.opendaylight.mdsal.binding.model.api.Enumeration; -import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject; -import org.opendaylight.mdsal.binding.model.api.GeneratedType; -import org.opendaylight.mdsal.binding.model.api.JavaTypeName; -import org.opendaylight.mdsal.binding.model.api.Restrictions; -import org.opendaylight.mdsal.binding.model.api.Type; -import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder; -import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder; -import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder; -import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase; -import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder; -import org.opendaylight.mdsal.binding.model.ri.BaseYangTypes; -import org.opendaylight.mdsal.binding.model.ri.BindingTypes; -import org.opendaylight.mdsal.binding.model.ri.TypeConstants; -import org.opendaylight.mdsal.binding.model.ri.Types; -import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.AbstractEnumerationBuilder; -import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.GeneratedPropertyBuilderImpl; -import org.opendaylight.mdsal.binding.spec.naming.BindingMapping; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.Revision; -import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.api.SchemaNode; -import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.opendaylight.yangtools.yang.model.api.Status; -import org.opendaylight.yangtools.yang.model.api.TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit; -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.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.spi.ModuleDependencySort; - -// FIXME: remove this class -@Deprecated(forRemoval = true) -abstract class AbstractTypeProvider { - private static final JavaTypeName DEPRECATED_ANNOTATION = JavaTypeName.create(Deprecated.class); - private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:"); - - /** - * Contains the schema data red from YANG files. - */ - private final SchemaContext schemaContext; - - private final Map, Map>> genTypeDefsContextMap = - new HashMap<>(); - private final Map> additionalTypes = new HashMap<>(); - - /** - * Creates new instance of class TypeProviderImpl. - * - * @param schemaContext contains the schema data red from YANG files - * @param renames renaming table - * @throws IllegalArgumentException if schemaContext equal null. - */ - AbstractTypeProvider(final EffectiveModelContext schemaContext) { - this.schemaContext = requireNonNull(schemaContext); - - resolveTypeDefsFromContext(); - } - - /** - * Resolve of YANG Type Definition to it's java counter part. If the Type Definition contains one of YANG primitive - * types the method will return {@code java.lang.} counterpart. (For example if YANG type is int32 the Java - * counterpart is {@link Integer}). In case that Type Definition contains extended type defined via YANG typedef - * statement the method SHOULD return Generated Type or Generated Transfer Object if that Type is correctly - * referenced to resolved imported YANG module. - * - *

- * The method will return null value in situations that TypeDefinition can't be resolved (either due - * to missing YANG import or incorrectly specified type). - * - *

- * {@code leafref} resolution for relative paths has two models of operation: lenient and strict. This is needed to - * handle the case where a grouping leaf's path points outside of the grouping tree. In such a case we cannot - * completely determine the correct type and need to fallback to {@link Object}. - * - * @param type Type Definition to resolve from - * @param lenientRelativeLeafrefs treat relative leafrefs leniently - * @return Resolved Type - */ - public Type javaTypeForSchemaDefinitionType(final TypeDefinition type, final SchemaNode parentNode) { - return javaTypeForSchemaDefinitionType(type, parentNode, null); - } - - /** - * Converts schema definition type typeDefinition to JAVA Type. - * - * @param typeDefinition type definition which is converted to JAVA type - * @throws IllegalArgumentException - *

    - *
  • if typeDefinition equal null
  • - *
  • if Qname of typeDefinition equal null
  • - *
  • if name of typeDefinition equal null
  • - *
- */ - public Type javaTypeForSchemaDefinitionType(final TypeDefinition typeDefinition, final SchemaNode parentNode, - final Restrictions restrictions) { - throw new UnsupportedOperationException(); - } - - /** - * Gets base type definition for extendTypeDef. The method is - * recursively called until non ExtendedType type is found. - * - * @param extendTypeDef - * type definition for which is the base type definition sought - * @return type definition which is base type for extendTypeDef - * @throws IllegalArgumentException - * if extendTypeDef equal null - */ - private static TypeDefinition baseTypeDefForExtendedType(final TypeDefinition extendTypeDef) { - Preconditions.checkArgument(extendTypeDef != null, "Type Definition reference cannot be NULL!"); - - TypeDefinition ret = extendTypeDef; - while (ret.getBaseType() != null) { - ret = ret.getBaseType(); - } - - return ret; - } - - /** - * Converts enumTypeDef to {@link Enumeration enumeration}. - * - * @param enumTypeDef enumeration type definition which is converted to enumeration - * @param enumName string with name which is used as the enumeration name - * @return enumeration type which is built with data (name, enum values) from enumTypeDef - * @throws IllegalArgumentException - *
    - *
  • if enumTypeDef equals null
  • - *
  • if enum values of enumTypeDef equal null
  • - *
  • if Q name of enumTypeDef equal null
  • - *
  • if name of enumTypeDef equal null
  • - *
- */ - private Enumeration provideTypeForEnum(final EnumTypeDefinition enumTypeDef, final String enumName, - final SchemaNode parentNode) { - Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!"); - Preconditions.checkArgument(enumTypeDef.getValues() != null, - "EnumTypeDefinition MUST contain at least ONE value definition!"); - Preconditions.checkArgument(enumTypeDef.getQName() != null, "EnumTypeDefinition MUST contain NON-NULL QName!"); - Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null, - "Local Name in EnumTypeDefinition QName cannot be NULL!"); - - final Module module = findParentModule(schemaContext, parentNode); - final AbstractEnumerationBuilder enumBuilder = newEnumerationBuilder(JavaTypeName.create( - BindingMapping.getRootPackageName(module.getQNameModule()), BindingMapping.getClassName(enumName))); - addEnumDescription(enumBuilder, enumTypeDef); - enumTypeDef.getReference().ifPresent(enumBuilder::setReference); - enumBuilder.setModuleName(module.getName()); - enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef); - return enumBuilder.toInstance(); - } - - /** - * Adds enumeration to typeBuilder. The enumeration data are taken from enumTypeDef. - * - * @param enumTypeDef enumeration type definition is source of enumeration data for typeBuilder - * @param enumName string with the name of enumeration - * @param typeBuilder generated type builder to which is enumeration added - * @return enumeration type which contains enumeration data form enumTypeDef - * @throws IllegalArgumentException - *
    - *
  • if enumTypeDef equals null
  • - *
  • if enum values of enumTypeDef equal null
  • - *
  • if Q name of enumTypeDef equal null
  • - *
  • if name of enumTypeDef equal null
  • - *
  • if name of typeBuilder equal null
  • - *
- * - */ - private Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, - final String enumName, final GeneratedTypeBuilderBase typeBuilder) { - Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!"); - Preconditions.checkArgument(enumTypeDef.getValues() != null, - "EnumTypeDefinition MUST contain at least ONE value definition!"); - Preconditions.checkArgument(enumTypeDef.getQName() != null, "EnumTypeDefinition MUST contain NON-NULL QName!"); - Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null, - "Local Name in EnumTypeDefinition QName cannot be NULL!"); - Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!"); - - final EnumBuilder enumBuilder = newEnumerationBuilder( - typeBuilder.getIdentifier().createEnclosed(BindingMapping.getClassName(enumName), "$")); - addEnumDescription(enumBuilder, enumTypeDef); - enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef); - final Enumeration ret = enumBuilder.toInstance(); - typeBuilder.addEnumeration(ret); - - return ret; - } - - public abstract void addEnumDescription(EnumBuilder enumBuilder, EnumTypeDefinition enumTypeDef); - - public abstract AbstractEnumerationBuilder newEnumerationBuilder(JavaTypeName identifier); - - public abstract GeneratedTOBuilder newGeneratedTOBuilder(JavaTypeName identifier); - - /** - * 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 resolveRegExpressions(List patternConstraints); - - abstract void addCodegenInformation(GeneratedTypeBuilderBase genTOBuilder, TypeDefinition typeDef); - - /** - * Converts the pattern constraints from typedef to the list of the strings which represents these - * constraints. - * - * @param typedef extended type in which are the pattern constraints sought - * @return list of strings which represents the constraint patterns - * @throws IllegalArgumentException if typedef equals null - * - */ - private Map resolveRegExpressionsFromTypedef(final TypeDefinition typedef) { - if (!(typedef instanceof StringTypeDefinition)) { - return ImmutableMap.of(); - } - - // TODO: run diff against base ? - return resolveRegExpressions(((StringTypeDefinition) typedef).getPatternConstraints()); - } - - /** - * Passes through all modules and through all its type definitions and convert it to generated types. - * - *

- * The modules are first sorted by mutual dependencies. The modules are sequentially passed. All type definitions - * of a module are at the beginning sorted so that type definition with less amount of references to other type - * definition are processed first.
- * For each module is created mapping record in the map - * {@link AbstractTypeProvider#genTypeDefsContextMap genTypeDefsContextMap} - * which map current module name to the map which maps type names to returned types (generated types). - */ - private void resolveTypeDefsFromContext() { - final List modulesSortedByDependency = ModuleDependencySort.sort(schemaContext.getModules()); - - for (Module module : modulesSortedByDependency) { - Map, Map> dateTypeMap = genTypeDefsContextMap.computeIfAbsent( - module.getName(), key -> new HashMap<>()); - dateTypeMap.put(module.getRevision(), Collections.emptyMap()); - genTypeDefsContextMap.put(module.getName(), dateTypeMap); - } - - for (Module module : modulesSortedByDependency) { - if (module != null) { - final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); - if (basePackageName != null) { - final List> typeDefinitions = TypedefResolver.getAllTypedefs(module); - for (TypeDefinition typedef : sortTypeDefinitionAccordingDepth(typeDefinitions)) { - typedefToGeneratedType(basePackageName, module, typedef); - } - } - } - } - } - - /** - * Create Type for specified type definition. - * - * @param basePackageName string with name of package to which the module belongs - * @param module string with the name of the module for to which the typedef belongs - * @param typedef type definition of the node for which should be created JAVA Type - * (usually generated TO) - * @return JAVA Type representation of typedef or - * null value if basePackageName or - * modulName or typedef or Q name of - * typedef equals null - */ - private Type typedefToGeneratedType(final String basePackageName, final Module module, - final TypeDefinition typedef) { - final TypeDefinition baseTypedef = typedef.getBaseType(); - - // See generatedTypeForExtendedDefinitionType() above for rationale behind this special case. - if (baseTypedef instanceof LeafrefTypeDefinition || baseTypedef instanceof IdentityrefTypeDefinition) { - return null; - } - - final String typedefName = typedef.getQName().getLocalName(); - - final GeneratedType returnType; - if (baseTypedef.getBaseType() != null) { - returnType = provideGeneratedTOFromExtendedType(typedef, baseTypedef, basePackageName, - module.getName()); - } else if (baseTypedef instanceof UnionTypeDefinition) { - final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef( - JavaTypeName.create(basePackageName, BindingMapping.getClassName(typedef.getQName())), - (UnionTypeDefinition) baseTypedef, typedef); - genTOBuilder.setTypedef(true); - genTOBuilder.setIsUnion(true); - addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null)); - makeSerializable(genTOBuilder); - returnType = genTOBuilder.build(); - - // Define a corresponding union builder. Typedefs are always anchored at a Java package root, - // so we are placing the builder alongside the union. - final GeneratedTOBuilder unionBuilder = newGeneratedTOBuilder(JavaTypeName.create( - genTOBuilder.getPackageName(), genTOBuilder.getName() + BindingMapping.BUILDER_SUFFIX)); - unionBuilder.setIsUnionBuilder(true); - final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance"); - method.setReturnType(returnType); - method.addParameter(Types.STRING, "defaultValue"); - method.setAccessModifier(AccessModifier.PUBLIC); - method.setStatic(true); - additionalTypes.computeIfAbsent(module, key -> new HashSet<>()).add(unionBuilder.build()); - } else if (baseTypedef instanceof EnumTypeDefinition) { - // enums are automatically Serializable - final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypedef; - // TODO units for typedef enum - returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef); - } else if (baseTypedef instanceof BitsTypeDefinition) { - final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForBitsTypeDefinition( - JavaTypeName.create(basePackageName, BindingMapping.getClassName(typedef.getQName())), - (BitsTypeDefinition) baseTypedef, module.getName()); - genTOBuilder.setTypedef(true); - addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null)); - makeSerializable(genTOBuilder); - returnType = genTOBuilder.build(); - } else { - final Type javaType = javaTypeForSchemaDefinitionType(baseTypedef, typedef); - returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName()); - } - if (returnType != null) { - final Map, Map> modulesByDate = - genTypeDefsContextMap.get(module.getName()); - final Optional moduleRevision = module.getRevision(); - Map typeMap = modulesByDate.get(moduleRevision); - if (typeMap != null) { - if (typeMap.isEmpty()) { - typeMap = new HashMap<>(4); - modulesByDate.put(moduleRevision, typeMap); - } - typeMap.put(typedefName, returnType); - } - return returnType; - } - return null; - } - - /** - * Wraps base YANG type to generated TO. - * - * @param basePackageName string with name of package to which the module belongs - * @param typedef type definition which is converted to the TO - * @param javaType JAVA Type to which is typedef mapped - * @return generated transfer object which representjavaType - */ - private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition typedef, - final Type javaType, final String moduleName) { - requireNonNull(javaType, "javaType cannot be null"); - - final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef, moduleName); - genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef)); - final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(TypeConstants.VALUE_PROP); - genPropBuilder.setReturnType(javaType); - - genTOBuilder.addEqualsIdentity(genPropBuilder); - genTOBuilder.addHashIdentity(genPropBuilder); - genTOBuilder.addToStringProperty(genPropBuilder); - genTOBuilder.addImplementsType(BindingTypes.scalarTypeObject(javaType)); - if (typedef.getStatus() == Status.DEPRECATED) { - genTOBuilder.addAnnotation(DEPRECATED_ANNOTATION); - } - if (javaType instanceof ConcreteType && "String".equals(javaType.getName()) && typedef.getBaseType() != null) { - addStringRegExAsConstant(genTOBuilder, resolveRegExpressionsFromTypedef(typedef)); - } - addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null)); - genTOBuilder.setTypedef(true); - makeSerializable(genTOBuilder); - return genTOBuilder.build(); - } - - /** - * Converts output list of generated TO builders to one TO builder (first - * from list) which contains the remaining builders as its enclosing TO. - * - * @param typeName new type identifier - * @param typedef type definition which should be of type {@link UnionTypeDefinition} - * @return generated TO builder with the list of enclosed generated TO builders - */ - private GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final JavaTypeName typeName, - final UnionTypeDefinition typedef, final TypeDefinition parentNode) { - final List builders = provideGeneratedTOBuildersForUnionTypeDef(typeName, typedef, - parentNode); - Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef); - - final GeneratedTOBuilder resultTOBuilder = builders.remove(0); - builders.forEach(builder -> resultTOBuilder.addEnclosingTransferObject(builder.build())); - return resultTOBuilder; - } - - /** - * Converts typedef to generated TO with typeDefName. Every union type from - * typedef is added to generated TO builder as property. - * - * @param typeName new type identifier - * @param typedef type definition which should be of type UnionTypeDefinition - * @return generated TO builder which represents typedef - * @throws NullPointerException - *

    - *
  • if basePackageName is null
  • - *
  • if typedef is null
  • - *
  • if Qname of typedef is null
  • - *
- */ - private List provideGeneratedTOBuildersForUnionTypeDef(final JavaTypeName typeName, - final UnionTypeDefinition typedef, final SchemaNode parentNode) { - requireNonNull(typedef, "Type Definition cannot be NULL!"); - requireNonNull(typedef.getQName(), "Type definition QName cannot be NULL!"); - - final List generatedTOBuilders = new ArrayList<>(); - final List> unionTypes = typedef.getTypes(); - final Module module = findParentModule(schemaContext, parentNode); - - final GeneratedTOBuilder unionGenTOBuilder = newGeneratedTOBuilder(typeName); - unionGenTOBuilder.setIsUnion(true); - unionGenTOBuilder.setSchemaPath(typedef.getPath()); - unionGenTOBuilder.setModuleName(module.getName()); - unionGenTOBuilder.addImplementsType(TYPE_OBJECT); - addCodegenInformation(unionGenTOBuilder, typedef); - generatedTOBuilders.add(unionGenTOBuilder); - - // Pattern string is the key, XSD regex is the value. The reason for this choice is that the pattern carries - // also negation information and hence guarantees uniqueness. - final Map expressions = new HashMap<>(); - for (TypeDefinition unionType : unionTypes) { - final String unionTypeName = unionType.getQName().getLocalName(); - - // If we have a base type we should follow the type definition backwards, except for identityrefs, as those - // do not follow type encapsulation -- we use the general case for that. - if (unionType.getBaseType() != null && !(unionType instanceof IdentityrefTypeDefinition)) { - resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, expressions, parentNode); - } else if (unionType instanceof UnionTypeDefinition) { - generatedTOBuilders.addAll(resolveUnionSubtypeAsUnion(unionGenTOBuilder, - (UnionTypeDefinition) unionType, parentNode)); - } else if (unionType instanceof EnumTypeDefinition) { - final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType, - unionTypeName, unionGenTOBuilder); - updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName); - } else { - final Type javaType = javaTypeForSchemaDefinitionType(unionType, parentNode); - updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName); - } - } - addStringRegExAsConstant(unionGenTOBuilder, expressions); - - storeGenTO(typedef, unionGenTOBuilder, parentNode); - - return generatedTOBuilders; - } - - /** - * Wraps code which handles the case when union subtype is also of the type UnionType. - * - *

- * In this case the new generated TO is created for union subtype (recursive call of method - * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition, String, SchemaNode)} - * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder parentUnionGenTOBuilder is - * created property which type is equal to new generated TO. - * - * @param parentUnionGenTOBuilder generated TO builder to which is the property with the child union subtype added - * @param basePackageName string with the name of the module package - * @param unionSubtype type definition which represents union subtype - * @return list of generated TO builders. The number of the builders can be bigger one due to recursive call of - * provideGeneratedTOBuildersForUnionTypeDef method. - */ - private List resolveUnionSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder, - final UnionTypeDefinition unionSubtype, final SchemaNode parentNode) { - final JavaTypeName newTOBuilderName = parentUnionGenTOBuilder.getIdentifier().createSibling( - provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName())); - final List subUnionGenTOBUilders = provideGeneratedTOBuildersForUnionTypeDef( - newTOBuilderName, unionSubtype, parentNode); - - final GeneratedPropertyBuilder propertyBuilder; - propertyBuilder = parentUnionGenTOBuilder.addProperty(BindingMapping.getPropertyName( - newTOBuilderName.simpleName())); - propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0).build()); - parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder); - parentUnionGenTOBuilder.addToStringProperty(propertyBuilder); - - return subUnionGenTOBUilders; - } - - /** - * Wraps code which handle case when union subtype is of the type ExtendedType. If TO for this type - * already exists it is used for the creation of the property in parentUnionGenTOBuilder. Otherwise - * the base type is used for the property creation. - * - * @param parentUnionGenTOBuilder generated TO builder in which new property is created - * @param unionSubtype type definition of the ExtendedType type which represents union subtype - * @param expressions list of strings with the regular expressions - * @param parentNode parent Schema Node for Extended Subtype - */ - private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder, - final TypeDefinition unionSubtype, final Map expressions, final SchemaNode parentNode) { - final String unionTypeName = unionSubtype.getQName().getLocalName(); - final Type genTO = findGenTO(unionTypeName, unionSubtype); - if (genTO != null) { - updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, genTO.getName()); - return; - } - - final TypeDefinition baseType = baseTypeDefForExtendedType(unionSubtype); - if (unionTypeName.equals(baseType.getQName().getLocalName())) { - final Type javaType = baseJavaTypeForSchema(baseType, parentNode, - BindingGeneratorUtil.getRestrictions(unionSubtype)); - if (javaType != null) { - updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName); - } - } else if (baseType instanceof LeafrefTypeDefinition) { - final Type javaType = javaTypeForSchemaDefinitionType(baseType, parentNode); - boolean typeExist = false; - for (GeneratedPropertyBuilder generatedPropertyBuilder : parentUnionGenTOBuilder.getProperties()) { - final Type origType = ((GeneratedPropertyBuilderImpl) generatedPropertyBuilder).getReturnType(); - if (origType != null && javaType != null && javaType == origType) { - typeExist = true; - break; - } - } - if (!typeExist && javaType != null) { - updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, - BindingMapping.getUnionLeafrefMemberName(parentUnionGenTOBuilder.getName(), javaType.getName())); - } - } - if (baseType instanceof StringTypeDefinition) { - expressions.putAll(resolveRegExpressionsFromTypedef(unionSubtype)); - } - } - - private static Type baseJavaTypeForSchema(final TypeDefinition type, final SchemaNode parentNode, - final Restrictions restrictions) { - final String typeName = type.getQName().getLocalName(); - final Type mapped = BaseYangTypes.javaTypeForYangType(typeName); - return mapped == null || restrictions == null ? mapped : Types.restrictedType(mapped, restrictions); - } - - /** - * Searches for generated TO for searchedTypeDef type definition - * in {@link #genTypeDefsContextMap genTypeDefsContextMap}. - * - * @param searchedTypeName string with name of searchedTypeDef - * @return generated TO for searchedTypeDef or null it it doesn't exist - */ - private Type findGenTO(final String searchedTypeName, final SchemaNode parentNode) { - final Module typeModule = findParentModule(schemaContext, parentNode); - if (typeModule != null && typeModule.getName() != null) { - final Map, Map> modulesByDate = genTypeDefsContextMap.get( - typeModule.getName()); - final Map genTOs = modulesByDate.get(typeModule.getRevision()); - if (genTOs != null) { - return genTOs.get(searchedTypeName); - } - } - return null; - } - - /** - * Stores generated TO created from genTOBuilder for newTypeDef - * to {@link #genTypeDefsContextMap genTypeDefsContextMap} if the module for newTypeDef exists. - * - * @param newTypeDef type definition for which is genTOBuilder created - * @param genTOBuilder generated TO builder which is converted to generated TO and stored - */ - private void storeGenTO(final TypeDefinition newTypeDef, final GeneratedTOBuilder genTOBuilder, - final SchemaNode parentNode) { - if (!(newTypeDef instanceof UnionTypeDefinition)) { - final Module parentModule = findParentModule(schemaContext, parentNode); - if (parentModule != null && parentModule.getName() != null) { - final Map, Map> modulesByDate = genTypeDefsContextMap.get( - parentModule.getName()); - final Map genTOsMap = modulesByDate.get(parentModule.getRevision()); - genTOsMap.put(newTypeDef.getQName().getLocalName(), genTOBuilder.build()); - } - } - } - - /** - * Adds a new property with the name propertyName and with type type - * to unonGenTransObject. - * - * @param unionGenTransObject generated TO to which should be property added - * @param type JAVA type of the property which should be added to unionGentransObject - * @param propertyName string with name of property which should be added to unionGentransObject - */ - private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, - final String propertyName) { - if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) { - final GeneratedPropertyBuilder propBuilder = unionGenTransObject - .addProperty(BindingMapping.getPropertyName(propertyName)); - propBuilder.setReturnType(type); - - unionGenTransObject.addEqualsIdentity(propBuilder); - unionGenTransObject.addHashIdentity(propBuilder); - unionGenTransObject.addToStringProperty(propBuilder); - } - } - - /** - * Converts typedef to the generated TO builder. - * - * @param basePackageName string with name of package to which the module belongs - * @param typedef type definition from which is the generated TO builder created - * @return generated TO builder which contains data from typedef and basePackageName - */ - private GeneratedTOBuilder typedefToTransferObject(final String basePackageName, - final TypeDefinition typedef, final String moduleName) { - final JavaTypeName name = JavaTypeName.create( - packageNameForGeneratedType(basePackageName, typedef.getPath()), - BindingMapping.getClassName(typedef.getQName().getLocalName())); - - final GeneratedTOBuilder newType = newGeneratedTOBuilder(name); - newType.setSchemaPath(typedef.getPath()); - newType.setModuleName(moduleName); - addCodegenInformation(newType, typedef); - return newType; - } - - /** - * Creates package name from specified basePackageName (package name for module) - * and schemaPath. Resulting package name is concatenation of basePackageName - * and all local names of YANG nodes which are parents of some node for which schemaPath is specified. - * - * @param basePackageName string with package name of the module, MUST be normalized, otherwise this method may - * return an invalid string. - * @param schemaPath list of names of YANG nodes which are parents of some node + name of this node - * @return string with valid JAVA package name - * @throws NullPointerException if any of the arguments are null - */ - private static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) { - final int size = Iterables.size(schemaPath.getPathTowardsRoot()) - 1; - if (size <= 0) { - return basePackageName; - } - - return generateNormalizedPackageName(basePackageName, schemaPath.getPathFromRoot(), size); - } - - private static String generateNormalizedPackageName(final String base, final Iterable path, final int size) { - final StringBuilder builder = new StringBuilder(base); - final Iterator iterator = path.iterator(); - for (int i = 0; i < size; ++i) { - builder.append('.'); - final String nodeLocalName = iterator.next().getLocalName(); - // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement. - builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.')); - } - return BindingMapping.normalizePackageName(builder.toString()); - } - - /** - * Converts typeDef which should be of the type BitsTypeDefinition - * to GeneratedTOBuilder. All the bits of the typeDef are added to returning generated TO as - * properties. - * - * @param typeName new type identifier - * @param typeDef type definition from which is the generated TO builder created - * @return generated TO builder which represents typeDef - * @throws IllegalArgumentException - *

    - *
  • if typeDef equals null
  • - *
  • if basePackageName equals null
  • - *
- */ - private GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final JavaTypeName typeName, - final BitsTypeDefinition typeDef, final String moduleName) { - final GeneratedTOBuilder genTOBuilder = newGeneratedTOBuilder(typeName); - genTOBuilder.setSchemaPath(typeDef.getPath()); - genTOBuilder.setModuleName(moduleName); - genTOBuilder.setBaseType(typeDef); - genTOBuilder.addImplementsType(TYPE_OBJECT); - addCodegenInformation(genTOBuilder, typeDef); - - for (Bit bit : typeDef.getBits()) { - final String name = bit.getName(); - GeneratedPropertyBuilder genPropertyBuilder = genTOBuilder.addProperty( - BindingMapping.getPropertyName(name)); - genPropertyBuilder.setReadOnly(true); - genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE); - - genTOBuilder.addEqualsIdentity(genPropertyBuilder); - genTOBuilder.addHashIdentity(genPropertyBuilder); - genTOBuilder.addToStringProperty(genPropertyBuilder); - } - - return genTOBuilder; - } - - /** - * Adds to the genTOBuilder the constant which contains regular expressions from - * the regularExpressions. - * - * @param genTOBuilder generated TO builder to which are regular expressions added - * @param expressions list of string which represent regular expressions - */ - private static void addStringRegExAsConstant(final GeneratedTOBuilder genTOBuilder, - final Map expressions) { - if (!expressions.isEmpty()) { - genTOBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), TypeConstants.PATTERN_CONSTANT_NAME, - ImmutableMap.copyOf(expressions)); - } - } - - /** - * Creates generated TO with data about inner extended type innerExtendedType, about the package name - * typedefName and about the generated TO name typedefName. - * - *

- * It is assumed that innerExtendedType is already present in - * {@link AbstractTypeProvider#genTypeDefsContextMap genTypeDefsContextMap} to be possible set it as extended type - * for the returning generated TO. - * - * @param typedef Type Definition - * @param innerExtendedType extended type which is part of some other extended type - * @param basePackageName string with the package name of the module - * @param moduleName Module Name - * @return generated TO which extends generated TO for innerExtendedType - * @throws IllegalArgumentException - *

    - *
  • if extendedType equals null
  • - *
  • if basePackageName equals null
  • - *
  • if typedefName equals null
  • - *
- */ - private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition typedef, - final TypeDefinition innerExtendedType, final String basePackageName, final String moduleName) { - Preconditions.checkArgument(innerExtendedType != null, "Extended type cannot be NULL!"); - Preconditions.checkArgument(basePackageName != null, "String with base package name cannot be NULL!"); - - final GeneratedTOBuilder genTOBuilder = newGeneratedTOBuilder(JavaTypeName.create(basePackageName, - BindingMapping.getClassName(typedef.getQName()))); - genTOBuilder.setSchemaPath(typedef.getPath()); - genTOBuilder.setModuleName(moduleName); - genTOBuilder.setTypedef(true); - addCodegenInformation(genTOBuilder, typedef); - - final Restrictions r = BindingGeneratorUtil.getRestrictions(typedef); - genTOBuilder.setRestrictions(r); - addStringRegExAsConstant(genTOBuilder, resolveRegExpressionsFromTypedef(typedef)); - - if (typedef.getStatus() == Status.DEPRECATED) { - genTOBuilder.addAnnotation(DEPRECATED_ANNOTATION); - } - - if (baseTypeDefForExtendedType(innerExtendedType) instanceof UnionTypeDefinition) { - genTOBuilder.setIsUnion(true); - } - - Map, Map> modulesByDate = null; - Map typeMap = null; - final Module parentModule = findParentModule(schemaContext, innerExtendedType); - if (parentModule != null) { - modulesByDate = genTypeDefsContextMap.get(parentModule.getName()); - typeMap = modulesByDate.get(parentModule.getRevision()); - } - - if (typeMap != null) { - final String innerTypeDef = innerExtendedType.getQName().getLocalName(); - final GeneratedType type = typeMap.get(innerTypeDef); - if (type instanceof GeneratedTransferObject) { - genTOBuilder.setExtendsType((GeneratedTransferObject) type); - } - } - addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null)); - makeSerializable(genTOBuilder); - - return genTOBuilder.build(); - } - - /** - * Add {@link java.io.Serializable} to implemented interfaces of this TO. Also compute and add serialVersionUID - * property. - * - * @param gto transfer object which needs to be made serializable - */ - private static void makeSerializable(final GeneratedTOBuilder gto) { - gto.addImplementsType(Types.serializableType()); - final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID"); - prop.setValue(Long.toString(SerialVersionHelper.computeDefaultSUID(gto))); - gto.setSUID(prop); - } - - /** - * Finds out for each type definition how many immersion (depth) is necessary to get to the base type. Every type - * definition is inserted to the map which key is depth and value is list of type definitions with equal depth. - * In next step are lists from this map concatenated to one list in ascending order according to their depth. All - * type definitions are in the list behind all type definitions on which depends. - * - * @param unsortedTypeDefinitions list of type definitions which should be sorted by depth - * @return list of type definitions sorted according their each other dependencies (type definitions which are - * dependent on other type definitions are in list behind them). - */ - private static List> sortTypeDefinitionAccordingDepth( - final Collection> unsortedTypeDefinitions) { - final List> sortedTypeDefinition = new ArrayList<>(); - - final Map>> typeDefinitionsDepths = new TreeMap<>(); - for (TypeDefinition unsortedTypeDefinition : unsortedTypeDefinitions) { - final Integer depth = getTypeDefinitionDepth(unsortedTypeDefinition); - List> typeDefinitionsConcreteDepth = - typeDefinitionsDepths.computeIfAbsent(depth, k -> new ArrayList<>()); - typeDefinitionsConcreteDepth.add(unsortedTypeDefinition); - } - - // SortedMap guarantees order corresponding to keys in ascending order - for (List> v : typeDefinitionsDepths.values()) { - sortedTypeDefinition.addAll(v); - } - - return sortedTypeDefinition; - } - - /** - * Returns how many immersion is necessary to get from the type definition to the base type. - * - * @param typeDefinition type definition for which is depth sought. - * @return number of immersions which are necessary to get from the type definition to the base type - */ - private static int getTypeDefinitionDepth(final TypeDefinition typeDefinition) { - // FIXME: rewrite this in a non-recursive manner - if (typeDefinition == null) { - return 1; - } - final TypeDefinition baseType = typeDefinition.getBaseType(); - if (baseType == null) { - return 1; - } - - int depth = 1; - if (baseType.getBaseType() != null) { - depth = depth + getTypeDefinitionDepth(baseType); - } else if (baseType instanceof UnionTypeDefinition) { - final List> childTypeDefinitions = ((UnionTypeDefinition) baseType).getTypes(); - int maxChildDepth = 0; - int childDepth = 1; - for (TypeDefinition childTypeDefinition : childTypeDefinitions) { - childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition); - if (childDepth > maxChildDepth) { - maxChildDepth = childDepth; - } - } - return maxChildDepth; - } - return depth; - } - - /** - * Returns string which contains the same value as name but integer suffix is incremented by one. If - * name contains no number suffix, a new suffix initialized at 1 is added. A suffix is actually - * composed of a '$' marker, which is safe, as no YANG identifier can contain '$', and a unsigned decimal integer. - * - * @param name string with name of augmented node - * @return string with the number suffix incremented by one (or 1 is added) - */ - private static String provideAvailableNameForGenTOBuilder(final String name) { - final int dollar = name.indexOf('$'); - if (dollar == -1) { - return name + "$1"; - } - - final int newSuffix = Integer.parseUnsignedInt(name.substring(dollar + 1)) + 1; - Preconditions.checkState(newSuffix > 0, "Suffix counter overflow"); - return name.substring(0, dollar + 1) + newSuffix; - } - - private static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) { - if (!Strings.isNullOrEmpty(units)) { - to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\""); - final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS"); - prop.setReturnType(Types.STRING); - to.addToStringProperty(prop); - } - } - - /** - * Returns parent Yang Module for specified Schema Context in which Schema - * Node is declared. If the Schema Node is not present in Schema Context the - * operation will return null. - * - * @param context Schema Context - * @param schemaNode Schema Node - * @return Yang Module for specified Schema Context and Schema Node, if Schema Node is NOT present, the method will - * return null - * @throws NullPointerException if any of the arguments is null - */ - private static Module findParentModule(final SchemaContext context, final SchemaNode schemaNode) { - return context.findModule(schemaNode.getQName().getModule()).orElse(null); - } -} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/CodegenTypeProvider.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/CodegenTypeProvider.java deleted file mode 100644 index c1b7e227f9..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/CodegenTypeProvider.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2018 Pantheon Technologies, s.r.o. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.mdsal.binding.yang.types; - -import static org.opendaylight.mdsal.binding.generator.BindingGeneratorUtil.encodeAngleBrackets; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import org.opendaylight.mdsal.binding.model.api.JavaTypeName; -import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder; -import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTOBuilder; -import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilderBase; -import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.AbstractEnumerationBuilder; -import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.CodegenEnumerationBuilder; -import org.opendaylight.mdsal.binding.model.ri.generated.type.builder.CodegenGeneratedTOBuilder; -import org.opendaylight.yangtools.yang.binding.RegexPatterns; -import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * {@link AbstractTypeProvider} which generates full metadata, suitable for codegen purposes. For runtime purposes, - * considering using {@link RuntimeTypeProvider}. - */ -// FIXME: remove this class -@Deprecated(forRemoval = true) -final class CodegenTypeProvider extends AbstractTypeProvider { - private static final Logger LOG = LoggerFactory.getLogger(CodegenTypeProvider.class); - - @VisibleForTesting - CodegenTypeProvider(final EffectiveModelContext schemaContext) { - super(schemaContext); - } - - @Override - public void addEnumDescription(final EnumBuilder enumBuilder, final EnumTypeDefinition enumTypeDef) { - final Optional optDesc = enumTypeDef.getDescription(); - if (optDesc.isPresent()) { - enumBuilder.setDescription(encodeAngleBrackets(optDesc.get())); - } - } - - @Override - void addCodegenInformation(final GeneratedTypeBuilderBase genTOBuilder, final TypeDefinition typeDef) { - final Optional optDesc = typeDef.getDescription(); - if (optDesc.isPresent()) { - genTOBuilder.setDescription(encodeAngleBrackets(optDesc.get())); - } - 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 - public 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(); - - // The pattern can be inverted - final Optional optModifier = patternConstraint.getModifier(); - if (optModifier.isPresent()) { - regEx = applyModifier(optModifier.get(), regEx); - } - - regExps.put(regEx, patternConstraint.getRegularExpressionString()); - } - - return regExps; - } - - private static String applyModifier(final ModifierKind modifier, final String pattern) { - switch (modifier) { - case INVERT_MATCH: - return RegexPatterns.negatePatternString(pattern); - default: - LOG.warn("Ignoring unhandled modifier {}", modifier); - return pattern; - } - } - - @Override - public GeneratedTOBuilder newGeneratedTOBuilder(final JavaTypeName identifier) { - return new CodegenGeneratedTOBuilder(identifier); - } - - @Override - public AbstractEnumerationBuilder newEnumerationBuilder(final JavaTypeName identifier) { - return new CodegenEnumerationBuilder(identifier); - } -} diff --git a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/TypedefResolver.java b/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/TypedefResolver.java deleted file mode 100644 index 7d7fe9d829..0000000000 --- a/binding/mdsal-binding-generator/src/main/java/org/opendaylight/mdsal/binding/yang/types/TypedefResolver.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.mdsal.binding.yang.types; - -import java.util.ArrayList; -import java.util.List; -import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode; -import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; -import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; -import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; -import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; -import org.opendaylight.yangtools.yang.model.api.RpcDefinition; -import org.opendaylight.yangtools.yang.model.api.TypeDefinition; - -final class TypedefResolver { - private TypedefResolver() { - // Hidden on purpose - } - - static List> getAllTypedefs(final Module module) { - final List> ret = new ArrayList<>(); - - fillRecursively(ret, module); - - for (NotificationDefinition notificationDefinition : module.getNotifications()) { - fillRecursively(ret, notificationDefinition); - } - - for (RpcDefinition rpcDefinition : module.getRpcs()) { - ret.addAll(rpcDefinition.getTypeDefinitions()); - fillRecursively(ret, rpcDefinition.getInput()); - fillRecursively(ret, rpcDefinition.getOutput()); - } - - return ret; - } - - private static void fillRecursively(final List> list, final DataNodeContainer container) { - for (DataSchemaNode childNode : container.getChildNodes()) { - if (!childNode.isAugmenting()) { - if (childNode instanceof ContainerSchemaNode) { - fillRecursively(list, (ContainerSchemaNode) childNode); - } else if (childNode instanceof ListSchemaNode) { - fillRecursively(list, (ListSchemaNode) childNode); - } else if (childNode instanceof ChoiceSchemaNode) { - for (CaseSchemaNode caseNode : ((ChoiceSchemaNode) childNode).getCases()) { - fillRecursively(list, caseNode); - } - } - } - } - - list.addAll(container.getTypeDefinitions()); - - for (GroupingDefinition grouping : container.getGroupings()) { - fillRecursively(list, grouping); - } - } -} diff --git a/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingGeneratorTest.java b/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingGeneratorTest.java index 2db46bf78a..b0182fc204 100644 --- a/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingGeneratorTest.java +++ b/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/generator/impl/DefaultBindingGeneratorTest.java @@ -11,7 +11,10 @@ package org.opendaylight.mdsal.binding.generator.impl; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import java.util.List; import org.junit.AfterClass; @@ -25,14 +28,17 @@ import org.opendaylight.mdsal.binding.model.api.GeneratedType; import org.opendaylight.mdsal.binding.model.api.JavaTypeName; import org.opendaylight.mdsal.binding.model.api.MethodSignature; import org.opendaylight.mdsal.binding.model.api.ParameterizedType; +import org.opendaylight.mdsal.binding.model.api.Type; import org.opendaylight.mdsal.binding.model.ri.Types; -import org.opendaylight.mdsal.binding.yang.types.TypeProviderTest; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; /** * General test suite revolving around {@link DefaultBindingGenerator}. This class holds tests originally aimed at * specific implementation methods, but now they really are all about integration testing. + * + * @author Lukas Sedlak + * @author Robert Varga */ @RunWith(MockitoJUnitRunner.class) public class DefaultBindingGeneratorTest { @@ -44,13 +50,17 @@ public class DefaultBindingGeneratorTest { "org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.b.model.rev140915"; public static final JavaTypeName CONSTRUCTION_TYPE_TEST = JavaTypeName.create(TEST_TYPE_PROVIDER, "ConstructionTypeTest"); + public static final JavaTypeName TEST_TYPE_PROVIDER_B_DATA = + JavaTypeName.create(TEST_TYPE_PROVIDER_B, "TestTypeProviderBData"); + public static final JavaTypeName TEST_TYPE_PROVIDER_FOO = + JavaTypeName.create(TEST_TYPE_PROVIDER, "Foo"); public static EffectiveModelContext SCHEMA_CONTEXT; public static List TYPES; @BeforeClass public static void beforeClass() { - SCHEMA_CONTEXT = YangParserTestUtils.parseYangResources(TypeProviderTest.class, + SCHEMA_CONTEXT = YangParserTestUtils.parseYangResources(DefaultBindingGeneratorTest.class, "/base-yang-types.yang", "/test-type-provider-b.yang", "/test-type-provider.yang"); TYPES = DefaultBindingGenerator.generateFor(SCHEMA_CONTEXT); } @@ -63,7 +73,7 @@ public class DefaultBindingGeneratorTest { @Test public void javaTypeForSchemaDefinitionLeafrefToEnumTypeTest() { - final var bData = assertGeneratedType(JavaTypeName.create(TEST_TYPE_PROVIDER_B, "TestTypeProviderBData")); + final var bData = assertGeneratedType(TEST_TYPE_PROVIDER_B_DATA); final var bDataMethods = bData.getMethodDefinitions(); assertEquals(8, bDataMethods.size()); @@ -84,13 +94,8 @@ public class DefaultBindingGeneratorTest { @Test public void generatedTypeForExtendedDefinitionTypeWithIdentityrefBaseTypeTest() { - final var type = assertGeneratedMethod(CONSTRUCTION_TYPE_TEST, "getAesIdentityrefType").getReturnType(); - assertThat(type, instanceOf(ParameterizedType.class)); - final var pType = (ParameterizedType) type; - assertEquals(Types.CLASS, pType.getRawType()); - final var pTypeArgs = pType.getActualTypeArguments(); - assertEquals(1, pTypeArgs.length); - assertEquals(TEST_TYPE_PROVIDER + ".Aes", pTypeArgs[0].getFullyQualifiedName()); + assertEquals(Types.parameterizedTypeFor(Types.CLASS, Type.of(JavaTypeName.create(TEST_TYPE_PROVIDER, "Aes"))), + assertGeneratedMethod(CONSTRUCTION_TYPE_TEST, "getAesIdentityrefType").getReturnType()); } @Test @@ -182,14 +187,9 @@ public class DefaultBindingGeneratorTest { @Test public void javaTypeForSchemaDefinitionIdentityrefExtTypeTest() { - final var type = assertGeneratedMethod(JavaTypeName.create(TEST_TYPE_PROVIDER, "Foo"), "getCrypto") - .getReturnType(); - assertThat(type, instanceOf(ParameterizedType.class)); - final var param = (ParameterizedType) type; - assertEquals(JavaTypeName.create(Class.class), param.getIdentifier()); - final var params = param.getActualTypeArguments(); - assertEquals(1, params.length); - assertEquals(Types.wildcardTypeFor(JavaTypeName.create(TEST_TYPE_PROVIDER, "CryptoAlg")), params[0]); + assertEquals(Types.parameterizedTypeFor(Types.CLASS, + Types.wildcardTypeFor(JavaTypeName.create(TEST_TYPE_PROVIDER, "CryptoAlg"))), + assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getCrypto").getReturnType()); } @Test @@ -205,13 +205,14 @@ public class DefaultBindingGeneratorTest { @Test public void testUnresolvedLeafref() { - assertEquals(Types.objectType(), assertGeneratedMethod(JavaTypeName.create(TEST_TYPE_PROVIDER_B, "Grp"), - "getUnresolvableLeafref").getReturnType()); + assertSame(Types.objectType(), + assertGeneratedMethod(JavaTypeName.create(TEST_TYPE_PROVIDER_B, "Grp"), "getUnresolvableLeafref") + .getReturnType()); } @Test public void javaTypeForSchemaDefinitionInvalidLeafrefPathTest() { - final var ctx = YangParserTestUtils.parseYangResources(TypeProviderTest.class, "/unresolvable-leafref.yang"); + final var ctx = YangParserTestUtils.parseYangResource("/unresolvable-leafref.yang"); final var ex = assertThrows(IllegalArgumentException.class, () -> DefaultBindingGenerator.generateFor(ctx)); assertEquals("Failed to find leafref target /somewhere/i/belong", ex.getMessage()); final var cause = ex.getCause(); @@ -219,6 +220,72 @@ public class DefaultBindingGeneratorTest { assertEquals("Data tree child (foo)somewhere not present", cause.getMessage()); } + @Test + public void javaTypeForSchemaDefinitionConditionalLeafrefTest() { + // Note: previous incarnation did not resolve this, as the expression (pointed to a list) + assertSame(assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt16")), + assertGeneratedMethod(TEST_TYPE_PROVIDER_B_DATA, "getConditionalLeafref").getReturnType()); + } + + @Test + public void javaTypeForSchemaDefinitionLeafrefExtTypeTest() { + assertSame(assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8")), + assertGeneratedMethod(JavaTypeName.create(TEST_TYPE_PROVIDER, "Bar"), "getLeafrefValue").getReturnType()); + assertSame(assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt16")), + assertGeneratedMethod(TEST_TYPE_PROVIDER_B_DATA, "getId").getReturnType()); + } + + @Test + public void javaTypeForSchemaDefinitionEnumExtTypeTest() { + final var expected = assertGeneratedType(JavaTypeName.create(BASE_YANG_TYPES, "YangEnumeration")); + assertThat(expected, instanceOf(Enumeration.class)); + var enumValues = ((Enumeration) expected).getValues(); + assertEquals(2, enumValues.size()); + assertEquals("a", enumValues.get(0).getName()); + assertEquals("A", enumValues.get(0).getMappedName()); + assertEquals("b", enumValues.get(1).getName()); + assertEquals("B", enumValues.get(1).getMappedName()); + + assertSame(expected, assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getResolveEnumLeaf").getReturnType()); + + // Note: this part of the test contained invalid assertion that the return would be java.lang.Enum + final var type = assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getResolveDirectUseOfEnum").getReturnType(); + assertEquals(TEST_TYPE_PROVIDER_FOO.createEnclosed("ResolveDirectUseOfEnum"), type.getIdentifier()); + assertThat(expected, instanceOf(Enumeration.class)); + enumValues = ((Enumeration) type).getValues(); + assertEquals(3, enumValues.size()); + assertEquals("x", enumValues.get(0).getName()); + assertEquals("X", enumValues.get(0).getMappedName()); + assertEquals("y", enumValues.get(1).getName()); + assertEquals("Y", enumValues.get(1).getMappedName()); + assertEquals("z", enumValues.get(2).getName()); + assertEquals("Z", enumValues.get(2).getMappedName()); + } + + @Test + public void javaTypeForSchemaDefinitionRestrictedExtTypeTest() { + final var expected = assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8Restricted")); + assertEquals(1, expected.getProperties().size()); + final var rangeConstraints = expected.getRestrictions().getRangeConstraint(); + assertTrue(rangeConstraints.isPresent()); + final var it = rangeConstraints.orElseThrow().getAllowedRanges().asRanges().iterator(); + assertTrue(it.hasNext()); + final var constraint = it.next(); + assertEquals((byte) 1, constraint.lowerEndpoint()); + assertEquals((byte) 100, constraint.upperEndpoint()); + assertFalse(it.hasNext()); + + assertSame(expected, assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getRestrictedInt8Type").getReturnType()); + } + + @Test + public void javaTypeForSchemaDefinitionExtTypeTest() { + final var expected = assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8")); + assertEquals(1, expected.getProperties().size()); + + assertSame(expected, assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getYangInt8Type").getReturnType()); + } + private static MethodSignature assertGeneratedMethod(final JavaTypeName typeName, final String methodName) { return assertGeneratedMethod(assertGeneratedType(typeName).getMethodDefinitions(), methodName); } diff --git a/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/yang/types/TypeProviderTest.java b/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/yang/types/TypeProviderTest.java deleted file mode 100644 index b8c1ecc7de..0000000000 --- a/binding/mdsal-binding-generator/src/test/java/org/opendaylight/mdsal/binding/yang/types/TypeProviderTest.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.mdsal.binding.yang.types; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.google.common.collect.Range; -import java.util.List; -import java.util.Optional; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; -import org.opendaylight.mdsal.binding.generator.BindingGeneratorUtil; -import org.opendaylight.mdsal.binding.model.api.ConcreteType; -import org.opendaylight.mdsal.binding.model.api.Enumeration; -import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject; -import org.opendaylight.mdsal.binding.model.api.Restrictions; -import org.opendaylight.mdsal.binding.model.api.Type; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; -import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.SchemaNode; -import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.opendaylight.yangtools.yang.model.api.TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint; -import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; - -/** - * Test suite for testing public methods in TypeProviderImpl class. - * - * @see org.opendaylight.mdsal.binding.yang.types.AbstractTypeProvider - * @author Lukas Sedlak <lsedlak@cisco.com> - */ -// FIXME: rewrite tests without TypeProvider interface -@Ignore -@RunWith(MockitoJUnitRunner.class) -public class TypeProviderTest { - static EffectiveModelContext SCHEMA_CONTEXT; - static Module TEST_TYPE_PROVIDER; - - @Mock - public SchemaPath schemaPath; - - @Mock - public SchemaNode schemaNode; - - @BeforeClass - public static void beforeClass() { - SCHEMA_CONTEXT = YangParserTestUtils.parseYangResources(TypeProviderTest.class, - "/base-yang-types.yang", "/test-type-provider-b.yang", "/test-type-provider.yang"); - TEST_TYPE_PROVIDER = resolveModule("test-type-provider"); - } - - @AfterClass - public static void afterClass() { - TEST_TYPE_PROVIDER = null; - SCHEMA_CONTEXT = null; - } - - private static Module resolveModule(final String moduleName) { - return SCHEMA_CONTEXT.findModules(moduleName).iterator().next(); - } - - private static LeafSchemaNode provideLeafNodeFromTopLevelContainer(final Module module, final String containerName, - final String leafNodeName) { - final QName containerNode = QName.create(module.getQNameModule(), containerName); - final DataSchemaNode rootNode = module.findDataChildByName(containerNode).get(); - assertTrue(rootNode instanceof DataNodeContainer); - - final QName leafNode = QName.create(module.getQNameModule(), leafNodeName); - final DataNodeContainer rootContainer = (DataNodeContainer) rootNode; - final DataSchemaNode node = rootContainer.findDataChildByName(leafNode).get(); - assertTrue(node instanceof LeafSchemaNode); - return (LeafSchemaNode) node; - } - - @Test - public void javaTypeForSchemaDefinitionExtTypeTest() { - final AbstractTypeProvider provider = new CodegenTypeProvider(SCHEMA_CONTEXT); - final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(TEST_TYPE_PROVIDER, "foo", - "yang-int8-type"); - - final TypeDefinition leafType = leaf.getType(); - final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf); - assertNotNull(result); - assertTrue(result instanceof GeneratedTransferObject); - - final GeneratedTransferObject genTO = (GeneratedTransferObject) result; - assertEquals("base-yang-types", genTO.getModuleName()); - assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914", - genTO.getPackageName()); - assertEquals("YangInt8", genTO.getName()); - assertEquals(1, genTO.getProperties().size()); - } - - @Test - public void javaTypeForSchemaDefinitionRestrictedExtTypeTest() { - final AbstractTypeProvider provider = new CodegenTypeProvider(SCHEMA_CONTEXT); - final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(TEST_TYPE_PROVIDER, "foo", - "restricted-int8-type"); - - final TypeDefinition leafType = leaf.getType(); - final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(leafType); - - final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf, restrictions); - assertNotNull(result); - assertTrue(result instanceof GeneratedTransferObject); - - final GeneratedTransferObject genTO = (GeneratedTransferObject) result; - assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914", - genTO.getPackageName()); - assertEquals("YangInt8Restricted", genTO.getName()); - assertEquals(1, genTO.getProperties().size()); - final Optional> rangeConstraints = genTO.getRestrictions().getRangeConstraint(); - - assertTrue(rangeConstraints.isPresent()); - final Range constraint = rangeConstraints.get().getAllowedRanges().asRanges().iterator().next(); - assertEquals((byte) 1, constraint.lowerEndpoint()); - assertEquals((byte) 100, constraint.upperEndpoint()); - } - - @Test - public void javaTypeForSchemaDefinitionEnumExtTypeTest() { - final AbstractTypeProvider provider = new CodegenTypeProvider(SCHEMA_CONTEXT); - LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(TEST_TYPE_PROVIDER, "foo", "resolve-enum-leaf"); - TypeDefinition leafType = leaf.getType(); - Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf); - assertNotNull(result); - assertTrue(result instanceof Enumeration); - - final Enumeration enumType = (Enumeration) result; - final List enumValues = enumType.getValues(); - assertTrue(!enumValues.isEmpty()); - assertEquals("a", enumValues.get(0).getName()); - assertEquals("b", enumValues.get(1).getName()); - assertEquals("A", enumValues.get(0).getMappedName()); - assertEquals("B", enumValues.get(1).getMappedName()); - - leaf = provideLeafNodeFromTopLevelContainer(TEST_TYPE_PROVIDER, "foo", "resolve-direct-use-of-enum"); - leafType = leaf.getType(); - result = provider.javaTypeForSchemaDefinitionType(leafType, leaf); - assertNotNull(result); - assertTrue(result instanceof ConcreteType); - - assertEquals("java.lang", result.getPackageName()); - assertEquals("Enum", result.getName()); - } - - @Test - public void javaTypeForSchemaDefinitionLeafrefExtTypeTest() { - final AbstractTypeProvider provider = new CodegenTypeProvider(SCHEMA_CONTEXT); - LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(TEST_TYPE_PROVIDER, "bar", "leafref-value"); - TypeDefinition leafType = leaf.getType(); - final Type leafrefResolvedType1 = provider.javaTypeForSchemaDefinitionType(leafType, leaf); - assertNotNull(leafrefResolvedType1); - assertTrue(leafrefResolvedType1 instanceof GeneratedTransferObject); - - final Module module = resolveModule("test-type-provider-b"); - final QName leafNode = QName.create(module.getQNameModule(), "id"); - final DataSchemaNode rootNode = module.findDataChildByName(leafNode).get(); - assertNotNull("leaf id is not present in root of module " + module.getName(), rootNode); - assertTrue(rootNode instanceof LeafSchemaNode); - leaf = (LeafSchemaNode) rootNode; - leafType = leaf.getType(); - - final Type leafrefResolvedType2 = provider.javaTypeForSchemaDefinitionType(leafType, leaf); - assertNotNull(leafrefResolvedType2); - assertTrue(leafrefResolvedType2 instanceof GeneratedTransferObject); - } - - @Test - public void javaTypeForSchemaDefinitionConditionalLeafrefTest() { - final AbstractTypeProvider provider = new CodegenTypeProvider(SCHEMA_CONTEXT); - final Module module = resolveModule("test-type-provider-b"); - - final QName leafrefNode = QName.create(module.getQNameModule(), "conditional-leafref"); - final DataSchemaNode condLeaf = module.findDataChildByName(leafrefNode).get(); - assertTrue(condLeaf instanceof LeafSchemaNode); - final LeafSchemaNode leaf = (LeafSchemaNode) condLeaf; - final TypeDefinition leafType = leaf.getType(); - - final Type resultType = provider.javaTypeForSchemaDefinitionType(leafType, leaf); - assertNotNull(resultType); - assertTrue(resultType instanceof ConcreteType); - assertEquals("java.lang", resultType.getPackageName()); - assertEquals("Object", resultType.getName()); - } -} -- 2.36.6