org.datanucleus.store.db4o.fieldmanager.AssignStateManagerFieldManager Maven / Gradle / Ivy
/**********************************************************************
Copyright (c) 2006 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributors:
2007 Xuan Baldauf - Major improvements in the way DB4O is accessed. See CORE-3272
2007 Andy Jefferson - remove needless "if (true)" nonsense, and PersistenceCapable refs
...
**********************************************************************/
package org.datanucleus.store.db4o.fieldmanager;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.datanucleus.api.ApiAdapter;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.state.ObjectProviderFactory;
import org.datanucleus.store.ExecutionContext;
import org.datanucleus.store.ObjectProvider;
import org.datanucleus.store.db4o.DB4OStoreManager;
import org.datanucleus.store.db4o.exceptions.ObjectNotActiveException;
import org.datanucleus.store.fieldmanager.AbstractFieldManager;
import com.db4o.ObjectContainer;
/**
* Field manager that starts from the source object and for all fields will assign StateManagers to all
* related PersistenceCapable objects found (unless already managed), assuming they are in PersistenceClean state.
*
* @version $Revision: 1.1 $
**/
public class AssignStateManagerFieldManager extends AbstractFieldManager
{
/** DB4O ObjectContainer. */
private final ObjectContainer cont;
/** StateManager for the owning object whose fields are being fetched. */
private final ObjectProvider sm;
/**
* Constructor.
* @param cont ObjectContainer
* @param sm The state manager for the object.
**/
public AssignStateManagerFieldManager(ObjectContainer cont, ObjectProvider sm)
{
this.cont = cont;
this.sm = sm;
}
/**
* Utility method to process the passed persistable object.
* @param fieldNumber Absolute field number
* @param pc The persistable object
*/
protected void processPersistable(int fieldNumber, Object pc)
{
DB4OStoreManager mgr = (DB4OStoreManager)sm.getExecutionContext().getStoreManager();
// Find the id for this object stored in this field
Object id = null;
try
{
id = mgr.getObjectIdForObject(sm.getExecutionContext(), pc);
}
catch (ObjectNotActiveException onae)
{
// Object stored in this field is not active, so mark it as not loaded
sm.unloadField(sm.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber).getName());
}
if (id == null)
{
// Object is either not activated or not persistent so ignore
return;
}
// PC has no StateManager so it was created by DB4O
/*
* The PC may be active (because we may fetch too much because we try to cater for second-class objects),
* but without JPOX StateManager. In this case, we could either regard it as persistent-clean or we could
* make it hollow and deactivate it again. But this PC may contain second-class objects, which (because the
* fetching depth is not exact) may not be loaded. Thus, we make it hollow and deactivate it again. FIXME:
* In the long run, we finetune loading of second-class objects (by setting
* Configuration.objectClass().objectField().cascadeOnActivate() accordingly. If this finetuning is in
* place, then there is no need to deactivate objects preventively.
*/
ExecutionContext ec = sm.getExecutionContext();
if (cont.ext().isActive(pc))
{
// Add StateManager and mark as deactivated for now - why ?
ObjectProvider newStateManager = ObjectProviderFactory.newForHollowPreConstructed(ec, id, pc);
mgr.notifyObjectIsOutdated(newStateManager);
}
}
/**
* Method to store an object field.
* @param fieldNumber Number of the field (absolute)
* @param value Value of the field
*/
public void storeObjectField(int fieldNumber, Object value)
{
if (value != null)
{
ExecutionContext ec = sm.getExecutionContext();
ApiAdapter api = ec.getApiAdapter();
AbstractMemberMetaData fmd = sm.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
if (api.isPersistable(value))
{
// PC field
ObjectProvider valueSM = ec.findObjectProvider(value);
if (valueSM == null)
{
// Field is not yet managed
processPersistable(fieldNumber, value);
}
}
else if (value instanceof Collection)
{
// Collection that may contain PCs
if (fmd.hasCollection() && fmd.getCollection().elementIsPersistent())
{
Collection coll = (Collection)value;
Iterator iter = coll.iterator();
while (iter.hasNext())
{
Object element = iter.next();
if (api.isPersistable(element))
{
ObjectProvider elementSM = ec.findObjectProvider(element);
if (elementSM == null)
{
// Collection Element is not yet managed
processPersistable(fieldNumber, element);
}
}
}
}
}
else if (value instanceof Map)
{
// Map that may contain PCs in key or value
if (fmd.hasMap())
{
if (fmd.getMap().keyIsPersistent())
{
Map map = (Map)value;
Set keys = map.keySet();
Iterator iter = keys.iterator();
while (iter.hasNext())
{
Object mapKey = iter.next();
if (api.isPersistable(mapKey))
{
ObjectProvider keySM = ec.findObjectProvider(mapKey);
if (keySM == null)
{
// Map Key is not yet managed
processPersistable(fieldNumber, mapKey);
}
}
}
}
if (fmd.getMap().valueIsPersistent())
{
Map map = (Map)value;
Collection values = map.values();
Iterator iter = values.iterator();
while (iter.hasNext())
{
Object mapValue = iter.next();
if (api.isPersistable(mapValue))
{
ObjectProvider valueSM = ec.findObjectProvider(mapValue);
if (valueSM == null)
{
// Map Value is not yet managed
processPersistable(fieldNumber, mapValue);
}
}
}
}
}
}
else if (value instanceof Object[])
{
// Array that may contain PCs
if (fmd.hasArray() && fmd.getArray().elementIsPersistent())
{
for (int i=0;i