/*
 * 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.util.BitSet;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.AbstractPCData;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.PCData;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.InternalException;

import serp.bytecode.BCClass;
import serp.bytecode.BCField;
import serp.bytecode.BCMethod;
import serp.bytecode.Code;
import serp.bytecode.Constants;
import serp.bytecode.ExceptionHandler;
import serp.bytecode.Instruction;
import serp.bytecode.JumpInstruction;
import serp.bytecode.LookupSwitchInstruction;

/**
 * Generates {@link PCData} instances which avoid primitive wrappers
 * to optimize memory use and performance at the cost of slightly higher
 * startup time.
 *
 * @author Steve Kim
 * @since 0.3.2
 */
public class PCDataGenerator
    extends DynamicStorageGenerator {

    private static final Localizer _loc = Localizer.forPackage
        (PCDataGenerator.class);

    protected static final String POSTFIX = "$openjpapcdata";

    private final Map<Class<?>, DynamicStorage> _generated = new ConcurrentHashMap<>();
    private final OpenJPAConfiguration _conf;
    private final Log _log;

    public PCDataGenerator(OpenJPAConfiguration conf) {
        _conf = conf;
        _log = _conf.getLogFactory().getLog(OpenJPAConfiguration.LOG_ENHANCE);
    }

    /**
     * Return the configuration.
     */
    public OpenJPAConfiguration getConfiguration() {
        return _conf;
    }

    /**
     * Return a {@link PCData} instance for the given oid and metadata.
     */
    public PCData generatePCData(Object oid, ClassMetaData meta) {
        if (meta == null)
            return null;
        Class<?> type = meta.getDescribedType();
        DynamicStorage storage = _generated.get(type);
        if (storage == null) {
            storage = generateStorage(meta);
            _generated.put(type, storage);
            if (_log.isTraceEnabled())
                _log.trace(_loc.get("pcdata-created", type.getName(), meta));
        }
        DynamicPCData data = (DynamicPCData) storage.newInstance();
        data.setId(oid);
        data.setStorageGenerator(this);
        finish(data, meta);
        return data;
    }

    /**
     * Actually generate the factory instance.
     */
    private DynamicStorage generateStorage(ClassMetaData meta) {
        if (_log.isTraceEnabled())
            _log.trace(_loc.get("pcdata-generate", meta));

        FieldMetaData[] fields = meta.getFields();
        int[] types = new int[fields.length];
        for (int i = 0; i < types.length; i++)
            types[i] = replaceType(fields[i]);
        return generateStorage(types, meta);
    }

    /**
     * Perform any final actions before the pcdata is returned to client code.
     */
    protected void finish(DynamicPCData data, ClassMetaData meta) {
    }

    @Override
    protected int getCreateFieldMethods(int typeCode) {
        if (typeCode >= JavaTypes.OBJECT)
            return POLICY_SILENT;
        // don't bother creating set/get<Primitive> methods
        return POLICY_EMPTY;
    }

    @Override
    protected void declareClasses(BCClass bc) {
        super.declareClasses(bc);
        bc.declareInterface(DynamicPCData.class);
        bc.setSuperclass(AbstractPCData.class);
    }

    @Override
    protected final String getClassName(Object obj) {
        return getUniqueName(((ClassMetaData) obj).getDescribedType());
    }

    /**
     * Creates a unique name for the given type's pcdata implementation.
     */
    protected String getUniqueName(Class<?> type) {
        return type.getName() + "$" + System.identityHashCode(type) + POSTFIX;
    }

    @Override
    protected final void decorate(Object obj, BCClass bc, int[] types) {
        super.decorate(obj, bc, types);
        ClassMetaData meta = (ClassMetaData) obj;

        enhanceConstructor(bc);
        addBaseFields(bc);
        addImplDataMethods(bc, meta);
        addFieldImplDataMethods(bc, meta);
        addVersionMethods(bc);
        addGetType(bc, meta);
        addLoadMethod(bc, meta);
        addLoadWithFieldsMethod(bc, meta);
        addStoreMethods(bc, meta);
        addNewEmbedded(bc);
        addGetData(bc);
        decorate(bc, meta);
    }

    /**
     * Apply additional decoration to generated class.
     */
    protected void decorate(BCClass bc, ClassMetaData meta) {
    }

    /**
     * Enhance constructor to initialize fields
     */
    private void enhanceConstructor(BCClass bc) {
        BCMethod cons = bc.getDeclaredMethod("<init>", (String[]) null);
        Code code = cons.getCode(false);
        code.afterLast();
        code.previous();

        // private BitSet loaded = new BitSet();
        BCField loaded = addBeanField(bc, "loaded", BitSet.class);
        loaded.setFinal(true);
        code.aload().setThis();
        code.anew().setType(BitSet.class);
        code.dup();
        code.constant().setValue(bc.getFields().length);
        code.invokespecial().setMethod(BitSet.class, "<init>", void.class,
            new Class[]{ int.class });
        code.putfield().setField(loaded);

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

    /**
     * Have to load the type since it may not be available to the
     * same classloader (i.e. rar vs. ear). The context classloader
     * (i.e. the user app classloader) should be fine.
     */
    private void addGetType(BCClass bc, ClassMetaData meta) {
        BCField type = bc.declareField("type", Class.class);
        type.setStatic(true);
        type.makePrivate();
        // public Class getType() {
        BCMethod getter = bc.declareMethod("getType", Class.class, null);
        getter.makePublic();
        Code code = getter.getCode(true);
        // if (type == null) {
        // 		try {
        // 			type = Class.forName
        // 	            (meta.getDescribedType().getName(), true,
        // 	            Thread.currentThread().getContextClassLoader());
        // 		} catch (ClassNotFoundException cnfe) {
        // 			throw new InternalException();
        // 		}
        // }
        code.getstatic().setField(type);

        Collection<Instruction> jumps = new LinkedList<>();
        jumps.add(code.ifnonnull());
        ExceptionHandler handler = code.addExceptionHandler();

        handler.setTryStart(code.constant().setValue
            (meta.getDescribedType().getName()));
        code.constant().setValue(true);
        code.invokestatic().setMethod(Thread.class, "currentThread",
            Thread.class, null);
        code.invokevirtual().setMethod(Thread.class, "getContextClassLoader",
            ClassLoader.class, null);
        code.invokestatic().setMethod(Class.class, "forName", Class.class,
            new Class[]{ String.class, boolean.class, ClassLoader.class });
        code.putstatic().setField(type);
        Instruction go2 = code.go2();
        jumps.add(go2);
        handler.setTryEnd(go2);
        handler.setCatch(ClassNotFoundException.class);
        handler.setHandlerStart(throwException
            (code, InternalException.class));
        setTarget(code.getstatic().setField(type), jumps);
        code.areturn();

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

    /**
     * Declare standard dynamic pcdata fields.
     */
    private void addBaseFields(BCClass bc) {
        addBeanField(bc, "id", Object.class);
        BCField field = addBeanField(bc, "storageGenerator",
            PCDataGenerator.class);
        field.setAccessFlags(field.getAccessFlags()
            | Constants.ACCESS_TRANSIENT);
    }

    /**
     * Add methods for loading and storing class-level impl data.
     */
    private void addImplDataMethods(BCClass bc, ClassMetaData meta) {
        // void storeImplData(OpenJPAStateManager);
        BCMethod meth = bc.declareMethod("storeImplData", void.class,
            new Class[]{ OpenJPAStateManager.class });
        Code code = meth.getCode(true);

        BCField impl = null;
        if (!usesImplData(meta))
            code.vreturn();
        else {
            // if (sm.isImplDataCacheable())
            // 		setImplData(sm.getImplData());
            impl = addBeanField(bc, "implData", Object.class);
            code.aload().setParam(0);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "isImplDataCacheable", boolean.class, null);
            JumpInstruction ifins = code.ifeq();
            code.aload().setThis();
            code.aload().setParam(0);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "getImplData", Object.class, null);
            code.invokevirtual().setMethod("setImplData", void.class,
                new Class[]{ Object.class });
            ifins.setTarget(code.vreturn());
        }
        code.calculateMaxStack();
        code.calculateMaxLocals();

        // void loadImplData(OpenJPAStateManager);
        meth = bc.declareMethod("loadImplData", void.class,
            new Class[]{ OpenJPAStateManager.class });
        code = meth.getCode(true);
        if (!usesImplData(meta))
            code.vreturn();
        else {
            // if (sm.getImplData() == null && implData != null)
            // 		sm.setImplData(impl, true);
            code.aload().setParam(0);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "getImplData", Object.class, null);
            JumpInstruction ifins = code.ifnonnull();
            code.aload().setThis();
            code.getfield().setField(impl);
            JumpInstruction ifins2 = code.ifnull();
            code.aload().setParam(0);
            code.aload().setThis();
            code.getfield().setField(impl);
            code.constant().setValue(true);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "setImplData", void.class,
                new Class[]{ Object.class, boolean.class });
            Instruction ins = code.vreturn();
            ifins.setTarget(ins);
            ifins2.setTarget(ins);
        }
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Add methods for loading and storing class-level impl data.
     */
    private void addFieldImplDataMethods(BCClass bc, ClassMetaData meta) {
        // public void loadImplData(OpenJPAStateManager sm, int i)
        BCMethod meth = bc.declareMethod("loadImplData", void.class,
            new Class[]{ OpenJPAStateManager.class, int.class });
        meth.makePrivate();
        Code code = meth.getCode(true);

        int count = countImplDataFields(meta);
        BCField impl = null;
        if (count == 0)
            code.vreturn();
        else {
            // Object[] fieldImpl
            impl = bc.declareField("fieldImpl", Object[].class);
            impl.makePrivate();

            // if (fieldImpl != null)
            code.aload().setThis();
            code.getfield().setField(impl);
            JumpInstruction ifins = code.ifnonnull();
            code.vreturn();

            // Object obj = null;
            int obj = code.getNextLocalsIndex();
            ifins.setTarget(code.constant().setNull());
            code.astore().setLocal(obj);

            // establish switch target, then move before it
            Instruction target = code.aload().setLocal(obj);
            code.previous();

            // switch(i)
            code.iload().setParam(1);
            LookupSwitchInstruction lswitch = code.lookupswitch();
            FieldMetaData[] fields = meta.getFields();
            int cacheable = 0;
            for (int i = 0; i < fields.length; i++) {
                if (!usesImplData(fields[i]))
                    continue;
                // case x: obj = fieldImpl[y]; break;
                lswitch.addCase(i, code.aload().setThis());
                code.getfield().setField(impl);
                code.constant().setValue(cacheable++);
                code.aaload();
                code.astore().setLocal(obj);
                code.go2().setTarget(target);
            }
            lswitch.setDefaultTarget(target);

            // if (obj != null)
            code.next();    // jump back over target
            ifins = code.ifnonnull();
            code.vreturn();

            // sm.setImplData(index, impl);
            ifins.setTarget(code.aload().setParam(0));
            code.iload().setParam(1);
            code.aload().setLocal(obj);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "setImplData", void.class,
                new Class[]{ int.class, Object.class });
            code.vreturn();
        }
        code.calculateMaxLocals();
        code.calculateMaxStack();

        // void storeImplData(OpenJPAStateManager sm, int index, boolean loaded)
        meth = bc.declareMethod("storeImplData", void.class,
            new Class[]{ OpenJPAStateManager.class, int.class, boolean.class });
        code = meth.getCode(true);
        if (count == 0)
            code.vreturn();
        else {
            // int arrIdx = -1;
            // switch(index)
            int arrIdx = code.getNextLocalsIndex();
            code.constant().setValue(-1);
            code.istore().setLocal(arrIdx);
            code.iload().setParam(1);
            LookupSwitchInstruction lswitch = code.lookupswitch();

            // establish switch target, then move before it
            Instruction switchTarget = code.iload().setLocal(arrIdx);
            code.previous();

            FieldMetaData[] fields = meta.getFields();
            int cacheable = 0;
            for (int i = 0; i < fields.length; i++) {
                if (!usesImplData(fields[i]))
                    continue;
                // case x: arrIdx = y; break;
                lswitch.addCase(i, code.constant().setValue(cacheable++));
                code.istore().setLocal(arrIdx);
                code.go2().setTarget(switchTarget);
            }
            lswitch.setDefaultTarget(switchTarget);
            code.next();    // step over switch target

            // if (arrIdx != -1)
            code.constant().setValue(-1);
            JumpInstruction ifins = code.ificmpne();
            code.vreturn();

            // create null target, then move before it
            Instruction nullTarget = code.aload().setThis();
            code.previous();

            // if (loaded)
            ifins.setTarget(code.iload().setParam(2));
            code.ifeq().setTarget(nullTarget);

            // Object obj = sm.getImplData(index)
            int obj = code.getNextLocalsIndex();
            code.aload().setParam(0);
            code.iload().setParam(1);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "getImplData", Object.class, new Class[]{ int.class });
            code.astore().setLocal(obj);

            // if (obj != null)
            code.aload().setLocal(obj);
            code.ifnull().setTarget(nullTarget);

            // if (fieldImpl == null)
            // 		fieldImpl = new Object[fields];
            code.aload().setThis();
            code.getfield().setField(impl);
            ifins = code.ifnonnull();
            code.aload().setThis();
            code.constant().setValue(count);
            code.anewarray().setType(Object.class);
            code.putfield().setField(impl);

            // fieldImpl[arrIdx] = obj;
            // return;
            ifins.setTarget(code.aload().setThis());
            code.getfield().setField(impl);
            code.iload().setLocal(arrIdx);
            code.aload().setLocal(obj);
            code.aastore();
            code.vreturn();

            // if (fieldImpl != null)
            // 		fieldImpl[index] = null;
            code.next(); // step over nullTarget
            code.getfield().setField(impl);
            ifins = code.ifnonnull();
            code.vreturn();
            ifins.setTarget(code.aload().setThis());
            code.getfield().setField(impl);
            code.iload().setLocal(arrIdx);
            code.constant().setNull();
            code.aastore();
            code.vreturn();
        }
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Add methods for loading and storing version data.
     */
    protected void addVersionMethods(BCClass bc) {
        // void storeVersion(OpenJPAStateManager sm);
        addBeanField(bc, "version", Object.class);
        BCMethod meth = bc.declareMethod("storeVersion", void.class,
            new Class[]{ OpenJPAStateManager.class });
        Code code = meth.getCode(true);

        // version = sm.getVersion();
        code.aload().setThis();
        code.aload().setParam(0);
        code.invokeinterface()
            .setMethod(OpenJPAStateManager.class, "getVersion",
                Object.class, null);
        code.putfield().setField("version", Object.class);
        code.vreturn();
        code.calculateMaxStack();
        code.calculateMaxLocals();

        // void loadVersion(OpenJPAStateManager sm)
        meth = bc.declareMethod("loadVersion", void.class,
            new Class[]{ OpenJPAStateManager.class });
        code = meth.getCode(true);

        // if (sm.getVersion() == null)
        // 		sm.setVersion(version);
        code.aload().setParam(0);
        code.invokeinterface().setMethod(OpenJPAStateManager.class,
            "getVersion", Object.class, null);
        JumpInstruction ifins = code.ifnonnull();
        code.aload().setParam(0);
        code.aload().setThis();
        code.getfield().setField("version", Object.class);
        code.invokeinterface()
            .setMethod(OpenJPAStateManager.class, "setVersion",
                void.class, new Class[]{ Object.class });
        ifins.setTarget(code.vreturn());
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    private void addLoadMethod(BCClass bc, ClassMetaData meta) {
        // public void load(OpenJPAStateManager sm, FetchConfiguration fetch,
        // 		Object context)
        Code code = addLoadMethod(bc, false);
        FieldMetaData[] fmds = meta.getFields();
        Collection<Instruction> jumps = new LinkedList<>();
        Collection<Instruction> jumps2;

        int local = code.getNextLocalsIndex();
        code.constant().setNull();
        code.astore().setLocal(local);
        int inter = code.getNextLocalsIndex();
        code.constant().setNull();
        code.astore().setLocal(inter);

        int objectCount = 0;
        boolean intermediate;
        for (int i = 0; i < fmds.length; i++) {
            jumps2 = new LinkedList<>();
            intermediate = usesIntermediate(fmds[i]);
            setTarget(code.aload().setThis(), jumps);
            // if (loaded.get(i)) or (!loaded.get(i)) depending on inter resp
            code.getfield().setField("loaded", BitSet.class);
            code.constant().setValue(i);
            code.invokevirtual().setMethod(BitSet.class, "get",
                boolean.class, new Class[]{ int.class });
            jumps.add(code.ifne());

            if (intermediate)
                addLoadIntermediate(code, i, objectCount, jumps2, inter);
            jumps2.add(code.go2());

            // if (fetch.requiresFetch(fmds[i])!=FetchConfiguration.FETCH_NONE)
            setTarget(code.aload().setParam(1), jumps);
            code.aload().setParam(0);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "getMetaData", ClassMetaData.class, null);
            code.constant().setValue(fmds[i].getIndex());
            code.invokevirtual().setMethod(ClassMetaData.class,
                "getField", FieldMetaData.class, new Class[]{int.class});
            code.invokeinterface().setMethod (FetchConfiguration.class,
                "requiresFetch", int.class, new Class[]{FieldMetaData.class});
            code.constant().setValue(FetchConfiguration.FETCH_NONE);
            jumps2.add(code.ificmpeq());
            addLoad(bc, code, fmds[i], objectCount, local, false);

            jumps = jumps2;
            if (replaceType(fmds[i]) >= JavaTypes.OBJECT)
                objectCount++;
        }
        setTarget(code.vreturn(), jumps);
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    private void addLoadWithFieldsMethod(BCClass bc, ClassMetaData meta) {
        Code code = addLoadMethod(bc, true);
        // public void load(OpenJPAStateManager sm, BitSet fields,
        // 		FetchConfiguration fetch, Object conn)
        FieldMetaData[] fmds = meta.getFields();
        Collection<Instruction> jumps = new LinkedList<>();
        Collection<Instruction> jumps2;
        int objectCount = 0;
        boolean intermediate;
        int local = code.getNextLocalsIndex();
        code.constant().setNull();
        code.astore().setLocal(local);
        int inter = code.getNextLocalsIndex();
        code.constant().setNull();
        code.astore().setLocal(inter);

        for (int i = 0; i < fmds.length; i++) {
            jumps2 = new LinkedList<>();
            intermediate = usesIntermediate(fmds[i]);
            // if (fields.get(i))
            // {
            // 		if (loaded.get(i))
            setTarget(code.aload().setParam(1), jumps);
            code.constant().setValue(i);
            code.invokevirtual().setMethod(BitSet.class, "get",
                boolean.class, new Class[]{ int.class });
            jumps2.add(code.ifeq());
            code.aload().setThis();
            code.getfield().setField("loaded", BitSet.class);
            code.constant().setValue(i);
            code.invokevirtual().setMethod(BitSet.class, "get",
                boolean.class, new Class[]{ int.class });
            if (intermediate)
                jumps.add(code.ifeq());
            else
                jumps2.add(code.ifeq());

            addLoad(bc, code, fmds[i], objectCount, local, true);
            if (usesImplData(fmds[i])) {
                // loadImplData(sm, i);
                code.aload().setThis();
                code.aload().setParam(0);
                code.constant().setValue(i);
                code.invokevirtual().setMethod("loadImplData", void.class,
                    new Class[]{ OpenJPAStateManager.class, int.class });
            }

            // fields.clear(i);
            code.aload().setParam(1);
            code.constant().setValue(i);
            code.invokevirtual().setMethod(BitSet.class, "clear", void.class,
                new Class[] { int.class });

            jumps2.add(code.go2());

            if (intermediate)
                setTarget(addLoadIntermediate
                    (code, i, objectCount, jumps2, inter), jumps);

            jumps = jumps2;
            if (replaceType(fmds[i]) >= JavaTypes.OBJECT)
                objectCount++;
        }
        setTarget(code.vreturn(), jumps);
        code.calculateMaxStack();
        code.calculateMaxLocals();
    }

    /**
     * Declare and start the base load method.
     */
    private Code addLoadMethod(BCClass bc, boolean fields) {
        Class<?>[] args = null;
        if (fields)
            args = new Class[]{ OpenJPAStateManager.class, BitSet.class,
                FetchConfiguration.class, Object.class };
        else
            args = new Class[]{ OpenJPAStateManager.class,
                FetchConfiguration.class, Object.class };
        BCMethod load = bc.declareMethod("load", void.class, args);
        Code code = load.getCode(true);

        //loadVersion(sm);
        code.aload().setThis();
        code.aload().setParam(0);
        code.invokevirtual().setMethod("loadVersion", void.class,
            new Class[]{ OpenJPAStateManager.class });

        //loadImplData(sm);
        code.aload().setThis();
        code.aload().setParam(0);
        code.invokevirtual().setMethod("loadImplData", void.class,
            new Class[]{ OpenJPAStateManager.class });
        return code;
    }

    /**
     * Add the field load.
     */
    private Instruction addLoad(BCClass bc, Code code, FieldMetaData fmd,
        int objectCount, int local, boolean fields) {
        int index = fmd.getIndex();
        int typeCode = replaceType(fmd);
        Instruction first;
        if (typeCode < JavaTypes.OBJECT) {
            // sm.store<type>(i, field<i>)
            Class<?> type = forType(fmd.getTypeCode());
            first = code.aload().setParam(0);
            code.constant().setValue(index);
            code.aload().setThis();
            code.getfield().setField(getFieldName(index), type);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "store" + StringUtil.capitalize(type.getName()),
                void.class, new Class[]{ int.class, type });
        } else {
            // fmd = sm.getMetaData().getField(i);
            int offset = fields ? 1 : 0;
            first = code.aload().setParam(0);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "getMetaData", ClassMetaData.class, null);
            code.constant().setValue(fmd.getIndex());
            code.invokevirtual().setMethod(ClassMetaData.class, "getField",
                FieldMetaData.class, new Class[]{ int.class });
            code.astore().setLocal(local);
            // sm.storeField(i, toField(sm, fmd, objects[objectCount],
            // 		fetch, context);
            code.aload().setParam(0);
            code.constant().setValue(index);
            code.aload().setThis();
            code.aload().setParam(0);
            code.aload().setLocal(local);
            code.aload().setThis();
            code.getfield().setField("objects", Object[].class);
            code.constant().setValue(objectCount);
            code.aaload();
            code.aload().setParam(1 + offset);
            code.aload().setParam(2 + offset);
            code.invokevirtual().setMethod(bc.getName(), "toField",
                Object.class.getName(), toStrings(new Class[]{
                OpenJPAStateManager.class, FieldMetaData.class,
                Object.class, FetchConfiguration.class, Object.class }));
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "storeField", void.class,
                new Class[]{ int.class, Object.class });
        }
        return first;
    }

    /**
     * Load intermediate data if possible.
     */
    private Instruction addLoadIntermediate(Code code, int index,
        int objectCount, Collection<Instruction> jumps2, int inter) {
        // {
        // 		Object inter = objects[objectCount];
        Instruction first = code.aload().setThis();
        code.getfield().setField("objects", Object[].class);
        code.constant().setValue(objectCount);
        code.aaload();
        code.astore().setLocal(inter);
        // 		if (inter != null && !sm.getLoaded().get(index))
        code.aload().setLocal(inter);
        jumps2.add(code.ifnull());
        code.aload().setParam(0);
        code.invokeinterface().setMethod(OpenJPAStateManager.class,
            "getLoaded", BitSet.class, null);
        code.constant().setValue(index);
        code.invokevirtual().setMethod(BitSet.class, "get",
            boolean.class, new Class[]{ int.class });
        jumps2.add(code.ifne());
        //			sm.setIntermediate(index, inter);
        //	}  // end else
        code.aload().setParam(0);
        code.constant().setValue(index);
        code.aload().setLocal(inter);
        code.invokeinterface().setMethod(OpenJPAStateManager.class,
            "setIntermediate", void.class,
            new Class[]{ int.class, Object.class });
        return first;
    }

    private void addStoreMethods(BCClass bc, ClassMetaData meta) {
        // i.e. void store(OpenJPAStateManager sm, BitSet fields);
        addStoreMethod(bc, meta, true);
        // i.e. void store(OpenJPAStateManager sm);
        addStoreMethod(bc, meta, false);
    }

    private void addStoreMethod(BCClass bc, ClassMetaData meta,
        boolean fields) {
        BCMethod store;
        if (fields)
            store = bc.declareMethod("store", void.class,
                new Class[]{ OpenJPAStateManager.class, BitSet.class });
        else
            store = bc.declareMethod("store", void.class,
                new Class[]{ OpenJPAStateManager.class });
        Code code = store.getCode(true);

        // initialize();
        code.aload().setThis();
        code.invokevirtual().setMethod("initialize", void.class, null);

        // storeVersion(sm);
        code.aload().setThis();
        code.aload().setParam(0);
        code.invokevirtual().setMethod("storeVersion", void.class,
            new Class[]{ OpenJPAStateManager.class });

        // storeImplData(sm);
        code.aload().setThis();
        code.aload().setParam(0);
        code.invokevirtual().setMethod("storeImplData", void.class,
            new Class[]{ OpenJPAStateManager.class });

        FieldMetaData[] fmds = meta.getFields();
        Collection<Instruction> jumps = new LinkedList<>();
        int objectCount = 0;
        for (int i = 0; i < fmds.length; i++) {
            if (fields) {
                //  if (fields != null && fields.get(index))
                setTarget(code.aload().setParam(1), jumps);
                jumps.add(code.ifnull());
                code.aload().setParam(1);
                code.constant().setValue(i);
                code.invokevirtual().setMethod(BitSet.class, "get",
                    boolean.class, new Class[]{ int.class });
                jumps.add(code.ifeq());
            } else {
                // if (sm.getLoaded().get(index)))
                setTarget(code.aload().setParam(0), jumps);
                code.invokeinterface().setMethod(OpenJPAStateManager.class,
                    "getLoaded", BitSet.class, null);
                code.constant().setValue(i);
                code.invokevirtual().setMethod(BitSet.class, "get",
                    boolean.class, new Class[]{ int.class });
                jumps.add(code.ifeq());
            }
            addStore(bc, code, fmds[i], objectCount);
            if (usesIntermediate(fmds[i])) {
                JumpInstruction elseIns = code.go2();
                // else if (!loaded.get(index))
                setTarget(code.aload().setThis(), jumps);
                jumps.add(elseIns);
                code.getfield().setField("loaded", BitSet.class);
                code.constant().setValue(i);
                code.invokevirtual().setMethod(BitSet.class, "get",
                    boolean.class, new Class[]{ int.class });
                jumps.add(code.ifne());
                // Object val = sm.getIntermediate(index);
                // if (val != null)
                // 		objects[objectCount] = val;
                code.aload().setParam(0);
                code.constant().setValue(i);
                code.invokeinterface().setMethod(OpenJPAStateManager.class,
                    "getIntermediate", Object.class, new Class[]{ int.class });
                int local = code.getNextLocalsIndex();
                code.astore().setLocal(local);
                code.aload().setLocal(local);
                jumps.add(code.ifnull());
                code.aload().setThis();
                code.getfield().setField("objects", Object[].class);
                code.constant().setValue(objectCount);
                code.aload().setLocal(local);
                code.aastore();
            }
            if (replaceType(fmds[i]) >= JavaTypes.OBJECT)
                objectCount++;
        }
        setTarget(code.vreturn(), jumps);
        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    private void addStore(BCClass bc, Code code, FieldMetaData fmd,
        int objectCount) {
        int typeCode = replaceType(fmd);
        int index = fmd.getIndex();
        if (typeCode < JavaTypes.OBJECT) {
            Class<?> type = forType(typeCode);
            // field<i> = sm.fetch<Type>(index)
            code.aload().setThis();
            code.aload().setParam(0);
            code.constant().setValue(index);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "fetch" + StringUtil.capitalize(type.getName()), type,
                new Class[]{ int.class });
            code.putfield().setField(getFieldName(index), type);
            code.aload().setThis();
            code.getfield().setField("loaded", BitSet.class);
            code.constant().setValue(index);
            code.invokevirtual().setMethod(BitSet.class, "set", void.class,
                new Class[]{ int.class });
        } else {
            // Object val = toData(sm.getMetaData().getField(index),
            // 		sm.fetchField(index, false), sm.getContext());
            int local = code.getNextLocalsIndex();
            code.aload().setThis();
            code.aload().setParam(0);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "getMetaData", ClassMetaData.class, null);
            code.constant().setValue(fmd.getIndex());
            code.invokevirtual().setMethod(ClassMetaData.class,
                "getField", FieldMetaData.class, new Class[]{ int.class });
            code.aload().setParam(0);
            code.constant().setValue(fmd.getIndex());
            code.constant().setValue(false);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "fetchField", Object.class, new Class[]
                { int.class, boolean.class });
            code.aload().setParam(0);
            code.invokeinterface().setMethod(OpenJPAStateManager.class,
                "getContext", StoreContext.class, null);
            code.invokevirtual().setMethod(bc.getName(), "toData",
                Object.class.getName(), toStrings(new Class []{
                FieldMetaData.class, Object.class, StoreContext.class }));
            code.astore().setLocal(local);

            // if (val == NULL) {
            // 		val = null;
            // 		loaded.clear(index);
            // 	} else
            // 		loaded.set(index);
            // 	objects[objectCount] = val;
            code.aload().setLocal(local);
            code.getstatic().setField(AbstractPCData.class, "NULL",
                Object.class);
            JumpInstruction ifins = code.ifacmpne();
            code.constant().setNull();
            code.astore().setLocal(local);
            code.aload().setThis();
            code.getfield().setField("loaded", BitSet.class);
            code.constant().setValue(index);
            code.invokevirtual().setMethod(BitSet.class, "clear", void.class,
                new Class[]{ int.class });
            JumpInstruction go2 = code.go2();
            ifins.setTarget(code.aload().setThis());
            code.getfield().setField("loaded", BitSet.class);
            code.constant().setValue(index);
            code.invokevirtual().setMethod(BitSet.class, "set", void.class,
                new Class[]{ int.class });
            go2.setTarget(code.aload().setThis());
            code.getfield().setField("objects", Object[].class);
            code.constant().setValue(objectCount);
            code.aload().setLocal(local);
            code.aastore();
        }
        if (!usesImplData(fmd))
            return;

        // storeImplData(sm, i, loaded.get(i);
        code.aload().setThis();
        code.aload().setParam(0);
        code.constant().setValue(index);
        code.aload().setThis();
        code.getfield().setField("loaded", BitSet.class);
        code.constant().setValue(index);
        code.invokevirtual().setMethod(BitSet.class, "get", boolean.class,
            new Class[]{ int.class });
        code.invokevirtual().setMethod("storeImplData", void.class,
            new Class[]{ OpenJPAStateManager.class, int.class, boolean.class });
    }

    private void addNewEmbedded(BCClass bc) {
        // void newEmbeddedPCData(OpenJPAStateManager embedded)
        BCMethod meth = bc.declareMethod("newEmbeddedPCData", PCData.class,
            new Class[]{ OpenJPAStateManager.class });
        Code code = meth.getCode(true);
        // return getStorageGenerator().generatePCData
        // 		(sm.getId(), sm.getMetaData());
        code.aload().setThis();
        code.getfield().setField("storageGenerator", PCDataGenerator.class);
        code.aload().setParam(0);
        code.invokeinterface().setMethod(OpenJPAStateManager.class,
            "getId", Object.class, null);
        code.aload().setParam(0);
        code.invokeinterface().setMethod(OpenJPAStateManager.class,
            "getMetaData", ClassMetaData.class, null);
        code.invokevirtual().setMethod(PCDataGenerator.class,
            "generatePCData", PCData.class, new Class[]
            { Object.class, ClassMetaData.class });
        code.areturn();
        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    private void addGetData(BCClass bc) {
        // return getObjectField(i);
        BCMethod method = bc.declareMethod("getData", Object.class,
            new Class[]{ int.class });
        Code code = method.getCode(true);
        code.aload().setThis();
        code.iload().setParam(0);
        code.invokevirtual().setMethod("getObject", Object.class,
            new Class[]{ int.class });
        code.areturn();
        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    /////////////
    // Utilities
    /////////////

    /**
     * Return a valid {@link JavaTypes} constant for the given field
     */
    protected int replaceType(FieldMetaData fmd) {
        if (usesIntermediate(fmd))
            return JavaTypes.OBJECT;
        return fmd.getTypeCode();
    }

    /**
     * Whether the given field uses a cacheable intermediate value.
     */
    protected boolean usesIntermediate(FieldMetaData fmd) {
        return fmd.usesIntermediate();
    }

    /**
     * Whether the given type might have cacheable class-level impl data.
     */
    protected boolean usesImplData(ClassMetaData meta) {
        return true;
    }

    /**
     * Whether the given field might have cacheable impl data.
     */
    protected boolean usesImplData(FieldMetaData fmd) {
        return fmd.usesImplData() == null;
    }

    /**
     * The number of fields with cacheable impl data.
     */
    private int countImplDataFields(ClassMetaData meta) {
        FieldMetaData[] fmds = meta.getFields();
        int count = 0;
        for (FieldMetaData fmd : fmds)
            if (usesImplData(fmd))
                count++;
        return count;
    }

    /**
     * Add method which defers to AbstractPCData.
     */
    protected void callAbstractPCData(BCClass bc, String name, Class<?> retType,
        Class<?>[] args) {
        BCMethod meth = bc.declareMethod(name, retType, args);
        Code code = meth.getCode(true);
        code.aload().setThis();
        for (int i = 0; i < args.length; i++)
            code.xload().setParam(i).setType(args[i]);
        code.invokevirtual().setMethod(AbstractPCData.class, name, retType,
            args);
        if (!void.class.equals(retType))
            code.xreturn().setType(retType);
        code.calculateMaxLocals();
        code.calculateMaxStack();
    }

    /**
     * Set the collection of {@link JumpInstruction}s to the given instruction,
     * clearing the collection in the process.
     */
    protected void setTarget(Instruction ins, Collection<Instruction> jumps) {
        for (Instruction jump : jumps) {
            ((JumpInstruction) jump).setTarget(ins);
        }
        jumps.clear();
    }

    /**
     * Transform the given array of classes to strings.
     */
    private static String[] toStrings(Class<?>[] cls) {
        String[] strings = new String[cls.length];
        for (int i = 0; i < strings.length; i++)
            strings[i] = cls[i].getName();
        return strings;
    }

    /**
     * Dynamic {@link PCData}s generated will implement this interface
     * to simplify initialization.
     */
    public interface DynamicPCData extends PCData {

        void setId(Object oid);

        PCDataGenerator getStorageGenerator();

        void setStorageGenerator (PCDataGenerator generator);
	}
}
