diff --git a/code/pom.xml b/code/pom.xml
index 69cc532..c7a1041 100644
--- a/code/pom.xml
+++ b/code/pom.xml
@@ -43,15 +43,17 @@
org.apache.maven.pluginsmaven-compiler-plugin2.3.2
- 1.6
- 1.6
+ 1.5
+ 1.5
+ true
+ true
+ -Xlint:all,-options,-processing
@@ -76,6 +78,9 @@
${project.build.outputDirectory}/META-INF/MANIFEST.MF
+
+ ${project.groupId}.${project.artifactId}
+
@@ -107,6 +112,27 @@
+
+
+ org.codehaus.mojo
+ animal-sniffer-maven-plugin
+ 1.16
+
+
+ test
+
+ check
+
+
+
+ org.codehaus.mojo.signature
+ java15
+ 1.0
+
+
+
+
+
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/common/CharSequences.java b/code/src/main/java/com/googlecode/concurrenttrees/common/CharSequences.java
index d128862..23f468b 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/common/CharSequences.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/common/CharSequences.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,12 +15,6 @@
*/
package com.googlecode.concurrenttrees.common;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CodingErrorAction;
import java.util.Iterator;
/**
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/common/Iterables.java b/code/src/main/java/com/googlecode/concurrenttrees/common/Iterables.java
index dbca4ca..a3bc9ea 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/common/Iterables.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/common/Iterables.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/common/KeyValuePair.java b/code/src/main/java/com/googlecode/concurrenttrees/common/KeyValuePair.java
index 4bc3f42..05840fb 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/common/KeyValuePair.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/common/KeyValuePair.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/common/LazyIterator.java b/code/src/main/java/com/googlecode/concurrenttrees/common/LazyIterator.java
index ab87c87..6004cbb 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/common/LazyIterator.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/common/LazyIterator.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
* Copyright 2007 The Guava Authors
*
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/common/PrettyPrinter.java b/code/src/main/java/com/googlecode/concurrenttrees/common/PrettyPrinter.java
index b34b6bb..46dbd07 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/common/PrettyPrinter.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/common/PrettyPrinter.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,7 @@
package com.googlecode.concurrenttrees.common;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.util.PrettyPrintable;
import java.io.IOException;
@@ -83,7 +84,7 @@ static void prettyPrint(Node node, Appendable sb, String prefix, boolean isTail,
StringBuilder label = new StringBuilder();
if (isRoot) {
label.append("○");
- if (node.getIncomingEdge().length() > 0) {
+ if (node.getIncomingEdgeLength() > 0) {
label.append(" ");
}
}
@@ -92,7 +93,7 @@ static void prettyPrint(Node node, Appendable sb, String prefix, boolean isTail,
label.append(" (").append(node.getValue()).append(")");
}
sb.append(prefix).append(isTail ? isRoot ? "" : "└── ○ " : "├── ○ ").append(label).append("\n");
- List children = node.getOutgoingEdges();
+ NodeList children = node.getOutgoingEdges();
for (int i = 0; i < children.size() - 1; i++) {
prettyPrint(children.get(i), sb, prefix + (isTail ? isRoot ? "" : " " : "│ "), false, false);
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/common/SetFromMap.java b/code/src/main/java/com/googlecode/concurrenttrees/common/SetFromMap.java
new file mode 100644
index 0000000..a63461b
--- /dev/null
+++ b/code/src/main/java/com/googlecode/concurrenttrees/common/SetFromMap.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2012-2013 Niall Gallagher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.concurrenttrees.common;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * A facade implementation of a Java set for representing a Java map implementation.
+ *
+ * @param The element type.
+ */
+public class SetFromMap extends AbstractSet implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Map delegate;
+
+ private transient Set keySet;
+
+ public SetFromMap(Map delegate) {
+ this.delegate = delegate;
+ keySet = delegate.keySet();
+ }
+
+ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ keySet = delegate.keySet();
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return delegate.containsKey(o);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return delegate.remove(o) != null;
+ }
+
+ @Override
+ public void clear() {
+ delegate.clear();
+ }
+
+ @Override
+ public boolean add(E e) {
+ return delegate.put(e, Boolean.TRUE) == null;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return keySet.iterator();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return keySet.toArray();
+ }
+
+ @Override
+ public T[] toArray(T[] a) {
+ return keySet.toArray(a);
+ }
+
+ @Override
+ public String toString() {
+ return keySet.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return keySet.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o == this || keySet.equals(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection> c) {
+ return keySet.containsAll(c);
+ }
+
+ @Override
+ public boolean removeAll(Collection> c) {
+ return keySet.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection> c) {
+ return keySet.retainAll(c);
+ }
+}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTree.java
index 7f745c8..2cd0229 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTree.java
@@ -20,6 +20,8 @@
import com.googlecode.concurrenttrees.common.LazyIterator;
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
import com.googlecode.concurrenttrees.radix.node.util.PrettyPrintable;
import java.io.Serializable;
@@ -40,6 +42,8 @@
* @author Niall Gallagher
*/
public class ConcurrentRadixTree implements RadixTree, PrettyPrintable, Serializable {
+
+ private static final long serialVersionUID = 1L;
private final NodeFactory nodeFactory;
@@ -57,7 +61,7 @@ public class ConcurrentRadixTree implements RadixTree, PrettyPrintable, Se
public ConcurrentRadixTree(NodeFactory nodeFactory) {
this.nodeFactory = nodeFactory;
@SuppressWarnings({"NullableProblems", "UnnecessaryLocalVariable"})
- Node rootNode = nodeFactory.createNode("", null, Collections.emptyList(), true);
+ Node rootNode = nodeFactory.createNode("", null, new SimpleNodeList(), true);
this.root = rootNode;
}
@@ -99,10 +103,10 @@ public O putIfAbsent(CharSequence key, O value) {
*/
@Override
public O getValueForExactKey(CharSequence key) {
- SearchResult searchResult = searchTree(key);
- if (searchResult.classification.equals(SearchResult.Classification.EXACT_MATCH)) {
+ Node searchResult = (Node) searchTree(key, true);
+ if (searchResult != null) {
@SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
- O value = (O) searchResult.nodeFound.getValue();
+ O value = (O) searchResult.getValue();
return value;
}
return null;
@@ -207,7 +211,7 @@ public boolean remove(CharSequence key) {
}
// Proceed with deleting the node...
- List childEdges = searchResult.nodeFound.getOutgoingEdges();
+ NodeList childEdges = searchResult.nodeFound.getOutgoingEdges();
if (childEdges.size() > 1) {
// This node has more than one child, so if we delete the value from this node, we still need
// to leave a similar node in place to act as the split between the child edges.
@@ -237,11 +241,11 @@ else if (childEdges.size() == 1) {
// (a special case which we never merge), then we also need to merge the parent with its
// remaining child.
- List currentEdgesFromParent = searchResult.parentNode.getOutgoingEdges();
+ NodeList currentEdgesFromParent = searchResult.parentNode.getOutgoingEdges();
// Create a list of the outgoing edges of the parent which will remain
// if we remove this child...
// Use a non-resizable list, as a sanity check to force ArrayIndexOutOfBounds...
- List newEdgesOfParent = Arrays.asList(new Node[searchResult.parentNode.getOutgoingEdges().size() - 1]);
+ NodeList newEdgesOfParent = new SimpleNodeList(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) {
@@ -413,15 +417,15 @@ public Iterable> getKeyValuePairsForClosestKeys(CharSequence can
*/
@Override
public int size() {
- Deque stack = new LinkedList();
- stack.push(this.root);
+ LinkedList stack = new LinkedList();
+ stack.addFirst(this.root);
int count = 0;
while (true) {
if (stack.isEmpty()) {
return count;
}
- Node current = stack.pop();
- stack.addAll(current.getOutgoingEdges());
+ Node current = stack.removeFirst();
+ current.getOutgoingEdges().addTo(stack);
if (current.getValue() != null) {
count++;
}
@@ -484,7 +488,7 @@ Object putInternal(CharSequence key, Object value, boolean overwrite) {
// Create new nodes...
Node newChild = nodeFactory.createNode(suffixFromExistingEdge, searchResult.nodeFound.getValue(), searchResult.nodeFound.getOutgoingEdges(), false);
- Node newParent = nodeFactory.createNode(commonPrefix, value, Arrays.asList(newChild), false);
+ Node newParent = nodeFactory.createNode(commonPrefix, value, new SimpleNodeList(newChild), false);
// Add the new parent to the parent of the node being replaced (replacing the existing node)...
searchResult.parentNode.updateOutgoingEdge(newParent);
@@ -502,13 +506,13 @@ Object putInternal(CharSequence key, Object value, boolean overwrite) {
// Create a new child node containing the trailing characters...
CharSequence keySuffix = key.subSequence(searchResult.charsMatched, key.length());
- Node newChild = nodeFactory.createNode(keySuffix, value, Collections.emptyList(), false);
+ Node newChild = nodeFactory.createNode(keySuffix, value, new SimpleNodeList(), false);
// Clone the current node adding the new child...
List edges = new ArrayList(searchResult.nodeFound.getOutgoingEdges().size() + 1);
- edges.addAll(searchResult.nodeFound.getOutgoingEdges());
+ searchResult.nodeFound.getOutgoingEdges().addTo(edges);
edges.add(newChild);
- Node clonedNode = nodeFactory.createNode(searchResult.nodeFound.getIncomingEdge(), searchResult.nodeFound.getValue(), edges, searchResult.nodeFound == root);
+ Node clonedNode = nodeFactory.createNode(searchResult.nodeFound.getIncomingEdge(), searchResult.nodeFound.getValue(), new SimpleNodeList(edges), searchResult.nodeFound == root);
// Re-add the cloned node to its parent node...
if (searchResult.nodeFound == root) {
@@ -540,10 +544,10 @@ Object putInternal(CharSequence key, Object value, boolean overwrite) {
CharSequence suffixFromKey = key.subSequence(searchResult.charsMatched, key.length());
// Create new nodes...
- Node n1 = nodeFactory.createNode(suffixFromKey, value, Collections.emptyList(), false);
+ Node n1 = nodeFactory.createNode(suffixFromKey, value, new SimpleNodeList(), false);
Node n2 = nodeFactory.createNode(suffixFromExistingEdge, searchResult.nodeFound.getValue(), searchResult.nodeFound.getOutgoingEdges(), false);
@SuppressWarnings({"NullableProblems"})
- Node n3 = nodeFactory.createNode(commonPrefix, null, Arrays.asList(n1, n2), false);
+ Node n3 = nodeFactory.createNode(commonPrefix, null, new SimpleNodeList(n1, n2), false);
searchResult.parentNode.updateOutgoingEdge(n3);
@@ -738,7 +742,7 @@ public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- KeyValuePairImpl that = (KeyValuePairImpl) o;
+ KeyValuePairImpl> that = (KeyValuePairImpl>) o;
return key.equals(that.key);
@@ -782,9 +786,9 @@ protected Iterable lazyTraverseDescendants(final CharSequence start
public Iterator iterator() {
return new LazyIterator() {
- Deque stack = new LinkedList();
+ final LinkedList stack = new LinkedList();
{
- stack.push(new NodeKeyPair(startNode, startKey));
+ stack.addFirst(new NodeKeyPair(startNode, startKey));
}
@Override
@@ -792,15 +796,15 @@ protected NodeKeyPair computeNext() {
if (stack.isEmpty()) {
return endOfData();
}
- NodeKeyPair current = stack.pop();
- List childNodes = current.node.getOutgoingEdges();
+ NodeKeyPair current = stack.removeFirst();
+ NodeList childNodes = current.node.getOutgoingEdges();
// -> Iterate child nodes in reverse order and so push them onto the stack in reverse order,
// to counteract that pushing them onto the stack alone would otherwise reverse their processing order.
// This ensures that we actually process nodes in ascending alphabetical order.
for (int i = childNodes.size(); i > 0; i--) {
Node child = childNodes.get(i - 1);
- stack.push(new NodeKeyPair(child, CharSequences.concatenate(current.key, child.getIncomingEdge())));
+ stack.addFirst(new NodeKeyPair(child, CharSequences.concatenate(current.key, child.getIncomingEdge())));
}
return current;
}
@@ -899,7 +903,21 @@ protected CharSequence transformKeyForResult(CharSequence rawKey) {
* parent node, the number of characters of the key which were matched in total and within the edge of the
* matched node, and a {@link SearchResult#classification} of the match as described above
*/
+
SearchResult searchTree(CharSequence key) {
+ return (SearchResult) searchTree(key, false);
+ }
+
+ /**
+ * Implements {@link #searchTree(CharSequence)} but gives an option to return the exactly matched node directly
+ * without allocating a {@link SearchResult}.
+ *
+ * @param key a key for which the node matching the longest prefix of the key is required
+ * @param exactOnly If {@code true}, an exactly matched node is returned if such a node was found or {@code null}
+ * otherwise. If {@code false}, a {@link SearchResult} is returned.
+ * @return The resolved {@link SearchResult} or a {@link Node} if {@code exactOnly} was set to {@code true}.
+ */
+ private Object searchTree(CharSequence key, boolean exactOnly) {
Node parentNodesParent = null;
Node parentNode = null;
Node currentNode = root;
@@ -918,9 +936,8 @@ SearchResult searchTree(CharSequence key) {
parentNode = currentNode;
currentNode = nextNode;
charsMatchedInNodeFound = 0;
- CharSequence currentNodeEdgeCharacters = currentNode.getIncomingEdge();
- for (int i = 0, numEdgeChars = currentNodeEdgeCharacters.length(); i < numEdgeChars && charsMatched < keyLength; i++) {
- if (currentNodeEdgeCharacters.charAt(i) != key.charAt(charsMatched)) {
+ for (int i = 0, numEdgeChars = currentNode.getIncomingEdgeLength(); i < numEdgeChars && charsMatched < keyLength; i++) {
+ if (currentNode.getIncomingEdgeCharacterAt(i) != key.charAt(charsMatched)) {
// Found a difference in chars between character in key and a character in current node.
// Current node is the deepest match (inexact match)....
break outer_loop;
@@ -929,7 +946,15 @@ SearchResult searchTree(CharSequence key) {
charsMatchedInNodeFound++;
}
}
- return new SearchResult(key, currentNode, charsMatched, charsMatchedInNodeFound, parentNode, parentNodesParent);
+ if (exactOnly) {
+ if (SearchResult.doClassify(key, currentNode, charsMatched, charsMatchedInNodeFound).equals(Classification.EXACT_MATCH)) {
+ return currentNode;
+ } else {
+ return null;
+ }
+ } else {
+ return new SearchResult(key, currentNode, charsMatched, charsMatchedInNodeFound, parentNode, parentNodesParent);
+ }
}
/**
@@ -970,23 +995,32 @@ enum Classification {
}
protected Classification classify(CharSequence key, Node nodeFound, int charsMatched, int charsMatchedInNodeFound) {
+ return doClassify(key, nodeFound, charsMatched, charsMatchedInNodeFound);
+ }
+
+ protected static Classification doClassify(CharSequence key, Node nodeFound, int charsMatched, int charsMatchedInNodeFound) {
if (charsMatched == key.length()) {
- if (charsMatchedInNodeFound == nodeFound.getIncomingEdge().length()) {
+ if (charsMatchedInNodeFound == nodeFound.getIncomingEdgeLength()) {
return Classification.EXACT_MATCH;
}
- else if (charsMatchedInNodeFound < nodeFound.getIncomingEdge().length()) {
+ else if (charsMatchedInNodeFound < nodeFound.getIncomingEdgeLength()) {
return Classification.KEY_ENDS_MID_EDGE;
}
}
else if (charsMatched < key.length()) {
- if (charsMatchedInNodeFound == nodeFound.getIncomingEdge().length()) {
+ if (charsMatchedInNodeFound == nodeFound.getIncomingEdgeLength()) {
return Classification.INCOMPLETE_MATCH_TO_END_OF_EDGE;
}
- else if (charsMatchedInNodeFound < nodeFound.getIncomingEdge().length()) {
+ else if (charsMatchedInNodeFound < nodeFound.getIncomingEdgeLength()) {
return Classification.INCOMPLETE_MATCH_TO_MIDDLE_OF_EDGE;
}
}
- throw new IllegalStateException("Unexpected failure to classify SearchResult: " + this);
+ throw new IllegalStateException("Unexpected failure to classify SearchResult: {" +
+ "key=" + key +
+ ", nodeFound=" + nodeFound +
+ ", charsMatched=" + charsMatched +
+ ", charsMatchedInNodeFound=" + charsMatchedInNodeFound +
+ '}');
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/RadixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/RadixTree.java
index f319369..98014b1 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/RadixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/RadixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/Node.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/Node.java
index 279f369..9a4df53 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/Node.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/Node.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -96,7 +96,26 @@ public interface Node extends NodeCharacterProvider, Serializable {
*
* @return The first character of the "edge" encoded in this node
*/
- Character getIncomingEdgeFirstCharacter();
+ char getIncomingEdgeFirstCharacter();
+
+ /**
+ * Returns the length of the "edge" encoded in this node, belonging to the connection from a parent node to this
+ * node.
+ *
+ *
+ * @return The length of the "edge" encoded in this node
+ */
+ int getIncomingEdgeLength();
+
+ /**
+ * Returns the character at a given index of the "edge" encoded in this node, belonging to the connection from a
+ * parent node to this node.
+ *
+ *
+ * @param index The index of the character to resolve of the "edge" encoded in this node
+ * @return The character at the index of the "edge" encoded in this node
+ */
+ char getIncomingEdgeCharacterAt(int index);
/**
* Returns all characters of the "edge" encoded in this node, belonging to the connection from a parent node to this
@@ -115,7 +134,6 @@ public interface Node extends NodeCharacterProvider, Serializable {
*/
Object getValue();
-
/**
* Returns the child of this node whose edge starts with the given first character.
*
@@ -126,7 +144,7 @@ public interface Node extends NodeCharacterProvider, Serializable {
* @return The child of this node whose edge starts with the given first character, or null if this
* node has no such outgoing edge
*/
- Node getOutgoingEdge(Character edgeFirstCharacter);
+ Node getOutgoingEdge(char edgeFirstCharacter);
/**
* Updates the child node reference for a given edge (identified by its first character) to point to a different
@@ -136,7 +154,7 @@ public interface Node extends NodeCharacterProvider, Serializable {
* edge from this node.
*
* This write must be performed atomically, in relation to reads made via
- * {@link #getOutgoingEdge(Character)}.
+ * {@link #getOutgoingEdge(char)}.
*
* @param childNode The new child node to associated with this edge
*/
@@ -150,5 +168,5 @@ public interface Node extends NodeCharacterProvider, Serializable {
*
* @return A read-only list of the child nodes to which this node has outgoing edges
*/
- List getOutgoingEdges();
+ NodeList getOutgoingEdges();
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/NodeFactory.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/NodeFactory.java
index 6a767b3..96c3b71 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/NodeFactory.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/NodeFactory.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,6 +47,6 @@ public interface NodeFactory extends Serializable {
*
* @return An object implementing the {@link Node} interface which stores the given variables
*/
- Node createNode(CharSequence edgeCharacters, Object value, List childNodes, boolean isRoot);
+ Node createNode(CharSequence edgeCharacters, Object value, NodeList childNodes, boolean isRoot);
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/NodeList.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/NodeList.java
new file mode 100644
index 0000000..3bea2cd
--- /dev/null
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/NodeList.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012-2013 Niall Gallagher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.concurrenttrees.radix.node;
+
+import java.util.Collection;
+
+/**
+ * A list of {@link Node}s represented by a tree. This interface is used rather then a Java list,
+ * to allow representing concurrent arrays as such lists and to avoid allocating wrapper instances.
+ */
+public interface NodeList {
+
+ int size();
+
+ Node get(int index);
+
+ boolean isEmpty();
+
+ void set(int index, Node node);
+
+ boolean contains(Node node);
+
+ void addTo(Collection super Node> nodes);
+
+ Node[] toArray();
+}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/SimpleNodeList.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/SimpleNodeList.java
new file mode 100644
index 0000000..cfd4b58
--- /dev/null
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/SimpleNodeList.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012-2013 Niall Gallagher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.concurrenttrees.radix.node;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A simple implementation of a {@link NodeList} backed by a {@link List}.
+ */
+public class SimpleNodeList implements NodeList {
+
+ private final List nodes;
+
+ public static final NodeList EMPTY = new SimpleNodeList();
+
+ SimpleNodeList() {
+ this.nodes = Collections.emptyList();
+ }
+
+ public SimpleNodeList(Node node) {
+ this.nodes = Collections.singletonList(node);
+ }
+
+ public SimpleNodeList(Node... nodes) {
+ this.nodes = Arrays.asList(nodes);
+ }
+
+ public SimpleNodeList(List nodes) {
+ this.nodes = nodes;
+ }
+
+ @Override
+ public int size() {
+ return nodes.size();
+ }
+
+ @Override
+ public Node get(int index) {
+ return nodes.get(index);
+ }
+
+ @Override
+ public boolean contains(Node node) {
+ return nodes.contains(node);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return nodes.isEmpty();
+ }
+
+ @Override
+ public void set(int index, Node node) {
+ nodes.set(index, node);
+ }
+
+ @Override
+ public void addTo(Collection super Node> nodes) {
+ nodes.addAll(this.nodes);
+ }
+
+ @Override
+ public Node[] toArray() {
+ return nodes.toArray(new Node[0]);
+ }
+
+ @Override
+ public String toString() {
+ return nodes.toString();
+ }
+}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactory.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactory.java
index 3566ed3..e4b478d 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactory.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactory.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,12 +18,11 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.bytearray.*;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
-import java.util.List;
-
/**
* A {@link NodeFactory} which creates {@link Node} objects which store incoming edge characters as a byte array inside
* the node. This is similar to {@link DefaultCharArrayNodeFactory}, except nodes use a single byte to represent each
@@ -37,40 +36,50 @@
*/
public class DefaultByteArrayNodeFactory implements NodeFactory {
+ private static final long serialVersionUID = 1L;
+
+ private final boolean fast;
+
+ public DefaultByteArrayNodeFactory() {
+ fast = false;
+ }
+
+ DefaultByteArrayNodeFactory(boolean fast) {
+ this.fast = fast;
+ }
+
@Override
- public Node createNode(CharSequence edgeCharacters, Object value, List childNodes, boolean isRoot) {
- if (edgeCharacters == null) {
- throw new IllegalStateException("The edgeCharacters argument was null");
- }
- if (!isRoot && edgeCharacters.length() == 0) {
- throw new IllegalStateException("Invalid edge characters for non-root node: " + CharSequences.toString(edgeCharacters));
- }
- if (childNodes == null) {
- throw new IllegalStateException("The childNodes argument was null");
+ public Node createNode(CharSequence edgeCharacters, Object value, NodeList childNodes, boolean isRoot) {
+ assert edgeCharacters != null : "The edgeCharacters argument was null";
+ assert isRoot || edgeCharacters.length() > 0 : "Invalid edge characters for non-root node: " + CharSequences.toString(edgeCharacters);
+ assert childNodes != null : "The edgeCharacters argument was null";
+ assert NodeUtil.hasNoDuplicateEdges(childNodes) : "Duplicate edge detected in list of nodes supplied: " + childNodes;
+ byte[] incomingEdgeCharArray = ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharacters, fast);
+ if (incomingEdgeCharArray == null) {
+ return null;
}
- NodeUtil.ensureNoDuplicateEdges(childNodes);
if (childNodes.isEmpty()) {
// Leaf node...
if (value instanceof VoidValue) {
- return new ByteArrayNodeLeafVoidValue(edgeCharacters);
+ return new ByteArrayNodeLeafVoidValue(incomingEdgeCharArray);
}
else if (value != null) {
- return new ByteArrayNodeLeafWithValue(edgeCharacters, value);
+ return new ByteArrayNodeLeafWithValue(incomingEdgeCharArray, value);
}
else {
- return new ByteArrayNodeLeafNullValue(edgeCharacters);
+ return new ByteArrayNodeLeafNullValue(incomingEdgeCharArray);
}
}
else {
// Non-leaf node...
if (value instanceof VoidValue) {
- return new ByteArrayNodeNonLeafVoidValue(edgeCharacters, childNodes);
+ return new ByteArrayNodeNonLeafVoidValue(incomingEdgeCharArray, childNodes);
}
else if (value == null) {
- return new ByteArrayNodeNonLeafNullValue(edgeCharacters, childNodes);
+ return new ByteArrayNodeNonLeafNullValue(incomingEdgeCharArray, childNodes);
}
else {
- return new ByteArrayNodeDefault(edgeCharacters, value, childNodes);
+ return new ByteArrayNodeDefault(incomingEdgeCharArray, value, childNodes);
}
}
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactory.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactory.java
index d6f76ad..3c9fca9 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactory.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactory.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,14 +15,13 @@
*/
package com.googlecode.concurrenttrees.radix.node.concrete;
+import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.chararray.*;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
-import com.googlecode.concurrenttrees.common.CharSequences;
-
-import java.util.List;
/**
* A {@link NodeFactory} which creates various implementations of {@link Node} objects all of which store incoming
@@ -44,18 +43,14 @@
*/
public class DefaultCharArrayNodeFactory implements NodeFactory {
+ private static final long serialVersionUID = 1L;
+
@Override
- public Node createNode(CharSequence edgeCharacters, Object value, List childNodes, boolean isRoot) {
- if (edgeCharacters == null) {
- throw new IllegalStateException("The edgeCharacters argument was null");
- }
- if (!isRoot && edgeCharacters.length() == 0) {
- throw new IllegalStateException("Invalid edge characters for non-root node: " + CharSequences.toString(edgeCharacters));
- }
- if (childNodes == null) {
- throw new IllegalStateException("The childNodes argument was null");
- }
- NodeUtil.ensureNoDuplicateEdges(childNodes);
+ public Node createNode(CharSequence edgeCharacters, Object value, NodeList childNodes, boolean isRoot) {
+ assert edgeCharacters != null : "The edgeCharacters argument was null";
+ assert isRoot || edgeCharacters.length() > 0 : "Invalid edge characters for non-root node: " + CharSequences.toString(edgeCharacters);
+ assert childNodes != null : "The edgeCharacters argument was null";
+ assert NodeUtil.hasNoDuplicateEdges(childNodes) : "Duplicate edge detected in list of nodes supplied: " + childNodes;
if (childNodes.isEmpty()) {
// Leaf node...
if (value instanceof VoidValue) {
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharSequenceNodeFactory.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharSequenceNodeFactory.java
index a873422..347ec88 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharSequenceNodeFactory.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharSequenceNodeFactory.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,12 +18,11 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.charsequence.*;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
-import java.util.List;
-
/**
* A {@link NodeFactory} which creates various implementations of {@link Node} objects all of which store incoming
* edge characters as a {@link CharSequence} (a view onto the original key) rather than copying the edge into a
@@ -45,19 +44,14 @@
*/
public class DefaultCharSequenceNodeFactory implements NodeFactory {
- @Override
- public Node createNode(CharSequence edgeCharacters, Object value, List childNodes, boolean isRoot) {
- if (edgeCharacters == null) {
- throw new IllegalStateException("The edgeCharacters argument was null");
- }
- if (!isRoot && edgeCharacters.length() == 0) {
- throw new IllegalStateException("Invalid edge characters for non-root node: " + CharSequences.toString(edgeCharacters));
- }
- if (childNodes == null) {
- throw new IllegalStateException("The childNodes argument was null");
- }
- NodeUtil.ensureNoDuplicateEdges(childNodes);
+ private static final long serialVersionUID = 1L;
+ @Override
+ public Node createNode(CharSequence edgeCharacters, Object value, NodeList childNodes, boolean isRoot) {
+ assert edgeCharacters != null : "The edgeCharacters argument was null";
+ assert isRoot || edgeCharacters.length() > 0 : "Invalid edge characters for non-root node: " + CharSequences.toString(edgeCharacters);
+ assert childNodes != null : "The edgeCharacters argument was null";
+ assert NodeUtil.hasNoDuplicateEdges(childNodes) : "Duplicate edge detected in list of nodes supplied: " + childNodes;
if (childNodes.isEmpty()) {
// Leaf node...
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/SmartArrayBasedNodeFactory.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/SmartArrayBasedNodeFactory.java
index cd6e0db..582664b 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/SmartArrayBasedNodeFactory.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/SmartArrayBasedNodeFactory.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,10 +17,9 @@
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.bytearray.ByteArrayCharSequence;
-import java.util.List;
-
/**
* A {@link NodeFactory} which internally uses {@link DefaultByteArrayNodeFactory} to create nodes by default (which
* can reduce memory overhead), but falls back to {@link DefaultCharArrayNodeFactory} if characters are detected which
@@ -30,16 +29,18 @@
*/
public class SmartArrayBasedNodeFactory implements NodeFactory {
+ private static final long serialVersionUID = 1L;
+
final NodeFactory charArrayNodeFactory = new DefaultCharArrayNodeFactory();
- final NodeFactory byteArrayNodeFactory = new DefaultByteArrayNodeFactory();
+ final NodeFactory byteArrayNodeFactory = new DefaultByteArrayNodeFactory(true);
@Override
- public Node createNode(CharSequence edgeCharacters, Object value, List childNodes, boolean isRoot) {
- try {
- return byteArrayNodeFactory.createNode(edgeCharacters, value, childNodes, isRoot);
- }
- catch (ByteArrayCharSequence.IncompatibleCharacterException e) {
+ public Node createNode(CharSequence edgeCharacters, Object value, NodeList childNodes, boolean isRoot) {
+ Node node = byteArrayNodeFactory.createNode(edgeCharacters, value, childNodes, isRoot);
+ if (node == null) {
return charArrayNodeFactory.createNode(edgeCharacters, value, childNodes, isRoot);
+ } else {
+ return node;
}
}
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayCharSequence.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayCharSequence.java
index a38f99c..06f5fa1 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayCharSequence.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayCharSequence.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -71,12 +71,20 @@ public String toString() {
* @throws IllegalStateException If the characters cannot be encoded as described
*/
public static byte[] toSingleByteUtf8Encoding(CharSequence charSequence) {
+ return toSingleByteUtf8Encoding(charSequence, false);
+ }
+
+ public static byte[] toSingleByteUtf8Encoding(CharSequence charSequence, boolean nullIfIncompatible) {
final int length = charSequence.length();
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++) {
char inputChar = charSequence.charAt(i);
if (inputChar > 255) {
- throw new IncompatibleCharacterException("Input contains a character which cannot be represented as a single byte in UTF-8: " + inputChar);
+ if (nullIfIncompatible) {
+ return null;
+ } else {
+ throw new IncompatibleCharacterException("Input contains a character which cannot be represented as a single byte in UTF-8: " + inputChar);
+ }
}
bytes[i] = (byte)inputChar;
}
@@ -84,6 +92,9 @@ public static byte[] toSingleByteUtf8Encoding(CharSequence charSequence) {
}
public static class IncompatibleCharacterException extends IllegalStateException {
+
+ private static final long serialVersionUID = 1L;
+
public IncompatibleCharacterException(String s) {
super(s);
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeDefault.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeDefault.java
index 067b03b..12ced1a 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeDefault.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeDefault.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,13 +16,12 @@
package com.googlecode.concurrenttrees.radix.node.concrete.bytearray;
import com.googlecode.concurrenttrees.radix.node.Node;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReferenceArray;
/**
* Similar to {@link com.googlecode.concurrenttrees.radix.node.concrete.chararray.CharArrayNodeDefault} but represents
@@ -35,6 +34,7 @@
*/
public class ByteArrayNodeDefault implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -43,23 +43,23 @@ public class ByteArrayNodeDefault implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
-
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ private final AtomicNodeReferenceArray outgoingEdges;
// An arbitrary value which the application associates with a key matching the path to this node in the tree.
// This value can be null...
private final Object value;
- public ByteArrayNodeDefault(CharSequence edgeCharSequence, Object value, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public ByteArrayNodeDefault(CharSequence edgeCharSequence, Object value, NodeList outgoingEdges) {
+ this(ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence), value, outgoingEdges);
+ }
+
+ public ByteArrayNodeDefault(byte[] incomingEdgeCharArray, Object value, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
- this.incomingEdgeCharArray = ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
+ this.incomingEdgeCharArray = incomingEdgeCharArray;
this.value = value;
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
}
@Override
@@ -68,7 +68,17 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return (char) (incomingEdgeCharArray[index] & 0xFF);
+ }
+
+ @Override
+ public char getIncomingEdgeFirstCharacter() {
return (char) (incomingEdgeCharArray[0] & 0xFF);
}
@@ -78,7 +88,7 @@ public Object getValue() {
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -105,8 +115,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafNullValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafNullValue.java
index 5877be7..79256d7 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafNullValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafNullValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,9 +16,8 @@
package com.googlecode.concurrenttrees.radix.node.concrete.bytearray;
import com.googlecode.concurrenttrees.radix.node.Node;
-
-import java.util.Collections;
-import java.util.List;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
/**
* Similar to {@link com.googlecode.concurrenttrees.radix.node.concrete.chararray.CharArrayNodeLeafNullValue} but represents
@@ -31,13 +30,18 @@
*/
public class ByteArrayNodeLeafNullValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
private final byte[] incomingEdgeCharArray;
public ByteArrayNodeLeafNullValue(CharSequence edgeCharSequence) {
- this.incomingEdgeCharArray = ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence);
+ this(ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence));
+ }
+
+ public ByteArrayNodeLeafNullValue(byte[] incomingEdgeCharArray) {
+ this.incomingEdgeCharArray = incomingEdgeCharArray;
}
@Override
@@ -46,17 +50,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return (char) (incomingEdgeCharArray[0] & 0xFF);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return (char) (incomingEdgeCharArray[index] & 0xFF);
+ }
+
@Override
public Object getValue() {
return null;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -66,8 +80,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafVoidValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafVoidValue.java
index ea7bd4d..6dc9266 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafVoidValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafVoidValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,11 +16,10 @@
package com.googlecode.concurrenttrees.radix.node.concrete.bytearray;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
-import java.util.Collections;
-import java.util.List;
-
/**
* Similar to {@link com.googlecode.concurrenttrees.radix.node.concrete.chararray.CharArrayNodeLeafVoidValue} but represents
* each character in UTF-8, instead of Java's default 2-byte UFT-16 encoding.
@@ -32,12 +31,18 @@
*/
public class ByteArrayNodeLeafVoidValue implements Node {
+ private static final long serialVersionUID = 1L;
+
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
private final byte[] incomingEdgeCharArray;
public ByteArrayNodeLeafVoidValue(CharSequence edgeCharSequence) {
- this.incomingEdgeCharArray = ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence);
+ this(ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence));
+ }
+
+ public ByteArrayNodeLeafVoidValue(byte[] incomingEdgeCharArray) {
+ this.incomingEdgeCharArray = incomingEdgeCharArray;
}
@Override
@@ -46,17 +51,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return (char) (incomingEdgeCharArray[0] & 0xFF);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return (char) (incomingEdgeCharArray[index] & 0xFF);
+ }
+
@Override
public Object getValue() {
return VoidValue.SINGLETON;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -66,8 +81,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafWithValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafWithValue.java
index d0b10bd..8e4306c 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafWithValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeLeafWithValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,9 +16,8 @@
package com.googlecode.concurrenttrees.radix.node.concrete.bytearray;
import com.googlecode.concurrenttrees.radix.node.Node;
-
-import java.util.Collections;
-import java.util.List;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
/**
* Similar to {@link com.googlecode.concurrenttrees.radix.node.concrete.chararray.CharArrayNodeLeafWithValue} but represents
@@ -31,6 +30,7 @@
*/
public class ByteArrayNodeLeafWithValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -41,7 +41,11 @@ public class ByteArrayNodeLeafWithValue implements Node {
private final Object value;
public ByteArrayNodeLeafWithValue(CharSequence edgeCharSequence, Object value) {
- this.incomingEdgeCharArray = ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence);
+ this(ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence), value);
+ }
+
+ public ByteArrayNodeLeafWithValue(byte[] incomingEdgeCharArray, Object value) {
+ this.incomingEdgeCharArray = incomingEdgeCharArray;
this.value = value;
}
@@ -51,17 +55,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return (char) (incomingEdgeCharArray[0] & 0xFF);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return (char) (incomingEdgeCharArray[index] & 0xFF);
+ }
+
@Override
public Object getValue() {
return value;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -71,8 +85,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafNullValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafNullValue.java
index c2ce78b..6959d51 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafNullValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafNullValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,13 +16,12 @@
package com.googlecode.concurrenttrees.radix.node.concrete.bytearray;
import com.googlecode.concurrenttrees.radix.node.Node;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReferenceArray;
/**
* Similar to {@link com.googlecode.concurrenttrees.radix.node.concrete.chararray.CharArrayNodeNonLeafNullValue} but represents
@@ -35,6 +34,7 @@
*/
public class ByteArrayNodeNonLeafNullValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -43,18 +43,18 @@ public class ByteArrayNodeNonLeafNullValue implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
+ private final AtomicNodeReferenceArray outgoingEdges;
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ public ByteArrayNodeNonLeafNullValue(CharSequence edgeCharSequence, NodeList outgoingEdges) {
+ this(ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence), outgoingEdges);
+ }
- public ByteArrayNodeNonLeafNullValue(CharSequence edgeCharSequence, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public ByteArrayNodeNonLeafNullValue(byte[] incomingEdgeCharArray, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
- this.incomingEdgeCharArray = ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence);
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
+ this.incomingEdgeCharArray = incomingEdgeCharArray;
}
@Override
@@ -63,17 +63,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return (char) (incomingEdgeCharArray[0] & 0xFF);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return (char) (incomingEdgeCharArray[index] & 0xFF);
+ }
+
@Override
public Object getValue() {
return null;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -100,8 +110,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafVoidValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafVoidValue.java
index 9ce524d..4fa907d 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafVoidValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/bytearray/ByteArrayNodeNonLeafVoidValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,14 +16,13 @@
package com.googlecode.concurrenttrees.radix.node.concrete.bytearray;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReferenceArray;
/**
* Similar to {@link com.googlecode.concurrenttrees.radix.node.concrete.chararray.CharArrayNodeNonLeafVoidValue} but represents
@@ -36,6 +35,8 @@
*/
public class ByteArrayNodeNonLeafVoidValue implements Node {
+ private static final long serialVersionUID = 1L;
+
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
private final byte[] incomingEdgeCharArray;
@@ -43,18 +44,18 @@ public class ByteArrayNodeNonLeafVoidValue implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
+ private final AtomicNodeReferenceArray outgoingEdges;
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ public ByteArrayNodeNonLeafVoidValue(CharSequence edgeCharSequence, NodeList outgoingEdges) {
+ this(ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence), outgoingEdges);
+ }
- public ByteArrayNodeNonLeafVoidValue(CharSequence edgeCharSequence, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public ByteArrayNodeNonLeafVoidValue(byte[] incomingEdgeCharArray, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
- this.incomingEdgeCharArray = ByteArrayCharSequence.toSingleByteUtf8Encoding(edgeCharSequence);
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
+ this.incomingEdgeCharArray = incomingEdgeCharArray;
}
@Override
@@ -63,17 +64,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return (char) (incomingEdgeCharArray[0] & 0xFF);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return (char) (incomingEdgeCharArray[index] & 0xFF);
+ }
+
@Override
public Object getValue() {
return VoidValue.SINGLETON;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -100,8 +111,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeDefault.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeDefault.java
index 67b3ae8..f6bb728 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeDefault.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeDefault.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,14 +15,14 @@
*/
package com.googlecode.concurrenttrees.radix.node.concrete.chararray;
+import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
-import com.googlecode.concurrenttrees.common.CharSequences;
import java.util.Arrays;
-import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
@@ -36,7 +36,7 @@
* This implementation stores references to child nodes in an {@link AtomicReferenceArray}, in ascending sorted order
* of the first character of the edges which child nodes define.
*
- * The {@link #getOutgoingEdge(Character)} method uses binary search to locate a requested node, given the first character
+ * The {@link #getOutgoingEdge(char)} method uses binary search to locate a requested node, given the first character
* of an edge indicated. The node is then read and returned atomically from the {@link AtomicReferenceArray}.
*
* The {@link #updateOutgoingEdge(com.googlecode.concurrenttrees.radix.node.Node)} method ensures that any
@@ -51,6 +51,7 @@
*/
public class CharArrayNodeDefault implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -59,23 +60,19 @@ public class CharArrayNodeDefault implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
-
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ private final AtomicNodeReferenceArray outgoingEdges;
// An arbitrary value which the application associates with a key matching the path to this node in the tree.
// This value can be null...
private final Object value;
- public CharArrayNodeDefault(CharSequence edgeCharSequence, Object value, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public CharArrayNodeDefault(CharSequence edgeCharSequence, Object value, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
this.incomingEdgeCharArray = CharSequences.toCharArray(edgeCharSequence);
this.value = value;
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
}
@Override
@@ -84,17 +81,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharArray[0];
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharArray[index];
+ }
+
@Override
public Object getValue() {
return value;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -121,8 +128,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafNullValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafNullValue.java
index 67b67e2..6e37ee8 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafNullValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafNullValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,9 +17,8 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
-
-import java.util.Collections;
-import java.util.List;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
/**
* Stores only incoming edge as a {@code char[]}.
@@ -29,6 +28,7 @@
*/
public class CharArrayNodeLeafNullValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -44,17 +44,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharArray[0];
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharArray[index];
+ }
+
@Override
public Object getValue() {
return null;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -64,8 +74,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafVoidValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafVoidValue.java
index f699aee..7a5e7e7 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafVoidValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafVoidValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,11 +17,10 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
-import java.util.Collections;
-import java.util.List;
-
/**
* Stores only incoming edge as a {@code char[]}.
* Returns {@link VoidValue} for the value. Does not store any outgoing edges.
@@ -30,6 +29,8 @@
*/
public class CharArrayNodeLeafVoidValue implements Node {
+ private static final long serialVersionUID = 1L;
+
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
private final char[] incomingEdgeCharArray;
@@ -44,17 +45,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharArray[0];
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharArray[index];
+ }
+
@Override
public Object getValue() {
return VoidValue.SINGLETON;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -64,8 +75,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafWithValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafWithValue.java
index 400ced0..c392ab0 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafWithValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeLeafWithValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,9 +17,8 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
-
-import java.util.Collections;
-import java.util.List;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
/**
* Stores only incoming edge as a {@code char[]}, and a reference to a value. Does not store any outgoing
@@ -29,6 +28,7 @@
*/
public class CharArrayNodeLeafWithValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -49,17 +49,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharArray[0];
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharArray[index];
+ }
+
@Override
public Object getValue() {
return value;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -69,8 +79,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafNullValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafNullValue.java
index 0699312..3e906c4 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafNullValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafNullValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,12 +17,12 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
@@ -33,6 +33,7 @@
*/
public class CharArrayNodeNonLeafNullValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -41,18 +42,14 @@ public class CharArrayNodeNonLeafNullValue implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
-
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ private final AtomicNodeReferenceArray outgoingEdges;
- public CharArrayNodeNonLeafNullValue(CharSequence edgeCharSequence, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public CharArrayNodeNonLeafNullValue(CharSequence edgeCharSequence, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
this.incomingEdgeCharArray = CharSequences.toCharArray(edgeCharSequence);
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
}
@Override
@@ -61,17 +58,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharArray[0];
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharArray[index];
+ }
+
@Override
public Object getValue() {
return null;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -98,8 +105,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafVoidValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafVoidValue.java
index abdbbbe..f5be6c9 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafVoidValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/chararray/CharArrayNodeNonLeafVoidValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,13 +17,13 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
@@ -34,6 +34,8 @@
*/
public class CharArrayNodeNonLeafVoidValue implements Node {
+ private static final long serialVersionUID = 1L;
+
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
private final char[] incomingEdgeCharArray;
@@ -41,18 +43,14 @@ public class CharArrayNodeNonLeafVoidValue implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
-
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ private final AtomicNodeReferenceArray outgoingEdges;
- public CharArrayNodeNonLeafVoidValue(CharSequence edgeCharSequence, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public CharArrayNodeNonLeafVoidValue(CharSequence edgeCharSequence, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
this.incomingEdgeCharArray = CharSequences.toCharArray(edgeCharSequence);
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
}
@Override
@@ -61,17 +59,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharArray[0];
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharArray.length;
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharArray[index];
+ }
+
@Override
public Object getValue() {
return VoidValue.SINGLETON;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -98,8 +106,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeDefault.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeDefault.java
index ef451f8..627c03d 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeDefault.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeDefault.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,12 +16,12 @@
package com.googlecode.concurrenttrees.radix.node.concrete.charsequence;
import com.googlecode.concurrenttrees.radix.node.Node;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
@@ -36,7 +36,7 @@
* This implementation stores references to child nodes in an {@link AtomicReferenceArray}, in ascending sorted order
* of the first character of the edges which child nodes define.
*
- * The {@link #getOutgoingEdge(Character)} method uses binary search to locate a requested node, given the first character
+ * The {@link #getOutgoingEdge(char)} method uses binary search to locate a requested node, given the first character
* of an edge indicated. The node is then read and returned atomically from the {@link AtomicReferenceArray}.
*
* The {@link #updateOutgoingEdge(com.googlecode.concurrenttrees.radix.node.Node)} method ensures that any
@@ -51,6 +51,7 @@
*/
public class CharSequenceNodeDefault implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -59,23 +60,19 @@ public class CharSequenceNodeDefault implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
-
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ private final AtomicNodeReferenceArray outgoingEdges;
// An arbitrary value which the application associates with a key matching the path to this node in the tree.
// This value can be null...
private final Object value;
- public CharSequenceNodeDefault(CharSequence edgeCharSequence, Object value, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public CharSequenceNodeDefault(CharSequence edgeCharSequence, Object value, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
this.incomingEdgeCharSequence = edgeCharSequence;
this.value = value;
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
}
@Override
@@ -84,17 +81,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharSequence.charAt(0);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharSequence.length();
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharSequence.charAt(index);
+ }
+
@Override
public Object getValue() {
return value;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -121,8 +128,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafNullValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafNullValue.java
index 9a6013f..c428ccd 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafNullValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafNullValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,9 +16,8 @@
package com.googlecode.concurrenttrees.radix.node.concrete.charsequence;
import com.googlecode.concurrenttrees.radix.node.Node;
-
-import java.util.Collections;
-import java.util.List;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
/**
* Stores only incoming edge as a {@link CharSequence} (a view onto the original key) rather than copying the
@@ -28,6 +27,7 @@
*/
public class CharSequenceNodeLeafNullValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -43,17 +43,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharSequence.charAt(0);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharSequence.length();
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharSequence.charAt(index);
+ }
+
@Override
public Object getValue() {
return null;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -63,8 +73,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafVoidValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafVoidValue.java
index 971aac7..a880378 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafVoidValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafVoidValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,15 +16,9 @@
package com.googlecode.concurrenttrees.radix.node.concrete.charsequence;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
-import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
-import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReferenceArray;
/**
* Stores only incoming edge as a {@link CharSequence} (a view onto the original key) rather than copying the
@@ -34,6 +28,7 @@
*/
public class CharSequenceNodeLeafVoidValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -49,17 +44,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharSequence.charAt(0);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharSequence.length();
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharSequence.charAt(index);
+ }
+
@Override
public Object getValue() {
return VoidValue.SINGLETON;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -69,8 +74,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafWithValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafWithValue.java
index 5618f1c..f11eef4 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafWithValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeLeafWithValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,14 +16,8 @@
package com.googlecode.concurrenttrees.radix.node.concrete.charsequence;
import com.googlecode.concurrenttrees.radix.node.Node;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
-import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
-import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReferenceArray;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
/**
* Stores incoming edge as a {@link CharSequence} (a view onto the original key) rather than copying the
@@ -33,6 +27,7 @@
*/
public class CharSequenceNodeLeafWithValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -54,17 +49,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharSequence.charAt(0);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharSequence.length();
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharSequence.charAt(index);
+ }
+
@Override
public Object getValue() {
return value;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
return null;
}
@@ -74,8 +79,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return Collections.emptyList();
+ public NodeList getOutgoingEdges() {
+ return SimpleNodeList.EMPTY;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafNullValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafNullValue.java
index be43710..cdeb351 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafNullValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafNullValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,12 +16,12 @@
package com.googlecode.concurrenttrees.radix.node.concrete.charsequence;
import com.googlecode.concurrenttrees.radix.node.Node;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
@@ -33,6 +33,7 @@
*/
public class CharSequenceNodeNonLeafNullValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -41,18 +42,14 @@ public class CharSequenceNodeNonLeafNullValue implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
-
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ private final AtomicNodeReferenceArray outgoingEdges;
- public CharSequenceNodeNonLeafNullValue(CharSequence edgeCharSequence, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public CharSequenceNodeNonLeafNullValue(CharSequence edgeCharSequence, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
this.incomingEdgeCharSequence = edgeCharSequence;
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
}
@Override
@@ -61,17 +58,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharSequence.charAt(0);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharSequence.length();
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharSequence.charAt(index);
+ }
+
@Override
public Object getValue() {
return null;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -98,8 +105,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafVoidValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafVoidValue.java
index b320440..51c97a8 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafVoidValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/charsequence/CharSequenceNodeNonLeafVoidValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,13 +16,13 @@
package com.googlecode.concurrenttrees.radix.node.concrete.charsequence;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
-import com.googlecode.concurrenttrees.radix.node.util.AtomicReferenceArrayListAdapter;
+import com.googlecode.concurrenttrees.radix.node.util.AtomicNodeReferenceArray;
import com.googlecode.concurrenttrees.radix.node.util.NodeCharacterComparator;
import com.googlecode.concurrenttrees.radix.node.util.NodeUtil;
import java.util.Arrays;
-import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
/**
@@ -34,6 +34,7 @@
*/
public class CharSequenceNodeNonLeafVoidValue implements Node {
+ private static final long serialVersionUID = 1L;
// Characters in the edge arriving at this node from a parent node.
// Once assigned, we never modify this...
@@ -42,18 +43,14 @@ public class CharSequenceNodeNonLeafVoidValue implements Node {
// References to child nodes representing outgoing edges from this node.
// Once assigned we never add or remove references, but we do update existing references to point to new child
// nodes provided new edges start with the same first character...
- private final AtomicReferenceArray outgoingEdges;
-
- // A read-only List wrapper around the outgoingEdges AtomicReferenceArray...
- private final List outgoingEdgesAsList;
+ private final AtomicNodeReferenceArray outgoingEdges;
- public CharSequenceNodeNonLeafVoidValue(CharSequence edgeCharSequence, List outgoingEdges) {
- Node[] childNodeArray = outgoingEdges.toArray(new Node[outgoingEdges.size()]);
+ public CharSequenceNodeNonLeafVoidValue(CharSequence edgeCharSequence, NodeList outgoingEdges) {
+ Node[] childNodeArray = outgoingEdges.toArray();
// Sort the child nodes...
- Arrays.sort(childNodeArray, new NodeCharacterComparator());
- this.outgoingEdges = new AtomicReferenceArray(childNodeArray);
+ Arrays.sort(childNodeArray, NodeCharacterComparator.SINGLETON);
+ this.outgoingEdges = new AtomicNodeReferenceArray(childNodeArray);
this.incomingEdgeCharSequence = edgeCharSequence;
- this.outgoingEdgesAsList = new AtomicReferenceArrayListAdapter(this.outgoingEdges);
}
@Override
@@ -62,17 +59,27 @@ public CharSequence getIncomingEdge() {
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return incomingEdgeCharSequence.charAt(0);
}
+ @Override
+ public int getIncomingEdgeLength() {
+ return incomingEdgeCharSequence.length();
+ }
+
+ @Override
+ public char getIncomingEdgeCharacterAt(int index) {
+ return incomingEdgeCharSequence.charAt(index);
+ }
+
@Override
public Object getValue() {
return VoidValue.SINGLETON;
}
@Override
- public Node getOutgoingEdge(Character edgeFirstCharacter) {
+ public Node getOutgoingEdge(char edgeFirstCharacter) {
// Binary search for the index of the node whose edge starts with the given character.
// Note that this binary search is safe in the face of concurrent modification due to constraints
// we enforce on use of the array, as documented in the binarySearchForEdge method...
@@ -99,8 +106,8 @@ public void updateOutgoingEdge(Node childNode) {
}
@Override
- public List getOutgoingEdges() {
- return outgoingEdgesAsList;
+ public NodeList getOutgoingEdges() {
+ return outgoingEdges;
}
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/voidvalue/VoidValue.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/voidvalue/VoidValue.java
index 6cfffbe..2355fce 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/voidvalue/VoidValue.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/concrete/voidvalue/VoidValue.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/AtomicNodeReferenceArray.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/AtomicNodeReferenceArray.java
new file mode 100644
index 0000000..e1ade3e
--- /dev/null
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/AtomicNodeReferenceArray.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012-2013 Niall Gallagher
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.googlecode.concurrenttrees.radix.node.util;
+
+import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+public class AtomicNodeReferenceArray extends AtomicReferenceArray implements NodeList {
+
+ private static final long serialVersionUID = 1L;
+
+ public AtomicNodeReferenceArray(Node[] array) {
+ super(array);
+ }
+
+ @Override
+ public int size() {
+ return length();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return length() == 0;
+ }
+
+ @Override
+ public boolean contains(Node node) {
+ for (int index = 0; index < length(); index++) {
+ if (node == null && get(index) == null || node != null && node.equals(get(index))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void addTo(Collection super Node> nodes) {
+ for (int index = 0; index < length(); index++) {
+ nodes.add(get(index));
+ }
+ }
+
+ @Override
+ public Node[] toArray() {
+ Node[] nodes = new Node[length()];
+ for (int index = 0; index < nodes.length; index++) {
+ nodes[index] = get(index);
+ }
+ return nodes;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int index = 0; index < length(); index++) {
+ if (index > 0) {
+ sb.append(", ");
+ }
+ sb.append(get(index));
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/AtomicReferenceArrayListAdapter.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/AtomicReferenceArrayListAdapter.java
deleted file mode 100644
index 26d2567..0000000
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/AtomicReferenceArrayListAdapter.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright 2012-2013 Niall Gallagher
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.googlecode.concurrenttrees.radix.node.util;
-
-import java.io.Serializable;
-import java.util.AbstractList;
-import java.util.concurrent.atomic.AtomicReferenceArray;
-
-/**
- * Wraps an {@link AtomicReferenceArray} to implement read-only methods of the {@link java.util.List} interface.
- *
- * This enables binary search of an {@link AtomicReferenceArray}, using
- * {@link java.util.Collections#binarySearch(java.util.List, Object)}.
- *
- * @author Niall Gallagher
- */
-public class AtomicReferenceArrayListAdapter extends AbstractList implements Serializable {
-
- private final AtomicReferenceArray atomicReferenceArray;
-
- public AtomicReferenceArrayListAdapter(AtomicReferenceArray atomicReferenceArray) {
- this.atomicReferenceArray = atomicReferenceArray;
- }
-
- @Override
- public T get(int index) {
- return atomicReferenceArray.get(index);
- }
-
- @Override
- public int size() {
- return atomicReferenceArray.length();
- }
-}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterComparator.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterComparator.java
index fb7b91f..eaf6429 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterComparator.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterComparator.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,8 +25,13 @@
*/
public class NodeCharacterComparator implements Comparator {
+ NodeCharacterComparator() {
+ }
+
@Override
public int compare(NodeCharacterProvider o1, NodeCharacterProvider o2) {
- return o1.getIncomingEdgeFirstCharacter().compareTo(o2.getIncomingEdgeFirstCharacter());
+ return o1.getIncomingEdgeFirstCharacter() - o2.getIncomingEdgeFirstCharacter();
}
+
+ public static final Comparator SINGLETON = new NodeCharacterComparator();
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterKey.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterKey.java
index e909005..b15d391 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterKey.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterKey.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,21 +16,21 @@
package com.googlecode.concurrenttrees.radix.node.util;
/**
- * A lightweight object which simply wraps a {@link Character} and implements {@link NodeCharacterProvider}, which
+ * A lightweight object which simply wraps a {@code char} and implements {@link NodeCharacterProvider}, which
* can be used as a key to locate a node having the same edge first character in a list of nodes using binary search.
*
* @author Niall Gallagher
*/
public class NodeCharacterKey implements NodeCharacterProvider {
- private final Character character;
+ private final char character;
- public NodeCharacterKey(Character character) {
+ public NodeCharacterKey(char character) {
this.character = character;
}
@Override
- public Character getIncomingEdgeFirstCharacter() {
+ public char getIncomingEdgeFirstCharacter() {
return character;
}
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterProvider.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterProvider.java
index dd503f7..45f6097 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterProvider.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeCharacterProvider.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,5 +27,5 @@
*/
public interface NodeCharacterProvider {
- Character getIncomingEdgeFirstCharacter();
+ char getIncomingEdgeFirstCharacter();
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeUtil.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeUtil.java
index b180a03..7e26e60 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeUtil.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/NodeUtil.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,7 @@
package com.googlecode.concurrenttrees.radix.node.util;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.NodeList;
import java.util.*;
import java.util.concurrent.atomic.AtomicReferenceArray;
@@ -60,7 +61,7 @@ public class NodeUtil {
* @return The index of the node representing the indicated edge, or a value < 0 if no such node exists in the
* array
*/
- public static int binarySearchForEdge(AtomicReferenceArray childNodes, Character edgeFirstCharacter) {
+ public static int binarySearchForEdge(AtomicReferenceArray childNodes, char edgeFirstCharacter) {
// inspired by Collections#indexedBinarySearch()
int low = 0;
int high = childNodes.length() - 1;
@@ -68,7 +69,7 @@ public static int binarySearchForEdge(AtomicReferenceArray childNodes, Cha
while (low <= high) {
int mid = (low + high) >>> 1;
Node midVal = childNodes.get(mid);
- int cmp = midVal.getIncomingEdgeFirstCharacter().compareTo(edgeFirstCharacter);
+ int cmp = midVal.getIncomingEdgeFirstCharacter() - edgeFirstCharacter;
if (cmp < 0)
low = mid + 1;
@@ -81,19 +82,17 @@ else if (cmp > 0)
}
/**
- * Throws an exception if any nodes in the given list represent edges having the same first character.
+ * Checks if any nodes in the given list represent edges having the same first character.
*
* @param nodes The list of nodes to validate
- * @throws IllegalStateException If a duplicate edge is detected
+ * @return {@code true} if the supplied edges are free of duplicates.
*/
- public static void ensureNoDuplicateEdges(List nodes) {
+ public static boolean hasNoDuplicateEdges(NodeList nodes) {
// Sanity check that no two nodes specify an edge with the same first character...
Set uniqueChars = new HashSet(nodes.size());
- for (Node node : nodes) {
- uniqueChars.add(node.getIncomingEdgeFirstCharacter());
- }
- if (nodes.size() != uniqueChars.size()) {
- throw new IllegalStateException("Duplicate edge detected in list of nodes supplied: " + nodes);
+ for (int index = 0; index < nodes.size(); index++) {
+ uniqueChars.add(nodes.get(index).getIncomingEdgeFirstCharacter());
}
+ return nodes.size() == uniqueChars.size();
}
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/PrettyPrintable.java b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/PrettyPrintable.java
index 3fe1af0..4506602 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/PrettyPrintable.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radix/node/util/PrettyPrintable.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,5 +24,5 @@
* @author Niall Gallagher
*/
public interface PrettyPrintable {
- public Node getNode();
+ Node getNode();
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/ConcurrentInvertedRadixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/ConcurrentInvertedRadixTree.java
index 89e3ff5..bbaad83 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/ConcurrentInvertedRadixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/ConcurrentInvertedRadixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -37,8 +37,12 @@
*/
public class ConcurrentInvertedRadixTree implements InvertedRadixTree, PrettyPrintable, Serializable {
+ private static final long serialVersionUID = 1L;
+
static class ConcurrentInvertedRadixTreeImpl extends ConcurrentRadixTree {
+ private static final long serialVersionUID = 1L;
+
public ConcurrentInvertedRadixTreeImpl(NodeFactory nodeFactory) {
super(nodeFactory);
}
@@ -80,14 +84,13 @@ protected KeyValuePair computeNext() {
}
currentNode = nextNode;
- CharSequence currentNodeEdgeCharacters = currentNode.getIncomingEdge();
- final int numCharsInEdge = currentNodeEdgeCharacters.length();
+ final int numCharsInEdge = currentNode.getIncomingEdgeLength();
if (numCharsInEdge + charsMatched > documentLength) {
// This node can't be a match because it is too long...
return endOfData();
}
for (int i = 0; i < numCharsInEdge; i++) {
- if (currentNodeEdgeCharacters.charAt(i) != input.charAt(charsMatched + i)) {
+ if (currentNode.getIncomingEdgeCharacterAt(i) != input.charAt(charsMatched + i)) {
// Found a difference between a character in the input
// and a character in the edge represented by current node,
// current node is a dead end...
@@ -138,14 +141,13 @@ protected KeyValuePair scanForLongestKeyAtStartOfInput(final CharSequence inp
}
currentNode = nextNode;
- CharSequence currentNodeEdgeCharacters = currentNode.getIncomingEdge();
- final int numCharsInEdge = currentNodeEdgeCharacters.length();
+ final int numCharsInEdge = currentNode.getIncomingEdgeLength();
if (numCharsInEdge + charsMatched > documentLength) {
// This node can't be a match because it is too long...
break;
}
for (int i = 0; i < numCharsInEdge; i++) {
- if (currentNodeEdgeCharacters.charAt(i) != input.charAt(charsMatched + i)) {
+ if (currentNode.getIncomingEdgeCharacterAt(i) != input.charAt(charsMatched + i)) {
// Found a difference between a character in the input
// and a character in the edge represented by current node,
// current node is a dead end...
@@ -266,7 +268,7 @@ public Iterable getKeysPrefixing(final CharSequence document) {
@Override
public Iterator iterator() {
return new LazyIterator() {
- Iterator> matchesForCurrentSuffix = radixTree.scanForKeysAtStartOfInput(document).iterator();
+ final Iterator> matchesForCurrentSuffix = radixTree.scanForKeysAtStartOfInput(document).iterator();
@Override
protected CharSequence computeNext() {
@@ -291,7 +293,7 @@ public Iterable getValuesForKeysPrefixing(final CharSequence document) {
@Override
public Iterator iterator() {
return new LazyIterator() {
- Iterator> matchesForCurrentSuffix = radixTree.scanForKeysAtStartOfInput(document).iterator();
+ final Iterator> matchesForCurrentSuffix = radixTree.scanForKeysAtStartOfInput(document).iterator();
@Override
protected O computeNext() {
@@ -316,7 +318,7 @@ public Iterable> getKeyValuePairsForKeysPrefixing(final CharSequ
@Override
public Iterator> iterator() {
return new LazyIterator>() {
- Iterator> matchesForCurrentSuffix = radixTree.scanForKeysAtStartOfInput(document).iterator();
+ final Iterator> matchesForCurrentSuffix = radixTree.scanForKeysAtStartOfInput(document).iterator();
@Override
protected KeyValuePair computeNext() {
@@ -368,7 +370,7 @@ public Iterable getKeysContainedIn(final CharSequence document) {
@Override
public Iterator iterator() {
return new LazyIterator() {
- Iterator documentSuffixes = CharSequences.generateSuffixes(document).iterator();
+ final Iterator documentSuffixes = CharSequences.generateSuffixes(document).iterator();
Iterator> matchesForCurrentSuffix = Collections.>emptyList().iterator();
@Override
@@ -398,7 +400,7 @@ public Iterable getValuesForKeysContainedIn(final CharSequence document) {
@Override
public Iterator iterator() {
return new LazyIterator() {
- Iterator documentSuffixes = CharSequences.generateSuffixes(document).iterator();
+ final Iterator documentSuffixes = CharSequences.generateSuffixes(document).iterator();
Iterator> matchesForCurrentSuffix = Collections.>emptyList().iterator();
@Override
@@ -428,7 +430,7 @@ public Iterable> getKeyValuePairsForKeysContainedIn(final CharSe
@Override
public Iterator> iterator() {
return new LazyIterator>() {
- Iterator documentSuffixes = CharSequences.generateSuffixes(document).iterator();
+ final Iterator documentSuffixes = CharSequences.generateSuffixes(document).iterator();
Iterator> matchesForCurrentSuffix = Collections.>emptyList().iterator();
@Override
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/InvertedRadixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/InvertedRadixTree.java
index 3c43b5f..455e390 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/InvertedRadixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radixinverted/InvertedRadixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -113,7 +113,7 @@ public interface InvertedRadixTree extends RadixTree {
* @return The longest key in the tree which is a prefix of the given document, or null if no such key is
* contained in the tree
*/
- public CharSequence getLongestKeyPrefixing(CharSequence document);
+ CharSequence getLongestKeyPrefixing(CharSequence document);
/**
* Returns the value associated with the longest key in the tree which is a prefix of the given document.
@@ -122,7 +122,7 @@ public interface InvertedRadixTree extends RadixTree {
* @return The value associated with longest key in the tree which is a prefix of the given document, or null if
* no such key is contained in the tree
*/
- public O getValueForLongestKeyPrefixing(CharSequence document);
+ O getValueForLongestKeyPrefixing(CharSequence document);
/**
* Returns the {@link KeyValuePair} for the longest key in the tree which is a prefix of the given document.
@@ -131,7 +131,7 @@ public interface InvertedRadixTree extends RadixTree {
* @return The {@link KeyValuePair} for the longest key in the tree which is a prefix of the given document,
* or null if no such key is contained in the tree
*/
- public KeyValuePair getKeyValuePairForLongestKeyPrefixing(CharSequence document);
+ KeyValuePair getKeyValuePairForLongestKeyPrefixing(CharSequence document);
/**
* Returns a lazy iterable which returns the set of keys in the tree which are contained in the given document.
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ConcurrentReversedRadixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ConcurrentReversedRadixTree.java
index b312186..018e64d 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ConcurrentReversedRadixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ConcurrentReversedRadixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,7 +35,11 @@
*/
public class ConcurrentReversedRadixTree implements ReversedRadixTree, PrettyPrintable, Serializable {
- class ConcurrentReverseRadixTreeImpl extends ConcurrentRadixTree {
+ private static final long serialVersionUID = 1L;
+
+ static class ConcurrentReverseRadixTreeImpl extends ConcurrentRadixTree {
+
+ private static final long serialVersionUID = 1L;
public ConcurrentReverseRadixTreeImpl(NodeFactory nodeFactory) {
super(nodeFactory);
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ReversedRadixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ReversedRadixTree.java
index 85ecdb4..c821097 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ReversedRadixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/radixreversed/ReversedRadixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/solver/LCSubstringSolver.java b/code/src/main/java/com/googlecode/concurrenttrees/solver/LCSubstringSolver.java
index 72e8d8a..9a63c02 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/solver/LCSubstringSolver.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/solver/LCSubstringSolver.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,7 @@
package com.googlecode.concurrenttrees.solver;
import com.googlecode.concurrenttrees.common.CharSequences;
+import com.googlecode.concurrenttrees.common.SetFromMap;
import com.googlecode.concurrenttrees.radix.ConcurrentRadixTree;
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
@@ -36,6 +37,8 @@ public class LCSubstringSolver {
class ConcurrentSuffixTreeImpl extends ConcurrentRadixTree {
+ private static final long serialVersionUID = 1L;
+
public ConcurrentSuffixTreeImpl(NodeFactory nodeFactory) {
super(nodeFactory);
}
@@ -211,6 +214,6 @@ public CharSequence getLongestCommonSubstring() {
}
protected Set createSetForOriginalKeys() {
- return Collections.newSetFromMap(new ConcurrentHashMap());
+ return new SetFromMap(new ConcurrentHashMap());
}
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/suffix/ConcurrentSuffixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/suffix/ConcurrentSuffixTree.java
index 950d41e..6b739b5 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/suffix/ConcurrentSuffixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/suffix/ConcurrentSuffixTree.java
@@ -18,6 +18,7 @@
import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.common.KeyValuePair;
import com.googlecode.concurrenttrees.common.LazyIterator;
+import com.googlecode.concurrenttrees.common.SetFromMap;
import com.googlecode.concurrenttrees.radix.ConcurrentRadixTree;
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
@@ -38,7 +39,11 @@
*/
public class ConcurrentSuffixTree implements SuffixTree, PrettyPrintable, Serializable {
- class ConcurrentSuffixTreeImpl extends ConcurrentRadixTree {
+ private static final long serialVersionUID = 1L;
+
+ static class ConcurrentSuffixTreeImpl extends ConcurrentRadixTree {
+
+ private static final long serialVersionUID = 1L;
public ConcurrentSuffixTreeImpl(NodeFactory nodeFactory) {
super(nodeFactory);
@@ -197,7 +202,7 @@ void removeSuffixesFromRadixTree(String keyAsString) {
* @return A new {@link Set} in which original keys from which a suffix was generated can be stored
*/
protected Set createSetForOriginalKeys() {
- return Collections.newSetFromMap(new ConcurrentHashMap());
+ return new SetFromMap(new ConcurrentHashMap());
}
/**
@@ -234,7 +239,7 @@ public Iterable getValuesForKeysEndingWith(final CharSequence suffix) {
@Override
public Iterator iterator() {
return new LazyIterator() {
- Iterator originalKeys = nullSafeIterator(radixTree.getValueForExactKey(suffix));
+ final Iterator originalKeys = nullSafeIterator(radixTree.getValueForExactKey(suffix));
@Override
protected O computeNext() {
@@ -262,7 +267,7 @@ public Iterable> getKeyValuePairsForKeysEndingWith(final CharSeq
@Override
public Iterator> iterator() {
return new LazyIterator>() {
- Iterator originalKeys = nullSafeIterator(radixTree.getValueForExactKey(suffix));
+ final Iterator originalKeys = nullSafeIterator(radixTree.getValueForExactKey(suffix));
@Override
protected KeyValuePair computeNext() {
@@ -292,12 +297,12 @@ public Iterable getKeysContaining(final CharSequence fragment) {
public Iterator iterator() {
return new LazyIterator() {
- Iterator> originalKeysSets = radixTree.getValuesForKeysStartingWith(fragment).iterator();
+ final Iterator> originalKeysSets = radixTree.getValuesForKeysStartingWith(fragment).iterator();
Iterator keyIterator = Collections.emptyList().iterator();
// A given fragment can be contained many times within the same key, so track keys processed
// so far, so that we can avoid re-processing the same key multiple times...
- Set keysAlreadyProcessed = new HashSet();
+ final Set keysAlreadyProcessed = new HashSet();
@Override
protected CharSequence computeNext() {
@@ -332,12 +337,12 @@ public Iterable getValuesForKeysContaining(final CharSequence fragment) {
public Iterator iterator() {
return new LazyIterator() {
- Iterator> originalKeysSets = radixTree.getValuesForKeysStartingWith(fragment).iterator();
+ final Iterator> originalKeysSets = radixTree.getValuesForKeysStartingWith(fragment).iterator();
Iterator keyIterator = Collections.emptyList().iterator();
// A given fragment can be contained many times within the same key, so track keys processed
// so far, so that we can avoid re-processing the same key multiple times...
- Set keysAlreadyProcessed = new HashSet();
+ final Set keysAlreadyProcessed = new HashSet();
@Override
protected O computeNext() {
@@ -376,12 +381,12 @@ public Iterable> getKeyValuePairsForKeysContaining(final CharSeq
public Iterator> iterator() {
return new LazyIterator>() {
- Iterator> originalKeysSets = radixTree.getValuesForKeysStartingWith(fragment).iterator();
+ final Iterator> originalKeysSets = radixTree.getValuesForKeysStartingWith(fragment).iterator();
Iterator keyIterator = Collections.emptyList().iterator();
// A given fragment can be contained many times within the same key, so track keys processed
// so far, so that we can avoid re-processing the same key multiple times...
- Set keysAlreadyProcessed = new HashSet();
+ final Set keysAlreadyProcessed = new HashSet();
@Override
protected KeyValuePair computeNext() {
@@ -422,7 +427,6 @@ public int size() {
/**
* Utility method to return an iterator for the given iterable, or an empty iterator if the iterable is null.
*/
- @SuppressWarnings({"JavaDoc"})
static Iterator nullSafeIterator(Iterable iterable) {
return iterable == null ? Collections.emptyList().iterator() : iterable.iterator();
}
diff --git a/code/src/main/java/com/googlecode/concurrenttrees/suffix/SuffixTree.java b/code/src/main/java/com/googlecode/concurrenttrees/suffix/SuffixTree.java
index 250e946..d1df4b5 100644
--- a/code/src/main/java/com/googlecode/concurrenttrees/suffix/SuffixTree.java
+++ b/code/src/main/java/com/googlecode/concurrenttrees/suffix/SuffixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/common/CharSequencesTest.java b/code/src/test/java/com/googlecode/concurrenttrees/common/CharSequencesTest.java
index 1dc4241..6d2d088 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/common/CharSequencesTest.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/common/CharSequencesTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/common/IterablesTest.java b/code/src/test/java/com/googlecode/concurrenttrees/common/IterablesTest.java
index 87386e6..9744015 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/common/IterablesTest.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/common/IterablesTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/common/LazyIteratorTest.java b/code/src/test/java/com/googlecode/concurrenttrees/common/LazyIteratorTest.java
index 4b43bba..2d02be9 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/common/LazyIteratorTest.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/common/LazyIteratorTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/common/PrettyPrinterTest.java b/code/src/test/java/com/googlecode/concurrenttrees/common/PrettyPrinterTest.java
index c287e24..9030258 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/common/PrettyPrinterTest.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/common/PrettyPrinterTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,14 +17,13 @@
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultCharArrayNodeFactory;
import com.googlecode.concurrenttrees.radix.node.util.PrettyPrintable;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
/**
* @author Niall Gallagher
@@ -110,14 +109,14 @@ static Node getHandBuiltTestTree() {
// └── ○ DANA (4)
final Node n1, n2, n3, n4, n5, n6;
- n6 = nodeFactory.createNode("A", 6, Collections.emptyList(), false);
- n5 = nodeFactory.createNode("AN", 5, Arrays.asList(n6), false);
- n4 = nodeFactory.createNode("DANA", 4, Collections.emptyList(), false);
- n3 = nodeFactory.createNode("N", 3, Arrays.asList(n4, n5), false); // note: it should sort these such that n5 is first
- n2 = nodeFactory.createNode("A", 2, Arrays.asList(n3), false);
- n1 = nodeFactory.createNode("B", 1, Arrays.asList(n2), false);
+ n6 = nodeFactory.createNode("A", 6, SimpleNodeList.EMPTY, false);
+ n5 = nodeFactory.createNode("AN", 5, new SimpleNodeList(n6), false);
+ n4 = nodeFactory.createNode("DANA", 4, SimpleNodeList.EMPTY, false);
+ n3 = nodeFactory.createNode("N", 3, new SimpleNodeList(n4, n5), false); // note: it should sort these such that n5 is first
+ n2 = nodeFactory.createNode("A", 2, new SimpleNodeList(n3), false);
+ n1 = nodeFactory.createNode("B", 1, new SimpleNodeList(n2), false);
//noinspection NullableProblems
- return nodeFactory.createNode("", null, Arrays.asList(n1), true); // root
+ return nodeFactory.createNode("", null, new SimpleNodeList(n1), true); // root
}
PrettyPrintable wrapNodeForPrinting(final Node node) {
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/ConcurrentRadixTreeInMemoryFileSystem.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/ConcurrentRadixTreeInMemoryFileSystem.java
index 592cbbf..9448064 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/ConcurrentRadixTreeInMemoryFileSystem.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/ConcurrentRadixTreeInMemoryFileSystem.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystem.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystem.java
index 6684ef2..3696445 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystem.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystem.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystemUsage.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystemUsage.java
index 1c50265..c406706 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystemUsage.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/filesystem/InMemoryFileSystemUsage.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareSinglePlaySuffixTree.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareSinglePlaySuffixTree.java
index daff253..c2af06c 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareSinglePlaySuffixTree.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareSinglePlaySuffixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareTragediesSuffixTree.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareTragediesSuffixTree.java
index e080369..9511cf7 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareTragediesSuffixTree.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareTragediesSuffixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordRadixTree.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordRadixTree.java
index 93a95d7..c4f9d3c 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordRadixTree.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordRadixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordSuffixTree.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordSuffixTree.java
index e269c31..54454d3 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordSuffixTree.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/BuildShakespeareWordSuffixTree.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/FindLongestCommonSubstring.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/FindLongestCommonSubstring.java
index adeba2a..7c2d8ea 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/FindLongestCommonSubstring.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/FindLongestCommonSubstring.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/util/IOUtil.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/util/IOUtil.java
index 60e215d..771ec8c 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/util/IOUtil.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/shakespeare/util/IOUtil.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/InvertedRadixTreeUsage.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/InvertedRadixTreeUsage.java
index 70f9c11..3f5e5c8 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/InvertedRadixTreeUsage.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/InvertedRadixTreeUsage.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/IterablesUsage.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/IterablesUsage.java
index 0fca12c..23b89a5 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/IterablesUsage.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/IterablesUsage.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/LCSubstringSolverUsage.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/LCSubstringSolverUsage.java
index b094fe2..117ddec 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/LCSubstringSolverUsage.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/LCSubstringSolverUsage.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/RadixTreeUsage.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/RadixTreeUsage.java
index 33e7448..4404d4c 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/RadixTreeUsage.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/RadixTreeUsage.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/ReversedRadixTreeUsage.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/ReversedRadixTreeUsage.java
index 5314656..e51ae9d 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/ReversedRadixTreeUsage.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/ReversedRadixTreeUsage.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/SuffixTreeUsage.java b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/SuffixTreeUsage.java
index 3891a0c..69c9701 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/SuffixTreeUsage.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/examples/usage/SuffixTreeUsage.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTreeTest.java b/code/src/test/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTreeTest.java
index ef38e28..82f4cf4 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTreeTest.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/radix/ConcurrentRadixTreeTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,25 +15,19 @@
*/
package com.googlecode.concurrenttrees.radix;
-import com.googlecode.concurrenttrees.common.CharSequences;
import com.googlecode.concurrenttrees.common.Iterables;
import com.googlecode.concurrenttrees.common.KeyValuePair;
import com.googlecode.concurrenttrees.common.PrettyPrinter;
import com.googlecode.concurrenttrees.radix.node.Node;
import com.googlecode.concurrenttrees.radix.node.NodeFactory;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultCharArrayNodeFactory;
import com.googlecode.concurrenttrees.radix.node.concrete.DefaultCharSequenceNodeFactory;
import com.googlecode.concurrenttrees.radix.node.concrete.voidvalue.VoidValue;
import com.googlecode.concurrenttrees.radix.node.util.PrettyPrintable;
import com.googlecode.concurrenttrees.testutil.TestUtility;
-import junit.framework.Assert;
import org.junit.Test;
-import java.io.*;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
import static org.junit.Assert.*;
/**
* @author Niall Gallagher
@@ -59,14 +53,14 @@ public void testBuildTreeByHand() {
// └── ○ DANA (4)
final Node root, n1, n2, n3, n4, n5, n6;
- n6 = getNodeFactory().createNode("A", 6, Collections.emptyList(), false);
- n5 = getNodeFactory().createNode("AN", 5, Arrays.asList(n6), false);
- n4 = getNodeFactory().createNode("DANA", 4, Collections.emptyList(), false);
- n3 = getNodeFactory().createNode("N", 3, Arrays.asList(n4, n5), false); // note: it should sort alphabetically such that n5 is first
- n2 = getNodeFactory().createNode("A", 2, Arrays.asList(n3), false);
- n1 = getNodeFactory().createNode("B", 1, Arrays.asList(n2), false);
+ n6 = getNodeFactory().createNode("A", 6, SimpleNodeList.EMPTY, false);
+ n5 = getNodeFactory().createNode("AN", 5, new SimpleNodeList(n6), false);
+ n4 = getNodeFactory().createNode("DANA", 4, SimpleNodeList.EMPTY, false);
+ n3 = getNodeFactory().createNode("N", 3, new SimpleNodeList(n4, n5), false); // note: it should sort alphabetically such that n5 is first
+ n2 = getNodeFactory().createNode("A", 2, new SimpleNodeList(n3), false);
+ n1 = getNodeFactory().createNode("B", 1, new SimpleNodeList(n2), false);
//noinspection NullableProblems
- root = getNodeFactory().createNode("", null, Arrays.asList(n1), true);
+ root = getNodeFactory().createNode("", null, new SimpleNodeList(n1), true);
String expected =
"○\n" +
@@ -282,6 +276,9 @@ protected Classification classify(CharSequence key, Node nodeFound, int charsMat
}
// Override searchTree() to return the InvalidSearchResult...
ConcurrentRadixTree tree = new ConcurrentRadixTree(getNodeFactory()) {
+
+ private static final long serialVersionUID = 1L;
+
@Override
SearchResult searchTree(CharSequence key) {
return new InvalidSearchResult("FOO", root, 4, 4, null, null);
@@ -850,14 +847,14 @@ public void testSearchTree() {
// └── ○ DANA (4)
final Node root, n1, n2, n3, n4, n5, n6;
- n6 = getNodeFactory().createNode("A", 6, Collections.emptyList(), false);
- n5 = getNodeFactory().createNode("AN", 5, Arrays.asList(n6), false);
- n4 = getNodeFactory().createNode("DANA", 4, Collections.emptyList(), false);
- n3 = getNodeFactory().createNode("N", 3, Arrays.asList(n4, n5), false); // note: it should sort these such that n5 is first
- n2 = getNodeFactory().createNode("A", 2, Arrays.asList(n3), false);
- n1 = getNodeFactory().createNode("B", 1, Arrays.asList(n2), false);
+ n6 = getNodeFactory().createNode("A", 6, SimpleNodeList.EMPTY, false);
+ n5 = getNodeFactory().createNode("AN", 5, new SimpleNodeList(n6), false);
+ n4 = getNodeFactory().createNode("DANA", 4, SimpleNodeList.EMPTY, false);
+ n3 = getNodeFactory().createNode("N", 3, new SimpleNodeList(n4, n5), false); // note: it should sort these such that n5 is first
+ n2 = getNodeFactory().createNode("A", 2, new SimpleNodeList(n3), false);
+ n1 = getNodeFactory().createNode("B", 1, new SimpleNodeList(n2), false);
//noinspection NullableProblems
- root = getNodeFactory().createNode("", null, Arrays.asList(n1), true);
+ root = getNodeFactory().createNode("", null, new SimpleNodeList(n1), true);
// Overwrite the tree's default root with the one built by hand...
tree.root = root;
@@ -951,7 +948,7 @@ public void testSearchResult_FailureToClassify1() {
@Test(expected = IllegalStateException.class)
public void testSearchResult_FailureToClassify2() {
// Testing the various (unlikely) ways to fall through classification to have the exception thrown...
- Node dummyNodeFound = getNodeFactory().createNode("DUMMY", 1, Collections.emptyList(), false);
+ Node dummyNodeFound = getNodeFactory().createNode("DUMMY", 1, SimpleNodeList.EMPTY, false);
new ConcurrentRadixTree.SearchResult("DUMMY", dummyNodeFound, 5, 70, null, null);
}
@@ -959,7 +956,7 @@ public void testSearchResult_FailureToClassify2() {
@Test(expected = IllegalStateException.class)
public void testSearchResult_FailureToClassify3() {
// Testing the various (unlikely) ways to fall through classification to have the exception thrown...
- Node dummyNodeFound = getNodeFactory().createNode("DUMMY", 1, Collections.emptyList(), false);
+ Node dummyNodeFound = getNodeFactory().createNode("DUMMY", 1, SimpleNodeList.EMPTY, false);
new ConcurrentRadixTree.SearchResult("DUMMY", dummyNodeFound, 4, 70, null, null);
}
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactoryTest.java b/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactoryTest.java
index 61074f5..a703cff 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactoryTest.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultByteArrayNodeFactoryTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,30 +16,43 @@
package com.googlecode.concurrenttrees.radix.node.concrete;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
+import org.junit.Before;
import org.junit.Test;
import java.util.Collections;
+import static junit.framework.Assert.assertTrue;
+
/**
* @author Niall Gallagher
*/
public class DefaultByteArrayNodeFactoryTest {
+ private boolean assertions;
+
+ @Before
+ public void setUp() {
+ assert assertions = true;
+ }
- @Test(expected = IllegalStateException.class)
+ @Test(expected = AssertionError.class)
public void testCreateNode_NullEdge() throws Exception {
+ assertTrue(assertions);
//noinspection NullableProblems
- new DefaultByteArrayNodeFactory().createNode(null, 1, Collections.emptyList(), false);
+ new DefaultByteArrayNodeFactory().createNode(null, 1, SimpleNodeList.EMPTY, false);
}
- @Test(expected = IllegalStateException.class)
+ @Test(expected = AssertionError.class)
public void testCreateNode_EmptyEdgeNonRoot() throws Exception {
+ assertTrue(assertions);
//noinspection NullableProblems
- new DefaultByteArrayNodeFactory().createNode("", 1, Collections.emptyList(), false);
+ new DefaultByteArrayNodeFactory().createNode("", 1, SimpleNodeList.EMPTY, false);
}
- @Test(expected = IllegalStateException.class)
+ @Test(expected = AssertionError.class)
public void testCreateNode_NullEdges() throws Exception {
+ assertTrue(assertions);
//noinspection NullableProblems
new DefaultByteArrayNodeFactory().createNode("FOO", 1, null, false);
}
diff --git a/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactoryTest.java b/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactoryTest.java
index e7ff1c9..50030b7 100644
--- a/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactoryTest.java
+++ b/code/src/test/java/com/googlecode/concurrenttrees/radix/node/concrete/DefaultCharArrayNodeFactoryTest.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright 2012-2013 Niall Gallagher
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,30 +16,43 @@
package com.googlecode.concurrenttrees.radix.node.concrete;
import com.googlecode.concurrenttrees.radix.node.Node;
+import com.googlecode.concurrenttrees.radix.node.SimpleNodeList;
+import org.junit.Before;
import org.junit.Test;
import java.util.Collections;
+import static junit.framework.Assert.assertTrue;
+
/**
* @author Niall Gallagher
*/
public class DefaultCharArrayNodeFactoryTest {
+ private boolean assertions;
+
+ @Before
+ public void setUp() {
+ assert assertions = true;
+ }
- @Test(expected = IllegalStateException.class)
+ @Test(expected = AssertionError.class)
public void testCreateNode_NullEdge() throws Exception {
+ assertTrue(assertions);
//noinspection NullableProblems
- new DefaultCharArrayNodeFactory().createNode(null, 1, Collections.emptyList(), false);
+ new DefaultCharArrayNodeFactory().createNode(null, 1, SimpleNodeList.EMPTY, false);
}
- @Test(expected = IllegalStateException.class)
+ @Test(expected = AssertionError.class)
public void testCreateNode_EmptyEdgeNonRoot() throws Exception {
+ assertTrue(assertions);
//noinspection NullableProblems
- new DefaultCharArrayNodeFactory().createNode("", 1, Collections.