MultiPhaseTransducer.java
001 /*
002  *  MultiPhaseTransducer.java - transducer class
003  *
004  *  Copyright (c) 1995-2010, The University of Sheffield. See the file
005  *  COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006  *
007  *  This file is part of GATE (see http://gate.ac.uk/), and is free
008  *  software, licenced under the GNU Library General Public License,
009  *  Version 2, June 1991 (in the distribution as file licence.html,
010  *  and also available at http://gate.ac.uk/gate/licence.html).
011  *
012  *  Hamish Cunningham, 24/07/98
013  *
014  *  $Id: MultiPhaseTransducer.java 13280 2010-12-08 15:09:18Z markagreenwood $
015  */
016 
017 
018 package gate.jape;
019 
020 import java.util.ArrayList;
021 import java.util.Iterator;
022 
023 import gate.AnnotationSet;
024 import gate.Controller;
025 import gate.Document;
026 import gate.creole.ExecutionException;
027 import gate.creole.ExecutionInterruptedException;
028 import gate.creole.ontology.Ontology;
029 import gate.event.ProgressListener;
030 import gate.event.StatusListener;
031 import gate.util.Benchmark;
032 import gate.util.Err;
033 import gate.util.Strings;
034 
035 
036 /**
037   * Represents a complete CPSL grammar, with a phase name, options and
038   * rule set (accessible by name and by sequence).
039   * Implements a transduce method taking a Document as input.
040   * Constructs from String or File.
041   */
042 public class MultiPhaseTransducer extends Transducer
043 implements JapeConstants, java.io.Serializable
044 {
045   private static final long serialVersionUID = -1817675404943909246L;
046 
047   /** Debug flag */
048   private static final boolean DEBUG = false;
049 
050   /** Construction from name. */
051   public MultiPhaseTransducer(String name) {
052     this();
053     setName(name);
054   // constr from name
055 
056   /**
057    * Notifies this PR that it should stop its execution as soon as possible.
058    */
059   public synchronized void interrupt(){
060     interrupted = true;
061     Iterator phasesIter = phases.iterator();
062     while(phasesIter.hasNext()){
063       ((Transducer)phasesIter.next()).interrupt();
064     }
065   }
066 
067 
068   /** Anonymous construction */
069   public MultiPhaseTransducer() {
070     phases = new ArrayList();
071   // anon construction
072 
073   /** Set the name. */
074   public void setName(String name) { this.name = name; }
075 
076   /** The SinglePhaseTransducers that make up this one.
077     * Keyed by their phase names.
078     */
079   private ArrayList phases;
080 
081 
082   /**
083    * Sets the ontology used by this transducer;
084    @param ontology an {@link gate.creole.ontology.Ontology} value;
085    */
086   public void setOntology(Ontology ontology) {
087     super.setOntology(ontology);
088     Iterator phasesIter = phases.iterator();
089     while(phasesIter.hasNext()){
090       ((Transducer)phasesIter.next()).setOntology(ontology);
091     }
092   }
093 
094   /** Add phase. */
095   public void addPhase(String name, Transducer phase) {
096     //Debug.pr(this, "MPT: adding " + name + Debug.getNl());
097     phases.add(phase);
098   // addPhase
099 
100   /** Change the phase order to the one specified in a list of names. */
101   public void orderPhases(String[] phaseNames) {
102     Err.println("oops: MPT.orderPhases not done yet :-(");
103     /*
104     // for each phaseName
105     //   destructively get the phase and add to new array map
106     // errors: any phaseName not in phases,
107     HashMap newPhaseMap = new HashMap();
108     for(int i=0; i<phaseNames.length; i++) {
109       Transducer t = (Transducer) phases.remove(phaseNames[i]);
110       if(t == null) {
111         // ERROR
112       }
113       else {
114         newPhaseMap.add(t);
115       }
116     }
117     phases = newPhaseMap;
118     */
119   // orderPhases
120 
121 
122   /** Finish: replace dynamic data structures with Java arrays; called
123     * after parsing.
124     */
125   public void finish(){
126     for(Iterator i = phases.iterator(); i.hasNext())
127       ((Transduceri.next()).finish();
128   // finish
129 
130 
131   /** Transduce the document by running each phase in turn. */
132   public void transduce(Document doc, AnnotationSet input,
133                         AnnotationSet outputthrows JapeException,
134                                                      ExecutionException {
135     interrupted = false;
136     ProgressListener pListener = null;
137     StatusListener sListener = null;
138     pListener = new ProgressListener(){
139       public void processFinished(){
140         donePhases ++;
141         if(donePhases == phasesCntfireProcessFinished();
142       }
143 
144       public void progressChanged(int i){
145         int value = (donePhases * 100 + i)/phasesCnt;
146         fireProgressChanged(value);
147       }
148 
149       int phasesCnt = phases.size();
150       int donePhases = 0;
151     };
152 
153     sListener = new StatusListener(){
154       public void statusChanged(String text){
155         fireStatusChanged(text);
156       }
157     };
158 
159     for(Iterator i = phases.iterator(); i.hasNext()) {
160       Transducer t = (Transduceri.next();
161 
162       if(isInterrupted()) throw new ExecutionInterruptedException(
163         "The execution of the \"" + getName() +
164         "\" Jape transducer has been abruptly interrupted!");
165 
166       try {
167         fireStatusChanged("Transducing " + doc.getName() +
168                              " (Phase: " + t.getName() ")...");
169         String savedBenchmarkID = null;
170         String phaseBenchmarkID = null;
171         if(Benchmark.isBenchmarkingEnabled()) {
172           savedBenchmarkID = t.getBenchmarkId();
173           this.benchmarkFeatures.put(Benchmark.DOCUMENT_NAME_FEATURE, doc.getName());
174           phaseBenchmarkID = Benchmark.createBenchmarkId("phase__" + t.getName()this.getBenchmarkId());
175           t.setBenchmarkId(phaseBenchmarkID);
176         }
177         long startTime = Benchmark.startPoint();
178         t.addProgressListener(pListener);
179         t.addStatusListener(sListener);
180 
181         t.setActionContext(actionContext);
182         t.transduce(doc, input, output);
183         t.removeProgressListener(pListener);
184         t.removeStatusListener(sListener);
185         if(Benchmark.isBenchmarkingEnabled()) {
186           Benchmark.checkPoint(startTime, phaseBenchmarkID, this, benchmarkFeatures);
187           t.setBenchmarkId(savedBenchmarkID);
188         }
189         fireStatusChanged("");
190       catch(JapeException e) {
191         String location = "phase " + t.getName() ", document " + doc.getName();
192         e.setLocation(location);
193         throw e;
194       }
195     }
196 
197     cleanUp();
198   // transduce
199 
200   public void setEnableDebugging(boolean enableDebugging) {
201     this.enableDebugging = enableDebugging;
202     //propagate
203     for(int i = 0; i < phases.size(); i++){
204       ((Transducer)phases.get(i)).setEnableDebugging(enableDebugging);
205     }
206   }
207 
208 
209   /** Ask each phase to clean up (delete action class files, for e.g.). */
210   public void cleanUp() {
211 
212     for(Iterator i = phases.iterator(); i.hasNext())
213       ((Transduceri.next()).cleanUp();
214     
215     benchmarkFeatures.remove(Benchmark.DOCUMENT_NAME_FEATURE);
216 
217   // cleanUp
218 
219   /** Create a string representation of the object. */
220   public String toString() { return toString("")}
221 
222   /** Create a string representation of the object. */
223   public String toString(String pad) {
224     String newline = Strings.getNl();
225 
226     StringBuffer buf = new StringBuffer(
227       pad + "MPT: name(" + name + "); phases(" + newline + pad
228     );
229 
230     for(Iterator i = phases.iterator(); i.hasNext())
231       buf.append(
232         ((Transduceri.next()).toString(
233             Strings.addPadding(pad, INDENT_PADDING)
234         " "
235       );
236 
237     buf.append(newline + pad + ")." + newline);
238 
239     return buf.toString();
240   // toString
241 
242   //needed by FSM
243   public ArrayList getPhases(){ return phases; }
244   
245   /**
246    * Sets the phases
247    @param phases
248    */
249   public void setPhases(ArrayList phases) {
250     this.phases = phases;
251   }
252 
253   @Override
254   public void runControllerExecutionStartedBlock(
255     ActionContext ac, Controller c, Ontology othrows ExecutionException {
256     for(Iterator i = phases.iterator(); i.hasNext()) {
257       Transducer t = (Transduceri.next();
258       t.runControllerExecutionStartedBlock(ac, c, o);
259     }
260   }
261   @Override
262   public void runControllerExecutionFinishedBlock(
263     ActionContext ac, Controller c, Ontology othrows ExecutionException {
264     for(Iterator i = phases.iterator(); i.hasNext()) {
265       Transducer t = (Transduceri.next();
266       t.runControllerExecutionFinishedBlock(ac, c, o);
267     }
268   }
269   @Override
270   public void runControllerExecutionAbortedBlock(
271     ActionContext ac, Controller c, Throwable throwable, Ontology othrows ExecutionException {
272     for(Iterator i = phases.iterator(); i.hasNext()) {
273       Transducer t = (Transduceri.next();
274       t.runControllerExecutionAbortedBlock(ac, c,throwable, o);
275     }
276   }
277 
278 // class MultiPhaseTransducer
279 
280 
281 
282 // $Log$
283 // Revision 1.28  2005/10/07 16:06:47  nirajaswani
284 // Transducer Serialization added
285 //
286 // Revision 1.27  2005/01/11 13:51:36  ian
287 // Updating copyrights to 1998-2005 in preparation for v3.0
288 //
289 // Revision 1.26  2004/07/21 17:10:08  akshay
290 // Changed copyright from 1998-2001 to 1998-2004
291 //
292 // Revision 1.25  2004/03/25 13:01:13  valyt
293 // Imports optimisation throughout the Java sources
294 // (to get rid of annoying warnings in Eclipse)
295 //
296 // Revision 1.24  2003/11/14 12:45:47  valyt
297 // enableDebugging parameter
298 //
299 // Revision 1.23  2002/05/14 09:43:17  valyt
300 //
301 // Ontology Aware JAPE transducers
302 //
303 // Revision 1.22  2002/03/13 11:19:37  valyt
304 //
305 // bug fix: doc.getSourceURL() replaced by doc.getName()
306 //
307 // Revision 1.21  2002/02/26 13:27:12  valyt
308 //
309 // Error messages from the compiler
310 //
311 // Revision 1.20  2001/09/28 15:45:23  valyt
312 //
313 // All the PRs are now more or less interruptible
314 //
315 // THE STOP BUTTON shows its face when needed.
316 //
317 // Revision 1.19  2001/09/25 12:04:03  kalina
318 // I commented out temporarily the no events in batch mode code as it was
319 // not working completely correctly, so I want to reinstate it only after
320 // it's fully functional. All tests seems OK on a clean version (well, same
321 // mistakes as today due to the feature comparison stuff).
322 //
323 // Revision 1.18  2001/09/13 12:09:50  kalina
324 // Removed completely the use of jgl.objectspace.Array and such.
325 // Instead all sources now use the new Collections, typically ArrayList.
326 // I ran the tests and I ran some documents and compared with keys.
327 // JAPE seems to work well (that's where it all was). If there are problems
328 // maybe look at those new structures first.
329 //
330 // Revision 1.17  2001/09/12 15:24:44  kalina
331 // Made the batchMode flag in Main public. This is now checked before
332 // events are fired and listeners created. No bugs in tests or anywhere else
333 // yet. To disable events, set batchMode to true in your batch code. By default
334 // it is false, because some batch code e.g., MUSE, use events for progress
335 // indication. Not having events does give some small performance gains, but
336 // not much.
337 //
338 // Revision 1.16  2001/05/17 11:50:41  valyt
339 //
340 //   Factory now handles Runtime parameters as well as inittime ones.
341 //
342 //   There is a new rule application style Appelt-shortest
343 //
344 // Revision 1.15  2001/05/16 19:03:45  valyt
345 //
346 // Added a new option for jape in order to allow the use of the shortest match in appelt rules
347 //
348 // Revision 1.14  2001/04/30 16:56:32  valyt
349 //
350 //
351 // Unification of the NAME attribute implementation.
352 //
353 // Revision 1.13  2001/04/17 18:18:06  valyt
354 //
355 // events for jape & applications
356 //
357 // Revision 1.12  2001/03/06 20:11:14  valyt
358 //
359 // <b><em><strong>DOCUMENTATION</></></> for most of the GUI classes.
360 //
361 // Cleaned up some obsolete classes
362 //
363 // Revision 1.11  2001/01/21 20:51:31  valyt
364 // Added the DocumentEditor class and the necessary changes to the gate API
365 //
366 // Revision 1.10  2000/11/08 16:35:03  hamish
367 // formatting
368 //
369 // Revision 1.9  2000/10/26 10:45:30  oana
370 // Modified in the code style
371 //
372 // Revision 1.8  2000/10/18 13:26:47  hamish
373 // Factory.createResource now working, with a utility method that uses reflection (via java.beans.Introspector) to set properties on a resource from the
374 //     parameter list fed to createResource.
375 //     resources may now have both an interface and a class; they are indexed by interface type; the class is used to instantiate them
376 //     moved createResource from CR to Factory
377 //     removed Transients; use Factory instead
378 //
379 // Revision 1.7  2000/10/16 16:44:34  oana
380 // Changed the comment of DEBUG variable
381 //
382 // Revision 1.6  2000/10/10 15:36:36  oana
383 // Changed System.out in Out and System.err in Err;
384 // Added the DEBUG variable seted on false;
385 // Added in the header the licence;
386 //
387 // Revision 1.5  2000/07/12 14:19:19  valyt
388 // Testing CVS
389 //
390 // Revision 1.4  2000/07/04 14:37:39  valyt
391 // Added some support for Jape-ing in a different annotations et than the default one;
392 // Changed the L&F for the JapeGUI to the System default
393 //
394 // Revision 1.3  2000/07/03 21:00:59  valyt
395 // Added StatusBar and ProgressBar support for tokenisation & Jape transduction
396 // (it looks great :) )
397 //
398 // Revision 1.2  2000/04/14 18:02:46  valyt
399 // Added some gate.fsm classes
400 // added some accessor function in old jape classes
401 //
402 // Revision 1.1  2000/02/23 13:46:08  hamish
403 // added
404 //
405 // Revision 1.1.1.1  1999/02/03 16:23:02  hamish
406 // added gate2
407 //
408 // Revision 1.10  1998/11/01 21:21:39  hamish
409 // use Java arrays in transduction where possible
410 //
411 // Revision 1.9  1998/10/06 16:14:59  hamish
412 // phase ordering prob fixed; made phases an array
413 //
414 // Revision 1.8  1998/10/01 16:06:33  hamish
415 // new appelt transduction style, replacing buggy version
416 //
417 // Revision 1.7  1998/09/26 09:19:17  hamish
418 // added cloning of PE macros
419 //
420 // Revision 1.6  1998/09/18 13:35:59  hamish
421 // made Transducer a class
422 //
423 // Revision 1.5  1998/08/19 20:21:40  hamish
424 // new RHS assignment expression stuff added
425 //
426 // Revision 1.4  1998/08/12 15:39:39  hamish
427 // added padding toString methods
428 //
429 // Revision 1.3  1998/08/10 14:16:37  hamish
430 // fixed consumeblock bug and added batch.java
431 //
432 // Revision 1.2  1998/08/07 16:39:17  hamish
433 // parses, transduces. time for a break
434 //
435 // Revision 1.1  1998/08/07 16:18:45  hamish
436 // parser pretty complete, with backend link done