OSDN Git Service

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