<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-codec-xml</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-util</artifactId>
+ <!-- FIXME: remove this override -->
+ <version>7.0.15</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
-import org.opendaylight.yangtools.yang.model.api.ContainerLike;
+import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
-public final class InstanceIdentifierContext {
- private final YangInstanceIdentifier instanceIdentifier;
- private final SchemaNode schemaNode;
- private final DOMMountPoint mountPoint;
- private final EffectiveModelContext schemaContext;
+public abstract class InstanceIdentifierContext {
+ private static final class Root extends InstanceIdentifierContext {
+ private final @NonNull EffectiveModelContext context;
- private InstanceIdentifierContext(final EffectiveModelContext context, final DOMMountPoint mountPoint) {
- instanceIdentifier = YangInstanceIdentifier.empty();
- schemaContext = requireNonNull(context);
- schemaNode = schemaContext;
- this.mountPoint = mountPoint;
+ Root(final EffectiveModelContext context, final DOMMountPoint mountPoint) {
+ super(context, mountPoint);
+ this.context = requireNonNull(context);
+ }
+
+ @Override
+ public EffectiveModelContext getSchemaContext() {
+ return context;
+ }
+
+ @Override
+ public YangInstanceIdentifier getInstanceIdentifier() {
+ return YangInstanceIdentifier.empty();
+ }
+
+ @Override
+ public Inference inference() {
+ return SchemaInferenceStack.of(context).toInference();
+ }
+
+ @Override
+ InstanceIdentifierContext createWithConcapt(final List<PathArgument> concatArgs) {
+ return new DataPath(context, getMountPoint(), SchemaInferenceStack.of(context),
+ YangInstanceIdentifier.create(concatArgs));
+ }
}
- private InstanceIdentifierContext(final EffectiveModelContext context, final RpcDefinition rpc,
- final DOMMountPoint mountPoint) {
- instanceIdentifier = null;
- schemaContext = requireNonNull(context);
- schemaNode = requireNonNull(rpc);
- this.mountPoint = mountPoint;
+ private static final class DataPath extends InstanceIdentifierContext {
+ private final @NonNull YangInstanceIdentifier path;
+ private final @NonNull SchemaInferenceStack stack;
+
+ private DataPath(final SchemaNode schemaNode, final DOMMountPoint mountPoint,
+ final SchemaInferenceStack stack, final YangInstanceIdentifier path) {
+ super(schemaNode, mountPoint);
+ this.stack = requireNonNull(stack);
+ this.path = requireNonNull(path);
+ }
+
+ static @NonNull DataPath of(final EffectiveModelContext context, final YangInstanceIdentifier path,
+ final DOMMountPoint mountPoint) {
+ final var nodeAndStack = DataSchemaContextTree.from(context).enterPath(path).orElseThrow();
+ return new DataPath(nodeAndStack.node().getDataSchemaNode(), mountPoint, nodeAndStack.stack(), path);
+ }
+
+ @Override
+ public YangInstanceIdentifier getInstanceIdentifier() {
+ return path;
+ }
+
+ @Override
+ public Inference inference() {
+ return stack.toInference();
+ }
+
+ @Override
+ @NonNull
+ InstanceIdentifierContext createWithConcapt(final List<PathArgument> concatArgs) {
+ final var newInstanceIdentifier = YangInstanceIdentifier.create(
+ Iterables.concat(path.getPathArguments(), concatArgs));
+ return new DataPath(getSchemaNode(), getMountPoint(), stack, newInstanceIdentifier);
+ }
}
- private InstanceIdentifierContext(final EffectiveModelContext context, final ContainerLike rpcInputOutput,
- final DOMMountPoint mountPoint) {
- instanceIdentifier = null;
- schemaContext = requireNonNull(context);
- schemaNode = requireNonNull(rpcInputOutput);
- this.mountPoint = mountPoint;
+ private static final class WithoutDataPath extends InstanceIdentifierContext {
+ private final @NonNull SchemaInferenceStack stack;
+
+ private WithoutDataPath(final SchemaNode schemaNode, final DOMMountPoint mountPoint,
+ final SchemaInferenceStack stack) {
+ super(schemaNode, mountPoint);
+ this.stack = requireNonNull(stack);
+ }
+
+ @Override
+ public Inference inference() {
+ return stack.toInference();
+ }
+
+ @Override
+ public @Nullable YangInstanceIdentifier getInstanceIdentifier() {
+ return null;
+ }
+
+ @Override
+ InstanceIdentifierContext createWithConcapt(final List<PathArgument> concatArgs) {
+ return this;
+ }
}
- @Deprecated(forRemoval = true)
- public InstanceIdentifierContext(final YangInstanceIdentifier instanceIdentifier, final SchemaNode schemaNode,
- final DOMMountPoint mountPoint, final EffectiveModelContext context) {
- this.instanceIdentifier = instanceIdentifier;
- this.schemaNode = schemaNode;
+ private final @NonNull SchemaNode schemaNode;
+ private final @Nullable DOMMountPoint mountPoint;
+
+ InstanceIdentifierContext(final SchemaNode schemaNode, final DOMMountPoint mountPoint) {
+ this.schemaNode = requireNonNull(schemaNode);
this.mountPoint = mountPoint;
- schemaContext = context;
}
public static @NonNull InstanceIdentifierContext ofLocalRoot(final EffectiveModelContext context) {
- return new InstanceIdentifierContext(context, null);
+ return new Root(context, null);
}
@VisibleForTesting
public static @NonNull InstanceIdentifierContext ofLocalPath(final EffectiveModelContext context,
final YangInstanceIdentifier path) {
- return new InstanceIdentifierContext(requireNonNull(path),
- DataSchemaContextTree.from(context).findChild(path).orElseThrow().getDataSchemaNode(), null,
- requireNonNull(context));
+ return DataPath.of(context, path, null);
}
// Legacy bierman02 invokeRpc()
- public static @NonNull InstanceIdentifierContext ofLocalRpc(final EffectiveModelContext context,
- // FIXME: this this method really needed?
- final RpcDefinition rpc) {
- return new InstanceIdentifierContext(context, rpc, null);
+ public static @NonNull InstanceIdentifierContext ofRpcInput(final EffectiveModelContext context,
+ // FIXME: this this method really needed?
+ final RpcDefinition rpc, final @Nullable DOMMountPoint mountPoint) {
+ final var stack = SchemaInferenceStack.of(context);
+ stack.enterSchemaTree(rpc.getQName());
+ stack.enterSchemaTree(rpc.getInput().getQName());
+ return new WithoutDataPath(rpc, mountPoint, stack);
+ }
+
+ public static @NonNull InstanceIdentifierContext ofRpcOutput(final EffectiveModelContext context,
+ // FIXME: this this method really needed?
+ final RpcDefinition rpc, final @Nullable DOMMountPoint mountPoint) {
+ final var stack = SchemaInferenceStack.of(context);
+ stack.enterSchemaTree(rpc.getQName());
+ stack.enterSchemaTree(rpc.getOutput().getQName());
+ return new WithoutDataPath(rpc, mountPoint, stack);
}
// Invocations of various identifier-less details
public static @NonNull InstanceIdentifierContext ofDataSchemaNode(final EffectiveModelContext context,
final DataSchemaNode schemaNode) {
- return new InstanceIdentifierContext(null, requireNonNull(schemaNode), null, requireNonNull(context));
+ return new WithoutDataPath(schemaNode, null,
+ SchemaInferenceStack.ofInstantiatedPath(context, schemaNode.getPath()));
}
// Invocations of various identifier-less details, potentially having a mount point
public static @NonNull InstanceIdentifierContext ofDataSchemaNode(final EffectiveModelContext context,
final DataSchemaNode schemaNode, final @Nullable DOMMountPoint mountPoint) {
- return new InstanceIdentifierContext(null, requireNonNull(schemaNode), mountPoint, requireNonNull(context));
+ return new WithoutDataPath(schemaNode, mountPoint,
+ SchemaInferenceStack.ofSchemaPath(context, schemaNode.getPath()));
}
public static @NonNull InstanceIdentifierContext ofLocalRpcInput(final EffectiveModelContext context,
// FIXME: this this method really needed?
final RpcDefinition rpc) {
- return new InstanceIdentifierContext(context, rpc.getInput(), null);
+ final var stack = SchemaInferenceStack.of(context);
+ stack.enterSchemaTree(rpc.getQName());
+ stack.enterSchemaTree(rpc.getInput().getQName());
+ return new WithoutDataPath(rpc.getInput(), null, stack);
}
public static @NonNull InstanceIdentifierContext ofLocalRpcOutput(final EffectiveModelContext context,
// FIXME: we want to re-validate this, so might as well take a QName
final RpcDefinition rpc) {
- return new InstanceIdentifierContext(context, rpc, null);
+ final var stack = SchemaInferenceStack.of(context);
+ stack.enterSchemaTree(rpc.getQName());
+ stack.enterSchemaTree(rpc.getOutput().getQName());
+ return new WithoutDataPath(rpc, null, stack);
+ }
+
+ public static @NonNull InstanceIdentifierContext ofAction(final SchemaInferenceStack stack,
+ final ActionDefinition schemaNode, final YangInstanceIdentifier path,
+ final @Nullable DOMMountPoint mountPoint) {
+ return new DataPath(schemaNode, mountPoint, stack, path);
+ }
+
+ public static @NonNull InstanceIdentifierContext ofPath(final SchemaInferenceStack stack,
+ final SchemaNode schemaNode, final YangInstanceIdentifier path,
+ final @Nullable DOMMountPoint mountPoint) {
+ return new DataPath(schemaNode, mountPoint, stack, path);
}
public static @NonNull InstanceIdentifierContext ofMountPointRoot(final DOMMountPoint mountPoint,
final EffectiveModelContext mountContext) {
- return new InstanceIdentifierContext(mountContext, requireNonNull(mountPoint));
+ return new Root(mountContext, requireNonNull(mountPoint));
}
@VisibleForTesting
public static @NonNull InstanceIdentifierContext ofMountPointPath(final DOMMountPoint mountPoint,
final EffectiveModelContext context, final YangInstanceIdentifier path) {
- return new InstanceIdentifierContext(requireNonNull(path),
- DataSchemaContextTree.from(context).findChild(path).orElseThrow().getDataSchemaNode(),
- requireNonNull(mountPoint), requireNonNull(context));
- }
-
- public static @NonNull InstanceIdentifierContext ofMountPointRpc(final DOMMountPoint mountPoint,
- final EffectiveModelContext mountContext, final RpcDefinition rpc) {
- return new InstanceIdentifierContext(mountContext, rpc, requireNonNull(mountPoint));
+ return DataPath.of(context, path, requireNonNull(mountPoint));
}
public static @NonNull InstanceIdentifierContext ofMountPointRpcOutput(final DOMMountPoint mountPoint,
final EffectiveModelContext mountContext, final RpcDefinition rpc) {
- return new InstanceIdentifierContext(mountContext, rpc, requireNonNull(mountPoint));
+ final var stack = SchemaInferenceStack.of(mountContext);
+ stack.enterSchemaTree(rpc.getQName());
+ stack.enterSchemaTree(rpc.getOutput().getQName());
+ return new WithoutDataPath(rpc, requireNonNull(mountPoint), stack);
}
// FIXME: what the heck are the callers of this doing?!
- public @NonNull InstanceIdentifierContext withConcatenatedArgs(final List<PathArgument> concatArgs) {
- if (instanceIdentifier == null || concatArgs.isEmpty()) {
- return this;
- }
- final var newInstanceIdentifier = YangInstanceIdentifier.create(
- Iterables.concat(instanceIdentifier.getPathArguments(), concatArgs));
- return new InstanceIdentifierContext(newInstanceIdentifier, schemaNode, mountPoint, schemaContext);
+ public final @NonNull InstanceIdentifierContext withConcatenatedArgs(final List<PathArgument> concatArgs) {
+ return concatArgs.isEmpty() ? this : createWithConcapt(concatArgs);
}
- public YangInstanceIdentifier getInstanceIdentifier() {
- return instanceIdentifier;
- }
+ abstract @NonNull InstanceIdentifierContext createWithConcapt(List<PathArgument> concatArgs);
- public SchemaNode getSchemaNode() {
+ public final @NonNull SchemaNode getSchemaNode() {
return schemaNode;
}
- public DOMMountPoint getMountPoint() {
+ public final @Nullable DOMMountPoint getMountPoint() {
return mountPoint;
}
- public EffectiveModelContext getSchemaContext() {
- return schemaContext;
+ public @NonNull EffectiveModelContext getSchemaContext() {
+ return inference().getEffectiveModelContext();
}
+
+ public abstract @NonNull Inference inference();
+
+ public abstract @Nullable YangInstanceIdentifier getInstanceIdentifier();
}
operationsBuilder.withChild(ImmutableNodes.leafNode(leaf.getQName(), Empty.value()));
}
- return Map.entry(new InstanceIdentifierContext(null, operatationsSchema, mountPoint,
- new OperationsEffectiveModuleContext(ImmutableSet.copyOf(modules))), operationsBuilder.build());
+ return Map.entry(InstanceIdentifierContext.ofDataSchemaNode(
+ new OperationsEffectiveModuleContext(ImmutableSet.copyOf(modules)), operatationsSchema, mountPoint),
+ operationsBuilder.build());
}
}
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
import org.opendaylight.yangtools.yang.data.impl.schema.ResultAlreadySetException;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
- final SchemaInferenceStack parentSchema;
- if (isPost) {
- // FIXME: We need dispatch for RPC.
- parentSchema = SchemaInferenceStack.ofSchemaPath(path.getSchemaContext(), path.getSchemaNode().getPath());
- } else if (path.getSchemaNode() instanceof SchemaContext
- || SchemaPath.ROOT.equals(path.getSchemaNode().getPath().getParent())) {
- parentSchema = SchemaInferenceStack.of(path.getSchemaContext());
+ final Inference parentInference;
+ if (isPost && !(path.getSchemaNode() instanceof RpcDefinition)) {
+ parentInference = path.inference();
} else {
- parentSchema = SchemaInferenceStack.ofSchemaPath(path.getSchemaContext(),
- path.getSchemaNode().getPath().getParent());
+ final var inference = path.inference();
+ if (!inference.statementPath().isEmpty()) {
+ final var stack = inference.toSchemaInferenceStack();
+ stack.exit();
+ parentInference = stack.toInference();
+ } else {
+ parentInference = inference;
+ }
}
final JsonParserStream jsonParser = JsonParserStream.create(writer,
JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(path.getSchemaContext()),
- parentSchema.toInference());
+ parentInference);
final JsonReader reader = new JsonReader(new InputStreamReader(nonEmptyInputStreamOptional.get(),
StandardCharsets.UTF_8));
jsonParser.parse(reader);
errContBuild.withChild(listErorsBuilder.build());
final NormalizedNodeContext errContext = new NormalizedNodeContext(InstanceIdentifierContext.ofDataSchemaNode(
- controllerContext.getGlobalSchema(), (DataSchemaNode) errorsSchemaNode), errContBuild.build());
+ controllerContext.getGlobalSchema(), (DataSchemaNode) errorsSchemaNode, null), errContBuild.build());
Object responseBody;
if (mediaType.getSubtype().endsWith("json")) {
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
import static java.util.Objects.requireNonNull;
import com.google.common.base.Splitter;
ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED);
}
- final YangInstanceIdentifier partialPath = dataNormalizer.toNormalized(builder.build());
+ final YangInstanceIdentifier partialPath = dataNormalizer.toNormalized(builder.build()).getKey();
final Optional<DOMMountPoint> mountOpt = mountService.getMountPoint(partialPath);
if (mountOpt.isEmpty()) {
LOG.debug("Instance identifier to missing mount point: {}", partialPath);
rpc = getRpcDefinition(module, rpcName);
}
if (rpc != null) {
- return mountPoint == null ? InstanceIdentifierContext.ofLocalRpc(globalSchema, rpc)
- : InstanceIdentifierContext.ofMountPointRpc(mountPoint, getModelContext(mountPoint), rpc);
+ final var ctx = mountPoint == null ? globalSchema : getModelContext(mountPoint);
+ return InstanceIdentifierContext.ofRpcInput(ctx, rpc, mountPoint);
}
}
private static InstanceIdentifierContext createContext(final YangInstanceIdentifier instance,
final DataSchemaNode dataSchemaNode, final DOMMountPoint mountPoint,
final EffectiveModelContext schemaContext) {
- final YangInstanceIdentifier instanceIdentifier = new DataNormalizer(schemaContext).toNormalized(instance);
- return new InstanceIdentifierContext(instanceIdentifier, dataSchemaNode, mountPoint, schemaContext);
+ final var normalized = new DataNormalizer(schemaContext).toNormalized(instance);
+
+ // FIXME: Verification before we trust this
+ final var stack = normalized.getValue();
+ if (!stack.isEmpty()) {
+ final var stackPath = stack.toSchemaPath();
+ final var nodePath = dataSchemaNode.getPath();
+ verify(stackPath.equals(nodePath), "Mismatched path: expected %s got %s", nodePath, stackPath);
+ } else {
+ verify(dataSchemaNode.equals(schemaContext), "Unexpected node %s", dataSchemaNode);
+ }
+
+ return InstanceIdentifierContext.ofPath(normalized.getValue(), dataSchemaNode, normalized.getKey(), mountPoint);
}
public static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container,
return builder.toString();
}
- public YangInstanceIdentifier toNormalized(final YangInstanceIdentifier legacy) {
- try {
- return dataNormalizer.toNormalized(legacy);
- } catch (final NullPointerException e) {
- throw new RestconfDocumentedException("Data normalizer isn't set. Normalization isn't possible", e);
- }
- }
-
public YangInstanceIdentifier toXpathRepresentation(final YangInstanceIdentifier instanceIdentifier) {
try {
return dataNormalizer.toLegacy(instanceIdentifier);
package org.opendaylight.netconf.sal.restconf.impl;
import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
class DataNormalizer {
private final DataNormalizationOperation<?> operation;
+ private final EffectiveModelContext context;
DataNormalizer(final EffectiveModelContext ctx) {
+ context = requireNonNull(ctx);
operation = DataNormalizationOperation.from(ctx);
}
- YangInstanceIdentifier toNormalized(final YangInstanceIdentifier legacy) {
+ Entry<YangInstanceIdentifier, SchemaInferenceStack> toNormalized(final YangInstanceIdentifier legacy) {
List<PathArgument> normalizedArgs = new ArrayList<>();
DataNormalizationOperation<?> currentOp = operation;
Iterator<PathArgument> arguments = legacy.getPathArguments().iterator();
+ SchemaInferenceStack stack = SchemaInferenceStack.of(context);
try {
while (arguments.hasNext()) {
PathArgument legacyArg = arguments.next();
- currentOp = currentOp.getChild(legacyArg);
+ currentOp = currentOp.enterChild(legacyArg, stack);
checkArgument(currentOp != null,
"Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",
legacy, normalizedArgs);
while (currentOp.isMixin()) {
normalizedArgs.add(currentOp.getIdentifier());
- currentOp = currentOp.getChild(legacyArg.getNodeType());
+ currentOp = currentOp.enterChild(legacyArg.getNodeType(), stack);
}
normalizedArgs.add(legacyArg);
}
throw new IllegalArgumentException("Failed to normalize path " + legacy, e);
}
- return YangInstanceIdentifier.create(normalizedArgs);
+ return Map.entry(YangInstanceIdentifier.create(normalizedArgs), stack);
}
DataNormalizationOperation<?> getOperation(final YangInstanceIdentifier legacy)
SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) modulesSchemaNode);
moduleContainerBuilder.withChild(allModuleMap);
- return new NormalizedNodeContext(InstanceIdentifierContext.ofDataSchemaNode(schemaContext, modulesSchemaNode),
- moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
+ return new NormalizedNodeContext(
+ InstanceIdentifierContext.ofDataSchemaNode(schemaContext, modulesSchemaNode, null),
+ moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
}
/**
moduleContainerBuilder.withChild(mountPointModulesMap);
return new NormalizedNodeContext(
- InstanceIdentifierContext.ofDataSchemaNode(controllerContext.getGlobalSchema(), modulesSchemaNode),
- moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
+ InstanceIdentifierContext.ofDataSchemaNode(controllerContext.getGlobalSchema(), modulesSchemaNode, null),
+ moduleContainerBuilder.build(), QueryParametersParser.parseWriterParameters(uriInfo));
}
@Override
}
final var resultNodeSchema = (RpcDefinition) payload.getInstanceIdentifierContext().getSchemaNode();
- final var info = mountPoint == null ? InstanceIdentifierContext.ofLocalRpc(schemaContext, resultNodeSchema)
- : InstanceIdentifierContext.ofMountPointRpcOutput(mountPoint, schemaContext, resultNodeSchema);
-
- return new NormalizedNodeContext(info, resultData, QueryParametersParser.parseWriterParameters(uriInfo));
+ return new NormalizedNodeContext(
+ InstanceIdentifierContext.ofRpcOutput(schemaContext, resultNodeSchema, mountPoint), resultData,
+ QueryParametersParser.parseWriterParameters(uriInfo));
}
@SuppressFBWarnings(value = "NP_LOAD_OF_KNOWN_NULL_VALUE",
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
/**
* Unit tests for BrokerFacade.
when(patchContext.getData()).thenReturn(List.of());
// no mount point
- doReturn(InstanceIdentifierContext.ofDataSchemaNode(
- mock(EffectiveModelContext.class), mock(DataSchemaNode.class)))
+ doReturn(InstanceIdentifierContext.ofPath(SchemaInferenceStack.of(mock(EffectiveModelContext.class)),
+ mock(DataSchemaNode.class), YangInstanceIdentifier.empty(), null))
.when(patchContext).getInstanceIdentifierContext();
doReturn(CommitInfo.emptyFluentFuture()).when(rwTransaction).commit();
when(patchContext.getData()).thenReturn(List.of());
// return mount point with broker
- doReturn(InstanceIdentifierContext.ofDataSchemaNode(
- mock(EffectiveModelContext.class), mock(DataSchemaNode.class), mountPoint))
+ doReturn(InstanceIdentifierContext.ofPath(SchemaInferenceStack.of(mock(EffectiveModelContext.class)),
+ mock(DataSchemaNode.class), YangInstanceIdentifier.empty(), mountPoint))
.when(patchContext).getInstanceIdentifierContext();
when(mountPoint.getService(DOMDataBroker.class)).thenReturn(Optional.of(mountDataBroker));
final PatchContext patchContext = mock(PatchContext.class);
final DOMMountPoint mountPoint = mock(DOMMountPoint.class);
- doReturn(InstanceIdentifierContext.ofDataSchemaNode(
- mock(EffectiveModelContext.class), mock(DataSchemaNode.class), mountPoint))
+ doReturn(InstanceIdentifierContext.ofPath(SchemaInferenceStack.of(mock(EffectiveModelContext.class)),
+ mock(DataSchemaNode.class), YangInstanceIdentifier.empty(), mountPoint))
.when(patchContext).getInstanceIdentifierContext();
// missing broker on mounted device
contNode.withChild(lfNode);
container.withChild(contNode.build());
- return new NormalizedNodeContext(InstanceIdentifierContext.ofLocalRpc(schema, rpcSchemaNode),
+ return new NormalizedNodeContext(InstanceIdentifierContext.ofRpcInput(schema, rpcSchemaNode, null),
container.build());
}
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.withSettings;
import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
import com.google.common.collect.Iterables;
import org.opendaylight.yangtools.yang.common.ErrorTag;
import org.opendaylight.yangtools.yang.common.ErrorType;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.InputSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.OutputSchemaNode;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
@Test
public void testRpcForMountpoint() throws Exception {
+ final QName qname = QName.create("namespace", "2010-10-10", "localname");
final UriInfo uriInfo = mock(UriInfo.class);
doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters(anyBoolean());
final NormalizedNodeContext ctx = mock(NormalizedNodeContext.class);
- final RpcDefinition schemaNode = mock(RpcDefinition.class);
- doReturn(mock(SchemaPath.class)).when(schemaNode).getPath();
- doReturn(QName.create("namespace", "2010-10-10", "localname")).when(schemaNode).getQName();
+ final RpcDefinition rpc = mock(RpcDefinition.class,
+ withSettings().extraInterfaces(RpcEffectiveStatement.class));
+ doReturn(mock(SchemaPath.class)).when(rpc).getPath();
+ doReturn(qname).when(rpc).getQName();
+
+ final InputSchemaNode input = mock(InputSchemaNode.class,
+ withSettings().extraInterfaces(InputEffectiveStatement.class));
+ final QName inputQName = YangConstants.operationInputQName(qname.getModule());
+ doReturn(input).when(rpc).getInput();
+ doReturn(inputQName).when(input).getQName();
+ doReturn(Optional.of(input)).when((RpcEffectiveStatement) rpc).findSchemaTreeNode(inputQName);
+
+ final OutputSchemaNode output = mock(OutputSchemaNode.class,
+ withSettings().extraInterfaces(OutputEffectiveStatement.class));
+ final QName outputQName = YangConstants.operationInputQName(qname.getModule());
+ doReturn(output).when(rpc).getOutput();
+ doReturn(outputQName).when(output).getQName();
+ doReturn(Optional.of(output)).when((RpcEffectiveStatement) rpc).findSchemaTreeNode(outputQName);
+
+ final EffectiveModelContext mountContext = mock(EffectiveModelContext.class);
+ final ModuleEffectiveStatement mountModule = mock(ModuleEffectiveStatement.class);
+ doReturn(Map.of(qname.getModule(), mountModule)).when(mountContext).getModuleStatements();
+ doReturn(Optional.of(rpc)).when(mountModule).findSchemaTreeNode(qname);
final DOMMountPoint mount = mock(DOMMountPoint.class);
- doReturn(Optional.of(FixedDOMSchemaService.of(schemaContext))).when(mount).getService(DOMSchemaService.class);
+ doReturn(Optional.of(FixedDOMSchemaService.of(mountContext))).when(mount).getService(DOMSchemaService.class);
- doReturn(InstanceIdentifierContext.ofMountPointRpc(mount, schemaContext, schemaNode))
+ doReturn(InstanceIdentifierContext.ofRpcInput(mountContext, rpc, mount))
.when(ctx).getInstanceIdentifierContext();
final DOMRpcService rpcService = mock(DOMRpcService.class);
*/
@Test
public void createNotificationStreamTest() {
- final NormalizedNodeContext payload = mock(NormalizedNodeContext.class);
+ final QName rpcQName = QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote",
+ "2014-01-14", "create-notification-stream");
- final RpcDefinition schemaNode = mock(RpcDefinition.class);
- doReturn(mock(SchemaPath.class)).when(schemaNode).getPath();
- doReturn(InstanceIdentifierContext.ofLocalRpc(schemaContext, schemaNode)).when(payload)
- .getInstanceIdentifierContext();
+ final RpcDefinition schemaNode = schemaContext.getOperations().stream()
+ .filter(rpc -> rpc.getQName().equals(rpcQName))
+ .findFirst()
+ .orElseThrow();
- doReturn(QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote",
- "2014-01-14", "create-notification-stream")).when(schemaNode).getQName();
+ final NormalizedNodeContext payload = mock(NormalizedNodeContext.class);
+ doReturn(InstanceIdentifierContext.ofRpcInput(schemaContext, schemaNode, null)).when(payload)
+ .getInstanceIdentifierContext();
final Set<DataContainerChild> children = new HashSet<>();
final LeafSetNode child = mock(LeafSetNode.class);
when(rpcDef.getPath()).thenReturn(SchemaPath.create(true, rpcQName));
when(rpcDef.getQName()).thenReturn(rpcQName);
- return new NormalizedNodeContext(InstanceIdentifierContext.ofLocalRpc(schema, rpcDef), container.build());
+ return new NormalizedNodeContext(InstanceIdentifierContext.ofRpcInput(schema, rpcDef, null), container.build());
}
}
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-util</artifactId>
+ <!-- FIXME: remove this override -->
+ <version>7.0.15</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
final Absolute schemaPath = Absolute.of(ImmutableList.copyOf(context.getSchemaNode().getPath()
.getPathFromRoot()));
final DOMActionResult response;
- final EffectiveModelContext schemaContextRef;
if (mountPoint != null) {
response = invokeAction((ContainerNode) data, schemaPath, yangIIdContext, mountPoint);
- schemaContextRef = modelContext(mountPoint);
} else {
response = invokeAction((ContainerNode) data, schemaPath, yangIIdContext, actionService);
- schemaContextRef = schemaContextHandler.get();
}
final DOMActionResult result = checkActionResponse(response);
- ActionDefinition resultNodeSchema = null;
ContainerNode resultData = null;
if (result != null) {
- final Optional<ContainerNode> optOutput = result.getOutput();
- if (optOutput.isPresent()) {
- resultData = optOutput.get();
- resultNodeSchema = (ActionDefinition) context.getSchemaNode();
- }
+ resultData = result.getOutput().orElse(null);
}
if (resultData != null && resultData.isEmpty()) {
}
return Response.status(Status.OK)
- .entity(NormalizedNodePayload.ofNullable(
- new InstanceIdentifierContext(yangIIdContext, resultNodeSchema, mountPoint, schemaContextRef),
- resultData))
+ .entity(NormalizedNodePayload.ofNullable(context, resultData))
.build();
}
(LeafSchemaNode) ((ContainerSchemaNode) grouping.getDataChildByName(Restconf.QNAME))
.getDataChildByName(YANG_LIBRARY_VERSION);
- return NormalizedNodePayload.of(InstanceIdentifierContext.ofDataSchemaNode(context, schemaNode),
+ return NormalizedNodePayload.of(InstanceIdentifierContext.ofDataSchemaNode(context, schemaNode, null),
ImmutableNodes.leafNode(YANG_LIBRARY_VERSION, IetfYangLibrary.REVISION.toString()));
}
}
public static YangInstanceIdentifier deserialize(final String data, final EffectiveModelContext schemaContext) {
return data == null ? YangInstanceIdentifier.empty()
- : YangInstanceIdentifier.create(YangInstanceIdentifierDeserializer.create(schemaContext, data));
+ : YangInstanceIdentifierDeserializer.create(schemaContext, data).path;
}
}
package org.opendaylight.restconf.nb.rfc8040.utils.parser;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.base.Verify.verifyNotNull;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import org.opendaylight.yangtools.yang.common.Revision;
import org.opendaylight.yangtools.yang.common.YangNames;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
-import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
-import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
*/
private static InstanceIdentifierContext createIIdContext(final EffectiveModelContext schemaContext,
final String url, final @Nullable DOMMountPoint mountPoint) {
- final YangInstanceIdentifier urlPath = IdentifierCodec.deserialize(url, schemaContext);
// First things first: an empty path means data invocation on SchemaContext
- if (urlPath.isEmpty()) {
+ if (url == null) {
return mountPoint != null ? InstanceIdentifierContext.ofMountPointRoot(mountPoint, schemaContext)
: InstanceIdentifierContext.ofLocalRoot(schemaContext);
}
- return new InstanceIdentifierContext(urlPath, getPathSchema(schemaContext, urlPath), mountPoint, schemaContext);
- }
-
- private static SchemaNode getPathSchema(final EffectiveModelContext schemaContext,
- final YangInstanceIdentifier urlPath) {
- // Peel the last component and locate the parent data node, empty path resolves to SchemaContext
- final DataSchemaContextNode<?> parent = DataSchemaContextTree.from(schemaContext)
- .findChild(verifyNotNull(urlPath.getParent()))
- .orElseThrow(
- // Parent data node is not present, this is not a valid location.
- () -> new RestconfDocumentedException("Parent of " + urlPath + " not found",
- ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE));
-
- // Now try to resolve the last component as a data item...
- final DataSchemaContextNode<?> data = parent.getChild(urlPath.getLastPathArgument());
- if (data != null) {
- return data.getDataSchemaNode();
- }
-
- // ... otherwise this has to be an operation invocation. RPCs cannot be defined anywhere but schema root,
- // actions can reside everywhere else (and SchemaContext reports them empty)
- final QName qname = urlPath.getLastPathArgument().getNodeType();
- final DataSchemaNode parentSchema = parent.getDataSchemaNode();
- if (parentSchema instanceof SchemaContext) {
- for (final RpcDefinition rpc : ((SchemaContext) parentSchema).getOperations()) {
- if (qname.equals(rpc.getQName())) {
- return rpc;
- }
- }
- }
- if (parentSchema instanceof ActionNodeContainer) {
- for (final ActionDefinition action : ((ActionNodeContainer) parentSchema).getActions()) {
- if (qname.equals(action.getQName())) {
- return action;
- }
- }
- }
-
- // No luck: even if we found the parent, we did not locate a data, nor RPC, nor action node, hence the URL
- // is deemed invalid
- throw new RestconfDocumentedException("Context for " + urlPath + " not found", ErrorType.PROTOCOL,
- ErrorTag.INVALID_VALUE);
+ final var result = YangInstanceIdentifierDeserializer.create(schemaContext, url);
+ return InstanceIdentifierContext.ofPath(result.stack, result.node, result.path, mountPoint);
}
/**
*/
package org.opendaylight.restconf.nb.rfc8040.utils.parser;
+import static com.google.common.base.Verify.verify;
import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.text.ParseException;
import java.util.ArrayList;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.IdentityEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
* Deserializer for {@link String} to {@link YangInstanceIdentifier} for restconf.
*/
public final class YangInstanceIdentifierDeserializer {
+ public static final class Result {
+ public final @NonNull YangInstanceIdentifier path;
+ public final @NonNull SchemaInferenceStack stack;
+ public final @NonNull SchemaNode node;
+
+ Result(final EffectiveModelContext context) {
+ path = YangInstanceIdentifier.empty();
+ node = requireNonNull(context);
+ stack = SchemaInferenceStack.of(context);
+ }
+
+ Result(final EffectiveModelContext context, final QName qname) {
+ // Legacy behavior: RPCs do not really have a YangInstanceIdentifier, but the rest of the code expects it
+ path = YangInstanceIdentifier.of(qname);
+ stack = SchemaInferenceStack.of(context);
+
+ final var stmt = stack.enterSchemaTree(qname);
+ verify(stmt instanceof RpcDefinition, "Unexpected statement %s", stmt);
+ node = (RpcDefinition) stmt;
+ }
+
+ Result(final List<PathArgument> steps, final SchemaInferenceStack stack, final SchemaNode node) {
+ path = YangInstanceIdentifier.create(steps);
+ this.stack = requireNonNull(stack);
+ this.node = requireNonNull(node);
+ }
+ }
+
private final @NonNull EffectiveModelContext schemaContext;
private final @NonNull ApiPath apiPath;
* @return {@link Iterable} of {@link PathArgument}
* @throws RestconfDocumentedException the path is not valid
*/
- public static List<PathArgument> create(final EffectiveModelContext schemaContext, final String data) {
+ public static Result create(final EffectiveModelContext schemaContext, final String data) {
final ApiPath path;
try {
path = ApiPath.parse(requireNonNull(data));
return create(schemaContext, path);
}
- public static List<PathArgument> create(final EffectiveModelContext schemaContext, final ApiPath path) {
+ public static Result create(final EffectiveModelContext schemaContext, final ApiPath path) {
return new YangInstanceIdentifierDeserializer(schemaContext, path).parse();
}
//
// All of this really is an utter mess because we end up calling into this code from various places which,
// for example, should not allow RPCs to be valid targets
- private ImmutableList<PathArgument> parse() {
+ private Result parse() {
final var it = apiPath.steps().iterator();
if (!it.hasNext()) {
- return ImmutableList.of();
+ return new Result(schemaContext);
}
// First step is somewhat special:
+ "therefore it must not contain key values", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
}
- // Legacy behavior: RPCs do not really have a YangInstanceIdentifier, but the rest of the code expects it
- return ImmutableList.of(new NodeIdentifier(qname));
+ return new Result(schemaContext, optRpc.orElseThrow().argument());
}
+ final var stack = SchemaInferenceStack.of(schemaContext);
final var path = new ArrayList<PathArgument>();
+ final SchemaNode node;
+
var parentNode = DataSchemaContextTree.from(schemaContext).getRoot();
while (true) {
final var parentSchema = parentNode.getDataSchemaNode();
if (parentSchema instanceof ActionNodeContainer) {
- if (((ActionNodeContainer) parentSchema).findAction(qname).isPresent()) {
+ final var optAction = ((ActionNodeContainer) parentSchema).findAction(qname);
+ if (optAction.isPresent()) {
if (it.hasNext()) {
throw new RestconfDocumentedException("Request path resolves to action '" + qname + "' and "
+ "therefore it must not continue past it", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
// Legacy behavior: Action's path should not include its path, but the rest of the code expects it
path.add(new NodeIdentifier(qname));
+ stack.enterSchemaTree(qname);
+ node = optAction.orElseThrow();
break;
}
}
// Resolve the child step with respect to data schema tree
- final var found = RestconfDocumentedException.throwIfNull(parentNode.getChild(qname),
+ final var found = RestconfDocumentedException.throwIfNull(parentNode.enterChild(stack, qname),
ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, "Schema for '%s' not found", qname);
// Now add all mixins encountered to the path
var childNode = found;
while (childNode.isMixin()) {
path.add(childNode.getIdentifier());
- childNode = verifyNotNull(childNode.getChild(qname),
+ childNode = verifyNotNull(childNode.enterChild(stack, qname),
"Mixin %s is missing child for %s while resolving %s", childNode, qname, found);
}
path.add(pathArg);
if (!it.hasNext()) {
+ node = childNode.getDataSchemaNode();
break;
}
qname = step.identifier().bindTo(namespace);
}
- return ImmutableList.copyOf(path);
+ return new Result(path, stack, node);
}
private NodeIdentifierWithPredicates prepareNodeWithPredicates(final QName qname,
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.withSettings;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import javax.ws.rs.core.MultivaluedHashMap;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class QueryParamsTest {
assertNotNull(params.fields());
// fields for write filtering
- final var containerSchema = mock(ContainerSchemaNode.class);
- doReturn(QName.create(containerChild, "container")).when(containerSchema).getQName();
+ final var containerSchema = mock(ContainerSchemaNode.class,
+ withSettings().extraInterfaces(ContainerEffectiveStatement.class));
+ final var containerQName = QName.create(containerChild, "container");
+ doReturn(containerQName).when(containerSchema).getQName();
+ doReturn(SchemaPath.create(true, containerQName)).when(containerSchema).getPath();
final var containerChildSchema = mock(LeafSchemaNode.class);
doReturn(containerChild).when(containerChildSchema).getQName();
doReturn(containerChildSchema).when(containerSchema).dataChildByName(containerChild);
+ final var module = mock(ModuleEffectiveStatement.class);
+ doReturn(Optional.of(containerSchema)).when(module).findSchemaTreeNode(containerQName);
+ final var context = mock(EffectiveModelContext.class);
+ doReturn(Map.of(containerQName.getModule(), module)).when(context).getModuleStatements();
+
final QueryParameters queryParameters = QueryParams.newQueryParameters(params,
- InstanceIdentifierContext.ofDataSchemaNode(mock(EffectiveModelContext.class), containerSchema));
+ InstanceIdentifierContext.ofDataSchemaNode(context, containerSchema));
final List<Set<QName>> fields = queryParameters.fields();
assertNotNull(fields);
assertEquals(1, fields.size());
.withValue(o).build();
container.withChild(lfNode);
- return NormalizedNodePayload.of(new InstanceIdentifierContext(null, rpcInputSchemaNode, null, SCHEMA_CTX),
- container.build());
+ return NormalizedNodePayload.of(
+ InstanceIdentifierContext.ofDataSchemaNode(SCHEMA_CTX, rpcInputSchemaNode, null), container.build());
}
}
*/
package org.opendaylight.restconf.nb.rfc8040.rests.services.impl;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import com.google.common.util.concurrent.Futures;
import java.io.FileNotFoundException;
-import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
-import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
-import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
mock(DOMMountPointService.class), mock(RestconfStreamsSubscriptionService.class),
actionService, mock(Configuration.class));
- final var schemaNode = loadAction(contextRef, RESET_QNAME, ACTION_YII).orElseThrow();
+ final var nodeAndStack = DataSchemaContextTree.from(contextRef).enterPath(ACTION_YII).orElseThrow();
+ final var node = nodeAndStack.node().getDataSchemaNode();
+ assertThat(node, instanceOf(ActionNodeContainer.class));
+ final var actionNode = ((ActionNodeContainer) node).findAction(RESET_QNAME).orElseThrow();
+ final var stack = nodeAndStack.stack();
+ stack.enterSchemaTree(RESET_QNAME);
+
final var response = dataService.invokeAction(NormalizedNodePayload.of(
- new InstanceIdentifierContext(ACTION_YII, schemaNode, null, contextRef),
+ InstanceIdentifierContext.ofAction(stack, actionNode, ACTION_YII, null),
Builders.containerBuilder()
.withNodeIdentifier(NodeIdentifier.create(INPUT_QNAME))
.withChild(ImmutableNodes.leafNode(DELAY_QNAME, Uint32.TEN))
assertEquals(204, response.getStatus());
assertNull(response.getEntity());
}
-
- private static Optional<ActionDefinition> loadAction(final EffectiveModelContext modelContext,
- final QName actionQName, final YangInstanceIdentifier actionYII) {
- return DataSchemaContextTree.from(modelContext)
- .findChild(actionYII)
- .map(DataSchemaContextNode::getDataSchemaNode)
- .flatMap(node -> node instanceof ActionNodeContainer ? ((ActionNodeContainer) node).findAction(actionQName)
- : Optional.empty());
- }
}
}
private NormalizedNodePayload prepNNC(final NormalizedNode result) {
- final RpcDefinition schemaNode = mock(RpcDefinition.class);
- final QName qname = QName.create("invoke:rpc:module", "2013-12-03", "rpcTest");
- doReturn(qname).when(schemaNode).getQName();
+ final QName qname = QName.create("invoke:rpc:module", "2013-12-03", "rpc-test");
+ final RpcDefinition schemaNode = CONTEXT.getOperations().stream().filter(rpc -> rpc.getQName().equals(qname))
+ .findFirst()
+ .orElseThrow();
+
final NormalizedNode data = mock(NormalizedNode.class);
final DOMRpcResult domRpcResult = mock(DOMRpcResult.class);
doReturn(immediateFluentFuture(domRpcResult)).when(rpcService).invokeRpc(qname, data);
doReturn(result).when(domRpcResult).getResult();
return NormalizedNodePayload.of(
- InstanceIdentifierContext.ofLocalRpc(CONTEXT, schemaNode), data);
+ InstanceIdentifierContext.ofRpcInput(CONTEXT, schemaNode, null), data);
}
}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.when;
import java.text.ParseException;
import java.util.List;
-import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mock;
import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
import org.opendaylight.restconf.nb.rfc8040.FieldsParam;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.Revision;
import org.opendaylight.yangtools.yang.common.XMLNamespace;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
public abstract class AbstractFieldsTranslatorTest<T> {
// FIXME: remove all this mocking -- just parse the underlying model and be done with it
// container jukebox
- @Mock
- private ContainerSchemaNode containerJukebox;
private static final QName JUKEBOX_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "jukebox");
// container player
- @Mock
- private ContainerSchemaNode containerPlayer;
protected static final QName PLAYER_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "player");
// container library
- @Mock
- private ContainerSchemaNode containerLibrary;
protected static final QName LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "library");
+ // list artist
+ protected static final QName ARTIST_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "artist");
+
// container augmented library
- @Mock
- private ContainerSchemaNode augmentedContainerLibrary;
protected static final QName AUGMENTED_LIBRARY_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX,
"augmented-library");
- // augmentation that contains speed leaf
- @Mock
- private AugmentationSchemaNode speedAugmentation;
-
// leaf speed
- @Mock
- private LeafSchemaNode leafSpeed;
protected static final QName SPEED_Q_NAME = QName.create(Q_NAME_MODULE_AUGMENTED_JUKEBOX, "speed");
// list album
- @Mock
- private ListSchemaNode listAlbum;
public static final QName ALBUM_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "album");
// leaf name
- @Mock
- private LeafSchemaNode leafName;
protected static final QName NAME_Q_NAME = QName.create(Q_NAME_MODULE_JUKEBOX, "name");
// container test data
- @Mock
- private ContainerSchemaNode containerTestData;
private static final QName TEST_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "test-data");
// list services
- @Mock
- private ListSchemaNode listServices;
protected static final QName SERVICES_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "services");
// leaf type-of-service
- @Mock
- private LeafSchemaNode leafTypeOfService;
protected static final QName TYPE_OF_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "type-of-service");
// list instance
- @Mock
- private ListSchemaNode listInstance;
protected static final QName INSTANCE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance");
// leaf instance-name
- @Mock
- private LeafSchemaNode leafInstanceName;
protected static final QName INSTANCE_NAME_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "instance-name");
// leaf provider
- @Mock
- private LeafSchemaNode leafProvider;
protected static final QName PROVIDER_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "provider");
// container next-data
- @Mock
- private ContainerSchemaNode containerNextData;
protected static final QName NEXT_DATA_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-data");
// leaf next-service
- @Mock
- private LeafSchemaNode leafNextService;
protected static final QName NEXT_SERVICE_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "next-service");
// leaf-list protocols
- @Mock
- private LeafListSchemaNode leafListProtocols;
protected static final QName PROTOCOLS_Q_NAME = QName.create(Q_NAME_MODULE_TEST_SERVICES, "protocols");
@Before
public void setUp() throws Exception {
final EffectiveModelContext schemaContextJukebox =
YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/jukebox"));
- initJukeboxSchemaNodes(schemaContextJukebox);
+ identifierJukebox = InstanceIdentifierContext.ofDataSchemaNode(schemaContextJukebox,
+ schemaContextJukebox.getDataChildByName(JUKEBOX_Q_NAME));
final EffectiveModelContext schemaContextTestServices =
YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/test-services"));
- initTestServicesSchemaNodes(schemaContextTestServices);
- }
-
- private void initJukeboxSchemaNodes(final EffectiveModelContext schemaContext) {
- identifierJukebox = InstanceIdentifierContext.ofDataSchemaNode(schemaContext, containerJukebox);
- when(containerJukebox.getQName()).thenReturn(JUKEBOX_Q_NAME);
-
- when(containerLibrary.getQName()).thenReturn(LIBRARY_Q_NAME);
- when(containerJukebox.dataChildByName(LIBRARY_Q_NAME)).thenReturn(containerLibrary);
-
- when(augmentedContainerLibrary.getQName()).thenReturn(AUGMENTED_LIBRARY_Q_NAME);
- when(containerJukebox.dataChildByName(AUGMENTED_LIBRARY_Q_NAME))
- .thenReturn(augmentedContainerLibrary);
-
- when(containerPlayer.getQName()).thenReturn(PLAYER_Q_NAME);
- when(containerJukebox.dataChildByName(PLAYER_Q_NAME)).thenReturn(containerPlayer);
-
- when(listAlbum.getQName()).thenReturn(ALBUM_Q_NAME);
- when(containerLibrary.dataChildByName(ALBUM_Q_NAME)).thenReturn(listAlbum);
-
- when(leafName.getQName()).thenReturn(NAME_Q_NAME);
- when(listAlbum.dataChildByName(NAME_Q_NAME)).thenReturn(leafName);
-
- when(leafSpeed.getQName()).thenReturn(SPEED_Q_NAME);
- when(leafSpeed.isAugmenting()).thenReturn(true);
- when(containerPlayer.dataChildByName(SPEED_Q_NAME)).thenReturn(leafSpeed);
- when(containerPlayer.getDataChildByName(SPEED_Q_NAME)).thenReturn(leafSpeed);
- doReturn(List.of(leafSpeed)).when(speedAugmentation).getChildNodes();
- doReturn(List.of(speedAugmentation)).when(containerPlayer).getAvailableAugmentations();
- when(speedAugmentation.findDataChildByName(SPEED_Q_NAME)).thenReturn(Optional.of(leafSpeed));
- }
-
- private void initTestServicesSchemaNodes(final EffectiveModelContext schemaContext) {
- identifierTestServices = InstanceIdentifierContext.ofDataSchemaNode(schemaContext, containerTestData);
- when(containerTestData.getQName()).thenReturn(TEST_DATA_Q_NAME);
-
- when(listServices.getQName()).thenReturn(SERVICES_Q_NAME);
- when(containerTestData.dataChildByName(SERVICES_Q_NAME)).thenReturn(listServices);
-
- when(leafListProtocols.getQName()).thenReturn(PROTOCOLS_Q_NAME);
- when(containerTestData.dataChildByName(PROTOCOLS_Q_NAME)).thenReturn(leafListProtocols);
-
- when(leafTypeOfService.getQName()).thenReturn(TYPE_OF_SERVICE_Q_NAME);
- when(listServices.dataChildByName(TYPE_OF_SERVICE_Q_NAME)).thenReturn(leafTypeOfService);
-
- when(listInstance.getQName()).thenReturn(INSTANCE_Q_NAME);
- when(listServices.dataChildByName(INSTANCE_Q_NAME)).thenReturn(listInstance);
-
- when(leafInstanceName.getQName()).thenReturn(INSTANCE_NAME_Q_NAME);
- when(listInstance.dataChildByName(INSTANCE_NAME_Q_NAME)).thenReturn(leafInstanceName);
-
- when(leafProvider.getQName()).thenReturn(PROVIDER_Q_NAME);
- when(listInstance.dataChildByName(PROVIDER_Q_NAME)).thenReturn(leafProvider);
-
- when(containerNextData.getQName()).thenReturn(NEXT_DATA_Q_NAME);
- when(listServices.dataChildByName(NEXT_DATA_Q_NAME)).thenReturn(containerNextData);
-
- when(leafNextService.getQName()).thenReturn(NEXT_SERVICE_Q_NAME);
- when(containerNextData.dataChildByName(NEXT_SERVICE_Q_NAME)).thenReturn(leafNextService);
+ identifierTestServices = InstanceIdentifierContext.ofDataSchemaNode(schemaContextTestServices,
+ schemaContextTestServices.getDataChildByName(TEST_DATA_Q_NAME));
}
protected abstract List<T> translateFields(InstanceIdentifierContext context, FieldsParam fields);
*/
@Test
public void testSubPath() {
- final var result = translateFields(identifierJukebox, assertFields("library/album/name"));
+ final var result = translateFields(identifierJukebox, assertFields("library/artist/album/name"));
assertNotNull(result);
assertSubPath(result);
}
*/
@Test
public void testChildrenPath() {
- final var result = translateFields(identifierJukebox, assertFields("library(album(name))"));
+ final var result = translateFields(identifierJukebox, assertFields("library(artist(album(name)))"));
assertNotNull(result);
assertChildrenPath(result);
}
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
/**
* Unit test for {@link NetconfFieldsTranslator}.
protected void assertChildrenPath(final List<YangInstanceIdentifier> result) {
assertEquals(1, result.size());
final var pathArguments = result.get(0).getPathArguments();
- assertEquals(3, pathArguments.size());
+ assertEquals(4, pathArguments.size());
assertEquals(LIBRARY_Q_NAME, pathArguments.get(0).getNodeType());
- assertEquals(ALBUM_Q_NAME, pathArguments.get(1).getNodeType());
- assertEquals(NAME_Q_NAME, pathArguments.get(2).getNodeType());
+ assertEquals(ARTIST_Q_NAME, pathArguments.get(1).getNodeType());
+ assertEquals(ALBUM_Q_NAME, pathArguments.get(2).getNodeType());
+ assertEquals(NAME_Q_NAME, pathArguments.get(3).getNodeType());
}
@Override
@Override
protected void assertListFieldUnderList(final List<YangInstanceIdentifier> result) {
assertEquals(1, result.size());
- assertEquals(List.of(new NodeIdentifier(SERVICES_Q_NAME), new NodeIdentifier(INSTANCE_Q_NAME)),
+ assertEquals(List.of(
+ // FIXME: this does not look right: where are the corresponding NodeIdentifiers?
+ NodeIdentifierWithPredicates.of(SERVICES_Q_NAME),
+ NodeIdentifierWithPredicates.of(INSTANCE_Q_NAME)),
result.get(0).getPathArguments());
}
@Override
protected void assertSubPath(final List<Set<QName>> result) {
- assertEquals(3, result.size());
+ assertEquals(4, result.size());
assertEquals(Set.of(LIBRARY_Q_NAME), result.get(0));
- assertEquals(Set.of(ALBUM_Q_NAME), result.get(1));
- assertEquals(Set.of(NAME_Q_NAME), result.get(2));
+ assertEquals(Set.of(ARTIST_Q_NAME), result.get(1));
+ assertEquals(Set.of(ALBUM_Q_NAME), result.get(2));
+ assertEquals(Set.of(NAME_Q_NAME), result.get(3));
}
@Override
protected void assertChildrenPath(final List<Set<QName>> result) {
- assertEquals(3, result.size());
+ assertEquals(4, result.size());
assertEquals(Set.of(LIBRARY_Q_NAME), result.get(0));
- assertEquals(Set.of(ALBUM_Q_NAME), result.get(1));
- assertEquals(Set.of(NAME_Q_NAME), result.get(2));
+ assertEquals(Set.of(ARTIST_Q_NAME), result.get(1));
+ assertEquals(Set.of(ALBUM_Q_NAME), result.get(2));
+ assertEquals(Set.of(NAME_Q_NAME), result.get(3));
}
@Override
*/
@Test
public void deserializeContainerTest() {
- final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, "deserializer-test:contA");
+ final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, "deserializer-test:contA")
+ .path.getPathArguments();
assertEquals(1, result.size());
assertEquals(NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")), result.get(0));
}
*/
@Test
public void deserializeContainerWithLeafTest() {
- final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, "deserializer-test:contA/leaf-A");
+ final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, "deserializer-test:contA/leaf-A")
+ .path.getPathArguments();
assertEquals(2, result.size());
assertEquals(NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")), result.get(0));
assertEquals(NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "leaf-A")), result.get(1));
@Test
public void deserializeContainerWithListWithLeafListTest() {
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test:contA/list-A=100/leaf-list-AA=instance");
+ "deserializer-test:contA/list-A=100/leaf-list-AA=instance").path.getPathArguments();
assertEquals(5, result.size());
// container
@Test
public void deserializeContainerWithListWithActionTest() {
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "example-actions:interfaces/interface=eth0/reset");
+ "example-actions:interfaces/interface=eth0/reset").path.getPathArguments();
assertEquals(4, result.size());
// container
assertEquals(NodeIdentifier.create(ACTIONS_INTERFACES), result.get(0));
@Test
public void deserializeContainerWithChoiceSchemaNodeWithActionTest() {
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "example-actions:interfaces/typeA-gigabyte/interface=eth0/reboot");
+ "example-actions:interfaces/typeA-gigabyte/interface=eth0/reboot").path.getPathArguments();
assertEquals(6, result.size());
// container
@Test
public void deserializeContainerWithChoiceCaseSchemaNodeWithActionTest() {
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "example-actions:interfaces/udp/reboot");
+ "example-actions:interfaces/udp/reboot").path.getPathArguments();
assertEquals(4, result.size());
// container
assertEquals(NodeIdentifier.create(ACTIONS_INTERFACES), result.get(0));
*/
@Test
public void deserializeListWithNoKeysTest() {
- final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, "deserializer-test:list-no-key");
+ final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, "deserializer-test:list-no-key")
+ .path.getPathArguments();
assertEquals(2, result.size());
final QName list = QName.create("deserializer:test", "2016-06-06", "list-no-key");
assertEquals(NodeIdentifier.create(list), result.get(0));
@Test
public void deserializeListWithOneKeyTest() {
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test:list-one-key=value");
+ "deserializer-test:list-one-key=value").path.getPathArguments();
assertEquals(2, result.size());
final QName list = QName.create("deserializer:test", "2016-06-06", "list-one-key");
assertEquals(NodeIdentifier.create(list), result.get(0));
QName.create(list, "enabled"), false);
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test:list-multiple-keys=value,100,false");
+ "deserializer-test:list-multiple-keys=value,100,false").path.getPathArguments();
assertEquals(2, result.size());
assertEquals(NodeIdentifier.create(list), result.get(0));
assertEquals(NodeIdentifierWithPredicates.of(list, values), result.get(1));
@Test
public void deserializeLeafListTest() {
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test:leaf-list-0=true");
+ "deserializer-test:leaf-list-0=true").path.getPathArguments();
assertEquals(2, result.size());
final QName leafList = QName.create("deserializer:test", "2016-06-06", "leaf-list-0");
*/
@Test
public void deserializeEmptyDataTest() {
- assertEquals(List.of(), YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, ""));
+ assertEquals(List.of(), YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, "").path.getPathArguments());
}
/**
@Test
public void deserializeMultipleSlashesTest() throws ParseException {
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- ApiPath.parseUrl("deserializer-test:contA////list-A=40//list-key"));
+ ApiPath.parseUrl("deserializer-test:contA////list-A=40//list-key")).path.getPathArguments();
assertEquals(4, result.size());
// container
QName.create(list, "enabled"), false);
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test:list-multiple-keys=%3Afoo,1,false/string-value");
+ "deserializer-test:list-multiple-keys=%3Afoo,1,false/string-value").path.getPathArguments();
assertEquals(3, result.size());
// list
assertEquals(NodeIdentifier.create(list), result.get(0));
@Test
public void percentEncodedKeyEndsWithNoPercentEncodedChars() {
final String URI = "deserializer-test:list-multiple-keys=%3Afoo,1,true";
- final YangInstanceIdentifier result = YangInstanceIdentifier.create(
- YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, URI));
+ final YangInstanceIdentifier result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, URI).path;
final Iterator<Entry<QName, Object>> resultListKeys =
((NodeIdentifierWithPredicates)result.getLastPathArgument()).entrySet().iterator();
QName.create(list, "enabled"), true);
final var result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test:list-multiple-keys=,0,true");
+ "deserializer-test:list-multiple-keys=,0,true").path.getPathArguments();
assertEquals(2, result.size());
assertEquals(NodeIdentifier.create(list), result.get(0));
assertEquals(NodeIdentifierWithPredicates.of(list, values), result.get(1));
@Test
public void deserializePartInOtherModuleTest() {
final List<PathArgument> result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test-included:augmented-list=100/deserializer-test:augmented-leaf");
+ "deserializer-test-included:augmented-list=100/deserializer-test:augmented-leaf")
+ .path.getPathArguments();
assertEquals(4, result.size());
// list
@Test
public void deserializeListInOtherModuleTest() {
final List<PathArgument> result = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT,
- "deserializer-test-included:augmented-list=100/deserializer-test:augmenting-list=0");
+ "deserializer-test-included:augmented-list=100/deserializer-test:augmenting-list=0")
+ .path.getPathArguments();
assertEquals(5, result.size());
// list
}
private static void assertIdentityrefKeyValue(final String path) {
- final var pathArgs = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, path);
+ final var pathArgs = YangInstanceIdentifierDeserializer.create(SCHEMA_CONTEXT, path).path.getPathArguments();
assertEquals(4, pathArgs.size());
assertEquals("refs", pathArgs.get(0).getNodeType().getLocalName());