Add AbstractIRObject equality contract 73/102673/2
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 13 Oct 2022 16:40:40 +0000 (18:40 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 13 Oct 2022 16:53:21 +0000 (18:53 +0200)
Make sure the objects we are giving out implement proper equality. Also
use JDK17 features to seal the class hierarchy.

Change-Id: Iff7f3fa1f071f44e41eb322e8adc070030cdbd30
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/ir/AbstractIRObject.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/ir/IRArgument.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/ir/IRKeyword.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/ir/IRStatement.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/ir/IRStatement044.java

index ab7102869f4182aaaba91a4ea3d2f99489c4788b..23a742d150b14f0821dd403bd6e433e63da63e55 100644 (file)
@@ -10,7 +10,13 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.ir;
 import com.google.common.base.MoreObjects;
 import org.opendaylight.yangtools.concepts.Immutable;
 
-abstract class AbstractIRObject implements Immutable {
+abstract sealed class AbstractIRObject implements Immutable permits IRArgument, IRKeyword, IRStatement {
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract boolean equals(Object obj);
+
     @Override
     public final String toString() {
         return MoreObjects.toStringHelper(this).add("fragment", toYangFragment(new StringBuilder())).toString();
index a4b6989eae3727cef5fe902d2a566687924d2176..b439dfe6dc9f4d302e49c5f16d10d2524062bc83 100644 (file)
@@ -11,7 +11,6 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
-import java.util.Iterator;
 import java.util.List;
 import org.eclipse.jdt.annotation.NonNull;
 
@@ -43,7 +42,7 @@ import org.eclipse.jdt.annotation.NonNull;
  * </ul>
  */
 @Beta
-public abstract class IRArgument extends AbstractIRObject {
+public abstract sealed class IRArgument extends AbstractIRObject {
     /**
      * An argument composed of multiple concatenated parts.
      */
@@ -63,9 +62,19 @@ public abstract class IRArgument extends AbstractIRObject {
             return parts;
         }
 
+        @Override
+        public int hashCode() {
+            return parts.hashCode();
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            return this == obj || obj instanceof Concatenation other && parts.equals(other.parts);
+        }
+
         @Override
         StringBuilder toYangFragment(final StringBuilder sb) {
-            final Iterator<Single> it = parts.iterator();
+            final var it = parts.iterator();
             it.next().toYangFragment(sb);
             while (it.hasNext()) {
                 it.next().toYangFragment(sb.append(" + "));
@@ -87,7 +96,7 @@ public abstract class IRArgument extends AbstractIRObject {
      * The subclasses may very much change, in terms of both naming and function, to support whatever StatementFactory
      * ends up doing.
      */
-    public abstract static class Single extends IRArgument {
+    public abstract static sealed class Single extends IRArgument {
         private final @NonNull String string;
 
         Single(final String string) {
@@ -153,6 +162,17 @@ public abstract class IRArgument extends AbstractIRObject {
             return this instanceof Identifier;
         }
 
+        @Override
+        public final int hashCode() {
+            return string.hashCode();
+        }
+
+        @Override
+        public final boolean equals(final Object obj) {
+            return this == obj || obj != null && getClass().equals(obj.getClass())
+                && string.equals(((Single) obj).string);
+        }
+
         @Override
         StringBuilder toYangFragment(final StringBuilder sb) {
             return sb.append(string);
index 0df3c4d2e982d74d0ba9a9ad08b291d7504e01b7..af7932f78a9b89b132afc372013d844502e614d8 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.ir;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.Beta;
+import java.util.Objects;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.AbstractQName;
@@ -26,7 +27,7 @@ import org.opendaylight.yangtools.yang.common.AbstractQName;
  * that connection, rather than following the RFC-assigned names.
  */
 @Beta
-public abstract class IRKeyword extends AbstractIRObject {
+public abstract sealed class IRKeyword extends AbstractIRObject {
     @Beta
     public static final class Qualified extends IRKeyword {
         private final @NonNull String prefix;
@@ -77,7 +78,7 @@ public abstract class IRKeyword extends AbstractIRObject {
     private final @NonNull String identifier;
 
     IRKeyword(final String localName) {
-        this.identifier = requireNonNull(localName);
+        identifier = requireNonNull(localName);
     }
 
     /**
@@ -113,4 +114,15 @@ public abstract class IRKeyword extends AbstractIRObject {
      * @return Declaration string.
      */
     public abstract @NonNull String asStringDeclaration();
+
+    @Override
+    public final int hashCode() {
+        return Objects.hashCode(prefix()) * 31 + identifier.hashCode();
+    }
+
+    @Override
+    public final boolean equals(final Object obj) {
+        return this == obj || obj instanceof IRKeyword other && identifier.equals(other.identifier)
+            && Objects.equals(prefix(), other.prefix());
+    }
 }
index e9d49c33769aceebcff92b7f1c7dca3e3560ce41..400127b685958e4d90b1300aba0718389d68ebe3 100644 (file)
@@ -12,6 +12,7 @@ import static java.util.Objects.requireNonNull;
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
+import java.util.Objects;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 
@@ -24,7 +25,8 @@ import org.eclipse.jdt.annotation.Nullable;
  * </ul>
  */
 @Beta
-public abstract class IRStatement extends AbstractIRObject {
+public abstract sealed class IRStatement extends AbstractIRObject
+        permits IRStatement022, IRStatement031, IRStatement044 {
     private final @NonNull IRKeyword keyword;
     private final IRArgument argument;
 
@@ -83,7 +85,7 @@ public abstract class IRStatement extends AbstractIRObject {
             argument.toYangFragment(sb.append(' '));
         }
 
-        final List<? extends IRStatement> statements = statements();
+        final var statements = statements();
         if (statements.isEmpty()) {
             return sb.append(';');
         }
@@ -94,4 +96,16 @@ public abstract class IRStatement extends AbstractIRObject {
         }
         return sb.append('}');
     }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(keyword, argument, statements()) ^ startLine() ^ startColumn();
+    }
+
+    @Override
+    public final boolean equals(final Object obj) {
+        return obj == this || obj instanceof IRStatement other && keyword.equals(other.keyword)
+            && Objects.equals(argument, other.argument) && startLine() == other.startLine()
+            && startColumn() == other.startColumn() && statements().equals(other.statements());
+    }
 }
index ed8dfc69fa59042afdc0857dbb1b0ebd936cf8e9..d0d45882fa19c6a96057203af82c6ab3f912f494 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.ir;
 
-class IRStatement044 extends IRStatement {
+sealed class IRStatement044 extends IRStatement permits IRStatement144, IRStatementL44 {
     private final int startLine;
     private final int startColumn;