From 17f092cc375493891b15139cc0f57584298ba18e Mon Sep 17 00:00:00 2001 From: Peter Kajsa Date: Tue, 26 Jan 2016 15:13:23 +0100 Subject: [PATCH] Bug 5059: Do not fail when 'refine' targets an extension. Yang parser does not fail when 'refine' targets an extension, but the parser logs a warning and the refine statement is ignored. Change-Id: I9a4ad46ac254c36b64b44903162361c1e14f4e71 Signed-off-by: Peter Kajsa (cherry picked from commit d20d90de04fa676f96d117d827fe284370fdc3d9) --- .../parser/spi/meta/StmtContextUtils.java | 24 +++++++++++-- .../parser/stmt/rfc6020/GroupingUtils.java | 12 ++++++- .../SchemaNodeIdentifierBuildNamespace.java | 36 +++++++++++++++++-- .../yangtools/yang/stmt/test/Bug5059.java | 25 +++++++++++++ .../src/test/resources/bugs/bug5059/foo.yang | 33 +++++++++++++++++ 5 files changed, 124 insertions(+), 6 deletions(-) create mode 100644 yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5059.java create mode 100644 yang/yang-parser-impl/src/test/resources/bugs/bug5059/foo.yang diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java index 77b285f16a..05b7f67c33 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java @@ -83,17 +83,37 @@ public final class StmtContextUtils { } @SuppressWarnings("unchecked") - public static > Collection> findAllDeclaredSubstatement( + public static > Collection> findAllDeclaredSubstatements( final StmtContext stmtContext, final Class
declaredType) { ImmutableList.Builder> listBuilder = ImmutableList.builder(); for (StmtContext subStmtContext : stmtContext.declaredSubstatements()) { - if (producesDeclared(subStmtContext,declaredType)) { + if (producesDeclared(subStmtContext, declaredType)) { listBuilder.add((StmtContext) subStmtContext); } } return listBuilder.build(); } + @SuppressWarnings("unchecked") + public static > Collection> findAllEffectiveSubstatements( + final StmtContext stmtContext, final Class
type) { + ImmutableList.Builder> listBuilder = ImmutableList.builder(); + for (StmtContext subStmtContext : stmtContext.effectiveSubstatements()) { + if (producesDeclared(subStmtContext, type)) { + listBuilder.add((StmtContext) subStmtContext); + } + } + return listBuilder.build(); + } + + public static > Collection> findAllSubstatements( + final StmtContext stmtContext, final Class
type) { + ImmutableList.Builder> listBuilder = ImmutableList.builder(); + listBuilder.addAll(findAllDeclaredSubstatements(stmtContext, type)); + listBuilder.addAll(findAllEffectiveSubstatements(stmtContext, type)); + return listBuilder.build(); + } + @SuppressWarnings("unchecked") public static > StmtContext findFirstEffectiveSubstatement( final StmtContext stmtContext, final Class
declaredType) { diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java index 7f92ae4a74..8106aa6350 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/GroupingUtils.java @@ -28,9 +28,13 @@ import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace; import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType; import org.opendaylight.yangtools.yang.parser.stmt.reactor.StatementContextBase; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public final class GroupingUtils { + private static final Logger LOG = LoggerFactory.getLogger(GroupingUtils.class); + private GroupingUtils() { throw new UnsupportedOperationException(); } @@ -159,6 +163,13 @@ public final class GroupingUtils { StatementContextBase refineTargetNodeCtx = Utils.findNode(usesParentCtx, refineTargetNodeIdentifier); Preconditions.checkArgument(refineTargetNodeCtx != null, "Refine target node %s not found. At %s", refineTargetNodeIdentifier, refineCtx.getStatementSourceReference()); + if (StmtContextUtils.isUnknownStatement(refineTargetNodeCtx)) { + LOG.warn("Refine node '{}' in uses '{}' has target node unknown statement '{}'. Refine has been skipped. At line: {}", + refineCtx.getStatementArgument(), refineCtx.getParentContext().getStatementArgument(), refineTargetNodeCtx.getStatementArgument(), + refineCtx.getStatementSourceReference()); + refineCtx.addAsEffectOfStatement(refineTargetNodeCtx); + return; + } addOrReplaceNodes(refineCtx, refineTargetNodeCtx); refineCtx.addAsEffectOfStatement(refineTargetNodeCtx); @@ -177,7 +188,6 @@ public final class GroupingUtils { final StatementContextBase refineTargetNodeCtx) { StatementDefinition refineSubstatementDef = refineSubstatementCtx.getPublicDefinition(); - StatementDefinition refineTargetNodeDef = refineTargetNodeCtx.getPublicDefinition(); SourceException.throwIf(!isSupportedRefineTarget(refineSubstatementCtx, refineTargetNodeCtx), refineSubstatementCtx.getStatementSourceReference(), diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java index 93069256e5..5fdf765ab1 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/SchemaNodeIdentifierBuildNamespace.java @@ -8,14 +8,18 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; +import java.util.Collection; import java.util.Iterator; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; +import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement; import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable; +import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; class SchemaNodeIdentifierBuildNamespace extends DerivedNamespaceBehaviour>, QName, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodes> @@ -32,6 +36,7 @@ class SchemaNodeIdentifierBuildNamespace extends throw new UnsupportedOperationException("Direct access to namespace is not supported"); } + @SuppressWarnings("unchecked") @Override public StmtContext.Mutable> getFrom(NamespaceStorageNode storage, SchemaNodeIdentifier key) { @@ -49,13 +54,38 @@ class SchemaNodeIdentifierBuildNamespace extends return null; } } - StmtContext.Mutable> current = (StmtContext.Mutable>) lookupStartStorage.getFromLocalStorage(ChildSchemaNodes.class, iterator.next()); - while(current != null && iterator.hasNext()) { - current = (StmtContext.Mutable>) current.getFromNamespace(ChildSchemaNodes.class, iterator.next()); + QName nextPath = iterator.next(); + StmtContext.Mutable> current = (StmtContext.Mutable>) lookupStartStorage + .getFromLocalStorage(ChildSchemaNodes.class, nextPath); + if(current == null && lookupStartStorage instanceof StmtContext) { + return tryToFindUnknownStatement(nextPath.getLocalName(), (Mutable>) lookupStartStorage); + } + while (current != null && iterator.hasNext()) { + nextPath = iterator.next(); + StmtContext.Mutable> nextNodeCtx = (StmtContext.Mutable>) current + .getFromNamespace(ChildSchemaNodes.class, nextPath); + if (nextNodeCtx == null) { + return tryToFindUnknownStatement(nextPath.getLocalName(), current); + } else { + current = nextNodeCtx; + } } return current; } + @SuppressWarnings("unchecked") + private Mutable> tryToFindUnknownStatement(final String localName, + final Mutable> current) { + Collection> unknownSubstatements = StmtContextUtils.findAllSubstatements(current, + UnknownStatement.class); + for (StmtContext unknownSubstatement : unknownSubstatements) { + if(unknownSubstatement.rawStatementArgument().equals(localName)) { + return (Mutable>) unknownSubstatement; + } + } + return null; + } + @Override public QName getSignificantKey(SchemaNodeIdentifier key) { return key.getLastComponent(); diff --git a/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5059.java b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5059.java new file mode 100644 index 0000000000..35f2437ee5 --- /dev/null +++ b/yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/stmt/test/Bug5059.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015 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.yangtools.yang.stmt.test; + +import static org.junit.Assert.assertNotNull; + +import java.io.FileNotFoundException; +import java.net.URISyntaxException; +import org.junit.Test; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; + +public class Bug5059 { + @Test + public void test() throws SourceException, FileNotFoundException, ReactorException, URISyntaxException { + SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug5059"); + assertNotNull(context); + } +} diff --git a/yang/yang-parser-impl/src/test/resources/bugs/bug5059/foo.yang b/yang/yang-parser-impl/src/test/resources/bugs/bug5059/foo.yang new file mode 100644 index 0000000000..3a35eecba2 --- /dev/null +++ b/yang/yang-parser-impl/src/test/resources/bugs/bug5059/foo.yang @@ -0,0 +1,33 @@ +module foo { + namespace "foo"; + prefix foo; + + revision 2016-01-25 { + description "test"; + } + + grouping my-grouping { + container my-container { + foo:e2 "e2"; + } + foo:e1 "e1"; + } + + container root { + uses my-grouping { + refine e1 { + description "new description for e1"; + } + refine my-container/e2 { + description "new description for e2"; + } + } + } + + extension e1 { + argument name; + } + extension e2 { + argument name; + } +} -- 2.36.6