From 93c88753cecac66a36543f0db541aa6c83754bf3 Mon Sep 17 00:00:00 2001 From: Jakub Toth Date: Thu, 26 May 2016 10:32:29 +0200 Subject: [PATCH] Bug 5528 - Read data impl *impl RestconfDataService *util class for constants *wrapper for transaction vars Change-Id: I61f4662b61ac9cf15535492f31bc896a863ce986 Signed-off-by: Jakub Toth --- .../impl/RestconfDataServiceImpl.java | 83 ++++ .../transaction/TransactionVarsWrapper.java | 120 ++++++ .../restful/utils/FutureCallbackTx.java | 95 +++++ .../restful/utils/FutureDataFactory.java | 24 ++ .../utils/ReadDataTransactionUtil.java | 357 ++++++++++++++++++ .../utils/RestconfDataServiceConstant.java | 38 ++ 6 files changed, 717 insertions(+) create mode 100644 restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java create mode 100644 restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java create mode 100644 restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureCallbackTx.java create mode 100644 restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureDataFactory.java create mode 100644 restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java create mode 100644 restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RestconfDataServiceConstant.java diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java new file mode 100644 index 0000000000..cc34101c27 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/services/impl/RestconfDataServiceImpl.java @@ -0,0 +1,83 @@ +/* + * 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."); + } +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java new file mode 100644 index 0000000000..3b65762e64 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/transaction/TransactionVarsWrapper.java @@ -0,0 +1,120 @@ +/* + * 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; + } +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureCallbackTx.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureCallbackTx.java new file mode 100644 index 0000000000..a2b95fbe0b --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureCallbackTx.java @@ -0,0 +1,95 @@ +/* + * 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>, ReadFailedException> listenableFuture, + final AsyncTransaction> transaction, final String txType, + final FutureDataFactory dataFactory) { + Futures.addCallback(listenableFuture, new FutureCallback>>() { + + @Override + public void onFailure(final Throwable t) { + handlingLoggerAndValues(t, txType, transaction, null, null); + } + + @Override + public void onSuccess(final Optional> result) { + handlingLoggerAndValues(null, txType, transaction, result, dataFactory); + } + + }); + } + + /** + * Handling logger and result of callback - on success or on failure + *
    + *
  • on success - set result to the factory + *
  • on failure - throw exception + *
+ * + * @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> transaction, + final Optional> 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()); + } + } + } +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureDataFactory.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureDataFactory.java new file mode 100644 index 0000000000..42f75653fb --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/FutureDataFactory.java @@ -0,0 +1,24 @@ +/* + * 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 org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +class FutureDataFactory { + + private NormalizedNode normalizedNode = null; + + public void setData(final NormalizedNode normalizedNode) { + this.normalizedNode = normalizedNode; + } + + public NormalizedNode getData() { + return this.normalizedNode; + } + +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java new file mode 100644 index 0000000000..a6c4ef6dfc --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/ReadDataTransactionUtil.java @@ -0,0 +1,357 @@ +/* + * 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. + *
    + *
  • config + *
  • state + *
  • all (config + state) + *
+ * + */ +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>, 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 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 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 mapEntryBuilder) { + for (final DataContainerChild 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 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 mapEntryBuilder) { + for (final DataContainerChild 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 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 > void addChildToMap(final Class type, + final DataContainerChild child, + final DataContainerNodeBuilder mapEntryBuilder) { + @SuppressWarnings("unchecked") + final T node = (T) child; + for (final DataContainerChild 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>, ReadFailedException> listenableFuture, + final TransactionVarsWrapper transactionNode) { + Optional> 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()); + } +} diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RestconfDataServiceConstant.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RestconfDataServiceConstant.java new file mode 100644 index 0000000000..01cec9e3c3 --- /dev/null +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/RestconfDataServiceConstant.java @@ -0,0 +1,38 @@ +/* + * 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; + +/** + * Constants for RestconfDataService + * + */ +public final class RestconfDataServiceConstant { + + public static final String CONTENT = "content"; + + private RestconfDataServiceConstant() { + throw new UnsupportedOperationException("Util class."); + } + + /** + * Constants for read data + * + */ + public final class ReadData { + + public static final String CONFIG = "config"; + public static final String NONCONFIG = "nonconfig"; + public static final String ALL = "all"; + public static final String READ_TYPE_TX = "READ"; + + private ReadData() { + throw new UnsupportedOperationException("Util class."); + } + } + +} -- 2.36.6