1   /*
2    *  Rule.java - transducer class
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   *  Hamish Cunningham, 24/07/98
12   *
13   *  $Id: Rule.java,v 1.13 2001/09/13 12:09:50 kalina Exp $
14   */
15  
16  
17  package gate.jape;
18  
19  import java.util.*;
20  import gate.annotation.*;
21  import gate.event.*;
22  import gate.util.*;
23  import gate.*;
24  
25  /**
26    * A CPSL rule. Has an LHS, RHS and a name, and a priority.
27    */
28  public class Rule extends Transducer
29  implements JapeConstants, java.io.Serializable
30  {
31    /** Debug flag */
32    private static final boolean DEBUG = false;
33  
34    /** Construction */
35    public Rule(
36      String name, int position, int priority,
37      LeftHandSide lhs, RightHandSide rhs
38    ) {
39      this.name = name;
40      this.position = position;
41      this.priority = priority;
42      this.lhs = lhs;
43      this.rhs = rhs;
44    } // Construction
45  
46    /** The LHS or pattern of the rule. */
47    private LeftHandSide lhs;
48  
49    /** The RHS or action of the rule. */
50    private RightHandSide rhs;
51  
52    /** The priority of the rule. */
53    private int priority;
54  
55    /** Get the rule priority. */
56    public int getPriority() { return priority; }
57  
58    /** The rule's position in sequence (e.g. order in file). */
59    private int position;
60  
61    /** Get the rule's position in sequence (e.g. order in file). */
62    public int getPosition() { return position; }
63  
64    /** If we're pending (have matched), get the position we want to fire in,
65      * else -1.
66      */
67    public int pending() {
68      return pendingPosition;
69    } // pending
70  
71    /** If we matched but didn't fire yet, this is our pending position. */
72    private int pendingPosition = -1;
73  
74    /** Flag for end of document during getNextMatch. */
75    private boolean weFinished = false;
76  
77    /** Have we hit the end of the document without matching? */
78    public boolean finished() {
79      return weFinished;
80    } // finished
81  
82    /** Finish: replace dynamic data structures with Java arrays; called
83      * after parsing. WARNING:
84      * bad choice of names: this is not related to the weFinished
85      * member or the finished method!
86      */
87    public void finish() {
88      lhs.finish();
89    } // finish
90  
91    /** If another match at or beyond <CODE>position</CODE> is possible return
92      * the position we want to fire in, else -1.
93      */
94    public int getNextMatch(Document doc, int position, int end) {
95      MutableInteger newPosition = new MutableInteger();
96      newPosition.value = position;
97      while(position < end) {
98  
99        if(matches(doc, position, newPosition)) {
100         pendingPosition = getStartPosition();
101         return pendingPosition;
102       }
103       position = Math.max(position + 1, newPosition.value);
104 
105     } // while position not final
106 
107     weFinished = true;
108     return -1;
109   } // getNextMatch
110 
111   /** Return the ending position of a match. This is the rightmost span
112     * end of the matched annotations.
113     */
114   public int getEndPosition() {
115     return lhs.getMatchedAnnots().lastNode().getOffset().intValue();
116   }
117 
118   /** Return the starting position of a match. This is the leftmost span
119     * start of the matched annotations.
120     */
121   public int getStartPosition() {
122     return lhs.getMatchedAnnots().firstNode().getOffset().intValue();
123   }
124 
125   /** Does this element match the document at this position? */
126   public boolean matches(
127     Document doc, int position, MutableInteger newPosition
128   ) {
129     if(DEBUG) Out.println("trying rule " + name + " at " + position);
130     return lhs.matches(doc, position, newPosition);
131   } // matches
132 
133   /** Apply the RHS of this rule (LHS must have been matched first). */
134   public void transduce(Document doc, AnnotationSet inputAS,
135                         AnnotationSet outputAS) throws JapeException {
136     // the righthand side does the transduction, using bindings from lhs */
137     if(DEBUG) Out.println("applying rule " + name);
138 //    rhs.transduce(doc);
139     /*Debug.pr(
140       this, "Rule.transduce: annotations after transduction: " +
141       doc.selectAnnotations("Name", new FeatureMap()).toString() +
142       Debug.getNl()
143     );*/
144 
145     // clear the caches of matched annotations in the LHS
146     reset();
147     //Debug.pr(this, "LHS after reset: " + lhs.toString());
148 
149   } // transduce
150 
151   /** Clear away the results of a match. */
152   public void reset() {
153      if(weFinished) // no annotations cached
154        weFinished = false;
155      else
156        lhs.reset();
157      pendingPosition = -1;
158   }
159 
160   /** For debugging. */
161   // public String getName() { return name; }
162 
163   /** Clean up (delete action class files, for e.g.). */
164   public void cleanUp() {
165     rhs.cleanUp();
166   } // cleanUp
167 
168 
169   /** Create a string representation of the object. */
170   public String toString() { return toString(""); }
171 
172   /** Create a string representation of the object. */
173   public String toString(String pad) {
174     String newline = Strings.getNl();
175     String newPad = Strings.addPadding(pad, INDENT_PADDING);
176 
177     StringBuffer buf = new StringBuffer(
178       pad + "Rule: name(" + name + "); position(" + position + "); priority(" +
179       priority + "); pendingPosition(" + pendingPosition + "); " +
180       "weFinished(" + weFinished + "); lhs(" + newline +
181       lhs.toString(newPad) + newline + pad + "); rhs(" + newline +
182       rhs.toString(newPad) + newline + pad + ");"
183     );
184 
185     buf.append(newline + pad + ") Rule." + newline);
186 
187     return buf.toString();
188   } // toString
189 
190   //needed by FSM
191   public LeftHandSide getLHS(){
192     return lhs;
193   }
194   public RightHandSide getRHS(){
195     return rhs;
196   }
197 
198   //StatusReporter VOID Implementation
199   public void addStatusListener(StatusListener listener){}
200   public void removeStatusListener(StatusListener listener){}
201 
202   //ProcessProgressReporter VOID implementation
203   public void addProcessProgressListener(ProgressListener listener){}
204   public void removeProcessProgressListener(ProgressListener listener){}
205   //ProcessProgressReporter implementation ends here
206 
207 } // class Rule
208 
209 
210 // $Log: Rule.java,v $
211 // Revision 1.13  2001/09/13 12:09:50  kalina
212 // Removed completely the use of jgl.objectspace.Array and such.
213 // Instead all sources now use the new Collections, typically ArrayList.
214 // I ran the tests and I ran some documents and compared with keys.
215 // JAPE seems to work well (that's where it all was). If there are problems
216 // maybe look at those new structures first.
217 //
218 // Revision 1.12  2001/03/06 20:11:14  valyt
219 //
220 // <b><em><strong>DOCUMENTATION</></></> for most of the GUI classes.
221 //
222 // Cleaned up some obsolete classes
223 //
224 // Revision 1.11  2001/02/20 12:25:49  valyt
225 //
226 // Fixed the Jpae priorities bug
227 //
228 // Revision 1.10  2001/01/21 20:51:31  valyt
229 // Added the DocumentEditor class and the necessary changes to the gate API
230 //
231 // Revision 1.9  2000/11/08 16:35:03  hamish
232 // formatting
233 //
234 // Revision 1.8  2000/10/26 10:45:31  oana
235 // Modified in the code style
236 //
237 // Revision 1.7  2000/10/16 16:44:34  oana
238 // Changed the comment of DEBUG variable
239 //
240 // Revision 1.6  2000/10/10 15:36:37  oana
241 // Changed System.out in Out and System.err in Err;
242 // Added the DEBUG variable seted on false;
243 // Added in the header the licence;
244 //
245 // Revision 1.5  2000/07/04 14:37:39  valyt
246 // Added some support for Jape-ing in a different annotations et than the default one;
247 // Changed the L&F for the JapeGUI to the System default
248 //
249 // Revision 1.4  2000/07/03 21:00:59  valyt
250 // Added StatusBar and ProgressBar support for tokenisation & Jape transduction
251 // (it looks great :) )
252 //
253 // Revision 1.3  2000/05/05 12:51:12  valyt
254 // Got rid of deprecation warnings
255 //
256 // Revision 1.2  2000/04/14 18:02:46  valyt
257 // Added some gate.fsm classes
258 // added some accessor function in old jape classes
259 //
260 // Revision 1.1  2000/02/23 13:46:11  hamish
261 // added
262 //
263 // Revision 1.1.1.1  1999/02/03 16:23:02  hamish
264 // added gate2
265 //
266 // Revision 1.16  1998/11/01 21:21:40  hamish
267 // use Java arrays in transduction where possible
268 //
269 // Revision 1.15  1998/10/30 14:06:46  hamish
270 // added getTransducer
271 //
272 // Revision 1.14  1998/10/29 12:16:13  hamish
273 // changed reset to not do lhs if weFinished  - coz
274 // there should be no state cached if the last try failed
275 //
276 // Revision 1.13  1998/10/01 16:06:37  hamish
277 // new appelt transduction style, replacing buggy version
278 //
279 // Revision 1.12  1998/09/18 13:36:00  hamish
280 // made Transducer a class
281 //
282 // Revision 1.11  1998/08/19 20:21:43  hamish
283 // new RHS assignment expression stuff added
284 //
285 // Revision 1.10  1998/08/12 19:05:48  hamish
286 // fixed multi-part CG bug; set reset to real reset and fixed multi-doc bug
287 //
288 // Revision 1.9  1998/08/12 15:39:43  hamish
289 // added padding toString methods
290 //
291 // Revision 1.8  1998/08/10 14:16:39  hamish
292 // fixed consumeblock bug and added batch.java
293 //
294 // Revision 1.7  1998/08/03 21:44:58  hamish
295 // moved parser classes to gate.jape.parser
296 //
297 // Revision 1.6  1998/08/03 19:51:27  hamish
298 // rollback added
299 //
300 // Revision 1.5  1998/07/31 16:50:19  mks
301 // RHS compilation works; it runs - and falls over...
302 //
303 // Revision 1.4  1998/07/31 13:12:27  mks
304 // done RHS stuff, not tested
305 //
306 // Revision 1.3  1998/07/30 11:05:25  mks
307 // more jape
308 //
309 // Revision 1.2  1998/07/29 11:07:11  hamish
310 // first compiling version
311 //
312 // Revision 1.1.1.1  1998/07/28 16:37:46  hamish
313 // gate2 lives
314