// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.document.annotation;
import com.yahoo.document.serialization.SpanNodeReader;
import java.util.ListIterator;
import java.util.NoSuchElementException;
/**
* This class represents a range of characters from a string. This is the leaf node
* in a Span tree. Its boundaries are defined as inclusive-from and exclusive-to.
*
* @author baldersheim
* @author Einar M R Rosenvinge
*/
public class Span extends SpanNode {
public static final byte ID = 1;
private int from;
private int length;
/**
* This will construct a valid span or throw {@link IllegalArgumentException}
* if the span is invalid.
*
* @param from Start of the span. Must be >= 0.
* @param length of the span. Must be >= 0.
* @throws IllegalArgumentException if illegal span
*/
public Span(int from, int length) {
setFrom(from);
setLength(length);
}
/**
* Creates an empty Span, used mainly for deserialization.
*
* @param reader the reader that must populate this Span instance
*/
public Span(SpanNodeReader reader) {
reader.read(this);
}
/**
* WARNING! Only to be used by deserializers! Creates an empty Span instance.
*/
public Span() {
}
/**
* Copies the given Span into a new Span instance.
*
* @param spanToCopy the Span to copy.
*/
public Span(Span spanToCopy) {
this(spanToCopy.getFrom(), spanToCopy.getLength());
}
@Override
public final int getFrom() {
return from;
}
/**
* NOTE: DO NOT USE. Should only be used by {@link com.yahoo.document.serialization.SpanNodeReader}.
* @param from the from value to set
*/
public void setFrom(int from) {
if (from < 0) {
throw new IllegalArgumentException("From cannot be < 0. (Was " + from + ").");
}
this.from = from;
}
@Override
public final int getTo() {
return from + length;
}
@Override
public final int getLength() {
return length;
}
/**
* NOTE: DO NOT USE. Should only be used by {@link com.yahoo.document.serialization.SpanNodeReader}.
* @param length the length value to set
*/
public void setLength(int length) {
if (length < 0) {
throw new IllegalArgumentException("Length cannot be < 0. (Was " + length + ").");
}
this.length = length;
}
public String toString() {
return new StringBuilder("span [").append(from).append(',').append(getTo()).append('>').toString();
}
@Override
public final CharSequence getText(CharSequence text) {
return text.subSequence(from, getTo());
}
/**
* Always returns true.
*
* @return always true.
*/
@Override
public boolean isLeafNode() {
return true;
}
/**
* Returns a ListIterator that iterates over absolutely nothing.
*
* @return a ListIterator that iterates over absolutely nothing.
*/
@Override
public ListIterator childIterator() {
return new EmptyIterator();
}
/**
* Returns a ListIterator that iterates over absolutely nothing.
*
* @return a ListIterator that iterates over absolutely nothing.
*/
@Override
public ListIterator childIteratorRecursive() {
return childIterator();
}
private class EmptyIterator implements ListIterator {
@Override
public boolean hasNext() {
return false;
}
@Override
public SpanNode next() {
throw new NoSuchElementException("A Span has no children");
}
@Override
public boolean hasPrevious() {
return false;
}
@Override
public SpanNode previous() {
throw new NoSuchElementException("A Span has no children");
}
@Override
public int nextIndex() {
return 0;
}
@Override
public int previousIndex() {
return 0;
}
@Override
public void remove() {
throw new UnsupportedOperationException("A Span has no children");
}
@Override
public void set(SpanNode spanNode) {
throw new UnsupportedOperationException("A Span has no children");
}
@Override
public void add(SpanNode spanNode) {
throw new UnsupportedOperationException("A Span has no children");
}
}
}