001 /*
002 * State.java
003 *
004 * Copyright (c) 1995-2010, The University of Sheffield. See the file
005 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006 *
007 * This file is part of GATE (see http://gate.ac.uk/), and is free
008 * software, licenced under the GNU Library General Public License,
009 * Version 2, June 1991 (in the distribution as file licence.html,
010 * and also available at http://gate.ac.uk/gate/licence.html).
011 *
012 * Valentin Tablan, 11/Apr/2000
013 *
014 * $Id: State.java 12006 2009-12-01 17:24:28Z thomas_heitz $
015 */
016
017 package gate.fsm;
018
019 import java.util.ArrayList;
020 import java.util.HashMap;
021 import java.util.Iterator;
022
023 import gate.jape.*;
024 import gate.util.SimpleArraySet;
025
026 /**
027 * This class implements a Finite State Machine state.
028 *
029 */
030 public class State implements JapeConstants {
031
032 /** Debug flag
033 */
034
035 private static final boolean DEBUG = false;
036
037 public static final int UNKNOWN_INDEX = 1;
038 public static final int VISITED_INDEX = -2;
039 public static final int UNVISITED_INDEX = 2;
040 public static final int INITIAL_INDEX = 0;
041 public static final String INITIAL_RULE = "_____Initial_State_for_all_rules";
042 public static final String UNKNOWN_RULE = "___UNKNOWN_RULES_TYPE_1";
043 public static final String UNVISITED_RULE = "___UNKNOWN_RULES_TYPE_2";
044
045 // Points to the rule in the FSM which created this state
046 private int indexInRuleList = UNVISITED_INDEX;
047
048 /**
049 *
050 * @return The index of the rule in the ruleTimes ArrayList held in the FSM
051 */
052 public int getIndexInRuleList() {
053 return indexInRuleList;
054 }
055
056 /**
057 * This should only need to be called by getRuleForState when the state is being initialized
058 * @param indexInRuleList
059 */
060 void setIndexInRuleList(int indexInRuleList) {
061 this.indexInRuleList = indexInRuleList;
062 }
063
064 /**
065 * Sets the index of the rule for this state.
066 * Determines the appropriate rule by recursively searching this state's outbound transitions until
067 * we reach a final state. Record this state in the ruleTimes and ruleNameToIndexMap structures
068 * @param ruleNameToIndexMap
069 * @param ruleTimes
070 * @return
071 */
072 public int getRuleForState(HashMap<String,Integer> ruleNameToIndexMap,ArrayList<RuleTime>ruleTimes) {
073 if (this.getIndexInRuleList() != UNVISITED_INDEX) {
074 return this.getIndexInRuleList();
075 }
076 if (this.isFinal()) {
077 String ruleNameOfThisState = this.getAction().getRuleName();
078 int returnVal;
079 if (ruleNameToIndexMap.containsKey(ruleNameOfThisState)) {
080 returnVal = ruleNameToIndexMap.get(ruleNameOfThisState);
081 }
082 else {
083 ruleTimes.add(new RuleTime(0,ruleNameOfThisState));
084 ruleNameToIndexMap.put(ruleNameOfThisState, ruleTimes.size() - 1);
085 returnVal = ruleTimes.size() - 1;
086 }
087 this.setIndexInRuleList(returnVal);
088 return returnVal;
089 }
090 else {
091 this.setIndexInRuleList(VISITED_INDEX);
092 int returnVal = UNKNOWN_INDEX;
093 // Note that returnVal will always need to be the same for all returned elements
094 // (because a state is currently associated with only one rule), but
095 // we need to call it repeateadly to set the indexInRuleList for all states in
096 // the tree
097 for (Transition t :this.getTransitions()) {
098 int tempReturn = t.getTarget().getRuleForState(ruleNameToIndexMap,ruleTimes);
099 if (tempReturn != UNKNOWN_INDEX && tempReturn != VISITED_INDEX) {
100 returnVal = tempReturn;
101 }
102 }
103 if (returnVal == UNKNOWN_INDEX) {
104 this.setIndexInRuleList(returnVal);
105 }
106 else {
107 this.propogateRuleForward(returnVal);
108 }
109 return returnVal;
110 }
111 }
112
113
114 /**
115 * This sets the rule index for every descendant of the current state
116 * Note that we only need to set the state for states whose rule is Unknown
117 * Rules whose state is "VISITED_INDEX" are my ancestors. Their states will be set
118 * when the recursion backs out. Rules whose index is something other than VISITED_INDEX or
119 * UNKNOWN_RULE are finished and we know that all of their descendants have been set, by
120 * the properties of this algorithm
121 * @param ruleForThisState The rule to be associated with this state
122 */
123 private void propogateRuleForward(int ruleForThisState) {
124 this.setIndexInRuleList(ruleForThisState);
125 for (Transition t: this.getTransitions()) {
126 if (t.getTarget().getIndexInRuleList() == UNKNOWN_INDEX) {
127 t.getTarget().propogateRuleForward(ruleForThisState);
128 }
129 }
130 }
131
132 /**
133 * Build a new state.
134 */
135 public State() {
136 myIndex = State.index++;
137 isFinal = false;
138 }
139
140 /**
141 * Reports if this state is a final one.
142 * Note: A state has an associated action if and only if it is final.
143 */
144 public boolean isFinal() {
145 return isFinal;
146 }
147
148 /**
149 * Gets the set of transitions for this state.
150 *
151 * @return a Set contining objects of type gate.fsm.Transition
152 */
153 // >>> DAM, was Set
154 /*
155 public Set getTransitions() {
156 return transitions;
157 }
158 */
159 // >>> DAM, TransArray optimization
160 public SimpleArraySet<Transition> getTransitions() {
161 return transitions;
162 }
163 // >>> DAM, end
164 /** Sets the action associated to this FINAL state. An action is actually
165 * a gate.jape.RightHandSide object.
166 * NOTE: only a final state has an associated action so after a call to this
167 * method this state will be a final one.
168 */
169 protected void setAction(RightHandSide rhs) {
170 action = rhs;
171 isFinal = (action != null);
172 }
173
174 /** Sets the value for fileIndex. File index is the index in the jape
175 * definition file of the rule that contains as right hand side the action
176 * associated to this state. This value is only intended for final states.
177 */
178 protected void setFileIndex(int i) { fileIndex = i; }
179
180 /** Sets the value for priority. Priority is the priority in the jape
181 * definition file of the rule that contains as right hand side the action
182 * associated to this state. This value is only intended for final states.
183 */
184 protected void setPriority(int i) { priority = i; }
185
186 /**
187 * Gets the action associated to this state.
188 *
189 * @return a RightHandSide object
190 */
191 public RightHandSide getAction() {
192 return action;
193 }
194
195 /**
196 * Returns the index in the definition file of the rule that generated this
197 * state.
198 * The value for fileIndex is correct only on final states!
199 */
200 int getFileIndex() { return fileIndex; }
201
202 /**
203 * Returns the priority in the definition file of the rule that generated
204 * this state.
205 * This value is correct only on final states!
206 */
207 int getPriority() { return priority; }
208
209 /**
210 * Adds a new transition to the list of outgoing transitions for this state.
211 *
212 * @param transition the transition to be added
213 */
214 public void addTransition(Transition transition) {
215 transitions.add(transition);
216 } // addTransition
217
218 /**
219 * Gets the index of this state. Each state has a unique index (a int value).
220 * This value is not actually used by any of the algorithms. It is useful only
221 * as a way of refering to states in string representations so it is used by
222 * toString and GML related methods.
223 *
224 * @return the index associated to this state
225 */
226 public int getIndex() {
227 return myIndex;
228 }// getIndex
229
230 /**
231 * Returns a GML (graph modelling language) representation for the edges
232 * corresponding to transitions departing from this state in the
233 * transition graph of the FSM to which this state belongs
234 *
235 * @return a string value contining the GML text
236 */
237 public String getEdgesGML() {
238 /// String res = "";
239 StringBuffer res = new StringBuffer(gate.Gate.STRINGBUFFER_SIZE);
240
241 Iterator transIter = transitions.iterator();
242 BasicPatternElement bpe;
243
244 while(transIter.hasNext()) {
245 Transition currentTrans = (Transition)transIter.next();
246 /* res += "edge [ source " + myIndex +
247 " target " + currentTrans.getTarget().getIndex() +
248 " label \"" + currentTrans.shortDesc() + ":";
249 */
250 res.append("edge [ source ");
251 res.append(myIndex);
252 res.append(" target ");
253 res.append(currentTrans.getTarget().getIndex());
254 res.append(" label \"");
255 res.append(currentTrans.shortDesc());
256 res.append(":");
257
258 bpe = currentTrans.getConstraints();
259 if(bpe == null) ///res += "null";
260 res.append("null");
261 else ///res += bpe.shortDesc();
262 res.append(bpe.shortDesc());
263 /// res += " :" + currentTrans.getBindings() + "\" ]\n";
264 res.append(" :");
265 res.append(currentTrans.getBindings());
266 res.append("\" ]\n");
267 }
268 return res.toString();
269 } // getEdgesGML
270
271 /**
272 * Returns a textual description of this state
273 *
274 * @return a String value.
275 */
276 public String toString() {
277 /// String res = "State " + myIndex;
278 StringBuffer res = new StringBuffer(gate.Gate.STRINGBUFFER_SIZE);
279
280 if(isFinal()) ///res += "\nFinal!";
281 res.append("\nFinal!");
282
283 ///res += "\nTransitions:\n";
284 res.append("\nTransitions:\n");
285
286 Iterator transIter = transitions.iterator();
287 while(transIter.hasNext()){
288 ///res += transIter.next().toString();
289 res.append(transIter.next().toString());
290 }
291 return res.toString();
292 }
293
294
295 /**
296 * A set of objects of type gata.fsm.Transition representing the outgoing
297 * transitions.
298 */
299 // >>> DAM was
300 /*
301 private Set transitions = new HashSet();
302 */
303 // >>> DAM, TransArray optimization
304 private SimpleArraySet<Transition> transitions = new SimpleArraySet<Transition>();
305 // >>> DAM, end
306
307 /**
308 * Is this state a final one?
309 */
310 protected boolean isFinal = false;
311
312 /**
313 * The right hand side associated to the rule for which this state recognizes
314 * the lhs.
315 */
316 protected RightHandSide action = null;
317
318 /**
319 * The unique index of this state.
320 */
321 protected int myIndex;
322
323 /**
324 * The class data member used for generating unique indices for State
325 * instances.
326 */
327 protected static int index = 0;
328
329 /**
330 * The index in the definition file of the rule that was used for creating
331 * this state.
332 * NOTE: this member is consistent only for FINAL STATES!
333 */
334 protected int fileIndex = 0;
335
336 /**
337 * The priority of the rule from which this state derived.
338 *
339 */
340 protected int priority = -1;
341
342 } // State
|