/*
* Copyright (C) 2012 Jason Gedge <www.gedge.ca>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package io.github.xwz.base.trie;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.TreeSet;
/**
* A node in a radix tree.
*
* @param <V>
*/
class RadixTreeNode<V> implements Iterable<RadixTreeNode<V>>, Comparable<RadixTreeNode<V>>, Serializable {
/**
* The prefix at this node
*/
private String prefix;
/**
* The value stored at this node
*/
private V value;
/**
* Whether or not this node stores a value. This value is mainly used by
* {@link RadixTreeVisitor} to figure out whether or not this node should
* be visited.
*/
private boolean hasValue;
/**
* The children for this node. Note, because we use {@link TreeSet} here,
* traversal of {@link RadixTree} will be in lexicographical order.
*/
private Collection<RadixTreeNode<V>> children;
/**
* Constructs a node from the given prefix.
*
* @param prefix the prefix
*/
RadixTreeNode(String prefix) {
this(prefix, null);
this.hasValue = false;
}
/**
* Constructs a node from the given prefix and value.
*
* @param prefix the prefix
* @param value the value
*/
RadixTreeNode(String prefix, V value) {
this.prefix = prefix;
this.value = value;
this.hasValue = true;
}
/**
* Gets the value attached to this node.
*
* @return the value, or <code>null</code> if an internal node
*/
V getValue() {
return value;
}
/**
* Sets the value attached to this node.
*
* @param value the value, or <code>null</code> if an internal node
*/
void setValue(V value) {
this.value = value;
}
/**
* Gets the prefix associated with this node.
*
* @return the prefix
*/
String getPrefix() {
return prefix;
}
/**
* Sets the prefix associated with this node.
*
* @param prefix the prefix
*/
void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* Gets the children of this node.
*
* @return the list of children
*/
Collection<RadixTreeNode<V>> getChildren() {
// Delayed creation of children to reduce memory cost
if (children == null)
children = new TreeSet<>();
return children;
}
/**
* Whether or not this node has a value attached to it.
*
* @return whether or not this node has a value
*/
boolean hasValue() {
return hasValue;
}
/**
* Sets whether or not this node has a value attached to it.
*
* @param hasValue <code>true</code> if this node will have a value,
* <code>false</code> otherwise. If <code>false</code>,
* {@link #getValue()} will return <code>null</code>
* after this call.
*/
void setHasValue(boolean hasValue) {
this.hasValue = hasValue;
if (!hasValue)
this.value = null;
}
@Override
public Iterator<RadixTreeNode<V>> iterator() {
if (children == null) {
return new Iterator<RadixTreeNode<V>>() {
@Override
public boolean hasNext() {
return false;
}
@Override
public RadixTreeNode<V> next() {
return null;
}
@Override
public void remove() {
}
};
}
return children.iterator();
}
@Override
public int compareTo(RadixTreeNode<V> node) {
return prefix.compareTo(node.getPrefix());
}
}