@Test(expected = IllegalArgumentException.class) public void testRemove_ArgumentValidation() { ConcurrentRadixTree<Integer> tree = new ConcurrentRadixTree<Integer>(getNodeFactory()); tree.remove(null); }
@Override public boolean remove(CharSequence key) { if (key == null) { throw new IllegalArgumentException("The key argument was null"); } acquireWriteLock(); try { SearchResult searchResult = searchTree(key); SearchResult.Classification classification = searchResult.classification; switch (classification) { case EXACT_MATCH: { if (searchResult.nodeFound.getValue() == null) { return false; } List<Node> childEdges = searchResult.nodeFound.getOutgoingEdges(); if (childEdges.size() > 1) { @SuppressWarnings({"NullableProblems"}) Node cloned = nodeFactory.createNode(searchResult.nodeFound.getIncomingEdge(), null, searchResult.nodeFound.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(cloned); } else if (childEdges.size() == 1) { Node child = childEdges.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.nodeFound.getIncomingEdge(), child.getIncomingEdge()); Node mergedNode = nodeFactory.createNode(concatenatedEdges, child.getValue(), child.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(mergedNode); } else { List<Node> currentEdgesFromParent = searchResult.parentNode.getOutgoingEdges(); List<Node> newEdgesOfParent = Arrays.asList(new Node[searchResult.parentNode.getOutgoingEdges().size() - 1]); for (int i = 0, added = 0, numParentEdges = currentEdgesFromParent.size(); i < numParentEdges; i++) { Node node = currentEdgesFromParent.get(i); if (node != searchResult.nodeFound) { newEdgesOfParent.set(added++, node); } } boolean parentIsRoot = (searchResult.parentNode == root); Node newParent; if (newEdgesOfParent.size() == 1 && searchResult.parentNode.getValue() == null && !parentIsRoot) { Node parentsRemainingChild = newEdgesOfParent.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.parentNode.getIncomingEdge(), parentsRemainingChild.getIncomingEdge()); newParent = nodeFactory.createNode(concatenatedEdges, parentsRemainingChild.getValue(), parentsRemainingChild.getOutgoingEdges(), parentIsRoot); } else { newParent = nodeFactory.createNode(searchResult.parentNode.getIncomingEdge(), searchResult.parentNode.getValue(), newEdgesOfParent, parentIsRoot); } if (parentIsRoot) { this.root = newParent; } else { searchResult.parentNodesParent.updateOutgoingEdge(newParent); } } return true; } default: { return false; } } } finally { releaseWriteLock(); } }
ConcurrentRadixTree implements RadixTree<O>, PrettyPrintable, Serializable { @Override public boolean remove(CharSequence key) { if (key == null) { throw new IllegalArgumentException("The key argument was null"); } acquireWriteLock(); try { SearchResult searchResult = searchTree(key); SearchResult.Classification classification = searchResult.classification; switch (classification) { case EXACT_MATCH: { if (searchResult.nodeFound.getValue() == null) { return false; } List<Node> childEdges = searchResult.nodeFound.getOutgoingEdges(); if (childEdges.size() > 1) { @SuppressWarnings({"NullableProblems"}) Node cloned = nodeFactory.createNode(searchResult.nodeFound.getIncomingEdge(), null, searchResult.nodeFound.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(cloned); } else if (childEdges.size() == 1) { Node child = childEdges.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.nodeFound.getIncomingEdge(), child.getIncomingEdge()); Node mergedNode = nodeFactory.createNode(concatenatedEdges, child.getValue(), child.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(mergedNode); } else { List<Node> currentEdgesFromParent = searchResult.parentNode.getOutgoingEdges(); List<Node> newEdgesOfParent = Arrays.asList(new Node[searchResult.parentNode.getOutgoingEdges().size() - 1]); for (int i = 0, added = 0, numParentEdges = currentEdgesFromParent.size(); i < numParentEdges; i++) { Node node = currentEdgesFromParent.get(i); if (node != searchResult.nodeFound) { newEdgesOfParent.set(added++, node); } } boolean parentIsRoot = (searchResult.parentNode == root); Node newParent; if (newEdgesOfParent.size() == 1 && searchResult.parentNode.getValue() == null && !parentIsRoot) { Node parentsRemainingChild = newEdgesOfParent.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.parentNode.getIncomingEdge(), parentsRemainingChild.getIncomingEdge()); newParent = nodeFactory.createNode(concatenatedEdges, parentsRemainingChild.getValue(), parentsRemainingChild.getOutgoingEdges(), parentIsRoot); } else { newParent = nodeFactory.createNode(searchResult.parentNode.getIncomingEdge(), searchResult.parentNode.getValue(), newEdgesOfParent, parentIsRoot); } if (parentIsRoot) { this.root = newParent; } else { searchResult.parentNodesParent.updateOutgoingEdge(newParent); } } return true; } default: { return false; } } } finally { releaseWriteLock(); } } }
ConcurrentRadixTree implements RadixTree<O>, PrettyPrintable, Serializable { @Override public boolean remove(CharSequence key) { if (key == null) { throw new IllegalArgumentException("The key argument was null"); } acquireWriteLock(); try { SearchResult searchResult = searchTree(key); SearchResult.Classification classification = searchResult.classification; switch (classification) { case EXACT_MATCH: { if (searchResult.nodeFound.getValue() == null) { return false; } List<Node> childEdges = searchResult.nodeFound.getOutgoingEdges(); if (childEdges.size() > 1) { @SuppressWarnings({"NullableProblems"}) Node cloned = nodeFactory.createNode(searchResult.nodeFound.getIncomingEdge(), null, searchResult.nodeFound.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(cloned); } else if (childEdges.size() == 1) { Node child = childEdges.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.nodeFound.getIncomingEdge(), child.getIncomingEdge()); Node mergedNode = nodeFactory.createNode(concatenatedEdges, child.getValue(), child.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(mergedNode); } else { List<Node> currentEdgesFromParent = searchResult.parentNode.getOutgoingEdges(); List<Node> newEdgesOfParent = Arrays.asList(new Node[searchResult.parentNode.getOutgoingEdges().size() - 1]); for (int i = 0, added = 0, numParentEdges = currentEdgesFromParent.size(); i < numParentEdges; i++) { Node node = currentEdgesFromParent.get(i); if (node != searchResult.nodeFound) { newEdgesOfParent.set(added++, node); } } boolean parentIsRoot = (searchResult.parentNode == root); Node newParent; if (newEdgesOfParent.size() == 1 && searchResult.parentNode.getValue() == null && !parentIsRoot) { Node parentsRemainingChild = newEdgesOfParent.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.parentNode.getIncomingEdge(), parentsRemainingChild.getIncomingEdge()); newParent = nodeFactory.createNode(concatenatedEdges, parentsRemainingChild.getValue(), parentsRemainingChild.getOutgoingEdges(), parentIsRoot); } else { newParent = nodeFactory.createNode(searchResult.parentNode.getIncomingEdge(), searchResult.parentNode.getValue(), newEdgesOfParent, parentIsRoot); } if (parentIsRoot) { this.root = newParent; } else { searchResult.parentNodesParent.updateOutgoingEdge(newParent); } } return true; } default: { return false; } } } finally { releaseWriteLock(); } } ConcurrentRadixTree(NodeFactory nodeFactory); }
ConcurrentRadixTree implements RadixTree<O>, PrettyPrintable, Serializable { @Override public boolean remove(CharSequence key) { if (key == null) { throw new IllegalArgumentException("The key argument was null"); } acquireWriteLock(); try { SearchResult searchResult = searchTree(key); SearchResult.Classification classification = searchResult.classification; switch (classification) { case EXACT_MATCH: { if (searchResult.nodeFound.getValue() == null) { return false; } List<Node> childEdges = searchResult.nodeFound.getOutgoingEdges(); if (childEdges.size() > 1) { @SuppressWarnings({"NullableProblems"}) Node cloned = nodeFactory.createNode(searchResult.nodeFound.getIncomingEdge(), null, searchResult.nodeFound.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(cloned); } else if (childEdges.size() == 1) { Node child = childEdges.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.nodeFound.getIncomingEdge(), child.getIncomingEdge()); Node mergedNode = nodeFactory.createNode(concatenatedEdges, child.getValue(), child.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(mergedNode); } else { List<Node> currentEdgesFromParent = searchResult.parentNode.getOutgoingEdges(); List<Node> newEdgesOfParent = Arrays.asList(new Node[searchResult.parentNode.getOutgoingEdges().size() - 1]); for (int i = 0, added = 0, numParentEdges = currentEdgesFromParent.size(); i < numParentEdges; i++) { Node node = currentEdgesFromParent.get(i); if (node != searchResult.nodeFound) { newEdgesOfParent.set(added++, node); } } boolean parentIsRoot = (searchResult.parentNode == root); Node newParent; if (newEdgesOfParent.size() == 1 && searchResult.parentNode.getValue() == null && !parentIsRoot) { Node parentsRemainingChild = newEdgesOfParent.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.parentNode.getIncomingEdge(), parentsRemainingChild.getIncomingEdge()); newParent = nodeFactory.createNode(concatenatedEdges, parentsRemainingChild.getValue(), parentsRemainingChild.getOutgoingEdges(), parentIsRoot); } else { newParent = nodeFactory.createNode(searchResult.parentNode.getIncomingEdge(), searchResult.parentNode.getValue(), newEdgesOfParent, parentIsRoot); } if (parentIsRoot) { this.root = newParent; } else { searchResult.parentNodesParent.updateOutgoingEdge(newParent); } } return true; } default: { return false; } } } finally { releaseWriteLock(); } } 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(); }
ConcurrentRadixTree implements RadixTree<O>, PrettyPrintable, Serializable { @Override public boolean remove(CharSequence key) { if (key == null) { throw new IllegalArgumentException("The key argument was null"); } acquireWriteLock(); try { SearchResult searchResult = searchTree(key); SearchResult.Classification classification = searchResult.classification; switch (classification) { case EXACT_MATCH: { if (searchResult.nodeFound.getValue() == null) { return false; } List<Node> childEdges = searchResult.nodeFound.getOutgoingEdges(); if (childEdges.size() > 1) { @SuppressWarnings({"NullableProblems"}) Node cloned = nodeFactory.createNode(searchResult.nodeFound.getIncomingEdge(), null, searchResult.nodeFound.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(cloned); } else if (childEdges.size() == 1) { Node child = childEdges.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.nodeFound.getIncomingEdge(), child.getIncomingEdge()); Node mergedNode = nodeFactory.createNode(concatenatedEdges, child.getValue(), child.getOutgoingEdges(), false); searchResult.parentNode.updateOutgoingEdge(mergedNode); } else { List<Node> currentEdgesFromParent = searchResult.parentNode.getOutgoingEdges(); List<Node> newEdgesOfParent = Arrays.asList(new Node[searchResult.parentNode.getOutgoingEdges().size() - 1]); for (int i = 0, added = 0, numParentEdges = currentEdgesFromParent.size(); i < numParentEdges; i++) { Node node = currentEdgesFromParent.get(i); if (node != searchResult.nodeFound) { newEdgesOfParent.set(added++, node); } } boolean parentIsRoot = (searchResult.parentNode == root); Node newParent; if (newEdgesOfParent.size() == 1 && searchResult.parentNode.getValue() == null && !parentIsRoot) { Node parentsRemainingChild = newEdgesOfParent.get(0); CharSequence concatenatedEdges = CharSequences.concatenate(searchResult.parentNode.getIncomingEdge(), parentsRemainingChild.getIncomingEdge()); newParent = nodeFactory.createNode(concatenatedEdges, parentsRemainingChild.getValue(), parentsRemainingChild.getOutgoingEdges(), parentIsRoot); } else { newParent = nodeFactory.createNode(searchResult.parentNode.getIncomingEdge(), searchResult.parentNode.getValue(), newEdgesOfParent, parentIsRoot); } if (parentIsRoot) { this.root = newParent; } else { searchResult.parentNodesParent.updateOutgoingEdge(newParent); } } return true; } default: { return false; } } } finally { releaseWriteLock(); } } 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();  }