@Override
public NormalizedNodeContext invokeRpc(final String identifier, final NormalizedNodeContext payload,
- final UriInfo uriInfo) {
+ final UriInfo uriInfo) {
return this.delegRestconfInvokeOpsService.invokeRpc(identifier, payload, uriInfo);
}
}
public void setHandlers(final SchemaContextHandler schemaCtxHandler,
- final DOMMountPointServiceHandler domMountPointServiceHandler,
- final TransactionChainHandler transactionChainHandler, final DOMDataBrokerHandler domDataBrokerHandler,
- final RpcServiceHandler rpcServiceHandler) {
+ final DOMMountPointServiceHandler domMountPointServiceHandler,
+ final TransactionChainHandler transactionChainHandler,
+ final DOMDataBrokerHandler domDataBrokerHandler,
+ final RpcServiceHandler rpcServiceHandler) {
this.delegRestModService = new RestconfModulesServiceImpl(schemaCtxHandler, domMountPointServiceHandler);
this.delegRestOpsService = new RestconfOperationsServiceImpl(schemaCtxHandler, domMountPointServiceHandler);
this.delegRestSchService = new RestconfSchemaServiceImpl(schemaCtxHandler, domMountPointServiceHandler);
this.delegRestStrsService = new RestconfStreamsServiceImpl(schemaCtxHandler);
- this.delegRestconfDataService = new RestconfDataServiceImpl(schemaCtxHandler, transactionChainHandler);
+ this.delegRestconfDataService = new RestconfDataServiceImpl(schemaCtxHandler, transactionChainHandler,
+ domMountPointServiceHandler);
this.delegRestconfInvokeOpsService = new RestconfInvokeOperationsServiceImpl(rpcServiceHandler,
schemaCtxHandler);
this.delegRestconfSubscrService = new RestconfStreamsSubscriptionServiceImpl(domDataBrokerHandler);
package org.opendaylight.restconf.jersey.providers;
+import com.google.common.base.Optional;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
protected InstanceIdentifierContext<?> getInstanceIdentifierContext() {
return ParserIdentifier.toInstanceIdentifier(getIdentifier(),
- ControllerContext.getInstance().getGlobalSchema());
+ ControllerContext.getInstance().getGlobalSchema(), Optional.absent());
}
protected UriInfo getUriInfo() {
*/
package org.opendaylight.restconf.rest.services.impl;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.util.Collections;
import java.util.Set;
import javax.ws.rs.core.UriInfo;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
}
final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
- final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
- schemaContextRef.get());
- final DOMMountPointService domMointPointService = this.domMountPointServiceHandler.get();
- final DOMMountPoint mountPoint = domMointPointService
- .getMountPoint(mountPointIdentifier.getInstanceIdentifier()).get();
+ final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(
+ identifier, schemaContextRef.get(), Optional.of(this.domMountPointServiceHandler.get()));
+ final DOMMountPoint mountPoint = mountPointIdentifier.getMountPoint();
return getModules(mountPoint.getSchemaContext().getModules(), schemaContextRef, mountPoint);
}
Preconditions.checkNotNull(identifier);
final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
final QName moduleQname = ParserIdentifier.makeQNameFromIdentifier(identifier);
- Module module = null;
+ final Module module;
DOMMountPoint mountPoint = null;
if (identifier.contains(RestconfConstants.MOUNT)) {
- final InstanceIdentifierContext<?> point = ParserIdentifier.toInstanceIdentifier(identifier,
- schemaContextRef.get());
- final DOMMountPointService domMointPointService = this.domMountPointServiceHandler.get();
- mountPoint = domMointPointService.getMountPoint(point.getInstanceIdentifier()).get();
+ // we only need to find mount point itself
+ final String mountPointPath = identifier.substring(
+ 0, identifier.indexOf(RestconfConstants.MOUNT) + RestconfConstants.MOUNT.length());
+ final InstanceIdentifierContext<?> mountPointContext = ParserIdentifier.toInstanceIdentifier(
+ mountPointPath, schemaContextRef.get(), Optional.of(this.domMountPointServiceHandler.get()));
+ mountPoint = mountPointContext.getMountPoint();
module = schemaContextRef.findModuleInMountPointByQName(mountPoint, moduleQname);
} else {
module = schemaContextRef.findModuleByQName(moduleQname);
*/
package org.opendaylight.restconf.rest.services.impl;
+import com.google.common.base.Optional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@Override
public NormalizedNodeContext getOperations(final String identifier, final UriInfo uriInfo) {
- Set<Module> modules = null;
- DOMMountPoint mountPoint = null;
+ final Set<Module> modules;
+ final DOMMountPoint mountPoint;
final SchemaContextRef ref = new SchemaContextRef(this.schemaContextHandler.get());
if (identifier.contains(RestconfConstants.MOUNT)) {
- final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
- ref.get());
+ final InstanceIdentifierContext<?> mountPointIdentifier = ParserIdentifier.toInstanceIdentifier(
+ identifier, ref.get(), Optional.of(this.domMountPointServiceHandler.get()));
mountPoint = mountPointIdentifier.getMountPoint();
modules = ref.getModules(mountPoint);
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.TimeZone;
+import javax.annotation.Nonnull;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusContext;
import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
import org.opendaylight.restconf.RestConnectorProvider;
import org.opendaylight.restconf.common.references.SchemaContextRef;
+import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler;
import org.opendaylight.restconf.handlers.SchemaContextHandler;
import org.opendaylight.restconf.handlers.TransactionChainHandler;
import org.opendaylight.restconf.restful.services.api.RestconfDataService;
private final SchemaContextHandler schemaContextHandler;
private final TransactionChainHandler transactionChainHandler;
+ private final DOMMountPointServiceHandler mountPointServiceHandler;
public RestconfDataServiceImpl(final SchemaContextHandler schemaContextHandler,
- final TransactionChainHandler transactionChainHandler) {
+ final TransactionChainHandler transactionChainHandler,
+ final DOMMountPointServiceHandler mountPointServiceHandler) {
this.schemaContextHandler = schemaContextHandler;
this.transactionChainHandler = transactionChainHandler;
+ this.mountPointServiceHandler = mountPointServiceHandler;
}
@Override
Preconditions.checkNotNull(identifier);
final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
- final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
- schemaContextRef.get());
+ final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(
+ identifier, schemaContextRef.get(), Optional.of(this.mountPointServiceHandler.get()));
final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
final String value = uriInfo.getQueryParameters().getFirst(RestconfDataServiceConstant.CONTENT);
- DOMTransactionChain transaction = null;
+ final DOMTransactionChain transactionChain;
if (mountPoint == null) {
- transaction = this.transactionChainHandler.get();
+ transactionChain = this.transactionChainHandler.get();
} else {
- transaction = transactionOfMountPoint(mountPoint);
+ transactionChain = transactionChainOfMountPoint(mountPoint);
}
+
final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
- transaction);
+ transactionChain);
final NormalizedNode<?, ?> node = ReadDataTransactionUtil.readData(value, transactionNode);
+ if (node == null) {
+ throw new RestconfDocumentedException(
+ "Request could not be completed because the relevant data model content does not exist",
+ RestconfError.ErrorType.PROTOCOL,
+ RestconfError.ErrorTag.DATA_MISSING);
+ }
final SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
final String etag = '"' + node.getNodeType().getModule().getFormattedRevision()
+ node.getNodeType().getLocalName() + '"';
- Response resp = null;
+ final Response resp;
+
if ((value == null) || value.contains(RestconfDataServiceConstant.ReadData.CONFIG)) {
resp = Response.status(200).entity(new NormalizedNodeContext(instanceIdentifier, node)).header("ETag", etag)
- .header("Last-Modified", dateFormatGmt.toString()).build();
+ .header("Last-Modified", dateFormatGmt.format(new Date())).build();
} else {
resp = Response.status(200).entity(new NormalizedNodeContext(instanceIdentifier, node)).build();
}
@Override
public Response putData(final String identifier, final NormalizedNodeContext payload) {
- Preconditions.checkNotNull(identifier);
Preconditions.checkNotNull(payload);
final InstanceIdentifierContext<? extends SchemaNode> iid = payload
PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload);
final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
- DOMTransactionChain transaction = null;
- SchemaContextRef ref = null;
+ final DOMTransactionChain transactionChain;
+ final SchemaContextRef ref;
if (mountPoint == null) {
- transaction = this.transactionChainHandler.get();
+ transactionChain = this.transactionChainHandler.get();
ref = new SchemaContextRef(this.schemaContextHandler.get());
} else {
- transaction = transactionOfMountPoint(mountPoint);
+ transactionChain = transactionChainOfMountPoint(mountPoint);
ref = new SchemaContextRef(mountPoint.getSchemaContext());
}
final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
- payload.getInstanceIdentifierContext(), mountPoint, transaction);
+ payload.getInstanceIdentifierContext(), mountPoint, transactionChain);
return PutDataTransactionUtil.putData(payload, ref, transactionNode);
}
Preconditions.checkNotNull(payload);
final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
- DOMTransactionChain transaction = null;
- SchemaContextRef ref = null;
+ final DOMTransactionChain transactionChain;
+ final SchemaContextRef ref;
if (mountPoint == null) {
- transaction = this.transactionChainHandler.get();
+ transactionChain = this.transactionChainHandler.get();
ref = new SchemaContextRef(this.schemaContextHandler.get());
} else {
- transaction = transactionOfMountPoint(mountPoint);
+ transactionChain = transactionChainOfMountPoint(mountPoint);
ref = new SchemaContextRef(mountPoint.getSchemaContext());
}
final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
- payload.getInstanceIdentifierContext(), mountPoint, transaction);
+ payload.getInstanceIdentifierContext(), mountPoint, transactionChain);
return PostDataTransactionUtil.postData(uriInfo, payload, transactionNode, ref);
}
@Override
public Response deleteData(final String identifier) {
final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
- final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier,
- schemaContextRef.get());
+ final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(
+ identifier, schemaContextRef.get(), Optional.of(this.mountPointServiceHandler.get()));
final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
- final DOMTransactionChain transaction;
+ final DOMTransactionChain transactionChain;
if (mountPoint == null) {
- transaction = this.transactionChainHandler.get();
+ transactionChain = this.transactionChainHandler.get();
} else {
- transaction = transactionOfMountPoint(mountPoint);
+ transactionChain = transactionChainOfMountPoint(mountPoint);
}
final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
- transaction);
+ transactionChain);
return DeleteDataTransactionUtil.deleteData(transactionNode);
}
@Override
public PATCHStatusContext patchData(final String identifier, final PATCHContext context, final UriInfo uriInfo) {
- Preconditions.checkNotNull(identifier);
return patchData(context, uriInfo);
}
Preconditions.checkNotNull(context);
final DOMMountPoint mountPoint = context.getInstanceIdentifierContext().getMountPoint();
- final DOMTransactionChain transaction;
+ final DOMTransactionChain transactionChain;
final SchemaContextRef ref;
if (mountPoint == null) {
- transaction = this.transactionChainHandler.get();
+ transactionChain = this.transactionChainHandler.get();
ref = new SchemaContextRef(this.schemaContextHandler.get());
} else {
- transaction = transactionOfMountPoint(mountPoint);
+ transactionChain = transactionChainOfMountPoint(mountPoint);
ref = new SchemaContextRef(mountPoint.getSchemaContext());
}
final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
- context.getInstanceIdentifierContext(), mountPoint, transaction);
+ context.getInstanceIdentifierContext(), mountPoint, transactionChain);
return PatchDataTransactionUtil.patchData(context, transactionNode, ref);
}
/**
- * Prepare transaction to read data of mount point, if these data are
- * present.
+ * Prepare transaction chain to access data of mount point
* @param mountPoint
- * @return {@link DOMDataReadWriteTransaction}
+ * - mount point reference
+ * @return {@link DOMTransactionChain}
*/
- private static DOMTransactionChain transactionOfMountPoint(final DOMMountPoint mountPoint) {
+ private static DOMTransactionChain transactionChainOfMountPoint(@Nonnull final DOMMountPoint mountPoint) {
final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
if (domDataBrokerService.isPresent()) {
return domDataBrokerService.get().createTransactionChain(RestConnectorProvider.transactionListener);
package org.opendaylight.restconf.restful.utils;
import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.CheckedFuture;
import java.util.Collection;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
import org.opendaylight.yangtools.yang.common.QNameModule;
+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;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
/**
* - {@link TransactionVarsWrapper} - wrapper for variables
* @return {@link NormalizedNode}
*/
- public static NormalizedNode<?, ?> readData(final String valueOfContent, final TransactionVarsWrapper transactionNode) {
+ public static @Nullable NormalizedNode<?, ?> readData(@Nullable final String valueOfContent,
+ @Nonnull final TransactionVarsWrapper transactionNode) {
+ final NormalizedNode<?, ?> data;
if (valueOfContent != null) {
switch (valueOfContent) {
case RestconfDataServiceConstant.ReadData.CONFIG:
transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
- return readDataViaTransaction(transactionNode);
+ data = readDataViaTransaction(transactionNode);
+ break;
case RestconfDataServiceConstant.ReadData.NONCONFIG:
transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
- return readDataViaTransaction(transactionNode);
+ data = readDataViaTransaction(transactionNode);
+ break;
case RestconfDataServiceConstant.ReadData.ALL:
- return readDataViaTransaction(transactionNode);
+ data = readAllData(transactionNode);
+ break;
default:
- throw new RestconfDocumentedException("Bad querry parameter for content.", ErrorType.APPLICATION,
+ throw new RestconfDocumentedException("Bad query parameter for content.", ErrorType.APPLICATION,
ErrorTag.INVALID_VALUE);
}
} else {
- return readDataViaTransaction(transactionNode);
+ data = readAllData(transactionNode);
}
+
+ return data;
}
/**
* - {@link TransactionVarsWrapper} - wrapper for variables
* @return {@link NormalizedNode}
*/
- private static NormalizedNode<?, ?> readDataViaTransaction(final TransactionVarsWrapper transactionNode) {
- if (transactionNode.getLogicalDatastoreType() != null) {
- final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture = transactionNode
- .getTransactionChain().newReadOnlyTransaction().read(transactionNode.getLogicalDatastoreType(),
- transactionNode.getInstanceIdentifier().getInstanceIdentifier());
- final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
- FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
- dataFactory);
- return dataFactory.build();
- } else {
- return readAllData(transactionNode);
- }
+ private static @Nullable NormalizedNode<?, ?> readDataViaTransaction(
+ @Nonnull final TransactionVarsWrapper transactionNode) {
+ final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture = transactionNode
+ .getTransactionChain().newReadOnlyTransaction().read(transactionNode.getLogicalDatastoreType(),
+ transactionNode.getInstanceIdentifier().getInstanceIdentifier());
+ final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
+ FutureCallbackTx.addCallback(listenableFuture, RestconfDataServiceConstant.ReadData.READ_TYPE_TX,
+ dataFactory);
+ return dataFactory.build();
}
/**
* - {@link TransactionVarsWrapper} - wrapper for variables
* @return {@link NormalizedNode}
*/
- private static NormalizedNode<?, ?> readAllData(final TransactionVarsWrapper transactionNode) {
+ private static @Nullable NormalizedNode<?, ?> readAllData(@Nonnull final TransactionVarsWrapper transactionNode) {
// PREPARE STATE DATA NODE
transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
final NormalizedNode<?, ?> stateDataNode = readDataViaTransaction(transactionNode);
// if no data exists
if ((stateDataNode == null) && (configDataNode == null)) {
- throw new RestconfDocumentedException(
- "Request could not be completed because the relevant data model content does not exist",
- ErrorType.PROTOCOL,
- ErrorTag.DATA_MISSING);
+ return null;
}
// return config data
* - data node of state data
* @param configDataNode
* - data node of config data
- * @param transactionNode
- * - {@link TransactionVarsWrapper} - wrapper for variables
* @return {@link NormalizedNode}
*/
- private static NormalizedNode<?, ?> mapNode(final NormalizedNode<?, ?> stateDataNode,
- final NormalizedNode<?, ?> configDataNode) {
+ private static @Nonnull NormalizedNode<?, ?> mapNode(@Nonnull final NormalizedNode<?, ?> stateDataNode,
+ @Nonnull final NormalizedNode<?, ?> configDataNode) {
validPossibilityOfMergeNodes(stateDataNode, configDataNode);
if (configDataNode instanceof RpcDefinition) {
return prepareRpcData(configDataNode, stateDataNode);
}
}
+ /**
+ * Valid of can be data merged together.
+ *
+ * @param stateDataNode
+ * - data node of state data
+ * @param configDataNode
+ * - data node of config data
+ */
+ private static void validPossibilityOfMergeNodes(@Nonnull final NormalizedNode<?, ?> stateDataNode,
+ @Nonnull final NormalizedNode<?, ?> configDataNode) {
+ final QNameModule moduleOfStateData = stateDataNode.getIdentifier().getNodeType().getModule();
+ final QNameModule moduleOfConfigData = configDataNode.getIdentifier().getNodeType().getModule();
+ if (moduleOfStateData != moduleOfConfigData) {
+ throw new RestconfDocumentedException("It is not possible to merge ");
+ }
+ }
+
/**
* Prepare and map data for rpc
*
* - data node of state data
* @return {@link NormalizedNode}
*/
- private static NormalizedNode<?, ?> prepareRpcData(final NormalizedNode<?, ?> configDataNode,
- final NormalizedNode<?, ?> stateDataNode) {
+ private static @Nonnull NormalizedNode<?, ?> prepareRpcData(@Nonnull final NormalizedNode<?, ?> configDataNode,
+ @Nonnull final NormalizedNode<?, ?> stateDataNode) {
final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = ImmutableNodes
.mapEntryBuilder();
mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier());
* @param mapEntryBuilder
* - builder for mapping data
*/
- private static void mapRpcDataNode(final NormalizedNode<?, ?> dataNode,
- final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
- for (final DataContainerChild<? extends PathArgument, ?> child : ((ContainerNode) dataNode).getValue()) {
- mapEntryBuilder.addChild(child);
- }
+ private static void mapRpcDataNode(@Nonnull final NormalizedNode<?, ?> dataNode,
+ @Nonnull final DataContainerNodeBuilder<
+ NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
+ ((ContainerNode) dataNode).getValue().forEach(mapEntryBuilder::addChild);
}
/**
* - data node of state data
* @return {@link NormalizedNode}
*/
- private static NormalizedNode<?, ?> prepareData(final NormalizedNode<?, ?> configDataNode,
- final NormalizedNode<?, ?> stateDataNode) {
-
- if (configDataNode instanceof MapNode) { // part for lists mapping
- final MapNode immutableStateData = ImmutableNodes.mapNodeBuilder(stateDataNode.getNodeType())
- .addChild((MapEntryNode) stateDataNode).build();
- final MapNode immutableConfigData = ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType())
- .addChild((MapEntryNode) configDataNode).build();
- final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = ImmutableNodes
- .mapEntryBuilder();
- mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier());
-
- // MAP CONFIG DATA
- mapDataNode(immutableConfigData, mapEntryBuilder);
- // MAP STATE DATA
- mapDataNode(immutableStateData, mapEntryBuilder);
- return ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()).addChild(mapEntryBuilder.build()).build();
- } else if (configDataNode instanceof ContainerNode) { // part for
- // containers
- // mapping
- final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> containerBuilder = Builders
- .containerBuilder((ContainerNode) configDataNode);
- // MAP CONFIG DATA
- mapCont(containerBuilder, ((ContainerNode) configDataNode).getValue());
- // MAP STATE DATA
- mapCont(containerBuilder, ((ContainerNode) stateDataNode).getValue());
-
- return containerBuilder.build();
+ private static @Nonnull NormalizedNode<?, ?> prepareData(@Nonnull final NormalizedNode<?, ?> configDataNode,
+ @Nonnull final NormalizedNode<?, ?> stateDataNode) {
+ if (configDataNode instanceof MapNode) {
+ final CollectionNodeBuilder<MapEntryNode, MapNode> builder = ImmutableNodes
+ .mapNodeBuilder().withNodeIdentifier(((MapNode) configDataNode).getIdentifier());
+
+ mapValueToBuilder(
+ ((MapNode) configDataNode).getValue(), ((MapNode) stateDataNode).getValue(), builder);
+
+ return builder.build();
+ } else if (configDataNode instanceof MapEntryNode) {
+ final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = ImmutableNodes
+ .mapEntryBuilder().withNodeIdentifier(((MapEntryNode) configDataNode).getIdentifier());
+
+ mapValueToBuilder(
+ ((MapEntryNode) configDataNode).getValue(), ((MapEntryNode) stateDataNode).getValue(), builder);
+
+ return builder.build();
+ } else if (configDataNode instanceof ContainerNode) {
+ final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = Builders
+ .containerBuilder().withNodeIdentifier(((ContainerNode) configDataNode).getIdentifier());
+
+ mapValueToBuilder(
+ ((ContainerNode) configDataNode).getValue(), ((ContainerNode) stateDataNode).getValue(), builder);
+
+ return builder.build();
+ } else if (configDataNode instanceof AugmentationNode) {
+ final DataContainerNodeBuilder<AugmentationIdentifier, AugmentationNode> builder = Builders
+ .augmentationBuilder().withNodeIdentifier(((AugmentationNode) configDataNode).getIdentifier());
+
+ mapValueToBuilder(
+ ((AugmentationNode) configDataNode).getValue(), ((AugmentationNode) stateDataNode).getValue(), builder);
+
+ return builder.build();
+ } else if (configDataNode instanceof ChoiceNode) {
+ final DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> builder = Builders
+ .choiceBuilder().withNodeIdentifier(((ChoiceNode) configDataNode).getIdentifier());
+
+ mapValueToBuilder(
+ ((ChoiceNode) configDataNode).getValue(), ((ChoiceNode) stateDataNode).getValue(), builder);
+
+ return builder.build();
+ } else if (configDataNode instanceof LeafNode) {
+ return ImmutableNodes.leafNode(configDataNode.getNodeType(), configDataNode.getValue());
} else {
throw new RestconfDocumentedException("Bad type of node.");
}
}
/**
- * Map data to builder
+ * Map value from container node to builder.
*
- * @param containerBuilder
- * - builder for mapping data
- * @param childs
- * - childs of data (container)
+ * @param configData
+ * - collection of config data nodes
+ * @param stateData
+ * - collection of state data nodes
+ * @param builder
+ * - builder
*/
- private static void mapCont(final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> containerBuilder,
- final Collection<DataContainerChild<? extends PathArgument, ?>> childs) {
- for (final DataContainerChild<? extends PathArgument, ?> child : childs) {
- containerBuilder.addChild(child);
- }
- }
+ private static <T extends NormalizedNode<? extends PathArgument, ?>> void mapValueToBuilder(
+ @Nonnull final Collection<T> configData,
+ @Nonnull final Collection<T> stateData,
+ @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+ final Map<PathArgument, T> configMap = configData.stream().collect(
+ Collectors.toMap(NormalizedNode::getIdentifier, Function.identity()));
+ final Map<PathArgument, T> stateMap = stateData.stream().collect(
+ Collectors.toMap(NormalizedNode::getIdentifier, Function.identity()));
- /**
- * Map data to builder
- *
- * @param immutableData
- * - immutable data - {@link MapNode}
- * @param mapEntryBuilder
- * - builder for mapping data
- */
- private static void mapDataNode(final MapNode immutableData,
- final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
- for (final DataContainerChild<? extends PathArgument, ?> child : immutableData.getValue().iterator()
- .next().getValue()) {
- Preconditions.checkNotNull(child);
- if (child instanceof ContainerNode) {
- addChildToMap(ContainerNode.class, child, mapEntryBuilder);
- } else if (child instanceof AugmentationNode) {
- addChildToMap(AugmentationNode.class, child, mapEntryBuilder);
- } else if(child instanceof MapNode){
- final MapNode listNode = (MapNode) child;
- for (final MapEntryNode listChild : listNode.getValue()) {
- for (final DataContainerChild<? extends PathArgument, ?> entryChild : listChild.getValue()) {
- addChildToMap(MapEntryNode.class, entryChild, mapEntryBuilder);
- }
- }
- } else if (child instanceof ChoiceNode) {
- addChildToMap(ChoiceNode.class, child, mapEntryBuilder);
- } else if ((child instanceof LeafSetNode<?>) || (child instanceof LeafNode)) {
- mapEntryBuilder.addChild(child);
- }
+ // merge config and state data of children with different identifiers
+ mapDataToBuilder(configMap, stateMap, builder);
- }
+ // merge config and state data of children with the same identifiers
+ mergeDataToBuilder(configMap, stateMap, builder);
}
/**
- * Mapping child
+ * Map data with different identifiers to builder. Data with different identifiers can be just added
+ * as childs to parent node.
*
- * @param type
- * - type of data
- * @param child
- * - child to map
- * @param mapEntryBuilder
- * - builder for mapping child
+ * @param configMap
+ * - map of config data nodes
+ * @param stateMap
+ * - map of state data nodes
+ * @param builder
+ * - builder
*/
- private static <T extends DataContainerNode<? extends PathArgument>> void addChildToMap(final Class<T> type,
- final DataContainerChild<? extends PathArgument, ?> child,
- final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder) {
- @SuppressWarnings("unchecked")
- final T node = (T) child;
- for (final DataContainerChild<? extends PathArgument, ?> childNode : node.getValue()) {
- mapEntryBuilder.addChild(childNode);
- }
+ private static <T extends NormalizedNode<? extends PathArgument, ?>> void mapDataToBuilder(
+ @Nonnull final Map<PathArgument, T> configMap,
+ @Nonnull final Map<PathArgument, T> stateMap,
+ @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+ configMap.entrySet().stream().filter(x -> !stateMap.containsKey(x.getKey())).forEach(
+ y -> builder.addChild(y.getValue()));
+ stateMap.entrySet().stream().filter(x -> !configMap.containsKey(x.getKey())).forEach(
+ y -> builder.addChild(y.getValue()));
}
/**
- * Valid of can be data merged together.
+ * Map data with the same identifiers to builder. Data with the same identifiers cannot be just added but we need to
+ * go one level down with {@code prepareData} method.
*
- * @param stateDataNode
- * - data node of state data
- * @param configDataNode
- * - data node of config data
+ * @param configMap
+ * - immutable config data
+ * @param stateMap
+ * - immutable state data
+ * @param builder
+ * - builder
*/
- private static void validPossibilityOfMergeNodes(@Nonnull final NormalizedNode<?, ?> stateDataNode,
- @Nonnull final NormalizedNode<?, ?> configDataNode) {
- final QNameModule moduleOfStateData = stateDataNode.getIdentifier().getNodeType().getModule();
- final QNameModule moduleOfConfigData = configDataNode.getIdentifier().getNodeType().getModule();
- if (moduleOfStateData != moduleOfConfigData) {
- throw new RestconfDocumentedException("It is not possible to merge ");
- }
+ @SuppressWarnings("unchecked")
+ private static <T extends NormalizedNode<? extends PathArgument, ?>> void mergeDataToBuilder(
+ @Nonnull final Map<PathArgument, T> configMap,
+ @Nonnull final Map<PathArgument, T> stateMap,
+ @Nonnull final NormalizedNodeContainerBuilder<?, PathArgument, T, ?> builder) {
+ // it is enough to process only config data because operational contains the same data
+ configMap.entrySet().stream().filter(x -> stateMap.containsKey(x.getKey())).forEach(
+ y -> builder.addChild((T) prepareData(y.getValue(), stateMap.get(y.getKey()))));
}
}
*/
package org.opendaylight.restconf.utils.parser;
+import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
-import javax.annotation.Nullable;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
import org.opendaylight.netconf.md.sal.rest.schema.SchemaExportContext;
}
/**
- * Make {@link InstanceIdentifierContext} from identifier.
+ * Make {@link InstanceIdentifierContext} from {@link String} identifier
+ * <br>
+ * For identifiers of data NOT behind mount points returned
+ * {@link InstanceIdentifierContext} is prepared with {@code null} reference of {@link DOMMountPoint} and with
+ * controller's {@link SchemaContext}.
+ * <br>
+ * For identifiers of data behind mount points returned
+ * {@link InstanceIdentifierContext} is prepared with reference of {@link DOMMountPoint} and its
+ * own {@link SchemaContext}.
*
* @param identifier
- * - path identifier
+ * - path identifier
* @param schemaContext
- * - {@link SchemaContext}
+ * - controller schema context
+ * @param mountPointService
+ * - mount point service
* @return {@link InstanceIdentifierContext}
*/
- public static InstanceIdentifierContext<?> toInstanceIdentifier(@Nullable final String identifier,
- final SchemaContext schemaContext) {
- final YangInstanceIdentifier deserialize;
+ public static InstanceIdentifierContext<?> toInstanceIdentifier(
+ final String identifier,
+ final SchemaContext schemaContext,
+ final Optional<DOMMountPointService> mountPointService) {
if (identifier != null && identifier.contains(RestconfConstants.MOUNT)) {
- final String mountPointId = identifier.substring(0, identifier.indexOf("/" + RestconfConstants.MOUNT));
- deserialize = IdentifierCodec.deserialize(mountPointId, schemaContext);
+ if (!mountPointService.isPresent()) {
+ throw new RestconfDocumentedException("Mount point service is not available");
+ }
+
+ final Iterator<String> pathsIt = Splitter.on("/" + RestconfConstants.MOUNT).split(identifier).iterator();
+
+ final String mountPointId = pathsIt.next();
+ final YangInstanceIdentifier mountYangInstanceIdentifier = IdentifierCodec.deserialize(
+ mountPointId, schemaContext);
+ final Optional<DOMMountPoint> mountPoint = mountPointService.get().getMountPoint(mountYangInstanceIdentifier);
+
+ if (!mountPoint.isPresent()) {
+ throw new RestconfDocumentedException(
+ "Mount point does not exist.", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING);
+ }
+
+ final String pathId = pathsIt.next().replaceFirst("/", "");
+ final YangInstanceIdentifier pathYangInstanceIdentifier = IdentifierCodec.deserialize(
+ pathId, mountPoint.get().getSchemaContext());
+
+ final DataSchemaContextNode<?> child = DataSchemaContextTree.from(
+ mountPoint.get().getSchemaContext()).getChild(pathYangInstanceIdentifier);
+
+ return new InstanceIdentifierContext<SchemaNode>(
+ pathYangInstanceIdentifier, child.getDataSchemaNode(), mountPoint.get(),
+ mountPoint.get().getSchemaContext());
} else {
- deserialize = IdentifierCodec.deserialize(identifier, schemaContext);
+ final YangInstanceIdentifier deserialize = IdentifierCodec.deserialize(identifier, schemaContext);
+ final DataSchemaContextNode<?> child = DataSchemaContextTree.from(schemaContext).getChild(deserialize);
+
+ return new InstanceIdentifierContext<SchemaNode>(
+ deserialize, child.getDataSchemaNode(), null, schemaContext);
}
- final DataSchemaContextNode<?> child = DataSchemaContextTree.from(schemaContext).getChild(deserialize);
- return new InstanceIdentifierContext<SchemaNode>(deserialize, child.getDataSchemaNode(), null, schemaContext);
}
/**
pathBuilder.append(current);
}
final InstanceIdentifierContext<?> point = ParserIdentifier
- .toInstanceIdentifier(pathBuilder.toString(), schemaContext);
- final DOMMountPoint mountPoint = domMountPointService.getMountPoint(point.getInstanceIdentifier()).get();
+ .toInstanceIdentifier(pathBuilder.toString(), schemaContext, Optional.of(domMountPointService));
final String moduleName = RestconfValidation.validateAndGetModulName(componentIter);
final Date revision = RestconfValidation.validateAndGetRevision(componentIter);
- final Module module = mountPoint.getSchemaContext().findModuleByName(moduleName, revision);
- return new SchemaExportContext(mountPoint.getSchemaContext(), module);
+ final Module module = point.getMountPoint().getSchemaContext().findModuleByName(moduleName, revision);
+ return new SchemaExportContext(point.getMountPoint().getSchemaContext(), module);
}
}
}
/**
* Negative test of getting specific module supported by the mount point when specified mount point is not found
* (it is not registered in <code>DOMMountPointService</code>). Test is expected to fail with
- * <code>IllegalStateException</code>.
+ * <code>RestconfDocumentedException</code> and error type, error tag and error status code are compared to
+ * expected values.
*/
@Test
public void getModuleMountPointNotFoundNegativeTest() throws Exception {
final RestconfModulesService modulesService = setupNormalMountPoint();
// make test
- this.thrown.expect(IllegalStateException.class);
- modulesService.getModule(TEST_MODULE_BEHIND_NOT_REGISTERED_MOUNT_POINT, null);
+ try {
+ modulesService.getModule(TEST_MODULE_BEHIND_NOT_REGISTERED_MOUNT_POINT, null);
+ fail("Test should fail due to missing mount point");
+ } catch (final RestconfDocumentedException e) {
+ assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
+ assertEquals("Error tag is not correct", ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
+ assertEquals("Error code is not correct", 404, e.getErrors().get(0).getErrorTag().getStatusCode());
+ }
}
/**
* Negative test of getting all modules supported by the mount point when specified mount point is not found (it
* is not registered in <code>DOMMountPointService</code>). Test is expected to fail with
- * <code>IllegalStateException</code>.
+ * <code>RestconfDocumentedException</code> and error type, error tag and error status code are compared to
+ * expected values.
*/
@Test
public void getModulesMountPointNotFoundNegativeTest() throws Exception {
final RestconfModulesService modulesService = setupNormalMountPoint();
// make test
- this.thrown.expect(IllegalStateException.class);
- modulesService.getModules(NOT_REGISTERED_MOUNT_POINT, null);
+ try {
+ modulesService.getModules(NOT_REGISTERED_MOUNT_POINT, null);
+ fail("Test should fail due to missing mount point");
+ } catch (final RestconfDocumentedException e) {
+ assertEquals("Error type is not correct", ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
+ assertEquals("Error tag is not correct", ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
+ assertEquals("Error code is not correct", 404, e.getErrors().get(0).getErrorTag().getStatusCode());
+ }
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.restconf.restful.services.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
+import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
+import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+import org.opendaylight.netconf.sal.restconf.impl.PATCHContext;
+import org.opendaylight.netconf.sal.restconf.impl.PATCHEntity;
+import org.opendaylight.netconf.sal.restconf.impl.PATCHStatusContext;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.restconf.RestConnectorProvider;
+import org.opendaylight.restconf.common.references.SchemaContextRef;
+import org.opendaylight.restconf.handlers.DOMMountPointServiceHandler;
+import org.opendaylight.restconf.handlers.SchemaContextHandler;
+import org.opendaylight.restconf.handlers.TransactionChainHandler;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+public class RestconfDataServiceImplTest {
+
+ private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
+
+ private ContainerNode buildBaseCont;
+ private ContainerNode buildBaseContConfig;
+ private ContainerNode buildBaseContOperational;
+ private SchemaContextRef contextRef;
+ private YangInstanceIdentifier iidBase;
+ private DataSchemaNode schemaNode;
+ private RestconfDataServiceImpl dataService;
+ private QName baseQName;
+ private QName containerPlayerQname;
+ private QName leafQname;
+ private ContainerNode buildPlayerCont;
+ private ContainerNode buildLibraryCont;
+ private MapNode buildPlaylistList;
+
+ @Mock
+ private TransactionChainHandler transactionChainHandler;
+ @Mock
+ private DOMTransactionChain domTransactionChain;
+ @Mock
+ private UriInfo uriInfo;
+ @Mock
+ private DOMDataReadWriteTransaction readWrite;
+ @Mock
+ private DOMDataReadOnlyTransaction read;
+ @Mock
+ private DOMDataWriteTransaction write;
+ @Mock
+ private DOMMountPointServiceHandler mountPointServiceHandler;
+ @Mock
+ private DOMMountPointService mountPointService;
+ @Mock
+ private DOMMountPoint mountPoint;
+ @Mock
+ private DOMDataBroker mountDataBroker;
+ @Mock
+ private DOMTransactionChain transactionChain;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ this.baseQName = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
+ this.containerPlayerQname = QName.create(this.baseQName, "player");
+ this.leafQname = QName.create(this.baseQName, "gap");
+
+ final QName containerLibraryQName = QName.create(this.baseQName, "library");
+ final QName listPlaylistQName = QName.create(this.baseQName, "playlist");
+
+ final LeafNode buildLeaf = Builders.leafBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.leafQname))
+ .withValue(0.2)
+ .build();
+
+ this.buildPlayerCont = Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.containerPlayerQname))
+ .withChild(buildLeaf)
+ .build();
+
+ this.buildLibraryCont = Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(containerLibraryQName))
+ .build();
+
+ this.buildPlaylistList = Builders.mapBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(listPlaylistQName))
+ .build();
+
+ this.buildBaseCont = Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.baseQName))
+ .withChild(this.buildPlayerCont)
+ .build();
+
+ // config contains one child the same as in operational and one additional
+ this.buildBaseContConfig = Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.baseQName))
+ .withChild(this.buildPlayerCont)
+ .withChild(this.buildLibraryCont)
+ .build();
+
+ // operational contains one child the same as in config and one additional
+ this.buildBaseContOperational = Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(this.baseQName))
+ .withChild(this.buildPlayerCont)
+ .withChild(this.buildPlaylistList)
+ .build();
+
+ this.iidBase = YangInstanceIdentifier.builder()
+ .node(this.baseQName)
+ .build();
+
+ this.contextRef = new SchemaContextRef(TestRestconfUtils.loadSchemaContext(PATH_FOR_NEW_SCHEMA_CONTEXT));
+ this.schemaNode = DataSchemaContextTree.from(this.contextRef.get()).getChild(this.iidBase).getDataSchemaNode();
+
+ final SchemaContextHandler schemaContextHandler = new SchemaContextHandler();
+
+ schemaContextHandler.onGlobalContextUpdated(this.contextRef.get());
+ this.dataService = new RestconfDataServiceImpl(schemaContextHandler, this.transactionChainHandler, this.mountPointServiceHandler);
+ doReturn(this.domTransactionChain).when(this.transactionChainHandler).get();
+ doReturn(this.read).when(this.domTransactionChain).newReadOnlyTransaction();
+ doReturn(this.readWrite).when(this.domTransactionChain).newReadWriteTransaction();
+ doReturn(this.write).when(this.domTransactionChain).newWriteOnlyTransaction();
+ doReturn(this.mountPointService).when(this.mountPointServiceHandler).get();
+ doReturn(Optional.of(this.mountPoint)).when(this.mountPointService).getMountPoint(any(YangInstanceIdentifier.class));
+ doReturn(this.contextRef.get()).when(this.mountPoint).getSchemaContext();
+ doReturn(Optional.of(this.mountDataBroker)).when(this.mountPoint).getService(DOMDataBroker.class);
+ doReturn(this.transactionChain).when(this.mountDataBroker).createTransactionChain(any(TransactionChainListener.class));
+ doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
+ doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
+ }
+
+ @Test
+ public void testReadData() {
+ doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
+ doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
+ .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
+ final Response response = this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ assertEquals(this.buildBaseCont, ((NormalizedNodeContext) response.getEntity()).getData());
+ }
+
+ /**
+ * Test read data from mount point when both {@link LogicalDatastoreType#CONFIGURATION} and
+ * {@link LogicalDatastoreType#OPERATIONAL} contains the same data and some additional data to be merged.
+ */
+ @Test
+ public void testReadDataMountPoint() {
+ doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
+ doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContConfig))).when(this.read)
+ .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseContOperational))).when(this.read)
+ .read(LogicalDatastoreType.OPERATIONAL, this.iidBase);
+
+ final Response response = this.dataService.readData(
+ "example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox", this.uriInfo);
+
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+
+ // response must contain all child nodes from config and operational containers merged in one container
+ final NormalizedNode<?, ?> data = ((NormalizedNodeContext) response.getEntity()).getData();
+ assertTrue(data instanceof ContainerNode);
+ assertEquals(3, ((ContainerNode) data).getValue().size());
+ assertTrue(((ContainerNode) data).getChild(this.buildPlayerCont.getIdentifier()).isPresent());
+ assertTrue(((ContainerNode) data).getChild(this.buildLibraryCont.getIdentifier()).isPresent());
+ assertTrue(((ContainerNode) data).getChild(this.buildPlaylistList.getIdentifier()).isPresent());
+ }
+
+ @Test(expected = RestconfDocumentedException.class)
+ public void testReadDataNoData() {
+ doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION,
+ this.iidBase);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.OPERATIONAL,
+ this.iidBase);
+ this.dataService.readData("example-jukebox:jukebox", this.uriInfo);
+ }
+
+ @Ignore
+ @Test
+ public void testPutData() {
+ final InstanceIdentifierContext<DataSchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef.get());
+ final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
+
+ doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
+ .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.write).submit();
+ final Response response = this.dataService.putData(null, payload);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ }
+
+ @Ignore
+ @Test
+ public void testPutDataWithMountPoint() {
+ final DOMDataBroker dataBroker = Mockito.mock(DOMDataBroker.class);
+ final DOMMountPoint mountPoint = Mockito.mock(DOMMountPoint.class);
+ doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
+ doReturn(this.transactionChainHandler.get()).when(dataBroker).createTransactionChain(RestConnectorProvider.transactionListener);
+ final InstanceIdentifierContext<DataSchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, mountPoint, this.contextRef.get());
+ final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.buildBaseCont);
+
+ doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
+ .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, payload.getData());
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.write).submit();
+ final Response response = this.dataService.putData(null, payload);
+ assertNotNull(response);
+ assertEquals(200, response.getStatus());
+ }
+
+ @Test
+ public void testPostData() {
+ final QName listQname = QName.create(this.baseQName, "playlist");
+ final QName listKeyQname = QName.create(this.baseQName, "name");
+ final YangInstanceIdentifier.NodeIdentifierWithPredicates nodeWithKey =
+ new YangInstanceIdentifier.NodeIdentifierWithPredicates(listQname, listKeyQname, "name of band");
+ final LeafNode<Object> content = Builders.leafBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(this.baseQName, "name")))
+ .withValue("name of band")
+ .build();
+ final LeafNode<Object> content2 = Builders.leafBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(this.baseQName, "description")))
+ .withValue("band description")
+ .build();
+ final MapEntryNode mapEntryNode = Builders.mapEntryBuilder()
+ .withNodeIdentifier(nodeWithKey)
+ .withChild(content)
+ .withChild(content2)
+ .build();
+ final MapNode buildList = Builders.mapBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(listQname))
+ .withChild(mapEntryNode)
+ .build();
+
+ doReturn(new MultivaluedHashMap<String, String>()).when(this.uriInfo).getQueryParameters();
+ final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, null, null, this.contextRef.get());
+ final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, buildList);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(this.read).read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ final MapNode data = (MapNode) payload.getData();
+ final YangInstanceIdentifier.NodeIdentifierWithPredicates identifier = data.getValue().iterator().next().getIdentifier();
+ final YangInstanceIdentifier node = payload.getInstanceIdentifierContext().getInstanceIdentifier().node(identifier);
+ doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
+ doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION, node, payload.getData());
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
+ doReturn(UriBuilder.fromUri("http://localhost:8181/restconf/15/")).when(this.uriInfo).getBaseUriBuilder();
+
+ final Response response = this.dataService.postData(null, payload, this.uriInfo);
+ assertEquals(201, response.getStatus());
+ }
+
+ @Test
+ public void testDeleteData() {
+ doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
+ doReturn(Futures.immediateCheckedFuture(true)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ final Response response = this.dataService.deleteData("example-jukebox:jukebox");
+ assertNotNull(response);
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ }
+
+ /**
+ * Test of deleting data on mount point
+ */
+ @Test
+ public void testDeleteDataMountPoint() {
+ doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
+ doReturn(Futures.immediateCheckedFuture(true)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ final Response response = this.dataService.deleteData("example-jukebox:jukebox/yang-ext:mount/example-jukebox:jukebox");
+ assertNotNull(response);
+ assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
+ }
+
+ @Test
+ public void testPatchData() throws Exception {
+ final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef.get());
+ final List<PATCHEntity> entity = new ArrayList<>();
+ final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
+ .node(this.containerPlayerQname)
+ .node(this.leafQname)
+ .build();
+ entity.add(new PATCHEntity("create data", "CREATE", this.iidBase, this.buildBaseCont));
+ entity.add(new PATCHEntity("replace data", "REPLACE", this.iidBase, this.buildBaseCont));
+ entity.add(new PATCHEntity("delete data", "DELETE", iidleaf));
+ final PATCHContext patch = new PATCHContext(iidContext, entity, "test patch id");
+
+ doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
+ .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.write).submit();
+ doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
+ doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doReturn(Futures.immediateCheckedFuture(true)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
+ final PATCHStatusContext status = this.dataService.patchData(patch, this.uriInfo);
+ assertTrue(status.isOk());
+ assertEquals(3, status.getEditCollection().size());
+ assertEquals("replace data", status.getEditCollection().get(1).getEditId());
+ }
+
+ @Test
+ public void testPatchDataDeleteNotExist() throws Exception {
+ final Field handler = RestConnectorProvider.class.getDeclaredField("transactionChainHandler");
+ final Field broker = RestConnectorProvider.class.getDeclaredField("dataBroker");
+
+ handler.setAccessible(true);
+ handler.set(RestConnectorProvider.class, mock(TransactionChainHandler.class));
+
+ broker.setAccessible(true);
+ broker.set(RestConnectorProvider.class, mock(DOMDataBroker.class));
+ final InstanceIdentifierContext<? extends SchemaNode> iidContext = new InstanceIdentifierContext<>(this.iidBase, this.schemaNode, null, this.contextRef.get());
+ final List<PATCHEntity> entity = new ArrayList<>();
+ final YangInstanceIdentifier iidleaf = YangInstanceIdentifier.builder(this.iidBase)
+ .node(this.containerPlayerQname)
+ .node(this.leafQname)
+ .build();
+ entity.add(new PATCHEntity("create data", "CREATE", this.iidBase, this.buildBaseCont));
+ entity.add(new PATCHEntity("remove data", "REMOVE", iidleaf));
+ entity.add(new PATCHEntity("delete data", "DELETE", iidleaf));
+ final PATCHContext patch = new PATCHContext(iidContext, entity, "test patch id");
+
+ doReturn(Futures.immediateCheckedFuture(Optional.of(this.buildBaseCont))).when(this.read)
+ .read(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doNothing().when(this.write).put(LogicalDatastoreType.CONFIGURATION, this.iidBase, this.buildBaseCont);
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.write).submit();
+ doNothing().when(this.readWrite).delete(LogicalDatastoreType.CONFIGURATION, iidleaf);
+ doReturn(Futures.immediateCheckedFuture(null)).when(this.readWrite).submit();
+ doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidBase);
+ doReturn(Futures.immediateCheckedFuture(false)).when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, iidleaf);
+ doReturn(true).when(this.readWrite).cancel();
+ final PATCHStatusContext status = this.dataService.patchData(patch, this.uriInfo);
+
+ handler.set(RestConnectorProvider.class, null);
+ handler.setAccessible(false);
+
+ broker.set(RestConnectorProvider.class, null);
+ broker.setAccessible(false);
+
+ assertFalse(status.isOk());
+ assertEquals(3, status.getEditCollection().size());
+ assertTrue(status.getEditCollection().get(0).isOk());
+ assertTrue(status.getEditCollection().get(1).isOk());
+ assertFalse(status.getEditCollection().get(2).isOk());
+ assertFalse(status.getEditCollection().get(2).getEditErrors().isEmpty());
+ final String errorMessage = status.getEditCollection().get(2).getEditErrors().get(0).getErrorMessage();
+ assertEquals("Data does not exist", errorMessage);
+ }
+}
\ No newline at end of file
import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
import org.opendaylight.restconf.utils.RestconfConstants;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
* Unit tests for {@link ParserIdentifier}
*/
public class ParserIdentifierTest {
- // mount point identifier + expected result
+ // mount point identifier
private static final String MOUNT_POINT_IDENT =
"mount-point:mount-container/point-number" + "/" + RestconfConstants.MOUNT;
- private static final String MOUNT_POINT_IDENT_RESULT =
- "/(mount:point?revision=2016-06-02)mount-container/point-number";
-
// invalid mount point identifier
private static final String INVALID_MOUNT_POINT_IDENT =
"mount-point:point-number" + "/" + RestconfConstants.MOUNT;
// schema context with test modules
private SchemaContext schemaContext;
+ // contains the same modules but it is different object (it can be compared with equals)
+ private SchemaContext schemaContextOnMountPoint;
private static final String TEST_MODULE_NAME = "test-module";
private static final String TEST_MODULE_REVISION = "2016-06-02";
private DOMMountPointService mountPointService;
// mock mount point and mount point service
- @Mock DOMMountPoint mockMountPoint;
- @Mock DOMMountPointService mockMountPointService;
+ @Mock
+ private DOMMountPoint mockMountPoint;
+ @Mock
+ private DOMMountPointService mockMountPointService;
@Rule
public final ExpectedException thrown = ExpectedException.none();
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
schemaContext = TestRestconfUtils.loadSchemaContext("/parser-identifier");
+ schemaContextOnMountPoint = TestRestconfUtils.loadSchemaContext("/parser-identifier");
// create and register mount point
mountPoint = SimpleDOMMountPoint.create(
.node(QName.create("mount:point", "2016-06-02", "point-number"))
.build(),
ImmutableClassToInstanceMap.copyOf(Maps.newHashMap()),
- schemaContext
+ schemaContextOnMountPoint
);
mountPointService = new DOMMountPointServiceImpl();
@Test
public void toInstanceIdentifierTest() {
final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
- TEST_IDENT, schemaContext);
+ TEST_IDENT, schemaContext, Optional.absent());
assertEquals("Returned not expected identifier",
TEST_IDENT_RESULT, context .getInstanceIdentifier().toString());
@Test
public void toInstanceIdentifierOtherModulesTest() {
final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
- TEST_IDENT_OTHERS, schemaContext);
+ TEST_IDENT_OTHERS, schemaContext, Optional.absent());
assertEquals("Returned not expected identifier",
TEST_IDENT_OTHERS_RESULT, context.getInstanceIdentifier().toString());
@Test
public void toInstanceIdentifierMountPointTest() {
final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
- MOUNT_POINT_IDENT, schemaContext);
+ MOUNT_POINT_IDENT + "/" + TEST_IDENT, schemaContext, Optional.of(mountPointService));
assertEquals("Returned not expected identifier",
- MOUNT_POINT_IDENT_RESULT, context.getInstanceIdentifier().toString());
+ TEST_IDENT_RESULT.toString(), context.getInstanceIdentifier().toString());
+
+ assertEquals("Mount point not found",
+ mountPoint, context.getMountPoint());
+
+ assertEquals("Schema context from mount point expected",
+ schemaContextOnMountPoint, context.getSchemaContext());
}
/**
*/
@Test
public void toInstanceIdentifierNullIdentifierTest() {
- final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(null, schemaContext);
+ final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
+ null, schemaContext, Optional.absent());
assertEquals("Returned not expected identifier",
YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
}
@Test
public void toInstanceIdentifierNullSchemaContextNegativeTest() {
thrown.expect(NullPointerException.class);
- ParserIdentifier.toInstanceIdentifier(TEST_IDENT, null);
+ ParserIdentifier.toInstanceIdentifier(TEST_IDENT, null, Optional.absent());
}
/**
*/
@Test
public void toInstanceIdentifierEmptyIdentifierTest() {
- final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier("", schemaContext);
- assertEquals("Returned not expected identifier",
- YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
- }
-
- /**
- * Api path can be empty. <code>YangInstanceIdentifier.EMPTY</code> is expected to be returned.
- * Test when identifier contains {@link RestconfConstants#MOUNT}.
- */
- @Test
- public void toInstanceIdentifierEmptyIdentifierMountPointTest() {
final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
- "" + "/" + RestconfConstants.MOUNT, schemaContext);
+ "", schemaContext, Optional.absent());
assertEquals("Returned not expected identifier",
YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
}
@Test
public void toInstanceIdentifierInvalidIdentifierNegativeTest() {
thrown.expect(IllegalArgumentException.class);
- ParserIdentifier.toInstanceIdentifier(INVALID_TEST_IDENT, schemaContext);
+ ParserIdentifier.toInstanceIdentifier(INVALID_TEST_IDENT, schemaContext, Optional.absent());
}
/**
@Test
public void toInstanceIdentifierMountPointInvalidIdentifierNegativeTest() {
thrown.expect(IllegalArgumentException.class);
- ParserIdentifier.toInstanceIdentifier(INVALID_MOUNT_POINT_IDENT, schemaContext);
+ ParserIdentifier.toInstanceIdentifier(INVALID_MOUNT_POINT_IDENT, schemaContext, Optional.of(mountPointService));
+ }
+
+ /**
+ * Negative test when <code>DOMMountPoint</code> cannot be found. Test is expected to fail with
+ * <code>RestconfDocumentedException</code> error type, error tag and error status code are
+ * compared to expected values.
+ */
+ @Test
+ public void toInstanceIdentifierMissingMountPointNegativeTest() {
+ try {
+ ParserIdentifier.toInstanceIdentifier(
+ "" + "/" + RestconfConstants.MOUNT, schemaContext, Optional.of(mountPointService));
+ fail("Test should fail due to missing mount point");
+ } catch (final RestconfDocumentedException e) {
+ assertEquals("Not expected error type",
+ RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
+ assertEquals("Not expected error tag",
+ ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
+ assertEquals("Not expected error status code",
+ 404, e.getErrors().get(0).getErrorTag().getStatusCode());
+ }
+ }
+
+ /**
+ * Negative test when <code>{@link DOMMountPointService}</code> is absent. Test is expected to fail with
+ * <code>RestconfDocumentedException</code> error type, error tag and error status code are
+ * compared to expected values.
+ */
+ @Test
+ public void toInstanceIdentifierMissingMountPointServiceNegativeTest() {
+ try {
+ ParserIdentifier.toInstanceIdentifier(RestconfConstants.MOUNT, schemaContext, Optional.absent());
+ fail("Test should fail due to absent mount point service");
+ } catch (final RestconfDocumentedException e) {
+ assertEquals("Not expected error type",
+ ErrorType.APPLICATION, e.getErrors().get(0).getErrorType());
+ assertEquals("Not expected error tag",
+ ErrorTag.OPERATION_FAILED, e.getErrors().get(0).getErrorTag());
+ assertEquals("Not expected error status code",
+ 500, e.getErrors().get(0).getErrorTag().getStatusCode());
+ }
}
/**