private void addExtractObjectIdFieldValueCode()

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);
    }