diff --git a/src/main/java/com/mykola2312/retracker/bencode/BDict.java b/src/main/java/com/mykola2312/retracker/bencode/BDict.java new file mode 100644 index 0000000..ac1dfc1 --- /dev/null +++ b/src/main/java/com/mykola2312/retracker/bencode/BDict.java @@ -0,0 +1,41 @@ +package com.mykola2312.retracker.bencode; + +import com.mykola2312.retracker.bencode.error.BErrorKeyNotFound; +import com.mykola2312.retracker.bencode.error.BErrorNoChildren; +import com.mykola2312.retracker.bencode.error.BValueError; + +public class BDict extends BList { + @Override() + public BType getType() { + return BType.DICT; + } + + public BDict set(BValue key, BValue value) { + BValue node = find(key); + if (node != null) { + node.setNext(value); + } else { + key.setChild(value); + append(key); + } + + return this; + } + + public BDict set(String key, BValue value) { + return set(new BString(key), value); + } + + /* since we're going to employ builder pattern, we can't return null. + * chaining gets in one try-catch is better than checking every return value + */ + public BValue get(BValue key) throws BValueError { + BValue node = find(key); + if (node == null) throw new BErrorKeyNotFound(this, key); + + BValue value = node.getChild(); + if (value == node) throw new BErrorNoChildren(node); + + return value; + } +} diff --git a/src/main/java/com/mykola2312/retracker/bencode/BInteger.java b/src/main/java/com/mykola2312/retracker/bencode/BInteger.java index cab4c55..f06bbeb 100644 --- a/src/main/java/com/mykola2312/retracker/bencode/BInteger.java +++ b/src/main/java/com/mykola2312/retracker/bencode/BInteger.java @@ -20,4 +20,9 @@ public class BInteger extends BValue { public long get() { return value; } + + @Override + public String toString() { + return Long.toString(value); + } } diff --git a/src/main/java/com/mykola2312/retracker/bencode/BList.java b/src/main/java/com/mykola2312/retracker/bencode/BList.java index eca2f47..2387349 100644 --- a/src/main/java/com/mykola2312/retracker/bencode/BList.java +++ b/src/main/java/com/mykola2312/retracker/bencode/BList.java @@ -64,4 +64,18 @@ public class BList extends BValue { return it.next(); } + + public BValue find(BValue key) { + if (getLength() == 0) { + return null; + } + + for (BValue node : this) { + if (node.equals(key)) { + return node; + } + } + + return null; + } } diff --git a/src/main/java/com/mykola2312/retracker/bencode/error/BErrorKeyNotFound.java b/src/main/java/com/mykola2312/retracker/bencode/error/BErrorKeyNotFound.java new file mode 100644 index 0000000..2949359 --- /dev/null +++ b/src/main/java/com/mykola2312/retracker/bencode/error/BErrorKeyNotFound.java @@ -0,0 +1,11 @@ +package com.mykola2312.retracker.bencode.error; + +import com.mykola2312.retracker.bencode.BValue; + +public class BErrorKeyNotFound extends BValueError { + private static final long serialVersionUID = 4532538286014234752L; + + public BErrorKeyNotFound(BValue node, BValue key) { + super(node, key.toString()); + } +} diff --git a/src/main/java/com/mykola2312/retracker/bencode/error/BErrorNoChildren.java b/src/main/java/com/mykola2312/retracker/bencode/error/BErrorNoChildren.java index c286da0..f608cf3 100644 --- a/src/main/java/com/mykola2312/retracker/bencode/error/BErrorNoChildren.java +++ b/src/main/java/com/mykola2312/retracker/bencode/error/BErrorNoChildren.java @@ -2,7 +2,7 @@ package com.mykola2312.retracker.bencode.error; import com.mykola2312.retracker.bencode.BValue; -public class BErrorNoChildren extends BError { +public class BErrorNoChildren extends BValueError { private static final long serialVersionUID = -4503679050993811843L; public BErrorNoChildren(BValue node) { diff --git a/src/main/java/com/mykola2312/retracker/bencode/error/BError.java b/src/main/java/com/mykola2312/retracker/bencode/error/BValueError.java similarity index 70% rename from src/main/java/com/mykola2312/retracker/bencode/error/BError.java rename to src/main/java/com/mykola2312/retracker/bencode/error/BValueError.java index 0e51e23..6b577fd 100644 --- a/src/main/java/com/mykola2312/retracker/bencode/error/BError.java +++ b/src/main/java/com/mykola2312/retracker/bencode/error/BValueError.java @@ -2,12 +2,12 @@ package com.mykola2312.retracker.bencode.error; import com.mykola2312.retracker.bencode.BValue; -public class BError extends Exception { +public class BValueError extends Exception { private static final long serialVersionUID = 6950892783320917930L; public BValue node; - public BError(BValue node, String message) { + public BValueError(BValue node, String message) { super(message); this.node = node; } diff --git a/src/test/java/com/mykola2312/retracker/bencode/BDictTest.java b/src/test/java/com/mykola2312/retracker/bencode/BDictTest.java new file mode 100644 index 0000000..ac00789 --- /dev/null +++ b/src/test/java/com/mykola2312/retracker/bencode/BDictTest.java @@ -0,0 +1,45 @@ +package com.mykola2312.retracker.bencode; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +import com.mykola2312.retracker.bencode.error.BErrorKeyNotFound; +import com.mykola2312.retracker.bencode.error.BValueError; + +public class BDictTest { + @Test + public void testKeyValue() throws BValueError { + BDict dict = new BDict(); + + dict.set(new BString("first"), new BInteger(1)); + assertNotNull(dict.find(new BString("first"))); + assertNull(dict.find(new BString("second"))); + assertEquals(dict.get(new BString("first")), new BInteger(1)); + System.out.println(dict.get(new BString("first")).toString()); + + dict.set(new BString("second"), new BInteger(2)); + assertEquals(dict.get(new BString("second")), new BInteger(2)); + } + + @Test + public void testKeyNotFound() { + BDict empty = new BDict(); + + assertThrows(BErrorKeyNotFound.class, () -> { empty.get(new BString("non-existent")); }); + } + + @Test + public void testKeyChild() { + BDict dict = new BDict(); + dict.set(new BInteger(1), new BInteger(2)); + + BValue node = dict.find(new BInteger(1)); + assertNotNull(node); + assertNotNull(node.getChild()); + assertEquals(node.getChild(), new BInteger(2)); + } +} diff --git a/src/test/java/com/mykola2312/retracker/bencode/BListTest.java b/src/test/java/com/mykola2312/retracker/bencode/BListTest.java index 7f79dfd..3fb2117 100644 --- a/src/test/java/com/mykola2312/retracker/bencode/BListTest.java +++ b/src/test/java/com/mykola2312/retracker/bencode/BListTest.java @@ -1,6 +1,7 @@ package com.mykola2312.retracker.bencode; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -52,4 +53,15 @@ public class BListTest { assertThrows(IndexOutOfBoundsException.class, () -> list.get(3)); } + + @Test + public void testFind() { + BList list = new BList(); + list.append(new BInteger(1)); + list.append(new BInteger(2)); + + assertNotNull(list.find(new BInteger(1))); + assertNotNull(list.find(new BInteger(2))); + assertNull(list.find(new BInteger(3))); + } }