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

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

package eu.interedition.collatex.suffixtree;

import java.util.Iterator;

/**
 *
 * @param 
 * @param 
 *
 * @author Max Garfinkel
 */
class Edge> implements Iterable {
	private final int start;
	private int end = -1;
	private final Node parentNode;
	private final Sequence sequence;

	private Node terminal = null;
	private SuffixTree tree = null;
	
	/**
	 * Create a new Edge object.
	 * 
	 * @param start
	 *            The position in the master sequence of the first item in this
	 *            suffix.
	 * @param parent
	 *            The parent {@link Node}
	 * @param sequence
	 *            The master sequence which the {@link SuffixTree} indexes.
	 * @param tree
	 *            The master {@link SuffixTree} containing the root element
	 *            which this edge is a child of.
	 */
	Edge(int start, Node parent, Sequence sequence, SuffixTree tree) {
		this.start = start;
		this.parentNode = parent;
		this.sequence = sequence;
		this.tree = tree;
	}

	/**
	 * Checks to see if the edge starts with the given item.
	 * 
	 * @param item
	 *            The possible start item.
	 * @return True if this edge starts with item. False if not.
	 */
	boolean isStarting(Object item) {
		return sequence.getItem(start).equals(item);
	}

	/**
	 * Insert the given suffix at the supplied active point.
	 * 
	 * @param suffix
	 *            The suffix to insert.
	 * @param activePoint
	 *            The active point to insert it at.
	 * @return
	 */
	void insert(Suffix suffix, ActivePoint activePoint) {
		Object item = suffix.getEndItem();
		Object nextItem = getItemAt(activePoint.getLength());
		if (item.equals(nextItem)) {
			activePoint.incrementLength();
		} else {
			split(suffix, activePoint);
			suffix.decrement();
			activePoint.updateAfterInsert(suffix);

			if (suffix.isEmpty())
				return;
			else
				tree.insert(suffix);
		}
	}

	/**
	 * Splits the edge to enable the insertion of supplied suffix at the
	 * supplied active point.
	 * 
	 * @param suffix
	 *            The suffix to insert.
	 * @param activePoint
	 *            The active point to insert it at.
	 */
	private void split(Suffix suffix, ActivePoint activePoint) {
		Node breakNode = new Node(this, sequence, tree);
		Edge newEdge = new Edge(suffix.getEndPosition()-1, breakNode,
				sequence, tree);
		breakNode.insert(newEdge);
		Edge oldEdge = new Edge(start + activePoint.getLength(),
				breakNode, sequence, tree);
		oldEdge.end = end;
		oldEdge.terminal = this.terminal;
		breakNode.insert(oldEdge);
		this.terminal = breakNode;
		end = start + activePoint.getLength();
		tree.setSuffixLink(breakNode);
		tree.incrementInsertCount();
	}

	/**
	 * Gets the index of the true end of the edge.
	 * 
	 * @return The index of the end item, of this edge, in the original
	 *         sequence.
	 */
	int getEnd() {
		tree.getCurrentEnd();
		return end != -1 ? end : tree.getCurrentEnd();
	}

	/**
	 * Tests if this edge is terminates at a node.
	 * 
	 * @return True if this edge ends at a node. False if not.
	 */
	boolean isTerminating() {
		return terminal != null;
	}

	/**
	 * Retrieves the length of this edge.
	 * 
	 * @return
	 */
	int getLength() {
		int realEnd = getEnd();
		return realEnd - start;
	}

	/**
	 * Retrieves the terminating node of this edge if it has any, null if not.
	 * 
	 * @return The terminating node if any exists, null otherwise.
	 */
	Node getTerminal() {
		return terminal;
	}

	/**
	 * Retrieves the item at given position within the current edge.
	 * 
	 * @param position
	 *            The index of the item to retrieve relative to the start of
	 *            edge.
	 * @return The item at position.
	 * @throws IllegalArgumentException
	 *             when the position exceeds the length of the current edge.
	 */
	@SuppressWarnings("unchecked")
	T getItemAt(int position) {
		if (position > getLength())
			throw new IllegalArgumentException("Index " + position
					+ " is greater than " + getLength()
					+ " - the length of this edge.");
		return (T) sequence.getItem(start + position);
	}

	/**
	 * Retrieves the starting item of this edge.
	 * 
	 * @return The item at index 0 of this edge.
	 */
	@SuppressWarnings("unchecked")
	T getStartItem() {
		return (T) sequence.getItem(start);
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (int i = start; i < getEnd(); i++) {
			sb.append(sequence.getItem(i).toString()).append(", ");
			if(sequence.getItem(i).getClass().equals(SequenceTerminal.class))
				break;
		}
		return sb.toString();
	}

	/**
	 * Retrieves an iterator that steps over the items in this edge.
	 * 
	 * @return An iterator that walks this edge up to the end or terminating
	 *         node.
	 */
	public Iterator iterator() {
		return new Iterator() {
			private int currentPosition = start;
			private boolean hasNext = true;
			
			public boolean hasNext() {
				return hasNext;
			}

			@SuppressWarnings("unchecked")
			public T next() {
				if(end == -1)
					hasNext = !sequence.getItem(currentPosition).getClass().equals(SequenceTerminal.class);
				else
					hasNext = currentPosition < getEnd()-1;
				return (T) sequence.getItem(currentPosition++);
			}

			public void remove() {
				throw new UnsupportedOperationException(
						"The remove method is not supported.");
			}
		};
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy