Migrate GraphNode functionality into its own class and we inherit from this class...
[IRC.git] / Robust / src / Analysis / TaskStateAnalysis / FlagState.java
1 package Analysis.TaskStateAnalysis;
2 import Analysis.TaskStateAnalysis.*;
3 import IR.*;
4 import IR.Tree.*;
5 import IR.Flat.*;
6 import java.util.*;
7 import java.io.*;
8 import Util.GraphNode;
9
10 /** This class is used to hold the flag states that a class in the Bristlecone 
11  *  program can exist in, during runtime.
12  */
13 public class FlagState extends GraphNode {
14     public static final int ONETAG=1;
15     public static final int NOTAGS=0;
16     public static final int MULTITAGS=-1;
17     
18     private int uid;
19     private static int nodeid=0;
20
21     private final HashSet flagstate;
22     private final ClassDescriptor cd;
23     private final Hashtable<TagDescriptor,Integer> tags;
24
25     public void setOption(String option) {
26         this.nodeoption=","+option;
27     }
28
29     public void setMerge() {
30         merge=true;
31     }
32
33     /** Class constructor
34      *  Creates a new flagstate with all flags set to false.
35      *  @param cd ClassDescriptor
36      */
37     public FlagState(ClassDescriptor cd) {
38         this.flagstate=new HashSet();
39         this.cd=cd;
40         this.tags=new Hashtable<TagDescriptor,Integer>();
41         this.uid=FlagState.nodeid++;
42     }
43
44     /** Class constructor
45      *  Creates a new flagstate with flags set according to the HashSet.
46      *  If the flag exists in the hashset, it's set to true else set to false.
47      *  @param cd ClassDescriptor
48      *  @param flagstate a <CODE>HashSet</CODE> containing FlagDescriptors
49      */
50     private FlagState(HashSet flagstate, ClassDescriptor cd,Hashtable<TagDescriptor,Integer> tags) {
51         this.flagstate=flagstate;
52         this.cd=cd;
53         this.tags=tags;
54         this.uid=FlagState.nodeid++;
55         
56     }
57     
58     /** Accessor method
59       *  @param fd FlagDescriptor
60       *  @return true if the flagstate contains fd else false.
61       */
62     public boolean get(FlagDescriptor fd) {
63         return flagstate.contains(fd);
64     }
65
66     
67     public String toString() {
68         return cd.toString()+getTextLabel();
69     }
70
71     /** @return Iterator over the flags in the flagstate.
72      */
73      
74     public Iterator getFlags() {
75         return flagstate.iterator();
76     }
77     
78     public FlagState setTag(TagDescriptor tag){
79            
80             HashSet newset=(HashSet)flagstate.clone();
81             Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
82             
83             if (newtags.containsKey(tag)){
84                    switch (newtags.get(tag).intValue()){
85                            case ONETAG:
86                                         newtags.put(tag,new Integer(MULTITAGS));
87                                         break;
88                            case MULTITAGS:
89                                         newtags.put(tag,new Integer(MULTITAGS));
90                                         break;
91                         }
92                 }
93                 else{
94                         newtags.put(tag,new Integer(ONETAG));
95                 }
96                 
97                 return new FlagState(newset,cd,newtags);
98                                 
99     }
100
101     public int getTagCount(String tagtype){
102                 for (Enumeration en=getTags();en.hasMoreElements();){
103                         TagDescriptor td=(TagDescriptor)en.nextElement();
104                         if (tagtype.equals(td.getSymbol()))
105                                 return tags.get(td).intValue();   //returns either ONETAG or MULTITAG
106                 }
107                 return NOTAGS;
108                 
109     }
110     
111     public FlagState[] clearTag(TagDescriptor tag){
112             FlagState[] retstates;
113             
114             if (tags.containsKey(tag)){
115             switch(tags.get(tag).intValue()){
116                     case ONETAG:
117                         HashSet newset=(HashSet)flagstate.clone();
118                         Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
119                         newtags.remove(tag);
120                         retstates=new FlagState[]{new FlagState(newset,cd,newtags)};
121                         return retstates;
122                         
123                     case MULTITAGS:
124                         //when tagcount is more than 2, COUNT stays at MULTITAGS
125                         retstates=new FlagState[2];
126                         HashSet newset1=(HashSet)flagstate.clone();
127                         Hashtable<TagDescriptor,Integer> newtags1=(Hashtable<TagDescriptor,Integer>)tags.clone();
128                         retstates[1]=new FlagState(newset1,cd,newtags1);
129                         //when tagcount is 2, COUNT changes to ONETAG
130                         HashSet newset2=(HashSet)flagstate.clone();
131                         Hashtable<TagDescriptor,Integer> newtags2=(Hashtable<TagDescriptor,Integer>)tags.clone();
132                         newtags1.put(tag,new Integer(ONETAG));
133                         retstates[1]=new FlagState(newset2,cd,newtags2);
134                         return retstates;
135                 default:
136                         return null;                    
137         }
138                 }else{
139                         throw new Error("Invalid Operation: Can not clear a tag that doesn't exist.");
140                         
141                 }
142                 
143     }
144     
145     /** Creates a string description of the flagstate
146      *  e.g.  a flagstate with five flags could look like 01001
147      *  @param flags an array of flagdescriptors.
148      *  @return string representation of the flagstate.
149      */
150         public String toString(FlagDescriptor[] flags)
151         {
152                 StringBuffer sb = new StringBuffer(flagstate.size());
153                 for(int i=0;i < flags.length; i++)
154                 {
155                         if (get(flags[i]))
156                                 sb.append(1);
157                         else
158                                 sb.append(0);
159                 }
160                         
161                 return new String(sb);
162         }
163
164         /** Accessor method
165          *  @return returns the classdescriptor of the flagstate.
166          */
167          
168     public ClassDescriptor getClassDescriptor(){
169         return cd;
170     }
171
172         /** Sets the status of a specific flag in a flagstate after cloning it.
173          *  @param      fd FlagDescriptor of the flag whose status is being set.
174          *  @param  status boolean value
175          *  @return the new flagstate with <CODE>fd</CODE> set to <CODE>status</CODE>.
176          */
177          
178     public FlagState setFlag(FlagDescriptor fd, boolean status) {
179         HashSet newset=(HashSet) flagstate.clone();
180         Hashtable<TagDescriptor,Integer> newtags=(Hashtable<TagDescriptor,Integer>)tags.clone();
181         if (status)
182             newset.add(fd);
183         else if (newset.contains(fd)){
184             newset.remove(fd);
185         }
186         
187         return new FlagState(newset, cd,newtags);
188     }
189     
190     /** Tests for equality of two flagstate objects.
191     */
192     
193     public boolean equals(Object o) {
194         if (o instanceof FlagState) {
195             FlagState fs=(FlagState)o;
196             if (fs.cd!=cd)
197                 return false;
198             return (fs.flagstate.equals(flagstate) & fs.tags.equals(tags));
199         }
200         return false;
201     }
202
203     public int hashCode() {
204         return cd.hashCode()^flagstate.hashCode()^tags.hashCode();
205     }
206
207     public String getLabel() {
208         return "N"+uid;
209     }
210
211     public String getTextLabel() {
212         String label=null;
213         for(Iterator it=getFlags();it.hasNext();) {
214             FlagDescriptor fd=(FlagDescriptor) it.next();
215             if (label==null)
216                 label=fd.toString();
217             else
218                 label+=", "+fd.toString();
219         }
220         for (Enumeration en_tags=getTags();en_tags.hasMoreElements();){
221                 TagDescriptor td=(TagDescriptor)en_tags.nextElement();
222                 switch (tags.get(td).intValue()){
223                         case ONETAG:
224                                 label+=", "+td.toString()+"(1)";
225                                 break;
226                         case MULTITAGS:
227                                 label+=", "+td.toString()+"(n)";
228                                 break;
229                         default:
230                                 break;
231                 }
232         }
233         return label;
234     }
235     
236     public Enumeration getTags(){
237             return tags.keys();
238     }
239 }