1   /*
2    *  Transition.java
3    *
4    *  Copyright (c) 1998-2005, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Valentin Tablan, 11/Apr/2000
12   *
13   *  $Id: Transition.java,v 1.19 2005/12/28 23:31:32 kwilliams Exp $
14   */
15  
16  package gate.fsm;
17  
18  import java.io.Serializable;
19  import java.util.LinkedList;
20  
21  import gate.Annotation;
22  import gate.jape.BasicPatternElement;
23  import gate.jape.Constraint;
24  
25  /**
26    * This class implements a Finite State Machine transition.
27    * A transition is owned by a gate.fsm.State object and contains set of
28    * restrictions and a reference to the next state that will be accessed after
29    * consuming a set of input symbols according to the restrictions.
30    * A transition can also hold information about the label that should be bound
31    * to the symbols (annotations) consumed during the state transition.
32    */
33  // >>> DAM
34  /*
35  public class Transition implements Serializable {
36  */
37  // >>> DAM, TransArray optimzation, now implements the Comparable interface
38  public class Transition implements Serializable, Comparable {
39  // >>> DAM, end
40  
41    /** Debug flag */
42    private static final boolean DEBUG = false;
43  
44    /**
45      * Default constructor. Creates a new transition with a new unique index.
46      * This constructor should be called by all other constructors.
47      */
48    public Transition() {
49      myIndex = Transition.index++;
50    }
51  
52    /**
53      * Creates a new transition using the given set of constraints and target
54      * state.
55      * @param constraints the set on constraints associated to this transition
56      * @param state the target state of this transition
57      */
58    public Transition(BasicPatternElement constraints, State state) {
59      this(constraints, state, new LinkedList());
60    }
61  
62    /**
63      * Creates a new transition from a set of constraints, a target state and a
64      * list of labels to be bound with the recognized input symbols
65      * (aka annotations).
66      */
67    public Transition(BasicPatternElement constraints, State state,
68                      LinkedList bindings) {
69      this();
70      this.constraints = constraints;
71      target = state;
72      this.bindings = bindings;
73    }
74  
75    /**
76      * Creates a new transition to the given State with the same 
77      * bindings as this one.
78      */
79    public Transition spawn(State s)
80    {
81        return new Transition(constraints, s, bindings);
82    }
83  
84    /**
85      * Gets the target state of this transition
86      * @return an object of type gate.fsm.State
87      */
88    public State getTarget(){ return target; }
89  
90    /**
91      * Gets the constraints associated to this transition
92      */
93    public BasicPatternElement getConstraints(){ return constraints; }
94  
95    /**
96      * Returns a boolean value indicating whether this Transition 
97      * has any constraints on it.
98      */
99    public boolean hasConstraints()
100   {
101       return constraints != null;
102   }
103 
104   /**
105     * Returns true if all the constraints on this transition are satisfied
106     * by the given Annotations, false otherwise.  The given Annotations
107     * should be the set of Annotations beginning at a single point in the
108     * document.
109     */
110   public boolean satisfiedBy(Annotation[] coIncidentAnnos) {
111       Constraint[] allConstraints = getConstraints().getConstraints();
112       
113       processAllConstraints:
114       for (int i = 0; i < allConstraints.length; i++)
115       {
116           Constraint c = allConstraints[i];
117           boolean negated = c.isNegated();
118           
119           for (int j = 0; j < coIncidentAnnos.length; j++)
120           {
121               if (coIncidentAnnos[j].getType().equals(c.getAnnotType())
122                   &&
123                   coIncidentAnnos[j].getFeatures().subsumes(c.getAttributeSeq()))
124               {
125                   // One of these puppies being satisfied invalidates the whole transition
126                   if (negated) return false;
127                   
128                   // This constraint is satisfied, go on to the next one
129                   continue processAllConstraints;
130               }
131           }
132           
133           // No matching annotations found for this constraint
134           if (!negated) return false;
135       }
136       
137       // All constraints satisfied
138       return true;
139   }
140 
141   /**
142     * Returns a boolean value indicating whether this Transition 
143     * deals with multiple types of annotations.
144     */
145   public boolean isMultiType() {
146       return constraints != null && constraints.isMultiType();
147   }
148   
149   /**
150     * Returns a textual desciption of this transition.
151     * @return a String
152     */
153   public String toString(){
154     String res = "If: " + constraints + " then ->: " + target.getIndex();
155     return res;
156   }
157 
158   /**
159     * Returns a shorter description that toSting().
160     * Actually, it returns the unique index in String form.
161     */
162   public String shortDesc(){
163     String res = "" + myIndex;
164     return res;
165   }
166 
167   /**
168     *  Returns the list of bindings associated to this transition
169     */
170   public LinkedList getBindings(){ return bindings; }
171 
172   /**
173     * The constraints on this transition.
174     */
175   private BasicPatternElement constraints;
176 
177   /**
178     * The state this transition leads to
179     */
180   private State target;
181 
182   /**
183     * A list with all the labels associated to the annotations recognized by
184     * this transition.
185     * We need to use the actual object and not the interface (java.util.List)
186     * because we need this object to be cloneable
187     */
188   private LinkedList bindings;
189 
190   /** The unique index of this transition. This value is not used by any of
191     * the algorithms. It is only provided as a convenient method of identifying
192     * the transitions in textual representations (toString() and GML related
193     * methods)
194     */
195   private int myIndex;
196 
197   /** Static member used for generating unique IDs for the objects of type
198     * Transition*/
199   private static int index = 0;
200 
201 // >>> DAM, TransArray optimzation, now implements the Comparable interface
202   public int compareTo(Object o)
203   throws ClassCastException
204   {
205     if (!(o instanceof Transition)) throw new ClassCastException("gate.frm.Transition(compareTo)");
206     return myIndex - ((Transition)o).myIndex;
207   }
208 // >>> DAM, end
209 } // Transition
210