* @see RPCUtil#transfer(Object, Pair, Lookup, Lookup, int)
*/
protected static TransferObject transfer(Instance instance, Pair attributes, Lookup diffMap, Lookup identityMap, int nTF)
{
Metaclass metaclass = (attributes != null || (nTF & TF_LAZY) == 0) ? instance.getMetaclass() : instance.getLazyMetaclass();
Attribute lockingAttribute = (metaclass.getPersistenceMapping() == null) ? null : metaclass.getPersistenceMapping().getLockingAttribute();
TransferObject tobj = (TransferObject)identityMap.get(instance);
TransferObject orig = (diffMap == null) ? null : (TransferObject)diffMap.get(instance);
boolean bMerge;
if (tobj == null)
{
if ((nTF & (TF_READABLE | TF_ALL)) == TF_READABLE && !instance.isReadable())
{
return ((nTF & (TF_HIDDEN | TF_REF)) == (TF_HIDDEN | TF_REF)) ? new TransferObject(metaclass.getName(), 0) : null;
}
tobj = new TransferObject(metaclass.getName());
tobj.setOID(instance.getOID());
if ((nTF & TF_CACHE) == 0)
{
switch (instance.getState())
{
case Instance.NEW:
tobj.setEventName("create");
if ((nTF & TF_IDENTITY) == 0 || instance.getOID() == null)
{
nTF |= TF_STATE;
}
break;
case Instance.DIRTY:
tobj.setEventName("update");
break;
case Instance.DELETED:
tobj.setEventName("delete");
break;
}
}
if (instance.isLazy())
{
tobj.setVersion((short)-1);
}
identityMap.put(instance, tobj);
bMerge = false;
}
else
{
bMerge = true;
}
nTF |= TF_READABLE | TF_REF;
boolean bOld = (nTF & TF_OLD) != 0 || ((nTF & TF_DELETED) != 0 && instance.getState() == Instance.DELETED);
for (; attributes != null; attributes = attributes.getNext())
{
Object head = attributes.getHead();
String sName;
Pair pair;
if (head instanceof Pair)
{
Pair field = (Pair)head;
Symbol sym = (Symbol)field.getHead();
if (sym == Symbol.ATAT)
{
field = field.getNext();
if (metaclass.getMetadata().getMetaclass(
((Symbol)field.getHead()).getName()).isUpcast(metaclass))
{
transfer(instance, field.getNext(), diffMap, identityMap, nTF);
}
continue;
}
if (sym == Symbol.COLON)
{
sName = ((Symbol)field.getNext().getHead()).getName();
tobj.setValue(sName, transfer(instance.findAnnotation(sName), null, diffMap, identityMap, nTF));
continue;
}
sName = sym.getName();
pair = field.getNext();
}
else
{
sName = ((Symbol)head).getName();
if (bMerge && tobj.hasValue(sName))
{
continue;
}
pair = null;
}
Attribute attribute = metaclass.getAttribute(sName);
Object value = (attribute.isStatic()) ? metaclass.getValue(attribute.getOrdinal()) :
(bOld) ? instance.getOldValue(attribute.getOrdinal()) : instance.getValue(attribute.getOrdinal());
if (value instanceof Instance)
{
tobj.setValue(sName, transfer((Instance)value, pair, diffMap, identityMap, nTF));
}
else if (value instanceof InstanceList)
{
tobj.setValue(sName, transfer((InstanceList)value, pair, diffMap, identityMap, nTF));
}
else if (orig == null || attribute == lockingAttribute ||
!ObjUtil.equal(value, orig.findValue(sName, Undefined.VALUE)))
{
tobj.setValue(sName, value);
}
}
// For non-persisted objects, add all the attributes with read/write access
if (!bMerge && (nTF & TF_STATE) != 0 &&
(tobj.getOID() == null || instance.getState() == Instance.NEW))
{
if (lockingAttribute != null)
{
instance.getValue(lockingAttribute.getOrdinal());
}
for (int i = 0, n = metaclass.getInstanceAttributeCount(); i < n; ++i)
{
Attribute attribute = metaclass.getInstanceAttribute(i);
Object value = instance.getValueDirect(attribute.getOrdinal());
if (!(value instanceof Undefined) && !tobj.hasValue(attribute.getName()) &&
instance.isReadable(attribute) && instance.isUpdateable(attribute) &&
(!attribute.isCalculated() || instance.isOverridden(attribute.getOrdinal())))
{
if (value instanceof Instance)
{
tobj.setValue(attribute.getName(), transfer((Instance)value, null, diffMap, identityMap, nTF));
}
else if (value instanceof InstanceList)
{
tobj.setValue(attribute.getName(), transfer((InstanceList)value, null, diffMap, identityMap, nTF));
}
else if ((orig == null ||
attribute == lockingAttribute ||
!ObjUtil.equal(value, orig.findValue(attribute.getName(), Undefined.VALUE))) &&
((nTF & TF_SERIALIZABLE) == 0 ||
attribute.getType() != Primitive.ANY ||
TextMarshaller.isSerializable(value)))
{
tobj.setValue(attribute.getName(), value);
}
}
}
}