// build the unmarshal method for item; this just generates code
// to unmarshal attributes and content, first creating an
// instance of the class if one was not passed in, then
// returning the unmarshalled instance as the value of the call
String type = m_class.getClassName();
ContextMethodBuilder mb = new ContextMethodBuilder(UNMARSHAL_METHODNAME,
Type.OBJECT, UNMARSHAL_METHOD_ARGS, cf,
Constants.ACC_PUBLIC|Constants.ACC_FINAL, 1, type,
2, UNMARSHALCONTEXT_INTERFACE);
mb.addException(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS);
// first part of generated code just checks if an object has
// been supplied; if it has, this can just go direct to
// unmarshalling
mb.loadObject();
BranchWrapper ifnnull = mb.appendIFNONNULL(this);
// check for extension mapping handling required
if (m_extensions != null) {
// generate name comparison unless an abstract mapping
BranchWrapper ifthis = null;
if (hasname) {
// test if at defined element name
mb.addException(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS);
mb.loadContext();
m_name.genPushUriPair(mb);
mb.appendCallInterface(UNMARSHAL_ISATMETHOD,
UNMARSHAL_ISATSIGNATURE);
ifthis = mb.appendIFNE(this);
}
// build code to check each extension mapping in turn,
// keeping an instance of the unmarshaller for the matching
// extension
BranchWrapper[] iffounds =
new BranchWrapper[m_extensions.size()];
for (int i = 0; i < iffounds.length; i++) {
IMapping map = (IMapping)m_extensions.get(i);
mb.loadContext();
mb.appendLoadConstant(map.getMappingName());
mb.appendCallInterface(GETUNMARSHALLER_METHOD,
GETUNMARSHALLER_SIGNATURE);
mb.appendDUP();
mb.loadContext();
mb.appendCallInterface(UNMARSHALLERPRESENT_METHOD,
UNMARSHALLERPRESENT_SIGNATURE);
iffounds[i] = mb.appendIFNE(this);
mb.appendPOP();
}
// generate code to throw exception if no matching extension
// found
mb.appendCreateNew("java.lang.StringBuffer");
mb.appendDUP();
mb.appendLoadConstant("Element ");
mb.appendCallInit("java.lang.StringBuffer",
"(Ljava/lang/String;)V");
mb.appendDUP();
mb.loadContext(UNMARSHALCONTEXT_CLASS);
mb.appendCallVirtual(CURRENTELEMENT_METHOD,
CURRENTELEMENT_SIGNATURE);
mb.appendCallVirtual("java.lang.StringBuffer.append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;");
mb.appendDUP();
mb.appendLoadConstant(" has no mapping that extends " +
m_class.getClassName());
mb.appendCallVirtual("java.lang.StringBuffer.append",
"(Ljava/lang/String;)Ljava/lang/StringBuffer;");
mb.appendCallVirtual("java.lang.StringBuffer.toString",
"()Ljava/lang/String;");
mb.appendCreateNew(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS);
mb.appendDUP_X1();
mb.appendSWAP();
mb.appendCallInit(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS,
MethodBuilder.EXCEPTION_CONSTRUCTOR_SIGNATURE1);
mb.appendThrow();
if (iffounds.length > 0) {
// finish by calling unmarshaller for extension mapping
// found and returning the result with no further
// processing
mb.initStackState(iffounds[0]);
BranchTarget found = mb.appendTargetACONST_NULL();
for (int i = 0; i < iffounds.length; i++) {
iffounds[i].setTarget(found, mb);
}
mb.loadContext();
mb.appendCallInterface(UNMARSHALLERUNMARSHAL_METHOD,
UNMARSHALLERUNMARSHAL_SIGNATURE);
mb.appendReturn("java.lang.Object");
}
// fall into instance creation if this mapping reference
if (ifthis != null) {
mb.targetNext(ifthis);
}
} else if (m_isAbstract) {
// throw an exception when no instance supplied
mb.appendCreateNew(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS);
mb.appendDUP();
mb.appendLoadConstant("Abstract mapping requires instance to " +
"be supplied for class " + m_class.getClassName());
mb.appendCallInit(MethodBuilder.FRAMEWORK_EXCEPTION_CLASS,
MethodBuilder.EXCEPTION_CONSTRUCTOR_SIGNATURE1);
mb.appendThrow();
}
if (hasname) {
// just create an instance of the (non-abstract) mapped class
mb.appendACONST_NULL();
genNewInstance(mb);
mb.storeObject();
}
// define unmarshallings for child mappings of this mapping
mb.targetNext(ifnnull);
ArrayList maps = m_defContext.getMappings();
if (maps != null && maps.size() > 0) {
for (int i = 0; i < maps.size(); i++) {
IMapping map = (IMapping)maps.get(i);
if (!map.isAbstract() || map.isBase()) {
mb.loadContext(UNMARSHALCONTEXT_CLASS);
mb.appendLoadConstant(map.getMappingName());
NameDefinition mname = map.getName();
if (mname == null) {
mb.appendACONST_NULL();
mb.appendACONST_NULL();
} else {
map.getName().genPushUriPair(mb);
}
mb.appendLoadConstant(map.getUnmarshaller().getName());
mb.appendCallVirtual(ADDUNMARSHALLER_METHOD,
ADDUNMARSHALLER_SIGNATURE);
}
}
}
// load object and cast to type
mb.loadObject();
mb.appendCreateCast(type);
// handle the actual unmarshalling
if (hasattr) {
m_component.genAttributeUnmarshal(mb);
}
if (hasattr || !hasname) {
mb.loadContext(UNMARSHALCONTEXT_CLASS);
mb.appendCallVirtual(PARSERNEXT_METHOD,
PARSERNEXT_SIGNATURE);
mb.appendPOP();
}
if (hascont) {
m_component.genContentUnmarshal(mb);
}
// undefine unmarshallings for child mappings of this mapping
if (maps != null && maps.size() > 0) {
for (int i = 0; i < maps.size(); i++) {
IMapping map = (IMapping)maps.get(i);
if (!map.isAbstract() || map.isBase()) {
mb.loadContext(UNMARSHALCONTEXT_CLASS);
mb.appendLoadConstant(map.getMappingName());
mb.appendCallVirtual(REMOVEUNMARSHALLER_METHOD,
REMOVEUNMARSHALLER_SIGNATURE);
}
}
}
// finish by returning unmarshalled object reference
mb.appendReturn("java.lang.Object");
mb.codeComplete(false);
mb.addMethod();
// add interface if mapped class is directly unmarshallable
if (hasname && m_class.getClassFile() == m_class.getMungedFile()) {
addIUnmarshallableMethod();
}