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