/*******************************************************************************
* Copyright (c) 2009 MATERNA Information & Communications. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html. For further
* project-related information visit http://www.ws4d.org. The most recent
* version of the JMEDS framework can be obtained from
* http://sourceforge.net/projects/ws4d-javame.
******************************************************************************/
package org.ws4d.java.structures;
import java.util.NoSuchElementException;
import org.ws4d.java.util.WS4DIllegalStateException;
public abstract class List extends DataStructure {
private static final String CLASS_SHORT_NAME = "List";
protected transient int changes = 0;
transient int size = 0;
// -----------------------------------------------------
public String getClassShortName() {
return CLASS_SHORT_NAME;
}
public void add(int index, Object obj) {
throw new UnsupportedOperationException();
}
public boolean add(Object obj) {
add(size(), obj);
return true;
}
/*
* (non-Javadoc)
* @see
* org.ws4d.java.structures.DataStructure#addAll(org.ws4d.java.structures
* .DataStructure)
*/
public boolean addAll(DataStructure data) {
boolean changed = false;
for (Iterator it = data.iterator(); it.hasNext();) {
Object obj = it.next();
add(obj);
changed = true;
}
return changed;
}
public boolean addAll(int index, DataStructure data) {
boolean changed = false;
for (Iterator it = data.iterator(); it.hasNext();) {
add(index++, it.next());
changed = true;
}
return changed;
}
public abstract Object get(int index);
public int indexOf(Object o) {
if (o == null) {
for (ListIterator it = listIterator(); it.hasNext();) {
if (it.next() == null) {
return it.indexOfNext() - 1;
}
}
} else {
for (ListIterator it = listIterator(); it.hasNext();) {
if (o.equals(it.next())) {
return it.indexOfNext() - 1;
}
}
}
return -1;
}
public Iterator iterator() {
return new IteratorImpl(0);
}
public int lastIndexOf(Object object) {
if (object == null) {
for (ListIterator it = listIterator(size()); it.hasPrevious();) {
if (it.previous() == null) {
return it.indexOfNext();
}
}
} else {
for (ListIterator it = listIterator(size()); it.hasPrevious();) {
if (object.equals(it.previous())) {
return it.indexOfNext();
}
}
}
return -1;
}
public ListIterator listIterator() {
return listIterator(0);
}
public ListIterator listIterator(int index) {
return new ListIteratorImpl(index);
}
public Object remove(int index) {
throw new UnsupportedOperationException();
}
public Object set(int index, Object obj) {
throw new UnsupportedOperationException();
}
public int size() {
return size;
}
public List subList(int fromIndex, int toIndex) {
return new SubList(fromIndex, toIndex);
}
// ------------------------- OVERRIDDEN OBJECT METHODS
// ------------------------------------
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if ((obj == null) || !(obj instanceof List)) {
return false;
}
List other = (List) obj;
if (other.size() != size()) {
return false;
}
ListIterator e1 = listIterator();
ListIterator e2 = other.listIterator();
while (e1.hasNext() && e2.hasNext()) {
Object o1 = e1.next();
Object o2 = e2.next();
if (!(o1 == null ? o2 == null : o1.equals(o2))) {
return false;
}
}
return !(e1.hasNext() || e2.hasNext());
}
// ========================== INNER CLASS ==============================
private class IteratorImpl implements Iterator {
/** Index of the next element to be returned by next */
int nextIndex;
int currentIndex = -1;
int changesIt = changes;
IteratorImpl(int nextIndex) {
this.nextIndex = nextIndex;
changesIt = changes;
}
protected final void checkChanges() {
if (changes != changesIt) {
throw new ConcurrentChangeException();
}
}
public boolean hasNext() {
return (nextIndex < size());
}
public Object next() {
checkChanges();
try {
final Object obj = get(nextIndex);
currentIndex = nextIndex++;
return obj;
} catch (IndexOutOfBoundsException e) {
checkChanges();
throw new NoSuchElementException();
}
}
public void remove() {
checkChanges();
if (currentIndex == -1) {
throw new WS4DIllegalStateException();
}
List.this.remove(currentIndex);
if (currentIndex < nextIndex) {
nextIndex--;
}
currentIndex = -1;
changesIt = changes;
}
}
private class ListIteratorImpl extends IteratorImpl implements ListIterator {
ListIteratorImpl(final int nextIndex) {
super(nextIndex);
}
public void add(Object obj) {
checkChanges();
List.this.add(nextIndex++, obj);
currentIndex = -1;
changesIt = changes;
}
public boolean hasPrevious() {
return (nextIndex != 0);
}
public int indexOfNext() {
return nextIndex;
}
public Object previous() {
checkChanges();
try {
int prevIndex = nextIndex - 1;
Object obj = get(prevIndex);
currentIndex = nextIndex = prevIndex;
return obj;
} catch (IndexOutOfBoundsException e) {
checkChanges();
throw new NoSuchElementException();
}
}
public void set(Object obj) {
checkChanges();
List.this.set(currentIndex, obj);
}
}
private final class SubList extends List {
// int fromIndex;
int offset;
int size;
SubList(final int fromIndex, final int toIndex) {
// this.fromIndex = fromIndex;
this.offset = fromIndex;
this.size = toIndex - fromIndex;
}
public void add(int index, Object obj) {
List.this.add(index + offset, obj);
size++;
}
public boolean addAll(DataStructure data) {
return addAll(size, data);
}
public boolean addAll(int index, DataStructure data) {
if (index < 0 || index > size) throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
int dataSize = data.size();
if (dataSize == 0) {
return false;
}
final boolean result = List.this.addAll(offset + index, data);
size += dataSize;
return result;
}
public Object get(int index) {
return List.this.get(index + offset);
}
public Iterator iterator() {
return new IteratorImpl(0);
}
public ListIterator listIterator(final int index) {
return new ListIteratorImpl(index) {
public int indexOfNext() {
return super.indexOfNext() - offset;
}
};
}
public Object remove(int index) {
final Object obj = List.this.remove(index + offset);
size--;
return obj;
}
public Object set(int index, Object obj) {
return List.this.set(index + offset, obj);
}
public int size() {
return size;
}
public List subList(int fromIndex, int toIndex) {
return new SubList(fromIndex + offset, toIndex + offset);
}
}
}