From 8c4ab985c1723336640324789c65489e71deb4e0 Mon Sep 17 00:00:00 2001 From: Tomas Cere Date: Fri, 10 Jul 2020 13:51:54 +0200 Subject: [PATCH] Resolve generated type for leafrefs targetting unions We need to be able to resolve the generated type of unions which are targeted by leafrefs during codegen. Introduce a path that attempts this by consulting ModuleContext for the generated types in case we are resolving a leafref. JIRA: MDSAL-572 Change-Id: I40448a4c9f2fdf26280e0911ebb9dcc5fc60d3f1 Signed-off-by: Tomas Cere Signed-off-by: Robert Varga --- .../generator/impl/AbstractTypeGenerator.java | 26 ++++++++++++---- .../yang/types/AbstractTypeProvider.java | 11 +++++++ .../binding/generator/impl/Mdsal572Test.java | 24 +++++++++++++++ .../src/test/resources/mdsal572.yang | 30 +++++++++++++++++++ 4 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal572Test.java create mode 100644 binding/mdsal-binding-generator-impl/src/test/resources/mdsal572.yang diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java index 55bcb53c29..1ba24c4a07 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/AbstractTypeGenerator.java @@ -118,10 +118,12 @@ 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.TypeDefinition; +import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode; import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; 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.LeafrefTypeDefinition; 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.ModuleDependencySort; @@ -1424,13 +1426,25 @@ abstract class AbstractTypeGenerator { returnType = genTOBuilder.build(); } } else { - // It is constrained version of already declared type (inner declared type exists, - // onlyfor special cases (Enum, Union, Bits), which were already checked. - // In order to get proper class we need to look up closest derived type - // and apply restrictions from leaf type + // It is constrained version of already declared type (inner declared type exists, only for special + // cases (Enum, Union, Bits), which were already checked. + // In order to get proper class we need to look up closest derived type and apply restrictions from leaf + // type final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef); - returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf, - restrictions, inGrouping); + final TypeDefinition baseOrDeclaredType = getBaseOrDeclaredType(typeDef); + // we need to try to lookup an already generated type in case the leafref is targetting a generated type + if (baseOrDeclaredType instanceof LeafrefTypeDefinition) { + final SchemaNode leafrefTarget = + typeProvider.getTargetForLeafref((LeafrefTypeDefinition) baseOrDeclaredType, leaf); + if (leafrefTarget instanceof TypedDataSchemaNode) { + returnType = context.getInnerType(((TypedDataSchemaNode) leafrefTarget).getType().getPath()); + } + } + if (returnType == null) { + returnType = typeProvider.javaTypeForSchemaDefinitionType(baseOrDeclaredType, leaf, + restrictions, inGrouping); + } + addPatternConstant(typeBuilder, leaf.getQName().getLocalName(), restrictions.getPatternConstraints()); } } else { diff --git a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java index bf5054d9f2..88af37f1e5 100644 --- a/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java +++ b/binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/yang/types/AbstractTypeProvider.java @@ -223,6 +223,17 @@ public abstract class AbstractTypeProvider implements TypeProvider { return returnType; } + public SchemaNode getTargetForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) { + final PathExpression xpath = leafrefType.getPathStatement(); + Preconditions.checkArgument(xpath != null, "The Path Statement for Leafref Type Definition cannot be NULL!"); + + final Module module = findParentModule(schemaContext, parentNode); + Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode); + + return xpath.isAbsolute() ? findDataTreeSchemaNode(schemaContext, module.getQNameModule(), xpath) + : findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath); + } + private GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, final Restrictions restrictions) { final GeneratedTOBuilder gtob = newGeneratedTOBuilder(gto.getIdentifier()); diff --git a/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal572Test.java b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal572Test.java new file mode 100644 index 0000000000..c59c8962e1 --- /dev/null +++ b/binding/mdsal-binding-generator-impl/src/test/java/org/opendaylight/mdsal/binding/generator/impl/Mdsal572Test.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.generator.impl; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import org.junit.Test; +import org.opendaylight.mdsal.binding.model.api.Type; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +public class Mdsal572Test { + @Test + public void mdsal572Test() { + final List types = new BindingGeneratorImpl().generateTypes(YangParserTestUtils.parseYangResource( + "/mdsal572.yang")); + assertEquals(6, types.size()); + } +} diff --git a/binding/mdsal-binding-generator-impl/src/test/resources/mdsal572.yang b/binding/mdsal-binding-generator-impl/src/test/resources/mdsal572.yang new file mode 100644 index 0000000000..533c9db0dc --- /dev/null +++ b/binding/mdsal-binding-generator-impl/src/test/resources/mdsal572.yang @@ -0,0 +1,30 @@ +module mdsal572 { + namespace "mdsal572"; + prefix l; + + grouping state-top { + leaf index { + type union { + type enumeration { + enum ALL; + } + type uint32; + } + } + } + + grouping g { + list l { + container state { + uses state-top; + } + leaf index { + type leafref { + path "../state/index"; + } + } + } + } + + uses g; +} \ No newline at end of file -- 2.36.6