Clean up AbstractRegistrationTree 33/109233/3
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 8 Dec 2023 19:22:56 +0000 (20:22 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 8 Dec 2023 19:59:30 +0000 (20:59 +0100)
Inline RegistrationTree{Node,Snapshot} and perform general cleanups:
- hide snapshot() method so it can only be invoked from subclasses
- add @VisibleForTesting annotations
- use Map.computeIfAbsent()
- use local variable type inference
- check result of Collection.remove() on cleanup

JIRA: MDSAL-843
Change-Id: I4776be432da92bfe2f81d0551dd0d81184380987
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/AbstractRegistrationTree.java
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeNode.java [deleted file]
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeSnapshot.java [deleted file]
dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/store/AbstractDOMStoreTreeChangePublisher.java
dom/mdsal-dom-spi/src/test/java/org/opendaylight/mdsal/dom/spi/AbstractRegistrationTreeTest.java
dom/mdsal-dom-spi/src/test/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeNodeTest.java
dom/mdsal-dom-spi/src/test/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeSnapshotTest.java

index be12ad3e8c9a1c56a636765d5a7124074a700493..3b000ef4b73aacb4e8e6fcbc003408aae757efcd 100644 (file)
@@ -7,10 +7,31 @@
  */
 package org.opendaylight.mdsal.dom.spi;
 
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.StampedLock;
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.AbstractRegistration;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * An abstract tree of registrations. Allows a read-only snapshot to be taken.
@@ -18,12 +39,141 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgum
  * @param <T> Type of registered object
  */
 public abstract class AbstractRegistrationTree<T> {
-    private final RegistrationTreeNode<T> rootNode = new RegistrationTreeNode<>(null, null);
-    private final Lock writeLock;
-    private final Lock readLock;
+    /**
+     * This is a single node within the registration tree. Note that the data returned from and instance of this class
+     * is guaranteed to have any relevance or consistency only as long as the {@link Snapshot} instance through which it
+     * is reached remains unclosed.
+     *
+     * @param <T> registration type
+     */
+    protected static final class Node<T> implements Identifiable<PathArgument> {
+        private static final Logger LOG = LoggerFactory.getLogger(Node.class);
+
+        private final Map<PathArgument, Node<T>> children = new HashMap<>();
+        private final List<T> registrations = new ArrayList<>(2);
+        private final List<T> publicRegistrations = Collections.unmodifiableList(registrations);
+        private final Reference<Node<T>> parent;
+        private final PathArgument identifier;
+
+        Node(final Node<T> parent, final PathArgument identifier) {
+            this.parent = new WeakReference<>(parent);
+            this.identifier = identifier;
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            return identifier;
+        }
+
+        /**
+         * Return the child matching a {@link PathArgument} specification.
+         *
+         * @param arg Child identifier
+         * @return Child matching exactly, or {@code null}.
+         */
+        public @Nullable Node<T> getExactChild(final @NonNull PathArgument arg) {
+            return children.get(requireNonNull(arg));
+        }
+
+        /**
+         * Return a collection children which match a {@link PathArgument} specification inexactly.
+         * This explicitly excludes the child returned by {@link #getExactChild(PathArgument)}.
+         *
+         * @param arg Child identifier
+         * @return Collection of children, guaranteed to be non-null.
+         */
+        public @NonNull Collection<Node<T>> getInexactChildren(final @NonNull PathArgument arg) {
+            requireNonNull(arg);
+            if (arg instanceof NodeWithValue || arg instanceof NodeIdentifierWithPredicates) {
+                /*
+                 * TODO: This just all-or-nothing wildcards, which we have historically supported. Given
+                 *       that the argument is supposed to have all the elements filled out, we could support
+                 *       partial wildcards by iterating over the registrations and matching the maps for
+                 *       partial matches.
+                 */
+                final var child = children.get(new NodeIdentifier(arg.getNodeType()));
+                return child == null ? List.of() : Collections.singletonList(child);
+            }
+
+            return List.of();
+        }
+
+        public Collection<T> getRegistrations() {
+            return publicRegistrations;
+        }
+
+        @VisibleForTesting
+        @NonNull Node<T> ensureChild(final @NonNull PathArgument child) {
+            return children.computeIfAbsent(requireNonNull(child), key -> new Node<>(this, key));
+        }
+
+        @VisibleForTesting
+        void addRegistration(final @NonNull T registration) {
+            registrations.add(requireNonNull(registration));
+            LOG.debug("Registration {} added", registration);
+        }
+
+        @VisibleForTesting
+        void removeRegistration(final @NonNull T registration) {
+            if (registrations.remove(requireNonNull(registration))) {
+                LOG.debug("Registration {} removed", registration);
+
+                // We have been called with the write-lock held, so we can perform some cleanup.
+                removeThisIfUnused();
+            }
+        }
+
+        private void removeThisIfUnused() {
+            final var p = parent.get();
+            if (p != null && registrations.isEmpty() && children.isEmpty()) {
+                p.removeChild(identifier);
+            }
+        }
+
+        private void removeChild(final PathArgument arg) {
+            children.remove(arg);
+            removeThisIfUnused();
+        }
+
+        @Override
+        public String toString() {
+            return MoreObjects.toStringHelper(this)
+                .add("identifier", identifier)
+                .add("registrations", registrations.size())
+                .add("children", children.size())
+                .toString();
+        }
+    }
+
+    /**
+     * A stable read-only snapshot of a {@link AbstractRegistrationTree}.
+     */
+    @NonNullByDefault
+    protected static final class Snapshot<T> extends AbstractRegistration {
+        private final Node<T> node;
+        private final Lock lock;
+
+        Snapshot(final Lock lock, final Node<T> node) {
+            this.lock = requireNonNull(lock);
+            this.node = requireNonNull(node);
+        }
+
+        public Node<T> getRootNode() {
+            return node;
+        }
+
+        @Override
+        protected void removeRegistration() {
+            lock.unlock();
+        }
+    }
+
+    private final @NonNull Node<T> rootNode = new Node<>(null, null);
+    private final @NonNull Lock writeLock;
+    private final @NonNull Lock readLock;
 
     protected AbstractRegistrationTree() {
-        final StampedLock lock = new StampedLock();
+        final var lock = new StampedLock();
         readLock = lock.asReadLock();
         writeLock = lock.asWriteLock();
     }
@@ -50,12 +200,11 @@ public abstract class AbstractRegistrationTree<T> {
      * @param path Path to find a node for
      * @return A registration node for the specified path
      */
-    protected final @NonNull RegistrationTreeNode<T> findNodeFor(final @NonNull Iterable<PathArgument> path) {
-        RegistrationTreeNode<T> walkNode = rootNode;
-        for (final PathArgument arg : path) {
+    protected final @NonNull Node<T> findNodeFor(final @NonNull Iterable<PathArgument> path) {
+        var walkNode = rootNode;
+        for (var arg : path) {
             walkNode = walkNode.ensureChild(arg);
         }
-
         return walkNode;
     }
 
@@ -66,7 +215,7 @@ public abstract class AbstractRegistrationTree<T> {
      * @param node Tree node
      * @param registration Registration instance
      */
-    protected final void addRegistration(final @NonNull RegistrationTreeNode<T> node, final @NonNull T registration) {
+    protected final void addRegistration(final @NonNull Node<T> node, final @NonNull T registration) {
         node.addRegistration(registration);
     }
 
@@ -76,7 +225,7 @@ public abstract class AbstractRegistrationTree<T> {
      * @param node Tree node
      * @param registration Registration instance
      */
-    protected final void removeRegistration(final @NonNull RegistrationTreeNode<T> node,
+    protected final void removeRegistration(final @NonNull Node<T> node,
             final @NonNull T registration) {
         // Take the write lock
         writeLock.lock();
@@ -89,14 +238,13 @@ public abstract class AbstractRegistrationTree<T> {
     }
 
     /**
-     * Obtain a tree snapshot. This snapshot ensures a consistent view of
-     * registrations. The snapshot should be closed as soon as it is not required,
-     * because each unclosed instance blocks modification of this tree.
+     * Obtain a tree snapshot. This snapshot ensures a consistent view of registrations. The snapshot should be closed
+     * as soon as it is not required, because each unclosed instance blocks modification of this tree.
      *
      * @return A snapshot instance.
      */
-    public final @NonNull RegistrationTreeSnapshot<T> takeSnapshot() {
+    protected final @NonNull Snapshot<T> takeSnapshot() {
         readLock.lock();
-        return new RegistrationTreeSnapshot<>(readLock, rootNode);
+        return new Snapshot<>(readLock, rootNode);
     }
 }
diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeNode.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeNode.java
deleted file mode 100644 (file)
index f89dce9..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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.mdsal.dom.spi;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.MoreObjects;
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This is a single node within the registration tree. Note that the data returned from
- * and instance of this class is guaranteed to have any relevance or consistency
- * only as long as the {@link RegistrationTreeSnapshot} instance through which it is reached
- * remains unclosed.
- *
- * @param <T> registration type
- * @author Robert Varga
- */
-public final class RegistrationTreeNode<T> implements Identifiable<PathArgument> {
-    private static final Logger LOG = LoggerFactory.getLogger(RegistrationTreeNode.class);
-
-    private final Map<PathArgument, RegistrationTreeNode<T>> children = new HashMap<>();
-    private final Collection<T> registrations = new ArrayList<>(2);
-    private final Collection<T> publicRegistrations = Collections.unmodifiableCollection(registrations);
-    private final Reference<RegistrationTreeNode<T>> parent;
-    private final PathArgument identifier;
-
-    RegistrationTreeNode(final RegistrationTreeNode<T> parent, final PathArgument identifier) {
-        this.parent = new WeakReference<>(parent);
-        this.identifier = identifier;
-    }
-
-    @Override
-    public PathArgument getIdentifier() {
-        return identifier;
-    }
-
-    /**
-     * Return the child matching a {@link PathArgument} specification.
-     *
-     * @param arg Child identifier
-     * @return Child matching exactly, or null.
-     */
-    public RegistrationTreeNode<T> getExactChild(final @NonNull PathArgument arg) {
-        return children.get(requireNonNull(arg));
-    }
-
-    /**
-     * Return a collection children which match a {@link PathArgument} specification inexactly.
-     * This explicitly excludes the child returned by {@link #getExactChild(PathArgument)}.
-     *
-     * @param arg Child identifier
-     * @return Collection of children, guaranteed to be non-null.
-     */
-    public @NonNull Collection<RegistrationTreeNode<T>> getInexactChildren(final @NonNull PathArgument arg) {
-        requireNonNull(arg);
-        if (arg instanceof NodeWithValue || arg instanceof NodeIdentifierWithPredicates) {
-            /*
-             * TODO: This just all-or-nothing wildcards, which we have historically supported. Given
-             *       that the argument is supposed to have all the elements filled out, we could support
-             *       partial wildcards by iterating over the registrations and matching the maps for
-             *       partial matches.
-             */
-            final RegistrationTreeNode<T> child = children.get(new NodeIdentifier(arg.getNodeType()));
-            if (child == null) {
-                return Collections.emptyList();
-            }
-
-            return Collections.singletonList(child);
-        }
-
-        return Collections.emptyList();
-    }
-
-    public Collection<T> getRegistrations() {
-        return publicRegistrations;
-    }
-
-    RegistrationTreeNode<T> ensureChild(final @NonNull PathArgument child) {
-        RegistrationTreeNode<T> potential = children.get(requireNonNull(child));
-        if (potential == null) {
-            potential = new RegistrationTreeNode<>(this, child);
-            children.put(child, potential);
-        }
-        return potential;
-    }
-
-    void addRegistration(final @NonNull T registration) {
-        registrations.add(requireNonNull(registration));
-        LOG.debug("Registration {} added", registration);
-    }
-
-    void removeRegistration(final @NonNull T registration) {
-        registrations.remove(requireNonNull(registration));
-        LOG.debug("Registration {} removed", registration);
-
-        // We have been called with the write-lock held, so we can perform some cleanup.
-        removeThisIfUnused();
-    }
-
-    private void removeThisIfUnused() {
-        final RegistrationTreeNode<T> p = parent.get();
-        if (p != null && registrations.isEmpty() && children.isEmpty()) {
-            p.removeChild(identifier);
-        }
-    }
-
-    private void removeChild(final PathArgument arg) {
-        children.remove(arg);
-        removeThisIfUnused();
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("identifier", identifier)
-                .add("registrations", registrations.size())
-                .add("children", children.size()).toString();
-    }
-}
diff --git a/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeSnapshot.java b/dom/mdsal-dom-spi/src/main/java/org/opendaylight/mdsal/dom/spi/RegistrationTreeSnapshot.java
deleted file mode 100644 (file)
index af33832..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. 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.mdsal.dom.spi;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.concurrent.locks.Lock;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.opendaylight.yangtools.concepts.AbstractRegistration;
-
-/**
- * A stable read-only snapshot of a {@link AbstractRegistrationTree}.
- *
- * @author Robert Varga
- */
-@NonNullByDefault
-public final class RegistrationTreeSnapshot<T> extends AbstractRegistration {
-    private final RegistrationTreeNode<T> node;
-    private final Lock lock;
-
-    RegistrationTreeSnapshot(final Lock lock, final RegistrationTreeNode<T> node) {
-        this.lock = requireNonNull(lock);
-        this.node = requireNonNull(node);
-    }
-
-    public RegistrationTreeNode<T> getRootNode() {
-        return node;
-    }
-
-    @Override
-    protected void removeRegistration() {
-        lock.unlock();
-    }
-}
index d7dbeed74456d7aa9d4da3449b56dce067d38a32..18c2c702290bd4ebbad1c30e6b26ad491d94f41c 100644 (file)
@@ -19,7 +19,6 @@ import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener;
 import org.opendaylight.mdsal.dom.spi.AbstractDOMDataTreeChangeListenerRegistration;
 import org.opendaylight.mdsal.dom.spi.AbstractRegistrationTree;
-import org.opendaylight.mdsal.dom.spi.RegistrationTreeNode;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
@@ -93,7 +92,7 @@ public abstract class AbstractDOMStoreTreeChangePublisher
         // Take the write lock
         takeLock();
         try {
-            final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> node =
+            final Node<AbstractDOMDataTreeChangeListenerRegistration<?>> node =
                     findNodeFor(treeId.getPathArguments());
             final var reg = new AbstractDOMDataTreeChangeListenerRegistration<>(listener) {
                 @Override
@@ -112,19 +111,19 @@ public abstract class AbstractDOMStoreTreeChangePublisher
     }
 
     private void lookupAndNotify(final List<PathArgument> args,
-            final int offset, final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> node,
+            final int offset, final Node<AbstractDOMDataTreeChangeListenerRegistration<?>> node,
             final DataTreeCandidate candidate,
             final Multimap<AbstractDOMDataTreeChangeListenerRegistration<?>, DataTreeCandidate> listenerChanges) {
         if (args.size() != offset) {
             final PathArgument arg = args.get(offset);
 
-            final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> exactChild
+            final Node<AbstractDOMDataTreeChangeListenerRegistration<?>> exactChild
                 = node.getExactChild(arg);
             if (exactChild != null) {
                 lookupAndNotify(args, offset + 1, exactChild, candidate, listenerChanges);
             }
 
-            for (RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> c :
+            for (Node<AbstractDOMDataTreeChangeListenerRegistration<?>> c :
                     node.getInexactChildren(arg)) {
                 lookupAndNotify(args, offset + 1, c, candidate, listenerChanges);
             }
@@ -134,7 +133,7 @@ public abstract class AbstractDOMStoreTreeChangePublisher
     }
 
     private void notifyNode(final YangInstanceIdentifier path,
-            final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> regNode,
+            final Node<AbstractDOMDataTreeChangeListenerRegistration<?>> regNode,
             final DataTreeCandidateNode candNode,
             final Multimap<AbstractDOMDataTreeChangeListenerRegistration<?>, DataTreeCandidate> listenerChanges) {
         if (candNode.modificationType() == ModificationType.UNMODIFIED) {
index 9656d7a7201a56031f0917fc858bed9018d60e79..c97f7b52feed818b3683f7c57963e9ddb7371174 100644 (file)
@@ -21,9 +21,9 @@ public class AbstractRegistrationTreeTest extends AbstractRegistrationTree<Objec
     @Test
     public void basicTest() throws Exception {
         final NodeIdentifier pathArgument = new NodeIdentifier(QName.create("", "pathArgument"));
-        final RegistrationTreeNode<Object> registrationTreeNodeParent = new RegistrationTreeNode<>(null, pathArgument);
-        final RegistrationTreeNode<Object> registrationTreeNode =
-                new RegistrationTreeNode<>(registrationTreeNodeParent, pathArgument);
+        final Node<Object> registrationTreeNodeParent = new Node<>(null, pathArgument);
+        final Node<Object> registrationTreeNode =
+                new Node<>(registrationTreeNodeParent, pathArgument);
 
         final Object registration = new Object();
         takeLock();
index 6e0d10c8588e9644b0f88dc3e190b7dbb6d94a65..9573743c9d2be0d61ef2ace3ebdaf43cbc67cb36 100644 (file)
@@ -7,43 +7,45 @@
  */
 package org.opendaylight.mdsal.dom.spi;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+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.assertTrue;
 
 import java.util.List;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.opendaylight.mdsal.dom.spi.AbstractRegistrationTree.Node;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
 
-public class RegistrationTreeNodeTest {
+class RegistrationTreeNodeTest {
     @Test
-    public void basicTest() throws Exception {
-        final NodeIdentifier pathArgument = new NodeIdentifier(QName.create("", "pathArgument"));
-        final RegistrationTreeNode<Object> registrationTreeNodeParent = new RegistrationTreeNode<>(null, pathArgument);
-        final RegistrationTreeNode<Object> registrationTreeNode =
-                new RegistrationTreeNode<>(registrationTreeNodeParent, pathArgument);
+    void basicTest() {
+        final var pathArgument = new NodeIdentifier(QName.create("", "pathArgument"));
+        final var registrationTreeNodeParent = new Node<>(null, pathArgument);
+        final var registrationTreeNode = new Node<>(registrationTreeNodeParent, pathArgument);
 
         assertEquals(pathArgument, registrationTreeNode.getIdentifier());
 
-        final Object registration = new Object();
-        assertFalse(registrationTreeNode.getRegistrations().contains(registration));
+        final var registration = new Object();
+        final var registrations = registrationTreeNode.getRegistrations();
+        assertEquals(List.of(), registrations);
         registrationTreeNode.addRegistration(registration);
-        assertTrue(registrationTreeNode.getRegistrations().contains(registration));
+        assertEquals(List.of(registration), registrations);
         registrationTreeNode.removeRegistration(registration);
-        assertFalse(registrationTreeNode.getRegistrations().contains(registration));
+        assertEquals(List.of(), registrations);
         registrationTreeNode.removeRegistration(registration);
+        assertEquals(List.of(), registrations);
 
         assertNotNull(registrationTreeNode.ensureChild(pathArgument));
         assertNotNull(registrationTreeNode.getExactChild(pathArgument));
 
-        final NodeWithValue<?> nodeWithValue = new NodeWithValue<>(QName.create("", "testNode"), new Object());
+        final var nodeWithValue = new NodeWithValue<>(QName.create("", "testNode"), new Object());
         assertEquals(List.of(), registrationTreeNode.getInexactChildren(nodeWithValue));
         assertEquals(List.of(), registrationTreeNode.getInexactChildren(pathArgument));
 
-        final NodeIdentifier nodeWithoutValue = new NodeIdentifier(QName.create("", "testNode"));
+        final var nodeWithoutValue = new NodeIdentifier(QName.create("", "testNode"));
         assertNotNull(registrationTreeNode.ensureChild(nodeWithoutValue));
         assertFalse(registrationTreeNode.getInexactChildren(nodeWithValue).isEmpty());
 
index 1903bbf8dbaa4bef3441f510d4a1e59011f4c5ea..776977909041522439469d29cb4d86eda4c9486b 100644 (file)
@@ -7,31 +7,32 @@
  */
 package org.opendaylight.mdsal.dom.spi;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
 
 import java.util.concurrent.locks.Lock;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.opendaylight.mdsal.dom.spi.AbstractRegistrationTree.Node;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 
-public class RegistrationTreeSnapshotTest {
-    @Test
-    public void basicTest() throws Exception {
-        final Lock lock = mock(Lock.class);
-        final NodeIdentifier pathArgument = new NodeIdentifier(QName.create("", "pathArgument"));
-        final RegistrationTreeNode<?> registrationTreeNode = new RegistrationTreeNode<>(null, pathArgument);
-        final RegistrationTreeSnapshot<?> registrationTreeSnapshot =
-                new RegistrationTreeSnapshot<>(lock, registrationTreeNode);
-
-        assertNotNull(registrationTreeSnapshot.getRootNode());
-        assertEquals(registrationTreeNode, registrationTreeSnapshot.getRootNode());
+@ExtendWith(MockitoExtension.class)
+class RegistrationTreeSnapshotTest {
+    @Mock
+    private Lock lock;
 
-        doNothing().when(lock).unlock();
-        registrationTreeSnapshot.close();
-        verify(lock).unlock();
+    @Test
+    void basicTest() throws Exception {
+        final var pathArgument = new NodeIdentifier(QName.create("", "pathArgument"));
+        final var registrationTreeNode = new Node<>(null, pathArgument);
+        try (var registrationTreeSnapshot = new AbstractRegistrationTree.Snapshot<>(lock, registrationTreeNode)) {
+            assertNotNull(registrationTreeSnapshot.getRootNode());
+            assertEquals(registrationTreeNode, registrationTreeSnapshot.getRootNode());
+            doNothing().when(lock).unlock();
+        }
     }
 }
\ No newline at end of file