X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-nb-rfc8040%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Frestconf%2Fnb%2Frfc8040%2Frests%2Futils%2FPutDataTransactionUtil.java;h=6e688b3f6efdacde8a0ac0a79d4378ad14e3fc3e;hb=9cc114dc8e4109893e2346477b5ae14391afe01c;hp=200605da4b626b77fd72c811bd14ad019aeb4064;hpb=edf3b06cb4e53a91f3756663dfbea9a1eb9154d1;p=netconf.git diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PutDataTransactionUtil.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PutDataTransactionUtil.java index 200605da4b..6e688b3f6e 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PutDataTransactionUtil.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/PutDataTransactionUtil.java @@ -7,312 +7,148 @@ */ package org.opendaylight.restconf.nb.rfc8040.rests.utils; -import com.google.common.base.Optional; -import com.google.common.collect.Maps; -import com.google.common.util.concurrent.CheckedFuture; -import java.util.List; -import java.util.Map; +import com.google.common.util.concurrent.FluentFuture; +import java.util.Optional; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; -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.common.api.data.TransactionCommitFailedException; -import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; -import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.mdsal.common.api.CommitInfo; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.dom.api.DOMTransactionChain; import org.opendaylight.restconf.common.context.InstanceIdentifierContext; -import org.opendaylight.restconf.common.context.NormalizedNodeContext; import org.opendaylight.restconf.common.errors.RestconfDocumentedException; -import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag; -import org.opendaylight.restconf.common.errors.RestconfError.ErrorType; -import org.opendaylight.restconf.common.validation.RestconfValidationUtils; -import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler; -import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef; -import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper; +import org.opendaylight.restconf.nb.rfc8040.InsertParam; +import org.opendaylight.restconf.nb.rfc8040.PointParam; +import org.opendaylight.restconf.nb.rfc8040.WriteDataParams; +import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload; +import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy; +import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfTransaction; import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier; -import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.common.ErrorType; 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.LeafSetEntryNode; -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.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; 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 { + private static final String PUT_TX_TYPE = "PUT"; private 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 keyDefinitions = ((ListSchemaNode) schemaNode).getKeyDefinition(); - if (lastPathArgument instanceof NodeIdentifierWithPredicates && data instanceof MapEntryNode) { - final Map uriKeyValues = ((NodeIdentifierWithPredicates) lastPathArgument) - .getKeyValues(); - isEqualUriAndPayloadKeyValues(uriKeyValues, (MapEntryNode) data, keyDefinitions); - } - } - } - - private static void isEqualUriAndPayloadKeyValues(final Map uriKeyValues, final MapEntryNode payload, - final List keyDefinitions) { - final Map 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. + * Check mount point and prepare variables for put data to DS. Close {@link DOMTransactionChain} if any + * inside of object {@link RestconfStrategy} provided as a parameter if any. * - * @param payload - * data to put - * @param schemaCtxRef - * reference to {@link SchemaContext} - * @param transactionNode - * wrapper of variables for transaction - * @param point - * query parameter - * @param insert - * query parameter - * @return {@link CheckedFuture} + * @param payload data to put + * @param schemaContext reference to {@link EffectiveModelContext} + * @param strategy object that perform the actual DS operations + * @param params {@link WriteDataParams} + * @return {@link Response} */ - public static Response putData(final NormalizedNodeContext payload, final SchemaContextRef schemaCtxRef, - final TransactionVarsWrapper transactionNode, final String insert, final String point) { + public static Response putData(final NormalizedNodePayload payload, final EffectiveModelContext schemaContext, + final RestconfStrategy strategy, final WriteDataParams params) { final YangInstanceIdentifier path = payload.getInstanceIdentifierContext().getInstanceIdentifier(); - final SchemaContext schemaContext = schemaCtxRef.get(); - final DOMDataReadWriteTransaction readWriteTransaction = - transactionNode.getTransactionChain().newReadWriteTransaction(); - - final CheckedFuture existsFuture = - readWriteTransaction.exists(LogicalDatastoreType.CONFIGURATION, path); + final FluentFuture existsFuture = strategy.exists(LogicalDatastoreType.CONFIGURATION, path); final FutureDataFactory existsResponse = new FutureDataFactory<>(); - FutureCallbackTx.addCallback(existsFuture, RestconfDataServiceConstant.PutData.PUT_TX_TYPE, existsResponse); + FutureCallbackTx.addCallback(existsFuture, PUT_TX_TYPE, existsResponse); final ResponseFactory responseFactory = - new ResponseFactory(existsResponse.result ? Status.NO_CONTENT : Status.CREATED); - final CheckedFuture submitData = submitData(path, schemaContext, - transactionNode.getTransactionChainHandler(), readWriteTransaction, payload.getData(), insert, point); - FutureCallbackTx.addCallback(submitData, RestconfDataServiceConstant.PutData.PUT_TX_TYPE, responseFactory); + new ResponseFactory(existsResponse.result ? Status.NO_CONTENT : Status.CREATED); + final FluentFuture submitData = submitData(path, schemaContext, strategy, + payload.getData(), params); + //This method will close transactionChain if any + FutureCallbackTx.addCallback(submitData, PUT_TX_TYPE, responseFactory, path); return responseFactory.build(); } /** * Put data to DS. * - * @param path - * path of data - * @param schemaContext - * {@link SchemaContext} - * @param transactionChainHandler - * write transaction - * @param data - * data - * @param point - * query parameter - * @param insert - * query parameter - * @return {@link CheckedFuture} + * @param path path of data + * @param schemaContext {@link SchemaContext} + * @param strategy object that perform the actual DS operations + * @param data data + * @param params {@link WriteDataParams} + * @return {@link FluentFuture} */ - private static CheckedFuture submitData(final YangInstanceIdentifier path, - final SchemaContext schemaContext, final TransactionChainHandler transactionChainHandler, - final DOMDataReadWriteTransaction readWriteTransaction, - final NormalizedNode data, final String insert, final String point) { + private static FluentFuture submitData(final YangInstanceIdentifier path, + final EffectiveModelContext schemaContext, + final RestconfStrategy strategy, + final NormalizedNode data, + final WriteDataParams params) { + final RestconfTransaction transaction = strategy.prepareWriteExecution(); + final InsertParam insert = params.insert(); if (insert == null) { - return makePut(path, schemaContext, readWriteTransaction, data); - } else { - final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path); - switch (insert) { - case "first": - if (schemaNode instanceof ListSchemaNode) { - final NormalizedNode readData = - readList(path, schemaContext, transactionChainHandler, schemaNode); - final OrderedMapNode readList = (OrderedMapNode) readData; - if (readList == null || readList.getValue().isEmpty()) { - return makePut(path, schemaContext, readWriteTransaction, data); - } else { - readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, path.getParent()); - simplePut(LogicalDatastoreType.CONFIGURATION, path, readWriteTransaction, - schemaContext, data); - listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), readWriteTransaction, - schemaContext, readList); - return readWriteTransaction.submit(); - } - } else { - final NormalizedNode readData = - readList(path, schemaContext, transactionChainHandler, schemaNode); - - final OrderedLeafSetNode readLeafList = (OrderedLeafSetNode) readData; - if (readLeafList == null || readLeafList.getValue().isEmpty()) { - return makePut(path, schemaContext, readWriteTransaction, data); - } else { - readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION, path.getParent()); - simplePut(LogicalDatastoreType.CONFIGURATION, path, readWriteTransaction, - schemaContext, data); - listPut(LogicalDatastoreType.CONFIGURATION, path.getParent(), readWriteTransaction, - schemaContext, readLeafList); - return readWriteTransaction.submit(); - } - } - case "last": - return makePut(path, schemaContext, readWriteTransaction, data); - case "before": - if (schemaNode instanceof ListSchemaNode) { - final NormalizedNode readData = - readList(path, schemaContext, transactionChainHandler, schemaNode); - final OrderedMapNode readList = (OrderedMapNode) readData; - if (readList == null || readList.getValue().isEmpty()) { - return makePut(path, schemaContext, readWriteTransaction, data); - } else { - insertWithPointListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION, path, - data, schemaContext, point, readList, true); - return readWriteTransaction.submit(); - } - } else { - final NormalizedNode readData = - readList(path, schemaContext, transactionChainHandler, schemaNode); - - final OrderedLeafSetNode readLeafList = (OrderedLeafSetNode) readData; - if (readLeafList == null || readLeafList.getValue().isEmpty()) { - return makePut(path, schemaContext, readWriteTransaction, data); - } else { - insertWithPointLeafListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION, - path, data, schemaContext, point, readLeafList, true); - return readWriteTransaction.submit(); - } - } - case "after": - if (schemaNode instanceof ListSchemaNode) { - final NormalizedNode readData = - readList(path, schemaContext, transactionChainHandler, schemaNode); - final OrderedMapNode readList = (OrderedMapNode) readData; - if (readList == null || readList.getValue().isEmpty()) { - return makePut(path, schemaContext, readWriteTransaction, data); - } else { - insertWithPointListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION, - path, data, schemaContext, point, readList, false); - return readWriteTransaction.submit(); - } - } else { - final NormalizedNode readData = - readList(path, schemaContext, transactionChainHandler, schemaNode); + return makePut(path, schemaContext, transaction, data); + } - final OrderedLeafSetNode readLeafList = (OrderedLeafSetNode) readData; - if (readLeafList == null || readLeafList.getValue().isEmpty()) { - return makePut(path, schemaContext, readWriteTransaction, data); - } else { - insertWithPointLeafListPut(readWriteTransaction, LogicalDatastoreType.CONFIGURATION, - path, data, schemaContext, point, readLeafList, true); - return readWriteTransaction.submit(); - } - } - default: - throw new RestconfDocumentedException( - "Used bad value of insert parameter. Possible values are first, last, before or after, " - + "but was: " + insert); - } + checkListAndOrderedType(schemaContext, path); + final NormalizedNode readData; + switch (insert) { + case FIRST: + readData = readList(strategy, path.getParent()); + if (readData == null || ((NormalizedNodeContainer) readData).isEmpty()) { + return makePut(path, schemaContext, transaction, data); + } + transaction.remove(path.getParent()); + transaction.replace(path, data, schemaContext); + transaction.replace(path.getParent(), readData, schemaContext); + return transaction.commit(); + case LAST: + return makePut(path, schemaContext, transaction, data); + case BEFORE: + readData = readList(strategy, path.getParent()); + if (readData == null || ((NormalizedNodeContainer) readData).isEmpty()) { + return makePut(path, schemaContext, transaction, data); + } + insertWithPointPut(transaction, path, data, schemaContext, params.getPoint(), + (NormalizedNodeContainer) readData, true); + return transaction.commit(); + case AFTER: + readData = readList(strategy, path.getParent()); + if (readData == null || ((NormalizedNodeContainer) readData).isEmpty()) { + return makePut(path, schemaContext, transaction, data); + } + insertWithPointPut(transaction, path, data, schemaContext, params.getPoint(), + (NormalizedNodeContainer) readData, false); + return transaction.commit(); + default: + throw new RestconfDocumentedException( + "Used bad value of insert parameter. Possible values are first, last, before or after, " + + "but was: " + insert, ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE); } } - public static NormalizedNode readList(final YangInstanceIdentifier path, final SchemaContext schemaContext, - final TransactionChainHandler transactionChainHandler, final DataSchemaNode schemaNode) { - final InstanceIdentifierContext iid = new InstanceIdentifierContext( - path.getParent(), schemaNode, null, schemaContext); - final TransactionVarsWrapper transactionNode = new TransactionVarsWrapper(iid, null, transactionChainHandler); - final NormalizedNode readData = ReadDataTransactionUtil - .readData(RestconfDataServiceConstant.ReadData.CONFIG, transactionNode, schemaContext); - return readData; + // FIXME: this method is only called from a context where we are modifying data. This should be part of strategy, + // requiring an already-open transaction. It also must return a future, so it can be properly composed. + static NormalizedNode readList(final RestconfStrategy strategy, final YangInstanceIdentifier path) { + return ReadDataTransactionUtil.readDataViaTransaction(strategy, LogicalDatastoreType.CONFIGURATION, path); } - private static void insertWithPointLeafListPut(final DOMDataReadWriteTransaction rwTransaction, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, - final NormalizedNode data, final SchemaContext schemaContext, final String point, - final OrderedLeafSetNode readLeafList, final boolean before) { - rwTransaction.delete(datastore, path.getParent()); - final InstanceIdentifierContext instanceIdentifier = - ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.absent()); + private static void insertWithPointPut(final RestconfTransaction transaction, + final YangInstanceIdentifier path, + final NormalizedNode data, + final EffectiveModelContext schemaContext, final PointParam point, + final NormalizedNodeContainer readList, final boolean before) { + transaction.remove(path.getParent()); + final InstanceIdentifierContext instanceIdentifier = + // FIXME: Point should be able to give us this method + ParserIdentifier.toInstanceIdentifier(point.value(), schemaContext, Optional.empty()); int lastItemPosition = 0; - for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { + for (final NormalizedNode nodeChild : readList.body()) { if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } @@ -322,104 +158,48 @@ public final class PutDataTransactionUtil { lastItemPosition++; } int lastInsertedPosition = 0; - final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); - rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); + transaction.merge(YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + for (final NormalizedNode nodeChild : readList.body()) { if (lastInsertedPosition == lastItemPosition) { - simplePut(datastore, path, rwTransaction, schemaContext, data); + transaction.replace(path, data, schemaContext); } final YangInstanceIdentifier childPath = path.getParent().node(nodeChild.getIdentifier()); - rwTransaction.put(datastore, childPath, nodeChild); + transaction.replace(childPath, nodeChild, schemaContext); lastInsertedPosition++; } } - private static void insertWithPointListPut(final DOMDataReadWriteTransaction writeTx, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, - final NormalizedNode data, final SchemaContext schemaContext, final String point, - final OrderedMapNode readList, final boolean before) { - writeTx.delete(datastore, path.getParent()); - final InstanceIdentifierContext instanceIdentifier = - ParserIdentifier.toInstanceIdentifier(point, schemaContext, Optional.absent()); - int lastItemPosition = 0; - for (final MapEntryNode mapEntryNode : readList.getValue()) { - if (mapEntryNode.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { - break; - } - lastItemPosition++; - } - if (!before) { - lastItemPosition++; - } - int lastInsertedPosition = 0; - final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); - writeTx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - for (final MapEntryNode mapEntryNode : readList.getValue()) { - if (lastInsertedPosition == lastItemPosition) { - simplePut(datastore, path, writeTx, schemaContext, data); - } - final YangInstanceIdentifier childPath = path.getParent().node(mapEntryNode.getIdentifier()); - writeTx.put(datastore, childPath, mapEntryNode); - lastInsertedPosition++; - } - } - - private static void listPut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path, - final DOMDataReadWriteTransaction writeTx, final SchemaContext schemaContext, - final OrderedLeafSetNode payload) { - final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); - writeTx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx); - for (final LeafSetEntryNode child : ((LeafSetNode) payload).getValue()) { - final YangInstanceIdentifier childPath = path.node(child.getIdentifier()); - writeTx.put(datastore, childPath, child); - } - } - - private static void listPut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path, - final DOMDataReadWriteTransaction writeTx, final SchemaContext schemaContext, - final OrderedMapNode payload) { - final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); - writeTx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx); - for (final MapEntryNode child : payload.getValue()) { - final YangInstanceIdentifier childPath = path.node(child.getIdentifier()); - writeTx.put(datastore, childPath, child); - } - } - - private static void simplePut(final LogicalDatastoreType configuration, final YangInstanceIdentifier path, - final DOMDataReadWriteTransaction writeTx, final SchemaContext schemaContext, - final NormalizedNode data) { - TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx); - writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data); - } - - private static CheckedFuture makePut(final YangInstanceIdentifier path, - final SchemaContext schemaContext, final DOMDataWriteTransaction writeTx, final NormalizedNode data) { - TransactionUtil.ensureParentsByMerge(path, schemaContext, writeTx); - writeTx.put(LogicalDatastoreType.CONFIGURATION, path, data); - return writeTx.submit(); + private static FluentFuture makePut(final YangInstanceIdentifier path, + final SchemaContext schemaContext, + final RestconfTransaction transaction, + final NormalizedNode data) { + transaction.replace(path, data, schemaContext); + return transaction.commit(); } - public static DataSchemaNode checkListAndOrderedType(final SchemaContext ctx, final YangInstanceIdentifier path) { + public static DataSchemaNode checkListAndOrderedType(final EffectiveModelContext ctx, + final YangInstanceIdentifier path) { final YangInstanceIdentifier parent = path.getParent(); - final DataSchemaContextNode node = DataSchemaContextTree.from(ctx).getChild(parent); + final DataSchemaContextNode node = DataSchemaContextTree.from(ctx).findChild(parent).orElseThrow(); final DataSchemaNode dataSchemaNode = node.getDataSchemaNode(); if (dataSchemaNode instanceof ListSchemaNode) { if (!((ListSchemaNode) dataSchemaNode).isUserOrdered()) { - throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user list."); + throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user list.", + ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT); } return dataSchemaNode; } if (dataSchemaNode instanceof LeafListSchemaNode) { if (!((LeafListSchemaNode) dataSchemaNode).isUserOrdered()) { throw new RestconfDocumentedException( - "Insert parameter can be used only with ordered-by user leaf-list."); + "Insert parameter can be used only with ordered-by user leaf-list.", + ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT); } return dataSchemaNode; } - throw new RestconfDocumentedException("Insert parameter can be used only with list or leaf-list"); + throw new RestconfDocumentedException("Insert parameter can be used only with list or leaf-list", + ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT); } }