Simplify NetconfOperationChainedExecution 87/113087/2
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 10 Aug 2024 10:42:11 +0000 (12:42 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 10 Aug 2024 14:36:50 +0000 (16:36 +0200)
There is only a single implementation that reports being a termination
point. Rather than having these checks, just use 'null' to indicate
there is no subsequent operation.

Change-Id: I0c46ea596aec4d18ed8afa0bd39d461a4ae64c52
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
14 files changed:
netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/customrpc/SettableRpc.java
netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/monitoring/Get.java
netconf/tools/netconf-testtool/src/main/java/org/opendaylight/netconf/test/tool/rpchandler/SettableRpc.java
plugins/netconf-server-mdsal/src/test/java/org/opendaylight/netconf/server/mdsal/operations/AbstractNetconfOperationTest.java
plugins/netconf-server-mdsal/src/test/java/org/opendaylight/netconf/server/mdsal/operations/RuntimeRpcTest.java
protocol/netconf-server/src/main/java/org/opendaylight/netconf/server/api/operations/AbstractLastNetconfOperation.java
protocol/netconf-server/src/main/java/org/opendaylight/netconf/server/api/operations/AbstractNetconfOperation.java
protocol/netconf-server/src/main/java/org/opendaylight/netconf/server/api/operations/NetconfOperation.java
protocol/netconf-server/src/main/java/org/opendaylight/netconf/server/api/operations/NetconfOperationChainedExecution.java
protocol/netconf-server/src/main/java/org/opendaylight/netconf/server/mapping/operations/DefaultStartExi.java
protocol/netconf-server/src/main/java/org/opendaylight/netconf/server/osgi/NetconfOperationRouterImpl.java
protocol/netconf-server/src/test/java/org/opendaylight/netconf/server/ConcurrentClientsTest.java
protocol/netconf-server/src/test/java/org/opendaylight/netconf/server/api/operations/AbstractLastNetconfOperationTest.java
protocol/netconf-server/src/test/java/org/opendaylight/netconf/server/osgi/NetconfOperationRouterImplTest.java

index 49c922148a43fe0b6f1d181e56c805d8c697e7e2..8a282d18a1e57a76cd292ea7c0b0e80bf3cff25d 100644 (file)
@@ -50,11 +50,11 @@ final class SettableRpc implements NetconfOperation {
             checkForError(document);
             document.getDocumentElement().setAttribute(XmlNetconfConstants.MESSAGE_ID, msgId);
             return document;
-        } else if (subsequentOperation.isExecutionTermination()) {
+        } else if (subsequentOperation != null) {
+            return subsequentOperation.execute(requestMessage);
+        } else {
             throw new DocumentedException("Mapping not found " + XmlUtil.toString(requestMessage),
                     ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED, ErrorSeverity.ERROR);
-        } else {
-            return subsequentOperation.execute(requestMessage);
         }
     }
 
index 8811302914af715f5825d80a48b9a8d613a6d395..0a623939cbc719d45d5156ac92fb58a197fee1c7 100644 (file)
@@ -50,7 +50,7 @@ public class Get extends AbstractNetconfOperation {
     @Override
     public Document handle(final Document requestMessage, final NetconfOperationChainedExecution subsequentOperation)
             throws DocumentedException {
-        if (subsequentOperation.isExecutionTermination()) {
+        if (subsequentOperation == null) {
             throw new DocumentedException(String.format("Subsequent netconf operation expected by %s", this),
                 ErrorType.APPLICATION, ErrorTag.OPERATION_FAILED, ErrorSeverity.ERROR);
         }
index d4ef01240011114f858a09de659105c4cbb240f2..1570af0d26f0d248b125d26c9686925e0831cd5f 100644 (file)
@@ -49,11 +49,11 @@ class SettableRpc implements NetconfOperation {
             checkForError(document);
             document.getDocumentElement().setAttribute(XmlNetconfConstants.MESSAGE_ID, msgId);
             return document;
-        } else if (subsequentOperation.isExecutionTermination()) {
-            throw new DocumentedException("Mapping not found " + XmlUtil.toString(requestMessage),
-                    ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED, ErrorSeverity.ERROR);
-        } else {
+        } else if (subsequentOperation != null) {
             return subsequentOperation.execute(requestMessage);
+        } else {
+            throw new DocumentedException("Mapping not found " + XmlUtil.toString(requestMessage),
+                ErrorType.APPLICATION, ErrorTag.OPERATION_NOT_SUPPORTED, ErrorSeverity.ERROR);
         }
     }
 
index 9c450ad304ec0f7b0c5791bca5122f3098563831..3dc3280806ef4248861ca20087ae55eac4388dbe 100644 (file)
@@ -42,7 +42,6 @@ import org.opendaylight.mdsal.dom.spi.store.DOMStore;
 import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataStoreFactory;
 import org.opendaylight.netconf.api.xml.XmlUtil;
 import org.opendaylight.netconf.server.api.operations.NetconfOperation;
-import org.opendaylight.netconf.server.api.operations.NetconfOperationChainedExecution;
 import org.opendaylight.netconf.server.mdsal.CurrentSchemaContext;
 import org.opendaylight.netconf.server.mdsal.TransactionProvider;
 import org.opendaylight.netconf.test.util.NetconfXmlUnitRecursiveQualifier;
@@ -210,7 +209,7 @@ abstract class AbstractNetconfOperationTest {
     }
 
     protected static Document executeOperation(final NetconfOperation op, final Document request) throws Exception {
-        final Document response = op.handle(request, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+        final Document response = op.handle(request, null);
         LOG.debug("Got response {}", response);
         return response;
     }
index 4e9b2618cabc74157eebac011d8cd2f980000767..8501d3c83bcb4f9b6b12f66aba5e80c94a1d0f8e 100644 (file)
@@ -46,7 +46,6 @@ import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
 import org.opendaylight.netconf.api.DocumentedException;
 import org.opendaylight.netconf.api.xml.XmlUtil;
 import org.opendaylight.netconf.server.api.operations.HandlingPriority;
-import org.opendaylight.netconf.server.api.operations.NetconfOperationChainedExecution;
 import org.opendaylight.netconf.server.mdsal.CurrentSchemaContext;
 import org.opendaylight.netconf.test.util.XmlFileLoader;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.SessionIdType;
@@ -189,7 +188,7 @@ class RuntimeRpcTest {
         final HandlingPriority priority = rpc.canHandle(rpcDocument);
         assertNotNull(priority);
 
-        final Document response = rpc.handle(rpcDocument, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+        final Document response = rpc.handle(rpcDocument, null);
 
         verifyResponse(response, RPC_REPLY_OK);
     }
@@ -203,7 +202,7 @@ class RuntimeRpcTest {
         final HandlingPriority priority = rpc.canHandle(rpcDocument);
         assertNotNull(priority);
 
-        final Document response = rpc.handle(rpcDocument, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+        final Document response = rpc.handle(rpcDocument, null);
         verifyResponse(response, XmlFileLoader.xmlFileToDocument("messages/mapping/rpcs/rpc-nonvoid-control.xml"));
     }
 
@@ -216,7 +215,7 @@ class RuntimeRpcTest {
         final HandlingPriority priority = rpc.canHandle(rpcDocument);
         assertNotNull(priority);
 
-        final Document response = rpc.handle(rpcDocument, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+        final Document response = rpc.handle(rpcDocument, null);
         verifyResponse(response, XmlFileLoader.xmlFileToDocument("messages/mapping/rpcs/rpc-container-control.xml"));
     }
 
@@ -229,8 +228,7 @@ class RuntimeRpcTest {
         final HandlingPriority priority = rpc.canHandle(rpcDocument);
         assertNotNull(priority);
 
-        final DocumentedException e = assertThrows(DocumentedException.class,
-                () -> rpc.handle(rpcDocument, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT));
+        final DocumentedException e = assertThrows(DocumentedException.class, () -> rpc.handle(rpcDocument, null));
 
         assertEquals(e.getErrorSeverity(), ErrorSeverity.ERROR);
         assertEquals(e.getErrorTag(), ErrorTag.OPERATION_FAILED);
@@ -245,7 +243,7 @@ class RuntimeRpcTest {
         final HandlingPriority priority = rpc.canHandle(rpcDocument);
         assertNotNull(priority);
 
-        final Document response = rpc.handle(rpcDocument, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT);
+        final Document response = rpc.handle(rpcDocument, null);
 
         verifyResponse(response, RPC_REPLY_OK);
     }
@@ -255,8 +253,7 @@ class RuntimeRpcTest {
         final RuntimeRpc rpc = new RuntimeRpc(SESSION_ID_FOR_REPORTING, currentSchemaContext, RPC_SERVICE_VOID_INVOKER);
         final Document rpcDocument = XmlFileLoader.xmlFileToDocument("messages/mapping/rpcs/rpc-bad-namespace.xml");
 
-        final DocumentedException e = assertThrows(DocumentedException.class,
-                () -> rpc.handle(rpcDocument, NetconfOperationChainedExecution.EXECUTION_TERMINATION_POINT));
+        final DocumentedException e = assertThrows(DocumentedException.class, () -> rpc.handle(rpcDocument, null));
 
         assertEquals(e.getErrorSeverity(), ErrorSeverity.ERROR);
         assertEquals(e.getErrorTag(), ErrorTag.BAD_ELEMENT);
index 3551d674d6b502e0de54d9d5b490ecafc4bf0239..0b8fb6aab19aa8a31c2f35e725e12f8d6cf671d0 100644 (file)
@@ -24,12 +24,11 @@ public abstract class AbstractLastNetconfOperation extends AbstractNetconfOperat
     @Override
     protected Element handle(final Document document, final XmlElement operationElement,
                              final NetconfOperationChainedExecution subsequentOperation) throws DocumentedException {
-        if (!subsequentOperation.isExecutionTermination()) {
-            throw new DocumentedException(String.format(
-                    "No netconf operation expected to be subsequent to %s, but is %s", this, subsequentOperation),
-                    ErrorType.APPLICATION, ErrorTag.MALFORMED_MESSAGE, ErrorSeverity.ERROR);
+        if (subsequentOperation != null) {
+            throw new DocumentedException(
+                "No netconf operation expected to be subsequent to %s, but is %s".formatted(this, subsequentOperation),
+                ErrorType.APPLICATION, ErrorTag.MALFORMED_MESSAGE, ErrorSeverity.ERROR);
         }
-
         return handleWithNoSubsequentOperations(document, operationElement);
     }
 
index 99f83111959231ffda29867e1c7665c33469530a..14702480f4f46f1c72cd8a8126b7643b6ef1ce36 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.netconf.server.api.operations;
 import static java.util.Objects.requireNonNull;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.netconf.api.DocumentedException;
 import org.opendaylight.netconf.api.NamespaceURN;
 import org.opendaylight.netconf.api.messages.RpcMessage;
@@ -84,8 +85,8 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
     protected abstract String getOperationName();
 
     @Override
-    public Document handle(final Document requestMessage,
-            final NetconfOperationChainedExecution subsequentOperation) throws DocumentedException {
+    public Document handle(final Document requestMessage, final NetconfOperationChainedExecution subsequentOperation)
+            throws DocumentedException {
         final var requestElement = getRequestElementWithCheck(requestMessage);
         final var document = XmlUtil.newDocument();
         final var operationElement = requestElement.getOnlyChildElement();
@@ -113,8 +114,7 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
     }
 
     protected abstract Element handle(Document document, XmlElement message,
-                                      NetconfOperationChainedExecution subsequentOperation)
-            throws DocumentedException;
+        @Nullable NetconfOperationChainedExecution subsequentOperation) throws DocumentedException;
 
     @Override
     public String toString() {
index c6f1af826b0ba99707d547d8756893bec85e3054..1ecbb788f31f325600bb0289f51d2d56e15d08a9 100644 (file)
@@ -36,17 +36,13 @@ public interface NetconfOperation {
     @Nullable HandlingPriority canHandle(Document message) throws DocumentedException;
 
     /**
-     * Execute current netconf operation and trigger execution of subsequent
-     * operations. subsequentOperation parameter will provide information, if
-     * current operation is the termination point in execution. In case of
-     * last/singleton operation, subsequentOperation must indicate termination
-     * point.
+     * Execute current netconf operation and trigger execution of subsequent operations, if applicable.
      *
      * @param requestMessage request message
-     * @param subsequentOperation execution of subsequent netconf operation
+     * @param subsequentOperation execution of subsequent NETCONF operation, or {@code null}
      * @return {@code document}
      * @throws DocumentedException if operation fails
      */
-    Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
+    Document handle(Document requestMessage, @Nullable NetconfOperationChainedExecution subsequentOperation)
             throws DocumentedException;
 }
index 9a68d81fd752b6e561d5ec6918398cd6d68ea370..9d654cccd8cb0600cf7fb60a4f9267f416da789c 100644 (file)
@@ -11,34 +11,9 @@ import org.opendaylight.netconf.api.DocumentedException;
 import org.w3c.dom.Document;
 
 /**
- * Single link in netconf operation execution chain.
- * Wraps the execution of a single netconf operation.
+ * Single link in netconf operation execution chain. Wraps the execution of a single netconf operation.
  */
 public interface NetconfOperationChainedExecution {
-    /**
-     * Check if this is termination point in operation execution.
-     *
-     * @return true if this is termination point in operation execution, false
-     *     if there is a subsequent operation present that needs to be
-     *     executed.
-     */
-    boolean isExecutionTermination();
 
-    /**
-     * Do not execute if this is termination point.
-     */
     Document execute(Document requestMessage) throws DocumentedException;
-
-    NetconfOperationChainedExecution EXECUTION_TERMINATION_POINT = new NetconfOperationChainedExecution() {
-        @Override
-        public boolean isExecutionTermination() {
-            return true;
-        }
-
-        @Override
-        public Document execute(final Document requestMessage) {
-            throw new IllegalStateException("This execution represents the termination point in operation execution "
-                    + "and cannot be executed itself");
-        }
-    };
 }
index 64a9c6b57ae4470e7248f48835779cda4a95bdab..f05a220f5a88bb96fc99c5879d321859792d622c 100644 (file)
@@ -37,8 +37,8 @@ public class DefaultStartExi extends AbstractSingletonNetconfOperation implement
     }
 
     @Override
-    public Document handle(final Document message,
-                           final NetconfOperationChainedExecution subsequentOperation) throws DocumentedException {
+    public Document handle(final Document message, final NetconfOperationChainedExecution subsequentOperation)
+            throws DocumentedException {
         if (LOG.isDebugEnabled()) {
             LOG.debug("Received start-exi message {} ", XmlUtil.toString(message));
         }
@@ -54,8 +54,7 @@ public class DefaultStartExi extends AbstractSingletonNetconfOperation implement
     }
 
     @Override
-    protected Element handleWithNoSubsequentOperations(final Document document,
-                                                       final XmlElement operationElement) {
+    protected Element handleWithNoSubsequentOperations(final Document document, final XmlElement operationElement) {
         final Element getSchemaResult = document.createElementNS(NamespaceURN.BASE, XmlNetconfConstants.OK);
         LOG.trace("{} operation successful", START_EXI);
         return getSchemaResult;
index 6b644c838599c8d22515a0f6c1909d22d161c660..9ff2f34c442551353799fc1666c392a99455dc94 100644 (file)
@@ -179,11 +179,6 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter, AutoC
             this.subsequentExecution = subsequentExecution;
         }
 
-        @Override
-        public boolean isExecutionTermination() {
-            return false;
-        }
-
         @Override
         public Document execute(final Document message) throws DocumentedException {
             return netconfOperation.handle(message, subsequentExecution);
@@ -195,15 +190,8 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter, AutoC
             final NetconfOperation netconfOperation = sortedByPriority.get(handlingPriority);
             final HandlingPriority subsequentHandlingPriority = sortedByPriority.lowerKey(handlingPriority);
 
-            NetconfOperationChainedExecution subsequentExecution = null;
-
-            if (subsequentHandlingPriority != null) {
-                subsequentExecution = createExecutionChain(sortedByPriority, subsequentHandlingPriority);
-            } else {
-                subsequentExecution = EXECUTION_TERMINATION_POINT;
-            }
-
-            return new NetconfOperationExecution(netconfOperation, subsequentExecution);
+            return new NetconfOperationExecution(netconfOperation, subsequentHandlingPriority == null ? null
+                : createExecutionChain(sortedByPriority, subsequentHandlingPriority));
         }
     }
 
index 0e7a0f66c6ec99734e0a0d4fd1f307957a1a20e3..cfd085d57a1ee49034cb096fdeecf9721e43cb5a 100644 (file)
@@ -85,6 +85,7 @@ import org.opendaylight.yangtools.yang.common.Uint16;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
 
 @ExtendWith(MockitoExtension.class)
 class ConcurrentClientsTest {
@@ -238,7 +239,6 @@ class ConcurrentClientsTest {
                 ? null : HandlingPriority.HANDLE_WITH_MAX_PRIORITY;
         }
 
-        @SuppressWarnings("checkstyle:IllegalCatch")
         @Override
         public Document handle(final Document requestMessage,
                 final NetconfOperationChainedExecution subsequentOperation) throws DocumentedException {
@@ -246,7 +246,7 @@ class ConcurrentClientsTest {
             counter.getAndIncrement();
             try {
                 return XmlUtil.readXmlToDocument("<test/>");
-            } catch (Exception e) {
+            } catch (IOException | SAXException e) {
                 throw new RuntimeException(e);
             }
         }
index a7486f370db8691231e50c2d801ead8f862de9c5..d4413a3ad2411abb08cc2149fe4a79bc703fafd5 100644 (file)
@@ -60,10 +60,9 @@ class AbstractLastNetconfOperationTest {
 
     @Test
     void testHandle() {
-        NetconfOperationChainedExecution operation = mock(NetconfOperationChainedExecution.class);
+        final var operation = mock(NetconfOperationChainedExecution.class);
         doReturn("").when(operation).toString();
 
-        doReturn(false).when(operation).isExecutionTermination();
         assertThrows(DocumentedException.class, () -> netconfOperation.handle(null, null, operation));
     }
 }
index bf9f76e5975ff1e7defee299a6c33978b734a94d..e4764cde23591ed6d3570f9d66edbee41b815ce5 100644 (file)
@@ -8,10 +8,10 @@
 package org.opendaylight.netconf.server.osgi;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
@@ -77,37 +77,33 @@ class NetconfOperationRouterImplTest {
     void testOnNetconfMessage() throws Exception {
         doReturn(HandlingPriority.HANDLE_WITH_MAX_PRIORITY).when(maxPrioMock).canHandle(any(Document.class));
         doReturn(XmlUtil.readXmlToDocument(MAX_PRIORITY_REPLY)).when(maxPrioMock).handle(any(Document.class),
-            any(NetconfOperationChainedExecution.class));
+            any());
 
         doReturn(HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY).when(defaultPrioMock).canHandle(any(Document.class));
         doReturn(XmlUtil.readXmlToDocument(DEFAULT_PRIORITY_REPLY)).when(defaultPrioMock).handle(any(Document.class),
-            any(NetconfOperationChainedExecution.class));
-        final ArgumentCaptor<NetconfOperationChainedExecution> highPriorityChainEx =
-                ArgumentCaptor.forClass(NetconfOperationChainedExecution.class);
-        final ArgumentCaptor<NetconfOperationChainedExecution> defaultPriorityChainEx =
-                ArgumentCaptor.forClass(NetconfOperationChainedExecution.class);
+            isNull());
+        final var highPriorityChainEx = ArgumentCaptor.forClass(NetconfOperationChainedExecution.class);
 
-        final Document document = operationRouter.onNetconfMessage(TEST_RPC_DOC, null);
+        final var document = operationRouter.onNetconfMessage(TEST_RPC_DOC, null);
 
         //max priority message is first in chain
         verify(maxPrioMock).handle(any(Document.class), highPriorityChainEx.capture());
-        final NetconfOperationChainedExecution chainedExecution = highPriorityChainEx.getValue();
-        assertFalse(chainedExecution.isExecutionTermination());
+        final var chainedExecution = highPriorityChainEx.getValue();
+        assertNotNull(chainedExecution);
 
         //execute next in chain
-        final Document execute = chainedExecution.execute(XmlUtil.newDocument());
+        final var execute = chainedExecution.execute(XmlUtil.newDocument());
         assertEquals(DEFAULT_PRIORITY_REPLY, XmlUtil.toString(execute).trim());
 
         //default priority message is second and last
-        verify(defaultPrioMock).handle(any(Document.class), defaultPriorityChainEx.capture());
-        assertTrue(defaultPriorityChainEx.getValue().isExecutionTermination());
+        verify(defaultPrioMock).handle(any(Document.class), isNull());
 
         assertEquals(MAX_PRIORITY_REPLY, XmlUtil.toString(document).trim());
     }
 
     @Test
     void testOnNetconfMessageFail() {
-        final DocumentedException ex =  assertThrows(DocumentedException.class,
+        final var ex = assertThrows(DocumentedException.class,
             () -> emptyOperationRouter.onNetconfMessage(TEST_RPC_DOC, null));
         assertEquals(ErrorTag.OPERATION_NOT_SUPPORTED, ex.getErrorTag());
     }