/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */
package org.apache.openjpa.enhance;

import java.io.Externalizable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.meta.ClassArgParser;
import org.apache.openjpa.lib.util.BytecodeWriter;
import org.apache.openjpa.lib.util.ClassUtil;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.Localizer.Message;
import org.apache.openjpa.lib.util.Options;
import org.apache.openjpa.lib.util.Services;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.lib.util.git.GitUtils;
import org.apache.openjpa.meta.AccessCode;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataModes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.ValueStrategies;
import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.BigDecimalId;
import org.apache.openjpa.util.BigIntegerId;
import org.apache.openjpa.util.ByteId;
import org.apache.openjpa.util.CharId;
import org.apache.openjpa.util.DateId;
import org.apache.openjpa.util.DoubleId;
import org.apache.openjpa.util.FloatId;
import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.Id;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.IntId;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.LongId;
import org.apache.openjpa.util.ObjectId;
import org.apache.openjpa.util.OpenJPAException;
import org.apache.openjpa.util.ShortId;
import org.apache.openjpa.util.StringId;
import org.apache.openjpa.util.UserException;

import serp.bytecode.BCClass;
import serp.bytecode.BCField;
import serp.bytecode.BCMethod;
import serp.bytecode.ClassInstruction;
import serp.bytecode.Code;
import serp.bytecode.Constants;
import serp.bytecode.Exceptions;
import serp.bytecode.FieldInstruction;
import serp.bytecode.GetFieldInstruction;
import serp.bytecode.IfInstruction;
import serp.bytecode.Instruction;
import serp.bytecode.JumpInstruction;
import serp.bytecode.LoadInstruction;
import serp.bytecode.LookupSwitchInstruction;
import serp.bytecode.MethodInstruction;
import serp.bytecode.Project;
import serp.bytecode.PutFieldInstruction;
import serp.bytecode.TableSwitchInstruction;

/**
 * Bytecode enhancer used to enhance persistent classes from metadata. The
 * enhancer must be invoked on all persistence-capable and persistence aware
 * classes.
 *
 * @author Abe White
 */
public class PCEnhancer {
    // Designates a version for maintaining compatbility when PCEnhancer
    // modifies enhancement that can break serialization or other contracts
    // Each enhanced class will return the value of this field via
    // public int getEnhancementContractVersion()
    public static final int ENHANCER_VERSION;

    boolean _addVersionInitFlag = true;

    public static final int ENHANCE_NONE = 0;
    public static final int ENHANCE_AWARE = 2 << 0;
    public static final int ENHANCE_INTERFACE = 2 << 1;
    public static final int ENHANCE_PC = 2 << 2;

    public static final String PRE = "pc";
    public static final String ISDETACHEDSTATEDEFINITIVE = PRE
        + "isDetachedStateDefinitive";

    private static final Class PCTYPE = PersistenceCapable.class;
    private static final String SM = PRE + "StateManager";
    private static final Class SMTYPE = StateManager.class;
    private static final String INHERIT = PRE + "InheritedFieldCount";
    private static final String CONTEXTNAME = "GenericContext";
    private static final Class USEREXCEP = UserException.class;
    private static final Class INTERNEXCEP = InternalException.class;
    private static final Class HELPERTYPE = PCRegistry.class;
    private static final String SUPER = PRE + "PCSuperclass";
    private static final Class OIDFSTYPE = FieldSupplier.class;
    private static final Class OIDFCTYPE = FieldConsumer.class;

    private static final String VERSION_INIT_STR =  PRE + "VersionInit";

    private static final Localizer _loc = Localizer.forPackage
        (PCEnhancer.class);
    private static final String REDEFINED_ATTRIBUTE
        = PCEnhancer.class.getName() + "#redefined-type";

    private static final AuxiliaryEnhancer[] _auxEnhancers;
    static {
        Class[] classes = Services.getImplementorClasses(
            AuxiliaryEnhancer.class,
            AccessController.doPrivileged(
                J2DoPrivHelper.getClassLoaderAction(AuxiliaryEnhancer.class)));
        List auxEnhancers = new ArrayList(classes.length);
        for (Class aClass : classes) {
            try {
                auxEnhancers.add(AccessController.doPrivileged(
                        J2DoPrivHelper.newInstanceAction(aClass)));
            }
            catch (Throwable t) {
                // aux enhancer may rely on non-existant spec classes, etc
            }
        }
        _auxEnhancers = (AuxiliaryEnhancer[]) auxEnhancers.toArray
        (new AuxiliaryEnhancer[auxEnhancers.size()]);

        int rev = 0;
        Properties revisionProps = new Properties();
        try {
            InputStream in = PCEnhancer.class.getResourceAsStream("/META-INF/org.apache.openjpa.revision.properties");
            if (in != null) {
                try {
                    revisionProps.load(in);
                } finally {
                    in.close();
                }
            }
            rev = GitUtils.convertGitInfoToPCEnhancerVersion(revisionProps.getProperty("openjpa.enhancer.revision"));
        } catch (Exception e) {
        }
        if (rev > 0) {
            ENHANCER_VERSION = rev;
        } else {
            // Something bad happened and we couldn't load from the properties file. We need to default to using the
            // value of 2 because that is the value that was the value as of rev.511998.
            ENHANCER_VERSION = 2;
        }
    }

    private BCClass _pc;
    private final BCClass _managedType;
    private final MetaDataRepository _repos;
    private final ClassMetaData _meta;
    private final Log _log;
    private Collection _oids = null;
    private boolean _defCons = true;
    private boolean _redefine = false;
    private boolean _subclass = false;
    private boolean _fail = false;
    private Set _violations = null;
    private File _dir = null;
    private BytecodeWriter _writer = null;
    private Map _backingFields = null; // map of set / get names => field names
    private Map _attrsToFields = null; // map of attr names => field names
    private Map _fieldsToAttrs = null; // map of field names => attr names
    private boolean _isAlreadyRedefined = false;
    private boolean _isAlreadySubclassed = false;
    private boolean _bcsConfigured = false;

    private boolean _optimizeIdCopy = false; // whether to attempt optimizing id copy

    /**
     * Constructor. Supply configuration and type to enhance. This will look
     * up the metadata for <code>type</code> from <code>conf</code>'s
     * repository.
     */
    public PCEnhancer(OpenJPAConfiguration conf, Class type) {
        this(conf, AccessController.doPrivileged(J2DoPrivHelper
            .loadProjectClassAction(new Project(), type)),
            (MetaDataRepository) null);
    }

    /**
     * Constructor. Supply configuration and type to enhance. This will look
     * up the metadata for <code>meta</code> by converting back to a class
     * and then loading from <code>conf</code>'s repository.
     */
    public PCEnhancer(OpenJPAConfiguration conf, ClassMetaData meta) {
        this(conf, AccessController.doPrivileged(J2DoPrivHelper
            .loadProjectClassAction(new Project(), meta.getDescribedType())),
            meta.getRepository());
    }

    /**
     * Constructor. Supply configuration.
     *
     * @param type the bytecode representation fo the type to
     * enhance; this can be created from any stream or file
     * @param repos a metadata repository to use for metadata access,
     * or null to create a new reporitory; the repository
     * from the given configuration isn't used by default
     * because the configuration might be an
     * implementation-specific subclass whose metadata
     * required more than just base metadata files
     * @deprecated use {@link #PCEnhancer(OpenJPAConfiguration, BCClass,
        MetaDataRepository, ClassLoader)} instead.
     */
    @Deprecated
    public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
        MetaDataRepository repos) {
        this(conf, type, repos, null);
    }

    /**
     * Constructor. Supply configuration.
     *
     * @param type the bytecode representation fo the type to
     * enhance; this can be created from any stream or file
     * @param repos a metadata repository to use for metadata access,
     * or null to create a new reporitory; the repository
     * from the given configuration isn't used by default
     * because the configuration might be an
     * implementation-specific subclass whose metadata
     * required more than just base metadata files
     * @param loader the environment classloader to use for loading
     * classes and resources.
     */
    public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
        MetaDataRepository repos, ClassLoader loader) {
        _managedType = type;
        _pc = type;

        _log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);

        if (repos == null) {
            _repos = conf.newMetaDataRepositoryInstance();
            _repos.setSourceMode(MetaDataModes.MODE_META);
        } else
            _repos = repos;
        _meta = _repos.getMetaData(type.getType(), loader, false);

        configureOptimizeIdCopy();
    }

    /**
     * Constructor. Supply repository. The repository's configuration will
     * be used, and the metadata passed in will be used as-is without doing
     * any additional lookups. This is useful when running the enhancer
     * during metadata load.
     *
     * @param repos a metadata repository to use for metadata access,
     * or null to create a new reporitory; the repository
     * from the given configuration isn't used by default
     * because the configuration might be an
     * implementation-specific subclass whose metadata
     * required more than just base metadata files
     * @param type the bytecode representation fo the type to
     * enhance; this can be created from any stream or file
     * @param meta the metadata to use for processing this type.
     *
     * @since 1.1.0
     */
    public PCEnhancer(MetaDataRepository repos, BCClass type,
        ClassMetaData meta) {
        _managedType = type;
        _pc = type;

        _log = repos.getConfiguration()
            .getLog(OpenJPAConfiguration.LOG_ENHANCE);

        _repos = repos;
        _meta = meta;
    }

    static String toPCSubclassName(Class cls) {
        return ClassUtil.getPackageName(PCEnhancer.class) + "."
            + cls.getName().replace('.', '$') + "$pcsubclass";
    }

    /**
     * Whether or not <code>className</code> is the name for a
     * dynamically-created persistence-capable subclass.
     *
     * @since 1.1.0
     */
    public static boolean isPCSubclassName(String className) {
        return className.startsWith(ClassUtil.getPackageName(PCEnhancer.class))
            && className.endsWith("$pcsubclass");
    }

    /**
     * If <code>className</code> is a dynamically-created persistence-capable
     * subclass name, returns the name of the class that it subclasses.
     * Otherwise, returns <code>className</code>.
     *
     * @since 1.1.0
     */
    public static String toManagedTypeName(String className) {
        if (isPCSubclassName(className)) {
            className = className.substring(
                ClassUtil.getPackageName(PCEnhancer.class).length() + 1);
            className = className.substring(0, className.lastIndexOf("$"));
            // this is not correct for nested PCs
            className = className.replace('$', '.');
        }

        return className;
    }

    /**
     * Constructor. Supply configuration, type, and metadata.
     */
    public PCEnhancer(OpenJPAConfiguration conf, BCClass type,
        ClassMetaData meta) {
        this(conf, type, meta.getRepository());
    }

    /**
     * Return the bytecode representation of the persistence-capable class
     * being manipulated.
     */
    public BCClass getPCBytecode() {
        return _pc;
    }

    /**
     * Return the bytecode representation of the managed class being
     * manipulated. This is usually the same as {@link #getPCBytecode},
     * except when running the enhancer to redefine and subclass
     * existing persistent types.
     */
    public BCClass getManagedTypeBytecode() {
        return _managedType;
    }

    /**
     * Return the metadata for the class being manipulated, or null if not
     * a persistent type.
     */
    public ClassMetaData getMetaData() {
        return _meta;
    }

    /**
     * A boolean indicating whether the enhancer should add a no-args
     * constructor if one is not already present in the class. OpenJPA
     * requires that a no-arg constructor (whether created by the compiler
     * or by the user) be present in a PC.
     */
    public boolean getAddDefaultConstructor() {
        return _defCons;
    }

    /**
     * A boolean indicating whether the enhancer should add a no-args
     * constructor if one is not already present in the class. OpenJPA
     * requires that a no-arg constructor (whether created by the compiler
     * or by the user) be present in a PC.
     */
    public void setAddDefaultConstructor(boolean addDefaultConstructor) {
        _defCons = addDefaultConstructor;
    }

    /**
     * Whether the enhancer should mutate its arguments, or just run validation
     * and optional subclassing logic on them. Usually used in conjunction with
     * <code>setCreateSubclass(true)</code>.
     *
     * @since 1.0.0
     */
    public boolean getRedefine() {
        return _redefine;
    }

    /**
     * Whether the enhancer should mutate its arguments, or just run validation
     * and optional subclassing logic on them. Usually used in conjunction with
     * <code>setCreateSubclass(true)</code>.
     *
     * @since 1.0.0
     */
    public void setRedefine(boolean redefine) {
        _redefine = redefine;
    }

    /**
     * Whether the type that this instance is enhancing has already been
     * redefined.
     *
     * @since 1.0.0
     */
    public boolean isAlreadyRedefined() {
        return _isAlreadyRedefined;
    }

    /**
     * Whether the type that this instance is enhancing has already been
     * subclassed in this instance's environment classloader.
     *
     * @since 1.0.0
     */
    public boolean isAlreadySubclassed() {
        return _isAlreadySubclassed;
    }

    /**
     * Whether the enhancer should make its arguments persistence-capable,
     * or generate a persistence-capable subclass.
     *
     * @since 1.0.0
     */
    public boolean getCreateSubclass() {
        return _subclass;
    }

    /**
     * Whether the enhancer should make its arguments persistence-capable,
     * or generate a persistence-capable subclass.
     *
     * @since 1.0.0
     */
    public void setCreateSubclass(boolean subclass) {
        _subclass = subclass;
        _addVersionInitFlag = false;
    }

    /**
     * Whether to fail if the persistent type uses property access and
     * bytecode analysis shows that it may be violating OpenJPA's property
     * access restrictions.
     */
    public boolean getEnforcePropertyRestrictions() {
        return _fail;
    }

    /**
     * Whether to fail if the persistent type uses property access and
     * bytecode analysis shows that it may be violating OpenJPA's property
     * access restrictions.
     */
    public void setEnforcePropertyRestrictions(boolean fail) {
        _fail = fail;
    }

    /**
     * The base build directory to generate code to. The proper package
     * structure will be created beneath this directory. Defaults to
     * overwriting the existing class file if null.
     */
    public File getDirectory() {
        return _dir;
    }

    /**
     * The base build directory to generate code to. The proper package
     * structure will be creaed beneath this directory. Defaults to
     * overwriting the existing class file if null.
     */
    public void setDirectory(File dir) {
        _dir = dir;
    }

    /**
     * Return the current {@link BytecodeWriter} to write to or null if none.
     */
    public BytecodeWriter getBytecodeWriter() {
        return _writer;
    }

    /**
     * Set the {@link BytecodeWriter} to write the bytecode to or null if none.
     */
    public void setBytecodeWriter(BytecodeWriter writer) {
        _writer = writer;
    }

    /**
     * Perform bytecode enhancements.
     *
     * @return <code>ENHANCE_*</code> constant
     */
    public int run() {
        Class<?> type = _managedType.getType();
        try {
            // if enum, skip, no need of any meta
            if (_pc.isEnum())
                return ENHANCE_NONE;

            // if managed interface, skip
            if (_pc.isInterface())
                return ENHANCE_INTERFACE;

            // check if already enhanced
            ClassLoader loader = AccessController.doPrivileged(J2DoPrivHelper.getClassLoaderAction(type));
            for (String iface : _managedType.getDeclaredInterfaceNames()) {
                if (iface.equals(PCTYPE.getName())) {
                    if (_log.isTraceEnabled()) {
                        _log.trace(_loc.get("pc-type", type, loader));
                    }
                    return ENHANCE_NONE;
                }
            }
            if (_log.isTraceEnabled()) {
                _log.trace(_loc.get("enhance-start", type, loader));
            }


            configureBCs();

            // validate properties before replacing field access so that
            // we build up a record of backing fields, etc
            if (isPropertyAccess(_meta)) {
                validateProperties();
                if (getCreateSubclass())
                    addAttributeTranslation();
            }
            replaceAndValidateFieldAccess();
            processViolations();

            if (_meta != null) {
                enhanceClass();
                addFields();
                addStaticInitializer();
                addPCMethods();
                addAccessors();
                addAttachDetachCode();
                addSerializationCode();
                addCloningCode();
                runAuxiliaryEnhancers();
                return ENHANCE_PC;
            }
            return ENHANCE_AWARE;
        } catch (OpenJPAException ke) {
            throw ke;
        } catch (Exception e) {
            throw new GeneralException(_loc.get("enhance-error",
                type.getName(), e.getMessage()), e);
        }
    }

    private void configureBCs() {
        if (!_bcsConfigured) {
            if (getRedefine()) {
                if (_managedType.getAttribute(REDEFINED_ATTRIBUTE) == null)
                    _managedType.addAttribute(REDEFINED_ATTRIBUTE);
                else
                    _isAlreadyRedefined = true;
            }

            if (getCreateSubclass()) {
                PCSubclassValidator val = new PCSubclassValidator(
                    _meta, _managedType, _log, _fail);
                val.assertCanSubclass();

                _pc = _managedType.getProject().loadClass(
                    toPCSubclassName(_managedType.getType()));
                if (_pc.getSuperclassBC() != _managedType) {
                    _pc.setSuperclass(_managedType);
                    _pc.setAbstract(_managedType.isAbstract());
                    _pc.declareInterface(DynamicPersistenceCapable.class);
                } else {
                    _isAlreadySubclassed = true;
                }
            }

            _bcsConfigured = true;
        }
    }

    /**
     * Write the generated bytecode.
     */
    public void record()
        throws IOException {
        if (_managedType != _pc && getRedefine())
            record(_managedType);
        record(_pc);
        if (_oids != null)
            for (Object oid : _oids) {
                record((BCClass) oid);
            }
    }

    /**
     * Write the given class.
     */
    private void record(BCClass bc)
        throws IOException {
        if (_writer != null)
            _writer.write(bc);
        else if (_dir == null)
            AsmAdaptor.write(bc);
        else {
            File dir = Files.getPackageFile(_dir, bc.getPackageName(), true);
            AsmAdaptor.write(bc, new File(dir, bc.getClassName() + ".class"));
        }
    }

    /**
     * Validate that the methods that use a property-access instance are
     * written correctly. This method also gathers information on each
     * property's backing field.
     */
    private void validateProperties() {
        FieldMetaData[] fmds;
        if (getCreateSubclass())
            fmds = _meta.getFields();
        else
            fmds = _meta.getDeclaredFields();
        Method meth;
        BCMethod getter, setter;
        BCField returned, assigned = null;
        for (FieldMetaData fmd : fmds) {

            if (!(fmd.getBackingMember() instanceof Method)) {
                // If not mixed access is not defined, flag the field members,
                // otherwise do not process them because they are valid
                // persistent attributes.
                if (!_meta.isMixedAccess()) {
                    addViolation("property-bad-member",
                            new Object[]{fmd, fmd.getBackingMember()},
                            true);
                }
                continue;
            }

            meth = (Method) fmd.getBackingMember();
            // ##### this will fail if we override and don't call super.
            BCClass declaringType = _managedType.getProject()
                    .loadClass(fmd.getDeclaringType());
            getter = declaringType.getDeclaredMethod(meth.getName(),
                    meth.getParameterTypes());
            if (getter == null) {
                addViolation("property-no-getter", new Object[]{fmd},
                        true);
                continue;
            }
            returned = getReturnedField(getter);
            if (returned != null)
                registerBackingFieldInfo(fmd, getter, returned);

            setter = declaringType.getDeclaredMethod(getSetterName(fmd),
                    new Class[]{fmd.getDeclaredType()});
            if (setter == null) {
                if (returned == null) {
                    addViolation("property-no-setter",
                            new Object[]{fmd}, true);
                    continue;
                }
                else if (!getRedefine()) {
                    // create synthetic setter
                    setter = _managedType.declareMethod(getSetterName(fmd),
                            void.class, new Class[]{fmd.getDeclaredType()});
                    setter.makePrivate();
                    Code code = setter.getCode(true);
                    code.aload().setThis();
                    code.xload().setParam(0);
                    code.putfield().setField(returned);
                    code.vreturn();
                    code.calculateMaxStack();
                    code.calculateMaxLocals();
                }
            }

            if (setter != null)
                assigned = getAssignedField(setter);

            if (assigned != null) {
                if (setter != null)
                    registerBackingFieldInfo(fmd, setter, assigned);

                if (assigned != returned)
                    addViolation("property-setter-getter-mismatch", new Object[]
                            {fmd, assigned.getName(), (returned == null)
                                    ? null : returned.getName()}, false);
            }
        }
    }

    private void registerBackingFieldInfo(FieldMetaData fmd, BCMethod method,
        BCField field) {
        if (_backingFields == null)
            _backingFields = new HashMap();
        _backingFields.put(method.getName(), field.getName());

        if (_attrsToFields == null)
            _attrsToFields = new HashMap();
        _attrsToFields.put(fmd.getName(), field.getName());

        if (_fieldsToAttrs == null)
            _fieldsToAttrs = new HashMap();
        _fieldsToAttrs.put(field.getName(), fmd.getName());
    }

    private void addAttributeTranslation() {

        // Get all field metadata
        ArrayList<Integer> propFmds = new ArrayList<>();
        FieldMetaData[] fmds = _meta.getFields();

        if (_meta.isMixedAccess()) {
            // Stores indexes of property access fields to be used in
            //
            propFmds = new ArrayList<>();

            // Determine which fields have property access and save their
            // indexes
            for (int i = 0; i < fmds.length; i++) {
                if (isPropertyAccess(fmds[i]))
                    propFmds.add(i);
            }

            // if no fields have property access do not do attribute translation
            if (propFmds.size() == 0)
                return;
        }

        _pc.declareInterface(AttributeTranslator.class);
        BCMethod method = _pc.declareMethod(PRE + "AttributeIndexToFieldName",
            String.class, new Class[] { int.class });
        method.makePublic();
        Code code = method.getCode(true);

        // switch (val)
        code.iload().setParam(0);
        if (!_meta.isMixedAccess()) {
            // if not mixed access use a table switch on all property-based fmd.
            // a table switch is more efficient with +1 incremental operations
            TableSwitchInstruction tabins = code.tableswitch();

            tabins.setLow(0);
            tabins.setHigh(fmds.length - 1);

            // case i:
            //     return <_attrsToFields.get(fmds[i].getName())>
            for (FieldMetaData fmd : fmds) {
                tabins.addTarget(code.constant().setValue(
                        _attrsToFields.get(fmd.getName())));
                code.areturn();
            }
            // default: throw new IllegalArgumentException ()
            tabins.setDefaultTarget(throwException
                (code, IllegalArgumentException.class));
        }
        else {
            // In mixed access mode, property indexes are not +1 incremental
            // a lookup switch must be used to do indexed lookup.
            LookupSwitchInstruction lookupins = code.lookupswitch();

            for (Integer i : propFmds) {
                lookupins.addCase(i,
                    code.constant().setValue(
                    _attrsToFields.get(fmds[i].getName())));
                code.areturn();
            }
            // default: throw new IllegalArgumentException ()
            lookupins.setDefaultTarget(throwException
                (code, IllegalArgumentException.class));
        }

        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    /**
     * Return the name of the setter method for the given field.
     */
    private static String getSetterName(FieldMetaData fmd) {
        return fmd.getSetterName();
    }

    /**
     * Return the field returned by the given method, or null if none.
     * Package-protected and static for testing.
     */
    static BCField getReturnedField(BCMethod meth) {
        return findField(meth, (AccessController.doPrivileged(
            J2DoPrivHelper.newCodeAction())).xreturn()
            .setType(meth.getReturnType()), false);
    }

    /**
     * Return the field assigned in the given method, or null if none.
     * Package-protected and static for testing.
     */
    static BCField getAssignedField(BCMethod meth) {
        return findField(meth, (AccessController.doPrivileged(
            J2DoPrivHelper.newCodeAction())).putfield(), true);
    }

    /**
     * Return the field returned / assigned by <code>meth</code>. Returns
     * null if non-fields (methods, literals, parameters, variables) are
     * returned, or if non-parameters are assigned to fields.
     */
    private static BCField findField(BCMethod meth, Instruction template,
        boolean findAccessed) {
        // ignore any static methods. OpenJPA only currently supports
        // non-static setters and getters
        if (meth.isStatic())
            return null;

        Code code = meth.getCode(false);
        if (code == null)
            return null;
        code.beforeFirst();

        BCField field = null, cur;
        Instruction templateIns, prevIns, earlierIns;
        while (code.searchForward(template)) {
            int backupCount = 3;
            templateIns = code.previous();
            if (!code.hasPrevious())
                return null;
            prevIns = code.previous();

            if (prevIns instanceof ClassInstruction
                && code.hasPrevious()) {
                prevIns = code.previous();
                backupCount++;
            }

            if (!code.hasPrevious())
                return null;
            earlierIns = code.previous();

            // if the opcode two before the template was an aload_0, check
            // against the middle instruction based on what type of find
            // we're doing
            if (!(earlierIns instanceof LoadInstruction)
                || !((LoadInstruction) earlierIns).isThis())
                return null;

            // if the middle instruction was a getfield, then it's the
            // field that's being accessed
            if (!findAccessed && prevIns instanceof GetFieldInstruction) {
                final FieldInstruction fPrevIns = (FieldInstruction) prevIns;
                cur = AccessController.doPrivileged(
                    J2DoPrivHelper.getFieldInstructionFieldAction(fPrevIns));
                // if the middle instruction was an xload_1, then the
                // matched instruction is the field that's being set.
            } else if (findAccessed && prevIns instanceof LoadInstruction
                && ((LoadInstruction) prevIns).getParam() == 0) {
                final FieldInstruction fTemplateIns =
                    (FieldInstruction) templateIns;
                cur = AccessController.doPrivileged(J2DoPrivHelper
                    .getFieldInstructionFieldAction(fTemplateIns));
            } else
                return null;

            if (field != null && cur != field)
                return null;
            field = cur;

            // ready for next search iteration
            while (backupCount > 0) {
                code.next();
                backupCount--;
            }
        }
        return field;
    }

    /**
     * Record a violation of the property access restrictions.
     */
    private void addViolation(String key, Object[] args, boolean fatal) {
        if (_violations == null)
            _violations = new HashSet();
        _violations.add(_loc.get(key, args));
        _fail |= fatal;
    }

    /**
     * Log / throw recorded property access violations.
     */
    private void processViolations() {
        if (_violations == null)
            return;

        String sep = J2DoPrivHelper.getLineSeparator();
        StringBuilder buf = new StringBuilder();
        for (Iterator itr = _violations.iterator(); itr.hasNext();) {
            buf.append(itr.next());
            if (itr.hasNext())
                buf.append(sep);
        }
        Message msg = _loc.get("property-violations", buf);

        if (_fail)
            throw new UserException(msg);
        if (_log.isWarnEnabled())
            _log.warn(msg);
    }

    /**
     * Replaced all direct access to managed fields with the appropriate
     * pcGet/pcSet method. Note that this includes access to fields
     * owned by PersistenceCapable classes other than this one.
     */
    private void replaceAndValidateFieldAccess() throws NoSuchMethodException {
        // create template putfield/getfield instructions to search for
        Code template = AccessController.doPrivileged(
            J2DoPrivHelper.newCodeAction());
        Instruction put = template.putfield();
        Instruction get = template.getfield();
        Instruction stat = template.invokestatic();

        // look through all methods; this is done before any methods are added
        // so we don't need to worry about excluding synthetic methods.
        BCMethod[] methods = _managedType.getDeclaredMethods();
        Code code;
        for (BCMethod method : methods) {
            code = method.getCode(false);

            // don't modify the methods specified by the auxiliary enhancers
            if (code != null && !skipEnhance(method)) {
                replaceAndValidateFieldAccess(code, get, true, stat);
                replaceAndValidateFieldAccess(code, put, false, stat);
            }
        }
    }

    /**
     * Replaces all instructions matching the given template in the given
     * code block with calls to the appropriate generated getter/setter.
     *
     * @param code the code block to modify; the code iterator will
     * be placed before the first instruction on method start,
     * and will be after the last instruction on method completion
     * @param ins the template instruction to search for; either a
     * getfield or putfield instruction
     * @param get boolean indicating if this is a get instruction
     * @param stat template invokestatic instruction to replace with
     */
    private void replaceAndValidateFieldAccess(Code code, Instruction ins,
        boolean get, Instruction stat) throws NoSuchMethodException {
        code.beforeFirst();

        FieldInstruction fi;
        MethodInstruction mi;
        ClassMetaData owner;
        String name, typeName, methodName;
        while (code.searchForward(ins)) {
            // back up to the matched instruction
            fi = (FieldInstruction) code.previous();
            name = fi.getFieldName();
            typeName = fi.getFieldTypeName();
            owner = getPersistenceCapableOwner(name, fi.getFieldDeclarerType());
            FieldMetaData fmd = owner == null ? null : owner.getField(name);
            if (isPropertyAccess(fmd)) {
                // if we're directly accessing a field in another class
                // hierarchy that uses property access, something is wrong
                if (owner != _meta && owner.getDeclaredField(name) != null &&
                    _meta != null && !owner.getDescribedType()
                        .isAssignableFrom(_meta.getDescribedType()))
                    throw new UserException(_loc.get("property-field-access",
                        new Object[]{ _meta, owner, name,
                            code.getMethod().getName() }));

                // if we're directly accessing a property-backing field outside
                // the property in our own class, notify user
                if (isBackingFieldOfAnotherProperty(name, code))
                    addViolation("property-field-access", new Object[]{ _meta,
                        owner, name, code.getMethod().getName() }, false);
            }

            if (owner == null ||
                owner.getDeclaredField(fromBackingFieldName(name)) == null) {
                // not persistent field?
                code.next();
                continue;
            } else if (!getRedefine() && !getCreateSubclass()
                && isFieldAccess(fmd)) {
                // replace the instruction with a call to the generated access
                // method
                mi = (MethodInstruction) code.set(stat);

                // invoke the proper access method, whether getter or setter
                String prefix = (get) ? PRE + "Get" : PRE + "Set";
                methodName = prefix + name;
                if (get) {
                    mi.setMethod(getType(owner).getName(),
                        methodName, typeName, new String[]
                        { getType(owner).getName() });
                } else {
                    mi.setMethod(getType(owner).getName(),
                        methodName, "void", new String[]
                        { getType(owner).getName(), typeName });
                }
                code.next();
            } else if (getRedefine()) {
                name = fromBackingFieldName(name);
                if (get) {
                    addNotifyAccess(code, owner.getField(name));
                    code.next();
                } else {
                    // insert the set operations after the field mutation, but
                    // first load the old value for use in the
                    // StateManager.settingXXX method.
                    loadManagedInstance(code, false);
                    final FieldInstruction fFi = fi;
                    code.getfield().setField(
                        AccessController.doPrivileged(J2DoPrivHelper
                            .getFieldInstructionFieldAction(fFi)));
                    int val = code.getNextLocalsIndex();
                    code.xstore().setLocal(val).setType(fi.getFieldType());

                    // move past the putfield
                    code.next();
                    addNotifyMutation(code, owner.getField(name), val, -1);
                }
            } else {
                code.next();
            }
            code.calculateMaxLocals();
            code.calculateMaxStack();
        }
    }

    private void addNotifyAccess(Code code, FieldMetaData fmd) {
        // PCHelper.accessingField(this, <absolute-index>);
        code.aload().setThis();
        code.constant().setValue(fmd.getIndex());
        code.invokestatic().setMethod(RedefinitionHelper.class,
            "accessingField", void.class,
            new Class[] { Object.class, int.class });
    }

    /**
     * This must be called after setting the value in the object.
     *
     * @param val the position in the local variable table where the
     * old value is stored
     * @param param the parameter position containing the new value, or
     * -1 if the new value is unavailable and should therefore be looked
     * up.
     * @throws NoSuchMethodException
     */
    private void addNotifyMutation(Code code, FieldMetaData fmd, int val,
        int param)
        throws NoSuchMethodException {
        // PCHelper.settingField(this, <absolute-index>, old, new);
        code.aload().setThis();
        code.constant().setValue(fmd.getIndex());
        Class type = fmd.getDeclaredType();
        // we only have special signatures for primitives and Strings
        if (!type.isPrimitive() && type != String.class)
            type = Object.class;
        code.xload().setLocal(val).setType(type);
        if (param == -1) {
            loadManagedInstance(code, false);
            addGetManagedValueCode(code, fmd);
        } else {
            code.xload().setParam(param).setType(type);
        }
        code.invokestatic().setMethod(RedefinitionHelper.class, "settingField",
            void.class, new Class[] {
                Object.class, int.class, type, type
        });
    }

    /**
     * Return true if the given instruction accesses a field that is a backing
     * field of another property in this property-access class.
     */
    private boolean isBackingFieldOfAnotherProperty(String name, Code code) {
        String methName = code.getMethod().getName();
        return !"<init>".equals(methName)
            && _backingFields != null
            && !name.equals(_backingFields.get(methName))
            && _backingFields.containsValue(name);
    }

    /**
     * Helper method to return the declaring PersistenceCapable class of
     * the given field.
     *
     * @param fieldName the name of the field
     * @param owner the nominal owner of the field
     * @return the metadata for the PersistenceCapable type that
     * declares the field (and therefore has the static method), or null if none
     */
    private ClassMetaData getPersistenceCapableOwner(String fieldName,
        Class owner) {
        // find the actual ancestor class that declares the field, then
        // check if the class is persistent, and if the field is managed
        Field f = Reflection.findField(owner, fieldName, false);
        if (f == null)
            return null;

        // managed interface
        if (_meta != null && _meta.getDescribedType().isInterface())
            return _meta;

        return _repos.getMetaData(f.getDeclaringClass(), null, false);
    }

    /**
     * Adds all synthetic methods to the bytecode by delegating to
     * the various addXXXMethods () functions in this class. Includes
     * all static field access methods.
     * Note that the 'stock' methods like <code>pcIsTransactional</code>,
     * <code>pcFetchObjectId</code>, etc are defined only in the
     * least-derived PersistenceCapable type.
     */
    private void addPCMethods()
        throws NoSuchMethodException {
        addClearFieldsMethod();
        addNewInstanceMethod(true);
        addNewInstanceMethod(false);
        addManagedFieldCountMethod();
        addReplaceFieldsMethods();
        addProvideFieldsMethods();
        addCopyFieldsMethod();

        if (_meta.getPCSuperclass() == null || getCreateSubclass()) {
            addStockMethods();
            addGetVersionMethod();
            addReplaceStateManagerMethod();

            if (_meta.getIdentityType() != ClassMetaData.ID_APPLICATION)
                addNoOpApplicationIdentityMethods();
        }

        // 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
        // persistent class inheritance hierarchy
        if (_meta.getIdentityType() == ClassMetaData.ID_APPLICATION
            && (_meta.getPCSuperclass() == null || getCreateSubclass() ||
                _meta.getObjectIdType() !=
                    _meta.getPCSuperclassMetaData().getObjectIdType())) {
            addCopyKeyFieldsToObjectIdMethod(true);
            addCopyKeyFieldsToObjectIdMethod(false);
            addCopyKeyFieldsFromObjectIdMethod(true);
            addCopyKeyFieldsFromObjectIdMethod(false);
            if (_meta.hasAbstractPKField()) {
                addGetIDOwningClass();
            }

            if (_meta.isEmbeddable() && _meta.getIdentityType() == ClassMetaData.ID_APPLICATION) {
                _log.warn(_loc.get("ID-field-in-embeddable-unsupported", _meta.toString()));
            }

            addNewObjectIdInstanceMethod(true);
            addNewObjectIdInstanceMethod(false);
        }
        else if (_meta.hasPKFieldsFromAbstractClass()){
            addGetIDOwningClass();
        }
    }

    /**
     * Add a method to clear all persistent fields; we'll call this from
     * the new instance method to ensure that unloaded fields have
     * default values.
     */
    private void addClearFieldsMethod()
        throws NoSuchMethodException {
        // protected void pcClearFields ()
        BCMethod method = _pc.declareMethod(PRE + "ClearFields", void.class,
            null);
        method.makeProtected();
        Code code = method.getCode(true);

        // super.pcClearFields ()
        if (_meta.getPCSuperclass() != null && !getCreateSubclass()) {
            code.aload().setThis();
            code.invokespecial().setMethod(getType(_meta.
                getPCSuperclassMetaData()), PRE + "ClearFields", void.class,
                null);
        }

        FieldMetaData[] fmds = _meta.getDeclaredFields();
        for (FieldMetaData fmd : fmds) {
            if (fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT)
                continue;

            loadManagedInstance(code, false);
            switch (fmd.getDeclaredTypeCode()) {
                case JavaTypes.BOOLEAN:
                case JavaTypes.BYTE:
                case JavaTypes.CHAR:
                case JavaTypes.INT:
                case JavaTypes.SHORT:
                    code.constant().setValue(0);
                    break;
                case JavaTypes.DOUBLE:
                    code.constant().setValue(0D);
                    break;
                case JavaTypes.FLOAT:
                    code.constant().setValue(0F);
                    break;
                case JavaTypes.LONG:
                    code.constant().setValue(0L);
                    break;
                default:
                    code.constant().setNull();
                    break;
            }

            addSetManagedValueCode(code, fmd);
        }

        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds the <code>pcNewInstance</code> method to the bytecode.
     * These methods are used by the impl helper to create new
     * managed instances efficiently without reflection.
     *
     * @param oid set to true to mimic the method version that takes
     * an oid value as well as a state manager
     */
    private void addNewInstanceMethod(boolean oid) {
        // public PersistenceCapable pcNewInstance (...)
        Class[] args =
            (oid) ? new Class[]{ SMTYPE, Object.class, boolean.class }
                : new Class[]{ SMTYPE, boolean.class };
        BCMethod method = _pc.declareMethod(PRE + "NewInstance", PCTYPE, args);
        Code code = method.getCode(true);

        // if the type is abstract, throw a UserException
        if (_pc.isAbstract()) {
            throwException(code, USEREXCEP);

            code.calculateMaxStack();
            code.calculateMaxLocals();
            return;
        }

        // XXX pc = new XXX ();
        code.anew().setType(_pc);
        code.dup();
        code.invokespecial().setMethod("<init>", void.class, null);
        int inst = code.getNextLocalsIndex();
        code.astore().setLocal(inst);

        // if (clear)
        //   pc.pcClearFields ();
        code.iload().setParam((oid) ? 2 : 1);
        JumpInstruction noclear = code.ifeq();
        code.aload().setLocal(inst);
        code.invokevirtual().setMethod(PRE + "ClearFields", void.class, null);

        // pc.pcStateManager = sm;
        noclear.setTarget(code.aload().setLocal(inst));
        code.aload().setParam(0);
        code.putfield().setField(SM, SMTYPE);

        // copy key fields from oid
        if (oid) {
            code.aload().setLocal(inst);
            code.aload().setParam(1);
            code.invokevirtual().setMethod(PRE + "CopyKeyFieldsFromObjectId",
                void.class, new Class[]{ Object.class });
        }

        // return pc;
        code.aload().setLocal(inst);
        code.areturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds the <code>protected static int pcGetManagedFieldCount ()</code>
     * method to the bytecode, returning the inherited field count added
     * to the number of managed fields in the current PersistenceCapable class.
     */
    private void addManagedFieldCountMethod() {
        // protected static int pcGetManagedFieldCount ()
        BCMethod method = _pc.declareMethod(PRE + "GetManagedFieldCount",
            int.class, null);
        method.setStatic(true);
        method.makeProtected();
        Code code = method.getCode(true);

        // return <fields> + pcInheritedFieldCount
        // awhite: the above should work, but I'm seeing a messed up situation
        // all of a sudden where when a subclass calls this method, it somehow
        // happens before <clinit> is ever invoked, and so our
        // pcInheritedFieldCount field isn't initialized!  so instead,
        // return <fields> + <superclass>.pcGetManagedFieldCount ()
        code.constant().setValue(_meta.getDeclaredFields().length);
        if (_meta.getPCSuperclass() != null) {
            Class superClass = getType(_meta.getPCSuperclassMetaData());
            String superName = getCreateSubclass() ?
                PCEnhancer.toPCSubclassName(superClass) :
                superClass.getName();
            code.invokestatic().setMethod(superName,
                PRE + "GetManagedFieldCount", int.class.getName(), null);
            code.iadd();
        }
        code.ireturn();
        code.calculateMaxStack();
    }

    /**
     * Adds the {@link PersistenceCapable#pcProvideField} and
     * {@link PersistenceCapable#pcProvideFields} methods to the bytecode.
     */
    private void addProvideFieldsMethods()
        throws NoSuchMethodException {
        // public void pcProvideField (int fieldNumber)
        BCMethod method = _pc.declareMethod(PRE + "ProvideField", void.class,
            new Class[]{ int.class });
        Code code = method.getCode(true);

        // adds everything through the switch ()
        int relLocal = beginSwitchMethod(PRE + "ProvideField", code);

        // if no fields in this inst, just throw exception
        FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
            : _meta.getDeclaredFields();
        if (fmds.length == 0)
            throwException(code, IllegalArgumentException.class);
        else {
            // switch (val)
            code.iload().setLocal(relLocal);
            TableSwitchInstruction tabins = code.tableswitch();
            tabins.setLow(0);
            tabins.setHigh(fmds.length - 1);

            // <field> = pcStateManager.provided<type>Field
            //     (this, fieldNumber);
            for (FieldMetaData fmd : fmds) {
                tabins.addTarget(loadManagedInstance(code, false));
                code.getfield().setField(SM, SMTYPE);
                loadManagedInstance(code, false);
                code.iload().setParam(0);
                loadManagedInstance(code, false);
                addGetManagedValueCode(code, fmd);
                code.invokeinterface().setMethod(getStateManagerMethod
                        (fmd.getDeclaredType(), "provided", false, false));
                code.vreturn();
            }

            // default: throw new IllegalArgumentException ()
            tabins.setDefaultTarget(throwException
                (code, IllegalArgumentException.class));
        }

        code.calculateMaxStack();
        code.calculateMaxLocals();

        addMultipleFieldsMethodVersion(method);
    }

    /**
     * Adds the {@link PersistenceCapable#pcReplaceField} and
     * {@link PersistenceCapable#pcReplaceFields} methods to the bytecode.
     */
    private void addReplaceFieldsMethods()
        throws NoSuchMethodException {
        // public void pcReplaceField (int fieldNumber)
        BCMethod method = _pc.declareMethod(PRE + "ReplaceField", void.class,
            new Class[]{ int.class });
        Code code = method.getCode(true);

        // adds everything through the switch ()
        int relLocal = beginSwitchMethod(PRE + "ReplaceField", code);

        // if no fields in this inst, just throw exception
        FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
            : _meta.getDeclaredFields();
        if (fmds.length == 0)
            throwException(code, IllegalArgumentException.class);
        else {
            // switch (val)
            code.iload().setLocal(relLocal);
            TableSwitchInstruction tabins = code.tableswitch();
            tabins.setLow(0);
            tabins.setHigh(fmds.length - 1);

            // <field> = pcStateManager.replace<type>Field
            //  (this, fieldNumber);
            for (FieldMetaData fmd : fmds) {
                // for the addSetManagedValueCode call below.
                tabins.addTarget(loadManagedInstance(code, false, fmd));

                loadManagedInstance(code, false, fmd);
                code.getfield().setField(SM, SMTYPE);
                loadManagedInstance(code, false, fmd);
                code.iload().setParam(0);
                code.invokeinterface().setMethod(getStateManagerMethod
                        (fmd.getDeclaredType(), "replace", true, false));
                if (!fmd.getDeclaredType().isPrimitive())
                    code.checkcast().setType(fmd.getDeclaredType());

                addSetManagedValueCode(code, fmd);
                if (_addVersionInitFlag) {
                    if (fmd.isVersion()) {
                        // If this case is setting the version field
                        // pcVersionInit = true;
                        loadManagedInstance(code, false);
                        code.constant().setValue(1);
                        putfield(code, null, VERSION_INIT_STR, boolean.class);
                    }
                }
                code.vreturn();
            }

            // default: throw new IllegalArgumentException ()
            tabins.setDefaultTarget(throwException
                (code, IllegalArgumentException.class));
        }

        code.calculateMaxStack();
        code.calculateMaxLocals();

        addMultipleFieldsMethodVersion(method);
    }

    /**
     * Adds the {@link PersistenceCapable#pcCopyFields} method to the bytecode.
     */
    private void addCopyFieldsMethod()
        throws NoSuchMethodException {
        // public void pcCopyField (Object pc, int field)
        BCMethod method = _pc.declareMethod(PRE + "CopyField",
            void.class.getName(),
            new String[]{ _managedType.getName(), int.class.getName() });
        method.makeProtected();
        Code code = method.getCode(true);

        // adds everything through the switch ()
        int relLocal = beginSwitchMethod(PRE + "CopyField", code);

        // if no fields in this inst, just throw exception
        FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
            : _meta.getDeclaredFields();
        if (fmds.length == 0)
            throwException(code, IllegalArgumentException.class);
        else {
            // switch (val)
            code.iload().setLocal(relLocal);
            TableSwitchInstruction tabins = code.tableswitch();
            tabins.setLow(0);
            tabins.setHigh(fmds.length - 1);

            for (FieldMetaData fmd : fmds) {
                // <field> = other.<field>;
                // or set<field> (other.get<field>);
                tabins.addTarget(loadManagedInstance(code, false, fmd));
                code.aload().setParam(0);
                addGetManagedValueCode(code, fmd, false);
                addSetManagedValueCode(code, fmd);

                // break;
                code.vreturn();
            }

            // default: throw new IllegalArgumentException ()
            tabins.setDefaultTarget(throwException
                (code, IllegalArgumentException.class));
        }

        code.calculateMaxStack();
        code.calculateMaxLocals();

        addMultipleFieldsMethodVersion(method);
    }

    /**
     * Helper method to add the code common to the beginning of both the
     * pcReplaceField method and the pcProvideField method. This includes
     * calculating the relative field number of the desired field and calling
     * the superclass if necessary.
     *
     * @return the index in which the local variable holding the relative
     * field number is stored
     */
    private int beginSwitchMethod(String name, Code code) {
        boolean copy = (PRE + "CopyField").equals(name);
        int fieldNumber = (copy) ? 1 : 0;

        int relLocal = code.getNextLocalsIndex();
        if (getCreateSubclass()) {
            code.iload().setParam(fieldNumber);
            code.istore().setLocal(relLocal);
            return relLocal;
        }

        // int rel = fieldNumber - pcInheritedFieldCount
        code.iload().setParam(fieldNumber);
        code.getstatic().setField(INHERIT, int.class);
        code.isub();
        code.istore().setLocal(relLocal);
        code.iload().setLocal(relLocal);

        // super: if (rel < 0) super.pcReplaceField (fieldNumber); return;
        // no super: if (rel < 0) throw new IllegalArgumentException ();
        JumpInstruction ifins = code.ifge();
        if (_meta.getPCSuperclass() != null) {
            loadManagedInstance(code, false);
            String[] args;
            if (copy) {
                args = new String[]{ getType(_meta.getPCSuperclassMetaData()).
                    getName(), int.class.getName() };
                code.aload().setParam(0);
            } else
                args = new String[]{ int.class.getName() };
            code.iload().setParam(fieldNumber);
            code.invokespecial().setMethod(getType(_meta.
                getPCSuperclassMetaData()).getName(), name,
                void.class.getName(), args);
            code.vreturn();
        } else
            throwException(code, IllegalArgumentException.class);

        ifins.setTarget(code.nop());
        return relLocal;
    }

    /**
     * This helper method, given the pcReplaceField or pcProvideField
     * method, adds the bytecode for the corresponding 'plural' version
     * of the method -- the version that takes an int[] of fields to
     * to access rather than a single field. The multiple fields version
     * simply loops through the provided indexes and delegates to the
     * singular version for each one.
     */
    private void addMultipleFieldsMethodVersion(BCMethod single) {
        boolean copy = (PRE + "CopyField").equals(single.getName());

        // public void <method>s (int[] fields)
        Class[] args = (copy) ? new Class[]{ Object.class, int[].class }
            : new Class[]{ int[].class };
        BCMethod method = _pc.declareMethod(single.getName() + "s",
            void.class, args);
        Code code = method.getCode(true);

        int fieldNumbers = 0;
        int inst = 0;
        if (copy) {
            fieldNumbers = 1;

            if (getCreateSubclass()) {
                // get the managed instance into the local variable table
                code.aload().setParam(0);
                code.invokestatic().setMethod(ImplHelper.class,
                    "getManagedInstance", Object.class,
                    new Class[] { Object.class });
                code.checkcast().setType(_managedType);
                inst = code.getNextLocalsIndex();
                code.astore().setLocal(inst);

                // there might be a difference between the classes of 'this'
                // vs 'other' in this context; use the PC methods to get the SM
                code.aload().setParam(0);
                code.aload().setThis();
                code.getfield().setField(SM, SMTYPE);
                code.invokestatic().setMethod(ImplHelper.class,
                    "toPersistenceCapable", PersistenceCapable.class,
                    new Class[] { Object.class, Object.class });
                code.invokeinterface().setMethod(PersistenceCapable.class,
                    "pcGetStateManager", StateManager.class, null);
            } else {
                // XXX other = (XXX) pc;
                code.aload().setParam(0);
                code.checkcast().setType(_pc);
                inst = code.getNextLocalsIndex();
                code.astore().setLocal(inst);

                // access the other's sm field directly
                code.aload().setLocal(inst);
                code.getfield().setField(SM, SMTYPE);
            }

            // if (other.pcStateManager != pcStateManager)
            //	throw new IllegalArgumentException

            loadManagedInstance(code, false);
            code.getfield().setField(SM, SMTYPE);
            JumpInstruction ifins = code.ifacmpeq();
            throwException(code, IllegalArgumentException.class);
            ifins.setTarget(code.nop());

            // if (pcStateManager == null)
            //  throw new IllegalStateException
            loadManagedInstance(code, false);
            code.getfield().setField(SM, SMTYPE);
            ifins = code.ifnonnull();
            throwException(code, IllegalStateException.class);
            ifins.setTarget(code.nop());
        }

        // for (int i = 0;
        code.constant().setValue(0);
        int idx = code.getNextLocalsIndex();
        code.istore().setLocal(idx);
        JumpInstruction testins = code.go2();

        // <method> (fields[i]);
        Instruction bodyins = loadManagedInstance(code, false);
        if (copy)
            code.aload().setLocal(inst);
        code.aload().setParam(fieldNumbers);
        code.iload().setLocal(idx);
        code.iaload();
        code.invokevirtual().setMethod(single);

        // i++;
        code.iinc().setIncrement(1).setLocal(idx);

        // i < fields.length
        testins.setTarget(code.iload().setLocal(idx));
        code.aload().setParam(fieldNumbers);
        code.arraylength();
        code.ificmplt().setTarget(bodyins);
        code.vreturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds the 'stock' methods to the bytecode; these include methods
     * like {@link PersistenceCapable#pcFetchObjectId}
     * and {@link PersistenceCapable#pcIsTransactional}.
     */
    private void addStockMethods()
        throws NoSuchMethodException {
        try {
            // pcGetGenericContext
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "get" + CONTEXTNAME, (Class[]) null)), false);

            // pcFetchObjectId
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "fetchObjectId", (Class[]) null)), false);

            // pcIsDeleted
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "isDeleted", (Class[]) null)), false);

            // pcIsDirty
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "isDirty", (Class[]) null)), true);

            // pcIsNew
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "isNew", (Class[]) null)), false);

            // pcIsPersistent
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "isPersistent", (Class[]) null)), false);

            // pcIsTransactional
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "isTransactional", (Class[]) null)), false);

            // pcSerializing
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "serializing", (Class[]) null)), false);

            // pcDirty
            translateFromStateManagerMethod(
                AccessController.doPrivileged(
                    J2DoPrivHelper.getDeclaredMethodAction(
                        SMTYPE, "dirty", new Class[]{ String.class })), false);

            // pcGetStateManager
            BCMethod meth = _pc.declareMethod(PRE + "GetStateManager",
                StateManager.class, null);
            Code code = meth.getCode(true);
            loadManagedInstance(code, false);
            code.getfield().setField(SM, StateManager.class);
            code.areturn();
            code.calculateMaxStack();
            code.calculateMaxLocals();
        } catch (PrivilegedActionException pae) {
             throw (NoSuchMethodException) pae.getException();
        }
    }

    /**
     * Helper method to add a stock method to the bytecode. Each
     * stock method simply delegates to a corresponding StateManager method.
     * Given the StateManager method, then, this function translates it into
     * the wrapper method that should be added to the bytecode.
     */
    private void translateFromStateManagerMethod(Method m,
        boolean isDirtyCheckMethod) {
        // form the name of the method by prepending 'pc' to the sm method
        String name = PRE + StringUtil.capitalize(m.getName());
        Class[] params = m.getParameterTypes();
        Class returnType = m.getReturnType();

        // add the method to the pc
        BCMethod method = _pc.declareMethod(name, returnType, params);
        Code code = method.getCode(true);

        // if (pcStateManager == null) return <default>;
        loadManagedInstance(code, false);
        code.getfield().setField(SM, SMTYPE);
        JumpInstruction ifins = code.ifnonnull();
        if (returnType.equals(boolean.class))
            code.constant().setValue(false);
        else if (!returnType.equals(void.class))
            code.constant().setNull();
        code.xreturn().setType(returnType);

        // if this is the dirty-check method and we're subclassing but not
        // redefining, hook into PCHelper to do the dirty check
        if (isDirtyCheckMethod && !getRedefine()) {
            // RedefinitionHelper.dirtyCheck(sm);
            ifins.setTarget(loadManagedInstance(code, false));
            code.getfield().setField(SM, SMTYPE);
            code.dup(); // for the return statement below
            code.invokestatic().setMethod(RedefinitionHelper.class,
                "dirtyCheck", void.class, new Class[] { SMTYPE });
        } else {
            ifins.setTarget(loadManagedInstance(code, false));
            code.getfield().setField(SM, SMTYPE);
        }

        // return pcStateManager.<method> (<args>);
        // managed instance loaded above in if-else block
        for (int i = 0; i < params.length; i++)
            code.xload().setParam(i);
        code.invokeinterface().setMethod(m);
        code.xreturn().setType(returnType);

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds the {@link PersistenceCapable#pcGetVersion} method to the bytecode.
     */
    private void addGetVersionMethod()
        throws NoSuchMethodException {
        BCMethod method = _pc.declareMethod(PRE + "GetVersion", Object.class,
            null);
        Code code = method.getCode(true);

        // if (pcStateManager == null)
        loadManagedInstance(code, false);
        code.getfield().setField(SM, SMTYPE);
        JumpInstruction ifins = code.ifnonnull();
        FieldMetaData versionField = _meta.getVersionField();

        if (versionField == null)
            code.constant().setNull(); // return null;
        else {
            // return <versionField>;
            Class wrapper = toPrimitiveWrapper(versionField);
            if (wrapper != versionField.getDeclaredType()) {
                code.anew().setType(wrapper);
                code.dup();
            }
            loadManagedInstance(code, false);
            addGetManagedValueCode(code, versionField);
            if (wrapper != versionField.getDeclaredType())
                code.invokespecial().setMethod(wrapper, "<init>", void.class,
                    new Class[]{ versionField.getDeclaredType() });
        }
        code.areturn();

        // return pcStateManager.getVersion ();
        ifins.setTarget(loadManagedInstance(code, false));
        code.getfield().setField(SM, SMTYPE);
        code.invokeinterface().setMethod(SMTYPE, "getVersion", Object.class,
            null);
        code.areturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Return the version field type as a primitive wrapper, or null if
     * the version field is not primitive.
     */
    private Class toPrimitiveWrapper(FieldMetaData fmd) {
        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.BOOLEAN:
                return Boolean.class;
            case JavaTypes.BYTE:
                return Byte.class;
            case JavaTypes.CHAR:
                return Character.class;
            case JavaTypes.DOUBLE:
                return Double.class;
            case JavaTypes.FLOAT:
                return Float.class;
            case JavaTypes.INT:
                return Integer.class;
            case JavaTypes.LONG:
                return Long.class;
            case JavaTypes.SHORT:
                return Short.class;
        }
        return fmd.getDeclaredType();
    }

    /**
     * Adds the {@link PersistenceCapable#pcReplaceStateManager}
     * method to the bytecode.
     */
    private void addReplaceStateManagerMethod() {
        // public void pcReplaceStateManager (StateManager sm)
        BCMethod method = _pc.declareMethod(PRE + "ReplaceStateManager",
            void.class, new Class[]{ SMTYPE });
        method.getExceptions(true).addException(SecurityException.class);
        Code code = method.getCode(true);

        // if (pcStateManager != null)
        //	pcStateManager = pcStateManager.replaceStateManager(sm);
        loadManagedInstance(code, false);
        code.getfield().setField(SM, SMTYPE);
        JumpInstruction ifins = code.ifnull();
        loadManagedInstance(code, false);
        loadManagedInstance(code, false);
        code.getfield().setField(SM, SMTYPE);
        code.aload().setParam(0);
        code.invokeinterface().setMethod(SMTYPE, "replaceStateManager",
            SMTYPE, new Class[]{ SMTYPE });
        code.putfield().setField(SM, SMTYPE);
        code.vreturn();

        // SecurityManager sec = System.getSecurityManager ();
        // if (sec != null)
        //		sec.checkPermission (Permission.SET_STATE_MANAGER);
        ifins.setTarget(code.invokestatic().setMethod(System.class,
            "getSecurityManager", SecurityManager.class, null));

        // pcStateManager = sm;
        ifins.setTarget(loadManagedInstance(code, false));
        code.aload().setParam(0);
        code.putfield().setField(SM, SMTYPE);
        code.vreturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Creates the PersistenceCapable methods dealing with application
     * identity and gives them no-op implementations.
     */
    private void addNoOpApplicationIdentityMethods() {
        // public void pcCopyKeyFieldsToObjectId (ObjectIdFieldSupplier fs,
        // 	Object oid)
        BCMethod method = _pc.declareMethod(PRE + "CopyKeyFieldsToObjectId",
            void.class, new Class[]{ OIDFSTYPE, Object.class });
        Code code = method.getCode(true);
        code.vreturn();
        code.calculateMaxLocals();

        // public void pcCopyKeyFieldsToObjectId (Object oid)
        method = _pc.declareMethod(PRE + "CopyKeyFieldsToObjectId",
            void.class, new Class[]{ Object.class });
        code = method.getCode(true);
        code.vreturn();
        code.calculateMaxLocals();

        // public void pcCopyKeyFieldsFromObjectId (ObjectIdFieldConsumer fc,
        //	Object oid)
        method = _pc.declareMethod(PRE + "CopyKeyFieldsFromObjectId",
            void.class, new Class[]{ OIDFCTYPE, Object.class });
        code = method.getCode(true);
        code.vreturn();
        code.calculateMaxLocals();

        // public void pcCopyKeyFieldsFromObjectId (Object oid)
        method = _pc.declareMethod(PRE + "CopyKeyFieldsFromObjectId",
            void.class, new Class[]{ Object.class });
        code = method.getCode(true);
        code.vreturn();
        code.calculateMaxLocals();

        // public Object pcNewObjectIdInstance ()
        method = _pc.declareMethod(PRE + "NewObjectIdInstance",
            Object.class, null);
        code = method.getCode(true);
        code.constant().setNull();
        code.areturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();

        // public Object pcNewObjectIdInstance (Object obj)
        method = _pc.declareMethod(PRE + "NewObjectIdInstance",
            Object.class, new Class[]{ Object.class });
        code = method.getCode(true);
        code.constant().setNull();
        code.areturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds the <code>pcCopyKeyFieldsToObjectId</code> methods
     * to classes using application identity.
     */
    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);

        // single field identity always throws exception
        if (_meta.isOpenJPAIdentity()) {
            throwException(code, INTERNEXCEP);

            code.calculateMaxStack();
            code.calculateMaxLocals();
            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);
        }

        // Object id = oid;
        if (fieldManager)
            code.aload().setParam(1);
        else
            code.aload().setParam(0);

        if (_meta.isObjectIdTypeShared()) {
            // oid = ((ObjectId) id).getId ();
            code.checkcast().setType(ObjectId.class);
            code.invokevirtual().setMethod(ObjectId.class, "getId",
                Object.class, null);
        }

        // <oid type> id = (<oid type>) oid;
        int id = code.getNextLocalsIndex();
        Class oidType = _meta.getObjectIdType();
        code.checkcast().setType(oidType);
        code.astore().setLocal(id);

        // int inherited = pcInheritedFieldCount;
        int inherited = 0;
        if (fieldManager) {
            code.getstatic().setField(INHERIT, int.class);
            inherited = code.getNextLocalsIndex();
            code.istore().setLocal(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) {
            ArrayList<Integer> pkfields = optimizeIdCopy(oidType, fmds);
            if (pkfields != null) {
                // search for a constructor on the IdClass that can be used
                // to construct the IdClass
                int parmOrder[] = getIdClassConstructorParmOrder(oidType, pkfields, fmds);
                if (parmOrder != null) {
                    // 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())
                                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());
                        }
                    }

                    // found a matching constructor.  parm array is constructor parm order
                    code.anew().setType(oidType);
                    code.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]);
                        } else {
                            // Load constructor parameters in appropriate order
                            loadLocalValue(code, localIndexes[parmIndex], fmds[parmIndex].getObjectIdFieldTypeCode());
                            if (fmds[parmIndex].getObjectIdFieldTypeCode() == JavaTypes.OBJECT &&
                                !fmds[parmIndex].getDeclaredType().isEnum()) {
                                code.checkcast().setType(ObjectId.class);
                                code.invokevirtual().setMethod(ObjectId.class, "getId",
                                    Object.class, null);
                            }
                            // 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]);
                        }
                    }
                    // 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);

                    // 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();
                    return;
                }
            }
        }

        for (int i = 0; i < fmds.length; i++) {
            if (!fmds[i].isPrimaryKey())
                continue;
            code.aload().setLocal(id);

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

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

                // 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);
            } else {
                loadManagedInstance(code, false);
                addGetManagedValueCode(code, fmds[i]);

                // get id/pk from pc instance
                if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC)
                    addExtractObjectIdFieldValueCode(code, fmds[i]);
            }

            if (reflect && field != null) {
                code.invokestatic().setMethod(Reflection.class, "set",
                    void.class, new Class[] { Object.class, Field.class,
                    (type.isPrimitive()) ? type : Object.class });
            } else if (reflect) {
                code.invokestatic().setMethod(Reflection.class, "set",
                    void.class, new Class[] { Object.class, Method.class,
                    (type.isPrimitive()) ? type : Object.class });
            } else if (field != null)
                code.putfield().setField(field);
            else
                code.invokevirtual().setMethod(setter);
        }
        code.vreturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds the appropriate load method for the given type and local
     * index.
     */
    private void loadLocalValue(Code code, int locidx, int typeCode) {
        switch (typeCode) {
            case JavaTypes.CHAR:
            case JavaTypes.BYTE:
            case JavaTypes.SHORT:
            case JavaTypes.INT:
                code.iload().setLocal(locidx);
                break;
            case JavaTypes.DOUBLE:
                code.dload().setLocal(locidx);
                break;
            case JavaTypes.FLOAT:
                code.fload().setLocal(locidx);
                break;
            case JavaTypes.LONG:
                code.lload().setLocal(locidx);
                break;
            default:
                code.aload().setLocal(locidx);
                break;
        }
    }

    /**
     * Adds the appropriate store method for the given type and local
     * index.
     */
    private void storeLocalValue(Code code, int locidx, int typeCode) {
        switch (typeCode) {
            case JavaTypes.CHAR:
            case JavaTypes.BYTE:
            case JavaTypes.SHORT:
            case JavaTypes.INT:
                code.istore().setLocal(locidx);
                break;
            case JavaTypes.DOUBLE:
                code.dstore().setLocal(locidx);
                break;
            case JavaTypes.FLOAT:
                code.fstore().setLocal(locidx);
                break;
            case JavaTypes.LONG:
                code.lstore().setLocal(locidx);
                break;
            default:
                code.astore().setLocal(locidx);
                break;
        }
    }

    /**
     * Add code to extract the id of the given primary key relation field for
     * setting into an objectid instance.
     */
    private void addExtractObjectIdFieldValueCode(Code code, FieldMetaData pk) {
        // if (val != null)
        //  val = ((PersistenceCapable) val).pcFetchObjectId();
        int pc = code.getNextLocalsIndex();
        code.astore().setLocal(pc);
        code.aload().setLocal(pc);
        JumpInstruction ifnull1 = code.ifnull();
        code.aload().setLocal(pc);
        code.checkcast().setType(PersistenceCapable.class);
        if (!pk.getTypeMetaData().isOpenJPAIdentity())
            code.invokeinterface().setMethod(PersistenceCapable.class,
                PRE + "FetchObjectId", Object.class, null);
        else
            code.invokeinterface().setMethod(PersistenceCapable.class,
                PRE + "NewObjectIdInstance", Object.class, null);

        int oid = code.getNextLocalsIndex();
        code.astore().setLocal(oid);
        code.aload().setLocal(oid);
        JumpInstruction ifnull2 = code.ifnull();

        // 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) {
            code.aload().setLocal(oid);
            code.checkcast().setType(Id.class);
            code.invokevirtual().setMethod(Id.class, "getId",
                long.class, null);
        } else if (pkmeta.getIdentityType() == ClassMetaData.ID_DATASTORE) {
            code.aload().setLocal(oid);
        } else if (pkmeta.isOpenJPAIdentity()) {
            switch (pkcode) {
                case JavaTypes.BYTE_OBJ:
                    code.anew().setType(Byte.class);
                    code.dup();
                    // no break
                case JavaTypes.BYTE:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(ByteId.class);
                    code.invokevirtual().setMethod(ByteId.class, "getId",
                        byte.class, null);
                    if (pkcode == JavaTypes.BYTE_OBJ)
                        code.invokespecial().setMethod(Byte.class, "<init>",
                            void.class, new Class[] {byte.class});
                    break;
                case JavaTypes.CHAR_OBJ:
                    code.anew().setType(Character.class);
                    code.dup();
                    // no break
                case JavaTypes.CHAR:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(CharId.class);
                    code.invokevirtual().setMethod(CharId.class, "getId",
                        char.class, null);
                    if (pkcode == JavaTypes.CHAR_OBJ)
                        code.invokespecial().setMethod(Character.class,
                            "<init>", void.class, new Class[] {char.class});
                    break;
                case JavaTypes.DOUBLE_OBJ:
                    code.anew().setType(Double.class);
                    code.dup();
                    // no break
                case JavaTypes.DOUBLE:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(DoubleId.class);
                    code.invokevirtual().setMethod(DoubleId.class, "getId",
                        double.class, null);
                    if (pkcode == JavaTypes.DOUBLE_OBJ)
                        code.invokespecial().setMethod(Double.class, "<init>",
                            void.class, new Class[]{double.class});
                    break;
                case JavaTypes.FLOAT_OBJ:
                    code.anew().setType(Float.class);
                    code.dup();
                    // no break
                case JavaTypes.FLOAT:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(FloatId.class);
                    code.invokevirtual().setMethod(FloatId.class, "getId",
                        float.class, null);
                    if (pkcode == JavaTypes.FLOAT_OBJ)
                        code.invokespecial().setMethod(Float.class, "<init>",
                            void.class, new Class[]{float.class});
                    break;
                case JavaTypes.INT_OBJ:
                    code.anew().setType(Integer.class);
                    code.dup();
                    // no break
                case JavaTypes.INT:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(IntId.class);
                    code.invokevirtual().setMethod(IntId.class, "getId",
                        int.class, null);
                    if (pkcode == JavaTypes.INT_OBJ)
                        code.invokespecial().setMethod(Integer.class, "<init>",
                            void.class, new Class[] {int.class});
                    break;
                case JavaTypes.LONG_OBJ:
                    code.anew().setType(Long.class);
                    code.dup();
                    // no break
                case JavaTypes.LONG:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(LongId.class);
                    code.invokevirtual().setMethod(LongId.class, "getId",
                        long.class, null);
                    if (pkcode == JavaTypes.LONG_OBJ)
                        code.invokespecial().setMethod(Long.class, "<init>",
                            void.class, new Class[] {long.class});
                    break;
                case JavaTypes.SHORT_OBJ:
                    code.anew().setType(Short.class);
                    code.dup();
                    // no break
                case JavaTypes.SHORT:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(ShortId.class);
                    code.invokevirtual().setMethod(ShortId.class, "getId",
                        short.class, null);
                    if (pkcode == JavaTypes.SHORT_OBJ)
                        code.invokespecial().setMethod(Short.class, "<init>",
                            void.class, new Class[]{short.class});
                    break;
                case JavaTypes.DATE:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(DateId.class);
                    code.invokevirtual().setMethod(DateId.class, "getId",
                        Date.class, null);
                    if (pktype != Date.class) {
                        // java.sql.Date.class
                        code.checkcast().setType(pktype);
                    }
                    break;
                case JavaTypes.STRING:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(StringId.class);
                    code.invokevirtual().setMethod(StringId.class, "getId",
                        String.class, null);
                    break;
                case JavaTypes.BIGDECIMAL:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(BigDecimalId.class);
                    code.invokevirtual().setMethod(BigDecimalId.class, "getId",
                        BigDecimal.class, null);
                    break;
                case JavaTypes.BIGINTEGER:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(BigIntegerId.class);
                    code.invokevirtual().setMethod(BigIntegerId.class, "getId",
                        BigInteger.class, null);
                    break;
                default:
                    code.aload().setLocal(oid);
                    code.checkcast().setType(ObjectId.class);
                    code.invokevirtual().setMethod(ObjectId.class, "getId",
                        Object.class, null);
            }
        } else if (pkmeta.getObjectIdType() != null) {
            code.aload().setLocal(oid);
            if (pkcode == JavaTypes.OBJECT) {
                code.checkcast().setType(ObjectId.class);
                code.invokevirtual().setMethod(ObjectId.class, "getId",
            			Object.class, null);
            }
            code.checkcast().setType(pktype);
        } else
            code.aload().setLocal(oid);
        JumpInstruction go2 = code.go2();

        // if (val == null)
        //   val = <default>;
        Instruction def;
        switch (pkcode) {
            case JavaTypes.BOOLEAN:
                def = code.constant().setValue(false);
                break;
            case JavaTypes.BYTE:
                def = code.constant().setValue((byte) 0);
                break;
            case JavaTypes.CHAR:
                def = code.constant().setValue((char) 0);
                break;
            case JavaTypes.DOUBLE:
                def = code.constant().setValue(0D);
                break;
            case JavaTypes.FLOAT:
                def = code.constant().setValue(0F);
                break;
            case JavaTypes.INT:
                def = code.constant().setValue(0);
                break;
            case JavaTypes.LONG:
                def = code.constant().setValue(0L);
                break;
            case JavaTypes.SHORT:
                def = code.constant().setValue((short) 0);
                break;
            default:
                def = code.constant().setNull();
        }
        ifnull1.setTarget(def);
        ifnull2.setTarget(def);
        go2.setTarget(code.nop());
    }

    /**
     * Adds the <code>pcCopyKeyFieldsFromObjectId</code> methods
     * to classes using application identity.
     */
    private void addCopyKeyFieldsFromObjectIdMethod(boolean fieldManager)
        throws NoSuchMethodException {
        // public void pcCopyKeyFieldsFromObjectId (ObjectIdFieldConsumer fc,
        //	Object oid)
        String[] args = (fieldManager)
            ?  new String[]{ OIDFCTYPE.getName(), Object.class.getName() }
            : new String[]{ Object.class.getName() };
        BCMethod method = _pc.declareMethod(PRE + "CopyKeyFieldsFromObjectId",
            void.class.getName(), args);
        Code code = method.getCode(true);

        // 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 + "CopyKeyFieldsFromObjectId", void.class.getName(), args);
        }

        if (fieldManager)
            code.aload().setParam(1);
        else
            code.aload().setParam(0);

        if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared()) {
            // oid = ((ObjectId) id).getId ();
            code.checkcast().setType(ObjectId.class);
            code.invokevirtual().setMethod(ObjectId.class, "getId",
                Object.class, null);
        }

        // <oid type> cast = (<oid type>) oid;
        int id = code.getNextLocalsIndex();
        Class oidType = _meta.getObjectIdType();
        code.checkcast().setType(oidType);
        code.astore().setLocal(id);

        // fs.store<type>Field (<index>, id.<field>); or...
        // this.<field> = id.<field>
        // or for single field identity: id.getId ()
        FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
            : _meta.getDeclaredFields();
        String name;
        Class type;
        Class unwrapped;
        Field field;
        Method getter;
        for (int i = 0; i < fmds.length; i++) {
            if (!fmds[i].isPrimaryKey())
                continue;

            name = fmds[i].getName();
            type = fmds[i].getObjectIdFieldType();
            if (!fieldManager
                && fmds[i].getDeclaredTypeCode() == JavaTypes.PC) {
                // if (sm == null) return;
                loadManagedInstance(code, false);
                code.getfield().setField(SM, SMTYPE);
                JumpInstruction ifins = code.ifnonnull();
                code.vreturn();
                // sm.getPCPrimaryKey(oid, i + pcInheritedFieldCount);
                ifins.setTarget(loadManagedInstance(code, false));
                code.dup(); // leave orig on stack to set value into
                code.getfield().setField(SM, SMTYPE);
                code.aload().setLocal(id);
                code.constant().setValue(i);
                code.getstatic().setField(INHERIT, int.class);
                code.iadd();
                code.invokeinterface().setMethod(StateManager.class,
                    "getPCPrimaryKey", Object.class,
                    new Class[] { Object.class, int.class });
                code.checkcast().setType(fmds[i].getDeclaredType());
            } else {
                unwrapped = (fmds[i].getDeclaredTypeCode() == JavaTypes.PC)
                    ? type : unwrapSingleFieldIdentity(fmds[i]);
                if (fieldManager) {
                    code.aload().setParam(0);
                    code.constant().setValue(i);
                    code.getstatic().setField(INHERIT, int.class);
                    code.iadd();
                } else
                    loadManagedInstance(code, false);

                if (unwrapped != type) {
                    code.anew().setType(type);
                    code.dup();
                }
                code.aload().setLocal(id);
                if (_meta.isOpenJPAIdentity()) {
                    if (oidType == ObjectId.class) {
                        code.invokevirtual().setMethod(oidType, "getId",
                            Object.class, null);
                        if (!fieldManager && type != Object.class)
                            code.checkcast().setType(fmds[i].getDeclaredType());
                    } else if (oidType == DateId.class) {
                        code.invokevirtual().setMethod(oidType, "getId",
                            Date.class, null);
                        if (!fieldManager && type != Date.class)
                            code.checkcast().setType(fmds[i].getDeclaredType());
                    } else {
                        code.invokevirtual().setMethod(oidType, "getId",
                            unwrapped, null);
                        if (unwrapped != type)
                            code.invokespecial().setMethod(type, "<init>",
                                void.class, new Class[]{ unwrapped });
                    }
                } else if (isFieldAccess(fmds[i])) {
                    field = Reflection.findField(oidType, name, true);
                    if (Modifier.isPublic(field.getModifiers()))
                        code.getfield().setField(field);
                    else {
                        boolean usedFastOid = false;
                        if (_optimizeIdCopy) {
                            // If fastOids, ignore access type and try to use a public getter
                            getter = Reflection.findGetter(oidType, name, false);
                            if (getter != null && Modifier.isPublic(getter.getModifiers())) {
                                usedFastOid = true;
                                code.invokevirtual().setMethod(getter);
                            }
                        }
                        if (!usedFastOid) {
                            // Reflection.getXXX(oid, Reflection.findField(...));
                            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 });
                            code.invokestatic().setMethod
                                (getReflectionGetterMethod(type, Field.class));
                            if (!type.isPrimitive() && type != Object.class)
                                code.checkcast().setType(type);
                        }
                    }
                } else {
                    getter = Reflection.findGetter(oidType, name, true);
                    if (Modifier.isPublic(getter.getModifiers()))
                        code.invokevirtual().setMethod(getter);
                    else {
                        // Reflection.getXXX(oid, Reflection.findGetter(...));
                        code.classconstant().setClass(oidType);
                        code.constant().setValue(name);
                        code.constant().setValue(true);
                        code.invokestatic().setMethod(Reflection.class,
                            "findGetter", Method.class, new Class[] {
                            Class.class, String.class, boolean.class });
                        code.invokestatic().setMethod
                            (getReflectionGetterMethod(type, Method.class));
                        if (!type.isPrimitive() && type != Object.class)
                            code.checkcast().setType(type);
                    }
                }
            }

            if (fieldManager)
                code.invokeinterface().setMethod(getFieldConsumerMethod(type));
            else
                addSetManagedValueCode(code, fmds[i]);
        }
        code.vreturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Return if the class uses the Class/String constructor
     * instead of just String.
     */
    private Boolean usesClassStringIdConstructor() {
        if (_meta.getIdentityType() != ClassMetaData.ID_APPLICATION)
            return Boolean.FALSE;

        if (_meta.isOpenJPAIdentity()) {
            if (_meta.getObjectIdType() == ObjectId.class)
                return null;
            return Boolean.TRUE;
        }

        Class oidType = _meta.getObjectIdType();
        try {
            oidType.getConstructor(new Class[]{ Class.class, String.class });
            return Boolean.TRUE;
        } catch (Throwable t) {
        }
        try {
            oidType.getConstructor(new Class[]{ String.class });
            return Boolean.FALSE;
        } catch (Throwable t) {
        }
        return null;
    }

    /**
     * If the given field is a wrapper-type single field identity primary key,
     * return its corresponding primitive class. Else return the field type.
     */
    private Class unwrapSingleFieldIdentity(FieldMetaData fmd) {
        if (!fmd.getDefiningMetaData().isOpenJPAIdentity())
            return fmd.getDeclaredType();

        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.BYTE_OBJ:
                return byte.class;
            case JavaTypes.CHAR_OBJ:
                return char.class;
            case JavaTypes.DOUBLE_OBJ:
                return double.class;
            case JavaTypes.FLOAT_OBJ:
                return float.class;
            case JavaTypes.INT_OBJ:
                return int.class;
            case JavaTypes.SHORT_OBJ:
                return short.class;
            case JavaTypes.LONG_OBJ:
                return long.class;
            default:
                return fmd.getDeclaredType();
        }
    }

    /**
     * Return the proper getter method of the {@link Reflection} helper for
     * a field or getter method of the given type.
     */
    private Method getReflectionGetterMethod(Class type, Class argType)
        throws NoSuchMethodException {
        String name = "get";
        if (type.isPrimitive())
            name += StringUtil.capitalize(type.getName());
        return Reflection.class.getMethod(name, new Class[] { Object.class,
            argType });
    }

    /**
     * Return the proper fetch method of the ObjectIdFieldSupplier for
     * a field of the given type.
     */
    private Method getFieldSupplierMethod(Class type)
        throws NoSuchMethodException {
        return getMethod(OIDFSTYPE, type, "fetch", true, false, false);
    }

    /**
     * Return the proper fetch method of the ObjectIdFieldConsumer for
     * a field of the given type.
     */
    private Method getFieldConsumerMethod(Class type)
        throws NoSuchMethodException {
        return getMethod(OIDFCTYPE, type, "store", false, false, false);
    }

    /**
     * Adds the pcNewObjectIdInstance method to classes using
     * application identity.
     */
    private void addNewObjectIdInstanceMethod(boolean obj)
        throws NoSuchMethodException {
        // public Object pcNewObjectIdInstance ()
        Class[] args = (obj) ? new Class[]{ Object.class } : null;
        BCMethod method = _pc.declareMethod(PRE + "NewObjectIdInstance",
            Object.class, args);
        Code code = method.getCode(true);

        Boolean usesClsString = usesClassStringIdConstructor();
        Class oidType = _meta.getObjectIdType();
        if (obj && usesClsString == null) {
            // throw new IllegalArgumentException (...);
            String msg = _loc.get("str-cons", oidType,
                _meta.getDescribedType()).getMessage();
            code.anew().setType(IllegalArgumentException.class);
            code.dup();
            code.constant().setValue(msg);
            code.invokespecial().setMethod(IllegalArgumentException.class,
                "<init>", void.class, new Class[]{ String.class });
            code.athrow();

            code.calculateMaxStack();
            code.calculateMaxLocals();
            return;
        }

        if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared()) {
            // new ObjectId (cls, oid)
            code.anew().setType(ObjectId.class);
            code.dup();
            if(_meta.isEmbeddedOnly() || _meta.hasAbstractPKField()) {
                code.aload().setThis();
                code.invokevirtual().setMethod(PRE + "GetIDOwningClass",
                    Class.class, null);
            } else {
                code.classconstant().setClass(getType(_meta));
            }
        }

        // new <oid class> ();
        code.anew().setType(oidType);
        code.dup();
        if (_meta.isOpenJPAIdentity() || (obj && usesClsString == Boolean.TRUE)) {
            if ((_meta.isEmbeddedOnly()
                && !(_meta.isEmbeddable() && _meta.getIdentityType() == ClassMetaData.ID_APPLICATION))
                || _meta.hasAbstractPKField()) {
                code.aload().setThis();
                code.invokevirtual().setMethod(PRE + "GetIDOwningClass", Class.class, null);
            } else {
                code.classconstant().setClass(getType(_meta));
            }
        }
        if (obj) {
            code.aload().setParam(0);
            code.checkcast().setType(String.class);
            if (usesClsString == Boolean.TRUE)
                args = new Class[]{ Class.class, String.class };
            else if (usesClsString == Boolean.FALSE)
                args = new Class[]{ String.class };
        } else if (_meta.isOpenJPAIdentity()) {
            // new <type>Identity (XXX.class, <pk>);
            loadManagedInstance(code, false);
            FieldMetaData pk = _meta.getPrimaryKeyFields()[0];
            addGetManagedValueCode(code, pk);
            if (pk.getDeclaredTypeCode() == JavaTypes.PC)
                addExtractObjectIdFieldValueCode(code, pk);
            if (_meta.getObjectIdType() == ObjectId.class)
                args = new Class[]{ Class.class, Object.class };
            else if (_meta.getObjectIdType() == Date.class)
                args = new Class[]{ Class.class, Date.class };
            else
                args = new Class[]{ Class.class, pk.getObjectIdFieldType() };
        }

        code.invokespecial().setMethod(oidType, "<init>", void.class, args);
        if (!_meta.isOpenJPAIdentity() && _meta.isObjectIdTypeShared())
            code.invokespecial().setMethod(ObjectId.class, "<init>",
                void.class, new Class[]{ Class.class, Object.class });
        code.areturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * When communicating with the StateManager, many methods are used
     * depending on the class of state being passed. This method,
     * given the type of information being passed and the prefix
     * ('provided', 'replace', etc) of the method to
     * call, returns the StateManager method that should be used.
     *
     * @param type the type of state being passed
     * @param prefix the prefix of the method to call; all methods
     * end in '[state type]Field'; only the prefix varies
     * @param get true if receiving information from the
     * StateManager, false if passing it to the SM
     * @param curValue true if the current state value is passed to
     * the StateManager as an extra argument
     */
    private Method getStateManagerMethod(Class type, String prefix,
        boolean get, boolean curValue)
        throws NoSuchMethodException {
        return getMethod(SMTYPE, type, prefix, get, true, curValue);
    }

    /**
     * Return the method of the given owner type matching the given criteria.
     *
     * @param type the type of state being passed
     * @param prefix the prefix of the method to call; all methods
     * end in '[state type]Field'; only the prefix varies
     * @param get true if receiving information from the
     * owner, false if passing it to the owner
     * @param haspc true if the pc is passed as an extra argument
     * @param curValue true if the current state value is passed to
     * the owner as an extra argument
     */
    private Method getMethod(Class owner, Class type, String prefix,
        boolean get, boolean haspc, boolean curValue)
        throws NoSuchMethodException {
        // all methods end in [field type]Field, where the field type
        // can be any of the primitve types (but capitalized), 'String',
        // or 'Object'; figure out what type to use
        String typeName = type.getName();
        if (type.isPrimitive())
            typeName = typeName.substring(0, 1).toUpperCase(Locale.ENGLISH)
                + typeName.substring(1);
        else if (type.equals(String.class))
            typeName = "String";
        else {
            typeName = "Object";
            type = Object.class;
        }

        // the field index is always passed as an arg; the pc instance and
        // the current value may be passed; if setting the new value is
        // also passed
        List plist = new ArrayList(4);
        if (haspc)
            plist.add(PCTYPE);
        plist.add(int.class);
        if (!get || curValue)
            plist.add(type);
        if (!get && curValue) {
            plist.add(type);
            plist.add(int.class);
        }

        // use reflection to return the right method
        String name = prefix + typeName + "Field";
        Class[] params = (Class[]) plist.toArray(new Class[plist.size()]);

        try {
            return AccessController.doPrivileged(
                J2DoPrivHelper.getDeclaredMethodAction(owner, name, params));
        } catch (PrivilegedActionException pae) {
             throw (NoSuchMethodException) pae.getException();
        }
    }

    /**
     * Helper method to add the code necessary to throw the given
     * exception type, sans message.
     */
    private Instruction throwException(Code code, Class type) {
        Instruction ins = code.anew().setType(type);
        code.dup();
        code.invokespecial().setMethod(type, "<init>", void.class, null);
        code.athrow();
        return ins;
    }

    /**
     * Adds the PersistenceCapable interface to the class being
     * enhanced, and adds a default constructor for use by OpenJPA
     * if it is not already present.
     */
    private void enhanceClass() {
        // make the class implement PersistenceCapable
        _pc.declareInterface(PCTYPE);

        // add a version stamp
        addGetEnhancementContractVersionMethod();

        // find the default constructor
        BCMethod method = _pc.getDeclaredMethod("<init>", (String[]) null);

        // a default constructor is required
        if (method == null) {
            String name = _pc.getName();
            if (!_defCons)
                throw new UserException(_loc.get("enhance-defaultconst", name));

            method = _pc.addDefaultConstructor();
            String access;
            if (_meta.isDetachable()) {
                // externalizable requires that the constructor
                // be public, so make the added constructor public
                method.makePublic();
                access = "public";
            } else if (_pc.isFinal()) {
                method.makePrivate();
                access = "private";
            } else {
                method.makeProtected();
                access = "protected";
            }
            if (!(_meta.getDescribedType().isInterface() || getCreateSubclass())
                && _log.isWarnEnabled())
                _log.warn(_loc.get("enhance-adddefaultconst", name, access));
        }
    }

    /**
     * Adds the following fields to the PersistenceCapable instance:
     * <ul>
     * <li><code>private static int pcInheritedFieldCount</code></li>
     * <li><code>private static Class pcPCSuperclass</code>
     * </li>
     * <li><code>private static String[] pcFieldNames</code></li>
     * <li><code>private static Class[] pcFieldTypes</code></li>
     * <li><code>private static byte[] pcFieldFlags</code></li>
     * <li><code>protected transient StateManager pcStateManager</code>
     * if no PersistenceCapable superclass present)</li>
     * </ul>
     */
    private void addFields() {
        _pc.declareField(INHERIT, int.class).setStatic(true);
        _pc.declareField(PRE + "FieldNames", String[].class).setStatic(true);
        _pc.declareField(PRE + "FieldTypes", Class[].class).setStatic(true);
        _pc.declareField(PRE + "FieldFlags", byte[].class).setStatic(true);
        _pc.declareField(SUPER, Class.class).setStatic(true);
        if (_addVersionInitFlag && _meta.getVersionField() != null) {
            // protected transient boolean pcVersionInit;
            BCField field = _pc.declareField(VERSION_INIT_STR, boolean.class);
            field.makeProtected();
            field.setTransient(true);
        }
        if (_meta.getPCSuperclass() == null || getCreateSubclass()) {
            BCField field = _pc.declareField(SM, SMTYPE);
            field.makeProtected();
            field.setTransient(true);
        }
    }

    /**
     * Modifies the class initialization method (creating one if necessary)
     * to initialize the static fields of the PersistenceCapable instance and
     * to register it with the impl helper.
     */
    private void addStaticInitializer() {
        Code code = getOrCreateClassInitCode(true);
        if (_meta.getPCSuperclass() != null) {
            if (getCreateSubclass()) {
                code.constant().setValue(0);
                code.putstatic().setField(INHERIT, int.class);
            } else {
                // pcInheritedFieldCount = <superClass>.pcGetManagedFieldCount()
                code.invokestatic().setMethod(getType(_meta.
                    getPCSuperclassMetaData()).getName(),
                    PRE + "GetManagedFieldCount", int.class.getName(), null);
                code.putstatic().setField(INHERIT, int.class);
            }

            // pcPCSuperclass = <superClass>;
            // this intentionally calls getDescribedType() directly
            // instead of PCEnhancer.getType()
            code.classconstant().setClass(
                _meta.getPCSuperclassMetaData().getDescribedType());
            code.putstatic().setField(SUPER, Class.class);
        }

        // pcFieldNames = new String[] { "<name1>", "<name2>", ... };
        FieldMetaData[] fmds = _meta.getDeclaredFields();
        code.constant().setValue(fmds.length);
        code.anewarray().setType(String.class);
        for (int i = 0; i < fmds.length; i++) {
            code.dup();
            code.constant().setValue(i);
            code.constant().setValue(fmds[i].getName());
            code.aastore();
        }
        code.putstatic().setField(PRE + "FieldNames", String[].class);

        // pcFieldTypes = new Class[] { <type1>.class, <type2>.class, ... };
        code.constant().setValue(fmds.length);
        code.anewarray().setType(Class.class);
        for (int i = 0; i < fmds.length; i++) {
            code.dup();
            code.constant().setValue(i);
            code.classconstant().setClass(fmds[i].getDeclaredType());
            code.aastore();
        }
        code.putstatic().setField(PRE + "FieldTypes", Class[].class);

        // pcFieldFlags = new byte[] { <flag1>, <flag2>, ... };
        code.constant().setValue(fmds.length);
        code.newarray().setType(byte.class);
        for (int i = 0; i < fmds.length; i++) {
            code.dup();
            code.constant().setValue(i);
            code.constant().setValue(getFieldFlag(fmds[i]));
            code.bastore();
        }
        code.putstatic().setField(PRE + "FieldFlags", byte[].class);

        // PCRegistry.register (cls,
        //	pcFieldNames, pcFieldTypes, pcFieldFlags,
        //  pcPCSuperclass, alias, new XXX ());
        code.classconstant().setClass(_meta.getDescribedType());
        code.getstatic().setField(PRE + "FieldNames", String[].class);
        code.getstatic().setField(PRE + "FieldTypes", Class[].class);
        code.getstatic().setField(PRE + "FieldFlags", byte[].class);
        code.getstatic().setField(SUPER, Class.class);

        if (_meta.isMapped() || _meta.isAbstract())
            code.constant().setValue(_meta.getTypeAlias());
        else
            code.constant().setNull();

        if (_pc.isAbstract())
            code.constant().setNull();
        else {
            code.anew().setType(_pc);
            code.dup();
            code.invokespecial().setMethod("<init>", void.class, null);
        }

        code.invokestatic().setMethod(HELPERTYPE, "register", void.class,
            new Class[]{ Class.class, String[].class, Class[].class,
                byte[].class, Class.class, String.class, PCTYPE });

        code.vreturn();
        code.calculateMaxStack();
    }

    /**
     * Return the flag for the given field.
     */
    private static byte getFieldFlag(FieldMetaData fmd) {
        if (fmd.getManagement() == FieldMetaData.MANAGE_NONE)
            return -1;

        byte flags = 0;
        if (fmd.getDeclaredType().isPrimitive()
            || Serializable.class.isAssignableFrom(fmd.getDeclaredType()))
            flags = PersistenceCapable.SERIALIZABLE;

        if (fmd.getManagement() == FieldMetaData.MANAGE_TRANSACTIONAL)
            flags |= PersistenceCapable.CHECK_WRITE;
        else if (!fmd.isPrimaryKey() && !fmd.isInDefaultFetchGroup())
            flags |= PersistenceCapable.CHECK_WRITE
                | PersistenceCapable.CHECK_READ;
        else
            flags |= PersistenceCapable.MEDIATE_WRITE
                | PersistenceCapable.MEDIATE_READ;
        return flags;
    }

    /**
     * Adds the code to properly handle PersistenceCapable serialization
     * to the bytecode. This includes creating and initializing the
     * static <code>serialVersionUID</code> constant if not already defined,
     * as well as creating a custom <code>writeObject</code> method if the
     * class is Serializable and does not define them.
     */
    private void addSerializationCode() {
        if (externalizeDetached()
            || !Serializable.class.isAssignableFrom(_meta.getDescribedType()))
            return;

        if (getCreateSubclass()) {
            // ##### what should happen if a type is Externalizable? It looks
            // ##### like Externalizable classes will not be serialized as PCs
            // ##### based on this logic.
            if (!Externalizable.class.isAssignableFrom(
                _meta.getDescribedType()))
                addSubclassSerializationCode();
            return;
        }

        // if not already present, add a serialVersionUID field; if the instance
        // is detachable and uses detached state without a declared field,
        // can't add a serial version UID because we'll be adding extra fields
        // to the enhanced version
        BCField field = _pc.getDeclaredField("serialVersionUID");
        if (field == null) {
            Long uid = null;
            try {
                uid = ObjectStreamClass.lookup
                    (_meta.getDescribedType()).getSerialVersionUID();
            } catch (Throwable t) {
                // last-chance catch for bug #283 (which can happen
                // in a variety of ClassLoading environments)
                if (_log.isTraceEnabled())
                    _log.warn(_loc.get("enhance-uid-access", _meta), t);
                else
                    _log.warn(_loc.get("enhance-uid-access", _meta));
            }

            // if we couldn't access the serialVersionUID, we will have to
            // skip the override of that field and not be serialization
            // compatible with non-enhanced classes
            if (uid != null) {
                field = _pc.declareField("serialVersionUID", long.class);
                field.makePrivate();
                field.setStatic(true);
                field.setFinal(true);

                Code code = getOrCreateClassInitCode(false);
                code.beforeFirst();
                code.constant().setValue(uid.longValue());
                code.putstatic().setField(field);

                code.calculateMaxStack();
            }
        }

        // add write object method
        BCMethod write = _pc.getDeclaredMethod("writeObject",
            new Class[]{ ObjectOutputStream.class });
        boolean full = write == null;
        if (full) {
            // private void writeObject (ObjectOutputStream out)
            write = _pc.declareMethod("writeObject", void.class,
                new Class[]{ ObjectOutputStream.class });
            write.getExceptions(true).addException(IOException.class);
            write.makePrivate();
        }
        modifyWriteObjectMethod(write, full);

        // and read object
        BCMethod read = _pc.getDeclaredMethod("readObject",
            new Class[]{ ObjectInputStream.class });
        full = read == null;
        if (full) {
            // private void readObject (ObjectInputStream in)
            read = _pc.declareMethod("readObject", void.class,
                new Class[]{ ObjectInputStream.class });
            read.getExceptions(true).addException(IOException.class);
            read.getExceptions(true).addException
                (ClassNotFoundException.class);
            read.makePrivate();
        }
        modifyReadObjectMethod(read, full);
    }

    private void addSubclassSerializationCode() {
        // for generated subclasses, serialization must write an instance of
        // the superclass instead of the subclass, so that the client VM can
        // deserialize successfully.

        // private Object writeReplace() throws ObjectStreamException
        BCMethod method = _pc.declareMethod("writeReplace", Object.class, null);
        method.getExceptions(true).addException(ObjectStreamException.class);
        Code code = method.getCode(true);

        // Object o = new <managed-type>()
        code.anew().setType(_managedType); // for return
        code.dup(); // for post-<init> work
        code.dup(); // for <init>
        code.invokespecial().setMethod(_managedType.getType(), "<init>",
            void.class, null);

        // copy all the fields.
        // ##### limiting to JPA @Transient limitations
        FieldMetaData[] fmds = _meta.getFields();
        for (FieldMetaData fmd : fmds) {
            if (fmd.isTransient())
                continue;
            // o.<field> = this.<field> (or reflective analog)
            code.dup(); // for putfield
            code.aload().setThis(); // for getfield
            getfield(code, _managedType, fmd.getName());
            putfield(code, _managedType, fmd.getName(),
                    fmd.getDeclaredType());
        }

        code.areturn().setType(Object.class);

        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    /**
     * Whether the class being enhanced should externalize to a detached
     * instance rather than serialize.
     */
    private boolean externalizeDetached() {
        return ClassMetaData.SYNTHETIC.equals(_meta.getDetachedState())
            && Serializable.class.isAssignableFrom(_meta.getDescribedType())
            && !_repos.getConfiguration().getDetachStateInstance().
            isDetachedStateTransient();
    }

    /**
     * Adds a custom writeObject method that delegates to the
     * {@link ObjectOutputStream#defaultWriteObject} method,
     * but only after calling the internal <code>pcSerializing</code> method.
     */
    private void modifyWriteObjectMethod(BCMethod method, boolean full) {
        Code code = method.getCode(true);
        code.beforeFirst();

        // bool clear = pcSerializing ();
        loadManagedInstance(code, false);
        code.invokevirtual().setMethod(PRE + "Serializing",
            boolean.class, null);
        int clear = code.getNextLocalsIndex();
        code.istore().setLocal(clear);

        if (full) {
            // out.defaultWriteObject ();
            code.aload().setParam(0);
            code.invokevirtual().setMethod(ObjectOutputStream.class,
                "defaultWriteObject", void.class, null);
            code.vreturn();
        }

        Instruction tmplate = (AccessController.doPrivileged(
            J2DoPrivHelper.newCodeAction())).vreturn();
        JumpInstruction toret;
        Instruction ret;
        code.beforeFirst();
        while (code.searchForward(tmplate)) {
            ret = code.previous();
            // if (clear) pcSetDetachedState (null);
            code.iload().setLocal(clear);
            toret = code.ifeq();
            loadManagedInstance(code, false);
            code.constant().setNull();
            code.invokevirtual().setMethod(PRE + "SetDetachedState",
                void.class, new Class[]{ Object.class });
            toret.setTarget(ret);
            code.next(); // jump over return
        }
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds a custom readObject method that delegates to the
     * {@link ObjectInputStream#readObject} method.
     */
    private void modifyReadObjectMethod(BCMethod method, boolean full) {
        Code code = method.getCode(true);
        code.beforeFirst();

        // if this instance uses synthetic detached state, note that it has
        // been deserialized
        if (ClassMetaData.SYNTHETIC.equals(_meta.getDetachedState())) {
            loadManagedInstance(code, false);
            code.getstatic().setField(PersistenceCapable.class,
                "DESERIALIZED", Object.class);
            code.invokevirtual().setMethod(PRE + "SetDetachedState",
                void.class, new Class[]{ Object.class });
        }

        if (full) {
            // in.defaultReadObject ();
            code.aload().setParam(0);
            code.invokevirtual().setMethod(ObjectInputStream.class,
                "defaultReadObject", void.class, null);
            code.vreturn();
        }

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Creates the pcIsDetached() method to determine if an instance
     * is detached.
     */
    private void addIsDetachedMethod()
        throws NoSuchMethodException {
        // public boolean pcIsDetached()
        BCMethod method = _pc.declareMethod(PRE + "IsDetached",
            Boolean.class, null);
        method.makePublic();
        Code code = method.getCode(true);
        boolean needsDefinitiveMethod = writeIsDetachedMethod(code);
        code.calculateMaxStack();
        code.calculateMaxLocals();
        if (!needsDefinitiveMethod)
            return;

        // private boolean pcIsDetachedStateDefinitive()
        //   return false;
        // auxilliary enhancers may change the return value of this method
        // if their specs consider detached state definitive
        method = _pc.declareMethod(ISDETACHEDSTATEDEFINITIVE, boolean.class,
            null);
        method.makePrivate();
        code = method.getCode(true);
        code.constant().setValue(false);
        code.ireturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Creates the body of the pcIsDetached() method to determine if an
     * instance is detached.
     *
     * @return true if we need a pcIsDetachedStateDefinitive method, false
     * otherwise
     */
    private boolean writeIsDetachedMethod(Code code)
        throws NoSuchMethodException {
        // not detachable: return Boolean.FALSE
        if (!_meta.isDetachable()) {
            code.getstatic().setField(Boolean.class, "FALSE", Boolean.class);
            code.areturn();
            return false;
        }

        // if (sm != null)
        //     return (sm.isDetached ()) ? Boolean.TRUE : Boolean.FALSE;
        loadManagedInstance(code, false);
        code.getfield().setField(SM, SMTYPE);
        JumpInstruction ifins = code.ifnull();
        loadManagedInstance(code, false);
        code.getfield().setField(SM, SMTYPE);
        code.invokeinterface().setMethod(SMTYPE, "isDetached",
            boolean.class, null);
        JumpInstruction iffalse = code.ifeq();
        code.getstatic().setField(Boolean.class, "TRUE", Boolean.class);
        code.areturn();
        iffalse.setTarget(code.getstatic().setField(Boolean.class, "FALSE",
            Boolean.class));
        code.areturn();

        // if we use detached state:
        // if (pcGetDetachedState () != null
        //     && pcGetDetachedState != DESERIALIZED)
        //     return Boolean.TRUE;
        Boolean state = _meta.usesDetachedState();
        JumpInstruction notdeser = null;
        Instruction target;
        if (state != Boolean.FALSE) {
            ifins.setTarget(loadManagedInstance(code, false));
            code.invokevirtual().setMethod(PRE + "GetDetachedState",
                Object.class, null);
            ifins = code.ifnull();
            loadManagedInstance(code, false);
            code.invokevirtual().setMethod(PRE + "GetDetachedState",
                Object.class, null);
            code.getstatic().setField(PersistenceCapable.class,
                "DESERIALIZED", Object.class);
            notdeser = code.ifacmpeq();
            code.getstatic().setField(Boolean.class, "TRUE", Boolean.class);
            code.areturn();

            if (state == Boolean.TRUE) {
                // if we have to use detached state:
                // return Boolean.FALSE;
                target = code.getstatic().setField(Boolean.class, "FALSE",
                    Boolean.class);
                ifins.setTarget(target);
                notdeser.setTarget(target);
                code.areturn();
                return false;
            }
        }

        // create artificial target to simplify
        target = code.nop();
        ifins.setTarget(target);
        if (notdeser != null)
            notdeser.setTarget(target);

        // allow users with version or auto-assigned pk fields to manually
        // construct a "detached" instance, so check these before taking into
        // account non-existent detached state

        // consider detached if version is non-default
        FieldMetaData version = _meta.getVersionField();
        if (state != Boolean.TRUE && version != null) {
            // if (<version> != <default>)
            //		return true;
            loadManagedInstance(code, false);
            addGetManagedValueCode(code, version);
            ifins = ifDefaultValue(code, version);
            code.getstatic().setField(Boolean.class, "TRUE", Boolean.class);
            code.areturn();
            if (!_addVersionInitFlag){
                // else return false;
                ifins.setTarget(code.getstatic().setField(Boolean.class, "FALSE", Boolean.class));
            }else{
                // noop
                ifins.setTarget(code.nop());
                // if (pcVersionInit != false)
                // return true
                // else return null; //  (returning null because we don't know the correct answer)
                loadManagedInstance(code, false);
                getfield(code, null, VERSION_INIT_STR);
                ifins = code.ifeq();
                code.getstatic().setField(Boolean.class, "TRUE", Boolean.class);
                code.areturn();
                ifins.setTarget(code.nop());
                code.constant().setNull();
            }
            code.areturn();
            return false;
        }

        // consider detached if auto-genned primary keys are non-default
        ifins = null;
        JumpInstruction ifins2 = null;
        boolean hasAutoAssignedPK = false;
        if (state != Boolean.TRUE
            && _meta.getIdentityType() == ClassMetaData.ID_APPLICATION) {
            // for each pk field:
            // if (<pk> != <default> [&& !"".equals (<pk>)])
            //		return Boolean.TRUE;
            FieldMetaData[] pks = _meta.getPrimaryKeyFields();
            for (FieldMetaData pk : pks) {
                if (pk.getValueStrategy() == ValueStrategies.NONE)
                    continue;

                target = loadManagedInstance(code, false);
                if (ifins != null)
                    ifins.setTarget(target);
                if (ifins2 != null)
                    ifins2.setTarget(target);
                ifins2 = null;

                addGetManagedValueCode(code, pk);
                ifins = ifDefaultValue(code, pk);
                if (pk.getDeclaredTypeCode() == JavaTypes.STRING) {
                    code.constant().setValue("");
                    loadManagedInstance(code, false);
                    addGetManagedValueCode(code, pk);
                    code.invokevirtual().setMethod(String.class, "equals",
                            boolean.class, new Class[]{Object.class});
                    ifins2 = code.ifne();
                }
                code.getstatic().setField(Boolean.class, "TRUE",
                        Boolean.class);
                code.areturn();
            }
        }

        // create artificial target to simplify
        target = code.nop();
        if (ifins != null)
            ifins.setTarget(target);
        if (ifins2 != null)
            ifins2.setTarget(target);

        // if has auto-assigned pk and we get to this point, must have default
        // value, so must be new instance
        if (hasAutoAssignedPK) {
            code.getstatic().setField(Boolean.class, "FALSE", Boolean.class);
            code.areturn();
            return false;
        }

        // if detached state is not definitive, just give up now and return
        // null so that the runtime will perform a DB lookup to determine
        // whether we're detached or new
        code.aload().setThis();
        code.invokespecial().setMethod(ISDETACHEDSTATEDEFINITIVE, boolean.class,
            null);
        ifins = code.ifne();
        code.constant().setNull();
        code.areturn();
        ifins.setTarget(code.nop());

        // no detached state: if instance uses detached state and it's not
        // synthetic or the instance is not serializable or the state isn't
        // transient, must not be detached
        if (state == null
            && (!ClassMetaData.SYNTHETIC.equals(_meta.getDetachedState())
            || !Serializable.class.isAssignableFrom(_meta.getDescribedType())
            || !_repos.getConfiguration().getDetachStateInstance().
            isDetachedStateTransient())) {
            // return Boolean.FALSE
            code.getstatic().setField(Boolean.class, "FALSE", Boolean.class);
            code.areturn();
            return true;
        }

        // no detached state: if instance uses detached state (and must be
        // synthetic and transient in serializable instance at this point),
        // not detached if state not set to DESERIALIZED
        if (state == null) {
            // if (pcGetDetachedState () == null) // instead of DESERIALIZED
            //     return Boolean.FALSE;
            loadManagedInstance(code, false);
            code.invokevirtual().setMethod(PRE + "GetDetachedState",
                Object.class, null);
            ifins = code.ifnonnull();
            code.getstatic().setField(Boolean.class, "FALSE", Boolean.class);
            code.areturn();
            ifins.setTarget(code.nop());
        }

        // give up; we just don't know
        code.constant().setNull();
        code.areturn();
        return true;
    }

    /**
     * Compare the given field to its Java default, returning the
     * comparison instruction. The field value will already be on the stack.
     */
    private static JumpInstruction ifDefaultValue(Code code,
        FieldMetaData fmd) {
        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.BOOLEAN:
            case JavaTypes.BYTE:
            case JavaTypes.CHAR:
            case JavaTypes.INT:
            case JavaTypes.SHORT:
                return code.ifeq();
            case JavaTypes.DOUBLE:
                code.constant().setValue(0D);
                code.dcmpl();
                return code.ifeq();
            case JavaTypes.FLOAT:
                code.constant().setValue(0F);
                code.fcmpl();
                return code.ifeq();
            case JavaTypes.LONG:
                code.constant().setValue(0L);
                code.lcmp();
                return code.ifeq();
            default:
                return code.ifnull();
        }
    }

    /**
     * Helper method to get the code for the class initializer method,
     * creating the method if it does not already exist.
     */
    private Code getOrCreateClassInitCode(boolean replaceLast) {
        BCMethod clinit = _pc.getDeclaredMethod("<clinit>");
        Code code;
        if (clinit != null) {
            code = clinit.getCode(true);
            if (replaceLast) {
                Code template = AccessController.doPrivileged(
                    J2DoPrivHelper.newCodeAction());
                code.searchForward(template.vreturn());
                code.previous();
                code.set(template.nop());
                code.next();
            }
            return code;
        }

        // add static initializer method if non exists
        clinit = _pc.declareMethod("<clinit>", void.class, null);
        clinit.makePackage();
        clinit.setStatic(true);
        clinit.setFinal(true);

        code = clinit.getCode(true);
        if (!replaceLast) {
            code.vreturn();
            code.previous();
        }
        return code;
    }

    /**
     * Adds bytecode modifying the cloning behavior of the class being
     * enhanced to correctly replace the <code>pcStateManager</code>
     * instance fields of any clone created with their default values.
     * Also, if this class is the base PC type and does not declared
     * a clone method, one will be added. Also, if _pc is a synthetic
     * subclass, create the clone() method that clears the state manager
     * that may have been initialized in a super's clone() method.
     */
    private void addCloningCode() {
        if (_meta.getPCSuperclass() != null && !getCreateSubclass())
            return;

        // add the clone method if necessary
        BCMethod clone = _pc.getDeclaredMethod("clone",
            (String[]) null);
        String superName = _managedType.getSuperclassName();
        Code code = null;
        if (clone == null) {
            // add clone support for base classes
            // which also implement cloneable
            boolean isCloneable = Cloneable.class.isAssignableFrom(
                _managedType.getType());
            boolean extendsObject =
                superName.equals(Object.class.getName());
            if (!isCloneable || (!extendsObject && !getCreateSubclass()))
                return;

            if (!getCreateSubclass())
                if (_log.isTraceEnabled())
                    _log.trace(
                        _loc.get("enhance-cloneable", _managedType.getName()));

            // add clone method
            // protected Object clone () throws CloneNotSupportedException
            clone = _pc.declareMethod("clone", Object.class, null);
            if (!setVisibilityToSuperMethod(clone))
                clone.makeProtected();
            clone.getExceptions(true).addException
                (CloneNotSupportedException.class);
            code = clone.getCode(true);

            // return super.clone ();
            loadManagedInstance(code, false);
            code.invokespecial().setMethod(superName, "clone",
                Object.class.getName(), null);
            code.areturn();
        } else {
            // get the clone method code
            code = clone.getCode(false);
            if (code == null)
                return;
        }

        // create template super.clone () instruction to match against
        Instruction template = (AccessController.doPrivileged(
            J2DoPrivHelper.newCodeAction())).invokespecial()
            .setMethod(superName, "clone", Object.class.getName(), null);

        // find calls to the template instruction; on match
        // clone will be on stack
        code.beforeFirst();
        if (code.searchForward(template)) {
            // ((<type>) clone).pcStateManager = null;
            code.dup();
            code.checkcast().setType(_pc);
            code.constant().setNull();
            code.putfield().setField(SM, SMTYPE);

            // if modified, increase stack
            code.calculateMaxStack();
            code.calculateMaxLocals();
        }
    }

    /**
     * Gets the auxiliary enhancers registered as {@link Services services}.
     */
    public AuxiliaryEnhancer[] getAuxiliaryEnhancers() {
		return _auxEnhancers;
    }

    /**
     * Allow any registered auxiliary code generators to run.
     */
    private void runAuxiliaryEnhancers() {
        for (AuxiliaryEnhancer auxEnhancer : _auxEnhancers) {
            auxEnhancer.run(_pc, _meta);
        }
    }

    /**
     * Affirms if the given method be skipped.
     *
     * @param method method to be skipped or not
     * @return true if any of the auxiliary enhancers skips the given method,
     * or if the method is a constructor
     */
    private boolean skipEnhance(BCMethod method) {
        if ("<init>".equals(method.getName()))
            return true;

        for (AuxiliaryEnhancer auxEnhancer : _auxEnhancers)
            if (auxEnhancer.skipEnhance(method))
                return true;

        return false;
    }

    /**
     * Adds synthetic field access methods that will replace all direct
     * field accesses.
     */
    private void addAccessors()
        throws NoSuchMethodException {
        FieldMetaData[] fmds = getCreateSubclass() ? _meta.getFields()
            : _meta.getDeclaredFields();
        for (int i = 0; i < fmds.length; i++) {
            if (getCreateSubclass()) {
                if (!getRedefine() && isPropertyAccess(fmds[i])) {
                    addSubclassSetMethod(fmds[i]);
                    addSubclassGetMethod(fmds[i]);
                }
            } else {
                addGetMethod(i, fmds[i]);
                addSetMethod(i, fmds[i]);
            }
        }
    }

    /**
     * Adds a non-static setter that delegates to the super methods, and
     * performs any necessary field tracking.
     */
    private void addSubclassSetMethod(FieldMetaData fmd)
        throws NoSuchMethodException {
        Class propType = fmd.getDeclaredType();
        String setterName = getSetterName(fmd);
        BCMethod setter = _pc.declareMethod(setterName, void.class,
            new Class[] { propType });
        setVisibilityToSuperMethod(setter);
        Code code = setter.getCode(true);

        // not necessary if we're already tracking access via redefinition
        if (!getRedefine()) {
            // get the orig value onto stack
            code.aload().setThis();
            addGetManagedValueCode(code, fmd);
            int val = code.getNextLocalsIndex();
            code.xstore().setLocal(val).setType(fmd.getDeclaredType());
            addNotifyMutation(code, fmd, val, 0);
        }

        // ##### test case: B extends A. Methods defined in A. What
        // ##### happens?
        // super.setXXX(...)
        code.aload().setThis();
        code.xload().setParam(0).setType(propType);
        code.invokespecial().setMethod(_managedType.getType(),
            setterName, void.class, new Class[] { propType });

        code.vreturn();
        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    private boolean setVisibilityToSuperMethod(BCMethod method) {
        BCMethod[] methods = _managedType.getMethods(method.getName(),
            method.getParamTypes());
        if (methods.length == 0)
            throw new UserException(_loc.get("no-accessor",
                _managedType.getName(), method.getName()));
        BCMethod superMeth = methods[0];
        if (superMeth.isPrivate()) {
            method.makePrivate();
            return true;
        } else if (superMeth.isPackage()) {
            method.makePackage();
            return true;
        } else if (superMeth.isProtected()) {
            method.makeProtected();
            return true;
        } else if (superMeth.isPublic()) {
            method.makePublic();
            return true;
        }
        return false;
    }

    /**
     * Adds a non-static getter that delegates to the super methods, and
     * performs any necessary field tracking.
     */
    private void addSubclassGetMethod(FieldMetaData fmd) {
        String methName = "get" + StringUtil.capitalize(fmd.getName());
        if (_managedType.getMethods(methName, new Class[0]).length == 0)
            methName = "is" + StringUtil.capitalize(fmd.getName());
        BCMethod getter = _pc.declareMethod(methName, fmd.getDeclaredType(),
            null);
        setVisibilityToSuperMethod(getter);
        getter.makePublic();
        Code code = getter.getCode(true);

        // if we're not already tracking field access via reflection, then we
        // must make the getter hook in lazy loading before accessing the super
        // method.
        if (!getRedefine())
            addNotifyAccess(code, fmd);

        code.aload().setThis();
        code.invokespecial().setMethod(_managedType.getType(), methName,
            fmd.getDeclaredType(), null);
        code.xreturn().setType(fmd.getDeclaredType());
        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    /**
     * Adds a static getter method for the given field.
     * The generated method interacts with the instance state and the
     * StateManager to get the value of the field.
     *
     * @param index the relative number of the field
     * @param fmd metadata about the field to get
     */
    private void addGetMethod(int index, FieldMetaData fmd)
        throws NoSuchMethodException {
        BCMethod method = createGetMethod(fmd);
        Code code = method.getCode(true);

        // if reads are not checked, just return the value
        byte fieldFlag = getFieldFlag(fmd);
        if ((fieldFlag & PersistenceCapable.CHECK_READ) == 0
            && (fieldFlag & PersistenceCapable.MEDIATE_READ) == 0) {
            loadManagedInstance(code, true, fmd);
            addGetManagedValueCode(code, fmd);
            code.xreturn().setType(fmd.getDeclaredType());

            code.calculateMaxStack();
            code.calculateMaxLocals();
            return;
        }

        // if (inst.pcStateManager == null) return inst.<field>;
        loadManagedInstance(code, true, fmd);
        code.getfield().setField(SM, SMTYPE);
        JumpInstruction ifins = code.ifnonnull();
        loadManagedInstance(code, true, fmd);
        addGetManagedValueCode(code, fmd);
        code.xreturn().setType(fmd.getDeclaredType());

        // int field = pcInheritedFieldCount + <fieldindex>;
        int fieldLocal = code.getNextLocalsIndex();
        ifins.setTarget(code.getstatic().setField(INHERIT, int.class));
        code.constant().setValue(index);
        code.iadd();
        code.istore().setLocal(fieldLocal);

        // inst.pcStateManager.accessingField (field);
        // return inst.<field>;
        loadManagedInstance(code, true, fmd);
        code.getfield().setField(SM, SMTYPE);
        code.iload().setLocal(fieldLocal);
        code.invokeinterface().setMethod(SMTYPE, "accessingField", void.class,
            new Class[]{ int.class });
        loadManagedInstance(code, true, fmd);
        addGetManagedValueCode(code, fmd);
        code.xreturn().setType(fmd.getDeclaredType());

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds a static setter method for the given field.
     * The generated method interacts with the instance state and the
     * StateManager to set the value of the field.
     *
     * @param index the relative number of the field
     * @param fmd metadata about the field to set
     */
    private void addSetMethod(int index, FieldMetaData fmd)
        throws NoSuchMethodException {
        BCMethod method = createSetMethod(fmd);
        Code code = method.getCode(true);

        // PCEnhancer uses static methods; PCSubclasser does not.
        int firstParamOffset = getAccessorParameterOffset(fmd);

        // if (inst.pcStateManager == null) inst.<field> = value;
        loadManagedInstance(code, true, fmd);
        code.getfield().setField(SM, SMTYPE);
        JumpInstruction ifins = code.ifnonnull();
        loadManagedInstance(code, true, fmd);
        code.xload().setParam(firstParamOffset);
        addSetManagedValueCode(code, fmd);
        if(fmd.isVersion() && _addVersionInitFlag){
            // if we are setting the version, flip the versionInit flag to true
            loadManagedInstance(code, true);
            code.constant().setValue(1);
            // pcVersionInit = true;
            putfield(code, null, VERSION_INIT_STR, boolean.class);
        }
        code.vreturn();

        // inst.pcStateManager.setting<fieldType>Field (inst,
        //     pcInheritedFieldCount + <index>, inst.<field>, value, 0);
        ifins.setTarget(loadManagedInstance(code, true, fmd));
        code.getfield().setField(SM, SMTYPE);
        loadManagedInstance(code, true, fmd);
        code.getstatic().setField(INHERIT, int.class);
        code.constant().setValue(index);
        code.iadd();
        loadManagedInstance(code, true, fmd);
        addGetManagedValueCode(code, fmd);
        code.xload().setParam(firstParamOffset);
        code.constant().setValue(0);
        code.invokeinterface().setMethod(getStateManagerMethod
            (fmd.getDeclaredType(), "setting", false, true));
        code.vreturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Determines which attach / detach methods to use.
     */
    private void addAttachDetachCode()
        throws NoSuchMethodException {
        // see if any superclasses are detachable
        boolean parentDetachable = false;
        for (ClassMetaData parent = _meta.getPCSuperclassMetaData();
            parent != null; parent = parent.getPCSuperclassMetaData()) {
            if (parent.isDetachable()) {
                parentDetachable = true;
                break;
            }
        }

        // if parent not detachable, we need to add the detach state fields and
        // accessor methods
        if (_meta.getPCSuperclass() == null || getCreateSubclass()
            || parentDetachable != _meta.isDetachable()) {
            addIsDetachedMethod();
            addDetachedStateMethods(_meta.usesDetachedState()
                != Boolean.FALSE);
        }

        // if we detach on serialize, we also need to implement the
        // externalizable interface to write just the state for the fields
        // being detached
        if (externalizeDetached()) {
            try {
                addDetachExternalize(parentDetachable,
                    _meta.usesDetachedState() != Boolean.FALSE);
            } catch (NoSuchMethodException nsme) {
                throw new GeneralException(nsme);
            }
        }
    }

    /**
     * Add the fields to hold detached state and their accessor methods.
     *
     * @param impl whether to fully implement detach state functionality
     */
    private void addDetachedStateMethods(boolean impl) {
        Field detachField = _meta.getDetachedStateField();
        String name = null;
        String declarer = null;
        if (impl && detachField == null) {
            name = PRE + "DetachedState";
            declarer = _pc.getName();
            BCField field = _pc.declareField(name, Object.class);
            field.makePrivate();
            field.setTransient(true);
        } else if (impl) {
            name = detachField.getName();
            declarer = detachField.getDeclaringClass().getName();
        }

        // public Object pcGetDetachedState ()
        BCMethod method = _pc.declareMethod(PRE + "GetDetachedState",
            Object.class, null);
        method.setStatic(false);
        method.makePublic();
        int access = method.getAccessFlags();

        Code code = method.getCode(true);
        if (impl) {
            // return pcDetachedState;
            loadManagedInstance(code, false);
            getfield(code, _managedType.getProject().loadClass(declarer),
                name);
        } else
            code.constant().setNull();
        code.areturn();
        code.calculateMaxLocals();
        code.calculateMaxStack();

        // public void pcSetDetachedState (Object state)
        method = _pc.declareMethod(PRE + "SetDetachedState",
            void.class, new Class []{ Object.class });
        method.setAccessFlags(access);
        code = method.getCode(true);
        if (impl) {
            // pcDetachedState = state;
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            putfield(code, _managedType.getProject().loadClass(declarer),
                name, Object.class);
        }
        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Adds to <code>code</code> the instructions to get field
     * <code>attrName</code> declared in type <code>declarer</code>
     * onto the top of the stack.
     *
     * The instance to access must already be on the top of the
     * stack when this is invoked.
     */
    private void getfield(Code code, BCClass declarer, String attrName) {
        if (declarer == null)
            declarer = _managedType;

        // first, see if we can convert the attribute name to a field name
        String fieldName = toBackingFieldName(attrName);

        // next, find the field in the managed type hierarchy
        BCField field = null;
        outer: for (BCClass bc = _pc; bc != null; bc = bc.getSuperclassBC()) {
            BCField[] fields = AccessController
                .doPrivileged(J2DoPrivHelper.getBCClassFieldsAction(bc,
                    fieldName));
            for (BCField bcField : fields) {
                field = bcField;
                // if we reach a field declared in this type, then this is the
                // most-masking field, and is the one that we want.
                if (bcField.getDeclarer() == declarer) {
                    break outer;
                }
            }
        }

        if (getCreateSubclass() && code.getMethod().getDeclarer() == _pc
            && (field == null || !field.isPublic())) {
            // we're creating the subclass, not redefining the user type.

            // Reflection.getXXX(this, Reflection.findField(...));
            code.classconstant().setClass(declarer);
            code.constant().setValue(fieldName);
            code.constant().setValue(true);
            code.invokestatic().setMethod(Reflection.class,
                "findField", Field.class, new Class[] {
                Class.class, String.class, boolean.class });
            Class type = _meta.getField(attrName).getDeclaredType();
            try {
                code.invokestatic().setMethod(
                    getReflectionGetterMethod(type, Field.class));
            } catch (NoSuchMethodException e) {
                // should never happen
                throw new InternalException(e);
            }
            if (!type.isPrimitive() && type != Object.class)
                code.checkcast().setType(type);
        } else {
            code.getfield().setField(declarer.getName(), fieldName,
                field.getType().getName());
        }
    }

    /**
     * Adds to <code>code</code> the instructions to set field
     * <code>attrName</code> declared in type <code>declarer</code>
     * to the value of type <code>fieldType</code> on the top of the stack.
     *
     * When this method is invoked, the value to load must
     * already be on the top of the stack in <code>code</code>,
     * and the instance to load into must be second.
     */
    private void putfield(Code code, BCClass declarer, String attrName,
        Class fieldType) {
        if (declarer == null)
            declarer = _managedType;

        String fieldName = toBackingFieldName(attrName);

        if (getRedefine() || getCreateSubclass()) {
            // Reflection.set(this, Reflection.findField(...), value);
            code.classconstant().setClass(declarer);
            code.constant().setValue(fieldName);
            code.constant().setValue(true);
            code.invokestatic().setMethod(Reflection.class,
                "findField", Field.class, new Class[] {
                Class.class, String.class, boolean.class });
            code.invokestatic().setMethod(Reflection.class, "set",
                void.class,
                new Class[] {
                    Object.class,
                    fieldType.isPrimitive() ? fieldType : Object.class,
                    Field.class });
        } else {
            code.putfield()
                .setField(declarer.getName(), fieldName, fieldType.getName());
        }
    }

    /**
     * If using property access, see if there is a different backing field
     * name for the persistent attribute <code>name</code>.
     */
    private String toBackingFieldName(String name) {
        // meta is null when enhancing persistence-aware
    	FieldMetaData fmd = _meta == null ? null : _meta.getField(name);
        if (_meta != null && isPropertyAccess(fmd)
            && _attrsToFields != null && _attrsToFields.containsKey(name))
            name = (String)_attrsToFields.get(name);
        return name;
    }

    /**
     * If using property access, see if there is a different persistent
     * attribute name for the backing field <code>name</code>.
     */
    private String fromBackingFieldName(String name) {
        // meta is null when enhancing persistence-aware
    	FieldMetaData fmd = _meta == null ? null : _meta.getField(name);
        if (_meta != null && isPropertyAccess(fmd)
            && _fieldsToAttrs != null && _fieldsToAttrs.containsKey(name))
            return (String)_fieldsToAttrs.get(name);
        else
            return name;
    }

    /**
     * Implement the externalizable interface to detach on serialize.
     */
    private void addDetachExternalize(boolean parentDetachable,
        boolean detachedState)
        throws NoSuchMethodException {
        // ensure that the declared default constructor is public
        // for externalization
        BCMethod meth = _pc.getDeclaredMethod("<init>", (String[]) null);
        if (!meth.isPublic()) {
            if (_log.isWarnEnabled())
                _log.warn(_loc.get("enhance-defcons-extern",
                  _meta.getDescribedType()));
            meth.makePublic();
        }
        // declare externalizable interface
        if (!Externalizable.class.isAssignableFrom(_meta.getDescribedType()))
            _pc.declareInterface(Externalizable.class);

        // make sure the user doesn't already have custom externalization or
        // serialization methods
        Class[] input = new Class[]{ ObjectInputStream.class };
        Class[] output = new Class[]{ ObjectOutputStream.class };
        if (_managedType.getDeclaredMethod("readObject", input) != null
            || _managedType.getDeclaredMethod("writeObject", output) != null)
            throw new UserException(_loc.get("detach-custom-ser", _meta));
        input[0] = ObjectInput.class;
        output[0] = ObjectOutput.class;
        if (_managedType.getDeclaredMethod("readExternal", input) != null
            || _managedType.getDeclaredMethod("writeExternal", output) != null)
            throw new UserException(_loc.get("detach-custom-extern", _meta));

        // create list of all unmanaged serializable fields
        BCField[] fields = _managedType.getDeclaredFields();
        Collection unmgd = new ArrayList(fields.length);
        for (BCField field : fields) {
            if (!field.isTransient() && !field.isStatic()
                    && !field.isFinal()
                    && !field.getName().startsWith(PRE)
                    && _meta.getDeclaredField(field.getName()) == null)
                unmgd.add(field);
        }

        addReadExternal(parentDetachable, detachedState);
        addReadUnmanaged(unmgd, parentDetachable);
        addWriteExternal(parentDetachable, detachedState);
        addWriteUnmanaged(unmgd, parentDetachable);
    }

    /**
     * Add custom readExternal method.
     */
    private void addReadExternal(boolean parentDetachable,
        boolean detachedState)
        throws NoSuchMethodException {
        Class[] inargs = new Class[]{ ObjectInput.class };
        BCMethod meth = _pc.declareMethod("readExternal", void.class, inargs);
        Exceptions exceps = meth.getExceptions(true);
        exceps.addException(IOException.class);
        exceps.addException(ClassNotFoundException.class);
        Code code = meth.getCode(true);

        // super.readExternal (in);
        // not sure if this works: this is depending on the order of the enhancement!
        // if the subclass gets enhanced first, then the superclass misses
        // the Externalizable at this point!
        Class<?> sup = _meta.getDescribedType().getSuperclass();
        if (!parentDetachable && Externalizable.class.isAssignableFrom(sup)) {
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokespecial().setMethod(sup, "readExternal",
                void.class, inargs);
        }

        // readUnmanaged (in);
        loadManagedInstance(code, false);
        code.aload().setParam(0);
        code.invokevirtual().setMethod(getType(_meta),
            PRE + "ReadUnmanaged", void.class, inargs);

        if (detachedState) {
            // pcSetDetachedState (in.readObject ());
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokeinterface().setMethod(ObjectInput.class, "readObject",
                Object.class, null);
            code.invokevirtual().setMethod(PRE + "SetDetachedState",
                void.class, new Class[]{ Object.class });

            // pcReplaceStateManager ((StateManager) in.readObject ());
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokeinterface().setMethod(ObjectInput.class, "readObject",
                Object.class, null);
            code.checkcast().setType(StateManager.class);
            code.invokevirtual().setMethod(PRE + "ReplaceStateManager",
                void.class, new Class[]{ StateManager.class });
        }

        addReadExternalFields();

        // readExternalFields(in.readObject ());
        loadManagedInstance(code, false);
        code.aload().setParam(0);
        code.invokevirtual().setMethod("readExternalFields",
            void.class, inargs);

        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    private void addReadExternalFields() throws NoSuchMethodException {
        Class<?>[] inargs = new Class[]{ ObjectInput.class };
        BCMethod meth = _pc.declareMethod("readExternalFields", void.class, inargs);
        meth.setAccessFlags(Constants.ACCESS_PROTECTED);
        Exceptions exceps = meth.getExceptions(true);
        exceps.addException(IOException.class);
        exceps.addException(ClassNotFoundException.class);
        Code code = meth.getCode(true);

        Class<?> sup = _meta.getPCSuperclass();
        if (sup != null) {
            //add a call to super.readExternalFields()
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokespecial().setMethod(sup, "readExternalFields", void.class, inargs);
        }

        // read managed fields
        FieldMetaData[] fmds = _meta.getDeclaredFields();
        for (FieldMetaData fmd : fmds) {
            if (!fmd.isTransient()) {
                readExternal(code, fmd.getName(),
                        fmd.getDeclaredType(), fmd);
            }
        }

        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Read unmanaged fields from the stream (pcReadUnmanaged).
     */
    private void addReadUnmanaged(Collection unmgd, boolean parentDetachable)
        throws NoSuchMethodException {
        Class[] inargs = new Class[]{ ObjectInput.class };
        BCMethod meth = _pc.declareMethod(PRE + "ReadUnmanaged", void.class,
            inargs);
        meth.makeProtected();
        Exceptions exceps = meth.getExceptions(true);
        exceps.addException(IOException.class);
        exceps.addException(ClassNotFoundException.class);
        Code code = meth.getCode(true);

        // super.readUnmanaged (in);
        if (parentDetachable) {
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokespecial().setMethod(getType(_meta.
                getPCSuperclassMetaData()), PRE + "ReadUnmanaged", void.class,
                inargs);
        }

        // read declared unmanaged serializable fields
        BCField field;
        for (Object o : unmgd) {
            field = (BCField) o;
            readExternal(code, field.getName(), field.getType(), null);
        }
        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Helper method to read a field from an externalization input stream.
     */
    private void readExternal(Code code, String fieldName, Class type,
        FieldMetaData fmd)
        throws NoSuchMethodException {
        String methName;
        if (type.isPrimitive()) {
            methName = type.getName();
            methName = methName.substring(0, 1).toUpperCase(Locale.ENGLISH)
                + methName.substring(1);
            methName = "read" + methName;
        } else
            methName = "readObject";

        // <field> = in.read<type> ();
        loadManagedInstance(code, false);
        code.aload().setParam(0);
        Class ret = (type.isPrimitive()) ? type : Object.class;
        code.invokeinterface().setMethod(ObjectInput.class, methName,
            ret, null);
        if (!type.isPrimitive() && type != Object.class)
            code.checkcast().setType(type);
        if (fmd == null)
            putfield(code, null, fieldName, type);
        else {
            addSetManagedValueCode(code, fmd);
            switch (fmd.getDeclaredTypeCode()) {
                case JavaTypes.DATE:
                case JavaTypes.ARRAY:
                case JavaTypes.COLLECTION:
                case JavaTypes.MAP:
                case JavaTypes.OBJECT:
                case JavaTypes.CALENDAR:
                    // if (sm != null)
                    //   sm.proxyDetachedDeserialized (<index>);
                    loadManagedInstance(code, false);
                    code.getfield().setField(SM, SMTYPE);
                    IfInstruction ifins = code.ifnull();
                    loadManagedInstance(code, false);
                    code.getfield().setField(SM, SMTYPE);
                    code.constant().setValue(fmd.getIndex());
                    code.invokeinterface().setMethod(SMTYPE,
                        "proxyDetachedDeserialized", void.class,
                        new Class[]{ int.class });
                    ifins.setTarget(code.nop());
            }
        }
    }

    /**
     * Add custom writeExternal method.
     */
    private void addWriteExternal(boolean parentDetachable,
        boolean detachedState)
        throws NoSuchMethodException {
        Class[] outargs = new Class[]{ ObjectOutput.class };
        BCMethod meth = _pc.declareMethod("writeExternal", void.class, outargs);
        Exceptions exceps = meth.getExceptions(true);
        exceps.addException(IOException.class);
        Code code = meth.getCode(true);

        // super.writeExternal (out);
        Class sup = getType(_meta).getSuperclass();
        if (!parentDetachable && Externalizable.class.isAssignableFrom(sup)) {
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokespecial().setMethod(sup, "writeExternal",
                void.class, outargs);
        }

        // writeUnmanaged (out);
        loadManagedInstance(code, false);
        code.aload().setParam(0);
        code.invokevirtual().setMethod(getType(_meta),
            PRE + "WriteUnmanaged", void.class, outargs);

        JumpInstruction go2 = null;
        if (detachedState) {
            // if (sm != null)
            //   if (sm.writeDetached (out))
            //      return;
            loadManagedInstance(code, false);
            code.getfield().setField(SM, SMTYPE);
            IfInstruction ifnull = code.ifnull();
            loadManagedInstance(code, false);
            code.getfield().setField(SM, SMTYPE);
            code.aload().setParam(0);
            code.invokeinterface().setMethod(SMTYPE, "writeDetached",
                boolean.class, outargs);
            go2 = code.ifeq();
            code.vreturn();

            // else
            //   out.writeObject (pcGetDetachedState ());
            Class[] objargs = new Class[]{ Object.class };
            ifnull.setTarget(code.aload().setParam(0));
            loadManagedInstance(code, false);
            code.invokevirtual().setMethod(PRE + "GetDetachedState",
                Object.class, null);
            code.invokeinterface().setMethod(ObjectOutput.class,
                "writeObject", void.class, objargs);
            //    out.writeObject (null) // StateManager
            code.aload().setParam(0);
            code.constant().setValue((Object) null);
            code.invokeinterface().setMethod(ObjectOutput.class,
                "writeObject", void.class, objargs);
        }
        if (go2 != null)
            go2.setTarget(code.nop());

        addWriteExternalFields();

        loadManagedInstance(code, false);
        code.aload().setParam(0);
        code.invokevirtual().setMethod("writeExternalFields",
            void.class, outargs);

        // return
        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }


    private void addWriteExternalFields()
        throws NoSuchMethodException {
        Class<?>[] outargs = new Class[]{ ObjectOutput.class };
        BCMethod meth = _pc.declareMethod("writeExternalFields", void.class, outargs);
        meth.setAccessFlags(Constants.ACCESS_PROTECTED);
        Exceptions exceps = meth.getExceptions(true);
        exceps.addException(IOException.class);
        Code code = meth.getCode(true);

        Class<?> sup = _meta.getPCSuperclass();
        if (sup != null) {
            // add a call to super.readExternalFields()
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokespecial().setMethod(sup, "writeExternalFields", void.class, outargs);
        }

        FieldMetaData[] fmds = _meta.getDeclaredFields();
        for (FieldMetaData fmd : fmds) {
            if (!fmd.isTransient()) {
                writeExternal(code, fmd.getName(),
                        fmd.getDeclaredType(), fmd);
            }
        }

        // return
        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Write unmanaged fields to the stream (pcWriteUnmanaged).
     */
    private void addWriteUnmanaged(Collection unmgd, boolean parentDetachable)
        throws NoSuchMethodException {
        Class[] outargs = new Class[]{ ObjectOutput.class };
        BCMethod meth = _pc.declareMethod(PRE + "WriteUnmanaged", void.class,
            outargs);
        meth.makeProtected();
        Exceptions exceps = meth.getExceptions(true);
        exceps.addException(IOException.class);
        Code code = meth.getCode(true);

        // super.writeUnmanaged (out);
        if (parentDetachable) {
            loadManagedInstance(code, false);
            code.aload().setParam(0);
            code.invokespecial().setMethod(getType(_meta.
                getPCSuperclassMetaData()), PRE + "WriteUnmanaged", void.class,
                outargs);
        }

        // write declared unmanaged serializable fields
        BCField field;
        for (Object o : unmgd) {
            field = (BCField) o;
            writeExternal(code, field.getName(), field.getType(), null);
        }
        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Helper method to write a field to an externalization output stream.
     */
    private void writeExternal(Code code, String fieldName, Class type,
        FieldMetaData fmd)
        throws NoSuchMethodException {
        String methName;
        if (type.isPrimitive()) {
            methName = type.getName();
            methName = methName.substring(0, 1).toUpperCase(Locale.ENGLISH)
                + methName.substring(1);
            methName = "write" + methName;
        } else
            methName = "writeObject";

        // out.write<type> (<field>);
        code.aload().setParam(0);
        loadManagedInstance(code, false);
        if (fmd == null)
            getfield(code, null, fieldName);
        else
            addGetManagedValueCode(code, fmd);
        Class[] args = new Class[]{ type };
        if (type == byte.class || type == char.class || type == short.class)
            args[0] = int.class;
        else if (!type.isPrimitive())
            args[0] = Object.class;
        code.invokeinterface().setMethod(ObjectOutput.class, methName,
            void.class, args);
    }

    private void addGetManagedValueCode(Code code, FieldMetaData fmd)
        throws NoSuchMethodException {
        addGetManagedValueCode(code, fmd, true);
    }

    /**
     * Load the field value specified by <code>fmd</code> onto the stack.
     * Before this method is called, the object that the data should be loaded
     * from will be on the top of the stack.
     *
     * @param fromSameClass if <code>true</code>, then <code>fmd</code> is
     * being loaded from an instance of the same class as the current execution
     * context. If <code>false</code>, then the instance on the top of the stack
     * might be a superclass of the current execution context's 'this' instance.
     */
    private void addGetManagedValueCode(Code code, FieldMetaData fmd,
        boolean fromSameClass)
        throws NoSuchMethodException {
        // if redefining, then we must always reflect (or access the field
        // directly if accessible), since the redefined methods will always
        // trigger method calls to StateManager, even from internal direct-
        // access usage. We could work around this by not redefining, and
        // just do a subclass approach instead. But this is not a good option,
        // since it would sacrifice lazy loading and efficient dirty tracking.

        if (getRedefine() || isFieldAccess(fmd)) {
            getfield(code, null, fmd.getName());
        } else if (getCreateSubclass()) {
            // property access, and we're not redefining. If we're operating
            // on an instance that is definitely the same type as 'this', then
            // call superclass method to bypass tracking. Otherwise, reflect
            // to both bypass tracking and avoid class verification errors.
            if (fromSameClass) {
                Method meth = (Method) fmd.getBackingMember();
                code.invokespecial().setMethod(meth);
            } else {
                getfield(code, null, fmd.getName());
            }
        } else {
            // regular enhancement + property access
            Method meth = (Method) fmd.getBackingMember();
            code.invokevirtual().setMethod(PRE + meth.getName(),
                meth.getReturnType(), meth.getParameterTypes());
        }
    }

    /**
     * Store the value at the top of the stack into the field value specified
     * by <code>fmd</code>. Before this method is called, the data to load will
     * be on the top of the stack and the object that the data should be loaded
     * into will be second in the stack.
     */
    private void addSetManagedValueCode(Code code, FieldMetaData fmd)
        throws NoSuchMethodException {
        // if redefining, then we must always reflect (or access the field
        // directly if accessible), since the redefined methods will always
        // trigger method calls to StateManager, even from internal direct-
        // access usage. We could work around this by not redefining, and
        // just do a subclass approach instead. But this is not a good option,
        // since it would sacrifice lazy loading and efficient dirty tracking.

        if (getRedefine() || isFieldAccess(fmd)) {
            putfield(code, null, fmd.getName(), fmd.getDeclaredType());
        } else if (getCreateSubclass()) {
            // property access, and we're not redefining. invoke the
            // superclass method to bypass tracking.
            code.invokespecial().setMethod(_managedType.getType(),
                getSetterName(fmd), void.class,
                new Class[] { fmd.getDeclaredType() });
        } else {
            // regular enhancement + property access
            code.invokevirtual().setMethod(PRE + getSetterName(fmd),
                void.class, new Class[] { fmd.getDeclaredType() });
        }
    }

    /**
     * Add the {@link Instruction}s to load the instance to modify onto the
     * stack, and return it. If <code>forStatic</code> is set, then
     * <code>code</code> is in an accessor method or another static method;
     * otherwise, it is in one of the PC-specified methods.
     *
     * @return the first instruction added to <code>code</code>.
     */
    private Instruction loadManagedInstance(Code code, boolean forStatic,
            FieldMetaData fmd) {
        if (forStatic && isFieldAccess(fmd))
            return code.aload().setParam(0);
        return code.aload().setThis();
    }

    /**
     * Add the {@link Instruction}s to load the instance to modify onto the
     * stack, and return it.  This method should not be used to load static
     * fields.
     *
     * @return the first instruction added to <code>code</code>.
     */
    private Instruction loadManagedInstance(Code code, boolean forStatic) {
    	return loadManagedInstance(code, forStatic, null);
    }

    private int getAccessorParameterOffset(FieldMetaData fmd) {
       return isFieldAccess(fmd) ? 1 : 0;
    }

    /**
     * Affirms if the given class is using field-based access.
     */
    boolean isPropertyAccess(ClassMetaData meta) {
    	return meta != null && (meta.isMixedAccess() ||
    		AccessCode.isProperty(meta.getAccessType()));
    }

    /**
     * Affirms if the given field is using field-based access.
     */
    boolean isPropertyAccess(FieldMetaData fmd) {
    	return fmd != null && AccessCode.isProperty(fmd.getAccessType());
    }

    /**
     * Affirms if the given field is using method-based access.
     */
    boolean isFieldAccess(FieldMetaData fmd) {
    	return fmd != null && AccessCode.isField(fmd.getAccessType());
    }

    /**
     * Create the generated getter {@link BCMethod} for <code>fmd</code>. The
     * calling environment will then populate this method's code block.
     */
    private BCMethod createGetMethod(FieldMetaData fmd) {
        BCMethod getter;
        if (isFieldAccess(fmd)) {
            // static <fieldtype> pcGet<field> (XXX inst)
            BCField field = _pc.getDeclaredField(fmd.getName());
            getter = _pc.declareMethod(PRE + "Get" + fmd.getName(), fmd.
                getDeclaredType().getName(), new String[]{ _pc.getName() });
            getter.setAccessFlags(field.getAccessFlags()
                & ~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE);
            getter.setStatic(true);
            getter.setFinal(true);
            return getter;
        }

        // property access:
        // copy the user's getter method to a new name; we can't just reset
        // the name, because that will also reset all calls to the method
        Method meth = (Method) fmd.getBackingMember();
        getter = _pc.getDeclaredMethod(meth.getName(),
            meth.getParameterTypes());
        BCMethod newgetter = _pc.declareMethod(PRE + meth.getName(),
            meth.getReturnType(), meth.getParameterTypes());
        newgetter.setAccessFlags(getter.getAccessFlags());
        newgetter.makeProtected();
        transferCodeAttributes(getter, newgetter);
        return getter;
    }

    /**
     * Create the generated setter {@link BCMethod} for <code>fmd</code>. The
     * calling environment will then populate this method's code block.
     */
    private BCMethod createSetMethod(FieldMetaData fmd) {
        BCMethod setter;
        if (isFieldAccess(fmd)) {
            // static void pcSet<field> (XXX inst, <fieldtype> value)
            BCField field = _pc.getDeclaredField(fmd.getName());
            setter = _pc.declareMethod(PRE + "Set" + fmd.getName(), void.class,
                new Class[]{ getType(_meta), fmd.getDeclaredType() });
            setter.setAccessFlags(field.getAccessFlags()
                & ~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE);
            setter.setStatic(true);
            setter.setFinal(true);
            return setter;
        }

        // property access:
        // copy the user's getter method to a new name; we can't just reset
        // the name, because that will also reset all calls to the method
        setter = _pc.getDeclaredMethod(getSetterName(fmd),
            new Class[]{ fmd.getDeclaredType() });
        BCMethod newsetter = _pc.declareMethod(PRE + setter.getName(),
            setter.getReturnName(), setter.getParamNames());
        newsetter.setAccessFlags(setter.getAccessFlags());
        newsetter.makeProtected();
        transferCodeAttributes(setter, newsetter);
        return setter;
    }

    private void addGetEnhancementContractVersionMethod() {
        // public int getEnhancementContractVersion()
        BCMethod method = _pc.declareMethod(PRE +
                "GetEnhancementContractVersion", int.class, null);
        method.makePublic();
        Code code = method.getCode(true);
        code.constant().setValue(ENHANCER_VERSION);
        code.ireturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Return the concrete type for the given class, i.e. impl for managed
     * interfaces
     */
    public Class getType(ClassMetaData meta) {
        if (meta.getInterfaceImpl() != null)
            return meta.getInterfaceImpl();
        return meta.getDescribedType();
    }

    /**
     * Move code-related attributes from one method to another.
     */
    private static void transferCodeAttributes(BCMethod from, BCMethod to) {
        Code code = from.getCode(false);
        if (code != null) {
            to.addAttribute(code);
            from.removeCode();
        }

        Exceptions exceps = from.getExceptions(false);
        if (exceps != null)
            to.addAttribute(exceps);
    }

    /**
     * Usage: java org.apache.openjpa.enhance.PCEnhancer [option]*
     * &lt;class name | .java file | .class file | .jdo file&gt;+
     *  Where the following options are recognized.
     * <ul>
     * <li><i>-properties/-p &lt;properties file&gt;</i>: The path to a OpenJPA
     * properties file containing information as outlined in
     * {@link Configuration}; optional.</li>
     * <li><i>-&lt;property name&gt; &lt;property value&gt;</i>: All bean
     * properties of the standard OpenJPA {@link OpenJPAConfiguration} can be
     * set by using their names and supplying a value; for example:
     * <li><i>-directory/-d &lt;build directory&gt;</i>: The path to the base
     * directory where enhanced classes are stored. By default, the
     * enhancer overwrites the original .class file with the enhanced
     * version. Use this option to store the generated .class file in
     * another directory. The package structure will be created beneath
     * the given directory.</li>
     * <li><i>-addDefaultConstructor/-adc [true/t | false/f]</i>: Whether to
     * add a default constructor to persistent classes missing one, as
     * opposed to throwing an exception. Defaults to true.</li>
     * <li><i>-tmpClassLoader/-tcl [true/t | false/f]</i>: Whether to
     * load the pre-enhanced classes using a temporary class loader.
     * Defaults to true. Set this to false when attempting to debug
     * class loading errors.</li>
     * <li><i>-enforcePropertyRestrictions/-epr [true/t | false/f]</i>:
     * Whether to throw an exception if a PROPERTY access entity appears
     * to be violating standard property restrictions. Defaults to false.</li>
     * </ul>
     *  Each additional argument can be either the full class name of the
     * type to enhance, the path to the .java file for the type, the path to
     * the .class file for the type, or the path to a .jdo file listing one
     * or more types to enhance.
     * If the type being enhanced has metadata, it will be enhanced as a
     * persistence capable class. If not, it will be considered a persistence
     * aware class, and all access to fields of persistence capable classes
     * will be replaced by the appropriate	get/set method. If the type
     * explicitly declares the persistence-capable interface, it will
     * not be enhanced. Thus, it is safe to invoke the enhancer on classes
     * that are already enhanced.
     */
    public static void main(String[] args) {
        Options opts = new Options();
        args = opts.setFromCmdLine(args);
        if (!run(args, opts)) {
            // START - ALLOW PRINT STATEMENTS
            System.err.println(_loc.get("enhance-usage"));
            // STOP - ALLOW PRINT STATEMENTS
        }
    }

    /**
     * Run the tool. Returns false if invalid options given. Runs against all
     * the persistence units defined in the resource to parse.
     */
    public static boolean run(final String[] args, Options opts) {
        return Configurations.runAgainstAllAnchors(opts,
            new Configurations.Runnable() {
            @Override
            public boolean run(Options opts) throws IOException {
                OpenJPAConfiguration conf = new OpenJPAConfigurationImpl();
                try {
                    return PCEnhancer.run(conf, args, opts);
                } finally {
                    conf.close();
                }
            }
        });
    }

    /**
     * Run the tool. Returns false if invalid options given.
     */
    public static boolean run(OpenJPAConfiguration conf, String[] args,
        Options opts)
        throws IOException {
        Flags flags = new Flags();
        flags.directory = Files.getFile(opts.removeProperty("directory", "d",
            null), null);
        flags.addDefaultConstructor = opts.removeBooleanProperty
            ("addDefaultConstructor", "adc", flags.addDefaultConstructor);
        flags.tmpClassLoader = opts.removeBooleanProperty
            ("tmpClassLoader", "tcl", flags.tmpClassLoader);
        flags.enforcePropertyRestrictions = opts.removeBooleanProperty
            ("enforcePropertyRestrictions", "epr",
                flags.enforcePropertyRestrictions);

        // for unit testing
        BytecodeWriter writer = (BytecodeWriter) opts.get(
            PCEnhancer.class.getName() + "#bytecodeWriter");

        Configurations.populateConfiguration(conf, opts);
        return run(conf, args, flags, null, writer, null);
    }

    /**
     * Enhance the given classes.
     */
    public static boolean run(OpenJPAConfiguration conf, String[] args,
        Flags flags, MetaDataRepository repos, BytecodeWriter writer,
        ClassLoader loader)
        throws IOException {
        if (loader == null)
            loader = conf.getClassResolverInstance().
                getClassLoader(PCEnhancer.class, null);
        if (flags.tmpClassLoader)
            loader = AccessController.doPrivileged(J2DoPrivHelper
                .newTemporaryClassLoaderAction(loader));

        if (repos == null) {
            repos = conf.newMetaDataRepositoryInstance();
            repos.setSourceMode(MetaDataModes.MODE_META);
        }

        Log log = conf.getLog(OpenJPAConfiguration.LOG_TOOL);
        Collection classes;
        if (args == null || args.length == 0) {
            classes = repos.getPersistentTypeNames(true, loader);
            if (classes == null) {
            	log.warn(_loc.get("no-class-to-enhance"));
            	return false;
            }
        } else {
            ClassArgParser cap = conf.getMetaDataRepositoryInstance().
                getMetaDataFactory().newClassArgParser();
            cap.setClassLoader(loader);
            classes = new HashSet();
            for (String arg : args) {
                classes.addAll(Arrays.asList(cap.parseTypes(arg)));
            }
        }

        Project project = new Project();
        BCClass bc;
        PCEnhancer enhancer;
        Collection persAwareClasses = new HashSet();

        int status;
        for (Object o : classes) {
            if (log.isInfoEnabled())
                log.info(_loc.get("enhance-running", o));

            if (o instanceof String)
                bc = project.loadClass((String) o, loader);
            else
                bc = project.loadClass((Class) o);
            enhancer = new PCEnhancer(conf, bc, repos, loader);
            if (writer != null)
                enhancer.setBytecodeWriter(writer);
            enhancer.setDirectory(flags.directory);
            enhancer.setAddDefaultConstructor(flags.addDefaultConstructor);
            status = enhancer.run();
            if (status == ENHANCE_NONE) {
                if (log.isTraceEnabled())
                    log.trace(_loc.get("enhance-norun"));
            }
            else if (status == ENHANCE_INTERFACE) {
                if (log.isTraceEnabled())
                    log.trace(_loc.get("enhance-interface"));
            }
            else if (status == ENHANCE_AWARE) {
                persAwareClasses.add(o);
                enhancer.record();
            }
            else {
                enhancer.record();
            }
            project.clear();
        }
        if(log.isInfoEnabled() && !persAwareClasses.isEmpty()){
        	log.info(_loc.get("pers-aware-classes", persAwareClasses.size(), persAwareClasses));
        }
        return true;
    }

    /**
     * Run flags.
     */
    public static class Flags {

        public File directory = null;
        public boolean addDefaultConstructor = true;
        public boolean tmpClassLoader = true;
        public boolean enforcePropertyRestrictions = false;
    }

    /**
     * Plugin interface for additional enhancement.
     */
    public interface AuxiliaryEnhancer
    {
        void run (BCClass bc, ClassMetaData meta);
        boolean skipEnhance(BCMethod m);
    }

    private void addGetIDOwningClass() throws NoSuchMethodException {
        BCMethod method = _pc.declareMethod(PRE + "GetIDOwningClass",
            Class.class, null);
        Code code = method.getCode(true);

        code.classconstant().setClass(getType(_meta));
        code.areturn();

        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * This static public worker method detects and logs any Entities that may have been enhanced at build time by
     * a version of the enhancer that is older than the current version.
     *
     * @param cls
     *            - A non-null Class implementing org.apache.openjpa.enhance.PersistenceCapable.
     * @param log
     *            - A non-null org.apache.openjpa.lib.log.Log.
     *
     * @throws - IllegalStateException if cls doesn't implement org.apache.openjpa.enhance.PersistenceCapable.
     *
     * @return true if the provided Class is down level from the current PCEnhancer.ENHANCER_VERSION. False
     *         otherwise.
     */
    public static boolean checkEnhancementLevel(Class<?> cls, Log log) {
        if (cls == null || log == null) {
            return false;
        }
        PersistenceCapable pc = PCRegistry.newInstance(cls, null, false);
        if (pc == null) {
            return false;
        }
        if (pc.pcGetEnhancementContractVersion() < PCEnhancer.ENHANCER_VERSION) {
            log.info(_loc.get("down-level-enhanced-entity", new Object[] { cls.getName(),
                pc.pcGetEnhancementContractVersion(), PCEnhancer.ENHANCER_VERSION }));
            return true;
        }
        return false;
    }

    /**
     * Read the optimizedIdCopy value from the config (if available)
     */
    private void configureOptimizeIdCopy() {
        if (_repos != null && _repos.getConfiguration() != null) {
            _optimizeIdCopy = _repos.getConfiguration().getOptimizeIdCopy();
        }
    }

    /*
     * Cycles through all primary keys verifying whether they can and should
     * be used for faster oid copy.  The field must be private and must
     * not have a public setter.  If this is the case, the list of pk fields is
     * returned.  If not, returns null.
     */
    private ArrayList<Integer> optimizeIdCopy(Class<?> oidType, FieldMetaData[] fmds) {
        // collect all object id fields and verify they
        // a) have a private field
        // b) do not have a public setter
        ArrayList<Integer> pkFields = new ArrayList<>();
        // build list of primary key fields
        for (int i = 0; i < fmds.length; i++) {
            if (!fmds[i].isPrimaryKey())
                continue;
            // optimizing copy with PC type not (yet) supported
            if (fmds[i].getDeclaredTypeCode() == JavaTypes.PC) {
                return null;
            }
            String name = fmds[i].getName();
            Field fld = Reflection.findField(oidType, name, false);
            if (fld == null || Modifier.isPublic(fld.getModifiers())) {
                return null;
            }
            Method setter = Reflection.findSetter(oidType, name, false);
            if (setter == null || !Modifier.isPublic(setter.getModifiers())) {
                pkFields.add(i);
            } else {
                return null;
            }
        }
        return pkFields.size() > 0 ? pkFields : null;
    }

    /*
     * Cycles through all constructors of an IdClass and examines the instructions to find
     * a matching constructor for the provided pk fields.  If a match is found, it returns
     * the order (relative to the field metadata) of the constructor parameters.  If a match
     * is not found, returns null.
    */
    private int[] getIdClassConstructorParmOrder(Class<?> oidType, ArrayList<Integer> pkfields,
            FieldMetaData[] fmds) {
        Project project = new Project();
        BCClass bc = project.loadClass(oidType);
        BCMethod[] methods = bc.getDeclaredMethods("<init>");
        if (methods == null || methods.length == 0) {
            return null;
        }

        int parmOrder[] = new int[pkfields.size()];
        for (BCMethod method : methods) {
            // constructor must be public
            if (!method.isPublic()) {
                continue;
            }
            Class<?>[] parmTypes = method.getParamTypes();
            // make sure the constructors have the same # of parms as
            // the number of pk fields
            if (parmTypes.length != pkfields.size()) {
                continue;
            }

            int parmOrderIndex = 0;
            Code code = method.getCode(false);
            Instruction[] ins = code.getInstructions();
            for (int i = 0; i < ins.length; i++) {
                if (ins[i] instanceof PutFieldInstruction) {
                    PutFieldInstruction pfi = (PutFieldInstruction)ins[i];
                    for (int j = 0; j < pkfields.size(); j++) {
                        int fieldNum = pkfields.get(j);
                        // Compare the field being set with the current pk field
                        String parmName = fmds[fieldNum].getName();
                        Class<?> parmType = fmds[fieldNum].getType();
                        if (parmName.equals(pfi.getFieldName())) {
                            // backup and examine the load instruction parm
                            if (i > 0 && ins[i-1] instanceof LoadInstruction) {
                                LoadInstruction li = (LoadInstruction)ins[i-1];
                                // Get the local index from the instruction.  This will be the index
                                // of the constructor parameter.  must be less than or equal to the
                                // max parm index to prevent from picking up locals that could have
                                // been produced within the constructor.  Also make sure the parm type
                                // matches the fmd type
                                int parm = li.getLocal();
                                if (parm <= pkfields.size() && parmTypes[parm-1].equals(parmType)) {
                                    parmOrder[parmOrderIndex] = fieldNum;
                                    parmOrderIndex++;
                                }
                            } else {
                                // Some other instruction found. can't make a determination of which local/parm
                                // is being used on the putfield.
                                break;
                            }
                        }
                    }
                }
            }
            if (parmOrderIndex == pkfields.size()) {
                return parmOrder;
            }
        }
        return null;
    }
}
