/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o 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 General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/. */
package com.db4o.foundation;
import com.db4o.types.*;
/**
* Fast linked list for all usecases.
*
* @exclude
*/
public class Collection4<T> implements Sequence4<T>, Iterable4<T>, DeepClone, Unversioned {
@decaf.Public
private List4<T> _first;
@decaf.Public
private List4<T> _last;
@decaf.Public
private int _size;
@decaf.Public
private int _version;
public Collection4() {
}
/**
* For jdk11 compatibility only.
*/
@decaf.Ignore(except=decaf.Platform.JDK11)
public Collection4(int initialLength) {
}
public Collection4(T[] elements) {
addAll(elements);
}
public Collection4(Iterable4<T> other) {
addAll(other);
}
public Collection4(Iterator4<T> iterator) {
addAll(iterator);
}
public T singleElement() {
if (size() != 1) {
throw new IllegalStateException();
}
return _first._element;
}
/**
* Adds an element to the end of this collection.
*
* @param element
*/
public final boolean add(T element) {
doAdd(element);
changed();
return true;
}
public final void prepend(T element) {
doPrepend(element);
changed();
}
private void doPrepend(T element) {
if (_first == null) {
doAdd(element);
} else {
_first = new List4<T>(_first, element);
_size++;
}
}
private void doAdd(T element) {
if (_last == null) {
_first = new List4<T>(element);
_last = _first;
} else {
_last._next = new List4<T>(element);
_last = _last._next;
}
_size++;
}
public final void addAll(T[] elements) {
assertNotNull(elements);
for (int i = 0; i < elements.length; i++) {
add(elements[i]);
}
}
public final void addAll(Iterable4<T> other) {
assertNotNull(other);
addAll(other.iterator());
}
public final void addAll(Iterator4<T> iterator) {
assertNotNull(iterator);
while (iterator.moveNext()) {
add(iterator.current());
}
}
public final void clear() {
_first = null;
_last = null;
_size = 0;
changed();
}
public final boolean contains(T element) {
return find(element) != null;
}
public boolean containsAll(Iterable4<T> iter) {
return containsAll(iter.iterator());
}
public boolean containsAll(Iterator4<T> iter) {
assertNotNull(iter);
while (iter.moveNext()) {
if (!contains(iter.current())) {
return false;
}
}
return true;
}
/**
* tests if the object is in the Collection. == comparison.
*/
public final boolean containsByIdentity(T element) {
Iterator4<T> i = internalIterator();
while (i.moveNext()) {
T current = i.current();
if (current == element) {
return true;
}
}
return false;
}
private List4<T> find(T obj){
List4<T> current = _first;
while (current != null) {
if (current.holds(obj)) {
return current;
}
current = current._next;
}
return null;
}
private List4<T> findByIdentity(T obj){
List4<T> current = _first;
while (current != null) {
if (current._element == obj) {
return current;
}
current = current._next;
}
return null;
}
/**
* returns the first object found in the Collections that equals() the
* passed object
*/
public final T get(T element) {
List4<T> holder = find(element);
return holder == null ? null : holder._element;
}
public Object deepClone(Object newParent) {
Collection4 col = new Collection4();
Object element = null;
Iterator4<T> i = internalIterator();
while (i.moveNext()) {
element = i.current();
if (element instanceof DeepClone) {
col.add(((DeepClone) element).deepClone(newParent));
} else {
col.add(element);
}
}
return col;
}
/**
* makes sure the passed object is in the Collection. equals() comparison.
*/
public final T ensure(T element) {
List4<T> list = find(element);
if(list == null){
add(element);
return element;
}
return list._element;
}
/**
* Iterates through the collection in reversed insertion order which happens
* to be the fastest.
*
* @return
*/
public final Iterator4<T> iterator() {
return _first == null
? Iterators.EMPTY_ITERATOR
: new Collection4Iterator(this, _first);
}
public T get(int index) {
if(index < 0) {
throw new IllegalArgumentException();
}
List4<T> cur = _first;
while(index > 0 && cur != null) {
cur = cur._next;
index--;
}
if(cur == null) {
throw new IllegalArgumentException();
}
return cur._element;
}
/**
* Removes all the elements from this collection that are returned by
* iterable.
*
* @param iterable
*/
public void removeAll(Iterable4<T> iterable) {
removeAll(iterable.iterator());
}
/**
* Removes all the elements from this collection that are returned by
* iterator.
*/
public void removeAll(Iterator4<T> iterator) {
while (iterator.moveNext()) {
remove(iterator.current());
}
}
/**
* removes an object from the Collection equals() comparison returns the
* removed object or null, if none found
*/
public boolean remove(T a_object) {
List4<T> previous = null;
List4<T> current = _first;
while (current != null) {
if (current.holds(a_object)) {
_size--;
adjustOnRemoval(previous, current);
changed();
return true;
}
previous = current;
current = current._next;
}
return false;
}
public void replace(T oldObject, T newObject) {
List4<T> list = find(oldObject);
if(list != null){
list._element = newObject;
}
}
public void replaceByIdentity(T oldObject, T newObject) {
List4<T> list = findByIdentity(oldObject);
if(list != null){
list._element = newObject;
}
}
private void adjustOnRemoval(List4<T> previous, List4<T> removed) {
if (removed == _first) {
_first = removed._next;
} else {
previous._next = removed._next;
}
if (removed == _last) {
_last = previous;
}
}
public final int size() {
return _size;
}
public int indexOf(T obj){
int index = 0;
List4<T> current = _first;
while (current != null) {
if (current.holds(obj)) {
return index;
}
index++;
current = current._next;
}
return -1;
}
public final boolean isEmpty() {
return _size == 0;
}
/**
* This is a non reflection implementation for more speed. In contrast to
* the JDK behaviour, the passed array has to be initialized to the right
* length.
*/
public final T[] toArray(T[] array) {
int j = 0;
Iterator4<T> i = internalIterator();
while (i.moveNext()) {
array[j++] = i.current();
}
return array;
}
public final Object[] toArray() {
int j = 0;
Object[] array = new Object[size()];
Iterator4<T> i = internalIterator();
while (i.moveNext()) {
array[j++] = i.current();
}
return array;
}
public String toString() {
return Iterators.toString(internalIterator());
}
private void changed() {
++_version;
}
int version() {
return _version;
}
private void assertNotNull(Object element) {
if (element == null) {
throw new ArgumentNullException();
}
}
/**
* Leaner iterator for faster iteration (but unprotected against
* concurrent modifications).
*/
private Iterator4<T> internalIterator() {
return new Iterator4Impl(_first);
}
}