in openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java [2740:2974]
private void addCopyKeyFieldsFromObjectIdMethod(boolean fieldManager) throws NoSuchMethodException {
// public void pcCopyKeyFieldsFromObjectId (ObjectIdFieldConsumer fc, Object oid)
String mDesc = fieldManager
? Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(OIDFCTYPE), AsmHelper.TYPE_OBJECT)
: Type.getMethodDescriptor(Type.VOID_TYPE, AsmHelper.TYPE_OBJECT);
MethodNode copyKFMeth = new MethodNode(Opcodes.ACC_PUBLIC,
PRE + "CopyKeyFieldsFromObjectId",
mDesc,
null, null);
final ClassNode classNode = pc.getClassNode();
classNode.methods.add(copyKFMeth);
InsnList instructions = copyKFMeth.instructions;
// call superclass method
if (_meta.getPCSuperclass() != null && !getCreateSubclass()) {
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st parameter object
if (fieldManager) {
instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // 2nd parameter object
}
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(getType(_meta.getPCSuperclassMetaData())),
PRE + "CopyKeyFieldsFromObjectId",
mDesc));
}
// Object id = oid;
if (fieldManager) {
instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); // 2nd parameter object
}
else {
instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st parameter object
}
if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared()) {
// oid = ((ObjectId) id).getId ();
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(ObjectId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(ObjectId.class),
"getId",
Type.getMethodDescriptor(AsmHelper.TYPE_OBJECT)));
}
// <oid type> id = (<oid type>) oid;
int nextFreeVarPos = (fieldManager) ? 3 : 2;
int idVarPos = nextFreeVarPos++;
Class oidType = _meta.getObjectIdType();
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(oidType)));
instructions.add(new VarInsnNode(Opcodes.ASTORE, idVarPos));
// fs.store<type>Field (<index>, id.<field>); or...
// this.<field> = id.<field>
// or for single field identity: id.getId ()
FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
: _meta.getDeclaredFields();
for (int i = 0; i < fmds.length; i++) {
if (!fmds[i].isPrimaryKey()) {
continue;
}
String name = fmds[i].getName();
Class<?> type = fmds[i].getObjectIdFieldType();
if (!fieldManager && fmds[i].getDeclaredTypeCode() == JavaTypes.PC) {
// if (sm == null) return;
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, SM, Type.getDescriptor(SMTYPE)));
LabelNode lblEndIfNotNull = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNONNULL, lblEndIfNotNull));
instructions.add(new InsnNode(Opcodes.RETURN));
instructions.add(lblEndIfNotNull);
// sm.getPCPrimaryKey(oid, i + pcInheritedFieldCount);
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
instructions.add(new InsnNode(Opcodes.DUP)); // leave orig on stack to set value into
instructions.add(new FieldInsnNode(Opcodes.GETFIELD, classNode.name, SM, Type.getDescriptor(SMTYPE)));
instructions.add(new VarInsnNode(Opcodes.ALOAD, idVarPos));
instructions.add(AsmHelper.getLoadConstantInsn(i));
instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, INHERIT, Type.INT_TYPE.getDescriptor()));
instructions.add(new InsnNode(Opcodes.IADD));
instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
Type.getInternalName(SMTYPE),
"getPCPrimaryKey",
Type.getMethodDescriptor(AsmHelper.TYPE_OBJECT, AsmHelper.TYPE_OBJECT, Type.INT_TYPE)));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(fmds[i].getDeclaredType())));
}
else {
Class<?> unwrapped = (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) ? type : unwrapSingleFieldIdentity(fmds[i]);
if (fieldManager) {
instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); // 1st param
instructions.add(AsmHelper.getLoadConstantInsn(i));
instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, classNode.name, INHERIT, Type.INT_TYPE.getDescriptor()));
instructions.add(new InsnNode(Opcodes.IADD));
}
else {
instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
}
if (unwrapped != type && type != Long.class) {
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(type)));
instructions.add(new InsnNode(Opcodes.DUP));
}
instructions.add(new VarInsnNode(Opcodes.ALOAD, idVarPos));
if (_meta.isOpenJPAIdentity()) {
if (oidType == ObjectId.class) {
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(oidType),
"getId",
Type.getMethodDescriptor(AsmHelper.TYPE_OBJECT)));
if (!fieldManager && type != Object.class) {
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(fmds[i].getDeclaredType())));
}
}
else if (oidType == DateId.class) {
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(oidType),
"getId",
Type.getMethodDescriptor(Type.getType(Date.class))));
if (!fieldManager && type != Date.class) {
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(fmds[i].getDeclaredType())));
}
}
else {
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(oidType),
"getId",
Type.getMethodDescriptor(Type.getType(unwrapped))));
if (unwrapped != type) {
if (type == Long.class) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(type),
LONG_VALUE_OF.getName(),
Type.getMethodDescriptor(LONG_VALUE_OF)));
} else {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(type),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(unwrapped))));
}
}
}
}
else if (isFieldAccess(fmds[i])) {
Field field = Reflection.findField(oidType, name, true);
if (Modifier.isPublic(field.getModifiers())) {
instructions.add(new FieldInsnNode(Opcodes.GETFIELD,
Type.getInternalName(field.getDeclaringClass()),
field.getName(),
Type.getDescriptor(field.getType())));
}
else {
boolean usedFastOid = false;
if (_optimizeIdCopy) {
// If fastOids, ignore access type and try to use a public getter
Method getter = Reflection.findGetter(oidType, name, false);
if (getter != null && Modifier.isPublic(getter.getModifiers())) {
usedFastOid = true;
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(getter.getDeclaringClass()),
getter.getName(),
Type.getMethodDescriptor(getter)));
}
}
if (!usedFastOid) {
// Reflection.getXXX(oid, Reflection.findField(...));
instructions.add(AsmHelper.getLoadConstantInsn(oidType));
instructions.add(AsmHelper.getLoadConstantInsn(name));
instructions.add(AsmHelper.getLoadConstantInsn(true));
instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(Reflection.class),
"findField",
Type.getMethodDescriptor(Type.getType(Field.class), Type.getType(Class.class),
Type.getType(String.class), Type.BOOLEAN_TYPE)));
final Method reflectionGetterMethod = getReflectionGetterMethod(type, Field.class);
instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(reflectionGetterMethod.getDeclaringClass()),
reflectionGetterMethod.getName(),
Type.getMethodDescriptor(reflectionGetterMethod)));
if (!type.isPrimitive() && type != Object.class) {
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(type)));
}
}
}
}
else {
Method getter = Reflection.findGetter(oidType, name, true);
if (Modifier.isPublic(getter.getModifiers())) {
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(getter.getDeclaringClass()),
getter.getName(),
Type.getMethodDescriptor(getter)));
}
else {
// Reflection.getXXX(oid, Reflection.findGetter(...));
instructions.add(AsmHelper.getLoadConstantInsn(oidType));
instructions.add(AsmHelper.getLoadConstantInsn(name));
instructions.add(AsmHelper.getLoadConstantInsn(true));
instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(Reflection.class),
"findGetter",
Type.getMethodDescriptor(Type.getType(Method.class), Type.getType(Class.class),
Type.getType(String.class), Type.BOOLEAN_TYPE)));
final Method reflectionGetterMethod = getReflectionGetterMethod(type, Method.class);
instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
Type.getInternalName(reflectionGetterMethod.getDeclaringClass()),
reflectionGetterMethod.getName(),
Type.getMethodDescriptor(reflectionGetterMethod)));
if (!type.isPrimitive() && type != Object.class) {
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(type)));
}
}
}
}
if (fieldManager) {
final Method fieldConsumerMethod = getFieldConsumerMethod(type);
instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
Type.getInternalName(fieldConsumerMethod.getDeclaringClass()),
fieldConsumerMethod.getName(),
Type.getMethodDescriptor(fieldConsumerMethod)));
}
else {
addSetManagedValueCode(classNode, instructions, fmds[i]);
}
}
instructions.add(new InsnNode(Opcodes.RETURN));
}