1   /*
2    *  Copyright (c) 1998-2005, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  Valentin Tablan, 01 Feb 2000
10   *
11   *  $Id: Transducer.java,v 1.33 2006/02/02 17:10:57 valyt Exp $
12   */
13  package gate.creole;
14  
15  import gate.Resource;
16  import gate.gui.MainFrame;
17  import gate.jape.Batch;
18  import gate.jape.JapeException;
19  import gate.util.Err;
20  import java.io.File;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.ObjectInputStream;
24  import java.io.ObjectOutputStream;
25  import java.util.ArrayList;
26  import java.util.List;
27  import javax.swing.JFileChooser;
28  import javax.swing.JOptionPane;
29  
30  /**
31   * A cascaded multi-phase transducer using the Jape language which is a variant
32   * of the CPSL language.
33   */
34  public class Transducer extends AbstractLanguageAnalyser
35                                                          implements
36                                                          gate.gui.ActionsPublisher {
37    public static final String TRANSD_DOCUMENT_PARAMETER_NAME = "document";
38  
39    public static final String TRANSD_INPUT_AS_PARAMETER_NAME = "inputASName";
40  
41    public static final String TRANSD_OUTPUT_AS_PARAMETER_NAME = "outputASName";
42  
43    public static final String TRANSD_ENCODING_PARAMETER_NAME = "encoding";
44  
45    public static final String TRANSD_GRAMMAR_URL_PARAMETER_NAME = "grammarURL";
46  
47    public static final String TRANSD_BINARY_GRAMMAR_URL_PARAMETER_NAME = "binaryGrammarURL";
48  
49    protected List actionList;
50  
51    /**
52     * Default constructor. Does nothing apart from calling the default
53     * constructor from the super class. The actual object initialisation is done
54     * via the {@link #init} method.
55     */
56    public Transducer() {
57      actionList = new ArrayList();
58      actionList.add(null);
59      actionList.add(new SerializeTransducerAction());
60    }
61  
62    /*
63     * private void writeObject(ObjectOutputStream oos) throws IOException {
64     * Out.prln("writing transducer"); oos.defaultWriteObject();
65     * Out.prln("finished writing transducer"); } // writeObject
66     */
67    /**
68     * This method is the one responsible for initialising the transducer. It
69     * assumes that all the needed parameters have been already set using the
70     * appropiate setXXX() methods.
71     * 
72     * @return a reference to <b>this</b>
73     */
74    public Resource init() throws ResourceInstantiationException {
75      try {
76        fireProgressChanged(0);
77        if(binaryGrammarURL != null) {
78          ObjectInputStream s = new ObjectInputStream(binaryGrammarURL
79                  .openStream());
80          batch = (gate.jape.Batch)s.readObject();
81        } else if(grammarURL != null) {
82          if(encoding != null) {
83            batch = new Batch(grammarURL, encoding, new InternalStatusListener());
84            if(enableDebugging != null) {
85              batch.setEnableDebugging(enableDebugging.booleanValue());
86            } else {
87              batch.setEnableDebugging(false);
88            }
89            batch.setOntology(ontology);
90          } else {
91            throw new ResourceInstantiationException("encoding is not set!");
92          }
93        } else {
94          throw new ResourceInstantiationException(
95                  "Neither grammarURL or binaryGrammarURL parameters are set!");
96        }
97      } catch(Exception e) {
98        throw new ResourceInstantiationException(e);
99      } finally {
100       fireProcessFinished();
101     }
102     batch.addProgressListener(new IntervalProgressListener(0, 100));
103     return this;
104   }
105 
106   /**
107    * Implementation of the run() method from {@link java.lang.Runnable}. This
108    * method is responsible for doing all the processing of the input document.
109    */
110   public void execute() throws ExecutionException {
111     interrupted = false;
112     if(document == null) throw new ExecutionException("No document provided!");
113     if(inputASName != null && inputASName.equals("")) inputASName = null;
114     if(outputASName != null && outputASName.equals("")) outputASName = null;
115     try {
116       batch.transduce(document, inputASName == null
117               ? document.getAnnotations()
118               : document.getAnnotations(inputASName), outputASName == null
119               ? document.getAnnotations()
120               : document.getAnnotations(outputASName));
121     } catch(JapeException je) {
122       throw new ExecutionException(je);
123     }
124   }
125 
126   /**
127    * Gets the list of actions that can be performed on this resource.
128    * 
129    * @return a List of Action objects (or null values)
130    */
131   public List getActions() {
132     List result = new ArrayList();
133     result.addAll(actionList);
134     return result;
135   }
136 
137   /**
138    * Saves the Jape Transuder to the binary file.
139    * 
140    * @author niraj
141    */
142   protected class SerializeTransducerAction extends javax.swing.AbstractAction {
143     public SerializeTransducerAction() {
144       super("Serialize Transducer");
145       putValue(SHORT_DESCRIPTION, "Serializes the Transducer as binary file");
146     }
147 
148     public void actionPerformed(java.awt.event.ActionEvent evt) {
149       Runnable runnable = new Runnable() {
150         public void run() {
151           JFileChooser fileChooser = MainFrame.getFileChooser();
152           fileChooser.setFileFilter(fileChooser.getAcceptAllFileFilter());
153           fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
154           fileChooser.setMultiSelectionEnabled(false);
155           if(fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
156             File file = fileChooser.getSelectedFile();
157             try {
158               MainFrame.lockGUI("Serializing JAPE Transducer...");
159               FileOutputStream out = new FileOutputStream(file);
160               ObjectOutputStream s = new ObjectOutputStream(out);
161               s.writeObject(batch);
162               s.flush();
163               s.close();
164               out.close();
165             } catch(IOException ioe) {
166               JOptionPane.showMessageDialog(null, "Error!\n" + ioe.toString(),
167                       "GATE", JOptionPane.ERROR_MESSAGE);
168               ioe.printStackTrace(Err.getPrintWriter());
169             } finally {
170               MainFrame.unlockGUI();
171             }
172           }
173         }
174       };
175       Thread thread = new Thread(runnable, "Transduer Serialization");
176       thread.setPriority(Thread.MIN_PRIORITY);
177       thread.start();
178     }
179   }
180 
181   /**
182    * Notifies all the PRs in this controller that they should stop their
183    * execution as soon as possible.
184    */
185   public synchronized void interrupt() {
186     interrupted = true;
187     batch.interrupt();
188   }
189 
190   /**
191    * Sets the grammar to be used for building this transducer.
192    * 
193    * @param newGrammarURL
194    *          an URL to a file containing a Jape grammar.
195    */
196   public void setGrammarURL(java.net.URL newGrammarURL) {
197     grammarURL = newGrammarURL;
198   }
199 
200   /**
201    * Gets the URL to the grammar used to build this transducer.
202    * 
203    * @return a {@link java.net.URL} pointing to the grammar file.
204    */
205   public java.net.URL getGrammarURL() {
206     return grammarURL;
207   }
208 
209   /**
210    * 
211    * Sets the encoding to be used for reding the input file(s) forming the Jape
212    * grammar. Note that if the input grammar is a multi-file one than the same
213    * encoding will be used for reding all the files. Multi file grammars with
214    * different encoding across the composing files are not supported!
215    * 
216    * @param newEncoding
217    *          a {link String} representing the encoding.
218    */
219   public void setEncoding(String newEncoding) {
220     encoding = newEncoding;
221   }
222 
223   /**
224    * Gets the encoding used for reding the grammar file(s).
225    */
226   public String getEncoding() {
227     return encoding;
228   }
229 
230   /**
231    * Sets the {@link gate.AnnotationSet} to be used as input for the transducer.
232    * 
233    * @param newInputASName
234    *          a {@link gate.AnnotationSet}
235    */
236   public void setInputASName(String newInputASName) {
237     inputASName = newInputASName;
238   }
239 
240   /**
241    * Gets the {@link gate.AnnotationSet} used as input by this transducer.
242    * 
243    * @return a {@link gate.AnnotationSet}
244    */
245   public String getInputASName() {
246     return inputASName;
247   }
248 
249   /**
250    * Sets the {@link gate.AnnotationSet} to be used as output by the transducer.
251    * 
252    * @param newOutputASName
253    *          a {@link gate.AnnotationSet}
254    */
255   public void setOutputASName(String newOutputASName) {
256     outputASName = newOutputASName;
257   }
258 
259   /**
260    * Gets the {@link gate.AnnotationSet} used as output by this transducer.
261    * 
262    * @return a {@link gate.AnnotationSet}
263    */
264   public String getOutputASName() {
265     return outputASName;
266   }
267 
268   public Boolean getEnableDebugging() {
269     return enableDebugging;
270   }
271 
272   public void setEnableDebugging(Boolean enableDebugging) {
273     this.enableDebugging = enableDebugging;
274   }
275 
276   /**
277    * The URL to the jape file used as grammar by this transducer.
278    */
279   protected java.net.URL grammarURL;
280 
281   /**
282    * The URL to the serialized jape file used as grammar by this transducer.
283    */
284   protected java.net.URL binaryGrammarURL;
285 
286   /**
287    * The actual JapeTransducer used for processing the document(s).
288    */
289   protected Batch batch;
290 
291   /**
292    * The encoding used for reding the grammar file(s).
293    */
294   protected String encoding;
295 
296   /**
297    * The {@link gate.AnnotationSet} used as input for the transducer.
298    */
299   protected String inputASName;
300 
301   /**
302    * The {@link gate.AnnotationSet} used as output by the transducer.
303    */
304   protected String outputASName;
305 
306   /**
307    * The ontology that will be available on the RHS of JAPE rules.
308    */
309   protected gate.creole.ontology.Ontology ontology;
310 
311   /**
312    * Gets the ontology used by this transducer.
313    * 
314    * @return an {@link gate.creole.ontology.Ontology} value.
315    */
316   public gate.creole.ontology.Ontology getOntology() {
317     return ontology;
318   }
319 
320   /**
321    * Sets the ontology used by this transducer.
322    * 
323    * @param ontology
324    *          an {@link gate.creole.ontology.Ontology} value.
325    */
326   public void setOntology(gate.creole.ontology.Ontology ontology) {
327     this.ontology = ontology;
328     //ontology is now a run-time param so we need to propagate it down to the 
329     //actual SPTs included in this transducer.
330     if(batch!= null) batch.setOntology(ontology);
331   }
332 
333   /**
334    * A switch used to activate the JAPE debugger.
335    */
336   protected Boolean enableDebugging;
337 
338 
339   public java.net.URL getBinaryGrammarURL() {
340     return binaryGrammarURL;
341   }
342 
343   public void setBinaryGrammarURL(java.net.URL binaryGrammarURL) {
344     this.binaryGrammarURL = binaryGrammarURL;
345   }
346 }