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