*/
package org.opendaylight.restconf.restful.services.impl;
+import com.google.common.base.Optional;
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.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
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.netconf.sal.restconf.impl.RestconfDocumentedException;
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.PutDataTransactionUtil;
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;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Implementation of {@link RestconfDataService}
*/
public class RestconfDataServiceImpl implements RestconfDataService {
+ private final static Logger LOG = LoggerFactory.getLogger(RestconfDataServiceImpl.class);
+
private SchemaContextHandler schemaContextHandler;
- private DOMMountPointServiceHandler domMountPointServiceHandler;
private TransactionChainHandler transactionChainHandler;
@Override
final DOMMountPoint mountPoint = instanceIdentifier.getMountPoint();
final String value = uriInfo.getQueryParameters().getFirst(RestconfDataServiceConstant.CONTENT);
+ DOMDataReadWriteTransaction transaction = null;
+ if (mountPoint == null) {
+ transaction = this.transactionChainHandler.get().newReadWriteTransaction();
+ } else {
+ transaction = transactionOfMountPoint(mountPoint);
+ }
final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(instanceIdentifier, mountPoint,
- this.transactionChainHandler.get(), this.domMountPointServiceHandler.get(), schemaContextRef.get());
+ transaction);
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.");
+ Preconditions.checkNotNull(identifier);
+ Preconditions.checkNotNull(payload);
+
+ final InstanceIdentifierContext<? extends SchemaNode> iid = payload
+ .getInstanceIdentifierContext();
+
+ PutDataTransactionUtil.validInputData(iid.getSchemaNode(), payload);
+ PutDataTransactionUtil.validTopLevelNodeName(iid.getInstanceIdentifier(), payload);
+ PutDataTransactionUtil.validateListKeysEqualityInPayloadAndUri(payload);
+
+ final DOMMountPoint mountPoint = payload.getInstanceIdentifierContext().getMountPoint();
+ DOMDataReadWriteTransaction transaction = null;
+ SchemaContextRef ref = null;
+ if (mountPoint == null) {
+ transaction = this.transactionChainHandler.get().newReadWriteTransaction();
+ ref = new SchemaContextRef(this.schemaContextHandler.get());
+ } else {
+ transaction = transactionOfMountPoint(mountPoint);
+ ref = new SchemaContextRef(mountPoint.getSchemaContext());
+ }
+
+ final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(
+ payload.getInstanceIdentifierContext(), mountPoint, transaction);
+ return PutDataTransactionUtil.putData(payload, ref, transactionNode);
}
@Override
public PATCHStatusContext patchData(final PATCHContext context, final UriInfo uriInfo) {
throw new UnsupportedOperationException("Not yet implemented.");
}
+
+ /**
+ * Prepare transaction to read data of mount point, if these data are
+ * present.
+ * @param mountPoint
+ *
+ * @param transactionNode
+ * - {@link TransactionVarsWrapper} - wrapper for variables
+ * @return {@link NormalizedNode}
+ */
+ private static DOMDataReadWriteTransaction transactionOfMountPoint(final DOMMountPoint mountPoint) {
+ final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
+ if (domDataBrokerService.isPresent()) {
+ return domDataBrokerService.get().newReadWriteTransaction();
+ } else {
+ final String errMsg = "DOM data broker service isn't available for mount point "
+ + mountPoint.getIdentifier();
+ LOG.warn(errMsg);
+ throw new RestconfDocumentedException(errMsg);
+ }
+ }
}
package org.opendaylight.restconf.restful.transaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.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.
private final InstanceIdentifierContext<?> instanceIdentifier;
private final DOMMountPoint mountPoint;
private LogicalDatastoreType configuration = null;
- private final DOMMountPointService domMountPointService;
- private final SchemaContext schemaContext;
- private final DOMTransactionChain domTransactionChain;
+ private final DOMDataReadWriteTransaction transaction;
/**
* 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).
+ * 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}
+ * - mount point if is present
+ * @param transaction
+ * - {@link DOMDataReadWriteTransaction} transaction for
+ * operations
*/
public TransactionVarsWrapper(final InstanceIdentifierContext<?> instanceIdentifier, final DOMMountPoint mountPoint,
- final DOMTransactionChain domTransactionChain, final DOMMountPointService domMountPointService,
- final SchemaContext schemaContext) {
+ final DOMDataReadWriteTransaction transaction) {
this.instanceIdentifier = instanceIdentifier;
this.mountPoint = mountPoint;
- this.domTransactionChain = domTransactionChain;
- this.domMountPointService = domMountPointService;
- this.schemaContext = schemaContext;
+ this.transaction = transaction;
}
/**
}
/**
- * Get mount point service
+ * Get specific type of transaction
*
- * @return {@link DOMMountPointService}
+ * @return specific type transaction
*/
- 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;
+ public DOMDataReadWriteTransaction getTransaction() {
+ return this.transaction;
}
}
*/
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;
* @param dataFactory
* - factory setting result
*/
- static void addCallback(final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture,
+ static <T, X extends Exception> void addCallback(final CheckedFuture<T, X> listenableFuture,
final AsyncTransaction<YangInstanceIdentifier, NormalizedNode<?, ?>> transaction, final String txType,
- final FutureDataFactory dataFactory) {
- Futures.addCallback(listenableFuture, new FutureCallback<Optional<NormalizedNode<?, ?>>>() {
+ final FutureDataFactory<T> dataFactory) {
+ Futures.addCallback(listenableFuture, new FutureCallback<T>() {
@Override
public void onFailure(final Throwable t) {
}
@Override
- public void onSuccess(final Optional<NormalizedNode<?, ?>> result) {
+ public void onSuccess(final T result) {
handlingLoggerAndValues(null, txType, transaction, result, dataFactory);
}
* @param dataFactory
* - setter for result - in callback is onSuccess
*/
- protected static void handlingLoggerAndValues(@Nullable final Throwable t, final String txType,
+ protected static <T> void handlingLoggerAndValues(@Nullable final Throwable t, final String txType,
final AsyncTransaction<YangInstanceIdentifier, NormalizedNode<?, ?>> transaction,
- final Optional<NormalizedNode<?, ?>> optionalNN, final FutureDataFactory dataFactory) {
+ final T result, final FutureDataFactory<T> 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());
- }
+ dataFactory.setResult(result);
}
}
}
*/
package org.opendaylight.restconf.restful.utils;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+class FutureDataFactory<T> {
-class FutureDataFactory {
+ protected T result;
- private NormalizedNode<?, ?> normalizedNode = null;
-
- public void setData(final NormalizedNode<?, ?> normalizedNode) {
- this.normalizedNode = normalizedNode;
- }
-
- public NormalizedNode<?, ?> getData() {
- return this.normalizedNode;
+ void setResult(final T result) {
+ this.result = result;
}
}
--- /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 org.apache.commons.lang3.builder.Builder;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+class NormalizedNodeFactory extends FutureDataFactory<Optional<NormalizedNode<?, ?>>>
+ implements Builder<NormalizedNode<?, ?>> {
+
+ @Override
+ public NormalizedNode<?, ?> build() {
+ if (this.result.isPresent()) {
+ return this.result.get();
+ }
+ return null;
+ }
+
+}
--- /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.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.Response;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.netconf.md.sal.rest.common.RestconfValidationUtils;
+import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext;
+import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext;
+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.common.references.SchemaContextRef;
+import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+
+/**
+ * Util class for put data to DS
+ *
+ */
+public final class PutDataTransactionUtil {
+
+ /**
+ * Valid input data with {@link SchemaNode}
+ *
+ * @param schemaNode
+ * - {@link SchemaNode}
+ * @param payload
+ * - input data
+ */
+ public static void validInputData(final SchemaNode schemaNode, final NormalizedNodeContext payload) {
+ if ((schemaNode != null) && (payload.getData() == null)) {
+ throw new RestconfDocumentedException("Input is required.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
+ } else if ((schemaNode == null) && (payload.getData() != null)) {
+ throw new RestconfDocumentedException("No input expected.", ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
+ }
+ }
+
+ /**
+ * Valid top level node name
+ *
+ * @param path
+ * - path of node
+ * @param payload
+ * - data
+ */
+ public static void validTopLevelNodeName(final YangInstanceIdentifier path, final NormalizedNodeContext payload) {
+ final String payloadName = payload.getData().getNodeType().getLocalName();
+
+ if (path.isEmpty()) {
+ if (!payload.getData().getNodeType().equals(RestconfDataServiceConstant.NETCONF_BASE_QNAME)) {
+ throw new RestconfDocumentedException("Instance identifier has to contain at least one path argument",
+ ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
+ }
+ } else {
+ final String identifierName = path.getLastPathArgument().getNodeType().getLocalName();
+ if (!payloadName.equals(identifierName)) {
+ throw new RestconfDocumentedException(
+ "Payload name (" + payloadName + ") is different from identifier name (" + identifierName + ")",
+ ErrorType.PROTOCOL, ErrorTag.MALFORMED_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Validates whether keys in {@code payload} are equal to values of keys in
+ * {@code iiWithData} for list schema node
+ *
+ * @throws RestconfDocumentedException
+ * if key values or key count in payload and URI isn't equal
+ *
+ */
+ public static void validateListKeysEqualityInPayloadAndUri(final NormalizedNodeContext payload) {
+ final InstanceIdentifierContext<?> iiWithData = payload.getInstanceIdentifierContext();
+ final PathArgument lastPathArgument = iiWithData.getInstanceIdentifier().getLastPathArgument();
+ final SchemaNode schemaNode = iiWithData.getSchemaNode();
+ final NormalizedNode<?, ?> data = payload.getData();
+ if (schemaNode instanceof ListSchemaNode) {
+ final List<QName> keyDefinitions = ((ListSchemaNode) schemaNode).getKeyDefinition();
+ if ((lastPathArgument instanceof NodeIdentifierWithPredicates) && (data instanceof MapEntryNode)) {
+ final Map<QName, Object> uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument)
+ .getKeyValues();
+ isEqualUriAndPayloadKeyValues(uriKeyValues, (MapEntryNode) data, keyDefinitions);
+ }
+ }
+ }
+
+ private static void isEqualUriAndPayloadKeyValues(final Map<QName, Object> uriKeyValues, final MapEntryNode payload,
+ final List<QName> keyDefinitions) {
+ final Map<QName, Object> mutableCopyUriKeyValues = Maps.newHashMap(uriKeyValues);
+ for (final QName keyDefinition : keyDefinitions) {
+ final Object uriKeyValue = mutableCopyUriKeyValues.remove(keyDefinition);
+ RestconfValidationUtils.checkDocumentedError(uriKeyValue != null, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING,
+ "Missing key " + keyDefinition + " in URI.");
+
+ final Object dataKeyValue = payload.getIdentifier().getKeyValues().get(keyDefinition);
+
+ if (!uriKeyValue.equals(dataKeyValue)) {
+ final String errMsg = "The value '" + uriKeyValue + "' for key '" + keyDefinition.getLocalName()
+ + "' specified in the URI doesn't match the value '" + dataKeyValue
+ + "' specified in the message body. ";
+ throw new RestconfDocumentedException(errMsg, ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE);
+ }
+ }
+ }
+
+ /**
+ * Check mount point and prepare variables for put data to DS
+ *
+ * @param payload
+ * - data to put
+ * @param schemaCtxRef
+ * - reference to {@link SchemaContext}
+ * @param transactionNode
+ * @return {@link CheckedFuture}
+ */
+ public static Response putData(final NormalizedNodeContext payload,
+ final SchemaContextRef schemaCtxRef, final TransactionVarsWrapper transactionNode) {
+ final YangInstanceIdentifier path = payload.getInstanceIdentifierContext().getInstanceIdentifier();
+ final ResponseFactory responseFactory = new ResponseFactory(
+ ReadDataTransactionUtil.readData(RestconfDataServiceConstant.ReadData.CONFIG, transactionNode));
+ final CheckedFuture<Void, TransactionCommitFailedException> submitData = submitData(path, schemaCtxRef.get(),
+ transactionNode.getTransaction(), payload.getData());
+ FutureCallbackTx.addCallback(submitData, transactionNode.getTransaction(),
+ RestconfDataServiceConstant.PutData.PUT_TX_TYPE, responseFactory);
+ return responseFactory.build();
+ }
+
+ /**
+ * Put data to DS
+ *
+ * @param path
+ * - path of data
+ * @param schemaContext
+ * - {@link SchemaContext}
+ * @param writeTx
+ * - write transaction
+ * @param data
+ * - data
+ * @return {@link CheckedFuture}
+ */
+ private static CheckedFuture<Void, TransactionCommitFailedException> submitData(final YangInstanceIdentifier path,
+ final SchemaContext schemaContext,
+ final DOMDataWriteTransaction writeTx, final NormalizedNode<?, ?> data) {
+ ensureParentsByMerge(path, schemaContext, writeTx);
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data);
+ return writeTx.submit();
+ }
+
+ /**
+ * Merged parents of data
+ *
+ * @param path
+ * - path of data
+ * @param schemaContext
+ * - {@link SchemaContext}
+ * @param writeTx
+ * - write transaction
+ */
+ private static void ensureParentsByMerge(final YangInstanceIdentifier path, final SchemaContext schemaContext,
+ final DOMDataWriteTransaction writeTx) {
+ final List<PathArgument> normalizedPathWithoutChildArgs = new ArrayList<>();
+ boolean hasList = false;
+ YangInstanceIdentifier rootNormalizedPath = null;
+
+ final Iterator<PathArgument> it = path.getPathArguments().iterator();
+ final Module module = schemaContext.findModuleByNamespaceAndRevision(
+ path.getLastPathArgument().getNodeType().getModule().getNamespace(),
+ path.getLastPathArgument().getNodeType().getModule().getRevision());
+
+ while (it.hasNext()) {
+ final PathArgument pathArgument = it.next();
+ if (rootNormalizedPath == null) {
+ rootNormalizedPath = YangInstanceIdentifier.create(pathArgument);
+ }
+ if (it.hasNext()) {
+ normalizedPathWithoutChildArgs.add(pathArgument);
+ if (module.getDataChildByName(pathArgument.getNodeType()) instanceof ListSchemaNode) {
+ hasList = true;
+ }
+ }
+ }
+ if (normalizedPathWithoutChildArgs.isEmpty()) {
+ return;
+ }
+ if (hasList) {
+ Preconditions.checkArgument(rootNormalizedPath != null, "Empty path received");
+ final NormalizedNode<?, ?> parentStructure = ImmutableNodes.fromInstanceId(schemaContext,
+ YangInstanceIdentifier.create(normalizedPathWithoutChildArgs));
+ writeTx.merge(LogicalDatastoreType.CONFIGURATION, rootNormalizedPath, parentStructure);
+ }
+ }
+}
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.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.
*/
public final class ReadDataTransactionUtil {
- private final static Logger LOG = LoggerFactory.getLogger(ReadDataTransactionUtil.class);
-
private ReadDataTransactionUtil() {
throw new UnsupportedOperationException("Util class.");
}
switch (valueOfContent) {
case RestconfDataServiceConstant.ReadData.CONFIG:
transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
- return readData(transactionNode);
+ return readDataViaTransaction(transactionNode);
case RestconfDataServiceConstant.ReadData.NONCONFIG:
transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
- return readData(transactionNode);
+ return readDataViaTransaction(transactionNode);
case RestconfDataServiceConstant.ReadData.ALL:
- return readData(transactionNode);
+ return readDataViaTransaction(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);
+ return readDataViaTransaction(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)
+ * {@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) {
+ private static NormalizedNode<?, ?> readDataViaTransaction(final TransactionVarsWrapper transactionNode) {
if (transactionNode.getLogicalDatastoreType() != null) {
- final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture = readTransaction
- .read(transactionNode.getLogicalDatastoreType(),
+ final CheckedFuture<Optional<NormalizedNode<?, ?>>, ReadFailedException> listenableFuture = transactionNode
+ .getTransaction().read(transactionNode.getLogicalDatastoreType(),
transactionNode.getInstanceIdentifier().getInstanceIdentifier());
- final FutureDataFactory dataFactory = new FutureDataFactory();
- FutureCallbackTx.addCallback(listenableFuture, readTransaction,
+ final NormalizedNodeFactory dataFactory = new NormalizedNodeFactory();
+ FutureCallbackTx.addCallback(listenableFuture, transactionNode.getTransaction(),
RestconfDataServiceConstant.ReadData.READ_TYPE_TX, dataFactory);
- return dataFactory.getData();
+ return dataFactory.build();
} 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.
*
private static NormalizedNode<?, ?> readAllData(final TransactionVarsWrapper transactionNode) {
// PREPARE STATE DATA NODE
transactionNode.setLogicalDatastoreType(LogicalDatastoreType.OPERATIONAL);
- final NormalizedNode<?, ?> stateDataNode = readData(transactionNode);
+ final NormalizedNode<?, ?> stateDataNode = readDataViaTransaction(transactionNode);
// PREPARE CONFIG DATA NODE
transactionNode.setLogicalDatastoreType(LogicalDatastoreType.CONFIGURATION);
- final NormalizedNode<?, ?> configDataNode = readData(transactionNode);
+ final NormalizedNode<?, ?> configDataNode = readDataViaTransaction(transactionNode);
- return mapNode(stateDataNode, configDataNode, transactionNode);
+ return mapNode(stateDataNode, configDataNode);
}
/**
* @return {@link NormalizedNode}
*/
private static NormalizedNode<?, ?> mapNode(final NormalizedNode<?, ?> stateDataNode,
- final NormalizedNode<?, ?> configDataNode,
- final TransactionVarsWrapper transactionNode) {
+ final NormalizedNode<?, ?> configDataNode) {
validPossibilityOfMergeNodes(stateDataNode, configDataNode);
if (configDataNode instanceof RpcDefinition) {
return prepareRpcData(configDataNode, stateDataNode);
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());
- }
}
--- /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 javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import org.apache.commons.lang3.builder.Builder;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+final class ResponseFactory extends FutureDataFactory<Void> implements Builder<Response> {
+
+ private final NormalizedNode<?, ?> readData;
+
+ ResponseFactory(final NormalizedNode<?, ?> readData) {
+ this.readData = readData;
+ }
+
+ @Override
+ public Response build() {
+ final Status status = this.readData != null ? Status.OK : Status.CREATED;
+ return Response.status(status).build();
+ }
+}
*/
package org.opendaylight.restconf.restful.utils;
+import java.net.URI;
+import java.net.URISyntaxException;
+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.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+
/**
* Constants for RestconfDataService
*
public final class RestconfDataServiceConstant {
public static final String CONTENT = "content";
+ public static final QName NETCONF_BASE_QNAME;
+ static {
+ try {
+ NETCONF_BASE_QNAME = QName.create(
+ QNameModule.create(new URI(PutData.NETCONF_BASE), null), PutData.NETCONF_BASE_PAYLOAD_NAME);
+ } catch (final URISyntaxException e) {
+ final String errMsg = "It wasn't possible to create instance of URI class with " + PutData.NETCONF_BASE
+ + " URI";
+ throw new RestconfDocumentedException(errMsg, ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED);
+ }
+ }
private RestconfDataServiceConstant() {
throw new UnsupportedOperationException("Util class.");
}
}
+ /**
+ * Constants for data to put
+ *
+ */
+ public final class PutData {
+ public static final String NETCONF_BASE = "urn:ietf:params:xml:ns:netconf:base:1.0";
+ public static final String NETCONF_BASE_PAYLOAD_NAME = "data";
+ public static final String PUT_TX_TYPE = "PUT";
+
+ private PutData() {
+ throw new UnsupportedOperationException("Util class.");
+ }
+ }
}