/**
 * Copyright (c) 2014 University of Sao Paulo and Contributors.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Roberto Araujo - initial API and implementation and/or initial documentation
 */
package br.usp.each.saeg.badua.core.internal.instr;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FrameNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;

public class LabelFrameNode extends LabelNode {

    private final Set<FrameNode> frames;

    public LabelFrameNode() {
        frames = new HashSet<FrameNode>();
    }

    public Set<FrameNode> getFrameNodes() {
        return Collections.unmodifiableSet(frames);
    }

    public boolean addFrameNode(final FrameNode frame) {
        return frames.add(frame);
    }

    public static void insertBefore(final AbstractInsnNode location,
            final InsnList insns, final InsnList insert) {

        AbstractInsnNode insn = location.getPrevious();
        while (true) {
            switch (insn.getType()) {
            case AbstractInsnNode.LABEL:
                final LabelFrameNode lfn = (LabelFrameNode) insn;
                final LabelFrameNode label = create(lfn);
                if (label != null) {
                    insert.add(label);
                }
                break;
            case AbstractInsnNode.FRAME:
            case AbstractInsnNode.LINE:
                insn = insn.getPrevious();
                continue;
            default:
                break;
            }
            insns.insertBefore(location, insert);
            return;
        }
    }

    private static LabelFrameNode create(final LabelFrameNode lfn) {
        final LabelFrameNode label = new LabelFrameNode();

        boolean changed = false;
        for (final FrameNode frame : lfn.frames) {
            for (int i = 0; i < frame.local.size(); i++) {
                if (frame.local.get(i) == lfn) {
                    frame.local.set(i, label);
                    changed = true;
                }
            }
            for (int i = 0; i < frame.stack.size(); i++) {
                if (frame.stack.get(i) == lfn) {
                    frame.stack.set(i, label);
                    changed = true;
                }
            }
        }

        if (!changed)
            return null;

        return label;
    }

}

@@ -1231,40 +1231,50 @@
     
-AbstractInsn
+final LabelFrame
 Node 
-ins
+lf
 n = 
+create(
 location
 .get
@@ -1273,101 +1273,171 @@
 tion
-.getPrevious();%0A        while (true) %7B%0A            switch (insn.getType()) %7B
+);%0A        if (lfn != null) %7B%0A            insert.add(lfn);%0A        %7D%0A        insns.insertBefore(location, insert);
 %0A    
+%7D%0A%0A
     
-    case
+public static void insertBefore(final
  Abs
@@ -1453,17 +1453,19 @@
 Node
-.LABEL:%0A 
+ location,%0A
     
@@ -1476,69 +1476,64 @@
     
-   final LabelFrameNode lfn = (LabelFrameNode) insn;%0A        
+final InsnList insns, final AbstractInsnNode insert) %7B%0A%0A
     
@@ -1558,20 +1558,18 @@
 meNode l
-abel
+fn
  = creat
@@ -1571,17 +1571,22 @@
 create(l
-f
+ocatio
 n);%0A    
@@ -1593,25 +1593,61 @@
     
- 
+insns.insertBefore(location, insert);%0A
        
+ 
 if (l
-abel
+fn
  != 
@@ -1670,74 +1670,346 @@
     
-        insert.add(label);%0A                %7D%0A                break
+insns.insertBefore(location, lfn);%0A        %7D%0A    %7D%0A%0A    private static LabelFrameNode create(final AbstractInsnNode location) %7B%0A        AbstractInsnNode insn = location.getPrevious();%0A        while (true) %7B%0A            switch (insn.getType()) %7B%0A            case AbstractInsnNode.LABEL:%0A                return create((LabelFrameNode) insn)
 ;%0A  
@@ -2197,77 +2197,19 @@
     
-b
 re
-ak;%0A            %7D%0A            insns.insertBefore(location, insert)
+turn null
 ;%0A  
@@ -2222,15 +2222,9 @@
     
-return;
+%7D
 %0A   

Refactor LabelFrameNode and new static method to insert a instruction before a location