From 587bb60fa54c63dfbb9b03f11d26b03fb0afe845 Mon Sep 17 00:00:00 2001 From: Querz Date: Sun, 9 Dec 2018 20:37:28 +0100 Subject: [PATCH] all tags should implement hashCode() --- src/main/java/net/querz/nbt/ByteArrayTag.java | 5 ++ src/main/java/net/querz/nbt/CompoundTag.java | 13 +-- src/main/java/net/querz/nbt/EndTag.java | 2 +- src/main/java/net/querz/nbt/IntArrayTag.java | 5 ++ src/main/java/net/querz/nbt/ListTag.java | 11 +-- src/main/java/net/querz/nbt/LongArrayTag.java | 5 ++ src/main/java/net/querz/nbt/Tag.java | 7 +- .../java/net/querz/nbt/custom/ObjectTag.java | 15 ++-- .../net/querz/nbt/custom/ShortArrayTag.java | 5 ++ .../java/net/querz/nbt/custom/StructTag.java | 12 +-- .../java/net/querz/nbt/CompoundTagTest.java | 86 ++++++++++++++++++- .../java/net/querz/nbt/TagFactoryTest.java | 2 +- .../net/querz/nbt/custom/ObjectTagTest.java | 19 +++- .../querz/nbt/custom/ShortArrayTagTest.java | 8 ++ .../net/querz/nbt/custom/StructTagTest.java | 10 +++ 15 files changed, 175 insertions(+), 30 deletions(-) diff --git a/src/main/java/net/querz/nbt/ByteArrayTag.java b/src/main/java/net/querz/nbt/ByteArrayTag.java index bc6ef765..e14ed352 100644 --- a/src/main/java/net/querz/nbt/ByteArrayTag.java +++ b/src/main/java/net/querz/nbt/ByteArrayTag.java @@ -49,6 +49,11 @@ public boolean equals(Object other) { && Arrays.equals(getValue(), ((ByteArrayTag) other).getValue())); } + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } + @Override public ByteArrayTag clone() { return new ByteArrayTag(Arrays.copyOf(getValue(), length())); diff --git a/src/main/java/net/querz/nbt/CompoundTag.java b/src/main/java/net/querz/nbt/CompoundTag.java index 3d339b96..93d45876 100644 --- a/src/main/java/net/querz/nbt/CompoundTag.java +++ b/src/main/java/net/querz/nbt/CompoundTag.java @@ -3,11 +3,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.BiConsumer; public class CompoundTag extends Tag> implements Iterable> { @@ -293,6 +289,13 @@ public boolean equals(Object other) { return true; } + @Override + public int hashCode() { + int keyHash = Objects.hash(getValue().keySet().toArray()); + int valueHash = Objects.hash(values().toArray()); + return Objects.hash(keyHash, valueHash); + } + @Override public int compareTo(Tag> o) { if (!(o instanceof CompoundTag)) { diff --git a/src/main/java/net/querz/nbt/EndTag.java b/src/main/java/net/querz/nbt/EndTag.java index 1ef1a63f..2fd2e9fe 100644 --- a/src/main/java/net/querz/nbt/EndTag.java +++ b/src/main/java/net/querz/nbt/EndTag.java @@ -45,7 +45,7 @@ public int compareTo(Tag o) { } @Override - protected EndTag clone() { + public EndTag clone() { return INSTANCE; } } diff --git a/src/main/java/net/querz/nbt/IntArrayTag.java b/src/main/java/net/querz/nbt/IntArrayTag.java index 9fa884ba..302b07e5 100644 --- a/src/main/java/net/querz/nbt/IntArrayTag.java +++ b/src/main/java/net/querz/nbt/IntArrayTag.java @@ -53,6 +53,11 @@ public boolean equals(Object other) { && Arrays.equals(getValue(), ((IntArrayTag) other).getValue())); } + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } + @Override public IntArrayTag clone() { return new IntArrayTag(Arrays.copyOf(getValue(), length())); diff --git a/src/main/java/net/querz/nbt/ListTag.java b/src/main/java/net/querz/nbt/ListTag.java index 5007b284..a450d7d1 100644 --- a/src/main/java/net/querz/nbt/ListTag.java +++ b/src/main/java/net/querz/nbt/ListTag.java @@ -3,11 +3,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; +import java.util.*; import java.util.function.Consumer; public class ListTag extends Tag> implements Iterable { @@ -311,6 +307,11 @@ public boolean equals(Object other) { return true; } + @Override + public int hashCode() { + return Objects.hash(getValue().toArray()); + } + @Override public int compareTo(Tag> o) { if (!(o instanceof ListTag)) { diff --git a/src/main/java/net/querz/nbt/LongArrayTag.java b/src/main/java/net/querz/nbt/LongArrayTag.java index 41741e35..f3a4c404 100644 --- a/src/main/java/net/querz/nbt/LongArrayTag.java +++ b/src/main/java/net/querz/nbt/LongArrayTag.java @@ -53,6 +53,11 @@ public boolean equals(Object other) { && Arrays.equals(getValue(), ((LongArrayTag) other).getValue())); } + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } + @Override public LongArrayTag clone() { return new LongArrayTag(Arrays.copyOf(getValue(), length())); diff --git a/src/main/java/net/querz/nbt/Tag.java b/src/main/java/net/querz/nbt/Tag.java index a2e62c76..815fd9aa 100644 --- a/src/main/java/net/querz/nbt/Tag.java +++ b/src/main/java/net/querz/nbt/Tag.java @@ -199,12 +199,17 @@ public boolean equals(Object other) { return other != null && getClass() == other.getClass(); } + @Override + public int hashCode() { + return value.hashCode(); + } + /** * Creates a clone of this Tag. * @return A clone of this Tag. * */ @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException") - protected abstract Tag clone(); + public abstract Tag clone(); /** * A utility method to check if some value is null. diff --git a/src/main/java/net/querz/nbt/custom/ObjectTag.java b/src/main/java/net/querz/nbt/custom/ObjectTag.java index 0cb8f922..f92482a3 100644 --- a/src/main/java/net/querz/nbt/custom/ObjectTag.java +++ b/src/main/java/net/querz/nbt/custom/ObjectTag.java @@ -2,12 +2,8 @@ import net.querz.nbt.Tag; import net.querz.nbt.TagFactory; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; + +import java.io.*; import java.lang.reflect.InvocationTargetException; public class ObjectTag extends Tag { @@ -58,7 +54,7 @@ public void serializeValue(DataOutputStream dos, int depth) throws IOException { public void deserializeValue(DataInputStream dis, int depth) throws IOException { try { setValue((T) new ObjectInputStream(dis).readObject()); - } catch (ClassNotFoundException e) { + } catch (InvalidClassException | ClassNotFoundException e) { throw new IOException(e.getCause()); } } @@ -81,6 +77,11 @@ public boolean equals(Object other) { && getValue().equals(((ObjectTag) other).getValue())); } + @Override + public int hashCode() { + return getValue().hashCode(); + } + @SuppressWarnings("unchecked") @Override public int compareTo(Tag o) { diff --git a/src/main/java/net/querz/nbt/custom/ShortArrayTag.java b/src/main/java/net/querz/nbt/custom/ShortArrayTag.java index 85a9ee9e..a973842c 100644 --- a/src/main/java/net/querz/nbt/custom/ShortArrayTag.java +++ b/src/main/java/net/querz/nbt/custom/ShortArrayTag.java @@ -59,6 +59,11 @@ public boolean equals(Object other) { && Arrays.equals(getValue(), ((ShortArrayTag) other).getValue())); } + @Override + public int hashCode() { + return Arrays.hashCode(getValue()); + } + @Override public ShortArrayTag clone() { return new ShortArrayTag(Arrays.copyOf(getValue(), length())); diff --git a/src/main/java/net/querz/nbt/custom/StructTag.java b/src/main/java/net/querz/nbt/custom/StructTag.java index e9904d01..009877c6 100644 --- a/src/main/java/net/querz/nbt/custom/StructTag.java +++ b/src/main/java/net/querz/nbt/custom/StructTag.java @@ -17,10 +17,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; +import java.util.*; import java.util.function.Consumer; public class StructTag extends Tag> implements Iterable { @@ -286,6 +283,11 @@ public boolean equals(Object other) { return true; } + @Override + public int hashCode() { + return Objects.hash(getValue().toArray()); + } + @Override public int compareTo(Tag> o) { if (!(o instanceof StructTag)) { @@ -298,7 +300,7 @@ public int compareTo(Tag> o) { public StructTag clone() { StructTag copy = new StructTag(); for (Tag tag : getValue()) { - copy.add(tag); + copy.add(tag.clone()); } return copy; } diff --git a/src/test/java/net/querz/nbt/CompoundTagTest.java b/src/test/java/net/querz/nbt/CompoundTagTest.java index f7ea7201..0c295397 100644 --- a/src/test/java/net/querz/nbt/CompoundTagTest.java +++ b/src/test/java/net/querz/nbt/CompoundTagTest.java @@ -1,10 +1,9 @@ package net.querz.nbt; -import junit.framework.TestCase; - import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; +import static org.junit.Assert.assertNotEquals; public class CompoundTagTest extends NBTTestCase { @@ -50,6 +49,89 @@ public void testEquals() { assertEquals(ct, ct); } + public void testHashCode() { + CompoundTag t = new CompoundTag(); + for (int i = 0; i < 256; i++) { + t.putByte("key_byte" + i, (byte) i); + t.putShort("key_short" + i, (short) i); + t.putInt("key_int" + i, i); + t.putLong("key_long" + i, i); + t.putFloat("key_float" + i, i * 1.001f); + t.putDouble("key_double" + i, i * 1.001); + t.putString("key_string" + i, "value" + i); + + byte[] bArray = new byte[257]; + int[] iArray = new int[257]; + long[] lArray = new long[257]; + for (byte b = -128; b < 127; b++) { + bArray[b + 128] = b; + iArray[b + 128] = b; + lArray[b + 128] = b; + } + bArray[256] = (byte) i; + iArray[256] = i; + lArray[256] = i; + t.putByteArray("key_byte_array" + i, bArray); + t.putIntArray("key_int_array" + i, iArray); + t.putLongArray("key_long_array" + i, lArray); + + ListTag l = new ListTag<>(); + for (int j = 0; j < 256; j++) { + l.addString("value" + j); + } + l.addString("value" + i); + t.put("key_list" + i, l); + + CompoundTag c = new CompoundTag(); + c.putString("key_string" + i, "value" + i); + t.put("key_child" + i, c); + } + CompoundTag t2 = new CompoundTag(); + for (int i = 0; i < 256; i++) { + t2.putString("key_string" + i, "value" + i); + t2.putDouble("key_double" + i, i * 1.001); + t2.putFloat("key_float" + i, i * 1.001f); + t2.putLong("key_long" + i, i); + t2.putInt("key_int" + i, i); + t2.putShort("key_short" + i, (short) i); + t2.putByte("key_byte" + i, (byte) i); + + byte[] bArray = new byte[257]; + int[] iArray = new int[257]; + long[] lArray = new long[257]; + for (byte b = -128; b < 127; b++) { + bArray[b + 128] = b; + iArray[b + 128] = b; + lArray[b + 128] = b; + } + bArray[256] = (byte) i; + iArray[256] = i; + lArray[256] = i; + t2.putByteArray("key_byte_array" + i, bArray); + t2.putIntArray("key_int_array" + i, iArray); + t2.putLongArray("key_long_array" + i, lArray); + + ListTag l = new ListTag<>(); + for (int j = 0; j < 256; j++) { + l.addString("value" + j); + } + l.addString("value" + i); + t2.put("key_list" + i, l); + + CompoundTag c = new CompoundTag(); + c.putString("key_string" + i, "value" + i); + t2.put("key_child" + i, c); + } + + assertEquals(t, t2); + assertEquals(t.hashCode(), t2.hashCode()); + + t.getCompoundTag("key_child1").remove("key_string1"); + + assertNotEquals(t, t2); + assertNotEquals(t.hashCode(), t2.hashCode()); + } + public void testClone() { CompoundTag ct = createCompoundTag(); CompoundTag cl = ct.clone(); diff --git a/src/test/java/net/querz/nbt/TagFactoryTest.java b/src/test/java/net/querz/nbt/TagFactoryTest.java index d2db03ee..742abacc 100644 --- a/src/test/java/net/querz/nbt/TagFactoryTest.java +++ b/src/test/java/net/querz/nbt/TagFactoryTest.java @@ -77,7 +77,7 @@ public String valueToTagString(int depth) { } @Override - protected InvalidCustomTag clone() { + public InvalidCustomTag clone() { return null; } diff --git a/src/test/java/net/querz/nbt/custom/ObjectTagTest.java b/src/test/java/net/querz/nbt/custom/ObjectTagTest.java index 0efa6722..43ad6d58 100644 --- a/src/test/java/net/querz/nbt/custom/ObjectTagTest.java +++ b/src/test/java/net/querz/nbt/custom/ObjectTagTest.java @@ -3,11 +3,10 @@ import net.querz.nbt.NBTTestCase; import net.querz.nbt.NBTUtil; import net.querz.nbt.TagFactory; - -import java.io.File; +import static org.junit.Assert.assertNotEquals; import java.io.IOException; import java.io.Serializable; -import java.util.Arrays; +import java.util.Objects; import java.util.Random; public class ObjectTagTest extends NBTTestCase implements Serializable { @@ -31,6 +30,15 @@ public void testEquals() { assertTrue(o.equals(o4)); } + public void testHashCode() { + DummyObject d = new DummyObject(); + DummyObject d2 = new DummyObject(); + ObjectTag o = new ObjectTag<>(d); + ObjectTag o2 = new ObjectTag<>(d2); + assertNotEquals(o.hashCode(), o2.hashCode()); + assertEquals(o.hashCode(), o.clone().hashCode()); + } + public void testClone() { DummyObject d = new DummyObject(); ObjectTag o = new ObjectTag<>(d); @@ -157,5 +165,10 @@ public boolean equals(Object other) { } return false; } + + @Override + public int hashCode() { + return Objects.hash(a, b, c, d, e, f); + } } } diff --git a/src/test/java/net/querz/nbt/custom/ShortArrayTagTest.java b/src/test/java/net/querz/nbt/custom/ShortArrayTagTest.java index 200e1b91..e4c3f3b9 100644 --- a/src/test/java/net/querz/nbt/custom/ShortArrayTagTest.java +++ b/src/test/java/net/querz/nbt/custom/ShortArrayTagTest.java @@ -2,6 +2,7 @@ import net.querz.nbt.NBTTestCase; import java.util.Arrays; +import static org.junit.Assert.assertNotEquals; public class ShortArrayTagTest extends NBTTestCase { @@ -21,6 +22,13 @@ public void testEquals() { assertFalse(t.equals(t3)); } + public void testHashCode() { + ShortArrayTag t = new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE}); + ShortArrayTag t2 = new ShortArrayTag(new short[]{Short.MAX_VALUE, 0, Short.MIN_VALUE}); + assertNotEquals(t.hashCode(), t2.hashCode()); + assertEquals(t.hashCode(), t.clone().hashCode()); + } + public void testClone() { ShortArrayTag t = new ShortArrayTag(new short[]{Short.MIN_VALUE, 0, Short.MAX_VALUE}); ShortArrayTag tc = t.clone(); diff --git a/src/test/java/net/querz/nbt/custom/StructTagTest.java b/src/test/java/net/querz/nbt/custom/StructTagTest.java index 24e7ecbb..be68d134 100644 --- a/src/test/java/net/querz/nbt/custom/StructTagTest.java +++ b/src/test/java/net/querz/nbt/custom/StructTagTest.java @@ -10,6 +10,7 @@ import net.querz.nbt.StringTag; import net.querz.nbt.Tag; import java.util.Arrays; +import static org.junit.Assert.assertNotEquals; public class StructTagTest extends NBTTestCase { @@ -45,6 +46,15 @@ public void testEquals() { assertFalse(s.equals(s4)); } + public void testHashCode() { + StructTag s = createStructTag(); + StructTag s2 = createStructTag(); + s2.addInt(123); + assertNotEquals(s.hashCode(), s2.hashCode()); + assertEquals(s.hashCode(), s.clone().hashCode()); + + } + public void testClone() { StructTag s = createStructTag(); StructTag c = s.clone();