OSDN Git Service

コントロールフローを抽出可能にした.
[stigmata/stigmata-plugins.git] / opcodes / src / main / java / jp / sourceforge / stigmata / birthmarks / Opcode.java
1 package jp.sourceforge.stigmata.birthmarks;
2
3 /*
4  * $Id$
5  */
6
7 import java.io.Serializable;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.Iterator;
11 import java.util.List;
12
13 import org.objectweb.asm.Label;
14
15 /**
16  *
17  * @author Haruaki Tamada
18  * @version $Revision$
19  */
20 public class Opcode implements Serializable, Iterable<Label>{
21     private static final long serialVersionUID = -2349834745416345564L;
22
23     public static enum Category{
24         NORMAL, BRANCH, OBJECT, INVOKE, TARGETER,
25     };
26     private int opcode;
27     private String name;
28     private int argumentCount;
29     private int act;
30     private Category category;
31     private List<Label> labels = new ArrayList<Label>();
32
33     public Opcode(Opcode opcode){
34         this(opcode.getOpcode(), opcode.getName(), opcode.getArgumentCount(), opcode.getAct(), opcode.getCategory());
35     }
36
37     public Opcode(int opcode, String name, int argumentCount, int act, String category){
38         this(opcode, name, argumentCount, act, Category.valueOf(category));
39     }
40
41     public Opcode(int opcode, String name, int argumentCount, int act, Category category){
42         this.opcode = opcode;
43         this.name = name;
44         this.argumentCount = argumentCount;
45         this.act = act;
46         this.category = category;
47     }
48
49     public final int getOpcode(){
50         return opcode;
51     }
52
53     public final String getName(){
54         return name;
55     }
56
57     public int getArgumentCount(){
58         return argumentCount;
59     }
60
61     public void addLabel(Label label){
62         if(label == null){
63             throw new NullPointerException();
64         }
65         if(!(category == Category.TARGETER && labels.size() == 0) 
66                 && category != Category.BRANCH){
67             throw new IllegalStateException("this method allows only branch category");
68         }
69         labels.add(label);
70     }
71
72     public void setLabels(Label[] labelArray){
73         if(labelArray == null){
74             throw new NullPointerException();
75         }
76         if(category != Category.BRANCH){
77             throw new IllegalStateException("this method allows only branch category");
78         }
79         labels.clear();
80         for(Label label: labelArray){
81             if(label == null){
82                 throw new NullPointerException();
83             }
84             labels.add(label);
85         }
86     }
87
88     public boolean hasLabel(Label label){
89         return labels.contains(label);
90     }
91
92     public Label getLabel(int index){
93         return labels.get(index);
94     }
95
96     public synchronized Label[] getLabels(){
97         return labels.toArray(new Label[labels.size()]);
98     }
99
100     public Iterator<Label> iterator(){
101         return Collections.unmodifiableList(labels).iterator();
102     }
103
104     public void setAct(int act){
105         if(category != Category.OBJECT && category != Category.INVOKE){
106             throw new IllegalStateException("setAct can be called only object and invoke category.");
107         }
108         this.act = act;
109     }
110
111     public int getAct(){
112         return act;
113     }
114
115     public Category getCategory(){
116         return category;
117     }
118
119     public String toString(){
120         StringBuilder sb = new StringBuilder();
121         sb.append(String.format("%d:%s:%d(%s)", getOpcode(), getName(), getAct(), getCategory()));
122
123         if(getCategory() == Category.BRANCH || getCategory() == Category.TARGETER){
124             sb.append(labels);
125         }
126
127         return new String(sb);
128     }
129 }