/* 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.internal.collections;
import java.util.*;
import com.db4o.foundation.*;
import com.db4o.internal.*;
import com.db4o.internal.activation.*;
import com.db4o.internal.btree.*;
import com.db4o.marshall.*;
/**
* @exclude
* @sharpen.partial
*/
@decaf.Ignore(decaf.Platform.JDK11)
public class BigSet<E> implements Set<E>, BigSetPersistence {
private BTree _bTree;
private Transaction _transaction;
public BigSet(LocalObjectContainer db) {
if(db == null){
return;
}
_transaction = db.transaction();
_bTree = bTreeManager().newBTree();
}
private ObjectContainerBase container(){
return transaction().container();
}
public boolean add(E obj) {
synchronized(lock()){
final int id = getID(obj);
if(id == 0){
add(store(obj));
return true;
}
if (contains(id)) {
return false;
}
add(id);
return true;
}
}
private int store(E obj) {
return container().store(_transaction, obj, container().updateDepthProvider().unspecified(NullModifiedObjectQuery.INSTANCE));
}
private void add(int id) {
bTreeForUpdate().add(_transaction, new Integer(id));
}
private int getID(Object obj) {
return (int) container().getID(obj);
}
/**
* @sharpen.ignore
*/
public boolean addAll(Collection<? extends E> collection) {
final Iterable<? extends E> iterable = collection;
return addAll(iterable);
}
public boolean addAll(final Iterable<? extends E> iterable) {
boolean result = false;
for (E element : iterable) {
if (add(element)) {
result = true;
}
}
return result;
}
public void clear() {
synchronized(lock()){
bTreeForUpdate().clear(transaction());
}
}
public boolean contains(Object obj) {
int id = getID(obj);
if(id == 0){
return false;
}
return contains(id);
}
private boolean contains(int id) {
synchronized(lock()){
BTreeRange range = bTree().searchRange(transaction(), new Integer(id));
return ! range.isEmpty();
}
}
/**
* @sharpen.ignore
*/
public boolean containsAll(Collection<?> collection) {
final Iterable<?> iterable = collection;
for (Object element : iterable) {
if(! contains(element)){
return false;
}
}
return true;
}
/**
* @sharpen.property
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* @sharpen.ignore
*/
public Iterator<E> iterator() {
return new Iterator4JdkIterator(elements());
}
/**
* @sharpen.ignore
*/
private Iterator4 elements() {
return new MappingIterator(bTreeIterator()) {
protected Object map(Object current) {
int id = ((Integer)current).intValue();
return element(id);
}
};
}
private Iterator4 bTreeIterator() {
return new SynchronizedIterator4(bTree().iterator(transaction()), lock());
}
public boolean remove(Object obj) {
synchronized(lock()){
if(!contains(obj)){
return false;
}
int id = getID(obj);
bTreeForUpdate().remove(transaction(), new Integer(id));
return true;
}
}
/**
* @sharpen.ignore
*/
public boolean removeAll(Collection<?> collection) {
boolean res = false;
for (Object element : collection) {
if(remove(element)){
res = true;
}
}
return res;
}
/**
* @sharpen.ignore
*/
public boolean retainAll(Collection<?> c) {
throw new UnsupportedOperationException();
}
public int size() {
synchronized(lock()){
return bTree().size(transaction());
}
}
public Object[] toArray() {
throw new UnsupportedOperationException();
}
public <T> T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
/* (non-Javadoc)
* @see com.db4o.internal.collections.BigSetPersistence#write(com.db4o.marshall.WriteContext)
*/
public void write(WriteContext context) {
int id = bTree().getID();
if(id == 0){
bTree().write(systemTransaction());
}
context.writeInt(bTree().getID());
}
/* (non-Javadoc)
* @see com.db4o.internal.collections.BigSetPersistence#read(com.db4o.marshall.ReadContext)
*/
public void read(ReadContext context) {
int id = context.readInt();
if(_bTree != null){
assertCurrentBTreeId(id);
return;
}
_transaction = context.transaction();
_bTree = bTreeManager().produceBTree(id);
}
private BigSetBTreeManager bTreeManager() {
return new BigSetBTreeManager(_transaction);
}
private void assertCurrentBTreeId(int id) {
if (id != _bTree.getID()) {
throw new IllegalStateException();
}
}
private Transaction transaction(){
return _transaction;
}
private Transaction systemTransaction(){
return container().systemTransaction();
}
/* (non-Javadoc)
* @see com.db4o.internal.collections.BigSetPersistence#invalidate()
*/
public void invalidate() {
_bTree = null;
}
private BTree bTree() {
if(_bTree == null){
throw new IllegalStateException();
}
return _bTree;
}
private BTree bTreeForUpdate() {
final BTree bTree = bTree();
bTreeManager().ensureIsManaged(bTree);
return bTree;
}
private Object element(int id) {
Object obj = container().getByID(transaction(), id);
container().activate(obj);
return obj;
}
private Object lock(){
return container().lock();
}
}