/*
* Copyright (C) 2003-2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.chromattic.common.collection.delta;
import java.util.Iterator;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
abstract class Segment<E> {
abstract Segment<E> getNext();
abstract void setNext(Segment<E> next);
abstract Segment<E> getPrevious();
abstract void setPrevious(Segment<E> previous);
protected abstract E localGet(int index);
protected abstract int localSize();
protected abstract boolean localCanAdd(int index);
protected abstract void localAdd(int index, E element);
protected abstract E localRemove(int index);
protected abstract Iterator<E> localIterator();
public final E get(int index) {
Segment<E> segment = this;
while (true) {
if (index < 0) {
Segment<E> previous = segment.getPrevious();
if (previous == null) {
throw new IndexOutOfBoundsException();
} else {
index += previous.localSize();
segment = previous;
}
} else {
int localSize = segment.localSize();
if (index >= localSize) {
Segment<E> next = segment.getNext();
if (next == null) {
throw new IndexOutOfBoundsException();
} else {
index -= localSize;
segment = next;
}
} else {
break;
}
}
}
return segment.localGet(index);
}
public final void add(int index, E e) {
Segment<E> segment = this;
while (true) {
if (index < 0) {
throw new IndexOutOfBoundsException();
} else {
if (segment.localCanAdd(index)) {
segment.localAdd(index, e);
break;
} else {
Segment<E> next = segment.getNext();
if (next == null) {
throw new IndexOutOfBoundsException();
} else {
index -= segment.localSize();
segment = next;
}
}
}
}
}
public final E remove(int index) {
Segment<E> segment = this;
while (true) {
if (index < 0) {
throw new IndexOutOfBoundsException();
} else {
int localSize = segment.localSize();
if (index < localSize) {
return segment.localRemove(index);
} else {
Segment<E> next = segment.getNext();
if (next == null) {
throw new IndexOutOfBoundsException();
} else {
index -= localSize;
segment = next;
}
}
}
}
}
public final int size() {
int size = 0;
for (Segment<E> segment = this;segment != null;segment = segment.getNext()) {
size += segment.localSize();
}
return size;
}
public final Iterator<E> iterator() {
return new IteratorImpl<E>(this);
}
public final int complexity() {
int complexity = 0;
for (Segment<E> segment = this;segment != null;segment = segment.getNext()) {
complexity ++;
}
return complexity;
}
// *********************
final boolean hasNext() {
return getNext() != null;
}
final Segment<E> addAfter(Segment<E> segment) {
Segment<E> next = getNext();
if (next != null) {
segment.setNext(next);
next.setPrevious(segment);
}
//
segment.setPrevious(this);
setNext(segment);
//
return segment;
}
// *********************
protected abstract void format(StringBuilder builder);
public String format() {
StringBuilder builder = new StringBuilder("[");
int count = 0;
for (Segment<E> segment = this;segment != null;segment = segment.getNext()) {
if (count > 0) {
builder.append(",");
}
segment.format(builder);
count ++;
}
builder.append("]");
return builder.toString();
}
}