String[] args = (fieldManager) ?
new String[]{ OIDFSTYPE.getName(), Object.class.getName() }
: new String[]{ Object.class.getName() };
BCMethod method = _pc.declareMethod(PRE + "CopyKeyFieldsToObjectId",
void.class.getName(), args);
Code code = method.getCode(true);
// single field identity always throws exception
if (_meta.isOpenJPAIdentity()) {
throwException(code, INTERNEXCEP);
code.calculateMaxStack();
code.calculateMaxLocals();
return;
}
// call superclass method
if (_meta.getPCSuperclass() != null && !getCreateSubclass()) {
loadManagedInstance(code, false);
for (int i = 0; i < args.length; i++)
code.aload().setParam(i);
code.invokespecial().setMethod(getType(_meta.
getPCSuperclassMetaData()).getName(),
PRE + "CopyKeyFieldsToObjectId", void.class.getName(), args);
}
// Object id = oid;
if (fieldManager)
code.aload().setParam(1);
else
code.aload().setParam(0);
if (_meta.isObjectIdTypeShared()) {
// oid = ((ObjectId) id).getId ();
code.checkcast().setType(ObjectId.class);
code.invokevirtual().setMethod(ObjectId.class, "getId",
Object.class, null);
}
// <oid type> id = (<oid type>) oid;
int id = code.getNextLocalsIndex();
Class oidType = _meta.getObjectIdType();
code.checkcast().setType(oidType);
code.astore().setLocal(id);
// int inherited = pcInheritedFieldCount;
int inherited = 0;
if (fieldManager) {
code.getstatic().setField(INHERIT, int.class);
inherited = code.getNextLocalsIndex();
code.istore().setLocal(inherited);
}
// id.<field> = fs.fetch<type>Field (<index>); or...
// id.<field> = pc.<field>;
FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
: _meta.getDeclaredFields();
Class<?> type;
String name;
Field field;
Method setter;
boolean reflect;
// If optimizeIdCopy is enabled and not a field manager method, try to
// optimize the copyTo by using a public constructor instead of reflection
if (_optimizeIdCopy) {
ArrayList<Integer> pkfields = optimizeIdCopy(oidType, fmds);
if (pkfields != null) {
// search for a constructor on the IdClass that can be used
// to construct the IdClass
int parmOrder[] = getIdClassConstructorParmOrder(oidType, pkfields, fmds);
if (parmOrder != null) {
// If using a field manager, values must be loaded into locals so they can be properly ordered
// as constructor parameters.
int[] localIndexes = new int[fmds.length];
if (fieldManager) {
for (int k = 0; k < fmds.length; k++) {
if (!fmds[k].isPrimaryKey())
continue;
code.aload().setParam(0);
code.constant().setValue(k);
code.iload().setLocal(inherited);
code.iadd();
code.invokeinterface().setMethod(getFieldSupplierMethod(fmds[k].getObjectIdFieldType()));
localIndexes[k] = code.getNextLocalsIndex();
storeLocalValue(code, localIndexes[k], fmds[k].getObjectIdFieldTypeCode());
}
}
// found a matching constructor. parm array is constructor parm order
code.anew().setType(oidType);
code.dup();
// build the parm list in order
Class<?>[] clsArgs = new Class<?>[parmOrder.length];
for (int i = 0; i < clsArgs.length; i++) {
int parmIndex = parmOrder[i];
clsArgs[i] = fmds[parmIndex].getObjectIdFieldType();
if (!fieldManager) {
loadManagedInstance(code, false);
addGetManagedValueCode(code, fmds[parmIndex]);
} else {
// Load constructor parameters in appropriate order
loadLocalValue(code, localIndexes[parmIndex], fmds[parmIndex].getObjectIdFieldTypeCode());
if (fmds[parmIndex].getObjectIdFieldTypeCode() == JavaTypes.OBJECT &&
!fmds[parmIndex].getDeclaredType().isEnum()) {
code.checkcast().setType(ObjectId.class);
code.invokevirtual().setMethod(ObjectId.class, "getId",
Object.class, null);
}
// if the type of this field meta data is
// non-primitive and non-string, be sure to cast
// to the appropriate type.
if (!clsArgs[i].isPrimitive()
&& !clsArgs[i].getName().equals(String.class.getName()))
code.checkcast().setType(clsArgs[i]);
}
}
// invoke the public constructor to create a new local id
code.invokespecial().setMethod(oidType, "<init>", void.class, clsArgs);
int ret = code.getNextLocalsIndex();
code.astore().setLocal(ret);
// swap out the app id with the new one
code.aload().setLocal( fieldManager ? 2 : 1);
code.checkcast().setType(ObjectId.class);
code.aload().setLocal(ret);
code.invokestatic().setMethod(ApplicationIds.class,
"setAppId", void.class, new Class[] { ObjectId.class,
Object.class });
code.vreturn();
code.calculateMaxStack();
code.calculateMaxLocals();
return;
}
}
}
for (int i = 0; i < fmds.length; i++) {
if (!fmds[i].isPrimaryKey())
continue;
code.aload().setLocal(id);
name = fmds[i].getName();
type = fmds[i].getObjectIdFieldType();
if (isFieldAccess(fmds[i])) {
setter = null;
field = Reflection.findField(oidType, name, true);
reflect = !Modifier.isPublic(field.getModifiers());
if (reflect) {
code.classconstant().setClass(oidType);
code.constant().setValue(name);
code.constant().setValue(true);
code.invokestatic().setMethod(Reflection.class,
"findField", Field.class, new Class[] { Class.class,
String.class, boolean.class });
}
} else {
field = null;
setter = Reflection.findSetter(oidType, name, type, true);
reflect = !Modifier.isPublic(setter.getModifiers());
if (reflect) {
code.classconstant().setClass(oidType);
code.constant().setValue(name);
code.classconstant().setClass(type);
code.constant().setValue(true);
code.invokestatic().setMethod(Reflection.class,
"findSetter", Method.class, new Class[] { Class.class,
String.class, Class.class, boolean.class });
}
}
if (fieldManager) {
code.aload().setParam(0);
code.constant().setValue(i);
code.iload().setLocal(inherited);
code.iadd();
code.invokeinterface().setMethod
(getFieldSupplierMethod(type));
if (fmds[i].getObjectIdFieldTypeCode() == JavaTypes.OBJECT &&
!fmds[i].getDeclaredType().isEnum()) {
code.checkcast().setType(ObjectId.class);
code.invokevirtual().setMethod(ObjectId.class, "getId",
Object.class, null);
}
// if the type of this field meta data is
// non-primitive and non-string, be sure to cast
// to the appropriate type.
if (!reflect && !type.isPrimitive()
&& !type.getName().equals(String.class.getName()))
code.checkcast().setType(type);
} else {
loadManagedInstance(code, false);
addGetManagedValueCode(code, fmds[i]);
// get id/pk from pc instance
if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC)
addExtractObjectIdFieldValueCode(code, fmds[i]);
}
if (reflect && field != null) {
code.invokestatic().setMethod(Reflection.class, "set",
void.class, new Class[] { Object.class, Field.class,
(type.isPrimitive()) ? type : Object.class });
} else if (reflect) {
code.invokestatic().setMethod(Reflection.class, "set",
void.class, new Class[] { Object.class, Method.class,
(type.isPrimitive()) ? type : Object.class });
} else if (field != null)
code.putfield().setField(field);
else
code.invokevirtual().setMethod(setter);
}
code.vreturn();
code.calculateMaxStack();
code.calculateMaxLocals();
}