ConcurrentSuffixTree implements SuffixTree<O>, PrettyPrintable, Serializable { @Override public O put(CharSequence key, O value) { if (key == null) { throw new IllegalArgumentException("The key argument was null"); } if (key.length() == 0) { throw new IllegalArgumentException("The key argument was zero-length"); } if (value == null) { throw new IllegalArgumentException("The value argument was null"); } radixTree.acquireWriteLock(); try { String keyString = CharSequences.toString(key); final O replacedValue = valueMap.put(keyString, value); if (replacedValue == null) { addSuffixesToRadixTree(keyString); } return replacedValue; } finally { radixTree.releaseWriteLock(); } } ConcurrentSuffixTree(NodeFactory nodeFactory); @Override O put(CharSequence key, O value); @Override O putIfAbsent(CharSequence key, O value); @Override boolean remove(CharSequence key); @Override O getValueForExactKey(CharSequence key); @Override Iterable<CharSequence> getKeysEndingWith(CharSequence suffix); @Override Iterable<O> getValuesForKeysEndingWith(final CharSequence suffix); @Override Iterable<KeyValuePair<O>> getKeyValuePairsForKeysEndingWith(final CharSequence suffix); @Override Iterable<CharSequence> getKeysContaining(final CharSequence fragment); @Override Iterable<O> getValuesForKeysContaining(final CharSequence fragment); @Override Iterable<KeyValuePair<O>> getKeyValuePairsForKeysContaining(final CharSequence fragment); @Override int size(); @Override Node getNode();  }
@Test public void testPut_SingleKey() throws Exception { ConcurrentSuffixTree<Integer> tree = newConcurrentSuffixTreeForUnitTests(); tree.put("BANANA", 1); String expected = "○\n" + "├── ○ A ([BANANA])\n" + "│ └── ○ NA ([BANANA])\n" + "│ └── ○ NA ([BANANA])\n" + "├── ○ BANANA ([BANANA])\n" + "└── ○ NA ([BANANA])\n" + " └── ○ NA ([BANANA])\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test public void testPut_MultipleKeys() throws Exception { ConcurrentSuffixTree<Integer> tree = newConcurrentSuffixTreeForUnitTests(); tree.put("BANANA", 1); tree.put("BANDANA", 2); String expected = "○\n" + "├── ○ A ([BANANA, BANDANA])\n" + "│ └── ○ N\n" + "│ ├── ○ A ([BANANA, BANDANA])\n" + "│ │ └── ○ NA ([BANANA])\n" + "│ └── ○ DANA ([BANDANA])\n" + "├── ○ BAN\n" + "│ ├── ○ ANA ([BANANA])\n" + "│ └── ○ DANA ([BANDANA])\n" + "├── ○ DANA ([BANDANA])\n" + "└── ○ N\n" + " ├── ○ A ([BANANA, BANDANA])\n" + " │ └── ○ NA ([BANANA])\n" + " └── ○ DANA ([BANDANA])\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); }
@Test(expected = IllegalArgumentException.class) public void testPut_ArgumentValidation1() { ConcurrentSuffixTree<Integer> tree = newConcurrentSuffixTreeForUnitTests(); tree.put(null, 1); }
@Test(expected = IllegalArgumentException.class) public void testPut_ArgumentValidation2() { ConcurrentSuffixTree<Integer> tree = newConcurrentSuffixTreeForUnitTests(); tree.put("FOO", null); }
@Test(expected = IllegalArgumentException.class) public void testPut_ArgumentValidation3() { ConcurrentSuffixTree<Integer> tree = newConcurrentSuffixTreeForUnitTests(); tree.put("", 1); }
@Test public void testSerialization() { ConcurrentSuffixTree<Integer> tree1 = new ConcurrentSuffixTreeTestImpl<Integer>(getNodeFactory()); tree1.put("TEST", 1); tree1.put("TEAM", 2); tree1.put("TOAST", 3); ConcurrentSuffixTree<Integer> tree2 = TestUtility.deserialize(ConcurrentSuffixTree.class, TestUtility.serialize(tree1)); assertEquals(PrettyPrinter.prettyPrint(tree1), PrettyPrinter.prettyPrint(tree2)); }