/* * Copyright (C) 2014 Francis Galiegue <fgaliegue@gmail.com> * * 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.github.fge.grappa.matchers.trie; import java.nio.CharBuffer; import java.util.Map; import java.util.TreeMap; /** * A builder for a {@link TrieNode} tree * * <p>The tree is built "in depth"; each character of a string will create a new * builder unless there is already a builder for that character.</p> * * <p>When {@link #build()} is called, the whole tree is built from the leaves * up to the root.</p> * * @since 1.0.0-beta.6 */ public final class TrieNodeBuilder { private boolean fullWord = false; private final Map<Character, TrieNodeBuilder> subnodes = new TreeMap<>(); public TrieNodeBuilder addWord(final String word) { doAddWord(CharBuffer.wrap(word)); return this; } /** * Add a word * * <p>Here also, a {@link CharBuffer} is used, which changes position as we * progress into building the tree, character by character, node by node. * </p> * * <p>If the buffer is "empty" when entering this method, it means a match * must be recorded (see {@link #fullWord}).</p> * * @param buffer the buffer (never null) */ private void doAddWord(final CharBuffer buffer) { if (!buffer.hasRemaining()) { fullWord = true; return; } final char c = buffer.get(); TrieNodeBuilder builder = subnodes.get(c); if (builder == null) { builder = new TrieNodeBuilder(); subnodes.put(c, builder); } builder.doAddWord(buffer); } public TrieNode build() { final char[] nextChars = new char[subnodes.size()]; final TrieNode[] nextNodes = new TrieNode[subnodes.size()]; int index = 0; for (final Map.Entry<Character, TrieNodeBuilder> entry: subnodes.entrySet()) { nextChars[index] = entry.getKey(); nextNodes[index] = entry.getValue().build(); index++; } return new TrieNode(fullWord, nextChars, nextNodes); } }