| FSMInstance |

    1   /*
    2    *  FSMInstance.java
    3    *
    4    *  Copyright (c) 1998-2001, 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, 05/May/2000
    12   *
    13   *  $Id: FSMInstance.java,v 1.20 2001/11/16 13:24:51 valyt Exp $
    14   */
    15  package gate.fsm;
    16
    17  import gate.*;
    18  import gate.annotation.AnnotationSetImpl;
    19  import gate.util.*;
    20  import gate.jape.*;
    21
    22  import java.util.*;
    23  import java.io.*;
    24
    25  /**
    26    * The objects of this class represent instances of working Finite State
    27    * Machine during parsing a gate document (annotation set).
    28    * In order to completely define the state a FSM is in one needs to store
    29    * information regarding:
    30    * -the position in the FSM transition graph
    31    * -the position in the annotation graph
    32    * -the set of bindings that occured up to the current state.
    33    *  note that a set of bindings is an object of type Map that maps names
    34    * (java.lang.String) to bags of annotations (gate.AnnotationSet)
    35    */
    36  public class FSMInstance implements Comparable, Cloneable, Serializable {
    37
    38    /** Debug flag */
    39    private static final boolean DEBUG = false;
    40
    41    /** Creates a new FSMInstance object.
    42      * @param supportGraph the transition graph of the FSM
    43      * @param FSMPosition the state this instance will be in
    44      * @param startNode the node in the AnnotationGraph where this FSM instance
    45      * started the matching
    46      * @ AGPosition the node in the AnnotationGraph up to which this FSM Instance
    47      * advanced during the matching.
    48      * @param bindings a HashMap that maps from labels (objects of type String)
    49      * to sets of annotations (objects of type AnnotationSet). This map stores
    50      * all the bindings that took place during the matching process.
    51      * This FSMInstance started the matching on an AnnotationSet from "startNode"
    52      * and advanced to "AGPosition"; during this process it traversed the path in
    53      * the transition graph "supportGraph" from the initial state to
    54      * "FSMPosition" and made the bindings stored in "bindings".
    55      */
    56    public FSMInstance(FSM supportGraph, State FSMPosition,
    57                       Node startNode, Node AGPosition, HashMap bindings,
    58                       Document document) {
    59
    60      this.supportGraph = supportGraph;
    61      this.FSMPosition = FSMPosition;
    62      this.startNode = startNode;
    63      this.AGPosition = AGPosition;
    64      this.bindings = bindings;
    65      this.document = document;
    66      length = AGPosition.getOffset().longValue() -
    67               startNode.getOffset().longValue();
    68      fileIndex = FSMPosition.getFileIndex();
    69      priority = FSMPosition.getPriority();
    70    }
    71
    72    /** Returns the FSM transition graph that backs this FSM instance
    73      * @return an FSM object
    74      */
    75    public FSM getSupportGraph(){ return supportGraph; }
    76
    77    /** Returns the position in the support graph for this FSM instance
    78      * @return an object of type State
    79      */
    80    public State getFSMPosition(){ return FSMPosition; }
    81
    82    /** Sets the position in the support transition graph for this FSM instance
    83      * Convenience method for when the state is not known at construction time.
    84      */
    85    public void setFSMPosition(State newFSMPos) {
    86      FSMPosition = newFSMPos;
    87      fileIndex = FSMPosition.getFileIndex();
    88      priority = FSMPosition.getPriority();
    89    }
    90
    91    /** Returns the index in the Jape definition file of the rule that caused
    92      * the generation of the FSM state this instance is in.
    93      * This value is correct if and only if this FSM instance is in a final
    94      * state of the FSM transition graph.
    95      * @return an int value.
    96      */
    97    public int getFileIndex(){ return fileIndex; }
    98
    99    /** Returns the node in the AnnotationGraph from which this FSM instance
    100     * started the matching process.
    101     * @return a gate.Node object
    102     */
    103   public Node getStartAGPosition(){ return startNode; }
    104
    105   /** Returns the node up to which this FSM instance advanced in the
    106     * Annotation graph during the matching process.
    107     * @return a gate.Node object
    108     */
    109   public Node getAGPosition(){ return AGPosition; }
    110
    111   /** Sets the current position in the AnnotationGraph.
    112     * Convenience method for cases when this value is not known at construction
    113     * time.
    114     * @param node a position in the AnnotationGraph
    115     */
    116   public void setAGPosition(Node node){
    117     AGPosition = node;
    118     length = AGPosition.getOffset().longValue() -
    119              startNode.getOffset().longValue();
    120   }
    121
    122   /** Gets the map representing the bindings that took place during the matching
    123     * process this FSM instance performed.
    124     * @return a HashMap object
    125     */
    126   public HashMap getBindings() { return bindings; }
    127
    128   /** Returns the length of the parsed region in the document under scrutiny.
    129     * More precisely this is the distnace between the Node in the annotation
    130     * graph where the matching started and the current position.
    131     * @return a long value
    132     */
    133   public long getLength() { return length; }
    134
    135   /** Overrides the hashCode method from Object so this obejcts can be stored in
    136     * hash maps and hash sets.
    137     */
    138   public int hashCode() {
    139     return (int)length ^ priority ^ fileIndex ^ bindings.hashCode() ^
    140            FSMPosition.getAction().hashCode();
    141   }
    142
    143   public boolean equals(Object other){
    144     if(other instanceof FSMInstance){
    145       FSMInstance otherFSM = (FSMInstance)other;
    146       boolean result = length == otherFSM.length &&
    147              priority == otherFSM.priority &&
    148              fileIndex == otherFSM.fileIndex &&
    149              bindings.equals(otherFSM.bindings) &&
    150              FSMPosition.getAction().equals(otherFSM.FSMPosition.getAction());
    151       return result;
    152     }else{
    153       throw new ClassCastException(other.getClass().toString());
    154     }
    155   }
    156
    157   /** Returns a clone of this object.
    158     * The cloning is done bitwise except for the bindings that are cloned by
    159     * themselves
    160     * @return an Object value that is actually a FSMInstance object
    161     */
    162   public Object clone() {
    163     //do a classic clone except for bindings which need to be cloned themselves
    164     try {
    165       FSMInstance clone = (FSMInstance)super.clone();
    166       clone.bindings = (HashMap)bindings.clone();
    167       return clone;
    168     } catch (CloneNotSupportedException cnse) {
    169       cnse.printStackTrace(Err.getPrintWriter());
    170       return null;
    171     }
    172   }
    173
    174   /*
    175   public Object clone() {
    176   //do a classic clone except for bindings which need to be cloned themselves
    177   //Out.println("Clone!");
    178     FSMInstance clone = FSMInstance.getNewInstance(this.supportGraph,
    179                                                    this.FSMPosition,
    180                                                    this.startNode,
    181                                                    this.AGPosition,
    182                                                    null);
    183     clone.bindings = (HashMap)(bindings.clone());
    184     return (FSMInstance)clone;
    185   }
    186   */
    187
    188   /** Implementation of the compareTo method required by the Comparable
    189     * interface. The comparison is based on the size of the matched region and
    190     * the index in the definition file of the rule associated to this FSM
    191     * instance (which needs to be in a final state)
    192     * The order imposed by this method is the priority needed in case of a
    193     * multiple match.
    194     */
    195   public int compareTo(Object obj) {
    196     if (obj instanceof FSMInstance) {
    197       if(obj == this) return 0;
    198       FSMInstance other = (FSMInstance)obj;
    199       if(length < other.getLength()) return -1;
    200       else if(length > other.getLength()) return 1;
    201       //equal length
    202       else if(priority < other.priority) return -1;
    203       else if(priority > other.priority) return 1;
    204       //equal priority
    205       else return other.fileIndex - fileIndex;
    206     } else throw new ClassCastException(
    207                     "Attempt to compare a FSMInstance object to an object " +
    208                     "of type " + obj.getClass()+"!");
    209   }
    210
    211   /** Returns a textual representation of this FSM instance.
    212     */
    213   public String toString() {
    214     String res = "";
    215     RightHandSide rhs = getFSMPosition().getAction();
    216     if(rhs != null){
    217       res += rhs.getPhaseName() + "." + rhs.getRuleName() + ": \"";
    218       try{
    219         res += document.getContent().getContent(
    220                         getStartAGPosition().getOffset(),
    221                         getAGPosition().getOffset()).toString() + "\"";
    222       }catch(InvalidOffsetException ioe){
    223         ioe.printStackTrace(Err.getPrintWriter());
    224       }
    225
    226       Iterator labelIter = bindings.keySet().iterator();
    227       res += "\n{";
    228       while(labelIter.hasNext()){
    229         String label = (String)labelIter.next();
    230         Collection annots = (Collection)bindings.get(label);
    231         res += "\n" + label + ": ";
    232         Iterator annIter = annots.iterator();
    233         while(annIter.hasNext()){
    234           Annotation ann  = (Annotation)annIter.next();
    235           res += ann.getType() + "(\"";
    236           try{
    237             res += document.getContent().
    238                             getContent(ann.getStartNode().getOffset(),
    239                                        ann.getEndNode().getOffset()).toString();
    240           }catch(InvalidOffsetException ioe){
    241             ioe.printStackTrace(Err.getPrintWriter());
    242           }
    243           res += "\") ";
    244         }
    245       }
    246       res += "\n}";
    247     }else{
    248       res +=  "FSM position :" + FSMPosition.getIndex() +
    249               "\nFirst matched ANN at:" + startNode.getId() +
    250               "\nLast matched ANN at :" + AGPosition.getId() +
    251               "\nPriority :" + priority +
    252               "\nFile index :" + fileIndex +
    253               "\nBindings     :" + bindings;
    254     }
    255     return res;
    256   }
    257
    258   /** The FSM for which this FSMInstance is an instance of. */
    259   private FSM supportGraph;
    260
    261   /** The current state of this FSMInstance */
    262   private State FSMPosition;
    263
    264   /** The place (Node) in the AnnotationGraph where the matching started*/
    265   private Node AGPosition, startNode;
    266
    267   /** A map from java.lang.String to gate.AnnotationSet describing all the
    268     * bindings that took place during matching.
    269     * needs to be HashMap instead of simply Map in order to cloneable
    270     */
    271   private HashMap bindings;
    272
    273   /** The size of the matched region in the Annotation Graph*/
    274   private long length = 0;
    275
    276   /**
    277     * The index in the definition file of the rule from which the AGPosition
    278     * state was generated.
    279     */
    280   private int fileIndex;
    281
    282
    283   private Document document;
    284   /**
    285     * The priority in the definition file of the rule from which the AGPosition
    286     * state was generated.
    287     */
    288   private int priority;
    289
    290   /** Static method that provides new FSM instances. This method handles some
    291     * basic object pooling in order to reuse the FSMInstance objects.
    292     * This is considered to be a good idea because during jape transducing
    293     * a large number of FSMIntances are needed for short periods.
    294     */
    295   public static FSMInstance getNewInstance(FSM supportGraph, State FSMPosition,
    296                                            Node startNode, Node AGPosition,
    297                                            HashMap bindings, Document doc) {
    298     FSMInstance res;
    299     if(myInstances.isEmpty()) res = new FSMInstance(supportGraph, FSMPosition,
    300                                                     startNode, AGPosition,
    301                                                     bindings, doc);
    302     else {
    303       res = (FSMInstance)myInstances.removeFirst();
    304       res.supportGraph = supportGraph;
    305       res.FSMPosition = FSMPosition;
    306       res.startNode = startNode;
    307       res.AGPosition = AGPosition;
    308       res.bindings = bindings;
    309     }
    310     return res;
    311   }
    312
    313   /** Static method used to return a FSMInstance that is not needed anymore
    314     */
    315   public static void returnInstance(FSMInstance ins) {
    316     myInstances.addFirst(ins);
    317   }
    318
    319   /** Release all the FSMInstances that are not currently in use */
    320   public static void clearInstances() {
    321     myInstances = new LinkedList();
    322   }
    323
    324   /** The list of existing instances of type FSMInstance */
    325   private static LinkedList myInstances;
    326
    327   /** The offset in the input List where the last matched annotation was*/
    328   static{
    329     myInstances = new LinkedList();
    330   }
    331
    332 } // FSMInstance
    333

| FSMInstance |