From af5b2323bb4ed819689f224c8684131373a9677e Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Sun, 16 Feb 2020 15:33:56 +0100 Subject: [PATCH] Fixup SchemaNodeIdentifier design There are a number of errors with regard to how SchemaNodeIdentifier interacts with its non-existent users. Clean these up as well as the overall implementation interactions. JIRA: YANGTOOLS-1083 Change-Id: I616efbad3a2d54df5ecbfa656b3a843e852c187a Signed-off-by: Robert Varga --- .../model/api/stmt/SchemaNodeIdentifier.java | 300 ++++-------------- .../SchemaTreeAwareEffectiveStatement.java | 2 +- .../stmt/reactor/StatementContextBase.java | 2 +- .../namespace/ChildSchemaNodeNamespace.java | 2 +- .../parser/rfc7950/stmt/ArgumentUtils.java | 8 +- .../AbstractAugmentStatementSupport.java | 2 +- .../AbstractDeviateStatementSupport.java | 5 +- .../deviation/DeviationStatementSupport.java | 4 +- .../rfc7950/stmt/key/KeyStatementSupport.java | 7 +- .../list/AbstractListStatementSupport.java | 2 +- .../refine/RefineEffectiveStatementImpl.java | 5 +- .../stmt/unique/UniqueStatementSupport.java | 3 +- .../yang/stmt/AugmentArgumentParsingTest.java | 7 +- .../yangtools/yang/stmt/Bug5946Test.java | 6 +- .../yang/stmt/DeviationResolutionTest.java | 4 +- .../yang/stmt/YangParserNegativeTest.java | 4 +- .../parser/spi/meta/StmtContextUtils.java | 3 +- 17 files changed, 98 insertions(+), 268 deletions(-) diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaNodeIdentifier.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaNodeIdentifier.java index 544af22308..e8ff4558e9 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaNodeIdentifier.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaNodeIdentifier.java @@ -11,14 +11,12 @@ import static com.google.common.base.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; import com.google.common.base.MoreObjects; -import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.UnmodifiableIterator; import java.util.Arrays; -import java.util.NoSuchElementException; -import java.util.Objects; +import java.util.Collection; +import java.util.List; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.concepts.Immutable; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.SchemaPath; @@ -32,254 +30,84 @@ public abstract class SchemaNodeIdentifier implements Immutable { * An absolute schema node identifier. */ public static final class Absolute extends SchemaNodeIdentifier { - private Absolute(final SchemaNodeIdentifier parent, final QName qname) { - super(parent, qname); + Absolute(final QName qname) { + super(qname); } - @Override - public boolean isAbsolute() { - return true; + Absolute(final Collection qnames) { + super(qnames); } - @Override - public Absolute createChild(final QName element) { - return new Absolute(this, requireNonNull(element)); + public static Absolute of(final QName nodeIdentifier) { + return new Absolute(nodeIdentifier); } - } - /** - * A descendant schema node identifier. - */ - public static final class Descendant extends SchemaNodeIdentifier { - private Descendant(final SchemaNodeIdentifier parent, final QName qname) { - super(parent, qname); + public static Absolute of(final QName... nodeIdentifiers) { + return new Absolute(Arrays.asList(nodeIdentifiers)); } - @Override - public boolean isAbsolute() { - return false; + public static Absolute of(final Collection nodeIdentifiers) { + return new Absolute(ImmutableList.copyOf(nodeIdentifiers)); } @Override - public Descendant createChild(final QName element) { - return new Descendant(this, requireNonNull(element)); + SchemaPath implicitSchemaPathParent() { + return SchemaPath.ROOT; } } - @SuppressWarnings("rawtypes") - private static final AtomicReferenceFieldUpdater LEGACYPATH_UPDATER = - AtomicReferenceFieldUpdater.newUpdater(SchemaNodeIdentifier.class, ImmutableList.class, "legacyPath"); - private static final AtomicReferenceFieldUpdater SCHEMAPATH_UPDATER = - AtomicReferenceFieldUpdater.newUpdater(SchemaNodeIdentifier.class, SchemaPath.class, "schemaPath"); - /** - * Shared instance of the conceptual root schema node. - */ - public static final Absolute ROOT = new Absolute(null, null); - /** - * Shared instance of the "same" relative schema node. - */ - public static final Descendant SAME = new Descendant(null, null); - - /** - * Parent path. - */ - private final SchemaNodeIdentifier parent; - - /** - * This component. - */ - private final QName qname; - - /** - * Cached hash code. We can use this since we are immutable. - */ - private final int hash; - - /** - * Cached legacy path, filled-in when {@link #getPath()} or {@link #getPathTowardsRoot()} - * is invoked. - */ - private volatile ImmutableList legacyPath; - - /** - * Cached SchemaPath. + * A descendant schema node identifier. */ - private volatile SchemaPath schemaPath; - - SchemaNodeIdentifier(final SchemaNodeIdentifier parent, final QName qname) { - this.parent = parent; - this.qname = qname; - - int tmp = Objects.hashCode(parent); - if (qname != null) { - tmp = tmp * 31 + qname.hashCode(); + public static final class Descendant extends SchemaNodeIdentifier { + Descendant(final QName qname) { + super(qname); } - hash = tmp; - } - - private ImmutableList getLegacyPath() { - ImmutableList ret = legacyPath; - if (ret == null) { - ret = ImmutableList.copyOf(getPathTowardsRoot()).reverse(); - LEGACYPATH_UPDATER.lazySet(this, ret); + Descendant(final Collection qnames) { + super(qnames); } - return ret; - } - - /** - * Constructs new instance of this class with the concrete path. - * - * @param path - * list of QName instances which specifies exact path to the - * module node - * @param absolute - * boolean value which specifies if the path is absolute or - * relative - * - * @return A SchemaNodeIdentifier instance. - */ - public static SchemaNodeIdentifier create(final Iterable path, final boolean absolute) { - final SchemaNodeIdentifier parent = absolute ? ROOT : SAME; - return parent.createChild(path); - } - - /** - * Constructs new instance of this class with the concrete path. - * - * @param absolute - * boolean value which specifies if the path is absolute or - * relative - * @param path - * one or more QName instances which specifies exact path to the - * module node - * - * @return A SchemaPath instance. - */ - public static SchemaNodeIdentifier create(final boolean absolute, final QName... path) { - return create(Arrays.asList(path), absolute); - } - - /** - * Create a child path based on concatenation of this path and a relative path. - * - * @param relative Relative path - * @return A new child path - */ - public SchemaNodeIdentifier createChild(final Iterable relative) { - if (Iterables.isEmpty(relative)) { - return this; + public static Descendant of(final QName nodeIdentifier) { + return new Descendant(nodeIdentifier); } - SchemaNodeIdentifier parentNode = this; - for (QName item : relative) { - parentNode = parentNode.createChild(item); + public static Descendant of(final QName... nodeIdentifiers) { + return new Descendant(Arrays.asList(nodeIdentifiers)); } - return parentNode; - } - - /** - * Create a child path based on concatenation of this path and a relative path. - * - * @param relative Relative SchemaPath - * @return A new child path - */ - public SchemaNodeIdentifier createChild(final SchemaNodeIdentifier relative) { - checkArgument(!relative.isAbsolute(), "Child creation requires relative path"); - return createChild(relative.getPathFromRoot()); - } - - /** - * Create a child path based on concatenation of this path and an additional path element. - * - * @param element Next SchemaPath element - * @return A new child path - */ - public abstract SchemaNodeIdentifier createChild(QName element); - - /** - * Create a child path based on concatenation of this path and additional - * path elements. - * - * @param elements Relative SchemaPath elements - * @return A new child path - */ - public SchemaNodeIdentifier createChild(final QName... elements) { - return createChild(Arrays.asList(elements)); - } + public static Descendant of(final Collection nodeIdentifiers) { + return new Descendant(nodeIdentifiers); + } - /** - * Returns the list of nodes which need to be traversed to get from the - * starting point (root for absolute SchemaPaths) to the node represented - * by this object. - * - * @return list of qname instances which represents - * path from the root to the schema node. - */ - public Iterable getPathFromRoot() { - return getLegacyPath(); + @Override + SchemaPath implicitSchemaPathParent() { + return SchemaPath.SAME; + } } - /** - * Returns the list of nodes which need to be traversed to get from this - * node to the starting point (root for absolute SchemaPaths). - * - * @return list of qname instances which represents - * path from the schema node towards the root. - */ - public Iterable getPathTowardsRoot() { - return () -> new UnmodifiableIterator<>() { - private SchemaNodeIdentifier current = SchemaNodeIdentifier.this; + private static final AtomicReferenceFieldUpdater SCHEMAPATH_UPDATER = + AtomicReferenceFieldUpdater.newUpdater(SchemaNodeIdentifier.class, SchemaPath.class, "schemaPath"); - @Override - public boolean hasNext() { - return current.parent != null; - } + private final @NonNull Object qnames; - @Override - public QName next() { - if (current.parent != null) { - final QName ret = current.qname; - current = current.parent; - return ret; - } else { - throw new NoSuchElementException("No more elements available"); - } - } - }; - } + // Cached SchemaPath. + private volatile SchemaPath schemaPath; + // Cached hashCode + private volatile int hash; - /** - * Returns the immediate parent SchemaPath. - * - * @return Parent path, null if this SchemaPath is already toplevel. - */ - public SchemaNodeIdentifier getParent() { - return parent; + SchemaNodeIdentifier(final QName qname) { + this.qnames = requireNonNull(qname); } - /** - * Get the last component of this path. - * - * @return The last component of this path. - */ - public final QName getLastComponent() { - return qname; + SchemaNodeIdentifier(final Collection qnames) { + final ImmutableList tmp = ImmutableList.copyOf(qnames); + checkArgument(!tmp.isEmpty()); + this.qnames = tmp.size() == 1 ? tmp.get(0) : tmp; } - private SchemaPath createSchemaPath() { - final SchemaPath newPath; - if (parent == null) { - final SchemaPath parentPath = isAbsolute() ? SchemaPath.ROOT : SchemaPath.SAME; - newPath = qname == null ? parentPath : parentPath.createChild(qname); - } else { - newPath = parent.asSchemaPath().createChild(qname); - } - - return SCHEMAPATH_UPDATER.compareAndSet(this, null, newPath) ? newPath : schemaPath; + public @NonNull List getNodeIdentifiers() { + return qnames instanceof QName ? ImmutableList.of((QName) qnames) : (ImmutableList) qnames; } /** @@ -287,22 +115,22 @@ public abstract class SchemaNodeIdentifier implements Immutable { * * @return SchemaPath equivalent. */ - public final SchemaPath asSchemaPath() { + public final @NonNull SchemaPath asSchemaPath() { final SchemaPath ret = schemaPath; - return ret != null ? ret : createSchemaPath(); + return ret != null ? ret : loadSchemaPath(); } - /** - * Describes whether schema node identifier is|isn't absolute. - * - * @return boolean value which is true if schema path is - * absolute. - */ - public abstract boolean isAbsolute(); + private SchemaPath loadSchemaPath() { + final SchemaPath newPath = implicitSchemaPathParent().createChild(getNodeIdentifiers()); + return SCHEMAPATH_UPDATER.compareAndSet(this, null, newPath) ? newPath : schemaPath; + } + + abstract SchemaPath implicitSchemaPathParent(); @Override public final int hashCode() { - return hash; + final int local; + return (local = hash) != 0 ? local : (hash = qnames.hashCode()); } @Override @@ -310,22 +138,14 @@ public abstract class SchemaNodeIdentifier implements Immutable { if (this == obj) { return true; } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { + if (obj == null || getClass() != obj.getClass()) { return false; } - final SchemaNodeIdentifier other = (SchemaNodeIdentifier) obj; - return Objects.equals(qname, other.qname) && Objects.equals(parent, other.parent); + return qnames.equals(((SchemaNodeIdentifier) obj).qnames); } @Override public final String toString() { - return addToStringAttributes(MoreObjects.toStringHelper(this)).toString(); - } - - protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { - return toStringHelper.add("path", getPathFromRoot()); + return MoreObjects.toStringHelper(this).add("qnames", qnames).toString(); } } diff --git a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaTreeAwareEffectiveStatement.java b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaTreeAwareEffectiveStatement.java index 58a09a5042..6d845b7ef2 100644 --- a/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaTreeAwareEffectiveStatement.java +++ b/yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/stmt/SchemaTreeAwareEffectiveStatement.java @@ -20,7 +20,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement; /** * Interface implemented by all {@link EffectiveStatement}s which can contain a {@code schema tree} child. This tree * can be walked using {@link SchemaNodeIdentifier}, looking up each component of - * {@link SchemaNodeIdentifier#getPathFromRoot()} using {@link #findSchemaTreeNode(QName)}. + * {@link SchemaNodeIdentifier#getNodeIdentifiers()} using {@link #findSchemaTreeNode(QName)}. * * @param Argument type * @param Class representing declared version of this statement. diff --git a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java index fa9f8a540d..ff83cac19d 100644 --- a/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java +++ b/yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java @@ -1050,7 +1050,7 @@ public abstract class StatementContextBase, E || StmtContextUtils.producesDeclared(this, RefineStatement.class) || StmtContextUtils.producesDeclared(this, DeviationStatement.class))) { - return parentPath.createChild(((SchemaNodeIdentifier) argument).getPathFromRoot()); + return parentPath.createChild(((SchemaNodeIdentifier) argument).getNodeIdentifiers()); } // FIXME: this does not look right diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java index 20cbeb5f4e..fe9c4e58c9 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/namespace/ChildSchemaNodeNamespace.java @@ -77,7 +77,7 @@ public final class ChildSchemaNodeNamespace, */ public static Optional> findNode(final StmtContext root, final SchemaNodeIdentifier identifier) { - final Iterator iterator = identifier.getPathFromRoot().iterator(); + final Iterator iterator = identifier.getNodeIdentifiers().iterator(); if (!iterator.hasNext()) { return Optional.of(root); } diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/ArgumentUtils.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/ArgumentUtils.java index d1cebe0e9b..7e168e6a8b 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/ArgumentUtils.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/ArgumentUtils.java @@ -19,6 +19,8 @@ import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant; import org.opendaylight.yangtools.yang.model.api.stmt.UnresolvedNumber; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext; import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils; @@ -96,7 +98,11 @@ public final class ArgumentUtils { } } - return SchemaNodeIdentifier.create(qNames, PATH_ABS.matcher(path).matches()); + if (qNames.isEmpty()) { + throw new SourceException("Schema node identifier must not be empty", ctx.getStatementSourceReference()); + } + + return PATH_ABS.matcher(path).matches() ? Absolute.of(qNames) : Descendant.of(qNames); } private static String trimSingleLastSlashFromXPath(final String path) { diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java index fcf923d434..c292c9c761 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/augment/AbstractAugmentStatementSupport.java @@ -91,7 +91,7 @@ abstract class AbstractAugmentStatementSupport augmentAction.requiresCtx(augmentNode, ModelProcessingPhase.EFFECTIVE_MODEL); final Prerequisite>> target = augmentAction.mutatesEffectiveCtxPath( getSearchRoot(augmentNode), ChildSchemaNodeNamespace.class, - augmentNode.coerceStatementArgument().getPathFromRoot()); + augmentNode.coerceStatementArgument().getNodeIdentifiers()); augmentAction.apply(new InferenceAction() { @Override diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java index 04d39c06ed..f9d85c5b1b 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviate/AbstractDeviateStatementSupport.java @@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.deviate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.SetMultimap; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -138,7 +139,7 @@ abstract class AbstractDeviateStatementSupport final Prerequisite>> targetCtxPrerequisite = deviateAction.mutatesEffectiveCtxPath(deviateStmtCtx.getRoot(), - ChildSchemaNodeNamespace.class, deviationTarget.getPathFromRoot()); + ChildSchemaNodeNamespace.class, deviationTarget.getNodeIdentifiers()); deviateAction.apply(new InferenceAction() { @Override @@ -222,7 +223,7 @@ abstract class AbstractDeviateStatementSupport final QNameModule currentModule = deviateStmtCtx.getFromNamespace(ModuleCtxToModuleQName.class, deviateStmtCtx.getRoot()); - final QNameModule targetModule = deviationTarget.getLastComponent().getModule(); + final QNameModule targetModule = Iterables.getLast(deviationTarget.getNodeIdentifiers()).getModule(); final Set deviationModulesSupportedByTargetModule = modulesDeviatedByModules.get(targetModule); if (deviationModulesSupportedByTargetModule != null) { diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviation/DeviationStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviation/DeviationStatementSupport.java index bd4e994aad..0f1e78393f 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviation/DeviationStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/deviation/DeviationStatementSupport.java @@ -8,6 +8,7 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.deviation; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement; @@ -51,7 +52,8 @@ public final class DeviationStatementSupport final Mutable ctx) { final QNameModule currentModule = ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx.getRoot()); - final QNameModule targetModule = ctx.coerceStatementArgument().getLastComponent().getModule(); + final QNameModule targetModule = Iterables.getLast(ctx.coerceStatementArgument().getNodeIdentifiers()) + .getModule(); if (currentModule.equals(targetModule)) { throw new InferenceException(ctx.getStatementSourceReference(), diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/key/KeyStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/key/KeyStatementSupport.java index 3c514691c3..4286d4ebf7 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/key/KeyStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/key/KeyStatementSupport.java @@ -14,6 +14,7 @@ import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Iterables; import java.util.Collection; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.QName; @@ -51,7 +52,7 @@ public final class KeyStatementSupport final Builder builder = ImmutableSet.builder(); int tokens = 0; for (String keyToken : LIST_KEY_SPLITTER.split(value)) { - builder.add(SchemaNodeIdentifier.SAME.createChild(StmtContextUtils.parseNodeIdentifier(ctx, keyToken))); + builder.add(SchemaNodeIdentifier.Descendant.of(StmtContextUtils.parseNodeIdentifier(ctx, keyToken))); tokens++; } @@ -69,10 +70,10 @@ public final class KeyStatementSupport final Builder builder = ImmutableSet.builder(); boolean replaced = false; for (final SchemaNodeIdentifier arg : ctx.coerceStatementArgument()) { - final QName qname = arg.getLastComponent(); + final QName qname = Iterables.getLast(arg.getNodeIdentifiers()); if (!targetModule.equals(qname.getModule())) { final QName newQname = qname.bindTo(targetModule).intern(); - builder.add(SchemaNodeIdentifier.SAME.createChild(newQname)); + builder.add(SchemaNodeIdentifier.Descendant.of(newQname)); replaced = true; } else { builder.add(arg); diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/list/AbstractListStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/list/AbstractListStatementSupport.java index 968fec4a22..24bbfd07c7 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/list/AbstractListStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/list/AbstractListStatementSupport.java @@ -89,7 +89,7 @@ abstract class AbstractListStatementSupport extends BaseQNameStatementSupport
  • ctx) { super(ctx); - qname = verifyNotNull(ctx.coerceStatementArgument().getLastComponent()); + qname = Iterables.getLast(ctx.coerceStatementArgument().getNodeIdentifiers()); path = ctx.getSchemaPath().get(); refineTargetNode = (SchemaNode) ctx.getEffectOfStatement().iterator().next().buildEffective(); } diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/unique/UniqueStatementSupport.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/unique/UniqueStatementSupport.java index 09b2f984b2..6e0154a85f 100644 --- a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/unique/UniqueStatementSupport.java +++ b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/unique/UniqueStatementSupport.java @@ -15,6 +15,7 @@ import java.util.Set; import java.util.regex.Pattern; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Descendant; import org.opendaylight.yangtools.yang.model.api.stmt.UniqueEffectiveStatement; import org.opendaylight.yangtools.yang.model.api.stmt.UniqueStatement; @@ -80,7 +81,7 @@ public final class UniqueStatementSupport final Set uniqueConstraintNodes = new HashSet<>(); for (final String uniqueArgToken : SEP_SPLITTER.split(nocrlf)) { final SchemaNodeIdentifier nodeIdentifier = ArgumentUtils.nodeIdentifierFromPath(ctx, uniqueArgToken); - SourceException.throwIf(nodeIdentifier.isAbsolute(), ctx.getStatementSourceReference(), + SourceException.throwIf(nodeIdentifier instanceof Absolute, ctx.getStatementSourceReference(), "Unique statement argument '%s' contains schema node identifier '%s' " + "which is not in the descendant node identifier form.", argumentValue, uniqueArgToken); uniqueConstraintNodes.add((Descendant) nodeIdentifier); diff --git a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/AugmentArgumentParsingTest.java b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/AugmentArgumentParsingTest.java index e2b3600f32..747a3f6c80 100644 --- a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/AugmentArgumentParsingTest.java +++ b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/AugmentArgumentParsingTest.java @@ -10,7 +10,6 @@ package org.opendaylight.yangtools.yang.stmt; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.opendaylight.yangtools.yang.stmt.StmtTestUtils.sourceForResource; @@ -75,10 +74,8 @@ public class AugmentArgumentParsingTest { public void invalidAugEmptyTest() throws ReactorException { final ReactorException ex = assertReactorThrows(INVALID_EMPTY); final Throwable cause = ex.getCause(); - assertThat(cause, instanceOf(IllegalArgumentException.class)); - assertEquals( - "Namespace class org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace keys may" - + " not be empty", cause.getMessage()); + assertThat(cause, instanceOf(SourceException.class)); + assertThat(cause.getMessage(), startsWith("Schema node identifier must not be empty")); } @Test diff --git a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5946Test.java b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5946Test.java index 8a3018c9fa..ee20186e6f 100644 --- a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5946Test.java +++ b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/Bug5946Test.java @@ -35,9 +35,9 @@ public class Bug5946Test { private static final QName WITHOUT_UNIQUE = QName.create(NS, REV, "without-unique"); private static final QName SIMPLE_UNIQUE = QName.create(NS, REV, "simple-unique"); private static final QName MULTIPLE_UNIQUE = QName.create(NS, REV, "multiple-unique"); - private static final SchemaNodeIdentifier L1_ID = SchemaNodeIdentifier.create(false, L1); - private static final SchemaNodeIdentifier L2_ID = SchemaNodeIdentifier.create(false, L2); - private static final SchemaNodeIdentifier C_L3_ID = SchemaNodeIdentifier.create(false, C, L3); + private static final SchemaNodeIdentifier L1_ID = SchemaNodeIdentifier.Descendant.of(L1); + private static final SchemaNodeIdentifier L2_ID = SchemaNodeIdentifier.Descendant.of(L2); + private static final SchemaNodeIdentifier C_L3_ID = SchemaNodeIdentifier.Descendant.of(C, L3); @Test public void test() throws Exception { diff --git a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/DeviationResolutionTest.java b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/DeviationResolutionTest.java index c97e81db40..ae378a74dd 100644 --- a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/DeviationResolutionTest.java +++ b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/DeviationResolutionTest.java @@ -8,6 +8,8 @@ package org.opendaylight.yangtools.yang.stmt; +import static org.hamcrest.CoreMatchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -282,7 +284,7 @@ public class DeviationResolutionTest { } catch (final ReactorException ex) { final Throwable cause = ex.getCause().getCause(); assertTrue(cause instanceof InferenceException); - assertTrue(cause.getMessage().startsWith("Deviation target 'Absolute{path=[(bar?revision=2017-01-20)" + assertThat(cause.getMessage(), startsWith("Deviation target 'Absolute{qnames=[(bar?revision=2017-01-20)" + "invalid, (bar?revision=2017-01-20)path]}' not found")); } } diff --git a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java index c46257223c..0ecf34c845 100644 --- a/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java +++ b/yang/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/YangParserNegativeTest.java @@ -81,7 +81,7 @@ public class YangParserNegativeTest { final Throwable rootCause = Throwables.getRootCause(e); assertThat(rootCause, isA(InferenceException.class)); assertThat(rootCause.getMessage(), startsWith( - "Augment target 'Absolute{path=[(urn:simple.container.demo)unknown]}' not found")); + "Augment target 'Absolute{qnames=(urn:simple.container.demo)unknown}' not found")); } } @@ -92,7 +92,7 @@ public class YangParserNegativeTest { fail("ReactorException should be thrown"); } catch (final ReactorException e) { assertThat(e.getCause().getMessage(), containsString("Error in module 'test4' in the refine of uses " - + "'Descendant{path=[(urn:simple.container.demo)node]}': can not perform refine of 'PRESENCE' for" + + "'Descendant{qnames=(urn:simple.container.demo)node}': can not perform refine of 'PRESENCE' for" + " the target 'LEAF_LIST'.")); } } diff --git a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java index 4a1ef8e113..6989469285 100644 --- a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java +++ b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContextUtils.java @@ -12,6 +12,7 @@ import static java.util.Objects.requireNonNull; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import java.util.Collection; import java.util.Optional; import java.util.Set; @@ -446,7 +447,7 @@ public final class StmtContextUtils { private static boolean isListKey(final StmtContext leafStmtCtx, final StmtContext, ?, ?> keyStmtCtx) { for (final SchemaNodeIdentifier keyIdentifier : keyStmtCtx.coerceStatementArgument()) { - if (leafStmtCtx.getStatementArgument().equals(keyIdentifier.getLastComponent())) { + if (leafStmtCtx.getStatementArgument().equals(Iterables.getLast(keyIdentifier.getNodeIdentifiers()))) { return true; } } -- 2.36.6