in openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java [2458:2734]
private void addExtractObjectIdFieldValueCode(ClassNode classNode, InsnList instructions, FieldMetaData pk, int nextFreeVarPos) {
// if (val != null) {
int pcVarPos = nextFreeVarPos++;
instructions.add(new VarInsnNode(Opcodes.ASTORE, pcVarPos));
instructions.add(new VarInsnNode(Opcodes.ALOAD, pcVarPos));
LabelNode lblAfterIfNull = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNULL, lblAfterIfNull));
instructions.add(new VarInsnNode(Opcodes.ALOAD, pcVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(PersistenceCapable.class)));
// val = ((PersistenceCapable) val).pcFetchObjectId(); or pcNewObjectIdInstance()
if (!pk.getTypeMetaData().isOpenJPAIdentity()) {
instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
Type.getInternalName(PersistenceCapable.class),
PRE + "FetchObjectId",
Type.getMethodDescriptor(AsmHelper.TYPE_OBJECT)));
}
else {
instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
Type.getInternalName(PersistenceCapable.class),
PRE + "NewObjectIdInstance",
Type.getMethodDescriptor(AsmHelper.TYPE_OBJECT)));
}
int oidVarPos = nextFreeVarPos++;
instructions.add(new VarInsnNode(Opcodes.ASTORE, oidVarPos));
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
LabelNode lblAfterIfNull2 = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.IFNULL, lblAfterIfNull2));
// for datastore / single-field identity:
// if (val != null)
// val = ((OpenJPAId) val).getId();
ClassMetaData pkmeta = pk.getDeclaredTypeMetaData();
int pkcode = pk.getObjectIdFieldTypeCode();
Class pktype = pk.getObjectIdFieldType();
if (pkmeta.getIdentityType() == ClassMetaData.ID_DATASTORE && pkcode == JavaTypes.LONG) {
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(Id.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(Id.class),
"getId",
Type.getMethodDescriptor(Type.LONG_TYPE)));
}
else if (pkmeta.getIdentityType() == ClassMetaData.ID_DATASTORE) {
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
}
else if (pkmeta.isOpenJPAIdentity()) {
switch (pkcode) {
case JavaTypes.BYTE_OBJ:
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(Byte.class)));
instructions.add(new InsnNode(Opcodes.DUP));
// no break
case JavaTypes.BYTE:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(ByteId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(ByteId.class),
"getId",
Type.getMethodDescriptor(Type.BYTE_TYPE)));
if (pkcode == JavaTypes.BYTE_OBJ) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(Byte.class),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.BYTE_TYPE)));
}
break;
case JavaTypes.CHAR_OBJ:
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(Character.class)));
instructions.add(new InsnNode(Opcodes.DUP));
// no break
case JavaTypes.CHAR:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(CharId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(CharId.class),
"getId",
Type.getMethodDescriptor(Type.CHAR_TYPE)));
if (pkcode == JavaTypes.CHAR_OBJ) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(Character.class),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.CHAR_TYPE)));
}
break;
case JavaTypes.DOUBLE_OBJ:
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(Double.class)));
instructions.add(new InsnNode(Opcodes.DUP));
// no break
case JavaTypes.DOUBLE:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(DoubleId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(DoubleId.class),
"getId",
Type.getMethodDescriptor(Type.DOUBLE_TYPE)));
if (pkcode == JavaTypes.DOUBLE_OBJ) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(Character.class),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.CHAR_TYPE)));
}
break;
case JavaTypes.FLOAT_OBJ:
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(Float.class)));
instructions.add(new InsnNode(Opcodes.DUP));
// no break
case JavaTypes.FLOAT:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(FloatId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(FloatId.class),
"getId",
Type.getMethodDescriptor(Type.FLOAT_TYPE)));
if (pkcode == JavaTypes.FLOAT_OBJ) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(Float.class),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.FLOAT_TYPE)));
}
break;
case JavaTypes.INT_OBJ:
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(Integer.class)));
instructions.add(new InsnNode(Opcodes.DUP));
// no break
case JavaTypes.INT:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(IntId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(IntId.class),
"getId",
Type.getMethodDescriptor(Type.INT_TYPE)));
if (pkcode == JavaTypes.INT_OBJ) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(Integer.class),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE)));
}
break;
case JavaTypes.LONG_OBJ:
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(Long.class)));
instructions.add(new InsnNode(Opcodes.DUP));
// no break
case JavaTypes.LONG:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(LongId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(LongId.class),
"getId",
Type.getMethodDescriptor(Type.LONG_TYPE)));
if (pkcode == JavaTypes.LONG_OBJ) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(Long.class),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.LONG_TYPE)));
}
break;
case JavaTypes.SHORT_OBJ:
instructions.add(new TypeInsnNode(Opcodes.NEW, Type.getInternalName(Short.class)));
instructions.add(new InsnNode(Opcodes.DUP));
// no break
case JavaTypes.SHORT:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(ShortId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(ShortId.class),
"getId",
Type.getMethodDescriptor(Type.SHORT_TYPE)));
if (pkcode == JavaTypes.SHORT_OBJ) {
instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
Type.getInternalName(Short.class),
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, Type.SHORT_TYPE)));
}
break;
case JavaTypes.DATE:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(DateId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(DateId.class),
"getId",
Type.getMethodDescriptor(Type.getType(Date.class))));
if (pktype != Date.class) {
// java.sql.Date.class
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(pktype)));
}
break;
case JavaTypes.STRING:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(StringId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(StringId.class),
"getId",
Type.getMethodDescriptor(Type.getType(String.class))));
break;
case JavaTypes.BIGDECIMAL:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(BigDecimalId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(BigDecimalId.class),
"getId",
Type.getMethodDescriptor(Type.getType(BigDecimal.class))));
break;
case JavaTypes.BIGINTEGER:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(BigIntegerId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(BigIntegerId.class),
"getId",
Type.getMethodDescriptor(Type.getType(BigInteger.class))));
break;
default:
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(ObjectId.class)));
instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
Type.getInternalName(ObjectId.class),
"getId",
Type.getMethodDescriptor(Type.getType(Object.class))));
}
}
else if (pkmeta.getObjectIdType() != null) {
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
if (pkcode == JavaTypes.OBJECT) {
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)));
}
instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(pktype)));
}
else {
instructions.add(new VarInsnNode(Opcodes.ALOAD, oidVarPos));
}
// jump from here to the end
LabelNode lblGo2End = new LabelNode();
instructions.add(new JumpInsnNode(Opcodes.GOTO, lblGo2End));
// elses from above to define the defaults
instructions.add(lblAfterIfNull);
instructions.add(lblAfterIfNull2);
switch (pkcode) {
case JavaTypes.BOOLEAN:
instructions.add(AsmHelper.getLoadConstantInsn(false));
break;
case JavaTypes.BYTE:
instructions.add(AsmHelper.getLoadConstantInsn(0));
break;
case JavaTypes.CHAR:
instructions.add(AsmHelper.getLoadConstantInsn(0));
break;
case JavaTypes.DOUBLE:
instructions.add(AsmHelper.getLoadConstantInsn(0D));
break;
case JavaTypes.FLOAT:
instructions.add(AsmHelper.getLoadConstantInsn(0F));
break;
case JavaTypes.INT:
instructions.add(AsmHelper.getLoadConstantInsn(0));
break;
case JavaTypes.LONG:
instructions.add(AsmHelper.getLoadConstantInsn(0L));
break;
case JavaTypes.SHORT:
instructions.add(AsmHelper.getLoadConstantInsn((short) 0));
break;
default:
instructions.add(AsmHelper.getLoadConstantInsn(null));
}
instructions.add(lblGo2End);
}