All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.interedition.collatex.suffixtree.Node Maven / Gradle / Ivy

package eu.interedition.collatex.suffixtree;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 *
 * @param 
 * @param 
 *
 * @author Max Garfinkel
 */
class Node> implements Iterable> {
	private final Map> edges = new HashMap>();
	private final Edge incomingEdge;
	private Set> sequenceTerminals = new HashSet>();
	private final Sequence sequence;
	private final SuffixTree tree;
	private Node link = null;

	/**
	 * Create a new node, for the supplied tree and sequence.
	 * 
	 * @param incomingEdge
	 *            The parent edge, unless this is a root node.
	 * @param sequence
	 *            The sequence this tree is indexing.
	 * @param tree
	 *            The tree to which this node belongs.
	 */
	Node(Edge incomingEdge, Sequence sequence, SuffixTree tree) {
		this.incomingEdge = incomingEdge;
		this.sequence = sequence;
		this.tree = tree;
	}

	/**
	 * Inserts the suffix at the given active point.
	 * 
	 * @param suffix
	 *            The suffix to insert.
	 * @param activePoint
	 *            The active point to insert it at.
	 */
	@SuppressWarnings("unchecked")
	void insert(Suffix suffix, ActivePoint activePoint) {
		Object item = suffix.getEndItem();
		
		if (edges.containsKey(item)) {
			if (tree.isNotFirstInsert() && activePoint.getNode() != tree.getRoot())
				tree.setSuffixLink(activePoint.getNode());
			activePoint.setEdge(edges.get(item));
			activePoint.incrementLength();
		} else {
			saveSequenceTerminal(item);
			Edge newEdge = new Edge(suffix.getEndPosition()-1, this,
					sequence, tree);
			edges.put((T) suffix.getEndItem(), newEdge);
			suffix.decrement();
			activePoint.updateAfterInsert(suffix);
			
			if(tree.isNotFirstInsert() && !this.equals(tree.getRoot())){
				tree.getLastNodeInserted().setSuffixLink(this);
			}
			if (suffix.isEmpty())
				return;
			else
				tree.insert(suffix);
		}
	}

	private void saveSequenceTerminal(Object item) {
		if(item.getClass().equals(SequenceTerminal.class)){
			@SuppressWarnings("unchecked")
			SequenceTerminal terminal = (SequenceTerminal) item;
			sequenceTerminals.add(terminal);
		}
	}

	/**
	 * Inserts the given edge as a child of this node. The edge must not already
	 * exist as child or an IllegalArgumentException will be thrown.
	 * 
	 * @param edge
	 *            The edge to be inserted.
	 * @throws IllegalArgumentException
	 *             This is thrown when the edge already exists as an out bound
	 *             edge of this node.
	 */
	void insert(Edge edge) {
		if (edges.containsKey(edge.getStartItem()))
			throw new IllegalArgumentException("Item " + edge.getStartItem()
					+ " already exists in node " + toString());
		edges.put(edge.getStartItem(), edge);
	}

	/**
	 * Retrieves the edge starting with item or null if none exists.
	 * 
	 * @param item
	 * @return The edge extending from this node starting with item.
	 */
	Edge getEdgeStarting(Object item) {
			return edges.get(item);
	}

	/**
	 * True if the node has a suffix link extending from it.
	 * 
	 * @return True if node has suffix link. False if not.
	 */
	boolean hasSuffixLink() {
		return link != null;
	}

	/**
	 * Gets the number of edges extending from this node.
	 * 
	 * @return The count of the number edges extending from this node.
	 */
	int getEdgeCount() {
		return edges.size();
	}

	/**
	 * @return An iterator which iterates over the child edges. No order is
	 *         guaranteed.
	 */
	public Iterator> iterator() {
		return edges.values().iterator();
	}

	/**
	 * 
	 * @return The node that this nodes suffix link points to if it has one.
	 *         Null if not.
	 */
	Node getSuffixLink() {
		return link;
	}

	/**
	 * Sets the suffix link of this node to point to the supplied node.
	 * 
	 * @param node
	 *            The node this suffix link should point to.
	 */
	void setSuffixLink(Node node) {
		link = node;
	}

	@Override
	public String toString() {
		if (incomingEdge == null)
			return "root";
		else {
			return "end of edge [" + incomingEdge.toString() + "]";
		}
	}

	public Collection> getSuffixTerminals() {
		return sequenceTerminals;
	}
	
	public Collection> getEdges(){
		return edges.values();
	}
}