/* 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;
import com.db4o.foundation.*;
import com.db4o.internal.delete.*;
import com.db4o.internal.marshall.*;
import com.db4o.internal.query.processor.*;
import com.db4o.internal.replication.*;
import com.db4o.marshall.*;
import com.db4o.reflect.*;
import com.db4o.typehandlers.*;
/**
* TODO: refactor for symmetric inheritance - don't inherit from YapField and override,
* instead extract an abstract superclass from YapField and let both YapField and this class implement
*
* @exclude
*/
public abstract class VirtualFieldMetadata extends FieldMetadata {
private static final Object ANY_OBJECT = new Object();
private ReflectClass _classReflector;
private BuiltinTypeHandler _handler;
VirtualFieldMetadata(int fieldTypeID, BuiltinTypeHandler handler) {
super(fieldTypeID);
_handler = handler;
}
@Override
public TypeHandler4 getHandler() {
return _handler;
}
public abstract void addFieldIndex(ObjectIdContextImpl context) throws FieldIndexException ;
public boolean alive() {
return true;
}
boolean canAddToQuery(String fieldName){
return fieldName.equals(getName());
}
@Override
public boolean canBeDisabled() {
return false;
}
public boolean canUseNullBitmap(){
return false;
}
public ReflectClass classReflector(Reflector reflector){
if (_classReflector == null) {
_classReflector = ((BuiltinTypeHandler)getHandler()).classReflector();
}
return _classReflector;
}
void collectConstraints(Transaction a_trans, QConObject a_parent,
Object a_template, Visitor4 a_visitor) {
// QBE constraint collection call
// There isn't anything useful to do here, since virtual fields
// are not on the actual object.
}
public void deactivate(ActivationContext context) {
// do nothing
}
public abstract void delete(DeleteContextImpl context, boolean isUpdate);
public Object getOrCreate(Transaction a_trans, Object a_OnObject) {
// This is the first part of marshalling
// Virtual fields do it all in #marshall(), the object is never used.
// Returning any object here prevents triggering null handling.
return ANY_OBJECT;
}
public boolean needsArrayAndPrimitiveInfo(){
return false;
}
public void activate(UnmarshallingContext context) {
context.objectReference().produceVirtualAttributes();
instantiate1(context);
}
abstract void instantiate1(ObjectReferenceContext context);
public void loadFieldTypeById(){
// do nothing
}
public void marshall(MarshallingContext context, Object obj){
marshall(context.transaction(), context.reference(), context, context.isNew());
}
private final void marshall(
Transaction trans,
ObjectReference ref,
WriteBuffer buffer,
boolean isNew) {
if(! trans.supportsVirtualFields()){
marshallIgnore(buffer);
return;
}
ObjectContainerBase stream = trans.container();
HandlerRegistry handlers = stream._handlers;
boolean migrating = false;
if (stream._replicationCallState == Const4.NEW) {
Db4oReplicationReferenceProvider provider = handlers._replicationReferenceProvider;
Object parentObject = ref.getObject();
Db4oReplicationReference replicationReference = provider.referenceFor(parentObject);
if(replicationReference != null){
migrating = true;
VirtualAttributes va = ref.produceVirtualAttributes();
va.i_version = replicationReference.version();
va.i_uuid = replicationReference.longPart();
va.i_database = replicationReference.signaturePart();
}
}
if (ref.virtualAttributes() == null) {
ref.produceVirtualAttributes();
migrating = false;
}
marshall(trans, ref, buffer, migrating, isNew);
}
abstract void marshall(Transaction trans, ObjectReference ref, WriteBuffer buffer, boolean migrating, boolean isNew);
abstract void marshallIgnore(WriteBuffer writer);
public void readVirtualAttribute(ObjectReferenceContext context) {
if(! context.transaction().supportsVirtualFields()){
incrementOffset(context, context);
return;
}
instantiate1(context);
}
@Override
public boolean isVirtual() {
return true;
}
protected Object indexEntryFor(Object indexEntry) {
return indexEntry;
}
protected Indexable4 indexHandler(ObjectContainerBase stream) {
return (Indexable4)getHandler();
}
}