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