--- /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 com.google.common.base.Preconditions;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+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.PATCHStatusContext;
+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;
+import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
+import org.opendaylight.restconf.restful.utils.ReadDataTransactionUtil;
+import org.opendaylight.restconf.restful.utils.RestconfDataServiceConstant;
+import org.opendaylight.restconf.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ * Implementation of {@link RestconfDataService}
+ */
+public class RestconfDataServiceImpl implements RestconfDataService {
+
+ private SchemaContextHandler schemaContextHandler;
+ private DOMMountPointServiceHandler domMountPointServiceHandler;
+ private TransactionChainHandler transactionChainHandler;
+
+ @Override
+ public NormalizedNodeContext readData(final String identifier, final UriInfo uriInfo) {
+ Preconditions.checkNotNull(identifier);
+ final SchemaContextRef schemaContextRef = new SchemaContextRef(this.schemaContextHandler.get());
+
+ final InstanceIdentifierContext<?> instanceIdentifier = ParserIdentifier.toInstanceIdentifier(identifier, schemaContextRef.get());
+ final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
+ final String value = uriInfo.getQueryParameters().getFirst(RestconfDataServiceConstant.CONTENT);
+
+ final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
+ this.transactionChainHandler.get(), this.domMountPointServiceHandler.get(), schemaContextRef.get());
+ final NormalizedNode<?, ?> node = ReadDataTransactionUtil.readData(value, transactionNode);
+
+ return new NormalizedNodeContext(instanceIdentifier, node);
+ }
+
+ @Override
+ public Response putData(final String identifier, final NormalizedNodeContext payload) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public Response postData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public Response postData(final NormalizedNodeContext payload, final UriInfo uriInfo) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public Response deleteData(final String identifier) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public PATCHStatusContext patchData(final String identifier, final PATCHContext context, final UriInfo uriInfo) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public PATCHStatusContext patchData(final PATCHContext context, final UriInfo uriInfo) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+}
--- /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.transaction;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.netconf.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * This class represent delegation wrapper for transaction variables.
+ *
+ */
+public final class TransactionVarsWrapper {
+
+ private final InstanceIdentifierContext<?> instanceIdentifier;
+ private final DOMMountPoint mountPoint;
+ private LogicalDatastoreType configuration = null;
+ private final DOMMountPointService domMountPointService;
+ private final SchemaContext schemaContext;
+ private final DOMTransactionChain domTransactionChain;
+
+ /**
+ * Set base type of variables, which ones we need for transaction.
+ * {@link LogicalDatastoreType} is default set to null (to read all data
+ * from ds - config + state).
+ *
+ * @param instanceIdentifier
+ * - {@link InstanceIdentifierContext} of data for transaction
+ * @param mountPoint
+ * - mount point if is presnet
+ * @param domTransactionChain
+ * - {@link DOMTransactionChain} for transactions
+ * @param domMountPointService
+ * - mount point service
+ * @param schemaContext
+ * - {@link SchemaContext}
+ */
+ public TransactionVarsWrapper(final InstanceIdentifierContext<?> instanceIdentifier, final DOMMountPoint mountPoint,
+ final DOMTransactionChain domTransactionChain, final DOMMountPointService domMountPointService,
+ final SchemaContext schemaContext) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.mountPoint = mountPoint;
+ this.domTransactionChain = domTransactionChain;
+ this.domMountPointService = domMountPointService;
+ this.schemaContext = schemaContext;
+ }
+
+ /**
+ * Get instance identifier of data
+ *
+ * @return {@link InstanceIdentifierContext}
+ */
+ public InstanceIdentifierContext<?> getInstanceIdentifier() {
+ return this.instanceIdentifier;
+ }
+
+ /**
+ * Get mount point
+ *
+ * @return {@link DOMMountPoint}
+ */
+ public DOMMountPoint getMountPoint() {
+ return this.mountPoint;
+ }
+
+ /**
+ * Set {@link LogicalDatastoreType} of data for transaction.
+ *
+ * @param configuration
+ * - {@link LogicalDatastoreType}
+ */
+ public void setLogicalDatastoreType(final LogicalDatastoreType configuration) {
+ this.configuration = configuration;
+
+ }
+
+ /**
+ * Get type of data.
+ *
+ * @return {@link LogicalDatastoreType}
+ */
+ public LogicalDatastoreType getLogicalDatastoreType() {
+ return this.configuration;
+ }
+
+ /**
+ * Get mount point service
+ *
+ * @return {@link DOMMountPointService}
+ */
+ public DOMMountPointService getDomMountPointService() {
+ return this.domMountPointService;
+ }
+
+ /**
+ * Get schema context of data
+ *
+ * @return {@link SchemaContext}
+ */
+ public SchemaContext getSchemaContext() {
+ return this.schemaContext;
+ }
+
+ /**
+ * Get transaction chain
+ *
+ * @return {@link DOMTransactionChain}
+ */
+ public DOMTransactionChain getDomTransactionChain() {
+ return this.domTransactionChain;
+ }
+}
--- /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.utils;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Add callback for future objects and result set to the data factory.
+ *
+ */
+final class FutureCallbackTx {
+
+ private final static Logger LOG = LoggerFactory.getLogger(FutureCallbackTx.class);
+
+ private FutureCallbackTx() {
+ throw new UnsupportedOperationException("Util class");
+ }
+
+ /**
+ * Add callback to the future object
+ *
+ * @param listenableFuture
+ * - future object
+ * @param transaction
+ * - transaction used for read of future object
+ * @param txType
+ * - type of operation (READ, POST, PUT, DELETE)
+ * @param dataFactory
+ * - factory setting result
+ */
+ static void addCallback(final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture,
+ final AsyncTransaction<YangInstanceIdentifier, NormalizedNode<?, ?>> transaction, final String txType,
+ final FutureDataFactory dataFactory) {
+ Futures.addCallback(listenableFuture, new FutureCallback<Optional<NormalizedNode<?, ?>>>() {
+
+ @Override
+ public void onFailure(final Throwable t) {
+ handlingLoggerAndValues(t, txType, transaction, null, null);
+ }
+
+ @Override
+ public void onSuccess(final Optional<NormalizedNode<?, ?>> result) {
+ handlingLoggerAndValues(null, txType, transaction, result, dataFactory);
+ }
+
+ });
+ }
+
+ /**
+ * Handling logger and result of callback - on success or on failure
+ * <ul>
+ * <li>on success - set result to the factory
+ * <li>on failure - throw exception
+ * </ul>
+ *
+ * @param t
+ * - exception - if callback is onFailure
+ * @param txType
+ * - type of operation (READ, POST, PUT, DELETE)
+ * @param transaction
+ * - transaction used for read of future object
+ * @param optionalNN
+ * - result - if callback is on Success
+ * @param dataFactory
+ * - setter for result - in callback is onSuccess
+ */
+ protected static void handlingLoggerAndValues(@Nullable final Throwable t, final String txType,
+ final AsyncTransaction<YangInstanceIdentifier, NormalizedNode<?, ?>> transaction,
+ final Optional<NormalizedNode<?, ?>> optionalNN, final FutureDataFactory dataFactory) {
+ if (t != null) {
+ LOG.info("Transaction({}) {} FAILED!", txType, transaction.getIdentifier(), t);
+ throw new IllegalStateException(" Transaction(" + txType + ") not committed correctly", t);
+ } else {
+ LOG.trace("Transaction({}) {} SUCCESSFUL!", txType, transaction.getIdentifier());
+ if (optionalNN.isPresent()) {
+ dataFactory.setData(optionalNN.get());
+ }
+ }
+ }
+}
--- /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.utils;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
+import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
+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.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.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Util class for read data from data store via transaction.
+ * <ul>
+ * <li>config
+ * <li>state
+ * <li>all (config + state)
+ * </ul>
+ *
+ */
+public final class ReadDataTransactionUtil {
+
+ private final static Logger LOG = LoggerFactory.getLogger(ReadDataTransactionUtil.class);
+
+ private ReadDataTransactionUtil() {
+ throw new UnsupportedOperationException("Util class.");
+ }
+
+ /**
+ * Read specific type of data from data store via transaction.
+ *
+ * @param valueOfContent
+ * - type of data to read (config, state, all)
+ * @param transactionNode
+ * - {@link TransactionVarsWrapper} - wrapper for variables
+ * @return {@link NormalizedNode}
+ */
+ public static NormalizedNode<?, ?> readData(final String valueOfContent, final TransactionVarsWrapper transactionNode) {
+ if (valueOfContent != null) {
+ switch (valueOfContent) {
+ case RestconfDataServiceConstant.ReadData.CONFIG:
+ transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
+ return readData(transactionNode);
+ case RestconfDataServiceConstant.ReadData.NONCONFIG:
+ transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
+ return readData(transactionNode);
+ case RestconfDataServiceConstant.ReadData.ALL:
+ return readData(transactionNode);
+ default:
+ throw new RestconfDocumentedException("Bad querry parameter for content.", ErrorType.APPLICATION,
+ ErrorTag.INVALID_VALUE);
+ }
+ } else {
+ return readData(transactionNode);
+ }
+ }
+
+ /**
+ * Check mount point
+ *
+ * @param transactionNode
+ * - {@link TransactionVarsWrapper} - wrapper for variables
+ * @return {@link NormalizedNode}
+ */
+ private static NormalizedNode<?, ?> readData(final TransactionVarsWrapper transactionNode) {
+ if (transactionNode.getMountPoint() == null) {
+ return readDataViaTransaction(transactionNode.getDomTransactionChain().newReadOnlyTransaction(),
+ transactionNode);
+ } else {
+ return readDataOfMountPointViaTransaction(transactionNode);
+ }
+ }
+
+ /**
+ * If is set specific {@link LogicalDatastoreType} in
+ * {@link TransactionVarsWrapper}, then read this type of data from DS. If don't,
+ * we have to read all data from DS (state + config)
+ *
+ * @param readTransaction
+ * - {@link DOMDataReadTransaction} to read data from DS
+ * @param transactionNode
+ * - {@link TransactionVarsWrapper} - wrapper for variables
+ * @return {@link NormalizedNode}
+ */
+ private static NormalizedNode<?, ?> readDataViaTransaction(final DOMDataReadTransaction readTransaction,
+ final TransactionVarsWrapper transactionNode) {
+ if (transactionNode.getLogicalDatastoreType() != null) {
+ final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture = readTransaction
+ .read(transactionNode.getLogicalDatastoreType(),
+ transactionNode.getInstanceIdentifier().getInstanceIdentifier());
+ final FutureDataFactory dataFactory = new FutureDataFactory();
+ FutureCallbackTx.addCallback(listenableFuture, readTransaction,
+ RestconfDataServiceConstant.ReadData.READ_TYPE_TX, dataFactory);
+ return dataFactory.getData();
+ } else {
+ return readAllData(transactionNode);
+ }
+ }
+
+ /**
+ * Prepare transaction to read data of mount point, if these data are
+ * present.
+ *
+ * @param transactionNode
+ * - {@link TransactionVarsWrapper} - wrapper for variables
+ * @return {@link NormalizedNode}
+ */
+ private static NormalizedNode<?, ?> readDataOfMountPointViaTransaction(final TransactionVarsWrapper transactionNode) {
+ final Optional<DOMDataBroker> domDataBrokerService = transactionNode.getMountPoint()
+ .getService(DOMDataBroker.class);
+ if (domDataBrokerService.isPresent()) {
+ return readDataViaTransaction(domDataBrokerService.get().newReadOnlyTransaction(), transactionNode);
+ } else {
+ final String errMsg = "DOM data broker service isn't available for mount point "
+ + transactionNode.getInstanceIdentifier().getInstanceIdentifier();
+ LOG.warn(errMsg);
+ throw new RestconfDocumentedException(errMsg);
+ }
+ }
+
+ /**
+ * Read config and state data, then map them.
+ *
+ * @param transactionNode
+ * - {@link TransactionVarsWrapper} - wrapper for variables
+ * @return {@link NormalizedNode}
+ */
+ private static NormalizedNode<?, ?> readAllData(final TransactionVarsWrapper transactionNode) {
+ // PREPARE STATE DATA NODE
+ transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
+ final NormalizedNode<?, ?> stateDataNode = readData(transactionNode);
+
+ // PREPARE CONFIG DATA NODE
+ transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
+ final NormalizedNode<?, ?> configDataNode = readData(transactionNode);
+
+ return mapNode(stateDataNode, configDataNode, transactionNode);
+ }
+
+ /**
+ * Map data by type of read node.
+ *
+ * @param stateDataNode
+ * - 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,
+ final TransactionVarsWrapper transactionNode) {
+ validPossibilityOfMergeNodes(stateDataNode, configDataNode);
+ if (configDataNode instanceof RpcDefinition) {
+ return prepareRpcData(configDataNode, stateDataNode);
+ } else {
+ return prepareData(configDataNode, stateDataNode);
+ }
+ }
+
+ /**
+ * Prepare and map data for rpc
+ *
+ * @param configDataNode
+ * - data node of config data
+ * @param stateDataNode
+ * - data node of state data
+ * @return {@link NormalizedNode}
+ */
+ private static NormalizedNode<?, ?> prepareRpcData(final NormalizedNode<?, ?> configDataNode,
+ final NormalizedNode<?, ?> stateDataNode) {
+ final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder = ImmutableNodes
+ .mapEntryBuilder();
+ mapEntryBuilder.withNodeIdentifier((NodeIdentifierWithPredicates) configDataNode.getIdentifier());
+
+ // MAP CONFIG DATA
+ mapRpcDataNode(configDataNode, mapEntryBuilder);
+ // MAP STATE DATA
+ mapRpcDataNode(stateDataNode, mapEntryBuilder);
+
+ return ImmutableNodes.mapNodeBuilder(configDataNode.getNodeType()).addChild(mapEntryBuilder.build()).build();
+ }
+
+ /**
+ * Map node to map entry builder.
+ *
+ * @param dataNode
+ * - data node
+ * @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);
+ }
+ }
+
+ /**
+ * Prepare and map all data from DS
+ *
+ * @param configDataNode
+ * - data node of config data
+ * @param stateDataNode
+ * - data node of state data
+ * @return {@link NormalizedNode}
+ */
+ private static NormalizedNode<?, ?> prepareData(final NormalizedNode<?, ?> configDataNode,
+ final NormalizedNode<?, ?> stateDataNode) {
+ 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();
+ }
+
+ /**
+ * 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);
+ }
+
+ }
+ }
+
+ /**
+ * Mapping child
+ *
+ * @param type
+ * - type of data
+ * @param child
+ * - child to map
+ * @param mapEntryBuilder
+ * - builder for mapping child
+ */
+ 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);
+ }
+ }
+
+ /**
+ * 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(final NormalizedNode<?, ?> stateDataNode,
+ 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 ");
+ }
+ }
+
+ /**
+ * Get data from future object if these data are present.
+ *
+ * @param listenableFuture
+ * - future of optional {@link NormalizedNode}
+ * @param transactionNode
+ * - {@link TransactionVarsWrapper} - wrapper for variables
+ * @return {@link NormalizedNode}
+ */
+ private static NormalizedNode<?, ?> getNodeFromFuture(
+ final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture,
+ final TransactionVarsWrapper transactionNode) {
+ Optional<NormalizedNode<?, ?>> optional;
+ try {
+ LOG.debug("Reading result data from transaction.");
+ optional = listenableFuture.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception by reading {} via Restconf: {}", transactionNode.getLogicalDatastoreType().name(),
+ transactionNode.getInstanceIdentifier().getInstanceIdentifier(), e);
+ throw new RestconfDocumentedException("Problem to get data from transaction.", e.getCause());
+
+ }
+ if (optional != null) {
+ if (optional.isPresent()) {
+ return optional.get();
+ }
+ }
+ throw new RestconfDocumentedException("Normalized node is not available : "
+ + transactionNode.getInstanceIdentifier().getInstanceIdentifier());
+ }
+}