
querqy.trie.Node Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of querqy-core Show documentation
Show all versions of querqy-core Show documentation
Querqy library for query rewriting: Querqy Core
/**
*
*/
package querqy.trie;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* @author René Kriegler, @renekrie
*
*/
public class Node {
public final char character;
T value;
T prefixValue;
Node firstChild;
Node next;
boolean hasPrefix = false;
public Node(char character, T value) {
this.character = character;
this.value = value;
}
public Node(char character) {
this(character, null);
}
public void putPrefix(CharSequence seq, int index, T value) {
put(seq, index, value, true);
}
public void put(CharSequence seq, int index, T value) {
put(seq, index, value, false);
}
public void put(CharSequence seq, int index, T value, boolean isPrefix) {
if (seq.charAt(index) == character) {
if (index == (seq.length() - 1)) {
if (isPrefix) {
this.prefixValue = value;
} else {
this.value = value;
}
this.hasPrefix |= isPrefix;
} else {
if (firstChild == null) {
synchronized (this) {
if (firstChild == null) {
firstChild = new Node(seq.charAt(index + 1));
}
}
}
firstChild.put(seq, index + 1, value, isPrefix);
}
} else {
if (next == null) {
synchronized (this) {
if (next == null) {
next = new Node<>(seq.charAt(index));
}
}
}
next.put(seq, index, value, isPrefix);
}
}
public States get(CharSequence seq, int index) {
if (seq.charAt(index) == character) {
if (index == seq.length() - 1) {
return new States<>(new State(true, value, this, index));
// do not add prefix match here, as we should have at least one char matching the wildcard
} else {
if (firstChild == null) {
States states = new States<>(new State(false, null, null));
if (hasPrefix) {
states.addPrefix(new State<>(true, prefixValue, this, seq.charAt(0) == ' ' ? index - 1 : index));
}
return states;
} else {
States states = firstChild.get(seq, index + 1);
if (hasPrefix) {
states.addPrefix(new State<>(true, prefixValue, this, seq.charAt(0) == ' ' ? index - 1 : index));
}
return states;
}
}
} else {
return (next != null) ? next.get(seq, index) : new States<>(new State(false, null, null));
}
}
public States getNext(CharSequence seq, int index) {
return (firstChild != null) ? firstChild.get(seq, index) : new States<>(new State(false, null, null));
}
public ValueIterator iterator() {
return new ValueIterator();
}
enum IterationState {THIS, THIS_PREFIX, CHILD, NEXT}
public class ValueIterator implements Iterator {
IterationState iterationState = IterationState.THIS;
ValueIterator childIterator = null;
ValueIterator nextIterator = null;
@Override
public boolean hasNext() {
switch (iterationState) {
case THIS:
if (value != null) return true;
iterationState = IterationState.THIS_PREFIX;
return hasNext();
case THIS_PREFIX:
if (prefixValue != null) {
return true;
}
iterationState = IterationState.CHILD;
return hasNext();
case CHILD:
if (childIterator == null) {
if (firstChild == null) {
iterationState = IterationState.NEXT;
return hasNext();
}
childIterator = firstChild.iterator();
}
if (childIterator.hasNext()) {
return true;
}
iterationState = IterationState.NEXT;
return hasNext();
case NEXT:
if (nextIterator == null) {
if (next == null) {
return false;
}
nextIterator = next.iterator();
}
return nextIterator.hasNext();
}
return false;
}
@Override
public T next() {
if (!hasNext()) throw new NoSuchElementException();
switch (iterationState) {
case THIS: iterationState = IterationState.THIS_PREFIX; return value;
case THIS_PREFIX: iterationState = IterationState.CHILD; return prefixValue;
case CHILD: return childIterator.next();
case NEXT: return nextIterator.next();
}
throw new NoSuchElementException();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy