Cleanup datastore interactions 35/96135/4
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 12 May 2021 20:01:05 +0000 (22:01 +0200)
committerRobert Varga <nite@hq.sk>
Wed, 12 May 2021 22:39:46 +0000 (22:39 +0000)
Datastore handles lifecycle of non-semantic portions, hence we do not
need utterly ugly special-cases dealing with container/list
initialization. This removes a chunk of crud, makes things more
type-safe and more straightforward.

Change-Id: I7fe72a0c37cd0a1ef94f2921fb3c66800eccfa26
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfDataServiceImpl.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/SubscribeToStreamUtil.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/utils/mapping/RestconfMappingNodeUtil.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfStreamsSubscriptionServiceImplTest.java
restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/utils/mapping/RestconfMappingNodeUtilTest.java

index 4062f29f2b2fd655624c1452d06900eceba2ecbd..7c4520f94970310b03a710257e8df73f7d80040e 100644 (file)
@@ -74,6 +74,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
@@ -237,26 +238,11 @@ public class RestconfDataServiceImpl implements RestconfDataService {
             final UriInfo uriInfo, final RestconfTransaction transaction, final boolean exist,
             final NotificationListenerAdapter listener) {
         final URI uri = streamUtils.prepareUriByStreamName(uriInfo, listener.getStreamName());
-        final NormalizedNode<?, ?> mapToStreams =
-            RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
+        final MapEntryNode mapToStreams = RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
                 listener.getSchemaPath().lastNodeIdentifier(), schemaContext.getNotifications(), null,
-                listener.getOutputType(), uri, SubscribeToStreamUtil.getMonitoringModule(schemaContext), exist);
-        writeDataToDS(schemaContext,
-            listener.getSchemaPath().lastNodeIdentifier().getLocalName(), transaction, exist, mapToStreams);
-    }
-
-    private static boolean checkExist(final EffectiveModelContext schemaContext, final RestconfStrategy strategy) {
-        try {
-            return strategy.exists(LogicalDatastoreType.OPERATIONAL,
-                IdentifierCodec.deserialize(Rfc8040.MonitoringModule.PATH_TO_STREAMS, schemaContext)).get();
-        } catch (final InterruptedException | ExecutionException exception) {
-            throw new RestconfDocumentedException("Problem while checking data if exists", exception);
-        }
-    }
+                listener.getOutputType(), uri, SubscribeToStreamUtil.getMonitoringModule(schemaContext));
 
-    private static void writeDataToDS(final EffectiveModelContext schemaContext, final String name,
-                                      final RestconfTransaction transaction, final boolean exist,
-                                      final NormalizedNode<?, ?> mapToStreams) {
+        final String name = listener.getSchemaPath().lastNodeIdentifier().getLocalName();
         final String pathId;
         if (exist) {
             pathId = Rfc8040.MonitoringModule.PATH_TO_STREAM_WITHOUT_KEY + name;
@@ -267,6 +253,15 @@ public class RestconfDataServiceImpl implements RestconfDataService {
             mapToStreams);
     }
 
+    private static boolean checkExist(final EffectiveModelContext schemaContext, final RestconfStrategy strategy) {
+        try {
+            return strategy.exists(LogicalDatastoreType.OPERATIONAL,
+                IdentifierCodec.deserialize(Rfc8040.MonitoringModule.PATH_TO_STREAMS, schemaContext)).get();
+        } catch (final InterruptedException | ExecutionException exception) {
+            throw new RestconfDocumentedException("Problem while checking data if exists", exception);
+        }
+    }
+
     @Override
     public Response putData(final String identifier, final NormalizedNodeContext payload, final UriInfo uriInfo) {
         requireNonNull(payload);
index 04433f3ee0c367ae26656b1a3d6a59eb8612334d..ee96e3e36f6152c1773a657d436e1b1b80c6b37f 100644 (file)
@@ -21,7 +21,6 @@ import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
 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.DOMDataTreeReadWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMNotificationListener;
 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
@@ -42,7 +41,7 @@ import org.opendaylight.restconf.nb.rfc8040.utils.RestconfConstants;
 import org.opendaylight.restconf.nb.rfc8040.utils.mapping.RestconfMappingNodeUtil;
 import org.opendaylight.restconf.nb.rfc8040.utils.parser.IdentifierCodec;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
@@ -145,7 +144,6 @@ abstract class SubscribeToStreamUtil {
         final DOMTransactionChain transactionChain = handlersHolder.getTransactionChainHandler().get();
         final DOMDataTreeReadWriteTransaction writeTransaction = transactionChain.newReadWriteTransaction();
         final EffectiveModelContext schemaContext = handlersHolder.getSchemaHandler().get();
-        final boolean exist = checkExist(schemaContext, writeTransaction);
 
         final URI uri = prepareUriByStreamName(uriInfo, streamName);
         registerToListenNotification(
@@ -157,14 +155,13 @@ abstract class SubscribeToStreamUtil {
                 false, notificationQueryParams.isSkipNotificationData());
         notificationListenerAdapter.get().setCloseVars(
                 handlersHolder.getTransactionChainHandler(), handlersHolder.getSchemaHandler());
-        final NormalizedNode<?, ?> mapToStreams =
-                RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
+        final MapEntryNode mapToStreams = RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
                     notificationListenerAdapter.get().getSchemaPath().lastNodeIdentifier(),
                     schemaContext.getNotifications(), notificationQueryParams.getStart(),
-                    notificationListenerAdapter.get().getOutputType(), uri, getMonitoringModule(schemaContext), exist);
+                    notificationListenerAdapter.get().getOutputType(), uri, getMonitoringModule(schemaContext));
         writeDataToDS(schemaContext,
-                notificationListenerAdapter.get().getSchemaPath().lastNodeIdentifier().getLocalName(), writeTransaction,
-                exist, mapToStreams);
+            notificationListenerAdapter.get().getSchemaPath().lastNodeIdentifier().getLocalName(), writeTransaction,
+            mapToStreams);
         submitData(writeTransaction);
         transactionChain.close();
         return uri;
@@ -217,14 +214,13 @@ abstract class SubscribeToStreamUtil {
         final DOMTransactionChain transactionChain = handlersHolder.getTransactionChainHandler().get();
         final DOMDataTreeReadWriteTransaction writeTransaction = transactionChain.newReadWriteTransaction();
         final EffectiveModelContext schemaContext = handlersHolder.getSchemaHandler().get();
-        final boolean exist = checkExist(schemaContext, writeTransaction);
 
-        final NormalizedNode<?, ?> mapToStreams = RestconfMappingNodeUtil
-                .mapDataChangeNotificationStreamByIetfRestconfMonitoring(listener.get().getPath(),
-                        notificationQueryParams.getStart(), listener.get().getOutputType(), uri,
-                        getMonitoringModule(schemaContext), exist, schemaContext);
+        final MapEntryNode mapToStreams =
+            RestconfMappingNodeUtil.mapDataChangeNotificationStreamByIetfRestconfMonitoring(listener.get().getPath(),
+                notificationQueryParams.getStart(), listener.get().getOutputType(), uri,
+                getMonitoringModule(schemaContext), schemaContext);
         writeDataToDS(schemaContext, listener.get().getPath().getLastPathArgument().getNodeType().getLocalName(),
-                writeTransaction, exist, mapToStreams);
+                writeTransaction, mapToStreams);
         submitData(writeTransaction);
         transactionChain.close();
         return uri;
@@ -235,16 +231,11 @@ abstract class SubscribeToStreamUtil {
     }
 
     private static void writeDataToDS(final EffectiveModelContext schemaContext, final String name,
-            final DOMDataTreeReadWriteTransaction readWriteTransaction, final boolean exist,
-            final NormalizedNode<?, ?> mapToStreams) {
-        String pathId;
-        if (exist) {
-            pathId = MonitoringModule.PATH_TO_STREAM_WITHOUT_KEY + name;
-        } else {
-            pathId = MonitoringModule.PATH_TO_STREAMS;
-        }
+            final DOMDataTreeReadWriteTransaction readWriteTransaction, final MapEntryNode mapToStreams) {
         readWriteTransaction.merge(LogicalDatastoreType.OPERATIONAL,
-                IdentifierCodec.deserialize(pathId, schemaContext), mapToStreams);
+            // FIXME: do not use IdentifierCodec here
+            IdentifierCodec.deserialize(MonitoringModule.PATH_TO_STREAM_WITHOUT_KEY + name, schemaContext),
+            mapToStreams);
     }
 
     private static void submitData(final DOMDataTreeReadWriteTransaction readWriteTransaction) {
@@ -297,16 +288,6 @@ abstract class SubscribeToStreamUtil {
         listener.setRegistration(registration);
     }
 
-    private static boolean checkExist(final EffectiveModelContext schemaContext,
-                              final DOMDataTreeReadOperations readWriteTransaction) {
-        try {
-            return readWriteTransaction.exists(LogicalDatastoreType.OPERATIONAL,
-                    IdentifierCodec.deserialize(MonitoringModule.PATH_TO_STREAMS, schemaContext)).get();
-        } catch (final InterruptedException | ExecutionException exception) {
-            throw new RestconfDocumentedException("Problem while checking data if exists", exception);
-        }
-    }
-
     private static void registerToListenNotification(final NotificationListenerAdapter listener,
             final NotificationServiceHandler notificationServiceHandler) {
         if (listener.isListening()) {
index f9c02f1bbb089bd9ccd73dd85c11ce8b44113e0d..fe29f1f9f68ca46c3b05993fcbdbd6d1b6efc782 100644 (file)
@@ -315,15 +315,12 @@ public final class RestconfMappingNodeUtil {
      *            notification
      * @param monitoringModule
      *             ietf-restconf-monitoring module
-     * @param existParent
-     *             true if data of parent -
-     *            ietf-restconf-monitoring:restconf-state/streams - exist in DS
      * @return mapped data of notification - map entry node if parent exists,
      *         container streams with list and map entry node if not
      */
-    public static NormalizedNode<?, ?> mapYangNotificationStreamByIetfRestconfMonitoring(final QName notifiQName,
+    public static MapEntryNode mapYangNotificationStreamByIetfRestconfMonitoring(final QName notifiQName,
             final Collection<? extends NotificationDefinition> notifications, final Instant start,
-            final String outputType, final URI uri, final Module monitoringModule, final boolean existParent) {
+            final String outputType, final URI uri, final Module monitoringModule) {
         for (final NotificationDefinition notificationDefinition : notifications) {
             if (notificationDefinition.getQName().equals(notifiQName)) {
                 final DataSchemaNode streamListSchema = ((ContainerSchemaNode) ((ContainerSchemaNode) monitoringModule
@@ -355,14 +352,6 @@ public final class RestconfMappingNodeUtil {
                         (ListSchemaNode) listSchema.getDataChildByName(MonitoringModule.LIST_ACCESS_STREAM_QNAME),
                         outputType, uri);
 
-                if (!existParent) {
-                    final DataSchemaNode contStreamsSchema = ((ContainerSchemaNode) monitoringModule
-                            .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
-                                    .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME);
-                    return Builders.containerBuilder((ContainerSchemaNode) contStreamsSchema).withChild(Builders
-                            .mapBuilder((ListSchemaNode) streamListSchema).withChild(streamEntry.build()).build())
-                            .build();
-                }
                 return streamEntry.build();
             }
         }
@@ -412,18 +401,15 @@ public final class RestconfMappingNodeUtil {
      *            notification
      * @param monitoringModule
      *             ietf-restconf-monitoring module
-     * @param existParent
-     *             true if data of parent -
-     *            ietf-restconf-monitoring:restconf-state/streams - exist in DS
      * @param schemaContext
      *             schemaContext for parsing instance identifier to get schema
      *            node of data
      * @return mapped data of notification - map entry node if parent exists,
      *         container streams with list and map entry node if not
      */
-    public static NormalizedNode<?, ?> mapDataChangeNotificationStreamByIetfRestconfMonitoring(
+    public static MapEntryNode mapDataChangeNotificationStreamByIetfRestconfMonitoring(
             final YangInstanceIdentifier path, final Instant start, final String outputType, final URI uri,
-            final Module monitoringModule, final boolean existParent, final EffectiveModelContext schemaContext) {
+            final Module monitoringModule, final EffectiveModelContext schemaContext) {
         final SchemaNode schemaNode = ParserIdentifier
                 .toInstanceIdentifier(ParserIdentifier.stringFromYangInstanceIdentifier(path, schemaContext),
                         schemaContext, Optional.empty())
@@ -454,15 +440,6 @@ public final class RestconfMappingNodeUtil {
                 (ListSchemaNode) listSchema.getDataChildByName(MonitoringModule.LIST_ACCESS_STREAM_QNAME), outputType,
                 uri);
 
-        if (!existParent) {
-            final DataSchemaNode contStreamsSchema = ((ContainerSchemaNode) monitoringModule
-                    .getDataChildByName(MonitoringModule.CONT_RESTCONF_STATE_QNAME))
-                            .getDataChildByName(MonitoringModule.CONT_STREAMS_QNAME);
-            return Builders
-                    .containerBuilder((ContainerSchemaNode) contStreamsSchema).withChild(Builders
-                            .mapBuilder((ListSchemaNode) streamListSchema).withChild(streamEntry.build()).build())
-                    .build();
-        }
         return streamEntry.build();
     }
 }
index ab66da5767c782aafd88544542743c9f037e8dd5..6b273d2a34b3ae6d6acadb2804c1e280069931c1 100644 (file)
@@ -12,7 +12,6 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
 
 import com.google.common.collect.ImmutableClassToInstanceMap;
 import java.io.FileNotFoundException;
@@ -88,7 +87,6 @@ public class RestconfStreamsSubscriptionServiceImplTest {
         final DOMDataTreeWriteTransaction wTx = mock(DOMDataTreeWriteTransaction.class);
         when(domTx.newWriteOnlyTransaction()).thenReturn(wTx);
         final DOMDataTreeReadWriteTransaction rwTx = mock(DOMDataTreeReadWriteTransaction.class);
-        when(rwTx.exists(any(), any())).thenReturn(immediateTrueFluentFuture());
         doReturn(CommitInfo.emptyFluentFuture()).when(rwTx).commit();
         when(domTx.newReadWriteTransaction()).thenReturn(rwTx);
         doReturn(CommitInfo.emptyFluentFuture()).when(wTx).commit();
index b8fdb3c17d413ef9c1398773c412ca2eaee3d025..d14e396038c9a8ecea572b718c7e7bbf4fd8280a 100644 (file)
@@ -40,7 +40,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 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.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
@@ -76,7 +75,6 @@ public class RestconfMappingNodeUtilTest {
     @Test
     public void restconfMappingNodeTest() {
         // write modules into list module in Restconf
-        final Module ietfYangLibMod = schemaContext.findModule(IetfYangLibrary.MODULE_QNAME).get();
         final ContainerNode mods = RestconfMappingNodeUtil.mapModulesByIetfYangLibraryYang(
             RestconfMappingNodeUtilTest.modules, schemaContext, "1");
 
@@ -117,16 +115,13 @@ public class RestconfMappingNodeUtilTest {
         final String outputType = "XML";
         final URI uri = new URI("uri");
         final Module monitoringModule = schemaContextMonitoring.findModule(MonitoringModule.MODULE_QNAME).orElse(null);
-        final boolean exist = true;
 
-        final Map<QName, Object> map =
-                prepareMap(path.getLastPathArgument().getNodeType().getLocalName(), uri, start, outputType);
+        final Map<QName, Object> map = prepareMap(path.getLastPathArgument().getNodeType().getLocalName(), uri, start,
+            outputType);
 
-        final NormalizedNode<?, ?> mappedData =
-                RestconfMappingNodeUtil.mapDataChangeNotificationStreamByIetfRestconfMonitoring(
-                        path, start, outputType, uri, monitoringModule, exist, schemaContextMonitoring);
-        assertNotNull(mappedData);
-        testData(map, mappedData);
+        final MapEntryNode mappedData = RestconfMappingNodeUtil.mapDataChangeNotificationStreamByIetfRestconfMonitoring(
+            path, start, outputType, uri, monitoringModule, schemaContextMonitoring);
+        assertMappedData(map, mappedData);
     }
 
     @Test
@@ -135,17 +130,14 @@ public class RestconfMappingNodeUtilTest {
         final String outputType = "JSON";
         final URI uri = new URI("uri");
         final Module monitoringModule = schemaContextMonitoring.findModule(MonitoringModule.MODULE_QNAME).orElse(null);
-        final boolean exist = true;
 
         final Map<QName, Object> map = prepareMap("notifi", uri, start, outputType);
         map.put(MonitoringModule.LEAF_DESCR_STREAM_QNAME, "Notifi");
 
         final QName notifiQName = QName.create("urn:nested:module", "2014-06-03", "notifi");
-        final NormalizedNode<?, ?> mappedData =
-                RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(notifiQName,
-                    schemaContextMonitoring.getNotifications(), start, outputType, uri, monitoringModule, exist);
-        assertNotNull(mappedData);
-        testData(map, mappedData);
+        final MapEntryNode mappedData = RestconfMappingNodeUtil.mapYangNotificationStreamByIetfRestconfMonitoring(
+            notifiQName, schemaContextMonitoring.getNotifications(), start, outputType, uri, monitoringModule);
+        assertMappedData(map, mappedData);
     }
 
     private static Map<QName, Object> prepareMap(final String name, final URI uri, final Instant start,
@@ -160,8 +152,9 @@ public class RestconfMappingNodeUtilTest {
         return map;
     }
 
-    private static void testData(final Map<QName, Object> map, final NormalizedNode<?, ?> mappedData) {
-        for (final DataContainerChild<? extends PathArgument, ?> child : ((MapEntryNode) mappedData).getValue()) {
+    private static void assertMappedData(final Map<QName, Object> map, final MapEntryNode mappedData) {
+        assertNotNull(mappedData);
+        for (final DataContainerChild<?, ?> child : mappedData.getValue()) {
             if (child instanceof LeafNode) {
                 final LeafNode<?> leaf = (LeafNode<?>) child;
                 assertTrue(map.containsKey(leaf.getNodeType()));