class MultistepProxyTransformer extends AbstractProxyTransformer
{
    private static final AgentLogger LOGGER = AgentLogger.getLogger(MultistepProxyTransformer.class);
    public static boolean addThirdStep = false;

    protected byte[] classfileBuffer;
    protected Map<Class<?>, TransformationState> transformationStates;
    protected ProxyBytecodeGenerator generator;
    protected ProxyBytecodeTransformer transformer;

    public MultistepProxyTransformer(Class<?> classBeingRedefined, ClassPool classPool, byte[] classfileBuffer,
            Map<Class<?>, TransformationState> transformationStates) {
        super(classBeingRedefined, classPool);
        this.classPool = classPool;
        this.transformationStates = transformationStates;
        this.classfileBuffer = classfileBuffer;
    }

    /**
     * Handles the current transformation state
     *
     * @return
     * @throws Exception
     */
    public byte[] transformRedefine() throws Exception {<FILL_FUNCTION_BODY>}

    /**
     * @return Current transformation state of the classBeingRedefined
     */
    protected TransformationState getTransformationstate() {
        TransformationState transformationState = transformationStates.get(classBeingRedefined);
        if (transformationState == null)
            transformationState = TransformationState.NEW;
        return transformationState;
    }

    /**
     * Generate new redefinition event for current classBeingRedefined
     */
    protected void scheduleRedefinition() {
        RedefinitionScheduler.schedule(this);
    }

    /**
     * Set classBeingRedefined as waiting
     *
     * @return
     */
    protected TransformationState setClassAsWaiting() {
        return transformationStates.put(classBeingRedefined, TransformationState.WAITING);
    }

    /**
     * Set classBeingRedefined as finished
     *
     * @return
     */
    protected TransformationState setClassAsFinished() {
        return transformationStates.put(classBeingRedefined, TransformationState.FINISHED);
    }

    /**
     * Remove any state associated with classBeingRedefined
     *
     * @return
     */
    public TransformationState removeClassState() {
        return transformationStates.remove(classBeingRedefined);
    }

    /**
     * The Class this instance is redefining
     *
     * @return
     */
    public Class<?> getClassBeingRedefined() {
        return classBeingRedefined;
    }

    /**
     * Bytecode of the Class this instance is redefining.
     *
     * @return
     */
    public byte[] getClassfileBuffer() {
        return classfileBuffer;
    }
}

        switch (getTransformationstate()) {
            case NEW:
                if (!isTransformingNeeded()) {
                    return classfileBuffer;
                }
                setClassAsWaiting();
                // We can't do the transformation in this event, because we can't see the changes in the class
                // definitons. Schedule a new redefinition event.
                scheduleRedefinition();
                return classfileBuffer;
            case WAITING:
                classfileBuffer = getTransformer().transform(getGenerator().generate());
                LOGGER.reload("Class '{}' has been reloaded.", classBeingRedefined.getName());
                if (addThirdStep) {
                    setClassAsFinished();
                    scheduleRedefinition();
                } else
                    removeClassState();
                return classfileBuffer;
            case FINISHED:
                removeClassState();
                return classfileBuffer;
            default:
                throw new RuntimeException("Unhandeled TransformationState!");
        }
    
<methods>public void <init>(Class<?>, org.hotswap.agent.javassist.ClassPool) <variables>protected Class<?> classBeingRedefined,protected org.hotswap.agent.javassist.ClassPool classPool,protected org.hotswap.agent.plugin.proxy.api.ProxyBytecodeGenerator generator,protected org.hotswap.agent.plugin.proxy.api.ProxyBytecodeTransformer transformer