Package org.jpox.enhancer.bcel.method

Source Code of org.jpox.enhancer.bcel.method.JdoCopyKeyFieldsFromObjectId

/**********************************************************************
Copyright (c) 2004 Kikuchi Kousuke and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
2004 Andy Jefferson - fix to SingleFieldIdentity getKey call
    ...
**********************************************************************/
package org.jpox.enhancer.bcel.method;

import java.lang.reflect.Modifier;

import javax.jdo.identity.ByteIdentity;
import javax.jdo.identity.CharIdentity;
import javax.jdo.identity.IntIdentity;
import javax.jdo.identity.LongIdentity;
import javax.jdo.identity.ObjectIdentity;
import javax.jdo.identity.ShortIdentity;
import javax.jdo.identity.StringIdentity;

import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.generic.ALOAD;
import org.apache.bcel.generic.ASTORE;
import org.apache.bcel.generic.BranchInstruction;
import org.apache.bcel.generic.IFNE;
import org.apache.bcel.generic.IFNONNULL;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionConstants;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.Type;
import org.jpox.enhancer.ClassEnhancer;
import org.jpox.enhancer.bcel.BCELClassEnhancer;
import org.jpox.enhancer.bcel.BCELClassMethod;
import org.jpox.enhancer.bcel.BCELUtils;
import org.jpox.enhancer.bcel.metadata.BCELMember;
import org.jpox.enhancer.bcel.metadata.BCELFieldPropertyMetaData;
import org.jpox.metadata.AbstractClassMetaData;
import org.jpox.metadata.AbstractMemberMetaData;
import org.jpox.metadata.IdentityType;
import org.jpox.metadata.MetaDataManager;
import org.jpox.util.ClassUtils;

/**
* Create the jdoCopyKeyFieldsFromObjectId(ObjectIdFieldConsumer fc, Object oid) method.
* @version $Revision: 1.14 $
*/
public class JdoCopyKeyFieldsFromObjectId extends BCELClassMethod
{
    /**
     * @param methodName Name of the method
     * @param type Type of object
     * @param resultType Result type from method
     * @param argType Types of args
     * @param argName Names of args
     * @param synthetic Whether it is synthetic
     * @param gen The generator base
     */
    public JdoCopyKeyFieldsFromObjectId(String methodName, int type, Type resultType, Type[] argType,
        String[] argName, boolean synthetic, BCELClassEnhancer gen)
    {
        super(methodName, type, resultType, argType, argName, synthetic, gen);
    }

    /**
     * Create and return instance of this class.
     * @param gen target class generator
     * @return instance of this class
     */
    public static JdoCopyKeyFieldsFromObjectId getInstance(BCELClassEnhancer gen)
    {
        return new JdoCopyKeyFieldsFromObjectId(
            "jdoCopyKeyFieldsFromObjectId",
            Constants.ACC_PUBLIC,
            Type.VOID,
            new Type[] { BCELClassEnhancer.OT_ObjectIdFieldConsumer, Type.OBJECT },
            new String[] { "fc", "oid" },
            false,
            gen);
    }

    public void execute()
    {
        AbstractMemberMetaData targetFields[] = cmd.getManagedMembers();
        AbstractMemberMetaData fields[] = cmd.getManagedMembers();
        InstructionHandle lv_o[] = new InstructionHandle[2];

        String oidClassName = cmd.getObjectidClass();
        if ((oidClassName != null) && (oidClassName.length() > 0))
        {
            ObjectType oidType = new ObjectType(oidClassName);
            il.append(InstructionConstants.ALOAD_1);
            BranchInstruction checkFmNotNull = new IFNONNULL(null);
            il.append(checkFmNotNull);
            createThrowException(ClassEnhancer.CN_IllegalArgumentException, "ObjectIdFieldConsumer is null");
            checkFmNotNull.setTarget(il.append(InstructionConstants.ALOAD_2));
            il.append(factory.createInstanceOf(oidType));

            BranchInstruction isInstanceof = new IFNE(null);
            il.append(isInstanceof);
            createThrowException(ClassEnhancer.CN_ClassCastException, "oid is not instanceof " + oidClassName);

            isInstanceof.setTarget(il.append(InstructionConstants.ALOAD_2));
            il.append(factory.createCast(Type.OBJECT, oidType));
            lv_o[0] = il.append(new ASTORE(3));

            if (fields != null)
            {
                for (int i = 0; i < fields.length; i++)
                {
                    AbstractMemberMetaData fieldConfig = (AbstractMemberMetaData)fields[i];
                    if (fieldConfig.isPrimaryKey())
                    {
                        BCELMember field = ((BCELFieldPropertyMetaData)targetFields[i]).getEnhanceField();

                        il.append(InstructionConstants.ALOAD_1);
                        il.append(BCELUtils.getBIPUSH(i));

                        //support for identifying relationships
                        //if the class has metadata, it is PersistenceCapable
                        //add JDOHelper.getObjectId(fieldXXXX);
                        MetaDataManager mgr = cmd.getMetaDataManager();
                        AbstractClassMetaData cmd = mgr.getMetaDataForClass(fieldConfig.getType(),
                            enhancer.getClassLoaderResolver());
                        if (cmd != null && cmd.getIdentityType() != IdentityType.NONDURABLE)
                        {
                            //jdoGetPersistenceManager().getObjectById(id.field,false)
                            //  jdoGetPersistenceManager
                            il.append(InstructionConstants.ALOAD_0);
                            il.append(factory.createInvoke(ClassEnhancer.CN_PersistenceCapable, ClassEnhancer.MN_JdoGetPersistenceManager,
                                BCELClassEnhancer.OT_PersistenceManager, Type.NO_ARGS, Constants.INVOKEINTERFACE));
                            //  getObjectById(id.field,false)
                            //  id.field
                            createGetField(
                                oidClassName,
                                fieldConfig.getName(),
                                new ObjectType(cmd.getObjectidClass()),
                                fieldConfig.isProperty(),
                                getModifiers(oidClassName, fieldConfig.getName()),
                                new ALOAD(3));

                            //  false
                            il.append(InstructionConstants.ICONST_0);
                            //  getObjectById
                            il.append(factory.createInvoke(ClassEnhancer.CN_PersistenceManager, "getObjectById", Type.OBJECT,
                                new Type[]{Type.OBJECT, Type.BOOLEAN}, Constants.INVOKEINTERFACE));
                            il.append(factory.createCast(Type.OBJECT, ((BCELFieldPropertyMetaData)fieldConfig).getEnhanceField().getType()));
                        }
                        else
                        {
                            if (mgr.getApiAdapter().isSingleFieldIdentityClass(oidClassName))
                            {
                                Type getKeyReturnType = field.getType();
                                if (oidClassName.equals(LongIdentity.class.getName()))
                                {
                                    getKeyReturnType = Type.LONG;
                                }
                                else if (oidClassName.equals(CharIdentity.class.getName()))
                                {
                                    getKeyReturnType = Type.CHAR;
                                }
                                else if (oidClassName.equals(ByteIdentity.class.getName()))
                                {
                                    getKeyReturnType = Type.BYTE;
                                }
                                else if (oidClassName.equals(IntIdentity.class.getName()))
                                {
                                    getKeyReturnType = Type.INT;
                                }
                                else if (oidClassName.equals(ShortIdentity.class.getName()))
                                {
                                    getKeyReturnType = Type.SHORT;
                                }
                                else if (oidClassName.equals(StringIdentity.class.getName()))
                                {
                                    getKeyReturnType = Type.STRING;
                                }
                                else if (oidClassName.equals(ObjectIdentity.class.getName()))
                                {
                                    getKeyReturnType = Type.OBJECT;
                                }

                                if (!getKeyReturnType.equals(field.getType()))
                                {
                                    if (getKeyReturnType == Type.OBJECT)
                                    {
                                        // Return type from getKey() needs cast to correct object type
                                        il.append(InstructionFactory.createLoad(Type.OBJECT, 3));
                                        il.append(factory.createInvoke(oidClassName, "getKey", getKeyReturnType, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
                                        il.append(factory.createCheckCast(new ObjectType(fieldConfig.getTypeName())));
                                    }
                                    else
                                    {
                                        // Return type from getKey() needs conversion to object wrapper
                                        il.append(factory.createNew(fieldConfig.getTypeName()));
                                        il.append(InstructionConstants.DUP);
                                        il.append(InstructionFactory.createLoad(Type.OBJECT, 3));
                                        il.append(factory.createInvoke(oidClassName, "getKey", getKeyReturnType, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
                                        il.append(factory.createInvoke(fieldConfig.getTypeName(), "<init>", Type.VOID,
                                            new Type[]{getKeyReturnType}, Constants.INVOKESPECIAL));
                                    }
                                }
                                else
                                {
                                    // Return type from getKey() is consistent with the field type
                                    il.append(new ALOAD(3));
                                    il.append(factory.createInvoke(oidClassName, "getKey", field.getType(), Type.NO_ARGS, Constants.INVOKEVIRTUAL));
                                }
                            }
                            else
                            {
                                createGetField(
                                    oidClassName,
                                    fieldConfig.getName(),
                                    field.getType(),
                                    fieldConfig.isProperty(),
                                    getModifiers(oidClassName, fieldConfig.getName()),
                                    new ALOAD(3));
                            }
                        }
                        String paramName = BCELUtils.getJDOMethodName(field.getType());
                        il.append(factory.createInvoke(ClassEnhancer.CN_ObjectIdFieldConsumer, "store" + paramName + "Field", Type.VOID, new Type[]{Type.INT,
                                BCELUtils.getJDOMethodType(field.getType())}, Constants.INVOKEINTERFACE));
                    }
                }
            }
            lv_o[1] = il.append(InstructionConstants.RETURN);
            methodGen.addLocalVariable("o", oidType, lv_o[0], lv_o[1]);
        }
        else
        {
            il.append(InstructionConstants.RETURN);
        }
    }
   
    /**
     * Several forms of accessing the fields : via persistent properties; persistent fields; private/protected fields
     * @param className
     * @param fieldName
     * @param fieldType
     * @param isProperty
     * @param isPrivate
     * @param isProtected
     */
    private void createGetField(String className, String fieldName, Type fieldType, boolean isProperty, int fieldModifiers, Instruction ih)
    {
        if( isProperty )
        {
            il.append(ih);
            il.append(factory.createInvoke(
                className,
                ClassUtils.getJavaBeanGetterName(fieldName, fieldType == Type.BOOLEAN),
                fieldType,
                new Type[] {},
                Constants.INVOKEVIRTUAL));
        }
        else
        {
            if( !Modifier.isPrivate(fieldModifiers) && !Modifier.isProtected(fieldModifiers) )
            {
                il.append(ih);
                il.append(factory.createGetField(className, fieldName, fieldType));
            }
            else
            {
                il.append(ih);
                il.append(factory.createInvoke(
                    "java.lang.Object",
                    "getClass",
                    Type.CLASS,
                    Type.NO_ARGS,
                    Constants.INVOKEVIRTUAL));
                il.append(new PUSH(constantPoolGen, fieldName));
                il.append(factory.createInvoke(
                    "java.lang.Class",
                    "getDeclaredField",
                    new ObjectType("java.lang.reflect.Field"),
                    new Type[] { Type.STRING },
                    Constants.INVOKEVIRTUAL));
                il.append(new ASTORE(4));
                il.append(new ALOAD(4));
                il.append(InstructionConstants.ICONST_1);
                il.append(factory.createInvoke(
                    "java.lang.reflect.Field",
                    "setAccessible",
                    Type.VOID,
                    new Type[] { Type.BOOLEAN },
                    Constants.INVOKEVIRTUAL));
                il.append(new ALOAD(4));
                il.append(ih);
                if( fieldType == Type.BOOLEAN )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getBoolean",
                        Type.BOOLEAN,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else if( fieldType == Type.BYTE )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getByte",
                        Type.BYTE,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else if( fieldType == Type.CHAR )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getChar",
                        Type.CHAR,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else if( fieldType == Type.DOUBLE )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getDouble",
                        Type.DOUBLE,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else if( fieldType == Type.FLOAT )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getFloat",
                        Type.FLOAT,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else if( fieldType == Type.INT )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getInt",
                        Type.INT,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else if( fieldType == Type.LONG )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getLong",
                        Type.LONG,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else if( fieldType == Type.SHORT )
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "getShort",
                        Type.SHORT,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                }
                else
                {
                    il.append(factory.createInvoke(
                        "java.lang.reflect.Field",
                        "get",
                        Type.OBJECT,
                        new Type[] { Type.OBJECT },
                        Constants.INVOKEVIRTUAL));
                    il.append(factory.createCast(Type.OBJECT, fieldType));
                }
            }
        }
    }

    /**
     * Retrieve the field modifiers for the given class
     * @param className
     * @param fieldName
     * @return
     */
    private int getModifiers(String className, String fieldName)
    {
        JavaClass javaClass;
        try
        {
            javaClass = Repository.getRepository().loadClass(className);
            for( int i=0; i<javaClass.getFields().length; i++)
            {
                if( fieldName.equals(javaClass.getFields()[i].getName()) )
                {
                    return javaClass.getFields()[i].getModifiers();
                }
            }
        }
        catch (ClassNotFoundException e)
        {
            //ignore
        }
        return -1;
    }
}
TOP

Related Classes of org.jpox.enhancer.bcel.method.JdoCopyKeyFieldsFromObjectId

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.