Seal YangInstanceIdentifier 99/100799/5
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 25 Apr 2022 15:26:31 +0000 (17:26 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 26 Apr 2022 09:48:47 +0000 (11:48 +0200)
We only allow two implementations, make sure we express that to the
runtime.

Change-Id: I3e4f2208d30682a9a0d23d2e1114d9d5d790e9b7
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/YangInstanceIdentifier.java
data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidateNodesTest.java
data/yang-data-tree-spi/src/test/java/org/opendaylight/yangtools/yang/data/tree/spi/DataTreeCandidatesTest.java

index f0d9627fe8dfbceadbbc41a521ab39525af0c192..e45d760faa8c2b6466d87620d0b53e108ab48e59 100644 (file)
@@ -75,8 +75,8 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
  *
  * @see <a href="http://tools.ietf.org/html/rfc6020#section-9.13">RFC6020</a>
  */
-// FIXME: sealed once we have JDK17+
-public abstract class YangInstanceIdentifier implements HierarchicalIdentifier<YangInstanceIdentifier> {
+public abstract sealed class YangInstanceIdentifier implements HierarchicalIdentifier<YangInstanceIdentifier>
+        permits FixedYangInstanceIdentifier, StackedYangInstanceIdentifier {
     private static final long serialVersionUID = 4L;
     private static final VarHandle TO_STRING_CACHE;
     private static final VarHandle HASH;
@@ -233,7 +233,7 @@ public abstract class YangInstanceIdentifier implements HierarchicalIdentifier<Y
 
     @Override
     public final boolean equals(final Object obj) {
-        return this == obj || obj instanceof YangInstanceIdentifier && pathArgumentsEqual((YangInstanceIdentifier) obj);
+        return this == obj || obj instanceof YangInstanceIdentifier other && pathArgumentsEqual(other);
     }
 
     /**
@@ -977,15 +977,7 @@ public abstract class YangInstanceIdentifier implements HierarchicalIdentifier<Y
 
         @Override
         public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (!(obj instanceof AugmentationIdentifier)) {
-                return false;
-            }
-
-            AugmentationIdentifier that = (AugmentationIdentifier) obj;
-            return childNames.equals(that.childNames);
+            return this == obj || obj instanceof AugmentationIdentifier other && childNames.equals(other.childNames);
         }
 
         @Override
@@ -996,10 +988,9 @@ public abstract class YangInstanceIdentifier implements HierarchicalIdentifier<Y
         @Override
         @SuppressWarnings("checkstyle:parameterName")
         public int compareTo(final PathArgument o) {
-            if (!(o instanceof AugmentationIdentifier)) {
+            if (!(o instanceof AugmentationIdentifier other)) {
                 return -1;
             }
-            AugmentationIdentifier other = (AugmentationIdentifier) o;
             Set<QName> otherChildNames = other.getPossibleChildNames();
             int thisSize = childNames.size();
             int otherSize = otherChildNames.size();
index 0c8bfcc21988ddf199561491a5c59d1da1e7b902..c664b682b10c8deea21bf251eef80e161aa78ee0 100644 (file)
@@ -18,10 +18,11 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -29,6 +30,7 @@ import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModificationCursor;
 import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
 
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class DataTreeCandidateNodesTest {
     @Test
     public void testFromNormalizedNode() {
@@ -80,9 +82,8 @@ public class DataTreeCandidateNodesTest {
         doReturn(ModificationType.DELETE).when(mockedChildNode3ChildNode).getModificationType();
         doReturn(List.of(mockedChildNode3ChildNode)).when(mockedChildNode3).getChildNodes();
 
-        final Collection<DataTreeCandidateNode> childNodes = List.of(mockedChildNode1, mockedChildNode2,
-                mockedChildNode3);
-        doReturn(childNodes).when(mockedDataTreeCandidateNode).getChildNodes();
+        doReturn(List.of(mockedChildNode1, mockedChildNode2, mockedChildNode3))
+            .when(mockedDataTreeCandidateNode).getChildNodes();
 
         DataTreeCandidateNodes.applyToCursor(mockedCursor, mockedDataTreeCandidateNode);
         verify(mockedCursor, times(2)).enter((PathArgument) isNull());
@@ -104,31 +105,30 @@ public class DataTreeCandidateNodesTest {
     @Test
     public void testApplyRootedNodeToCursorWithWriteModificationType() {
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
         final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class);
 
         doReturn(ModificationType.WRITE).when(mockedDataTreeCandidateNode).getModificationType();
         final NormalizedNode mockedNormalizedNode = mock(NormalizedNode.class);
         doReturn(Optional.of(mockedNormalizedNode)).when(mockedDataTreeCandidateNode).getDataAfter();
-        DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath, mockedDataTreeCandidateNode);
+        DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(),
+            mockedDataTreeCandidateNode);
         verify(mockedCursor, times(1)).write(isNull(), any(NormalizedNode.class));
     }
 
     @Test
     public void testApplyRootedNodeToCursorWithDeleteModificationType() {
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
         final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class);
 
         doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType();
-        DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath, mockedDataTreeCandidateNode);
+        DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(),
+            mockedDataTreeCandidateNode);
         verify(mockedCursor, times(1)).delete(isNull());
     }
 
     @Test
     public void testApplyRootedNodeToCursorWithSubtreeModifiedModificationType() {
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
         final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class);
 
         doReturn(ModificationType.SUBTREE_MODIFIED).when(mockedDataTreeCandidateNode).getModificationType();
@@ -137,7 +137,8 @@ public class DataTreeCandidateNodesTest {
         doReturn(ModificationType.DELETE).when(mockedChildNode1).getModificationType();
         doReturn(List.of(mockedChildNode1)).when(mockedDataTreeCandidateNode).getChildNodes();
 
-        DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath, mockedDataTreeCandidateNode);
+        DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(),
+            mockedDataTreeCandidateNode);
         verify(mockedCursor, times(1)).enter((PathArgument) isNull());
         verify(mockedCursor, times(1)).delete(isNull());
     }
@@ -145,12 +146,11 @@ public class DataTreeCandidateNodesTest {
     @Test
     public void testApplyRootedNodeToCursorWithUnsupportedModificationType() {
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
         final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class);
 
         doReturn(ModificationType.APPEARED).when(mockedDataTreeCandidateNode).getModificationType();
         final IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
-            () -> DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, mockedRootPath,
+            () -> DataTreeCandidateNodes.applyRootedNodeToCursor(mockedCursor, YangInstanceIdentifier.empty(),
                 mockedDataTreeCandidateNode));
         assertThat(ex.getMessage(), containsString("Unsupported modification"));
     }
index 561004f72c9ae2e401aee3694ab9fe6c4b0bdda0..5be065cb40187f62e02a0b94f3f81c3e28b2e75e 100644 (file)
@@ -8,11 +8,11 @@
 package org.opendaylight.yangtools.yang.data.tree.spi;
 
 import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.doReturn;
@@ -23,7 +23,11 @@ import static org.mockito.Mockito.verify;
 import java.util.List;
 import java.util.Optional;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.tree.api.CursorAwareDataTreeModification;
@@ -33,34 +37,32 @@ import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModificationCursor;
 import org.opendaylight.yangtools.yang.data.tree.api.ModificationType;
 
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class DataTreeCandidatesTest {
+    private static final NodeIdentifier FOO = new NodeIdentifier(QName.create("foo", "foo"));
 
     @Test
     public void testNewDataTreeCandidate() {
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
-        final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.newDataTreeCandidate(mockedRootPath,
-                mockedDataTreeCandidateNode);
+        final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.newDataTreeCandidate(
+            YangInstanceIdentifier.empty(), mockedDataTreeCandidateNode);
 
-        assertNotNull(dataTreeCandidate);
-        assertTrue(dataTreeCandidate instanceof DefaultDataTreeCandidate);
-        assertEquals(mockedRootPath, dataTreeCandidate.getRootPath());
+        assertThat(dataTreeCandidate, instanceOf(DefaultDataTreeCandidate.class));
+        assertSame(YangInstanceIdentifier.empty(), dataTreeCandidate.getRootPath());
         assertEquals(mockedDataTreeCandidateNode, dataTreeCandidate.getRootNode());
-        assertTrue(dataTreeCandidate.toString().contains(
-                "DefaultDataTreeCandidate{rootPath=/, rootNode=Mock for DataTreeCandidateNode, hashCode: "));
+        assertThat(dataTreeCandidate.toString(),
+            containsString("DefaultDataTreeCandidate{rootPath=/, rootNode=Mock for DataTreeCandidateNode, hashCode: "));
     }
 
     @Test
     public void testFromNormalizedNode() {
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
         final NormalizedNode mockedNormalizedNode = mock(NormalizedNode.class);
-        final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.fromNormalizedNode(mockedRootPath,
-                mockedNormalizedNode);
+        final DataTreeCandidate dataTreeCandidate = DataTreeCandidates.fromNormalizedNode(
+            YangInstanceIdentifier.empty(), mockedNormalizedNode);
 
-        assertNotNull(dataTreeCandidate);
-        assertTrue(dataTreeCandidate instanceof DefaultDataTreeCandidate);
-        assertEquals(mockedRootPath, dataTreeCandidate.getRootPath());
-        assertTrue(dataTreeCandidate.getRootNode() instanceof NormalizedNodeDataTreeCandidateNode);
+        assertThat(dataTreeCandidate, instanceOf(DefaultDataTreeCandidate.class));
+        assertSame(YangInstanceIdentifier.empty(), dataTreeCandidate.getRootPath());
+        assertThat(dataTreeCandidate.getRootNode(), instanceOf(NormalizedNodeDataTreeCandidateNode.class));
     }
 
     @Test
@@ -80,32 +82,26 @@ public class DataTreeCandidatesTest {
         final DataTreeCandidate mockedDataTreeCandidate = mock(DataTreeCandidate.class);
         final CursorAwareDataTreeModification mockedModification = mock(CursorAwareDataTreeModification.class);
 
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
-        doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath();
-        final YangInstanceIdentifier mockedRootPathParent = mock(YangInstanceIdentifier.class);
-        doReturn(mockedRootPathParent).when(mockedRootPath).getParent();
+        doReturn(YangInstanceIdentifier.create(FOO)).when(mockedDataTreeCandidate).getRootPath();
 
         final DataTreeModificationCursor mockedCursor = mock(DataTreeModificationCursor.class);
-        doReturn(Optional.of(mockedCursor)).when(mockedModification).openCursor(mockedRootPathParent);
+        doReturn(Optional.of(mockedCursor)).when(mockedModification).openCursor(YangInstanceIdentifier.empty());
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
         doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode();
 
         doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType();
 
         DataTreeCandidates.applyToModification(mockedModification, mockedDataTreeCandidate);
-        verify(mockedRootPath, times(1)).getParent();
-        verify(mockedModification, times(1)).openCursor(mockedRootPathParent);
-        verify(mockedCursor, times(1)).delete(isNull());
+        verify(mockedModification, times(1)).openCursor(YangInstanceIdentifier.empty());
+        verify(mockedCursor, times(1)).delete(FOO);
     }
 
     @Test
     public void testApplyToCursorAwareModificationRoot() {
         final DataTreeCandidate mockedDataTreeCandidate = mock(DataTreeCandidate.class);
         final CursorAwareDataTreeModification mockedModification = mock(CursorAwareDataTreeModification.class);
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
-        doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath();
-        doReturn(null).when(mockedRootPath).getParent();
+        doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath();
         doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode();
         doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType();
 
@@ -121,13 +117,12 @@ public class DataTreeCandidatesTest {
 
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
         doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode();
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
-        doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath();
+        doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath();
 
         doReturn(ModificationType.DELETE).when(mockedDataTreeCandidateNode).getModificationType();
 
         DataTreeCandidates.applyToModification(mockedModification, mockedDataTreeCandidate);
-        verify(mockedModification, times(1)).delete(any(YangInstanceIdentifier.class));
+        verify(mockedModification, times(1)).delete(YangInstanceIdentifier.empty());
     }
 
     @Test
@@ -137,8 +132,7 @@ public class DataTreeCandidatesTest {
 
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
         doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode();
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
-        doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath();
+        doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath();
         final NormalizedNode mockedNormalizedNode = mock(NormalizedNode.class);
         doReturn(Optional.of(mockedNormalizedNode)).when(mockedDataTreeCandidateNode).getDataAfter();
 
@@ -155,8 +149,7 @@ public class DataTreeCandidatesTest {
 
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
         doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode();
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
-        doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath();
+        doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath();
 
         doReturn(ModificationType.SUBTREE_MODIFIED).when(mockedDataTreeCandidateNode).getModificationType();
 
@@ -174,11 +167,10 @@ public class DataTreeCandidatesTest {
 
         final DataTreeCandidateNode mockedChildNode3 = mock(DataTreeCandidateNode.class);
         doReturn(ModificationType.SUBTREE_MODIFIED).when(mockedChildNode3).getModificationType();
-        final PathArgument mockedPathArgument3 = mock(PathArgument.class);
-        doReturn(mockedPathArgument3).when(mockedChildNode3).getIdentifier();
         final DataTreeCandidateNode mockedChildNode3ChildNode = mock(DataTreeCandidateNode.class);
         doReturn(ModificationType.DELETE).when(mockedChildNode3ChildNode).getModificationType();
         final PathArgument mockedPathArgument31 = mock(PathArgument.class);
+        final PathArgument mockedPathArgument3 = mock(PathArgument.class);
         doReturn(mockedPathArgument3).when(mockedChildNode3).getIdentifier();
         doReturn(mockedPathArgument31).when(mockedChildNode3ChildNode).getIdentifier();
         doReturn(List.of(mockedChildNode3ChildNode)).when(mockedChildNode3).getChildNodes();
@@ -198,8 +190,7 @@ public class DataTreeCandidatesTest {
 
         final DataTreeCandidateNode mockedDataTreeCandidateNode = mock(DataTreeCandidateNode.class);
         doReturn(mockedDataTreeCandidateNode).when(mockedDataTreeCandidate).getRootNode();
-        final YangInstanceIdentifier mockedRootPath = mock(YangInstanceIdentifier.class);
-        doReturn(mockedRootPath).when(mockedDataTreeCandidate).getRootPath();
+        doReturn(YangInstanceIdentifier.empty()).when(mockedDataTreeCandidate).getRootPath();
 
         doReturn(ModificationType.APPEARED).when(mockedDataTreeCandidateNode).getModificationType();