This is an automated email from the ASF dual-hosted git repository.

struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git

commit a40b718b03005be89c56b1cf361fadfce8ca29ab
Author: Mark Struberg <strub...@apache.org>
AuthorDate: Sun Jun 25 16:36:55 2023 +0200

    OPENJPA-2911 addCopyKeyFieldsToObjectIdMethod in ASM
---
 .../org/apache/openjpa/enhance/PCEnhancer.java     | 608 ++++++++++++++++-----
 .../org/apache/openjpa/util/asm/AsmHelper.java     |   9 +
 2 files changed, 481 insertions(+), 136 deletions(-)

diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java 
b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
index 44779186f..7dafa3697 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
@@ -1376,8 +1376,6 @@ public class PCEnhancer {
             }
         }
 
-        AsmHelper.readIntoBCClass(pc, _pc);
-
         // add the app id methods to each subclass rather
         // than just the superclass, since it is possible to have
         // a subclass with an app id hierarchy that matches the
@@ -1385,9 +1383,12 @@ public class PCEnhancer {
         if (_meta.getIdentityType() == ClassMetaData.ID_APPLICATION
                 && (_meta.getPCSuperclass() == null || getCreateSubclass() ||
                 _meta.getObjectIdType() != 
_meta.getPCSuperclassMetaData().getObjectIdType())) {
-            AsmHelper.readIntoBCClass(pc, _pc);
+
             addCopyKeyFieldsToObjectIdMethod(true);
             addCopyKeyFieldsToObjectIdMethod(false);
+
+            AsmHelper.readIntoBCClass(pc, _pc);
+
             addCopyKeyFieldsFromObjectIdMethod(true);
             addCopyKeyFieldsFromObjectIdMethod(false);
             if (_meta.hasAbstractPKField()) {
@@ -1404,10 +1405,12 @@ public class PCEnhancer {
             addNewObjectIdInstanceMethod(false);
         }
         else if (_meta.hasPKFieldsFromAbstractClass()) {
-            pc = AsmHelper.toClassNode(_pc);
             addGetIDOwningClass();
             AsmHelper.readIntoBCClass(pc, _pc);
         }
+        else {
+            AsmHelper.readIntoBCClass(pc, _pc);
+        }
     }
 
     /**
@@ -2249,70 +2252,74 @@ public class PCEnhancer {
      */
     private void addCopyKeyFieldsToObjectIdMethod(boolean fieldManager)
             throws NoSuchMethodException {
-        // public void pcCopyKeyFieldsToObjectId (ObjectIdFieldSupplier fs,
-        //    Object oid)
-        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);
+        // public void pcCopyKeyFieldsToObjectId (ObjectIdFieldSupplier fs, 
Object oid)
+        String mDesc = fieldManager
+                ? Type.getMethodDescriptor(Type.VOID_TYPE, 
Type.getType(OIDFSTYPE), TYPE_OBJECT)
+                : Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
+        MethodNode copyKFMeth = new MethodNode(Opcodes.ACC_PUBLIC,
+                                               PRE + "CopyKeyFieldsToObjectId",
+                                               mDesc,
+                                               null, null);
+        final ClassNode classNode = pc.getClassNode();
+        classNode.methods.add(copyKFMeth);
+        InsnList instructions = copyKFMeth.instructions;
 
         // single field identity always throws exception
         if (_meta.isOpenJPAIdentity()) {
-            throwException(code, INTERNEXCEP);
-
-            code.calculateMaxStack();
-            code.calculateMaxLocals();
+            instructions.add(throwException(INTERNEXCEP));
             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);
+            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 + 
"CopyKeyFieldsToObjectId",
+                                                mDesc));
         }
 
         // Object id = oid;
-        if (fieldManager)
-            code.aload().setParam(1);
-        else
-            code.aload().setParam(0);
+        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.isObjectIdTypeShared()) {
-            // oid = ((ObjectId) id).getId ();
-            code.checkcast().setType(ObjectId.class);
-            code.invokevirtual().setMethod(ObjectId.class, "getId",
-                                           Object.class, null);
+            instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(ObjectId.class)));
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                
Type.getInternalName(ObjectId.class),
+                                                "getId",
+                                                
Type.getMethodDescriptor(TYPE_OBJECT)));
         }
 
         // <oid type> id = (<oid type>) oid;
-        int id = code.getNextLocalsIndex();
+        int nextFreeVarPos = (fieldManager) ? 3 : 2;
+        int idVarPos = nextFreeVarPos++;
+
         Class oidType = _meta.getObjectIdType();
-        code.checkcast().setType(oidType);
-        code.astore().setLocal(id);
+        instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(oidType)));
+        instructions.add(new VarInsnNode(Opcodes.ASTORE, idVarPos));
 
         // int inherited = pcInheritedFieldCount;
         int inherited = 0;
         if (fieldManager) {
-            code.getstatic().setField(INHERIT, int.class);
-            inherited = code.getNextLocalsIndex();
-            code.istore().setLocal(inherited);
+            instructions.add(new FieldInsnNode(Opcodes.GETSTATIC, 
classNode.name, INHERIT, Type.INT_TYPE.getDescriptor()));
+            inherited = nextFreeVarPos++;
+            instructions.add(new VarInsnNode(Opcodes.ISTORE, 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) {
@@ -2325,154 +2332,204 @@ public class PCEnhancer {
                     // 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())
+                            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());
+                            }
+                            instructions.add(new VarInsnNode(Opcodes.ALOAD, 
1)); // 1st param
+                            instructions.add(AsmHelper.getLoadConstantInsn(k));
+                            instructions.add(new VarInsnNode(Opcodes.ILOAD, 
inherited));
+                            instructions.add(new InsnNode(Opcodes.IADD));
+
+                            final Method fieldSupplierMethod = 
getFieldSupplierMethod(fmds[k].getObjectIdFieldType());
+                            instructions.add(new 
MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                                
Type.getInternalName(fieldSupplierMethod.getDeclaringClass()),
+                                                                
fieldSupplierMethod.getName(),
+                                                                
Type.getMethodDescriptor(fieldSupplierMethod)));
+                            localIndexes[k] = nextFreeVarPos++;
+                            instructions.add(new 
VarInsnNode(AsmHelper.getStoreInsn(fmds[k].getObjectIdFieldType()), 
localIndexes[k]));
                         }
                     }
 
                     // found a matching constructor.  parm array is 
constructor parm order
-                    code.anew().setType(oidType);
-                    code.dup();
+                    instructions.add(new TypeInsnNode(Opcodes.NEW, 
Type.getInternalName(oidType)));
+                    instructions.add(new InsnNode(Opcodes.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]);
+                            instructions.add(new VarInsnNode(Opcodes.ALOAD, 
0)); // this
+                            addGetManagedValueCode(classNode, instructions, 
fmds[parmIndex], true);
                         }
                         else {
                             // Load constructor parameters in appropriate order
-                            loadLocalValue(code, localIndexes[parmIndex], 
fmds[parmIndex].getObjectIdFieldTypeCode());
+                            instructions.add(new 
VarInsnNode(AsmHelper.getLoadInsn(fmds[parmIndex].getObjectIdFieldType()), 
localIndexes[parmIndex]));
+
                             if (fmds[parmIndex].getObjectIdFieldTypeCode() == 
JavaTypes.OBJECT &&
                                     
!fmds[parmIndex].getDeclaredType().isEnum()) {
-                                code.checkcast().setType(ObjectId.class);
-                                code.invokevirtual().setMethod(ObjectId.class, 
"getId",
-                                                               Object.class, 
null);
+                                instructions.add(new 
TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(ObjectId.class)));
+                                instructions.add(new 
MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                                    
Type.getInternalName(ObjectId.class),
+                                                                    "getId",
+                                                                    
Type.getMethodDescriptor(TYPE_OBJECT)));
                             }
+
                             // 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]);
+                            if (!clsArgs[i].isPrimitive() && 
!clsArgs[i].getName().equals(String.class.getName())) {
+                                instructions.add(new 
TypeInsnNode(Opcodes.CHECKCAST, Type.getInternalName(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);
+                    Type[] parms = Arrays.stream(clsArgs)
+                            .map(c -> Type.getType(c))
+                            .toArray(Type[]::new);
+
+                    instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL,
+                                                        
Type.getInternalName(oidType),
+                                                        "<init>",
+                                                        
Type.getMethodDescriptor(Type.VOID_TYPE, parms)));
+
+
+                    int retVarPos = inherited + fmds.length;
+                    instructions.add(new VarInsnNode(Opcodes.ASTORE, 
retVarPos));
 
                     // 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();
+                    instructions.add(new VarInsnNode(Opcodes.ALOAD, 
fieldManager ? 2 : 1));
+                    instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(ObjectId.class)));
+                    instructions.add(new VarInsnNode(Opcodes.ALOAD, 
retVarPos));
+                    instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                        
Type.getInternalName(ApplicationIds.class),
+                                                        "setAppId",
+                                                        
Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(ObjectId.class), 
TYPE_OBJECT)));
+                    instructions.add(new InsnNode(Opcodes.RETURN));
                     return;
                 }
             }
         }
 
+        Field field = null;
+        Method setter = null;
         for (int i = 0; i < fmds.length; i++) {
-            if (!fmds[i].isPrimaryKey())
+            if (!fmds[i].isPrimaryKey()) {
                 continue;
-            code.aload().setLocal(id);
+            }
+
+            instructions.add(new VarInsnNode(Opcodes.ALOAD, idVarPos));
+
+            String name = fmds[i].getName();
+            Class<?> type = fmds[i].getObjectIdFieldType();
+            boolean reflect = false;
 
-            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});
+                    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)));
                 }
             }
             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});
+                    instructions.add(AsmHelper.getLoadConstantInsn(oidType));
+                    instructions.add(AsmHelper.getLoadConstantInsn(name));
+                    instructions.add(AsmHelper.getLoadConstantInsn(type));
+                    instructions.add(AsmHelper.getLoadConstantInsn(true));
+                    instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                        
Type.getInternalName(Reflection.class),
+                                                        "findSetter",
+                                                        
Type.getMethodDescriptor(Type.getType(Method.class),
+                                                                               
  Type.getType(Class.class),
+                                                                               
  Type.getType(String.class),
+                                                                               
  Type.getType(Class.class),
+                                                                               
  Type.BOOLEAN_TYPE)));
                 }
             }
 
             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);
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 1));  // 1st 
param
+                instructions.add(AsmHelper.getLoadConstantInsn(i));
+                instructions.add(new VarInsnNode(Opcodes.ILOAD, inherited));
+                instructions.add(new InsnNode(Opcodes.IADD));
+
+                final Method fieldSupplierMethod = 
getFieldSupplierMethod(type);
+                instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                    
Type.getInternalName(fieldSupplierMethod.getDeclaringClass()),
+                                                    
fieldSupplierMethod.getName(),
+                                                    
Type.getMethodDescriptor(fieldSupplierMethod)));
+
+
+                if (fmds[i].getObjectIdFieldTypeCode() == JavaTypes.OBJECT && 
!fmds[i].getDeclaredType().isEnum()) {
+                    instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(ObjectId.class)));
+                    instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                        
Type.getInternalName(ObjectId.class),
+                                                        "getId",
+                                                        
Type.getMethodDescriptor(TYPE_OBJECT)));
                 }
 
                 // 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);
+                if (!reflect && !type.isPrimitive() && 
!type.getName().equals(String.class.getName())) {
+                    instructions.add(new TypeInsnNode(Opcodes.CHECKCAST, 
Type.getInternalName(type)));
+                }
             }
             else {
-                loadManagedInstance(code, false);
-                addGetManagedValueCode(code, fmds[i]);
+                instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); // this
+                addGetManagedValueCode(classNode, instructions, fmds[i], true);
 
                 // get id/pk from pc instance
-                if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC)
-                    addExtractObjectIdFieldValueCode(code, fmds[i]);
+                if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) {
+                    addExtractObjectIdFieldValueCode(classNode, instructions, 
fmds[i], nextFreeVarPos++);
+                }
             }
 
             if (reflect && field != null) {
-                code.invokestatic().setMethod(Reflection.class, "set",
-                                              void.class, new 
Class[]{Object.class, Field.class,
-                                (type.isPrimitive()) ? type : Object.class});
+                instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                    
Type.getInternalName(Reflection.class),
+                                                    "set",
+                                                    
Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT, Type.getType(Field.class),
+                                                                             
(type.isPrimitive()) ? Type.getType(type) : TYPE_OBJECT)));
+
             }
             else if (reflect) {
-                code.invokestatic().setMethod(Reflection.class, "set",
-                                              void.class, new 
Class[]{Object.class, Method.class,
-                                (type.isPrimitive()) ? type : Object.class});
+                instructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
+                                                    
Type.getInternalName(Reflection.class),
+                                                    "set",
+                                                    
Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT, 
Type.getType(Method.class),
+                                                                             
(type.isPrimitive()) ? Type.getType(type) : TYPE_OBJECT)));
+            }
+            else if (field != null) {
+                instructions.add(new FieldInsnNode(Opcodes.PUTFIELD,
+                                                   
Type.getInternalName(field.getDeclaringClass()),
+                                                   field.getName(),
+                                                   
Type.getDescriptor(field.getType())));
+            }
+            else {
+                instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
+                                                    
Type.getInternalName(setter.getDeclaringClass()),
+                                                    setter.getName(),
+                                                    
Type.getMethodDescriptor(setter)));
             }
-            else if (field != null)
-                code.putfield().setField(field);
-            else
-                code.invokevirtual().setMethod(setter);
-        }
-        code.vreturn();
 
-        code.calculateMaxStack();
-        code.calculateMaxLocals();
+        }
+        instructions.add(new InsnNode(Opcodes.RETURN));
     }
 
     /**
@@ -2533,6 +2590,289 @@ public class PCEnhancer {
      * Add code to extract the id of the given primary key relation field for
      * setting into an objectid instance.
      */
+    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(TYPE_OBJECT)));
+        }
+        else {
+            instructions.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE,
+                                                
Type.getInternalName(PersistenceCapable.class),
+                                                PRE + "NewObjectIdInstance",
+                                                
Type.getMethodDescriptor(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(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);
+    }
+
+    /**
+     * Add code to extract the id of the given primary key relation field for
+     * setting into an objectid instance.
+     */
+    @Deprecated
     private void addExtractObjectIdFieldValueCode(Code code, FieldMetaData pk) 
{
         // if (val != null)
         //  val = ((PersistenceCapable) val).pcFetchObjectId();
@@ -2566,11 +2906,9 @@ public class PCEnhancer {
             code.checkcast().setType(Id.class);
             code.invokevirtual().setMethod(Id.class, "getId",
                                            long.class, null);
-        }
-        else if (pkmeta.getIdentityType() == ClassMetaData.ID_DATASTORE) {
+        } else if (pkmeta.getIdentityType() == ClassMetaData.ID_DATASTORE) {
             code.aload().setLocal(oid);
-        }
-        else if (pkmeta.isOpenJPAIdentity()) {
+        } else if (pkmeta.isOpenJPAIdentity()) {
             switch (pkcode) {
                 case JavaTypes.BYTE_OBJ:
                     code.anew().setType(Byte.class);
@@ -2583,7 +2921,7 @@ public class PCEnhancer {
                                                    byte.class, null);
                     if (pkcode == JavaTypes.BYTE_OBJ)
                         code.invokespecial().setMethod(Byte.class, "<init>",
-                                                       void.class, new 
Class[]{byte.class});
+                                                       void.class, new Class[] 
{byte.class});
                     break;
                 case JavaTypes.CHAR_OBJ:
                     code.anew().setType(Character.class);
@@ -2596,7 +2934,7 @@ public class PCEnhancer {
                                                    char.class, null);
                     if (pkcode == JavaTypes.CHAR_OBJ)
                         code.invokespecial().setMethod(Character.class,
-                                                       "<init>", void.class, 
new Class[]{char.class});
+                                                       "<init>", void.class, 
new Class[] {char.class});
                     break;
                 case JavaTypes.DOUBLE_OBJ:
                     code.anew().setType(Double.class);
@@ -2635,7 +2973,7 @@ public class PCEnhancer {
                                                    int.class, null);
                     if (pkcode == JavaTypes.INT_OBJ)
                         code.invokespecial().setMethod(Integer.class, "<init>",
-                                                       void.class, new 
Class[]{int.class});
+                                                       void.class, new Class[] 
{int.class});
                     break;
                 case JavaTypes.LONG_OBJ:
                     code.anew().setType(Long.class);
@@ -2648,7 +2986,7 @@ public class PCEnhancer {
                                                    long.class, null);
                     if (pkcode == JavaTypes.LONG_OBJ)
                         code.invokespecial().setMethod(Long.class, "<init>",
-                                                       void.class, new 
Class[]{long.class});
+                                                       void.class, new Class[] 
{long.class});
                     break;
                 case JavaTypes.SHORT_OBJ:
                     code.anew().setType(Short.class);
@@ -2697,8 +3035,7 @@ public class PCEnhancer {
                     code.invokevirtual().setMethod(ObjectId.class, "getId",
                                                    Object.class, null);
             }
-        }
-        else if (pkmeta.getObjectIdType() != null) {
+        } else if (pkmeta.getObjectIdType() != null) {
             code.aload().setLocal(oid);
             if (pkcode == JavaTypes.OBJECT) {
                 code.checkcast().setType(ObjectId.class);
@@ -2706,8 +3043,7 @@ public class PCEnhancer {
                                                Object.class, null);
             }
             code.checkcast().setType(pktype);
-        }
-        else
+        } else
             code.aload().setLocal(oid);
         JumpInstruction go2 = code.go2();
 
diff --git 
a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java 
b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java
index b3783c818..a87fde367 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/asm/AsmHelper.java
@@ -215,6 +215,15 @@ public final class AsmHelper {
             }
         }
 
+        if (val instanceof Boolean) {
+            if (((Boolean)val) == true) {
+                return new InsnNode(Opcodes.ICONST_1);
+            }
+            else {
+                return new InsnNode(Opcodes.ICONST_0);
+            }
+        }
+
         if (val instanceof Class) {
             if (boolean.class.equals(val)) {
                 return new FieldInsnNode(Opcodes.GETSTATIC, 
Type.getInternalName(Boolean.class), "TYPE",


Reply via email to