// add static field for instance
ClassItem inst = cf.addField(FACTORY_INTERFACE,
FACTORY_INSTNAME, PRIVATESTATIC_ACCESS);
// add private method to return binding classes blob (replaced later)
MethodBuilder mb = new ExceptionMethodBuilder(CLASSLIST_METHOD_NAME,
Type.STRING, new Type[0], cf,
Constants.ACC_PRIVATE|Constants.ACC_STATIC);
mb.appendACONST_NULL();
mb.appendReturn(Type.STRING);
mb.codeComplete(false);
ClassItem clasblobmeth = mb.addMethod();
// add the private constructor method
mb = new ExceptionMethodBuilder("<init>", Type.VOID, new Type[0], cf,
Constants.ACC_PRIVATE);
// start superclass constructor call with name/versions, classes used
mb.appendLoadLocal(0);
mb.appendLoadConstant(m_name);
mb.appendLoadConstant(m_majorVersion);
mb.appendLoadConstant(m_minorVersion);
mb.appendCall(clasblobmeth);
// load count of mapped classes
int count = s_mappedClasses.size();
int mcnt = m_extraClasses == null ? count : count +
m_extraClasses.size();
// create argument blob of mapped class names
String[] names = new String[mcnt];
for (int i = 0; i < count; i++) {
names[i] = (String)s_mappedClasses.get(i);
}
for (int i = count; i < mcnt; i++) {
names[i] = (String)m_extraClasses.get(i-count);
}
codegenString(buildClassNamesBlob(names), mb);
// create argument blob of unmarshaller class names
if (m_isInput) {
for (int i = 0; i < count; i++) {
String cname = (String)s_mappedClasses.get(i);
IMapping map = m_activeContext.getMappingAtLevel(cname);
if (map != null && map.getUnmarshaller() != null) {
names[i] = map.getUnmarshaller().getName();
} else {
names[i] = null;
}
}
for (int i = count; i < mcnt; i++) {
names[i] = (String)m_extraUnmarshallers.get(i-count);
}
codegenString(buildClassNamesBlob(names), mb);
} else {
mb.appendACONST_NULL();
}
// create argument blob of marshaller class names
if (m_isOutput) {
for (int i = 0; i < count; i++) {
String cname = (String)s_mappedClasses.get(i);
IMapping map = m_activeContext.getMappingAtLevel(cname);
if (map != null && map.getMarshaller() != null) {
names[i] = map.getMarshaller().getName();
} else {
names[i] = null;
}
}
for (int i = count; i < mcnt; i++) {
names[i] = (String)m_extraMarshallers.get(i-count);
}
codegenString(buildClassNamesBlob(names), mb);
} else {
mb.appendACONST_NULL();
}
// create argument array of namespace URIs
String[] nsuris = new String[m_namespaceUris.size()];
mb.appendLoadConstant(m_namespaceUris.size());
mb.appendCreateArray("java.lang.String");
for (int i = 0; i < m_namespaceUris.size(); i++) {
mb.appendDUP();
mb.appendLoadConstant(i);
String uri = (String)m_namespaceUris.get(i);
mb.appendLoadConstant(uri);
mb.appendAASTORE();
nsuris[i] = uri;
}
// create argument array of namespace prefixes
if (m_isOutput) {
mb.appendLoadConstant(m_namespacePrefixes.size());
mb.appendCreateArray("java.lang.String");
for (int i = 0; i < m_namespacePrefixes.size(); i++) {
mb.appendDUP();
mb.appendLoadConstant(i);
mb.appendLoadConstant((String)m_namespacePrefixes.get(i));
mb.appendAASTORE();
}
} else {
mb.appendACONST_NULL();
}
// create argument blobs of globally mapped element names and URIs
names = new String[count];
String[] namespaces = new String[count];
for (int i = 0; i < count; i++) {
String cname = (String)s_mappedClasses.get(i);
IMapping map = m_activeContext.getMappingAtLevel(cname);
if (map != null) {
NameDefinition ndef = map.getName();
if (ndef != null) {
names[i] = ndef.getName();
namespaces[i] = ndef.getNamespace();
}
}
}
codegenString(buildNamesBlob(names), mb);
mb.appendLoadConstant(buildNamespaceIndexBlob(nsuris, namespaces));
// create argument array of class names with unique IDs
if (m_uniqueIds != null && m_uniqueIds.size() > 0) {
mb.appendLoadConstant(m_uniqueIds.size());
mb.appendCreateArray("java.lang.String");
for (int i = 0; i < m_uniqueIds.size(); i++) {
mb.appendDUP();
mb.appendLoadConstant(i);
mb.appendLoadConstant((String)m_uniqueIds.get(i));
mb.appendAASTORE();
}
} else {
mb.appendACONST_NULL();
}
// create argument blobs of abstract mapping information
GrowableStringArray allnames = new GrowableStringArray();
int abmapcnt = 0;
StringBuffer buff = new StringBuffer();
for (int i = 0; i < count; i++) {
String tname = (String)s_mappedClasses.get(i);
IMapping map = m_activeContext.getMappingAtLevel(tname);
if (map != null && map.isAbstract()) {
ITypeBinding bind = map.getBinding();
allnames.add(tname);
allnames.add(map.getBoundType());
allnames.add(bind.getCreateMethod());
allnames.add(bind.getCompleteMethod());
allnames.add(bind.getPrepareMethod());
allnames.add(bind.getAttributePresentTestMethod());
allnames.add(bind.getAttributeUnmarshalMethod());
allnames.add(bind.getAttributeMarshalMethod());
allnames.add(bind.getContentPresentTestMethod());
allnames.add(bind.getContentUnmarshalMethod());
allnames.add(bind.getContentMarshalMethod());
abmapcnt++;
ArrayList nss = map.getNamespaces();
if (nss == null) {
buff.append((char)1);
} else {
buff.append((char)(nss.size()+1));
for (int j = 0; j < nss.size(); j++) {
NamespaceDefinition nsdef =
(NamespaceDefinition)nss.get(j);
buff.append((char)(nsdef.getIndex()+1));
}
}
}
}
codegenString(buildClassNamesBlob(allnames.toArray()), mb);
codegenString(buff.toString(), mb);
// create argument blobs of precompiled base binding names and factories
int basecount = m_baseBindings.size();
codegenString(buildNamesBlob(m_baseBindings.toArray()), mb);
String namesblob = buildClassNamesBlob(m_baseBindingFactories.toArray());
if (m_closureFactories.size() > 0) {
namesblob += "|" + buildClassNamesBlob(m_closureFactories.toArray());
}
codegenString(namesblob, mb);
// create argument blob for base binding factory hashes
char[] hashchars = new char[basecount*2];
for (int i = 0; i < basecount; i++) {
int hash = ((Integer)m_baseHashes.get(i)).intValue();
hashchars[i*2] = (char)(hash >> 16);
hashchars[i*2+1] = (char)hash;
}
codegenString(new String(hashchars), mb);
// create array of blobs of base binding namespace translation tables
mb.appendLoadConstant(basecount + m_closureNamespaceTables.size());
mb.appendCreateArray("java.lang.String");
for (int i = 0; i < basecount; i++) {
int[] table = (int[])m_baseNamespaceTables.get(i);
if (table != null) {
mb.appendDUP();
mb.appendLoadConstant(i);
mb.appendLoadConstant(buildIntsBlob(table));
mb.appendAASTORE();
}
}
for (int i = 0; i < m_closureNamespaceTables.size(); i++) {
int[] table = (int[])m_closureNamespaceTables.get(i);
mb.appendDUP();
mb.appendLoadConstant(i+basecount);
mb.appendLoadConstant(buildIntsBlob(table));
mb.appendAASTORE();
}
// call the base class constructor
mb.appendCallInit(FACTORY_BASE,
"(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;" +
"Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;" +
"[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;" +
"[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;" +
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;" +
"[Ljava/lang/String;)V");
// get class names for types (abstract non-base mappings)
GrowableStringArray tnames = new GrowableStringArray();
if (m_isForceClasses) {
for (int i = 0; i < count; i++) {
String cname = (String)s_mappedClasses.get(i);
IMapping map = m_activeContext.getMappingAtLevel(cname);
if (map != null && map.isAbstract() && !map.isBase()) {
String tname = map.getTypeName();
if (tname == null) {
tname = cname;
}
tnames.add(tname);
}
}
}
// check if map needed for types
ClassItem tmap = null;
if (tnames.size() >= TYPEMAP_MINIMUM_SIZE) {
// create field for map
tmap = cf.addPrivateField(STRINGINT_MAPTYPE, TYPEMAP_NAME);
// initialize with appropriate size
mb.appendLoadLocal(0);
mb.appendCreateNew(STRINGINT_MAPTYPE);
mb.appendDUP();
mb.appendLoadConstant(tnames.size());
mb.appendCallInit(STRINGINT_MAPTYPE, STRINGINTINIT_SIGNATURE);
// add all values to map
for (int i = 0; i < tnames.size(); i++) {
int index = s_mappedClasses.find(tnames.get(i));
if (index >= 0) {
mb.appendDUP();
mb.appendLoadConstant((String)tnames.get(i));
mb.appendLoadConstant(index);
mb.appendCallVirtual(STRINGINTADD_METHOD,
STRINGINTADD_SIGNATURE);
mb.appendPOP();
}
}
mb.appendPutField(tmap);
}
// finish with return from constructor
mb.appendReturn();
mb.codeComplete(false);
mb.addMethod();
// add the compiler version access method
mb = new ExceptionMethodBuilder(GETVERSION_METHODNAME,
Type.INT, new Type[0], cf, Constants.ACC_PUBLIC);
mb.appendLoadConstant(IBindingFactory.CURRENT_VERSION_NUMBER);
mb.appendReturn("int");
mb.codeComplete(false);
mb.addMethod();
// add the compiler distribution access method
mb = new ExceptionMethodBuilder(GETDISTRIB_METHODNAME,
Type.STRING, new Type[0], cf, Constants.ACC_PUBLIC);
mb.appendLoadConstant(CURRENT_VERSION_NAME);
mb.appendReturn(Type.STRING);
mb.codeComplete(false);
mb.addMethod();
// add the type mapping index lookup method
mb = new ExceptionMethodBuilder(GETTYPEINDEX_METHODNAME,
Type.INT, new Type[] { Type.STRING }, cf, Constants.ACC_PUBLIC);
if (tnames.size() > 0) {
if (tmap == null) {
// generate in-line compares for mapping
for (int i = 0; i < tnames.size(); i++) {
int index = s_mappedClasses.find(tnames.get(i));
if (index >= 0) {
mb.appendLoadLocal(1);
mb.appendLoadConstant((String)tnames.get(i));
mb.appendCallVirtual("java.lang.String.equals",
"(Ljava/lang/Object;)Z");
BranchWrapper onfail = mb.appendIFEQ(this);
mb.appendLoadConstant(index);
mb.appendReturn(Type.INT);
mb.targetNext(onfail);
}
}
mb.appendLoadConstant(-1);
} else {
// use map constructed in initializer
mb.appendLoadLocal(0);
mb.appendGetField(tmap);
mb.appendLoadLocal(1);
mb.appendCallVirtual(STRINGINTGET_METHOD,
STRINGINTGET_SIGNATURE);
}
} else {
// no types to handle, just always return failure
mb.appendLoadConstant(-1);
}
mb.appendReturn(Type.INT);
mb.codeComplete(false);
mb.addMethod();
// finish with instance creation method
mb = new ExceptionMethodBuilder(GETINST_METHODNAME,
ClassItem.typeFromName(FACTORY_INTERFACE), new Type[0], cf,
(short)(Constants.ACC_PUBLIC | Constants.ACC_STATIC));
mb.appendGetStatic(inst);
BranchWrapper ifdone = mb.appendIFNONNULL(this);
mb.appendCreateNew(cf.getName());
mb.appendDUP();
mb.appendCallInit(cf.getName(), "()V");
mb.appendPutStatic(inst);
mb.targetNext(ifdone);
mb.appendGetStatic(inst);
mb.appendReturn(FACTORY_INTERFACE);
mb.codeComplete(false);
mb.addMethod();
// add factory class to generated registry
cf.codeComplete();
MungedClass.addModifiedClass(cf);
m_factoryClass = cf;