1   /*
2    *  MultiPhaseTransducer.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: MultiPhaseTransducer.java,v 1.20 2001/09/28 15:45:23 valyt Exp $
14   */
15  
16  
17  package gate.jape;
18  
19  import java.util.*;
20  
21  
22  import gate.annotation.*;
23  import gate.event.*;
24  import gate.util.*;
25  import gate.creole.*;
26  import gate.*;
27  
28  
29  /**
30    * Represents a complete CPSL grammar, with a phase name, options and
31    * rule set (accessible by name and by sequence).
32    * Implements a transduce method taking a Document as input.
33    * Constructs from String or File.
34    */
35  public class MultiPhaseTransducer extends Transducer
36  implements JapeConstants, java.io.Serializable
37  {
38    /** Debug flag */
39    private static final boolean DEBUG = false;
40  
41    /** Construction from name. */
42    public MultiPhaseTransducer(String name) {
43      this();
44      setName(name);
45    } // constr from name
46  
47    /**
48     * Notifies this PR that it should stop its execution as soon as possible.
49     */
50    public synchronized void interrupt(){
51      interrupted = true;
52      Iterator phasesIter = phases.iterator();
53      while(phasesIter.hasNext()){
54        ((Transducer)phasesIter.next()).interrupt();
55      }
56    }
57  
58  
59    /** Anonymous construction */
60    public MultiPhaseTransducer() {
61      phases = new ArrayList();
62    } // anon construction
63  
64    /** Set the name. */
65    public void setName(String name) { this.name = name; }
66  
67    /** The SinglePhaseTransducers that make up this one.
68      * Keyed by their phase names.
69      */
70    private ArrayList phases;
71  
72  
73    /** Add phase. */
74    public void addPhase(String name, Transducer phase) {
75      //Debug.pr(this, "MPT: adding " + name + Debug.getNl());
76      phases.add(phase);
77    } // addPhase
78  
79    /** Change the phase order to the one specified in a list of names. */
80    public void orderPhases(String[] phaseNames) {
81      Err.println("oops: MPT.orderPhases not done yet :-(");
82      /*
83      // for each phaseName
84      //   destructively get the phase and add to new array map
85      // errors: any phaseName not in phases,
86      HashMap newPhaseMap = new HashMap();
87      for(int i=0; i<phaseNames.length; i++) {
88        Transducer t = (Transducer) phases.remove(phaseNames[i]);
89        if(t == null) {
90          // ERROR
91        }
92        else {
93          newPhaseMap.add(t);
94        }
95      }
96      phases = newPhaseMap;
97      */
98    } // orderPhases
99  
100 
101   /** Finish: replace dynamic data structures with Java arrays; called
102     * after parsing.
103     */
104   public void finish() {
105     for(Iterator i = phases.iterator(); i.hasNext(); )
106       ((Transducer) i.next()).finish();
107   } // finish
108 
109 
110   /** Transduce the document by running each phase in turn. */
111   public void transduce(Document doc, AnnotationSet input,
112                         AnnotationSet output) throws JapeException,
113                                                      ExecutionException {
114 
115     interrupted = false;
116     ProgressListener pListener = null;
117     StatusListener sListener = null;
118     pListener = new ProgressListener(){
119       public void processFinished(){
120         donePhases ++;
121         if(donePhases == phasesCnt) fireProcessFinished();
122       }
123 
124       public void progressChanged(int i){
125         int value = (donePhases * 100 + i)/phasesCnt;
126         fireProgressChanged(value);
127       }
128 
129       int phasesCnt = phases.size();
130       int donePhases = 0;
131     };
132 
133     sListener = new StatusListener(){
134       public void statusChanged(String text){
135         fireStatusChanged(text);
136       }
137     };
138 
139     for(Iterator i = phases.iterator(); i.hasNext(); ) {
140       Transducer t = (Transducer) i.next();
141 
142       if(isInterrupted()) throw new ExecutionInterruptedException(
143         "The execution of the \"" + getName() +
144         "\" Jape transducer has been abruptly interrupted!");
145 
146       try {
147         fireStatusChanged("Transducing " + doc.getName() +
148                              " (Phase: " + t.getName() + ")...");
149         t.addProgressListener(pListener);
150         t.addStatusListener(sListener);
151 
152         t.transduce(doc, input, output);
153         t.removeProgressListener(pListener);
154         t.removeStatusListener(sListener);
155         fireStatusChanged("");
156       } catch(JapeException e) {
157         String errorMessage = new String(
158           "Error transducing document " + doc.getSourceUrl() +
159           ", phase " + t.getName() + Strings.getNl() + e.getMessage()
160         );
161         throw(new JapeException(errorMessage));
162       }
163     }
164 
165     cleanUp();
166   } // transduce
167 
168   /** Ask each phase to clean up (delete action class files, for e.g.). */
169   public void cleanUp() {
170 
171     for(Iterator i = phases.iterator(); i.hasNext(); )
172       ((Transducer) i.next()).cleanUp();
173 
174   } // cleanUp
175 
176   /** Create a string representation of the object. */
177   public String toString() { return toString(""); }
178 
179   /** Create a string representation of the object. */
180   public String toString(String pad) {
181     String newline = Strings.getNl();
182 
183     StringBuffer buf = new StringBuffer(
184       pad + "MPT: name(" + name + "); phases(" + newline + pad
185     );
186 
187     for(Iterator i = phases.iterator(); i.hasNext(); )
188       buf.append(
189         ((Transducer) i.next()).toString(
190             Strings.addPadding(pad, INDENT_PADDING)
191         ) + " "
192       );
193 
194     buf.append(newline + pad + ")." + newline);
195 
196     return buf.toString();
197   } // toString
198 
199   //needed by FSM
200   public ArrayList getPhases(){ return phases; }
201 
202 } // class MultiPhaseTransducer
203 
204 
205 
206 // $Log: MultiPhaseTransducer.java,v $
207 // Revision 1.20  2001/09/28 15:45:23  valyt
208 //
209 // All the PRs are now more or less interruptible
210 //
211 // THE STOP BUTTON shows its face when needed.
212 //
213 // Revision 1.19  2001/09/25 12:04:03  kalina
214 // I commented out temporarily the no events in batch mode code as it was
215 // not working completely correctly, so I want to reinstate it only after
216 // it's fully functional. All tests seems OK on a clean version (well, same
217 // mistakes as today due to the feature comparison stuff).
218 //
219 // Revision 1.18  2001/09/13 12:09:50  kalina
220 // Removed completely the use of jgl.objectspace.Array and such.
221 // Instead all sources now use the new Collections, typically ArrayList.
222 // I ran the tests and I ran some documents and compared with keys.
223 // JAPE seems to work well (that's where it all was). If there are problems
224 // maybe look at those new structures first.
225 //
226 // Revision 1.17  2001/09/12 15:24:44  kalina
227 // Made the batchMode flag in Main public. This is now checked before
228 // events are fired and listeners created. No bugs in tests or anywhere else
229 // yet. To disable events, set batchMode to true in your batch code. By default
230 // it is false, because some batch code e.g., MUSE, use events for progress
231 // indication. Not having events does give some small performance gains, but
232 // not much.
233 //
234 // Revision 1.16  2001/05/17 11:50:41  valyt
235 //
236 //  Factory now handles Runtime parameters as well as inittime ones.
237 //
238 //  There is a new rule application style Appelt-shortest
239 //
240 // Revision 1.15  2001/05/16 19:03:45  valyt
241 //
242 // Added a new option for jape in order to allow the use of the shortest match in appelt rules
243 //
244 // Revision 1.14  2001/04/30 16:56:32  valyt
245 //
246 //
247 // Unification of the NAME attribute implementation.
248 //
249 // Revision 1.13  2001/04/17 18:18:06  valyt
250 //
251 // events for jape & applications
252 //
253 // Revision 1.12  2001/03/06 20:11:14  valyt
254 //
255 // <b><em><strong>DOCUMENTATION</></></> for most of the GUI classes.
256 //
257 // Cleaned up some obsolete classes
258 //
259 // Revision 1.11  2001/01/21 20:51:31  valyt
260 // Added the DocumentEditor class and the necessary changes to the gate API
261 //
262 // Revision 1.10  2000/11/08 16:35:03  hamish
263 // formatting
264 //
265 // Revision 1.9  2000/10/26 10:45:30  oana
266 // Modified in the code style
267 //
268 // Revision 1.8  2000/10/18 13:26:47  hamish
269 // Factory.createResource now working, with a utility method that uses reflection (via java.beans.Introspector) to set properties on a resource from the
270 //     parameter list fed to createResource.
271 //     resources may now have both an interface and a class; they are indexed by interface type; the class is used to instantiate them
272 //     moved createResource from CR to Factory
273 //     removed Transients; use Factory instead
274 //
275 // Revision 1.7  2000/10/16 16:44:34  oana
276 // Changed the comment of DEBUG variable
277 //
278 // Revision 1.6  2000/10/10 15:36:36  oana
279 // Changed System.out in Out and System.err in Err;
280 // Added the DEBUG variable seted on false;
281 // Added in the header the licence;
282 //
283 // Revision 1.5  2000/07/12 14:19:19  valyt
284 // Testing CVS
285 //
286 // Revision 1.4  2000/07/04 14:37:39  valyt
287 // Added some support for Jape-ing in a different annotations et than the default one;
288 // Changed the L&F for the JapeGUI to the System default
289 //
290 // Revision 1.3  2000/07/03 21:00:59  valyt
291 // Added StatusBar and ProgressBar support for tokenisation & Jape transduction
292 // (it looks great :) )
293 //
294 // Revision 1.2  2000/04/14 18:02:46  valyt
295 // Added some gate.fsm classes
296 // added some accessor function in old jape classes
297 //
298 // Revision 1.1  2000/02/23 13:46:08  hamish
299 // added
300 //
301 // Revision 1.1.1.1  1999/02/03 16:23:02  hamish
302 // added gate2
303 //
304 // Revision 1.10  1998/11/01 21:21:39  hamish
305 // use Java arrays in transduction where possible
306 //
307 // Revision 1.9  1998/10/06 16:14:59  hamish
308 // phase ordering prob fixed; made phases an array
309 //
310 // Revision 1.8  1998/10/01 16:06:33  hamish
311 // new appelt transduction style, replacing buggy version
312 //
313 // Revision 1.7  1998/09/26 09:19:17  hamish
314 // added cloning of PE macros
315 //
316 // Revision 1.6  1998/09/18 13:35:59  hamish
317 // made Transducer a class
318 //
319 // Revision 1.5  1998/08/19 20:21:40  hamish
320 // new RHS assignment expression stuff added
321 //
322 // Revision 1.4  1998/08/12 15:39:39  hamish
323 // added padding toString methods
324 //
325 // Revision 1.3  1998/08/10 14:16:37  hamish
326 // fixed consumeblock bug and added batch.java
327 //
328 // Revision 1.2  1998/08/07 16:39:17  hamish
329 // parses, transduces. time for a break
330 //
331 // Revision 1.1  1998/08/07 16:18:45  hamish
332 // parser pretty complete, with backend link done
333