OSDN Git Service

d055b08b14ca5988ecee261802140788bad539ff
[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
14 /**
15  * 
16  * @author Haruaki TAMADA
17  * @version $Revision$ 
18  */
19 public class StackPatternBasedBirthmarkElement extends BirthmarkElement implements Iterable<CurrentDepth>{
20     private static final long serialVersionUID = 7965456413167854L;
21
22     private List<CurrentDepth> list = new ArrayList<CurrentDepth>();
23     private int weight = -1;
24
25     public StackPatternBasedBirthmarkElement(CurrentDepth[] depthArray){
26         super(getStringRepresentation(depthArray));
27         for(CurrentDepth depth: depthArray){
28             list.add(depth);
29         }
30     }
31     public StackPatternBasedBirthmarkElement(String value){
32         super(value);
33         String[] depthList = value.split(", ");
34         for(int i = 0; i < depthList.length; i++){
35             String[] depthStringArray = depthList[i].split(":");
36             if(depthStringArray.length == 4){
37                 int opcode = Integer.parseInt(depthStringArray[0]);
38                 int depth = Integer.parseInt(depthStringArray[1]);
39                 int weight = Integer.parseInt(depthStringArray[2]);
40                 int act = Integer.parseInt(depthStringArray[3]);
41
42                 Opcode o = new Opcode(OpcodeManager.getInstance().getOpcode(opcode));
43                 o.setWeight(weight);
44                 if(o.getCategory() == Opcode.Category.OBJECT || 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     public Iterator<CurrentDepth> iterator(){
61         return Collections.unmodifiableList(list).iterator();
62     }
63
64     public int getWeight(StackPatternBasedBirthmarkElement element){
65         int[][] matrix = new int[element.getLength() + 1][getLength() + 1];
66
67         for(int i = 0; i <= element.getLength(); i++){
68             for(int j = 0; j <= getLength(); j++){
69                 if(i == 0 || j == 0){
70                     matrix[i][j] = 0;
71                 }
72                 else if(element.getDepth(i - 1).getOpcode().getOpcode() == getDepth(j - 1).getOpcode().getOpcode()){
73                     matrix[i][j] = (int)(matrix[i - 1][j - 1] + getDepth(j - 1).getOpcode().getWeight());
74                 }
75                 else{
76                     matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
77                 }
78             }
79         }
80
81         int max = 0;
82         int last = element.getLength();
83         for(int i = 0; i < matrix[last].length; i++){
84             if(matrix[last][i] > max){
85                 max = matrix[last][i];
86             }
87         }
88         return max;
89     }
90
91     public int getWeight(){
92         if(weight < 0){
93             int w = 0;
94             for(CurrentDepth depth: this){
95                 w += depth.getOpcode().getWeight();
96             }
97             this.weight = w;
98         }
99         return weight;
100     }
101
102     private static String getStringRepresentation(CurrentDepth[] depth){
103         StringBuilder builder = new StringBuilder();
104         for(int i = 0; i < depth.length; i++){
105             if(i != 0){
106                 builder.append(", ");
107             }
108             builder.append(depth[i]);
109         }
110         return new String(builder);
111     }
112 }