@SuppressWarnings({"ConstantConditions", "unchecked"})
@Override
public Object demarshall(final EJValue o, final MarshallingSession ctx) {
try {
if (o.isObject() != null) {
final EJObject oMap = o.isObject();
final Object newInstance;
if (MarshallUtil.isEncodedObject(oMap)) {
if (MarshallUtil.isEncodedNumeric(oMap)) {
return NumbersUtils.getEncodedNumber(oMap);
}
final String objID = oMap.get(SerializationParts.OBJECT_ID).isString().stringValue();
if (ctx.hasObject(objID)) {
newInstance = ctx.getObject(Object.class, objID);
/**
* If this only contains 2 fields, it is only a graph reference.
*/
if (oMap.size() == 2) {
return newInstance;
}
}
else {
/**
* Check to see if this object is instantiate only... meaning it has no fields to marshall.
*/
if (oMap.containsKey(SerializationParts.INSTANTIATE_ONLY)) {
newInstance = getTypeHandled().newInstance();
ctx.recordObject(objID, newInstance);
return newInstance;
}
final InstantiationMapping cMapping = definition.getInstantiationMapping();
final Object[] parms = new Object[cMapping.getMappings().length];
final Class[] targetTypes = cMapping.getSignature();
int i = 0;
for (final Mapping mapping : cMapping.getMappings()) {
final Marshaller<Object> marshaller = ctx.getMarshallerInstance(mapping.getType().getFullyQualifiedName());
//noinspection unchecked
parms[i] = DataConversion.convert(
marshaller.demarshall(oMap.get(mapping.getKey()), ctx), targetTypes[i++]);
}
if (cMapping instanceof ConstructorMapping) {
final Constructor constructor = ((ConstructorMapping) cMapping).getMember().asConstructor();
constructor.setAccessible(true);
newInstance = constructor.newInstance(parms);
}
else {
newInstance = ((FactoryMapping) cMapping).getMember().asMethod().invoke(null, parms);
}
ctx.recordObject(objID, newInstance);
}
for (final MemberMapping mapping : definition.getWritableMemberMappings()) {
final EJValue o1 = oMap.get(mapping.getKey());
if (!o1.isNull()) {
final Marshaller<Object> marshaller
= ctx.getMarshallerInstance(mapping.getType().getFullyQualifiedName());
if (mapping.getBindingMember() instanceof MetaField) {
final MetaField f = (MetaField) mapping.getBindingMember();
setProperty(newInstance, f.asField(),
marshaller.demarshall(o1, ctx));
}
else {
final Method m = ((MetaMethod) mapping.getBindingMember()).asMethod();
m.invoke(newInstance, DataConversion.convert(
marshaller.demarshall(o1, ctx),
m.getParameterTypes()[0]));
}
}
}
return newInstance;
}
else if (oMap.containsKey(SerializationParts.ENUM_STRING_VALUE)) {
return Enum.valueOf(getClassReference(oMap),
oMap.get(SerializationParts.ENUM_STRING_VALUE).isString().stringValue());
}
else {
throw new RuntimeException("bad payload");
}
}