Move RemoteDeviceId
[netconf.git] / netconf / sal-netconf-connector / src / main / java / org / opendaylight / netconf / sal / connect / netconf / sal / AbstractNetconfDataTreeService.java
index 22c2f2768400bf604c28b18de37616df74a05b7d..863d1ed28969e805fc8c3e1f98c35184940bed92 100644 (file)
@@ -23,13 +23,13 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
-import org.opendaylight.netconf.api.ModifyAction;
+import org.opendaylight.netconf.api.EffectiveOperation;
 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
+import org.opendaylight.netconf.sal.connect.api.RemoteDeviceId;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceServices.Rpcs;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfBaseOps;
 import org.opendaylight.netconf.sal.connect.netconf.util.NetconfRpcFutureCallback;
-import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yangtools.rfc8528.data.api.MountPointContext;
 import org.opendaylight.yangtools.yang.common.ErrorSeverity;
 import org.opendaylight.yangtools.yang.common.RpcError;
@@ -39,10 +39,11 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeService {
+public abstract sealed class AbstractNetconfDataTreeService implements NetconfDataTreeService {
     private static final class Candidate extends AbstractNetconfDataTreeService {
-        Candidate(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport) {
-            super(id, netconfOps, rollbackSupport);
+        Candidate(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport,
+                final boolean lockDatastore) {
+            super(id, netconfOps, rollbackSupport, lockDatastore);
         }
 
         /**
@@ -66,7 +67,7 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
 
         @Override
         ListenableFuture<? extends DOMRpcResult> editConfig(final DataContainerChild editStructure,
-                final ModifyAction defaultOperation) {
+                final EffectiveOperation defaultOperation) {
             final NetconfRpcFutureCallback callback = new NetconfRpcFutureCallback("Edit candidate", id);
             return defaultOperation == null ? netconfOps.editConfigCandidate(callback, editStructure, rollbackSupport)
                 : netconfOps.editConfigCandidate(callback, editStructure, defaultOperation, rollbackSupport);
@@ -74,8 +75,9 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
     }
 
     private static final class Running extends AbstractNetconfDataTreeService {
-        Running(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport) {
-            super(id, netconfOps, rollbackSupport);
+        Running(final RemoteDeviceId id, final NetconfBaseOps netconfOps, final boolean rollbackSupport,
+                final boolean lockDatastore) {
+            super(id, netconfOps, rollbackSupport, lockDatastore);
         }
 
         @Override
@@ -84,6 +86,12 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
             return RPC_SUCCESS;
         }
 
+        @Override
+        public ListenableFuture<DOMRpcResult> commit() {
+            // No candidate, hence we commit immediately
+            return RPC_SUCCESS;
+        }
+
         @Override
         ListenableFuture<? extends DOMRpcResult> lockSingle() {
             return netconfOps.lockRunning(new NetconfRpcFutureCallback("Lock running", id));
@@ -96,7 +104,7 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
 
         @Override
         ListenableFuture<? extends DOMRpcResult> editConfig(final DataContainerChild editStructure,
-                final ModifyAction defaultOperation) {
+                final EffectiveOperation defaultOperation) {
             final NetconfRpcFutureCallback callback = new NetconfRpcFutureCallback("Edit running", id);
             return defaultOperation == null ? netconfOps.editConfigRunning(callback, editStructure, rollbackSupport)
                 : netconfOps.editConfigRunning(callback, editStructure, defaultOperation, rollbackSupport);
@@ -108,10 +116,10 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
         private final Running running;
 
         CandidateWithRunning(final RemoteDeviceId id, final NetconfBaseOps netconfOps,
-                final boolean rollbackSupport) {
-            super(id, netconfOps, rollbackSupport);
-            candidate = new Candidate(id, netconfOps, rollbackSupport);
-            running = new Running(id, netconfOps, rollbackSupport);
+                final boolean rollbackSupport, final boolean lockDatastore) {
+            super(id, netconfOps, rollbackSupport, lockDatastore);
+            candidate = new Candidate(id, netconfOps, rollbackSupport, lockDatastore);
+            running = new Running(id, netconfOps, rollbackSupport, lockDatastore);
         }
 
         @Override
@@ -136,7 +144,7 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
 
         @Override
         ListenableFuture<? extends DOMRpcResult> editConfig(final DataContainerChild editStructure,
-                final ModifyAction defaultOperation) {
+                final EffectiveOperation defaultOperation) {
             return candidate.editConfig(editStructure, defaultOperation);
         }
     }
@@ -149,48 +157,47 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
     final NetconfBaseOps netconfOps;
     final boolean rollbackSupport;
 
-    // FIXME: what do we do with locks acquired before this got flipped?
-    private volatile boolean isLockAllowed = true;
+    private final boolean lockDatastore;
 
     AbstractNetconfDataTreeService(final RemoteDeviceId id, final NetconfBaseOps netconfOps,
-            final boolean rollbackSupport) {
+            final boolean rollbackSupport, final boolean lockDatastore) {
         this.id = requireNonNull(id);
         this.netconfOps = requireNonNull(netconfOps);
         this.rollbackSupport = rollbackSupport;
+        this.lockDatastore = lockDatastore;
     }
 
     public static @NonNull AbstractNetconfDataTreeService of(final RemoteDeviceId id,
             final MountPointContext mountContext, final Rpcs rpcs,
-            final NetconfSessionPreferences sessionPreferences) {
+            final NetconfSessionPreferences sessionPreferences, final boolean lockDatastore) {
         final var netconfOps = new NetconfBaseOps(rpcs, mountContext);
         final boolean rollbackSupport = sessionPreferences.isRollbackSupported();
 
         // Examine preferences and decide which implementation to use
         if (sessionPreferences.isCandidateSupported()) {
             return sessionPreferences.isRunningWritable()
-                ? new CandidateWithRunning(id, netconfOps, rollbackSupport)
-                    : new Candidate(id, netconfOps, rollbackSupport);
+                ? new CandidateWithRunning(id, netconfOps, rollbackSupport, lockDatastore)
+                    : new Candidate(id, netconfOps, rollbackSupport, lockDatastore);
         } else if (sessionPreferences.isRunningWritable()) {
-            return new Running(id, netconfOps, rollbackSupport);
+            return new Running(id, netconfOps, rollbackSupport, lockDatastore);
         } else {
-            throw new IllegalArgumentException("Device " + id.getName() + " has advertised neither :writable-running "
-                + "nor :candidate capability. Failed to establish session, as at least one of these must be "
-                + "advertised.");
+            throw new IllegalArgumentException("Device " + id.name() + " has advertised neither :writable-running nor "
+                + ":candidate capability. Failed to establish session, as at least one of these must be advertised.");
         }
     }
 
     @Override
     public synchronized ListenableFuture<DOMRpcResult> lock() {
-        if (!isLockAllowed) {
+        if (!lockDatastore) {
             LOG.trace("Lock is not allowed by device configuration, ignoring lock results: {}", id);
             return RPC_SUCCESS;
         }
 
         final ListenableFuture<DOMRpcResult> result = mergeFutures(lockImpl());
-        Futures.addCallback(result, new FutureCallback<DOMRpcResult>() {
+        Futures.addCallback(result, new FutureCallback<>() {
             @Override
             public void onSuccess(final DOMRpcResult result) {
-                final var errors = result.getErrors();
+                final var errors = result.errors();
                 if (errors.isEmpty()) {
                     LOG.debug("{}: Lock successful.", id);
                     return;
@@ -220,17 +227,16 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
 
     @Override
     public synchronized ListenableFuture<DOMRpcResult> unlock() {
-        // FIXME: deal with lock with lifecycle?
-        if (!isLockAllowed) {
+        if (!lockDatastore) {
             LOG.trace("Unlock is not allowed: {}", id);
             return RPC_SUCCESS;
         }
 
         final ListenableFuture<DOMRpcResult> result = mergeFutures(unlockImpl());
-        Futures.addCallback(result, new FutureCallback<DOMRpcResult>() {
+        Futures.addCallback(result, new FutureCallback<>() {
             @Override
             public void onSuccess(final DOMRpcResult result) {
-                final var errors = result.getErrors();
+                final var errors = result.errors();
                 if (errors.isEmpty()) {
                     LOG.debug("{}: Unlock successful.", id);
                     return;
@@ -280,30 +286,33 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
     @Override
     public synchronized ListenableFuture<? extends DOMRpcResult> merge(final LogicalDatastoreType store,
             final YangInstanceIdentifier path, final NormalizedNode data,
-            final Optional<ModifyAction> defaultOperation) {
+            final Optional<EffectiveOperation> defaultOperation) {
         checkEditable(store);
         return editConfig(
-            netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(ModifyAction.MERGE), path),
+            netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(EffectiveOperation.MERGE),
+                path),
             defaultOperation.orElse(null));
     }
 
     @Override
     public synchronized ListenableFuture<? extends DOMRpcResult> replace(final LogicalDatastoreType store,
             final YangInstanceIdentifier path, final NormalizedNode data,
-            final Optional<ModifyAction> defaultOperation) {
+            final Optional<EffectiveOperation> defaultOperation) {
         checkEditable(store);
         return editConfig(
-            netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(ModifyAction.REPLACE), path),
+            netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(EffectiveOperation.REPLACE),
+                path),
             defaultOperation.orElse(null));
     }
 
     @Override
     public synchronized ListenableFuture<? extends DOMRpcResult> create(final LogicalDatastoreType store,
             final YangInstanceIdentifier path, final NormalizedNode data,
-            final Optional<ModifyAction> defaultOperation) {
+            final Optional<EffectiveOperation> defaultOperation) {
         checkEditable(store);
         return editConfig(
-            netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(ModifyAction.CREATE), path),
+            netconfOps.createEditConfigStructure(Optional.ofNullable(data), Optional.of(EffectiveOperation.CREATE),
+                path),
             defaultOperation.orElse(null));
     }
 
@@ -311,14 +320,14 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
     public synchronized ListenableFuture<? extends DOMRpcResult> delete(final LogicalDatastoreType store,
             final YangInstanceIdentifier path) {
         return editConfig(netconfOps.createEditConfigStructure(Optional.empty(),
-                Optional.of(ModifyAction.DELETE), path), null);
+                Optional.of(EffectiveOperation.DELETE), path), null);
     }
 
     @Override
     public synchronized ListenableFuture<? extends DOMRpcResult> remove(final LogicalDatastoreType store,
             final YangInstanceIdentifier path) {
         return editConfig(netconfOps.createEditConfigStructure(Optional.empty(),
-                Optional.of(ModifyAction.REMOVE), path), null);
+                Optional.of(EffectiveOperation.REMOVE), path), null);
     }
 
     @Override
@@ -331,12 +340,8 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
         return id;
     }
 
-    final void setLockAllowed(final boolean isLockAllowedOrig) {
-        isLockAllowed = isLockAllowedOrig;
-    }
-
     abstract ListenableFuture<? extends DOMRpcResult> editConfig(DataContainerChild editStructure,
-        @Nullable ModifyAction defaultOperation);
+        @Nullable EffectiveOperation defaultOperation);
 
     private static void checkEditable(final LogicalDatastoreType store) {
         checkArgument(store == LogicalDatastoreType.CONFIGURATION, "Can only edit configuration data, not %s", store);
@@ -353,7 +358,7 @@ public abstract class AbstractNetconfDataTreeService implements NetconfDataTreeS
 
             final var builder = ImmutableList.<RpcError>builder();
             for (ListenableFuture<? extends DOMRpcResult> future : futures) {
-                builder.addAll(Futures.getDone(future).getErrors());
+                builder.addAll(Futures.getDone(future).errors());
             }
             return new DefaultDOMRpcResult(null, builder.build());
         }, MoreExecutors.directExecutor());