X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-nb-bierman02%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Frestconf%2Fimpl%2FBrokerFacade.java;h=4ce925f7f5a9160edda3529900a6384b7eb22443;hb=9cc114dc8e4109893e2346477b5ae14391afe01c;hp=2aa300f00eeec7c4781f0a1ca6cda166f3b9658f;hpb=86e8b0bb2c9e0f10f7d679cf70495c3d4249e547;p=netconf.git diff --git a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java index 2aa300f00e..4ce925f7f5 100644 --- a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java +++ b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/restconf/impl/BrokerFacade.java @@ -7,56 +7,62 @@ */ package org.opendaylight.netconf.sal.restconf.impl; -import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION; -import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL; +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION; +import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FluentFuture; import com.google.common.util.concurrent.FutureCallback; -import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import java.io.Closeable; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; +import java.util.Optional; import java.util.concurrent.CountDownLatch; -import javax.annotation.Nullable; +import java.util.concurrent.ExecutionException; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import javax.inject.Singleton; import javax.ws.rs.core.Response.Status; -import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; -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.DOMDataBroker; -import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction; -import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction; -import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; -import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService; -import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier; -import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; -import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint; -import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener; -import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcException; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcResult; -import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; +import org.eclipse.jdt.annotation.NonNull; +import org.opendaylight.mdsal.common.api.CommitInfo; +import org.opendaylight.mdsal.common.api.LogicalDatastoreType; +import org.opendaylight.mdsal.common.api.ReadFailedException; +import org.opendaylight.mdsal.dom.api.DOMDataBroker; +import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService; +import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier; +import org.opendaylight.mdsal.dom.api.DOMDataTreeReadOperations; +import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction; +import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction; +import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction; +import org.opendaylight.mdsal.dom.api.DOMMountPoint; +import org.opendaylight.mdsal.dom.api.DOMNotificationListener; +import org.opendaylight.mdsal.dom.api.DOMNotificationService; +import org.opendaylight.mdsal.dom.api.DOMRpcResult; +import org.opendaylight.mdsal.dom.api.DOMRpcService; +import org.opendaylight.mdsal.dom.api.DOMSchemaService; import org.opendaylight.netconf.sal.streams.listeners.ListenerAdapter; import org.opendaylight.netconf.sal.streams.listeners.NotificationListenerAdapter; import org.opendaylight.restconf.common.context.InstanceIdentifierContext; import org.opendaylight.restconf.common.errors.RestconfDocumentedException; import org.opendaylight.restconf.common.errors.RestconfError; -import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag; -import org.opendaylight.restconf.common.errors.RestconfError.ErrorType; import org.opendaylight.restconf.common.patch.PatchContext; import org.opendaylight.restconf.common.patch.PatchEditOperation; import org.opendaylight.restconf.common.patch.PatchEntity; import org.opendaylight.restconf.common.patch.PatchStatusContext; import org.opendaylight.restconf.common.patch.PatchStatusEntity; +import org.opendaylight.yang.gen.v1.urn.sal.restconf.event.subscription.rev140708.CreateDataChangeEventSubscriptionInput1.Scope; import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.common.ErrorType; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; @@ -69,54 +75,64 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode; -import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode; -import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode; +import org.opendaylight.yangtools.yang.data.api.schema.UserLeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.UserMapNode; +import org.opendaylight.yangtools.yang.data.api.schema.builder.CollectionNodeBuilder; +import org.opendaylight.yangtools.yang.data.api.schema.builder.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.api.schema.builder.NormalizedNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.SchemaAwareBuilders; import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode; import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; 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.LeafSchemaNode; import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaPath; +import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class BrokerFacade { +@Singleton +public class BrokerFacade implements Closeable { private static final Logger LOG = LoggerFactory.getLogger(BrokerFacade.class); - private static final BrokerFacade INSTANCE = new BrokerFacade(); - private volatile DOMRpcService rpcService; - - private DOMDataBroker domDataBroker; - private DOMNotificationService domNotification; + private final ThreadLocal isMounted = new ThreadLocal<>(); + private final DOMNotificationService domNotification; + private final ControllerContext controllerContext; + private final DOMDataBroker domDataBroker; - BrokerFacade() { - - } - - public void setRpcService(final DOMRpcService router) { - this.rpcService = router; - } + private volatile DOMRpcService rpcService; - public void setDomNotificationService(final DOMNotificationService service) { - this.domNotification = service; + @Inject + public BrokerFacade(final DOMRpcService rpcService, final DOMDataBroker domDataBroker, + final DOMNotificationService domNotification, final ControllerContext controllerContext) { + this.rpcService = requireNonNull(rpcService); + this.domDataBroker = requireNonNull(domDataBroker); + this.domNotification = requireNonNull(domNotification); + this.controllerContext = requireNonNull(controllerContext); } - public static BrokerFacade getInstance() { - return BrokerFacade.INSTANCE; + /** + * Factory method. + * + * @deprecated Just use + * {@link #BrokerFacade(DOMRpcService, DOMDataBroker, DOMNotificationService, ControllerContext)} + * constructor instead. + */ + @Deprecated + public static BrokerFacade newInstance(final DOMRpcService rpcService, final DOMDataBroker domDataBroker, + final DOMNotificationService domNotification, final ControllerContext controllerContext) { + return new BrokerFacade(rpcService, domDataBroker, domNotification, controllerContext); } - private void checkPreconditions() { - if (this.domDataBroker == null) { - throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE); - } + @Override + @PreDestroy + public void close() { } /** @@ -126,7 +142,7 @@ public class BrokerFacade { * path of data * @return read date */ - public NormalizedNode readConfigurationData(final YangInstanceIdentifier path) { + public NormalizedNode readConfigurationData(final YangInstanceIdentifier path) { return readConfigurationData(path, null); } @@ -139,9 +155,8 @@ public class BrokerFacade { * value of with-defaults parameter * @return read date */ - public NormalizedNode readConfigurationData(final YangInstanceIdentifier path, final String withDefa) { - checkPreconditions(); - try (DOMDataReadOnlyTransaction tx = this.domDataBroker.newReadOnlyTransaction()) { + public NormalizedNode readConfigurationData(final YangInstanceIdentifier path, final String withDefa) { + try (DOMDataTreeReadTransaction tx = domDataBroker.newReadOnlyTransaction()) { return readDataViaTransaction(tx, CONFIGURATION, path, withDefa); } } @@ -155,8 +170,7 @@ public class BrokerFacade { * path of data * @return read data */ - public NormalizedNode readConfigurationData(final DOMMountPoint mountPoint, - final YangInstanceIdentifier path) { + public NormalizedNode readConfigurationData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path) { return readConfigurationData(mountPoint, path, null); } @@ -171,17 +185,15 @@ public class BrokerFacade { * value of with-defaults parameter * @return read data */ - public NormalizedNode readConfigurationData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path, + public NormalizedNode readConfigurationData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final String withDefa) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - try (DOMDataReadOnlyTransaction tx = domDataBrokerService.get().newReadOnlyTransaction()) { + try (DOMDataTreeReadTransaction tx = domDataBrokerService.get().newReadOnlyTransaction()) { return readDataViaTransaction(tx, CONFIGURATION, path, withDefa); } } - final String errMsg = "DOM data broker service isn't available for mount point " + path; - LOG.warn(errMsg); - throw new RestconfDocumentedException(errMsg); + throw dataBrokerUnavailable(path); } /** @@ -191,10 +203,8 @@ public class BrokerFacade { * path of data * @return read data */ - public NormalizedNode readOperationalData(final YangInstanceIdentifier path) { - checkPreconditions(); - - try (DOMDataReadOnlyTransaction tx = this.domDataBroker.newReadOnlyTransaction()) { + public NormalizedNode readOperationalData(final YangInstanceIdentifier path) { + try (DOMDataTreeReadTransaction tx = domDataBroker.newReadOnlyTransaction()) { return readDataViaTransaction(tx, OPERATIONAL, path); } } @@ -208,16 +218,14 @@ public class BrokerFacade { * path of data * @return read data */ - public NormalizedNode readOperationalData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path) { + public NormalizedNode readOperationalData(final DOMMountPoint mountPoint, final YangInstanceIdentifier path) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - try (DOMDataReadOnlyTransaction tx = domDataBrokerService.get().newReadOnlyTransaction()) { + try (DOMDataTreeReadTransaction tx = domDataBrokerService.get().newReadOnlyTransaction()) { return readDataViaTransaction(tx, OPERATIONAL, path); } } - final String errMsg = "DOM data broker service isn't available for mount point " + path; - LOG.warn(errMsg); - throw new RestconfDocumentedException(errMsg); + throw dataBrokerUnavailable(path); } /** @@ -239,20 +247,19 @@ public class BrokerFacade { * insert * @return wrapper of status and future of PUT */ - public PutResult commitConfigurationDataPut( - final SchemaContext globalSchema, final YangInstanceIdentifier path, final NormalizedNode payload, - final String insert, final String point) { - Preconditions.checkNotNull(globalSchema); - Preconditions.checkNotNull(path); - Preconditions.checkNotNull(payload); - - checkPreconditions(); - - final DOMDataReadWriteTransaction newReadWriteTransaction = this.domDataBroker.newReadWriteTransaction(); + public PutResult commitConfigurationDataPut(final EffectiveModelContext globalSchema, + final YangInstanceIdentifier path, final NormalizedNode payload, final String insert, final String point) { + requireNonNull(globalSchema); + requireNonNull(path); + requireNonNull(payload); + + isMounted.set(false); + final DOMDataTreeReadWriteTransaction newReadWriteTransaction = domDataBroker.newReadWriteTransaction(); final Status status = readDataViaTransaction(newReadWriteTransaction, CONFIGURATION, path) != null ? Status.OK : Status.CREATED; - final CheckedFuture future = putDataViaTransaction( + final FluentFuture future = putDataViaTransaction( newReadWriteTransaction, CONFIGURATION, path, payload, globalSchema, insert, point); + isMounted.remove(); return new PutResult(status, future); } @@ -276,27 +283,26 @@ public class BrokerFacade { * insert * @return wrapper of status and future of PUT */ - public PutResult commitMountPointDataPut( - final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode payload, - final String insert, final String point) { - Preconditions.checkNotNull(mountPoint); - Preconditions.checkNotNull(path); - Preconditions.checkNotNull(payload); + public PutResult commitMountPointDataPut(final DOMMountPoint mountPoint, final YangInstanceIdentifier path, + final NormalizedNode payload, final String insert, final String point) { + requireNonNull(mountPoint); + requireNonNull(path); + requireNonNull(payload); + isMounted.set(true); final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - final DOMDataReadWriteTransaction newReadWriteTransaction = + final DOMDataTreeReadWriteTransaction newReadWriteTransaction = domDataBrokerService.get().newReadWriteTransaction(); final Status status = readDataViaTransaction(newReadWriteTransaction, CONFIGURATION, path) != null ? Status.OK : Status.CREATED; - final CheckedFuture future = putDataViaTransaction( - newReadWriteTransaction, CONFIGURATION, path, payload, mountPoint.getSchemaContext(), insert, - point); + final FluentFuture future = putDataViaTransaction( + newReadWriteTransaction, CONFIGURATION, path, payload, modelContext(mountPoint), insert, point); + isMounted.remove(); return new PutResult(status, future); } - final String errMsg = "DOM data broker service isn't available for mount point " + path; - LOG.warn(errMsg); - throw new RestconfDocumentedException(errMsg); + isMounted.remove(); + throw dataBrokerUnavailable(path); } public PatchStatusContext patchConfigurationDataWithinTransaction(final PatchContext patchContext) @@ -304,13 +310,13 @@ public class BrokerFacade { final DOMMountPoint mountPoint = patchContext.getInstanceIdentifierContext().getMountPoint(); // get new transaction and schema context on server or on mounted device - final SchemaContext schemaContext; - final DOMDataReadWriteTransaction patchTransaction; + final EffectiveModelContext schemaContext; + final DOMDataTreeReadWriteTransaction patchTransaction; if (mountPoint == null) { schemaContext = patchContext.getInstanceIdentifierContext().getSchemaContext(); - patchTransaction = this.domDataBroker.newReadWriteTransaction(); + patchTransaction = domDataBroker.newReadWriteTransaction(); } else { - schemaContext = mountPoint.getSchemaContext(); + schemaContext = modelContext(mountPoint); final Optional optional = mountPoint.getService(DOMDataBroker.class); @@ -324,11 +330,8 @@ public class BrokerFacade { patchContext.getPatchId(), null, false, - ImmutableList.of(new RestconfError( - ErrorType.APPLICATION, - ErrorTag.OPERATION_FAILED, - "DOM data broker service isn't available for mount point " - + mountPoint.getIdentifier())) + ImmutableList.of(new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, + "DOM data broker service isn't available for mount point " + mountPoint.getIdentifier())) ); } } @@ -429,12 +432,12 @@ public class BrokerFacade { // if no errors commit transaction final CountDownLatch waiter = new CountDownLatch(1); - final CheckedFuture future = patchTransaction.submit(); + final FluentFuture future = patchTransaction.commit(); final PatchStatusContextHelper status = new PatchStatusContextHelper(); - Futures.addCallback(future, new FutureCallback() { + future.addCallback(new FutureCallback() { @Override - public void onSuccess(@Nullable final Void result) { + public void onSuccess(final CommitInfo result) { status.setStatus(new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), true, null)); waiter.countDown(); @@ -445,7 +448,7 @@ public class BrokerFacade { // if commit failed it is global error LOG.error("Http Patch {} transaction commit has failed", patchContext.getPatchId()); status.setStatus(new PatchStatusContext(patchContext.getPatchId(), ImmutableList.copyOf(editCollection), - false, ImmutableList.of( + false, ImmutableList.of( new RestconfError(ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, throwable.getMessage())))); waiter.countDown(); } @@ -456,70 +459,69 @@ public class BrokerFacade { } // POST configuration - public CheckedFuture commitConfigurationDataPost( - final SchemaContext globalSchema, final YangInstanceIdentifier path, final NormalizedNode payload, - final String insert, final String point) { - checkPreconditions(); - return postDataViaTransaction(this.domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, - globalSchema, insert, point); + public FluentFuture commitConfigurationDataPost( + final EffectiveModelContext globalSchema, final YangInstanceIdentifier path, + final NormalizedNode payload, final String insert, final String point) { + isMounted.set(false); + FluentFuture future = + postDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path, payload, + globalSchema, insert, point); + isMounted.remove(); + return future; } - public CheckedFuture commitConfigurationDataPost( - final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode payload, + public FluentFuture commitConfigurationDataPost( + final DOMMountPoint mountPoint, final YangInstanceIdentifier path, final NormalizedNode payload, final String insert, final String point) { + isMounted.set(true); final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { - return postDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path, - payload, mountPoint.getSchemaContext(), insert, point); + FluentFuture future = + postDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path, + payload, modelContext(mountPoint), insert, point); + isMounted.remove(); + return future; } - final String errMsg = "DOM data broker service isn't available for mount point " + path; - LOG.warn(errMsg); - throw new RestconfDocumentedException(errMsg); + isMounted.remove(); + throw dataBrokerUnavailable(path); } // DELETE configuration - public CheckedFuture commitConfigurationDataDelete( - final YangInstanceIdentifier path) { - checkPreconditions(); - return deleteDataViaTransaction(this.domDataBroker.newReadWriteTransaction(), CONFIGURATION, path); + public FluentFuture commitConfigurationDataDelete(final YangInstanceIdentifier path) { + return deleteDataViaTransaction(domDataBroker.newReadWriteTransaction(), CONFIGURATION, path); } - public CheckedFuture commitConfigurationDataDelete( + public FluentFuture commitConfigurationDataDelete( final DOMMountPoint mountPoint, final YangInstanceIdentifier path) { final Optional domDataBrokerService = mountPoint.getService(DOMDataBroker.class); if (domDataBrokerService.isPresent()) { return deleteDataViaTransaction(domDataBrokerService.get().newReadWriteTransaction(), CONFIGURATION, path); } - final String errMsg = "DOM data broker service isn't available for mount point " + path; - LOG.warn(errMsg); - throw new RestconfDocumentedException(errMsg); + throw dataBrokerUnavailable(path); } // RPC - public CheckedFuture invokeRpc(final SchemaPath type, - final NormalizedNode input) { - checkPreconditions(); - if (this.rpcService == null) { + public ListenableFuture invokeRpc(final @NonNull QName type, + final @NonNull NormalizedNode input) { + if (rpcService == null) { throw new RestconfDocumentedException(Status.SERVICE_UNAVAILABLE); } LOG.trace("Invoke RPC {} with input: {}", type, input); - return this.rpcService.invokeRpc(type, input); + return rpcService.invokeRpc(type, input); } - public void registerToListenDataChanges(final LogicalDatastoreType datastore, final DataChangeScope scope, + public void registerToListenDataChanges(final LogicalDatastoreType datastore, final Scope scope, final ListenerAdapter listener) { - checkPreconditions(); - if (listener.isListening()) { return; } final YangInstanceIdentifier path = listener.getPath(); - DOMDataTreeChangeService changeService = (DOMDataTreeChangeService) - this.domDataBroker.getSupportedExtensions().get(DOMDataTreeChangeService.class); + DOMDataTreeChangeService changeService = domDataBroker.getExtensions() + .getInstance(DOMDataTreeChangeService.class); if (changeService == null) { throw new UnsupportedOperationException("DOMDataBroker does not support the DOMDataTreeChangeService" - + this.domDataBroker); + + domDataBroker); } DOMDataTreeIdentifier root = new DOMDataTreeIdentifier(datastore, path); ListenerRegistration registration = @@ -527,35 +529,30 @@ public class BrokerFacade { listener.setRegistration(registration); } - private NormalizedNode readDataViaTransaction(final DOMDataReadTransaction transaction, + private NormalizedNode readDataViaTransaction(final DOMDataTreeReadOperations transaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path) { return readDataViaTransaction(transaction, datastore, path, null); } - private NormalizedNode readDataViaTransaction(final DOMDataReadTransaction transaction, + private NormalizedNode readDataViaTransaction(final DOMDataTreeReadOperations transaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final String withDefa) { LOG.trace("Read {} via Restconf: {}", datastore.name(), path); try { - final Optional> optional = transaction.read(datastore, path).checkedGet(); - return !optional.isPresent() ? null : withDefa == null ? optional.get() : - prepareDataByParamWithDef(optional.get(), path, withDefa); - } catch (ReadFailedException e) { + final Optional optional = transaction.read(datastore, path).get(); + return optional.map(normalizedNode -> withDefa == null ? normalizedNode : + prepareDataByParamWithDef(normalizedNode, path, withDefa)).orElse(null); + } catch (InterruptedException e) { LOG.warn("Error reading {} from datastore {}", path, datastore.name(), e); - for (final RpcError error : e.getErrorList()) { - if (error.getErrorType() == RpcError.ErrorType.TRANSPORT - && error.getTag().equals(ErrorTag.RESOURCE_DENIED.getTagValue())) { - throw new RestconfDocumentedException( - error.getMessage(), - ErrorType.TRANSPORT, - ErrorTag.RESOURCE_DENIED_TRANSPORT, e); - } - } - throw new RestconfDocumentedException("Error reading data.", e, e.getErrorList()); + throw new RestconfDocumentedException("Error reading data.", e); + } catch (ExecutionException e) { + LOG.warn("Error reading {} from datastore {}", path, datastore.name(), e); + throw RestconfDocumentedException.decodeAndThrow("Error reading data.", Throwables.getCauseAs(e, + ReadFailedException.class)); } } - private NormalizedNode prepareDataByParamWithDef(final NormalizedNode result, + private NormalizedNode prepareDataByParamWithDef(final NormalizedNode result, final YangInstanceIdentifier path, final String withDefa) { boolean trim; switch (withDefa) { @@ -569,58 +566,58 @@ public class BrokerFacade { throw new RestconfDocumentedException("Bad value used with with-defaults parameter : " + withDefa); } - final SchemaContext ctx = ControllerContext.getInstance().getGlobalSchema(); + final EffectiveModelContext ctx = controllerContext.getGlobalSchema(); final DataSchemaContextTree baseSchemaCtxTree = DataSchemaContextTree.from(ctx); - final DataSchemaNode baseSchemaNode = baseSchemaCtxTree.getChild(path).getDataSchemaNode(); + final DataSchemaNode baseSchemaNode = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); if (result instanceof ContainerNode) { - final DataContainerNodeAttrBuilder builder = - Builders.containerBuilder((ContainerSchemaNode) baseSchemaNode); + final DataContainerNodeBuilder builder = + SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) baseSchemaNode); buildCont(builder, (ContainerNode) result, baseSchemaCtxTree, path, trim); return builder.build(); } - final DataContainerNodeAttrBuilder builder = - Builders.mapEntryBuilder((ListSchemaNode) baseSchemaNode); + final DataContainerNodeBuilder builder = + SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) baseSchemaNode); buildMapEntryBuilder(builder, (MapEntryNode) result, baseSchemaCtxTree, path, trim, ((ListSchemaNode) baseSchemaNode).getKeyDefinition()); return builder.build(); } private void buildMapEntryBuilder( - final DataContainerNodeAttrBuilder builder, + final DataContainerNodeBuilder builder, final MapEntryNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier actualPath, final boolean trim, final List keys) { - for (final DataContainerChild child : result.getValue()) { + for (final DataContainerChild child : result.body()) { final YangInstanceIdentifier path = actualPath.node(child.getIdentifier()); - final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(path).getDataSchemaNode(); + final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); if (child instanceof ContainerNode) { - final DataContainerNodeAttrBuilder childBuilder = - Builders.containerBuilder((ContainerSchemaNode) childSchema); + final DataContainerNodeBuilder childBuilder = + SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); buildCont(childBuilder, (ContainerNode) child, baseSchemaCtxTree, path, trim); builder.withChild(childBuilder.build()); } else if (child instanceof MapNode) { - final CollectionNodeBuilder childBuilder = - Builders.mapBuilder((ListSchemaNode) childSchema); + final CollectionNodeBuilder childBuilder = + SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim, ((ListSchemaNode) childSchema).getKeyDefinition()); builder.withChild(childBuilder.build()); } else if (child instanceof LeafNode) { final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null); - final Object nodeVal = ((LeafNode) child).getValue(); - final NormalizedNodeAttrBuilder> leafBuilder = - Builders.leafBuilder((LeafSchemaNode) childSchema); - if (keys.contains(child.getNodeType())) { - leafBuilder.withValue(((LeafNode) child).getValue()); + final Object nodeVal = child.body(); + final NormalizedNodeBuilder> leafBuilder = + SchemaAwareBuilders.leafBuilder((LeafSchemaNode) childSchema); + if (keys.contains(child.getIdentifier().getNodeType())) { + leafBuilder.withValue(child.body()); builder.withChild(leafBuilder.build()); } else { if (trim) { if (defaultVal == null || !defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(child.body()); builder.withChild(leafBuilder.build()); } } else { if (defaultVal != null && defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(child.body()); builder.withChild(leafBuilder.build()); } } @@ -629,49 +626,50 @@ public class BrokerFacade { } } - private void buildList(final CollectionNodeBuilder builder, final MapNode result, + private void buildList(final CollectionNodeBuilder builder, final MapNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier path, final boolean trim, final List keys) { - for (final MapEntryNode mapEntryNode : result.getValue()) { + for (final MapEntryNode mapEntryNode : result.body()) { final YangInstanceIdentifier actualNode = path.node(mapEntryNode.getIdentifier()); - final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(actualNode).getDataSchemaNode(); - final DataContainerNodeAttrBuilder mapEntryBuilder = - Builders.mapEntryBuilder((ListSchemaNode) childSchema); + final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(actualNode).orElseThrow() + .getDataSchemaNode(); + final DataContainerNodeBuilder mapEntryBuilder = + SchemaAwareBuilders.mapEntryBuilder((ListSchemaNode) childSchema); buildMapEntryBuilder(mapEntryBuilder, mapEntryNode, baseSchemaCtxTree, actualNode, trim, keys); builder.withChild(mapEntryBuilder.build()); } } - private void buildCont(final DataContainerNodeAttrBuilder builder, + private void buildCont(final DataContainerNodeBuilder builder, final ContainerNode result, final DataSchemaContextTree baseSchemaCtxTree, final YangInstanceIdentifier actualPath, final boolean trim) { - for (final DataContainerChild child : result.getValue()) { + for (final DataContainerChild child : result.body()) { final YangInstanceIdentifier path = actualPath.node(child.getIdentifier()); - final DataSchemaNode childSchema = baseSchemaCtxTree.getChild(path).getDataSchemaNode(); + final DataSchemaNode childSchema = baseSchemaCtxTree.findChild(path).orElseThrow().getDataSchemaNode(); if (child instanceof ContainerNode) { - final DataContainerNodeAttrBuilder builderChild = - Builders.containerBuilder((ContainerSchemaNode) childSchema); + final DataContainerNodeBuilder builderChild = + SchemaAwareBuilders.containerBuilder((ContainerSchemaNode) childSchema); buildCont(builderChild, result, baseSchemaCtxTree, actualPath, trim); builder.withChild(builderChild.build()); } else if (child instanceof MapNode) { - final CollectionNodeBuilder childBuilder = - Builders.mapBuilder((ListSchemaNode) childSchema); + final CollectionNodeBuilder childBuilder = + SchemaAwareBuilders.mapBuilder((ListSchemaNode) childSchema); buildList(childBuilder, (MapNode) child, baseSchemaCtxTree, path, trim, ((ListSchemaNode) childSchema).getKeyDefinition()); builder.withChild(childBuilder.build()); } else if (child instanceof LeafNode) { final Object defaultVal = ((LeafSchemaNode) childSchema).getType().getDefaultValue().orElse(null); - final Object nodeVal = ((LeafNode) child).getValue(); - final NormalizedNodeAttrBuilder> leafBuilder = - Builders.leafBuilder((LeafSchemaNode) childSchema); + final Object nodeVal = child.body(); + final NormalizedNodeBuilder> leafBuilder = + SchemaAwareBuilders.leafBuilder((LeafSchemaNode) childSchema); if (trim) { if (defaultVal == null || !defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(child.body()); builder.withChild(leafBuilder.build()); } } else { if (defaultVal != null && defaultVal.equals(nodeVal)) { - leafBuilder.withValue(((LeafNode) child).getValue()); + leafBuilder.withValue(child.body()); builder.withChild(leafBuilder.build()); } } @@ -682,28 +680,29 @@ public class BrokerFacade { /** * POST data and submit transaction {@link DOMDataReadWriteTransaction}. */ - private CheckedFuture postDataViaTransaction( - final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, - final String insert, final String point) { + private FluentFuture postDataViaTransaction( + final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, + final EffectiveModelContext schemaContext, final String insert, final String point) { LOG.trace("POST {} via Restconf: {} with payload {}", datastore.name(), path, payload); postData(rwTransaction, datastore, path, payload, schemaContext, insert, point); - return rwTransaction.submit(); + return rwTransaction.commit(); } /** * POST data and do NOT submit transaction {@link DOMDataReadWriteTransaction}. */ private void postDataWithinTransaction( - final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { + final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, + final EffectiveModelContext schemaContext) { LOG.trace("POST {} within Restconf Patch: {} with payload {}", datastore.name(), path, payload); postData(rwTransaction, datastore, path, payload, schemaContext, null, null); } - private void postData(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, - final SchemaContext schemaContext, final String insert, final String point) { + private void postData(final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, + final EffectiveModelContext schemaContext, final String insert, final String point) { if (insert == null) { makeNormalPost(rwTransaction, datastore, path, payload, schemaContext); return; @@ -714,9 +713,9 @@ public class BrokerFacade { switch (insert) { case "first": if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent().getParent()); - if (readList == null || readList.getValue().isEmpty()) { + final UserMapNode readList = + (UserMapNode) this.readConfigurationData(path.getParent().getParent()); + if (readList == null || readList.isEmpty()) { simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { rwTransaction.delete(datastore, path.getParent().getParent()); @@ -725,9 +724,9 @@ public class BrokerFacade { schemaContext); } } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { + final UserLeafSetNode readLeafList = + (UserLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.isEmpty()) { simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { rwTransaction.delete(datastore, path.getParent()); @@ -742,9 +741,9 @@ public class BrokerFacade { break; case "before": if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent().getParent()); - if (readList == null || readList.getValue().isEmpty()) { + final UserMapNode readList = + (UserMapNode) this.readConfigurationData(path.getParent().getParent()); + if (readList == null || readList.isEmpty()) { simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { insertWithPointListPost(rwTransaction, datastore, path, payload, schemaContext, point, @@ -752,9 +751,9 @@ public class BrokerFacade { true); } } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { + final UserLeafSetNode readLeafList = + (UserLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.isEmpty()) { simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { insertWithPointLeafListPost(rwTransaction, datastore, path, payload, schemaContext, point, @@ -764,9 +763,9 @@ public class BrokerFacade { break; case "after": if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent().getParent()); - if (readList == null || readList.getValue().isEmpty()) { + final UserMapNode readList = + (UserMapNode) this.readConfigurationData(path.getParent().getParent()); + if (readList == null || readList.isEmpty()) { simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { insertWithPointListPost(rwTransaction, datastore, path, payload, schemaContext, point, @@ -774,9 +773,9 @@ public class BrokerFacade { false); } } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { + final UserLeafSetNode readLeafList = + (UserLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.isEmpty()) { simplePostPut(rwTransaction, datastore, path, payload, schemaContext); } else { insertWithPointLeafListPost(rwTransaction, datastore, path, payload, schemaContext, point, @@ -791,15 +790,14 @@ public class BrokerFacade { } } - private static void insertWithPointLeafListPost(final DOMDataReadWriteTransaction rwTransaction, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, - final SchemaContext schemaContext, final String point, final OrderedLeafSetNode readLeafList, + private void insertWithPointLeafListPost(final DOMDataTreeReadWriteTransaction rwTransaction, + final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, + final SchemaContext schemaContext, final String point, final UserLeafSetNode readLeafList, final boolean before) { rwTransaction.delete(datastore, path.getParent().getParent()); - final InstanceIdentifierContext instanceIdentifier = - ControllerContext.getInstance().toInstanceIdentifier(point); + final InstanceIdentifierContext instanceIdentifier = controllerContext.toInstanceIdentifier(point); int lastItemPosition = 0; - for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { + for (final LeafSetEntryNode nodeChild : readLeafList.body()) { if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } @@ -809,10 +807,9 @@ public class BrokerFacade { lastItemPosition++; } int lastInsertedPosition = 0; - final NormalizedNode emptySubtree = - ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent()); + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent()); rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { + for (final LeafSetEntryNode nodeChild : readLeafList.body()) { if (lastInsertedPosition == lastItemPosition) { checkItemDoesNotExists(rwTransaction, datastore, path); simplePostPut(rwTransaction, datastore, path, payload, schemaContext); @@ -824,15 +821,14 @@ public class BrokerFacade { } } - private static void insertWithPointListPost(final DOMDataReadWriteTransaction rwTransaction, + private void insertWithPointListPost(final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, + final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, final String point, final MapNode readList, final boolean before) { rwTransaction.delete(datastore, path.getParent().getParent()); - final InstanceIdentifierContext instanceIdentifier = - ControllerContext.getInstance().toInstanceIdentifier(point); + final InstanceIdentifierContext instanceIdentifier = controllerContext.toInstanceIdentifier(point); int lastItemPosition = 0; - for (final MapEntryNode mapEntryNode : readList.getValue()) { + for (final MapEntryNode mapEntryNode : readList.body()) { if (mapEntryNode.getIdentifier() .equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; @@ -843,10 +839,9 @@ public class BrokerFacade { lastItemPosition++; } int lastInsertedPosition = 0; - final NormalizedNode emptySubtree = - ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent()); + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent().getParent()); rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - for (final MapEntryNode mapEntryNode : readList.getValue()) { + for (final MapEntryNode mapEntryNode : readList.body()) { if (lastInsertedPosition == lastItemPosition) { checkItemDoesNotExists(rwTransaction, datastore, path); simplePostPut(rwTransaction, datastore, path, payload, schemaContext); @@ -858,9 +853,10 @@ public class BrokerFacade { } } - private static DataSchemaNode checkListAndOrderedType(final SchemaContext ctx, final YangInstanceIdentifier path) { + private 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) { @@ -879,23 +875,27 @@ public class BrokerFacade { throw new RestconfDocumentedException("Insert parameter can be used only with list or leaf-list"); } - private static void makeNormalPost(final DOMDataReadWriteTransaction rwTransaction, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, + private void makeNormalPost(final DOMDataTreeReadWriteTransaction rwTransaction, + final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { - final Collection> children; + final Collection children; if (payload instanceof MapNode) { - children = ((MapNode) payload).getValue(); + children = ((MapNode) payload).body(); } else if (payload instanceof LeafSetNode) { - children = ((LeafSetNode) payload).getValue(); + children = ((LeafSetNode) payload).body(); } else { simplePostPut(rwTransaction, datastore, path, payload, schemaContext); return; } - final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); if (children.isEmpty()) { - rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); + if (isMounted != null && !isMounted.get()) { + + rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), + emptySubtree); + ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); + } return; } @@ -904,9 +904,12 @@ public class BrokerFacade { // ... now enqueue modifications. This relies on proper ordering of requests, i.e. these will not affect the // result of the existence checks... - rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); - for (final NormalizedNode child : children) { + if (isMounted != null && !isMounted.get()) { + + rwTransaction.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); + } + for (final NormalizedNode child : children) { // FIXME: we really want a create(YangInstanceIdentifier, NormalizedNode) method in the transaction, // as that would allow us to skip the existence checks rwTransaction.put(datastore, path.node(child.getIdentifier()), child); @@ -934,22 +937,27 @@ public class BrokerFacade { } } - private static void simplePostPut(final DOMDataReadWriteTransaction rwTransaction, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, + private void simplePostPut(final DOMDataTreeReadWriteTransaction rwTransaction, + final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { checkItemDoesNotExists(rwTransaction, datastore, path); - ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); + if (isMounted != null && !isMounted.get()) { + ensureParentsByMerge(datastore, path, rwTransaction, schemaContext); + } rwTransaction.put(datastore, path, payload); } - private static boolean doesItemExist(final DOMDataReadWriteTransaction rwTransaction, + private static boolean doesItemExist(final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path) { try { - return rwTransaction.exists(store, path).checkedGet(); - } catch (ReadFailedException e) { + return rwTransaction.exists(store, path).get(); + } catch (InterruptedException e) { + rwTransaction.cancel(); + throw new RestconfDocumentedException("Could not determine the existence of path " + path, e); + } catch (ExecutionException e) { rwTransaction.cancel(); - throw new RestconfDocumentedException("Could not determine the existence of path " + path, - e, e.getErrorList()); + throw RestconfDocumentedException.decodeAndThrow("Could not determine the existence of path " + path, + Throwables.getCauseAs(e, ReadFailedException.class)); } } @@ -959,11 +967,10 @@ public class BrokerFacade { * @param store Used datastore * @param path Path to item to verify its existence */ - private static void checkItemExists(final DOMDataReadWriteTransaction rwTransaction, + private static void checkItemExists(final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path) { if (!doesItemExist(rwTransaction, store, path)) { - final String errMsg = "Operation via Restconf was not executed because data does not exist"; - LOG.trace("{}:{}", errMsg, path); + LOG.trace("Operation via Restconf was not executed because data at {} does not exist", path); rwTransaction.cancel(); throw new RestconfDocumentedException("Data does not exist for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_MISSING); @@ -976,11 +983,10 @@ public class BrokerFacade { * @param store Used datastore * @param path Path to item to verify its existence */ - private static void checkItemDoesNotExists(final DOMDataReadWriteTransaction rwTransaction, + private static void checkItemDoesNotExists(final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path) { if (doesItemExist(rwTransaction, store, path)) { - final String errMsg = "Operation via Restconf was not executed because data already exists"; - LOG.trace("{}:{}", errMsg, path); + LOG.trace("Operation via Restconf was not executed because data at {} already exists", path); rwTransaction.cancel(); throw new RestconfDocumentedException("Data already exists for path: " + path, ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS); @@ -995,29 +1001,30 @@ public class BrokerFacade { * @param insert * insert */ - private CheckedFuture putDataViaTransaction( - final DOMDataReadWriteTransaction readWriteTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, - final String insert, final String point) { + private FluentFuture putDataViaTransaction( + final DOMDataTreeReadWriteTransaction readWriteTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, + final EffectiveModelContext schemaContext, final String insert, final String point) { LOG.trace("Put {} via Restconf: {} with payload {}", datastore.name(), path, payload); putData(readWriteTransaction, datastore, path, payload, schemaContext, insert, point); - return readWriteTransaction.submit(); + return readWriteTransaction.commit(); } /** * PUT data and do NOT submit {@link DOMDataReadWriteTransaction}. */ private void putDataWithinTransaction( - final DOMDataReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { + final DOMDataTreeReadWriteTransaction writeTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, + final EffectiveModelContext schemaContext) { LOG.trace("Put {} within Restconf Patch: {} with payload {}", datastore.name(), path, payload); putData(writeTransaction, datastore, path, payload, schemaContext, null, null); } // FIXME: This is doing correct put for container and list children, not sure if this will work for choice case - private void putData(final DOMDataReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, - final String insert, final String point) { + private void putData(final DOMDataTreeReadWriteTransaction rwTransaction, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, + final EffectiveModelContext schemaContext, final String insert, final String point) { if (insert == null) { makePut(rwTransaction, datastore, path, payload, schemaContext); return; @@ -1028,9 +1035,8 @@ public class BrokerFacade { switch (insert) { case "first": if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent()); - if (readList == null || readList.getValue().isEmpty()) { + final UserMapNode readList = (UserMapNode) this.readConfigurationData(path.getParent()); + if (readList == null || readList.isEmpty()) { simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { rwTransaction.delete(datastore, path.getParent()); @@ -1038,9 +1044,9 @@ public class BrokerFacade { makePut(rwTransaction, datastore, path.getParent(), readList, schemaContext); } } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { + final UserLeafSetNode readLeafList = + (UserLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.isEmpty()) { simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { rwTransaction.delete(datastore, path.getParent()); @@ -1055,18 +1061,17 @@ public class BrokerFacade { break; case "before": if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent()); - if (readList == null || readList.getValue().isEmpty()) { + final UserMapNode readList = (UserMapNode) this.readConfigurationData(path.getParent()); + if (readList == null || readList.isEmpty()) { simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { insertWithPointListPut(rwTransaction, datastore, path, payload, schemaContext, point, readList, true); } } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { + final UserLeafSetNode readLeafList = + (UserLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.isEmpty()) { simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { insertWithPointLeafListPut(rwTransaction, datastore, path, payload, schemaContext, point, @@ -1076,18 +1081,17 @@ public class BrokerFacade { break; case "after": if (schemaNode instanceof ListSchemaNode) { - final OrderedMapNode readList = - (OrderedMapNode) this.readConfigurationData(path.getParent()); - if (readList == null || readList.getValue().isEmpty()) { + final UserMapNode readList = (UserMapNode) this.readConfigurationData(path.getParent()); + if (readList == null || readList.isEmpty()) { simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { insertWithPointListPut(rwTransaction, datastore, path, payload, schemaContext, point, readList, false); } } else { - final OrderedLeafSetNode readLeafList = - (OrderedLeafSetNode) readConfigurationData(path.getParent()); - if (readLeafList == null || readLeafList.getValue().isEmpty()) { + final UserLeafSetNode readLeafList = + (UserLeafSetNode) readConfigurationData(path.getParent()); + if (readLeafList == null || readLeafList.isEmpty()) { simplePut(datastore, path, rwTransaction, schemaContext, payload); } else { insertWithPointLeafListPut(rwTransaction, datastore, path, payload, schemaContext, point, @@ -1102,15 +1106,14 @@ public class BrokerFacade { } } - private static void insertWithPointLeafListPut(final DOMDataWriteTransaction tx, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, - final SchemaContext schemaContext, final String point, final OrderedLeafSetNode readLeafList, + private void insertWithPointLeafListPut(final DOMDataTreeWriteTransaction tx, + final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, + final SchemaContext schemaContext, final String point, final UserLeafSetNode readLeafList, final boolean before) { tx.delete(datastore, path.getParent()); - final InstanceIdentifierContext instanceIdentifier = - ControllerContext.getInstance().toInstanceIdentifier(point); + final InstanceIdentifierContext instanceIdentifier = controllerContext.toInstanceIdentifier(point); int index1 = 0; - for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { + for (final LeafSetEntryNode nodeChild : readLeafList.body()) { if (nodeChild.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } @@ -1120,10 +1123,9 @@ public class BrokerFacade { index1++; } int index2 = 0; - final NormalizedNode emptySubtree = - ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); tx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - for (final LeafSetEntryNode nodeChild : readLeafList.getValue()) { + for (final LeafSetEntryNode nodeChild : readLeafList.body()) { if (index2 == index1) { simplePut(datastore, path, tx, schemaContext, payload); } @@ -1133,14 +1135,13 @@ public class BrokerFacade { } } - private static void insertWithPointListPut(final DOMDataWriteTransaction tx, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, - final String point, final OrderedMapNode readList, final boolean before) { + private void insertWithPointListPut(final DOMDataTreeWriteTransaction tx, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext, + final String point, final UserMapNode readList, final boolean before) { tx.delete(datastore, path.getParent()); - final InstanceIdentifierContext instanceIdentifier = - ControllerContext.getInstance().toInstanceIdentifier(point); + final InstanceIdentifierContext instanceIdentifier = controllerContext.toInstanceIdentifier(point); int index1 = 0; - for (final MapEntryNode mapEntryNode : readList.getValue()) { + for (final MapEntryNode mapEntryNode : readList.body()) { if (mapEntryNode.getIdentifier().equals(instanceIdentifier.getInstanceIdentifier().getLastPathArgument())) { break; } @@ -1150,10 +1151,9 @@ public class BrokerFacade { index1++; } int index2 = 0; - final NormalizedNode emptySubtree = - ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path.getParent()); tx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - for (final MapEntryNode mapEntryNode : readList.getValue()) { + for (final MapEntryNode mapEntryNode : readList.body()) { if (index2 == index1) { simplePut(datastore, path, tx, schemaContext, payload); } @@ -1163,13 +1163,15 @@ public class BrokerFacade { } } - private static void makePut(final DOMDataWriteTransaction tx, final LogicalDatastoreType datastore, - final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { + private void makePut(final DOMDataTreeWriteTransaction tx, final LogicalDatastoreType datastore, + final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { if (payload instanceof MapNode) { - final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); - tx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); - ensureParentsByMerge(datastore, path, tx, schemaContext); - for (final MapEntryNode child : ((MapNode) payload).getValue()) { + final NormalizedNode emptySubtree = ImmutableNodes.fromInstanceId(schemaContext, path); + if (isMounted != null && !isMounted.get()) { + tx.merge(datastore, YangInstanceIdentifier.create(emptySubtree.getIdentifier()), emptySubtree); + ensureParentsByMerge(datastore, path, tx, schemaContext); + } + for (final MapEntryNode child : ((MapNode) payload).body()) { final YangInstanceIdentifier childPath = path.node(child.getIdentifier()); tx.put(datastore, childPath, child); } @@ -1178,29 +1180,31 @@ public class BrokerFacade { } } - private static void simplePut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path, - final DOMDataWriteTransaction tx, final SchemaContext schemaContext, final NormalizedNode payload) { - ensureParentsByMerge(datastore, path, tx, schemaContext); + private void simplePut(final LogicalDatastoreType datastore, final YangInstanceIdentifier path, + final DOMDataTreeWriteTransaction tx, final SchemaContext schemaContext, final NormalizedNode payload) { + if (isMounted != null && !isMounted.get()) { + ensureParentsByMerge(datastore, path, tx, schemaContext); + } tx.put(datastore, path, payload); } - private static CheckedFuture deleteDataViaTransaction( - final DOMDataReadWriteTransaction readWriteTransaction, final LogicalDatastoreType datastore, + private static FluentFuture deleteDataViaTransaction( + final DOMDataTreeReadWriteTransaction readWriteTransaction, final LogicalDatastoreType datastore, final YangInstanceIdentifier path) { LOG.trace("Delete {} via Restconf: {}", datastore.name(), path); checkItemExists(readWriteTransaction, datastore, path); readWriteTransaction.delete(datastore, path); - return readWriteTransaction.submit(); + return readWriteTransaction.commit(); } - private static void deleteDataWithinTransaction(final DOMDataWriteTransaction tx, + private static void deleteDataWithinTransaction(final DOMDataTreeWriteTransaction tx, final LogicalDatastoreType datastore, final YangInstanceIdentifier path) { LOG.trace("Delete {} within Restconf Patch: {}", datastore.name(), path); tx.delete(datastore, path); } - private static void mergeDataWithinTransaction(final DOMDataWriteTransaction tx, - final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, + private static void mergeDataWithinTransaction(final DOMDataTreeWriteTransaction tx, + final LogicalDatastoreType datastore, final YangInstanceIdentifier path, final NormalizedNode payload, final SchemaContext schemaContext) { LOG.trace("Merge {} within Restconf Patch: {} with payload {}", datastore.name(), path, payload); ensureParentsByMerge(datastore, path, tx, schemaContext); @@ -1210,26 +1214,20 @@ public class BrokerFacade { tx.merge(datastore, path, payload); } - public void setDomDataBroker(final DOMDataBroker domDataBroker) { - this.domDataBroker = domDataBroker; - } - public void registerToListenNotification(final NotificationListenerAdapter listener) { - checkPreconditions(); - if (listener.isListening()) { return; } final SchemaPath path = listener.getSchemaPath(); - final ListenerRegistration registration = this.domNotification - .registerNotificationListener(listener, path); + final ListenerRegistration registration = domNotification + .registerNotificationListener(listener, Absolute.of(ImmutableList.copyOf(path.getPathFromRoot()))); listener.setRegistration(registration); } private static void ensureParentsByMerge(final LogicalDatastoreType store, - final YangInstanceIdentifier normalizedPath, final DOMDataWriteTransaction tx, + final YangInstanceIdentifier normalizedPath, final DOMDataTreeWriteTransaction tx, final SchemaContext schemaContext) { final List normalizedPathWithoutChildArgs = new ArrayList<>(); YangInstanceIdentifier rootNormalizedPath = null; @@ -1251,18 +1249,27 @@ public class BrokerFacade { return; } - Preconditions.checkArgument(rootNormalizedPath != null, "Empty path received"); + checkArgument(rootNormalizedPath != null, "Empty path received"); + tx.merge(store, rootNormalizedPath, ImmutableNodes.fromInstanceId(schemaContext, + YangInstanceIdentifier.create(normalizedPathWithoutChildArgs))); + } + + private static RestconfDocumentedException dataBrokerUnavailable(final YangInstanceIdentifier path) { + LOG.warn("DOM data broker service is not available for mount point {}", path); + return new RestconfDocumentedException("DOM data broker service is not available for mount point " + path); + } - final NormalizedNode parentStructure = ImmutableNodes.fromInstanceId(schemaContext, - YangInstanceIdentifier.create(normalizedPathWithoutChildArgs)); - tx.merge(store, rootNormalizedPath, parentStructure); + private static EffectiveModelContext modelContext(final DOMMountPoint mountPoint) { + return mountPoint.getService(DOMSchemaService.class) + .flatMap(svc -> Optional.ofNullable(svc.getGlobalContext())) + .orElse(null); } private static final class PatchStatusContextHelper { PatchStatusContext status; public PatchStatusContext getStatus() { - return this.status; + return status; } public void setStatus(final PatchStatusContext status) {