/* 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.btree;
/**
* @exclude
*/
import com.db4o.foundation.*;
import com.db4o.internal.*;
public abstract class BTreeUpdate extends BTreePatch {
protected BTreeUpdate _next;
public BTreeUpdate(Transaction transaction, Object obj) {
super(transaction, obj);
}
protected boolean hasNext() {
return _next != null;
}
public BTreePatch forTransaction(Transaction trans) {
if(_transaction == trans){
return this;
}
if(_next == null){
return null;
}
return _next.forTransaction(trans);
}
public BTreeUpdate removeFor(Transaction trans) {
if (_transaction == trans) {
return _next;
}
if (_next != null) {
_next = _next.removeFor(trans);
}
return this;
}
public void append(BTreeUpdate patch) {
if(_transaction == patch._transaction){
throw new IllegalArgumentException();
}
if(!hasNext()){
_next = patch;
}else{
_next.append(patch);
}
}
protected void applyKeyChange(Object obj) {
_object = obj;
if (hasNext()) {
_next.applyKeyChange(obj);
}
}
protected abstract void committed(BTree btree);
public Object commit(Transaction trans, BTree btree, BTreeNode node) {
final BTreeUpdate patch = (BTreeUpdate) forTransaction(trans);
if (patch instanceof BTreeCancelledRemoval) {
Object obj = patch.getCommittedObject();
applyKeyChange(obj);
} else if (patch instanceof BTreeRemove){
removedBy(trans, btree, node);
patch.committed(btree);
return No4.INSTANCE;
}
return internalCommit(trans, btree);
}
protected final Object internalCommit(Transaction trans, BTree btree) {
if(_transaction == trans){
committed(btree);
if (hasNext()){
return _next;
}
return getCommittedObject();
}
if(hasNext()){
setNextIfPatch(_next.internalCommit(trans, btree));
}
return this;
}
private void setNextIfPatch(Object newNext) {
if(newNext instanceof BTreeUpdate){
_next = (BTreeUpdate)newNext;
} else {
_next = null;
}
}
protected abstract Object getCommittedObject();
public Object rollback(Transaction trans, BTree btree) {
if(_transaction == trans){
if(hasNext()){
return _next;
}
return getObject();
}
if(hasNext()){
setNextIfPatch(_next.rollback(trans, btree));
}
return this;
}
public Object key(Transaction trans) {
BTreePatch patch = forTransaction(trans);
if (patch == null) {
return getObject();
}
if (patch.isRemove()) {
return No4.INSTANCE;
}
return patch.getObject();
}
public BTreeUpdate replacePatch(BTreePatch patch, BTreeUpdate update) {
if(patch == this){
update._next = _next;
return update;
}
if(_next == null){
throw new IllegalStateException();
}
_next = _next.replacePatch(patch, update);
return this;
}
public void removedBy(Transaction trans, BTree btree, BTreeNode node) {
if(trans != _transaction){
adjustSizeOnRemovalByOtherTransaction(btree, node);
}
if(hasNext()){
_next.removedBy(trans, btree, node);
}
}
protected abstract void adjustSizeOnRemovalByOtherTransaction(BTree btree, BTreeNode node);
public int sizeDiff(Transaction trans) {
BTreeUpdate patchForTransaction = (BTreeUpdate) forTransaction(trans);
if(patchForTransaction == null){
return 1;
}
return patchForTransaction.sizeDiff();
}
protected abstract int sizeDiff();
}