OSDN Git Service

move test case to new opcode extraction library
[stigmata/stigmata-plugins.git] / wsp / src / main / java / jp / sourceforge / stigmata / birthmarks / wsp / StackPatternBasedBirthmarkElement.java
1 package jp.sourceforge.stigmata.birthmarks.wsp;
2
3 /*
4  * $Id$
5  */
6
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.Iterator;
10 import java.util.List;
11
12 import jp.sourceforge.stigmata.BirthmarkElement;
13 import jp.sourceforge.stigmata.plugins.Opcode;
14 import jp.sourceforge.stigmata.plugins.OpcodeManager;
15
16 /**
17  *
18  * @author Haruaki TAMADA
19  * @version $Revision$
20  */
21 public class StackPatternBasedBirthmarkElement extends BirthmarkElement implements Iterable<CurrentDepth>{
22     private static final long serialVersionUID = 7965456413167854L;
23
24     private List<CurrentDepth> list = new ArrayList<CurrentDepth>();
25     private int weight = -1;
26
27     public StackPatternBasedBirthmarkElement(CurrentDepth[] depthArray){
28         super(getStringRepresentation(depthArray));
29         for(CurrentDepth depth: depthArray){
30             list.add(depth);
31         }
32     }
33     public StackPatternBasedBirthmarkElement(String value){
34         super(value);
35         String[] depthList = value.split(", ");
36         for(int i = 0; i < depthList.length; i++){
37             String[] depthStringArray = depthList[i].split(":");
38             if(depthStringArray.length == 4){
39                 int opcode = Integer.parseInt(depthStringArray[0]);
40                 int depth = Integer.parseInt(depthStringArray[1]);
41                 int weight = Integer.parseInt(depthStringArray[2]);
42                 int act = Integer.parseInt(depthStringArray[3]);
43
44                 Opcode o = new Opcode(OpcodeManager.getInstance().getOpcode(opcode));
45                 o.setWeight(weight);
46                 if(o.getCategory() == Opcode.Category.OBJECT || o.getCategory() == Opcode.Category.INVOKE){
47                     o.setAct(act);
48                 }
49                 list.add(new CurrentDepth(depth, o));
50             }
51         }
52     }
53
54     public int getLength(){
55         return list.size();
56     }
57
58     public CurrentDepth getDepth(int index){
59         return list.get(index);
60     }
61
62     public Iterator<CurrentDepth> iterator(){
63         return Collections.unmodifiableList(list).iterator();
64     }
65
66     public int getWeight(StackPatternBasedBirthmarkElement element){
67         int[][] matrix = new int[element.getLength() + 1][getLength() + 1];
68
69         for(int i = 0; i <= element.getLength(); i++){
70             for(int j = 0; j <= getLength(); j++){
71                 if(i == 0 || j == 0){
72                     matrix[i][j] = 0;
73                 }
74                 else if(element.getDepth(i - 1).getOpcode().getOpcode() == getDepth(j - 1).getOpcode().getOpcode()){
75                     matrix[i][j] = (int)(matrix[i - 1][j - 1] + getDepth(j - 1).getOpcode().getWeight());
76                 }
77                 else{
78                     matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
79                 }
80             }
81         }
82
83         int max = 0;
84         int last = element.getLength();
85         for(int i = 0; i < matrix[last].length; i++){
86             if(matrix[last][i] > max){
87                 max = matrix[last][i];
88             }
89         }
90         return max;
91     }
92
93     public int getWeight(){
94         if(weight < 0){
95             int w = 0;
96             for(CurrentDepth depth: this){
97                 w += depth.getOpcode().getWeight();
98             }
99             this.weight = w;
100         }
101         return weight;
102     }
103
104     private static String getStringRepresentation(CurrentDepth[] depth){
105         StringBuilder builder = new StringBuilder();
106         for(int i = 0; i < depth.length; i++){
107             if(i != 0){
108                 builder.append(", ");
109             }
110             builder.append(depth[i]);
111         }
112         return new String(builder);
113     }
114 }