Split out CapabilitiesWriter 09/103209/13
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 11 Nov 2022 00:10:36 +0000 (01:10 +0100)
committerRobert Varga <nite@hq.sk>
Tue, 25 Jul 2023 15:39:00 +0000 (15:39 +0000)
Maintaining ietf-restconf-monitoring capabilities is a separate task
not done by any other component (unlike ietf-yang-library). Separate it
out.

JIRA: NETCONF-668
Change-Id: Icc0e7bbf4bc0c9ecdac385b7ce311ea49868b9c3
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
Signed-off-by: Ivan Hrasko <ivan.hrasko@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/legacy/SchemaContextHandler.java [moved from restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandler.java with 82% similarity]
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/monitoring/CapabilitiesWriter.java [new file with mode: 0644]
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/monitoring/package-info.java [new file with mode: 0644]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/legacy/SchemaContextHandlerTest.java [moved from restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandlerTest.java with 53% similarity]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/monitoring/CapabilitiesWriterTest.java [new file with mode: 0644]
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/utils/mapping/RestconfMappingNodeUtilTest.java

similarity index 82%
rename from restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandler.java
rename to restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/legacy/SchemaContextHandler.java
index 27cdd0dbe3f35217b3783cdb96d6043197461e11..46e608a3bb1bc3aa5c35aaf428915071ee5165b1 100644 (file)
@@ -5,10 +5,9 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.restconf.nb.rfc8040.handlers;
+package org.opendaylight.restconf.nb.rfc8040.legacy;
 
 import static java.util.Objects.requireNonNull;
-import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.$YangModuleInfoImpl.qnameOf;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Throwables;
@@ -20,25 +19,13 @@ import java.util.concurrent.atomic.AtomicInteger;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
-import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.opendaylight.restconf.api.query.AbstractReplayParam;
-import org.opendaylight.restconf.api.query.ChangedLeafNodesOnlyParam;
-import org.opendaylight.restconf.api.query.DepthParam;
-import org.opendaylight.restconf.api.query.FieldsParam;
-import org.opendaylight.restconf.api.query.FilterParam;
-import org.opendaylight.restconf.api.query.LeafNodesOnlyParam;
-import org.opendaylight.restconf.api.query.PrettyPrintParam;
-import org.opendaylight.restconf.api.query.SkipNotificationDataParam;
-import org.opendaylight.restconf.api.query.WithDefaultsParam;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.RestconfState;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.restconf.state.Capabilities;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.ModulesState;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.Module.ConformanceType;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.module.Deviation;
@@ -72,19 +59,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Implementation of {@link SchemaContextHandler}.
+ * A component which maintains the state of {@code ietf-yang-library} inside the datastore.
  */
-// FIXME: this really is a service which is maintaining ietf-yang-library contents inside the datastore. It really
-//        should live in MD-SAL and be a dynamic store fragment. As a first step we should be turning this into a
-//        completely standalone application.
+// FIXME: this should be reconciled with the two other implementations we have.
 @Singleton
 @Component(service = { })
 public final class SchemaContextHandler implements EffectiveModelContextListener, AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(SchemaContextHandler.class);
 
-    @VisibleForTesting
-    static final @NonNull QName CAPABILITY_QNAME = qnameOf("capability");
-
     private static final NodeIdentifier MODULE_CONFORMANCE_NODEID =
         NodeIdentifier.create(QName.create(IetfYangLibrary.MODULE_QNAME, "conformance-type").intern());
     private static final NodeIdentifier MODULE_FEATURE_NODEID =
@@ -127,10 +109,6 @@ public final class SchemaContextHandler implements EffectiveModelContextListener
             putData(mapModulesByIetfYangLibraryYang(context.getModules(), context,
                 String.valueOf(moduleSetId.incrementAndGet())));
         }
-
-        if (schemaContext.findModuleStatement(RestconfState.QNAME.getModule()).isPresent()) {
-            putData(mapCapabilites());
-        }
     }
 
     @VisibleForTesting
@@ -164,33 +142,6 @@ public final class SchemaContextHandler implements EffectiveModelContextListener
         }
     }
 
-    /**
-     * Map capabilites by ietf-restconf-monitoring.
-     *
-     * @return mapped capabilites
-     */
-    @VisibleForTesting
-    static ContainerNode mapCapabilites() {
-        return Builders.containerBuilder()
-            .withNodeIdentifier(new NodeIdentifier(RestconfState.QNAME))
-            .withChild(Builders.containerBuilder()
-                .withNodeIdentifier(new NodeIdentifier(Capabilities.QNAME))
-                .withChild(Builders.<String>orderedLeafSetBuilder()
-                    .withNodeIdentifier(new NodeIdentifier(CAPABILITY_QNAME))
-                    .withChildValue(DepthParam.capabilityUri().toString())
-                    .withChildValue(FieldsParam.capabilityUri().toString())
-                    .withChildValue(FilterParam.capabilityUri().toString())
-                    .withChildValue(AbstractReplayParam.capabilityUri().toString())
-                    .withChildValue(WithDefaultsParam.capabilityUri().toString())
-                    .withChildValue(PrettyPrintParam.capabilityUri().toString())
-                    .withChildValue(LeafNodesOnlyParam.capabilityUri().toString())
-                    .withChildValue(SkipNotificationDataParam.capabilityUri().toString())
-                    .withChildValue(ChangedLeafNodesOnlyParam.capabilityUri().toString())
-                    .build())
-                .build())
-            .build();
-    }
-
     /**
      * Map data from modules to {@link NormalizedNode}.
      *
diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/monitoring/CapabilitiesWriter.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/monitoring/CapabilitiesWriter.java
new file mode 100644 (file)
index 0000000..e37cafe
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040.monitoring;
+
+import static java.util.Objects.requireNonNull;
+import static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.$YangModuleInfoImpl.qnameOf;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.MoreExecutors;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.checkerframework.checker.lock.qual.Holding;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.common.api.CommitInfo;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
+import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
+import org.opendaylight.restconf.api.query.AbstractReplayParam;
+import org.opendaylight.restconf.api.query.DepthParam;
+import org.opendaylight.restconf.api.query.FieldsParam;
+import org.opendaylight.restconf.api.query.FilterParam;
+import org.opendaylight.restconf.api.query.LeafNodesOnlyParam;
+import org.opendaylight.restconf.api.query.PrettyPrintParam;
+import org.opendaylight.restconf.api.query.SkipNotificationDataParam;
+import org.opendaylight.restconf.api.query.WithDefaultsParam;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.RestconfState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.restconf.state.Capabilities;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextListener;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A simple component which maintains {@link Capabilities} in the operational datastore.
+ */
+@Singleton
+@Component(service = { })
+public final class CapabilitiesWriter
+        implements AutoCloseable, EffectiveModelContextListener, DOMTransactionChainListener {
+    private static final Logger LOG = LoggerFactory.getLogger(CapabilitiesWriter.class);
+
+    @VisibleForTesting
+    static final @NonNull NodeIdentifier CAPABILITY = NodeIdentifier.create(qnameOf("capability"));
+
+    private static final YangInstanceIdentifier PATH = YangInstanceIdentifier.of(
+        NodeIdentifier.create(RestconfState.QNAME), NodeIdentifier.create(Capabilities.QNAME), CAPABILITY);
+
+    private final DOMDataBroker dataBroker;
+
+    private DOMTransactionChain txChain;
+    private Registration reg;
+
+    private boolean written;
+
+    @Inject
+    @Activate
+    public CapabilitiesWriter(@Reference final DOMDataBroker dataBroker,
+            @Reference final DOMSchemaService schemaService) {
+        this.dataBroker = requireNonNull(dataBroker);
+        reg = schemaService.registerSchemaContextListener(this);
+    }
+
+    @PreDestroy
+    @Deactivate
+    @Override
+    public synchronized void close() {
+        if (reg == null) {
+            return;
+        }
+        reg.close();
+        reg = null;
+        deleteRestconfState();
+        if (txChain != null) {
+            txChain.close();
+        }
+    }
+
+    @Override
+    public synchronized void onTransactionChainFailed(final DOMTransactionChain chain,
+            final DOMDataTreeTransaction transaction, final Throwable cause) {
+        LOG.warn("Transaction chain failed, updates may not have been propagated", cause);
+        txChain = null;
+    }
+
+    @Override
+    public synchronized void onTransactionChainSuccessful(final DOMTransactionChain chain) {
+        LOG.debug("Transaction chain closed successfully");
+        txChain = null;
+    }
+
+    @Override
+    public synchronized void onModelContextUpdated(final EffectiveModelContext newModelContext) {
+        if (reg != null) {
+            LOG.debug("Ignoring model context update");
+            return;
+        }
+
+        if (newModelContext.findModuleStatement(RestconfState.QNAME.getModule()).isPresent()) {
+            writeRestconfState();
+        } else {
+            deleteRestconfState();
+        }
+    }
+
+    @Holding("this")
+    private void deleteRestconfState() {
+        if (!written) {
+            LOG.debug("No state recorded as written, not attempting removal");
+            return;
+        }
+
+        LOG.debug("Removing ietf-restconf-monitoring state");
+        if (txChain == null) {
+            txChain = dataBroker.createMergingTransactionChain(this);
+        }
+
+        final var tx = txChain.newWriteOnlyTransaction();
+        tx.delete(LogicalDatastoreType.OPERATIONAL, PATH);
+        tx.commit().addCallback(new FutureCallback<CommitInfo>() {
+            @Override
+            public void onSuccess(final CommitInfo result) {
+                markUnwritten();
+            }
+
+            @Override
+            public void onFailure(final Throwable cause) {
+                // Ignored, will be reported on the transaction chain
+            }
+        }, MoreExecutors.directExecutor());
+    }
+
+    @Holding("this")
+    private void writeRestconfState() {
+        if (written) {
+            LOG.debug("State recorded as written, not updating it");
+            return;
+        }
+
+        LOG.debug("Updating state of ietf-restconf-monitoring");
+        if (txChain == null) {
+            txChain = dataBroker.createMergingTransactionChain(this);
+        }
+
+        final var tx = txChain.newWriteOnlyTransaction();
+        tx.put(LogicalDatastoreType.OPERATIONAL, PATH, mapCapabilites());
+        tx.commit().addCallback(new FutureCallback<CommitInfo>() {
+            @Override
+            public void onSuccess(final CommitInfo result) {
+                markWritten();
+            }
+
+            @Override
+            public void onFailure(final Throwable cause) {
+                // Ignored, will be reported on the transaction chain
+            }
+        }, MoreExecutors.directExecutor());
+    }
+
+    private synchronized void markWritten() {
+        LOG.debug("State of ietf-restconf-monitoring updated");
+        written = true;
+    }
+
+    private synchronized void markUnwritten() {
+        LOG.debug("State of ietf-restconf-monitoring removed");
+        written = false;
+    }
+
+    /**
+     * Create a {@code restconf-state} container.
+     *
+     * @return A container holding capabilities
+     */
+    @VisibleForTesting
+    static @NonNull LeafSetNode<String> mapCapabilites() {
+        return Builders.<String>orderedLeafSetBuilder()
+            .withNodeIdentifier(CAPABILITY)
+            .withChildValue(DepthParam.capabilityUri().toString())
+            .withChildValue(FieldsParam.capabilityUri().toString())
+            .withChildValue(FilterParam.capabilityUri().toString())
+            .withChildValue(AbstractReplayParam.capabilityUri().toString())
+            .withChildValue(WithDefaultsParam.capabilityUri().toString())
+            .withChildValue(PrettyPrintParam.capabilityUri().toString())
+            .withChildValue(LeafNodesOnlyParam.capabilityUri().toString())
+            .withChildValue(SkipNotificationDataParam.capabilityUri().toString())
+            .build();
+    }
+}
diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/monitoring/package-info.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/nb/rfc8040/monitoring/package-info.java
new file mode 100644 (file)
index 0000000..fd23715
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+/**
+ * Package hosting support for {@code ietf-restconf-monitoring}.
+ */
+package org.opendaylight.restconf.nb.rfc8040.monitoring;
\ No newline at end of file
similarity index 53%
rename from restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/handlers/SchemaContextHandlerTest.java
rename to restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/legacy/SchemaContextHandlerTest.java
index c022c5c3af0a285e23f6d783caf4df026e254e21..ac6ecc56577ce7fd1b88edfb05db27061aeff68c 100644 (file)
@@ -5,20 +5,15 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.restconf.nb.rfc8040.handlers;
+package org.opendaylight.restconf.nb.rfc8040.legacy;
 
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 import java.io.FileNotFoundException;
-import java.util.stream.Collectors;
 import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -26,16 +21,10 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
-import org.opendaylight.mdsal.common.api.CommitInfo;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.restconf.state.Capabilities;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
@@ -45,14 +34,12 @@ import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
  */
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class SchemaContextHandlerTest {
-
-    private static final String PATH_FOR_ACTUAL_SCHEMA_CONTEXT = "/modules";
-    private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/modules/modules-behind-mount-point";
-
     private static EffectiveModelContext SCHEMA_CONTEXT;
 
     private SchemaContextHandler schemaContextHandler;
 
+    @Mock
+    private DOMDataBroker mockDOMDataBroker;
     @Mock
     private DOMSchemaService mockDOMSchemaService;
     @Mock
@@ -60,8 +47,7 @@ public class SchemaContextHandlerTest {
 
     @BeforeClass
     public static void beforeClass() throws FileNotFoundException {
-        SCHEMA_CONTEXT = YangParserTestUtils.parseYangFiles(
-            TestRestconfUtils.loadFiles(PATH_FOR_ACTUAL_SCHEMA_CONTEXT));
+        SCHEMA_CONTEXT = YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/modules"));
     }
 
     @AfterClass
@@ -71,14 +57,9 @@ public class SchemaContextHandlerTest {
 
     @Before
     public void setup() throws Exception {
-        final DOMDataBroker dataBroker = mock(DOMDataBroker.class);
-        final DOMDataTreeWriteTransaction wTx = mock(DOMDataTreeWriteTransaction.class);
-        doReturn(wTx).when(dataBroker).newWriteOnlyTransaction();
-        doReturn(CommitInfo.emptyFluentFuture()).when(wTx).commit();
-
         doReturn(mockListenerReg).when(mockDOMSchemaService).registerSchemaContextListener(any());
 
-        schemaContextHandler = new SchemaContextHandler(dataBroker, mockDOMSchemaService);
+        schemaContextHandler = new SchemaContextHandler(mockDOMDataBroker, mockDOMSchemaService);
         verify(mockDOMSchemaService).registerSchemaContextListener(schemaContextHandler);
 
         schemaContextHandler.onModelContextUpdated(SCHEMA_CONTEXT);
@@ -117,7 +98,7 @@ public class SchemaContextHandlerTest {
     public void onGlobalContextUpdateTest() throws Exception {
         // create new SchemaContext and update SchemaContextHandler
         final EffectiveModelContext newSchemaContext =
-                YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT));
+                YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/modules/modules-behind-mount-point"));
         schemaContextHandler.onModelContextUpdated(newSchemaContext);
 
         assertNotEquals("SchemaContextHandler should not has reference to old SchemaContext",
@@ -125,36 +106,4 @@ public class SchemaContextHandlerTest {
         assertEquals("SchemaContextHandler should has reference to new SchemaContext",
                 newSchemaContext, schemaContextHandler.get());
     }
-
-    @Test
-    public void restconfStateCapabilitesTest() {
-        final ContainerNode normNode = SchemaContextHandler.mapCapabilites();
-
-        @SuppressWarnings("unchecked")
-        final LeafSetNode<String> capability = (LeafSetNode<String>) normNode.body().stream()
-            // Find 'capabilities' container
-            .filter(child -> Capabilities.QNAME.equals(child.getIdentifier().getNodeType()))
-            .findFirst()
-            .map(ContainerNode.class::cast)
-            .orElseThrow()
-            // Find 'capability' leaf-list
-            .body().stream()
-            .filter(child -> SchemaContextHandler.CAPABILITY_QNAME.equals(child.getIdentifier().getNodeType()))
-            .findFirst()
-            .orElseThrow();
-
-        assertThat(
-            capability.body().stream().map(entry -> ((LeafSetEntryNode<?>) entry).body()).collect(Collectors.toList()),
-            containsInAnyOrder(
-                equalTo("urn:ietf:params:restconf:capability:depth:1.0"),
-                equalTo("urn:ietf:params:restconf:capability:fields:1.0"),
-                equalTo("urn:ietf:params:restconf:capability:filter:1.0"),
-                equalTo("urn:ietf:params:restconf:capability:replay:1.0"),
-                equalTo("urn:ietf:params:restconf:capability:with-defaults:1.0"),
-                equalTo("urn:opendaylight:params:restconf:capability:pretty-print:1.0"),
-                equalTo("urn:opendaylight:params:restconf:capability:leaf-nodes-only:1.0"),
-                equalTo("urn:opendaylight:params:restconf:capability:changed-leaf-nodes-only:1.0"),
-                equalTo("urn:opendaylight:params:restconf:capability:skip-notification-data:1.0")));
-    }
-
 }
diff --git a/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/monitoring/CapabilitiesWriterTest.java b/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/rfc8040/monitoring/CapabilitiesWriterTest.java
new file mode 100644 (file)
index 0000000..b3ff180
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.restconf.nb.rfc8040.monitoring;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+
+public class CapabilitiesWriterTest {
+    @Test
+    public void restconfStateCapabilitiesTest() {
+        final var capability = CapabilitiesWriter.mapCapabilites();
+        assertEquals(CapabilitiesWriter.CAPABILITY, capability.name());
+
+        assertThat(capability.body().stream().map(LeafSetEntryNode::body).toList(),
+            containsInAnyOrder(
+                equalTo("urn:ietf:params:restconf:capability:depth:1.0"),
+                equalTo("urn:ietf:params:restconf:capability:fields:1.0"),
+                equalTo("urn:ietf:params:restconf:capability:filter:1.0"),
+                equalTo("urn:ietf:params:restconf:capability:replay:1.0"),
+                equalTo("urn:ietf:params:restconf:capability:with-defaults:1.0"),
+                equalTo("urn:opendaylight:params:restconf:capability:pretty-print:1.0"),
+                equalTo("urn:opendaylight:params:restconf:capability:leaf-nodes-only:1.0"),
+                equalTo("urn:opendaylight:params:restconf:capability:skip-notification-data:1.0")));
+    }
+}
index c72791758f4aa28acc94de654784153d1c15148f..55250ffa508a34d61bc788960d6e3af5ff3234d9 100644 (file)
@@ -23,7 +23,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.opendaylight.restconf.nb.rfc8040.Rfc8040.IetfYangLibrary;
 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
-import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
+import org.opendaylight.restconf.nb.rfc8040.legacy.SchemaContextHandler;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.library.rev190104.module.list.module.Deviation;
 import org.opendaylight.yangtools.yang.common.QName;