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.");
}
};
}
}