ConcurrentRadixTree implements RadixTree<O>, PrettyPrintable, Serializable { @Override public O put(CharSequence key, O value) { @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) O existingValue = (O) putInternal(key, value, true); return existingValue; } ConcurrentRadixTree(NodeFactory nodeFactory); @Override O put(CharSequence key, O value); @Override O putIfAbsent(CharSequence key, O value); @Override O getValueForExactKey(CharSequence key); @Override Iterable<CharSequence> getKeysStartingWith(CharSequence prefix); @Override Iterable<O> getValuesForKeysStartingWith(CharSequence prefix); @Override Iterable<KeyValuePair<O>> getKeyValuePairsForKeysStartingWith(CharSequence prefix); @Override boolean remove(CharSequence key); @Override Iterable<CharSequence> getClosestKeys(CharSequence candidate); @Override Iterable<O> getValuesForClosestKeys(CharSequence candidate); @Override Iterable<KeyValuePair<O>> getKeyValuePairsForClosestKeys(CharSequence candidate); @Override int size(); @Override Node getNode();  }
@Test public void testPut_AppendChild() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("FOO", 1); tree.put("FOOBAR", 2); String expected = "○\n" + "└── ○ FOO (1)\n" + " └── ○ BAR (2)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test public void testPut_SplitEdge() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("FOOBAR", 1); tree.put("FOO", 2); String expected = "○\n" + "└── ○ FOO (2)\n" + " └── ○ BAR (1)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test public void testPut_SplitWithImplicitNode() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("FOOBAR", 1); tree.put("FOOD", 2); String expected = "○\n" + "└── ○ FOO\n" + " ├── ○ BAR (1)\n" + " └── ○ D (2)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test public void testPut_SplitAndMove() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("TEST", 1); tree.put("TEAM", 2); tree.put("TOAST", 3); String expected = "○\n" + "└── ○ T\n" + " ├── ○ E\n" + " │ ├── ○ AM (2)\n" + " │ └── ○ ST (1)\n" + " └── ○ OAST (3)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test public void testPut_VoidValue_CharArrayNodeFactory() { ConcurrentRadixTree<VoidValue> tree = new ConcurrentRadixTree<VoidValue>(getNodeFactory()); tree.put("FOO", VoidValue.SINGLETON); tree.put("FOOBAR", VoidValue.SINGLETON); String expected = "○\n" + "└── ○ FOO (-)\n" + " └── ○ BAR (-)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test public void testPut_VoidValue_CharSequenceNodeFactory() { ConcurrentRadixTree<VoidValue> tree = new ConcurrentRadixTree<VoidValue>(new DefaultCharSequenceNodeFactory()); tree.put("FOO", VoidValue.SINGLETON); tree.put("FOOBAR", VoidValue.SINGLETON); String expected = "○\n" + "└── ○ FOO (-)\n" + " └── ○ BAR (-)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test(expected = IllegalArgumentException.class) public void testPutInternal_ArgumentValidation1() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put(null, 1); }
@Test(expected = IllegalArgumentException.class) public void testPutInternal_ArgumentValidation2() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("FOO", null); }
@Test(expected = IllegalArgumentException.class) public void testPutInternal_ArgumentValidation3() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("", 1); }
@Test(expected = IllegalStateException.class) public void testPutInternal_InvalidClassification() { class InvalidSearchResult extends ConcurrentRadixTree.SearchResult { InvalidSearchResult(CharSequence key, Node nodeFound, int charsMatched, int charsMatchedInNodeFound, Node parentNode, Node parentNodesParent) { super(key, nodeFound, charsMatched, charsMatchedInNodeFound, parentNode, parentNodesParent); } @Override protected Classification classify(CharSequence key, Node nodeFound, int charsMatched, int charsMatchedInNodeFound) { return Classification.INVALID; } } ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()) { @Override SearchResult searchTree(CharSequence key) { return new InvalidSearchResult("FOO", root, 4, 4, null, null); } }; tree.put("FOO", 1); }
@Test public void testSerialization() { ConcurrentRadixTree<Integer> tree1 = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree1.put("TEST", 1); tree1.put("TEAM", 2); tree1.put("TOAST", 3); ConcurrentRadixTree<Integer> tree2 = TestUtility.deserialize(ConcurrentRadixTree.class, TestUtility.serialize(tree1)); assertEquals(PrettyPrinter.prettyPrint(tree1), PrettyPrinter.prettyPrint(tree2)); }
@Test public void testPut_AddToRoot() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("A", 1); String expected = "○\n" + "└── ○ A (1)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test public void testPut_ChildNodeSorting() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.put("B", 1); tree.put("A", 2); String expected = "○\n" + "├── ○ A (2)\n" + "└── ○ B (1)\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }