You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2016/09/13 17:29:02 UTC

svn commit: r1760580 [2/5] - in /openjpa/branches/fb-3.0-asm: openjpa-examples/openbooks/ openjpa-kernel/src/main/java/org/apache/openjpa/ant/ openjpa-kernel/src/main/java/org/apache/openjpa/conf/ openjpa-kernel/src/main/java/org/apache/openjpa/enhance...

Modified: openjpa/branches/fb-3.0-asm/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
URL: http://svn.apache.org/viewvc/openjpa/branches/fb-3.0-asm/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java?rev=1760580&r1=1760579&r2=1760580&view=diff
==============================================================================
--- openjpa/branches/fb-3.0-asm/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java (original)
+++ openjpa/branches/fb-3.0-asm/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java Tue Sep 13 17:29:01 2016
@@ -1,4745 +1,46 @@
 /*
- * 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
+ * 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
+ *   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.    
+ * 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.Serializable;
-import java.io.ObjectStreamException;
-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.lib.util.StringUtil;
 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.Options;
-import org.apache.openjpa.lib.util.Services;
-import org.apache.openjpa.lib.util.Localizer.Message;
-import org.apache.openjpa.lib.util.svn.SVNUtils;
-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.MetaDataRepository;
-import org.apache.openjpa.meta.ValueStrategies;
-import org.apache.openjpa.util.ApplicationIds;
-import org.apache.openjpa.util.GeneralException;
-import org.apache.openjpa.util.InternalException;
-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.Id;
-import org.apache.openjpa.util.IntId;
-import org.apache.openjpa.util.FloatId;
-import org.apache.openjpa.util.LongId;
-import org.apache.openjpa.util.ObjectId;
-import org.apache.openjpa.util.ShortId;
-import org.apache.openjpa.util.StringId;
-import org.apache.openjpa.util.OpenJPAException;
-import org.apache.openjpa.util.UserException;
-import org.apache.openjpa.util.ImplHelper;
-import serp.bytecode.BCClass;
-import serp.bytecode.BCField;
-import serp.bytecode.BCMethod;
-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;
-import serp.bytecode.ClassInstruction;
 
-/**
- * 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 (int i = 0; i < classes.length; i++) {
-            try {
-                auxEnhancers.add(AccessController.doPrivileged(
-                    J2DoPrivHelper.newInstanceAction(classes[i])));
-            } 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();
-                }
-            }
-            String prop = revisionProps.getProperty("openjpa.enhancer.revision");
-            rev = SVNUtils.svnInfoToInteger(prop);
-        } 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. 
-     */
-    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(MetaDataRepository.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 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 (Iterator itr = _oids.iterator(); itr.hasNext();)
-                record((BCClass) itr.next());
-    }
-
-    /**
-     * 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 (int i = 0; i < fmds.length; i++) {
-
-            if (!(fmds[i].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[]{ fmds[i], fmds[i].getBackingMember() },
-                        true);
-                }
-                continue;
-            }
-            
-            meth = (Method) fmds[i].getBackingMember();
-            // ##### this will fail if we override and don't call super.
-            BCClass declaringType = _managedType.getProject()
-                .loadClass(fmds[i].getDeclaringType());
-            getter = declaringType.getDeclaredMethod(meth.getName(),
-                meth.getParameterTypes());
-            if (getter == null) {
-                addViolation("property-no-getter", new Object[]{ fmds[i] },
-                    true);
-                continue;
-            }
-            returned = getReturnedField(getter);
-            if (returned != null)
-                registerBackingFieldInfo(fmds[i], getter, returned);
-
-            setter = declaringType.getDeclaredMethod(getSetterName(fmds[i]),
-                new Class[]{ fmds[i].getDeclaredType() });
-            if (setter == null) {
-                if (returned == null) {
-                    addViolation("property-no-setter",
-                        new Object[]{ fmds[i] }, true);
-                    continue;
-                } else if (!getRedefine()) {
-                    // create synthetic setter
-                    setter = _managedType.declareMethod(getSetterName(fmds[i]),
-                        void.class, new Class[]{ fmds[i].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(fmds[i], setter, assigned);
-
-                if (assigned != returned)
-                    addViolation("property-setter-getter-mismatch", new Object[]
-                        { fmds[i], 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<Integer>();
-        FieldMetaData[] fmds = _meta.getFields();
-
-        if (_meta.isMixedAccess()) {
-            // Stores indexes of property access fields to be used in
-            // 
-            propFmds = new ArrayList<Integer>();
-            
-            // 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 (int i = 0; i < fmds.length; i++) {
-                tabins.addTarget(code.constant().setValue(
-                    _attrsToFields.get(fmds[i].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 (int i = 0; i < methods.length; i++) {
-            code = methods[i].getCode(false);
-
-            // don't modify the methods specified by the auxiliary enhancers
-            if (code != null && !skipEnhance(methods[i])) {
-                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() == true) { 
-                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 (int i = 0; i < fmds.length; i++) {
-            if (fmds[i].getManagement() != FieldMetaData.MANAGE_PERSISTENT)
-                continue;
-
-            loadManagedInstance(code, false);
-            switch (fmds[i].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, fmds[i]);
-        }
-
-        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 (int i = 0; i < fmds.length; i++) {
-                tabins.addTarget(loadManagedInstance(code, false));
-                code.getfield().setField(SM, SMTYPE);
-                loadManagedInstance(code, false);
-                code.iload().setParam(0);
-                loadManagedInstance(code, false);
-                addGetManagedValueCode(code, fmds[i]);
-                code.invokeinterface().setMethod(getStateManagerMethod
-                    (fmds[i].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 (int i = 0; i < fmds.length; i++) {
-                // for the addSetManagedValueCode call below.
-                tabins.addTarget(loadManagedInstance(code, false, fmds[i]));
-
-                loadManagedInstance(code, false, fmds[i]);
-                code.getfield().setField(SM, SMTYPE);
-                loadManagedInstance(code, false, fmds[i]);
-                code.iload().setParam(0);
-                code.invokeinterface().setMethod(getStateManagerMethod
-                    (fmds[i].getDeclaredType(), "replace", true, false));
-                if (!fmds[i].getDeclaredType().isPrimitive())
-                    code.checkcast().setType(fmds[i].getDeclaredType());
-
-                addSetManagedValueCode(code, fmds[i]);
-                if(_addVersionInitFlag){
-                    if(fmds[i].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 (int i = 0; i < fmds.length; i++) {
-                // <field> = other.<field>;
-                // or set<field> (other.get<field>);
-                tabins.addTarget(loadManagedInstance(code, false, fmds[i]));
-                code.aload().setParam(0);
-                addGetManagedValueCode(code, fmds[i], false);
-                addSetManagedValueCode(code, fmds[i]);
-
-                // 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.
-     */

[... 2923 lines stripped ...]