public ObjectMapper getMapper() {
return generateJavaBeanMapper();
}
private ObjectMapper generateJavaBeanMapper() {
final MappingDefinition mappingDefinition = context.getDefinitionsFactory().getDefinition(toMap);
if (mappingDefinition == null) {
throw new InvalidMappingException("no definition for: " + toMap.getFullyQualifiedName());
}
if ((toMap.isAbstract() || toMap.isInterface()) && !toMap.isEnum()) {
throw new RuntimeException("cannot map an abstract class or interface: " + toMap.getFullyQualifiedName());
}
return new ObjectMapper() {
@Override
public ClassStructureBuilder<?> getMarshaller(String marshallerClassName) {
ClassDefinitionStaticOption<?> staticOption = ClassBuilder.define(marshallerClassName).publicScope();
ClassStructureBuilder<?> classStructureBuilder = null;
BlockBuilder<?> initMethod = null;
if (!gwtTarget)
classStructureBuilder = staticOption.staticClass().implementsInterface(
parameterizedAs(GeneratedMarshaller.class, typeParametersOf(toMap))).body();
else {
classStructureBuilder = staticOption.implementsInterface(
parameterizedAs(GeneratedMarshaller.class, typeParametersOf(toMap))).body();
}
initMethod = classStructureBuilder.privateMethod(void.class, "lazyInit");
final MetaClass arrayType = toMap.asArrayOf(1);
classStructureBuilder.privateField("EMPTY_ARRAY", arrayType).initializesWith(Stmt.newArray(toMap, 0)).finish();
classStructureBuilder.publicMethod(arrayType, "getEmptyArray")
.append(Stmt.loadClassMember("EMPTY_ARRAY").returnValue())
.finish();
/**
*
* DEMARSHALL METHOD
*
*/
final BlockBuilder<?> builder =
classStructureBuilder.publicMethod(toMap, "demarshall",
Parameter.of(EJValue.class, "a0"), Parameter.of(MarshallingSession.class, "a1"));
builder.append(Stmt.loadVariable("this").invoke("lazyInit"));
builder.append(Stmt.declareVariable(EJObject.class).named("obj")
.initializeWith(loadVariable("a0").invoke("isObject")));
if (toMap.isEnum()) {
builder.append(Stmt.declareVariable(toMap).named("entity")
.initializeWith(demarshallEnum(loadVariable("obj"), loadVariable("a0"), toMap)));
}
else {
builder.append(If.cond(Bool.isNull(Refs.get("obj"))).append(Stmt.load(null).returnValue()).finish());
builder.append(Stmt.declareVariable(String.class).named("objId")
.initializeWith(loadVariable("obj")
.invoke("get", SerializationParts.OBJECT_ID)
.invoke("isString").invoke("stringValue")));
builder.append(
Stmt.if_(Bool.expr(loadVariable("a1").invoke("hasObject", loadVariable("objId"))))
.append(loadVariable("a1")
.invoke("getObject", toMap, loadVariable("objId")).returnValue()).finish());
final InstantiationMapping instantiationMapping = mappingDefinition.getInstantiationMapping();
/**
* Figure out how to construct this object.
*/
final Mapping[] cMappings = instantiationMapping.getMappings();
if (cMappings.length > 0) {
// use constructor mapping.
final List<String> memberKeys = new ArrayList<String>();
for (MemberMapping memberMapping : mappingDefinition.getMemberMappings()) {
memberKeys.add(memberMapping.getKey());
}
final Statement[] constructorParameters = new Statement[cMappings.length];
for (final Mapping mapping : instantiationMapping.getMappingsInKeyOrder(memberKeys)) {
int parmIndex = instantiationMapping.getIndex(mapping.getKey());
final MetaClass type = mapping.getType().asBoxed();
BlockBuilder<?> lazyInitMethod = (needsLazyInit(type)) ? initMethod : null;
if (type.isArray()) {
MetaClass toMap = type;
while (toMap.isArray()) {
toMap = toMap.getComponentType();
}
if (context.canMarshal(toMap.getFullyQualifiedName())) {
if (gwtTarget) {
BuildMetaClass arrayMarshaller = MarshallerGeneratorFactory.createArrayMarshallerClass(type);
if (!containsInnerClass(classStructureBuilder, arrayMarshaller)) {
classStructureBuilder.declaresInnerClass(new InnerClass(arrayMarshaller));
}
Statement deferred = context.getArrayMarshallerCallback().deferred(type, arrayMarshaller);
MarshallingGenUtil.ensureMarshallerFieldCreated(classStructureBuilder, toMap, type, lazyInitMethod,
deferred);
constructorParameters[parmIndex] =
Stmt.loadVariable(MarshallingGenUtil.getVarName(type)).invoke("demarshall",
extractJSONObjectProperty(mapping.getKey(), EJObject.class), Stmt.loadVariable("a1"));
}
else {
MarshallingGenUtil.ensureMarshallerFieldCreated(classStructureBuilder, toMap, type, lazyInitMethod);
constructorParameters[parmIndex] = context.getArrayMarshallerCallback()
.demarshall(type, extractJSONObjectProperty(mapping.getKey(), EJObject.class));
}
}
else {
throw new MarshallingException("Encountered non-marshallable type " + toMap +
" while building a marshaller for " + mappingDefinition.getMappingClass());
}
}
else {
MarshallingGenUtil.ensureMarshallerFieldCreated(classStructureBuilder, toMap, type, lazyInitMethod);
if (context.canMarshal(type.getFullyQualifiedName())) {
Statement s = maybeAddAssumedTypes(builder,
"c" + parmIndex,
mapping, fieldDemarshall(mapping, EJObject.class));
constructorParameters[parmIndex] = s;
}
else {
throw new MarshallingException("Encountered non-marshallable type " + type +
" while building a marshaller for " + mappingDefinition.getMappingClass());
}
}
}
if (instantiationMapping instanceof ConstructorMapping) {
final ConstructorMapping mapping = (ConstructorMapping) instantiationMapping;
final MetaConstructor constructor = mapping.getMember();
if (constructor.isPublic()) {
builder
.append(Stmt.declareVariable(toMap).named("entity")
.initializeWith(
Stmt.newObject(toMap, (Object[]) constructorParameters)));
}
else {
PrivateAccessUtil.addPrivateAccessStubs(gwtTarget ? "jsni" : "reflection", classStructureBuilder,
constructor);
builder.append(Stmt.declareVariable(toMap).named("entity")
.initializeWith(
Stmt.invokeStatic(
classStructureBuilder.getClassDefinition(),
PrivateAccessUtil.getPrivateMethodName(constructor),
(Object[]) constructorParameters)));
}
}
else if (instantiationMapping instanceof FactoryMapping) {
builder.append(Stmt.declareVariable(toMap).named("entity")
.initializeWith(
Stmt.invokeStatic(toMap, ((FactoryMapping) instantiationMapping).getMember().getName(),
(Object[]) constructorParameters)));
}
}
else {
// use default constructor
builder._(
Stmt.declareVariable(toMap).named("entity").initializeWith(
Stmt.nestedCall(Stmt.newObject(toMap))));
}
builder._(loadVariable("a1").invoke("recordObject",
loadVariable("objId"), loadVariable("entity")));
}
/**
*
* FIELD BINDINGS
*
*/
for (final MemberMapping memberMapping : mappingDefinition.getMemberMappings()) {
if (!memberMapping.canWrite())
continue;
if (memberMapping.getTargetType().isConcrete() && !context.isRendered(memberMapping.getTargetType())) {
context.getMarshallerGeneratorFactory().addMarshaller(memberMapping.getTargetType());
}