KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ba > obl > StateSet


1 /*
2  * Bytecode Analysis Framework
3  * Copyright (C) 2005, University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs.ba.obl;
21
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Map JavaDoc;
25
26 /**
27  * A dataflow fact used in ObligationAnalysis.
28  * It is a set of State objects, plus the additional capability
29  * to represent top and bottom elements.
30  *
31  * <p>Invariant: no StateSet may contain more than one
32  * State with the same ObligationSet.</p>
33  *
34  * <p>See Weimer and Necula,
35  * <a HREF="http://doi.acm.org/10.1145/1028976.1029011"
36  * >Finding and preventing run-time error handling mistakes</a>,
37  * OOPSLA 2004.</p>
38  *
39  * @author David Hovemeyer
40  */

41 public class StateSet {
42     public interface StateCallback {
43         public void apply(State state) throws NonexistentObligationException;
44     }
45     
46     private boolean isTop;
47     private boolean isBottom;
48     private Map JavaDoc<ObligationSet, State> stateMap;
49     private ObligationFactory factory;
50
51     public StateSet(ObligationFactory factory) {
52         this.isTop = this.isBottom = false;
53         this.stateMap = new HashMap JavaDoc<ObligationSet, State>();
54         this.factory = factory;
55     }
56
57     public void setTop() {
58         this.isTop = true;
59         this.isBottom = false;
60     }
61
62     public boolean isTop() {
63         return isTop;
64     }
65
66     public void setBottom() {
67         this.isBottom = true;
68         this.isTop = false;
69     }
70
71     public boolean isBottom() {
72         return this.isBottom;
73     }
74
75     public boolean isValid() {
76         return !this.isTop && !this.isBottom;
77     }
78     
79     /**
80      * Return an Iterator over the States in the StateSet.
81      *
82      * @return an Iterator over the States in the StateSet
83      */

84     public Iterator JavaDoc<State> stateIterator() {
85         return stateMap.values().iterator();
86     }
87     
88     /**
89      * Get the State which has the given ObligationSet.
90      * Returns null if there is no such state.
91      *
92      * @param obligationSet we want to get the State with this ObligationSet
93      * @return the State with the given ObligationSet, or null if there is no such State
94      */

95     public State getStateWithObligationSet(ObligationSet obligationSet) {
96         return stateMap.get(obligationSet);
97     }
98     
99     /**
100      * Initialize this object as the entry fact for a method:
101      * a single state with empty obligation set and path.
102      *
103      * @param factory the ObligationFactory used for the analysis
104      */

105     public void initEntryFact(ObligationFactory factory) {
106         this.isTop = this.isBottom = false;
107         this.stateMap.clear();
108         
109         // Add initial fact: empty obligations, empty path
110
State initState = new State(factory.getMaxObligationTypes(), factory);
111         this.stateMap.put(initState.getObligationSet(), initState);
112     }
113     
114     /**
115      * Make this StateSet an exact copy of the given StateSet.
116      *
117      * @param other a StateSet; this StateSet will be made identical to it
118      */

119     public void copyFrom(StateSet other) {
120         this.isTop = other.isTop;
121         this.isBottom = other.isBottom;
122         this.stateMap.clear();
123         for (State state : other.stateMap.values()) {
124             State dup = state.duplicate();
125             this.stateMap.put(dup.getObligationSet(), dup);
126         }
127     }
128     
129     /**
130      * Return an exact deep copy of this StateSet.
131      *
132      * @return an exact deep copy of this StateSet
133      */

134     public StateSet duplicate() {
135         StateSet dup = new StateSet(factory);
136         dup.copyFrom(this);
137         return dup;
138     }
139     
140     /**
141      * Add an obligation to every State in the StateSet.
142      *
143      * @param obligation the obligation to add
144      */

145     public void addObligation(final Obligation obligation) {
146         final Map JavaDoc<ObligationSet, State> updatedStateMap =
147             new HashMap JavaDoc<ObligationSet, State>();
148         
149         try {
150             applyToAllStatesAndUpdateMap(new StateCallback() {
151                 public void apply(State state) {
152                     state.getObligationSet().add(obligation);
153                     updatedStateMap.put(state.getObligationSet(), state);
154                 }
155             }, updatedStateMap);
156         } catch (NonexistentObligationException e) {
157             // This can't actually happen.
158
}
159     }
160     
161     /**
162      * Remove an Obligation from every State in the StateSet.
163      *
164      * @param obligation the obligation to remove
165      * @throws NonexistentObligationException
166      */

167     public void deleteObligation(final Obligation obligation)
168             throws NonexistentObligationException {
169         final Map JavaDoc<ObligationSet, State> updatedStateMap =
170             new HashMap JavaDoc<ObligationSet, State>();
171         
172         applyToAllStatesAndUpdateMap(new StateCallback() {
173             /* (non-Javadoc)
174              * @see edu.umd.cs.findbugs.ba.obl.StateSet.StateCallback#apply(edu.umd.cs.findbugs.ba.obl.State)
175              */

176             public void apply(State state)
177                     throws NonexistentObligationException {
178                 state.getObligationSet().remove(obligation);
179                 updatedStateMap.put(state.getObligationSet(), state);
180             }
181         }, updatedStateMap);
182     }
183     
184     @Override JavaDoc
185     public boolean equals(Object JavaDoc o) {
186         if (o == null || o.getClass() != this.getClass())
187             return false;
188         StateSet other = (StateSet) o;
189         return this.isTop == other.isTop
190             && this.isBottom == other.isBottom
191             && this.stateMap.equals(other.stateMap);
192     }
193     
194     @Override JavaDoc
195     public int hashCode() {
196         throw new UnsupportedOperationException JavaDoc();
197     }
198     
199     @Override JavaDoc
200     public String JavaDoc toString() {
201         if (isTop)
202             return "TOP";
203         else if (isBottom)
204             return "BOTTOM";
205         else {
206             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
207             boolean first = true;
208             for (Iterator JavaDoc<State> i = stateIterator(); i.hasNext();) {
209                 State state = i.next();
210                 if (first)
211                     first = false;
212                 else
213                     buf.append(",");
214                 buf.append(state.toString());
215             }
216             return buf.toString();
217         }
218     }
219     
220     /**
221      * Return a newly allocated Map of ObligationSet to State
222      * that may be passed to applyToAllStatesAndUpdateMap().
223      */

224     public Map JavaDoc<ObligationSet, State> createEmptyMap() {
225         return new HashMap JavaDoc<ObligationSet, State>();
226     }
227     
228     /**
229      * Apply a callback to all States and replace the
230      * ObligationSet -&gt; State map with the one given
231      * (which is assumed to be updated by the callback.)
232      *
233      * @param callback the callback
234      * @param updatedStateMap updated map of ObligationSets to States
235      */

236     public void applyToAllStatesAndUpdateMap(StateCallback callback,
237             Map JavaDoc<ObligationSet, State> updatedStateMap)
238             throws NonexistentObligationException {
239         applyToAllStates(callback);
240         this.stateMap = updatedStateMap;
241     }
242
243     /**
244      * Apply a callback to all States in the StateSet.
245      *
246      * @param callback
247      */

248     public void applyToAllStates(StateCallback callback)
249             throws NonexistentObligationException {
250         for (State state : stateMap.values()) {
251             callback.apply(state);
252         }
253     }
254 }
255
256 // vim:ts=4
257
Popular Tags