2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.sal.restconf.impl;
10 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
11 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Preconditions;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.util.concurrent.CheckedFuture;
17 import com.google.common.util.concurrent.FutureCallback;
18 import com.google.common.util.concurrent.Futures;
19 import java.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.concurrent.CountDownLatch;
23 import javax.annotation.Nullable;
24 import javax.ws.rs.core.Response.Status;
25 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
26 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
27 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
28 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
29 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
30 import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
31 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
32 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
33 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
34 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
35 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener;
36 import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
37 import org.opendaylight.controller.md.sal.dom.api.DOMRpcException;
38 import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult;
39 import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
40 import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession;
41 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
42 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
43 import org.opendaylight.netconf.sal.streams.listeners.ListenerAdapter;
44 import org.opendaylight.netconf.sal.streams.listeners.NotificationListenerAdapter;
45 import org.opendaylight.yangtools.concepts.ListenerRegistration;
46 import org.opendaylight.yangtools.yang.common.QName;
47 import org.opendaylight.yangtools.yang.common.RpcError;
48 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
49 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
50 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
51 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
52 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
53 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
54 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
56 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
57 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
58 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
59 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
60 import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
61 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
62 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
63 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
64 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
65 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
66 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
67 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
68 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
69 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
70 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
71 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
72 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
73 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
74 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
75 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
79 public class BrokerFacade {
80 private final static Logger LOG = LoggerFactory.getLogger(BrokerFacade.class);
82 private final static BrokerFacade INSTANCE = new BrokerFacade();
83 private volatile DOMRpcService rpcService;
84 private volatile ConsumerSession context;
85 private DOMDataBroker domDataBroker;
86 private DOMNotificationService domNotification;
88 private BrokerFacade() {}
90 public void setRpcService(final DOMRpcService router) {
91 this.rpcService = router;
94 public void setDomNotificationService(final DOMNotificationService domNotification) {
95 this.domNotification = domNotification;
98 public void setContext(final ConsumerSession context) {
99 this.context = context;
102 public static BrokerFacade getInstance() {
103 return BrokerFacade.INSTANCE;
106 private void checkPreconditions() {
107 if (this.context == null || this.domDataBroker == null) {
108 throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE);
113 * Read config data by path
119 public NormalizedNode<?, ?> readConfigurationData(final YangInstanceIdentifier path) {
120 return readConfigurationData(path, null);
124 * Read config data by path
129 * - value of with-defaults parameter
132 public NormalizedNode<?, ?> readConfigurationData(final YangInstanceIdentifier path, final String withDefa) {
133 checkPreconditions();
134 return readDataViaTransaction(this.domDataBroker.newReadOnlyTransaction(), CONFIGURATION, path, withDefa);
138 * Read config data from mount point by path.
141 * - mount point for reading data
146 public NormalizedNode<?, ?> readConfigurationData(final DOMMountPoint mountPoint,
147 final YangInstanceIdentifier path) {
148 return readConfigurationData(mountPoint, path, null);
152 * Read config data from mount point by path.
155 * - mount point for reading data
159 * - value of with-defaults parameter
162 public NormalizedNode<?, ?> readConfigurationData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path,
163 final String withDefa) {
164 final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
165 if (domDataBrokerService.isPresent()) {
166 return readDataViaTransaction(domDataBrokerService.get().newReadOnlyTransaction(), CONFIGURATION, path,
169 final String errMsg = "DOM data broker service isn't available for mount point " + path;
171 throw new RestconfDocumentedException(errMsg);
175 * Read operational data by path.
181 public NormalizedNode<?, ?> readOperationalData(final YangInstanceIdentifier path) {
182 checkPreconditions();
183 return readDataViaTransaction(this.domDataBroker.newReadOnlyTransaction(), OPERATIONAL, path);
187 * Read operational data from mount point by path.
190 * - mount point for reading data
195 public NormalizedNode<?, ?> readOperationalData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path) {
196 final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
197 if (domDataBrokerService.isPresent()) {
198 return readDataViaTransaction(domDataBrokerService.get().newReadOnlyTransaction(), OPERATIONAL, path);
200 final String errMsg = "DOM data broker service isn't available for mount point " + path;
202 throw new RestconfDocumentedException(errMsg);
206 * <b>PUT configuration data</b>
208 * Prepare result(status) for PUT operation and PUT data via transaction.
209 * Return wrapped status and future from PUT.
211 * @param globalSchema
212 * - used by merge parents (if contains list)
219 * @return wrapper of status and future of PUT
221 public PutResult commitConfigurationDataPut(
222 final SchemaContext globalSchema, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
223 final String insert, final String point) {
224 Preconditions.checkNotNull(globalSchema);
225 Preconditions.checkNotNull(path);
226 Preconditions.checkNotNull(payload);
228 checkPreconditions();
230 final DOMDataReadWriteTransaction newReadWriteTransaction = this.domDataBroker.newReadWriteTransaction();
231 final Status status = readDataViaTransaction(newReadWriteTransaction, CONFIGURATION, path) != null ? Status.OK
233 final CheckedFuture<Void, TransactionCommitFailedException> future = putDataViaTransaction(
234 newReadWriteTransaction, CONFIGURATION, path, payload, globalSchema, insert, point);
235 return new PutResult(status, future);
239 * <b>PUT configuration data (Mount point)</b>
241 * Prepare result(status) for PUT operation and PUT data via transaction.
242 * Return wrapped status and future from PUT.
245 * - mount point for getting transaction for operation and schema
246 * context for merging parents(if contains list)
253 * @return wrapper of status and future of PUT
255 public PutResult commitMountPointDataPut(
256 final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
257 final String insert, final String point) {
258 Preconditions.checkNotNull(mountPoint);
259 Preconditions.checkNotNull(path);
260 Preconditions.checkNotNull(payload);
262 final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
263 if (domDataBrokerService.isPresent()) {
264 final DOMDataReadWriteTransaction newReadWriteTransaction = domDataBrokerService.get().newReadWriteTransaction();
265 final Status status = readDataViaTransaction(newReadWriteTransaction, CONFIGURATION, path) != null
266 ? Status.OK : Status.CREATED;
267 final CheckedFuture<Void, TransactionCommitFailedException> future = putDataViaTransaction(
268 newReadWriteTransaction, CONFIGURATION, path, payload, mountPoint.getSchemaContext(), insert,
270 return new PutResult(status, future);
272 final String errMsg = "DOM data broker service isn't available for mount point " + path;
274 throw new RestconfDocumentedException(errMsg);
277 public PATCHStatusContext patchConfigurationDataWithinTransaction(final PATCHContext patchContext) throws Exception {
278 final DOMMountPoint mountPoint = patchContext.getInstanceIdentifierContext().getMountPoint();
280 // get new transaction and schema context on server or on mounted device
281 final SchemaContext schemaContext;
282 final DOMDataReadWriteTransaction patchTransaction;
283 if (mountPoint == null) {
284 schemaContext = patchContext.getInstanceIdentifierContext().getSchemaContext();
285 patchTransaction = this.domDataBroker.newReadWriteTransaction();
287 schemaContext = mountPoint.getSchemaContext();
289 final Optional<DOMDataBroker> optional = mountPoint.getService(DOMDataBroker.class);
291 if (optional.isPresent()) {
292 patchTransaction = optional.get().newReadWriteTransaction();
294 // if mount point does not have broker it is not possible to continue and global error is reported
295 LOG.error("Http PATCH {} has failed - device {} does not support broker service",
296 patchContext.getPatchId(), mountPoint.getIdentifier());
297 return new PATCHStatusContext(
298 patchContext.getPatchId(),
301 ImmutableList.of(new RestconfError(
302 ErrorType.APPLICATION,
303 ErrorTag.OPERATION_FAILED,
304 "DOM data broker service isn't available for mount point "
305 + mountPoint.getIdentifier()))
310 final List<PATCHStatusEntity> editCollection = new ArrayList<>();
311 List<RestconfError> editErrors;
312 boolean withoutError = true;
314 for (final PATCHEntity patchEntity : patchContext.getData()) {
315 final PATCHEditOperation operation = PATCHEditOperation.valueOf(patchEntity.getOperation().toUpperCase());
321 postDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(),
322 patchEntity.getNode(), schemaContext);
323 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null));
324 } catch (final RestconfDocumentedException e) {
325 LOG.error("Error call http PATCH operation {} on target {}",
327 patchEntity.getTargetNode().toString());
329 editErrors = new ArrayList<>();
330 editErrors.addAll(e.getErrors());
331 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors));
332 withoutError = false;
339 putDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity
340 .getTargetNode(), patchEntity.getNode(), schemaContext);
341 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null));
342 } catch (final RestconfDocumentedException e) {
343 LOG.error("Error call http PATCH operation {} on target {}",
345 patchEntity.getTargetNode().toString());
347 editErrors = new ArrayList<>();
348 editErrors.addAll(e.getErrors());
349 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors));
350 withoutError = false;
357 deleteDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity
359 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null));
360 } catch (final RestconfDocumentedException e) {
361 LOG.error("Error call http PATCH operation {} on target {}",
363 patchEntity.getTargetNode().toString());
365 editErrors = new ArrayList<>();
366 editErrors.addAll(e.getErrors());
367 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors));
368 withoutError = false;
375 deleteDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity
377 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null));
378 } catch (final RestconfDocumentedException e) {
379 LOG.error("Error call http PATCH operation {} on target {}",
381 patchEntity.getTargetNode().toString());
383 editErrors = new ArrayList<>();
384 editErrors.addAll(e.getErrors());
385 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors));
386 withoutError = false;
393 mergeDataWithinTransaction(patchTransaction, CONFIGURATION, patchEntity.getTargetNode(),
394 patchEntity.getNode(), schemaContext);
395 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), true, null));
396 } catch (final RestconfDocumentedException e) {
397 LOG.error("Error call http PATCH operation {} on target {}",
399 patchEntity.getTargetNode().toString());
401 editErrors = new ArrayList<>();
402 editErrors.addAll(e.getErrors());
403 editCollection.add(new PATCHStatusEntity(patchEntity.getEditId(), false, editErrors));
404 withoutError = false;
409 LOG.error("Unsupported http PATCH operation {} on target {}",
411 patchEntity.getTargetNode().toString());
416 // if errors then cancel transaction and return error status
418 patchTransaction.cancel();
419 return new PATCHStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), false, null);
422 // if no errors commit transaction
423 final CountDownLatch waiter = new CountDownLatch(1);
424 final CheckedFuture<Void, TransactionCommitFailedException> future = patchTransaction.submit();
425 final PATCHStatusContextHelper status = new PATCHStatusContextHelper();
427 Futures.addCallback(future, new FutureCallback<Void>() {
429 public void onSuccess(@Nullable final Void result) {
430 status.setStatus(new PATCHStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection),
436 public void onFailure(final Throwable t) {
437 // if commit failed it is global error
438 LOG.error("Http PATCH {} transaction commit has failed", patchContext.getPatchId());
439 status.setStatus(new PATCHStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection),
440 false, ImmutableList.of(
441 new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, t.getMessage()))));
447 return status.getStatus();
450 // POST configuration
451 public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataPost(
452 final SchemaContext globalSchema, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
453 final String insert, final String point) {
454 checkPreconditions();
455 return postDataViaTransaction(this.domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload,
456 globalSchema, insert, point);
459 public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataPost(
460 final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
461 final String insert, final String point) {
462 final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
463 if (domDataBrokerService.isPresent()) {
464 return postDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path,
465 payload, mountPoint.getSchemaContext(), insert, point);
467 final String errMsg = "DOM data broker service isn't available for mount point " + path;
469 throw new RestconfDocumentedException(errMsg);
472 // DELETE configuration
473 public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataDelete(
474 final YangInstanceIdentifier path) {
475 checkPreconditions();
476 return deleteDataViaTransaction(this.domDataBroker.newReadWriteTransaction(), CONFIGURATION, path);
479 public CheckedFuture<Void, TransactionCommitFailedException> commitConfigurationDataDelete(
480 final DOMMountPoint mountPoint, final YangInstanceIdentifier path) {
481 final Optional<DOMDataBroker> domDataBrokerService = mountPoint.getService(DOMDataBroker.class);
482 if (domDataBrokerService.isPresent()) {
483 return deleteDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path);
485 final String errMsg = "DOM data broker service isn't available for mount point " + path;
487 throw new RestconfDocumentedException(errMsg);
491 public CheckedFuture<DOMRpcResult, DOMRpcException> invokeRpc(final SchemaPath type, final NormalizedNode<?, ?> input) {
492 checkPreconditions();
493 if (this.rpcService == null) {
494 throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE);
496 LOG.trace("Invoke RPC {} with input: {}", type, input);
497 return this.rpcService.invokeRpc(type, input);
500 public void registerToListenDataChanges(final LogicalDatastoreType datastore, final DataChangeScope scope,
501 final ListenerAdapter listener) {
502 checkPreconditions();
504 if (listener.isListening()) {
508 final YangInstanceIdentifier path = listener.getPath();
509 final ListenerRegistration<DOMDataChangeListener> registration = this.domDataBroker.registerDataChangeListener(
510 datastore, path, listener, scope);
512 listener.setRegistration(registration);
515 private NormalizedNode<?, ?> readDataViaTransaction(final DOMDataReadTransaction transaction,
516 final LogicalDatastoreType datastore, final YangInstanceIdentifier path) {
517 return readDataViaTransaction(transaction, datastore, path, null);
520 private NormalizedNode<?, ?> readDataViaTransaction(final DOMDataReadTransaction transaction,
521 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final String withDefa) {
522 LOG.trace("Read {} via Restconf: {}", datastore.name(), path);
525 final Optional<NormalizedNode<?, ?>> optional = transaction.read(datastore, path).checkedGet();
526 return !optional.isPresent() ? null : withDefa == null ? optional.get() :
527 prepareDataByParamWithDef(optional.get(), path, withDefa);
528 } catch (ReadFailedException e) {
529 LOG.warn("Error reading {} from datastore {}", path, datastore.name(), e);
530 for (final RpcError error : e.getErrorList()) {
531 if (error.getErrorType() == RpcError.ErrorType.TRANSPORT
532 && error.getTag().equals(ErrorTag.RESOURCE_DENIED.getTagValue())) {
533 throw new RestconfDocumentedException(
536 ErrorTag.RESOURCE_DENIED_TRANSPORT);
539 throw new RestconfDocumentedException("Error reading data.", e, e.getErrorList());
543 private NormalizedNode<?, ?> prepareDataByParamWithDef(final NormalizedNode<?, ?> result,
544 final YangInstanceIdentifier path, final String withDefa) {
554 throw new RestconfDocumentedException("Bad value used with with-defaults parameter : " + withDefa);
557 final SchemaContext ctx = ControllerContext.getInstance().getGlobalSchema();
558 final DataSchemaContextTree baseSchemaCtxTree = DataSchemaContextTree.from(ctx);
559 final DataSchemaNode baseSchemaNode = baseSchemaCtxTree.getChild(path).getDataSchemaNode();
560 if (result instanceof ContainerNode) {
561 final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder =
562 Builders.containerBuilder((ContainerSchemaNode) baseSchemaNode);
563 buildCont(builder, (ContainerNode) result, baseSchemaCtxTree, path, trim);
564 return builder.build();
566 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder =
567 Builders.mapEntryBuilder((ListSchemaNode) baseSchemaNode);
568 buildMapEntryBuilder(builder, (MapEntryNode) result, baseSchemaCtxTree, path, trim,
569 ((ListSchemaNode) baseSchemaNode).getKeyDefinition());
570 return builder.build();
574 private void buildMapEntryBuilder(final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder,
575 final MapEntryNode result, final DataSchemaContextTree baseSchemaCtxTree,
576 final YangInstanceIdentifier actualPath, final boolean trim, final List<QName> keys) {
577 for (final DataContainerChild<? extends PathArgument, ?> child : result.getValue()) {
578 final YangInstanceIdentifier path = actualPath.node(child.getIdentifier());
579 final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(path).getDataSchemaNode();
580 if (child instanceof ContainerNode) {
581 final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> childBuilder =
582 Builders.containerBuilder((ContainerSchemaNode) childSchema);
583 buildCont(childBuilder, (ContainerNode) child, baseSchemaCtxTree, path, trim);
584 builder.withChild(childBuilder.build());
585 } else if (child instanceof MapNode) {
586 final CollectionNodeBuilder<MapEntryNode, MapNode> childBuilder =
587 Builders.mapBuilder((ListSchemaNode) childSchema);
588 buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim,
589 ((ListSchemaNode) childSchema).getKeyDefinition());
590 builder.withChild(childBuilder.build());
591 } else if (child instanceof LeafNode) {
592 final String defaultVal = ((LeafSchemaNode) childSchema).getDefault();
593 final String nodeVal = ((LeafNode<String>) child).getValue();
594 final NormalizedNodeAttrBuilder<NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
595 Builders.leafBuilder((LeafSchemaNode) childSchema);
596 if (keys.contains(child.getNodeType())) {
597 leafBuilder.withValue(((LeafNode) child).getValue());
598 builder.withChild(leafBuilder.build());
601 if (defaultVal == null || !defaultVal.equals(nodeVal)) {
602 leafBuilder.withValue(((LeafNode) child).getValue());
603 builder.withChild(leafBuilder.build());
606 if (defaultVal != null && defaultVal.equals(nodeVal)) {
607 leafBuilder.withValue(((LeafNode) child).getValue());
608 builder.withChild(leafBuilder.build());
616 private void buildList(final CollectionNodeBuilder<MapEntryNode, MapNode> builder, final MapNode result,
617 final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier path, final boolean trim,
618 final List<QName> keys) {
619 for (final MapEntryNode mapEntryNode : result.getValue()) {
620 final YangInstanceIdentifier actualNode = path.node(mapEntryNode.getIdentifier());
621 final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(actualNode).getDataSchemaNode();
622 final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder =
623 Builders.mapEntryBuilder((ListSchemaNode) childSchema);
624 buildMapEntryBuilder(mapEntryBuilder, mapEntryNode, baseSchemaCtxTree, actualNode, trim, keys);
625 builder.withChild(mapEntryBuilder.build());
629 private void buildCont(final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder,
630 final ContainerNode result, final DataSchemaContextTree baseSchemaCtxTree,
631 final YangInstanceIdentifier actualPath, final boolean trim) {
632 for (final DataContainerChild<? extends PathArgument, ?> child : result.getValue()) {
633 final YangInstanceIdentifier path = actualPath.node(child.getIdentifier());
634 final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(path).getDataSchemaNode();
635 if(child instanceof ContainerNode){
636 final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builderChild =
637 Builders.containerBuilder((ContainerSchemaNode) childSchema);
638 buildCont(builderChild, result, baseSchemaCtxTree, actualPath, trim);
639 builder.withChild(builderChild.build());
640 } else if (child instanceof MapNode) {
641 final CollectionNodeBuilder<MapEntryNode, MapNode> childBuilder =
642 Builders.mapBuilder((ListSchemaNode) childSchema);
643 buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim,
644 ((ListSchemaNode) childSchema).getKeyDefinition());
645 builder.withChild(childBuilder.build());
646 } else if (child instanceof LeafNode) {
647 final String defaultVal = ((LeafSchemaNode) childSchema).getDefault();
648 final String nodeVal = ((LeafNode<String>) child).getValue();
649 final NormalizedNodeAttrBuilder<NodeIdentifier, Object, LeafNode<Object>> leafBuilder =
650 Builders.leafBuilder((LeafSchemaNode) childSchema);
652 if (defaultVal == null || !defaultVal.equals(nodeVal)) {
653 leafBuilder.withValue(((LeafNode) child).getValue());
654 builder.withChild(leafBuilder.build());
657 if (defaultVal != null && defaultVal.equals(nodeVal)) {
658 leafBuilder.withValue(((LeafNode) child).getValue());
659 builder.withChild(leafBuilder.build());
667 * POST data and submit transaction {@link DOMDataReadWriteTransaction}
669 private CheckedFuture<Void, TransactionCommitFailedException> postDataViaTransaction(
670 final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
671 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext,
672 final String insert, final String point) {
673 LOG.trace("POST {} via Restconf: {} with payload {}", datastore.name(), path, payload);
674 postData(rWTransaction, datastore, path, payload, schemaContext, insert, point);
675 return rWTransaction.submit();
679 * POST data and do NOT submit transaction {@link DOMDataReadWriteTransaction}
681 private void postDataWithinTransaction(
682 final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
683 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext) {
684 LOG.trace("POST {} within Restconf PATCH: {} with payload {}", datastore.name(), path, payload);
685 postData(rWTransaction, datastore, path, payload, schemaContext, null, null);
688 private void postData(final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
689 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
690 final SchemaContext schemaContext, final String insert, final String point) {
691 if (insert == null) {
692 makeNormalPost(rWTransaction, datastore, path, payload, schemaContext);
694 final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path);
695 checkItemDoesNotExists(rWTransaction, datastore, path);
698 if(schemaNode instanceof ListSchemaNode){
699 final OrderedMapNode readList =
700 (OrderedMapNode) this.readConfigurationData(path.getParent().getParent());
701 if (readList == null || readList.getValue().isEmpty()) {
702 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
704 rWTransaction.delete(datastore, path.getParent().getParent());
705 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
706 makeNormalPost(rWTransaction, datastore, path.getParent().getParent(), readList,
710 final OrderedLeafSetNode readLeafList =
711 (OrderedLeafSetNode) readConfigurationData(path.getParent());
712 if (readLeafList == null || readLeafList.getValue().isEmpty()) {
713 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
715 rWTransaction.delete(datastore, path.getParent());
716 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
717 makeNormalPost(rWTransaction, datastore, path.getParent().getParent(), readLeafList,
723 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
726 if(schemaNode instanceof ListSchemaNode){
727 final OrderedMapNode readList =
728 (OrderedMapNode) this.readConfigurationData(path.getParent().getParent());
729 if (readList == null || readList.getValue().isEmpty()) {
730 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
732 insertWithPointListPost(rWTransaction, datastore, path, payload, schemaContext, point,
737 final OrderedLeafSetNode<?> readLeafList =
738 (OrderedLeafSetNode<?>) readConfigurationData(path.getParent());
739 if (readLeafList == null || readLeafList.getValue().isEmpty()) {
740 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
742 insertWithPointLeafListPost(rWTransaction, datastore, path, payload, schemaContext, point,
748 if (schemaNode instanceof ListSchemaNode) {
749 final OrderedMapNode readList =
750 (OrderedMapNode) this.readConfigurationData(path.getParent().getParent());
751 if (readList == null || readList.getValue().isEmpty()) {
752 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
754 insertWithPointListPost(rWTransaction, datastore, path, payload, schemaContext, point,
759 final OrderedLeafSetNode<?> readLeafList =
760 (OrderedLeafSetNode<?>) readConfigurationData(path.getParent());
761 if (readLeafList == null || readLeafList.getValue().isEmpty()) {
762 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
764 insertWithPointLeafListPost(rWTransaction, datastore, path, payload, schemaContext, point,
765 readLeafList, false);
770 throw new RestconfDocumentedException(
771 "Used bad value of insert parameter. Possible values are first, last, before or after, "
772 + "but was: " + insert);
777 private void insertWithPointLeafListPost(final DOMDataReadWriteTransaction rWTransaction,
778 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
779 final SchemaContext schemaContext, final String point, final OrderedLeafSetNode<?> readLeafList,
780 final boolean before) {
781 rWTransaction.delete(datastore, path.getParent().getParent());
782 final InstanceIdentifierContext<?> instanceIdentifier =
783 ControllerContext.getInstance().toInstanceIdentifier(point);
785 for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
786 if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
795 final NormalizedNode<?, ?> emptySubtree =
796 ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent());
797 rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
798 for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
800 checkItemDoesNotExists(rWTransaction, datastore, path);
801 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
803 final YangInstanceIdentifier childPath = path.getParent().getParent().node(nodeChild.getIdentifier());
804 checkItemDoesNotExists(rWTransaction, datastore, childPath);
805 rWTransaction.put(datastore, childPath, nodeChild);
810 private void insertWithPointListPost(final DOMDataReadWriteTransaction rWTransaction,
811 final LogicalDatastoreType datastore,
812 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext,
813 final String point, final MapNode readList, final boolean before) {
814 rWTransaction.delete(datastore, path.getParent().getParent());
815 final InstanceIdentifierContext<?> instanceIdentifier =
816 ControllerContext.getInstance().toInstanceIdentifier(point);
818 for (final MapEntryNode mapEntryNode : readList.getValue()) {
819 if (mapEntryNode.getIdentifier()
820 .equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
829 final NormalizedNode<?, ?> emptySubtree =
830 ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent());
831 rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
832 for (final MapEntryNode mapEntryNode : readList.getValue()) {
834 checkItemDoesNotExists(rWTransaction, datastore, path);
835 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
837 final YangInstanceIdentifier childPath = path.getParent().getParent().node(mapEntryNode.getIdentifier());
838 checkItemDoesNotExists(rWTransaction, datastore, childPath);
839 rWTransaction.put(datastore, childPath, mapEntryNode);
844 private static DataSchemaNode checkListAndOrderedType(final SchemaContext ctx, final YangInstanceIdentifier path) {
845 final YangInstanceIdentifier parent = path.getParent();
846 final DataSchemaContextNode<?> node = DataSchemaContextTree.from(ctx).getChild(parent);
847 final DataSchemaNode dataSchemaNode = node.getDataSchemaNode();
849 if (dataSchemaNode instanceof ListSchemaNode) {
850 if(!((ListSchemaNode) dataSchemaNode).isUserOrdered()) {
851 throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user list.");
853 return dataSchemaNode;
855 if (dataSchemaNode instanceof LeafListSchemaNode) {
856 if(!((LeafListSchemaNode) dataSchemaNode).isUserOrdered()) {
857 throw new RestconfDocumentedException("Insert parameter can be used only with ordered-by user leaf-list.");
859 return dataSchemaNode;
861 throw new RestconfDocumentedException("Insert parameter can be used only with list or leaf-list");
864 private void makeNormalPost(final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
865 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext) {
866 if (payload instanceof MapNode) {
867 final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path);
868 rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
869 ensureParentsByMerge(datastore, path, rWTransaction, schemaContext);
870 for (final MapEntryNode child : ((MapNode) payload).getValue()) {
871 final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
872 checkItemDoesNotExists(rWTransaction, datastore, childPath);
873 rWTransaction.put(datastore, childPath, child);
875 } else if (payload instanceof LeafSetNode) {
876 final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path);
877 rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
878 ensureParentsByMerge(datastore, path, rWTransaction, schemaContext);
879 for (final LeafSetEntryNode<?> child : ((LeafSetNode<?>) payload).getValue()) {
880 final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
881 checkItemDoesNotExists(rWTransaction, datastore, childPath);
882 rWTransaction.put(datastore, childPath, child);
885 simplePostPut(rWTransaction, datastore, path, payload, schemaContext);
889 private static void simplePostPut(final DOMDataReadWriteTransaction rWTransaction,
890 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
891 final SchemaContext schemaContext) {
892 checkItemDoesNotExists(rWTransaction, datastore, path);
893 ensureParentsByMerge(datastore, path, rWTransaction, schemaContext);
894 rWTransaction.put(datastore, path, payload);
897 private static boolean doesItemExist(final DOMDataReadWriteTransaction rWTransaction,
898 final LogicalDatastoreType store, final YangInstanceIdentifier path) {
900 return rWTransaction.exists(store, path).checkedGet();
901 } catch (ReadFailedException e) {
902 rWTransaction.cancel();
903 throw new RestconfDocumentedException("Could not determine the existence of path " + path,
904 e, e.getErrorList());
909 * Check if item already exists. Throws error if it does NOT already exist.
910 * @param rWTransaction Current transaction
911 * @param store Used datastore
912 * @param path Path to item to verify its existence
914 private static void checkItemExists(final DOMDataReadWriteTransaction rWTransaction,
915 final LogicalDatastoreType store, final YangInstanceIdentifier path) {
916 if (!doesItemExist(rWTransaction, store, path)) {
917 final String errMsg = "Operation via Restconf was not executed because data does not exist";
918 LOG.trace("{}:{}", errMsg, path);
919 rWTransaction.cancel();
920 throw new RestconfDocumentedException("Data does not exist for path: " + path, ErrorType.PROTOCOL,
921 ErrorTag.DATA_MISSING);
926 * Check if item does NOT already exist. Throws error if it already exists.
927 * @param rWTransaction Current transaction
928 * @param store Used datastore
929 * @param path Path to item to verify its existence
931 private static void checkItemDoesNotExists(final DOMDataReadWriteTransaction rWTransaction,
932 final LogicalDatastoreType store, final YangInstanceIdentifier path) {
933 if (doesItemExist(rWTransaction, store, path)) {
934 final String errMsg = "Operation via Restconf was not executed because data already exists";
935 LOG.trace("{}:{}", errMsg, path);
936 rWTransaction.cancel();
937 throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL,
938 ErrorTag.DATA_EXISTS);
943 * PUT data and submit {@link DOMDataReadWriteTransaction}
948 private CheckedFuture<Void, TransactionCommitFailedException> putDataViaTransaction(
949 final DOMDataReadWriteTransaction readWriteTransaction, final LogicalDatastoreType datastore,
950 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext,
951 final String insert, final String point) {
952 LOG.trace("Put {} via Restconf: {} with payload {}", datastore.name(), path, payload);
953 putData(readWriteTransaction, datastore, path, payload, schemaContext, insert, point);
954 return readWriteTransaction.submit();
958 * PUT data and do NOT submit {@link DOMDataReadWriteTransaction}
963 private void putDataWithinTransaction(
964 final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore,
965 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext) {
966 LOG.trace("Put {} within Restconf PATCH: {} with payload {}", datastore.name(), path, payload);
967 putData(writeTransaction, datastore, path, payload, schemaContext, null, null);
970 // FIXME: This is doing correct put for container and list children, not sure if this will work for choice case
971 private void putData(final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType datastore,
972 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext,
973 final String insert, final String point) {
974 if (insert == null) {
975 makePut(rWTransaction, datastore, path, payload, schemaContext);
977 final DataSchemaNode schemaNode = checkListAndOrderedType(schemaContext, path);
978 checkItemDoesNotExists(rWTransaction, datastore, path);
981 if (schemaNode instanceof ListSchemaNode) {
982 final OrderedMapNode readList =
983 (OrderedMapNode) this.readConfigurationData(path.getParent());
984 if (readList == null || readList.getValue().isEmpty()) {
985 simplePut(datastore, path, rWTransaction, schemaContext, payload);
987 rWTransaction.delete(datastore, path.getParent());
988 simplePut(datastore, path, rWTransaction, schemaContext, payload);
989 makePut(rWTransaction, datastore, path.getParent(), readList, schemaContext);
992 final OrderedLeafSetNode<?> readLeafList =
993 (OrderedLeafSetNode<?>) readConfigurationData(path.getParent());
994 if (readLeafList == null || readLeafList.getValue().isEmpty()) {
995 simplePut(datastore, path, rWTransaction, schemaContext, payload);
997 rWTransaction.delete(datastore, path.getParent());
998 simplePut(datastore, path, rWTransaction, schemaContext, payload);
999 makePut(rWTransaction, datastore, path.getParent(), readLeafList,
1005 simplePut(datastore, path, rWTransaction, schemaContext, payload);
1008 if (schemaNode instanceof ListSchemaNode) {
1009 final OrderedMapNode readList =
1010 (OrderedMapNode) this.readConfigurationData(path.getParent());
1011 if (readList == null || readList.getValue().isEmpty()) {
1012 simplePut(datastore, path, rWTransaction, schemaContext, payload);
1014 insertWithPointListPut(rWTransaction, datastore, path, payload, schemaContext, point,
1018 final OrderedLeafSetNode<?> readLeafList =
1019 (OrderedLeafSetNode<?>) readConfigurationData(path.getParent());
1020 if (readLeafList == null || readLeafList.getValue().isEmpty()) {
1021 simplePut(datastore, path, rWTransaction, schemaContext, payload);
1023 insertWithPointLeafListPut(rWTransaction, datastore, path, payload, schemaContext, point,
1024 readLeafList, true);
1029 if (schemaNode instanceof ListSchemaNode) {
1030 final OrderedMapNode readList =
1031 (OrderedMapNode) this.readConfigurationData(path.getParent());
1032 if (readList == null || readList.getValue().isEmpty()) {
1033 simplePut(datastore, path, rWTransaction, schemaContext, payload);
1035 insertWithPointListPut(rWTransaction, datastore, path, payload, schemaContext, point,
1039 final OrderedLeafSetNode<?> readLeafList =
1040 (OrderedLeafSetNode<?>) readConfigurationData(path.getParent());
1041 if (readLeafList == null || readLeafList.getValue().isEmpty()) {
1042 simplePut(datastore, path, rWTransaction, schemaContext, payload);
1044 insertWithPointLeafListPut(rWTransaction, datastore, path, payload, schemaContext, point,
1045 readLeafList, false);
1050 throw new RestconfDocumentedException(
1051 "Used bad value of insert parameter. Possible values are first, last, before or after, "
1052 + "but was: " + insert);
1057 private void insertWithPointLeafListPut(final DOMDataReadWriteTransaction rWTransaction,
1058 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
1059 final SchemaContext schemaContext, final String point, final OrderedLeafSetNode<?> readLeafList,
1060 final boolean before) {
1061 rWTransaction.delete(datastore, path.getParent());
1062 final InstanceIdentifierContext<?> instanceIdentifier =
1063 ControllerContext.getInstance().toInstanceIdentifier(point);
1065 for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
1066 if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
1075 final NormalizedNode<?, ?> emptySubtree =
1076 ImmutableNodes.fromInstanceId(schemaContext, path.getParent());
1077 rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
1078 for (final LeafSetEntryNode<?> nodeChild : readLeafList.getValue()) {
1080 simplePut(datastore, path, rWTransaction, schemaContext, payload);
1082 final YangInstanceIdentifier childPath = path.getParent().node(nodeChild.getIdentifier());
1083 rWTransaction.put(datastore, childPath, nodeChild);
1088 private void insertWithPointListPut(final DOMDataReadWriteTransaction rWTransaction,
1089 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
1090 final SchemaContext schemaContext, final String point, final OrderedMapNode readList,
1091 final boolean before) {
1092 rWTransaction.delete(datastore, path.getParent());
1093 final InstanceIdentifierContext<?> instanceIdentifier =
1094 ControllerContext.getInstance().toInstanceIdentifier(point);
1096 for (final MapEntryNode mapEntryNode : readList.getValue()) {
1097 if (mapEntryNode.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) {
1106 final NormalizedNode<?, ?> emptySubtree =
1107 ImmutableNodes.fromInstanceId(schemaContext, path.getParent());
1108 rWTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
1109 for (final MapEntryNode mapEntryNode : readList.getValue()) {
1111 simplePut(datastore, path, rWTransaction, schemaContext, payload);
1113 final YangInstanceIdentifier childPath = path.getParent().node(mapEntryNode.getIdentifier());
1114 rWTransaction.put(datastore, childPath, mapEntryNode);
1119 private static void makePut(final DOMDataReadWriteTransaction writeTransaction,
1120 final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload,
1121 final SchemaContext schemaContext) {
1122 if (payload instanceof MapNode) {
1123 final NormalizedNode<?, ?> emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path);
1124 writeTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree);
1125 ensureParentsByMerge(datastore, path, writeTransaction, schemaContext);
1126 for (final MapEntryNode child : ((MapNode) payload).getValue()) {
1127 final YangInstanceIdentifier childPath = path.node(child.getIdentifier());
1128 writeTransaction.put(datastore, childPath, child);
1131 simplePut(datastore, path, writeTransaction, schemaContext, payload);
1135 private static void simplePut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path,
1136 final DOMDataReadWriteTransaction writeTransaction, final SchemaContext schemaContext,
1137 final NormalizedNode<?, ?> payload) {
1138 ensureParentsByMerge(datastore, path, writeTransaction, schemaContext);
1139 writeTransaction.put(datastore, path, payload);
1142 private static CheckedFuture<Void, TransactionCommitFailedException> deleteDataViaTransaction(
1143 final DOMDataReadWriteTransaction readWriteTransaction, final LogicalDatastoreType datastore,
1144 final YangInstanceIdentifier path) {
1145 LOG.trace("Delete {} via Restconf: {}", datastore.name(), path);
1146 checkItemExists(readWriteTransaction, datastore, path);
1147 readWriteTransaction.delete(datastore, path);
1148 return readWriteTransaction.submit();
1151 private static void deleteDataWithinTransaction(final DOMDataWriteTransaction writeTransaction,
1152 final LogicalDatastoreType datastore, final YangInstanceIdentifier path) {
1153 LOG.trace("Delete {} within Restconf PATCH: {}", datastore.name(), path);
1154 writeTransaction.delete(datastore, path);
1157 private static void mergeDataWithinTransaction(
1158 final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore,
1159 final YangInstanceIdentifier path, final NormalizedNode<?, ?> payload, final SchemaContext schemaContext) {
1160 LOG.trace("Merge {} within Restconf PATCH: {} with payload {}", datastore.name(), path, payload);
1161 ensureParentsByMerge(datastore, path, writeTransaction, schemaContext);
1163 // merging is necessary only for lists otherwise we can call put method
1164 if (payload instanceof MapNode) {
1165 writeTransaction.merge(datastore, path, payload);
1167 writeTransaction.put(datastore, path, payload);
1171 public void setDomDataBroker(final DOMDataBroker domDataBroker) {
1172 this.domDataBroker = domDataBroker;
1175 public void registerToListenNotification(final NotificationListenerAdapter listener) {
1176 checkPreconditions();
1178 if (listener.isListening()) {
1182 final SchemaPath path = listener.getSchemaPath();
1183 final ListenerRegistration<DOMNotificationListener> registration = this.domNotification
1184 .registerNotificationListener(listener, path);
1186 listener.setRegistration(registration);
1189 private final class PATCHStatusContextHelper {
1190 PATCHStatusContext status;
1192 public PATCHStatusContext getStatus() {
1196 public void setStatus(final PATCHStatusContext status) {
1197 this.status = status;
1201 private static void ensureParentsByMerge(final LogicalDatastoreType store,
1202 final YangInstanceIdentifier normalizedPath, final DOMDataReadWriteTransaction rwTx,
1203 final SchemaContext schemaContext) {
1204 final List<PathArgument> normalizedPathWithoutChildArgs = new ArrayList<>();
1205 YangInstanceIdentifier rootNormalizedPath = null;
1207 final Iterator<PathArgument> it = normalizedPath.getPathArguments().iterator();
1209 while (it.hasNext()) {
1210 final PathArgument pathArgument = it.next();
1211 if (rootNormalizedPath == null) {
1212 rootNormalizedPath = YangInstanceIdentifier.create(pathArgument);
1216 normalizedPathWithoutChildArgs.add(pathArgument);
1220 if (normalizedPathWithoutChildArgs.isEmpty()) {
1224 Preconditions.checkArgument(rootNormalizedPath != null, "Empty path received");
1226 final NormalizedNode<?, ?> parentStructure = ImmutableNodes.fromInstanceId(schemaContext,
1227 YangInstanceIdentifier.create(normalizedPathWithoutChildArgs));
1228 rwTx.merge(store, rootNormalizedPath, parentStructure);