@Test
 public void testGetOutgoingEdge_NonExistent() throws Exception {
   Node node =
       new ByteArrayNodeNonLeafVoidValue(
           "FOO",
           Arrays.asList(
               (Node) new ByteArrayNodeDefault("BAR1", 1, Collections.<Node>emptyList())));
   Assert.assertNull(node.getOutgoingEdge('C'));
 }
 @Test(expected = IllegalStateException.class)
 public void testUpdateOutgoingEdge_NonExistentEdge() throws Exception {
   Node node =
       new ByteArrayNodeNonLeafVoidValue(
           "FOO",
           Arrays.asList(
               (Node) new ByteArrayNodeDefault("BAR", 1, Collections.<Node>emptyList())));
   node.updateOutgoingEdge(new ByteArrayNodeDefault("CAR", null, Collections.<Node>emptyList()));
 }
 @Test
 public void testUpdateOutgoingEdge() throws Exception {
   Node node =
       new ByteArrayNodeNonLeafVoidValue(
           "FOO",
           Arrays.asList(
               (Node) new ByteArrayNodeDefault("BAR1", 1, Collections.<Node>emptyList())));
   node.updateOutgoingEdge(new ByteArrayNodeDefault("BAR2", null, Collections.<Node>emptyList()));
 }
 @Override
 public void updateOutgoingEdge(Node childNode) {
   // 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...
   int index =
       NodeUtil.binarySearchForEdge(outgoingEdges, childNode.getIncomingEdgeFirstCharacter());
   if (index < 0) {
     throw new IllegalStateException(
         "Cannot update the reference to the following child node for the edge starting with '"
             + childNode.getIncomingEdgeFirstCharacter()
             + "', no such edge already exists: "
             + childNode);
   }
   // Atomically update the child node at this index...
   outgoingEdges.set(index, childNode);
 }
    /**
     * Traverses the tree based on characters in the given input, and for each node traversed which
     * encodes a key in the tree, invokes the given {@link KeyValueHandler} supplying it the key
     * which matched that node and the value from the node.
     *
     * @param input A sequence of characters which controls traversal of the tree
     * @param keyValueHandler An object which will be notified of every key and value encountered in
     *     the input
     */
    protected void scanForKeysAtStartOfInput(CharSequence input, KeyValueHandler keyValueHandler) {
      Node currentNode = super.root;
      int charsMatched = 0;

      final int documentLength = input.length();
      outer_loop:
      while (charsMatched < documentLength) {
        Node nextNode = currentNode.getOutgoingEdge(input.charAt(charsMatched));
        if (nextNode == null) {
          // Next node is a dead end...
          //noinspection UnnecessaryLabelOnBreakStatement
          break outer_loop;
        }

        currentNode = nextNode;
        CharSequence currentNodeEdgeCharacters = currentNode.getIncomingEdge();
        int charsMatchedThisEdge = 0;
        for (int i = 0,
                j = Math.min(currentNodeEdgeCharacters.length(), documentLength - charsMatched);
            i < j;
            i++) {
          if (currentNodeEdgeCharacters.charAt(i) != input.charAt(charsMatched + i)) {
            // 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;
          }
          charsMatchedThisEdge++;
        }
        if (charsMatchedThisEdge == currentNodeEdgeCharacters.length()) {
          // All characters in the current edge matched, add this number to total chars matched...
          charsMatched += charsMatchedThisEdge;
        }
        if (currentNode.getValue() != null) {
          keyValueHandler.handle(input.subSequence(0, charsMatched), currentNode.getValue());
        }
      }
    }
 @Test
 public void testToString() throws Exception {
   Node node = new ByteArrayNodeNonLeafVoidValue("FOO", Collections.<Node>emptyList());
   Assert.assertEquals("Node{edge=FOO, value=-, edges=[]}", node.toString());
 }