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