| RightHandSide.java |
1 /*
2 * RightHandSide.java - transducer class
3 *
4 * Copyright (c) 1998-2004, 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: RightHandSide.java,v 1.27 2004/07/21 17:10:08 akshay Exp $
14 */
15
16
17 package gate.jape;
18
19 import java.io.*;
20 import java.util.*;
21
22 import gate.*;
23 import gate.creole.ontology.Ontology;
24 import gate.util.Strings;
25
26
27 /**
28 * The RHS of a CPSL rule. The action part. Contains an inner class
29 * created from the code in the grammar RHS.
30 */
31 public class RightHandSide implements JapeConstants, java.io.Serializable
32 {
33 /** Debug flag */
34 private static final boolean DEBUG = false;
35
36 /** An instance of theActionClass. */
37 transient private Object theActionObject;
38
39 /** The string we use to create the action class. */
40 private StringBuffer actionClassString;
41
42 /** The bytes of the compiled action class. */
43 private byte[] actionClassBytes;
44
45 /** The name of the action class. */
46 private String actionClassName;
47
48 /** Package name for action classes. It's called a "dir name" because
49 * we used to dump the action classes to disk and compile them there.
50 */
51 static private String actionsDirName = "japeactionclasses";
52
53 /** The qualified name of the action class. */
54 private String actionClassQualifiedName;
55
56 /** Name of the .java file for the action class. */
57 private String actionClassJavaFileName;
58
59 /** Name of the .class file for the action class. */
60 private String actionClassClassFileName;
61
62 /** Cardinality of the action class set. Used for ensuring class name
63 * uniqueness.
64 */
65 private static int actionClassNumber = 0;
66
67 /** Allow setting of the initial action class number. Used for ensuring
68 * class name uniqueness when running more than one transducer. The
69 * long-term solution is to have separate class loaders for each
70 * transducer.
71 */
72 public static void setActionClassNumber(int n) { actionClassNumber = n; }
73
74 /** The set of block names.
75 * Used to ensure we only get their annotations once in the action class.
76 */
77 private HashSet blockNames;
78
79 /** Returns the string for the java code */
80 public String getActionClassString() { return actionClassString.toString(); }
81
82 public String getActionClassName() { return actionClassQualifiedName; }
83
84 /** The LHS of our rule, where we get bindings from. */
85 private LeftHandSide lhs;
86
87 /** A list of the files and directories we create. */
88 static private ArrayList tempFiles = new ArrayList();
89
90 /** Local fashion for newlines. */
91 private final String nl = Strings.getNl();
92
93 /** Debug flag. */
94 static final boolean debug = false;
95 private String phaseName;
96 private String ruleName;
97
98 /** Construction from the transducer name, rule name and the LHS. */
99 public RightHandSide(
100 String transducerName, String ruleName, LeftHandSide lhs
101 ) {
102 // debug = true;
103 this.lhs = lhs;
104 this.phaseName = transducerName;
105 this.ruleName = ruleName;
106 actionClassName = new String(
107 transducerName + ruleName + "ActionClass" + actionClassNumber++
108 );
109 blockNames = new HashSet();
110
111 // initialise the class action string
112 actionClassString = new StringBuffer(
113 "// " + actionClassName + nl +
114 "package " + actionsDirName + "; " + nl +
115 "import java.io.*;" + nl +
116 "import java.util.*;" + nl +
117 "import gate.*;" + nl +
118 "import gate.jape.*;" + nl +
119 "import gate.creole.ontology.Ontology;" + nl +
120 "import gate.annotation.*;" + nl +
121 "import gate.util.*;" + nl + nl +
122 "public class " + actionClassName + nl +
123 "implements java.io.Serializable, RhsAction { " + nl +
124 " public void doit(Document doc, java.util.Map bindings, " + nl +
125 " AnnotationSet annotations, " + nl +
126 " AnnotationSet inputAS, AnnotationSet outputAS, " + nl +
127 " Ontology ontology) {" + nl
128 );
129
130 // initialise various names
131 actionClassJavaFileName =
132 actionsDirName + File.separator +
133 actionClassName.replace('.', File.separatorChar) + ".java";
134 actionClassQualifiedName =
135 actionsDirName.
136 replace(File.separatorChar, '.').replace('/', '.').replace('\\', '.') +
137 "." + actionClassName;
138 actionClassClassFileName =
139 actionClassQualifiedName.replace('.', File.separatorChar) + ".class";
140 } // Construction from lhs
141
142 /** Add an anonymous block to the action class */
143 public void addBlock(String anonymousBlock) {
144 actionClassString.append(anonymousBlock);
145 actionClassString.append(nl);
146 } // addBlock(anon)
147
148 /** Add a named block to the action class */
149 public void addBlock(String name, String namedBlock) {
150 // is it really a named block?
151 // (dealing with null name cuts code in the parser...)
152 if(name == null) {
153 addBlock(namedBlock);
154 return;
155 }
156
157 if(blockNames.add(name)) // it wasn't already a member
158 actionClassString.append(
159 " AnnotationSet " + name + "Annots = (AnnotationSet)bindings.get(\""
160 + name + "\"); " + nl
161 );
162
163 actionClassString.append(
164 " if(" + name + "Annots != null && " + name +
165 "Annots.size() != 0) { " + nl + " " + namedBlock +
166 nl + " }" + nl
167 );
168 } // addBlock(name, block)
169
170 /** Create the action class and an instance of it. */
171 public void createActionClass() throws JapeException {
172 // terminate the class string
173 actionClassString.append(" }" + nl + "}" + nl);
174 // try {
175 // Javac.loadClass(actionClassString.toString(),
176 // actionClassJavaFileName);
177 // } catch(GateException e) {
178 // String nl = Strings.getNl();
179 // String actionWithNumbers =
180 // Strings.addLineNumbers(actionClassString.toString());
181 // throw new JapeException(
182 // "Couldn't create action class: " + nl + e + nl +
183 // "offending code was: " + nl + actionWithNumbers + nl
184 // );
185 // }
186 // instantiateActionClass();
187 } // createActionClass
188
189 /** Create an instance of the action class. */
190 public void instantiateActionClass() throws JapeException {
191
192 try {
193 theActionObject = Gate.getClassLoader().
194 loadClass(actionClassQualifiedName).
195 newInstance();
196 } catch(Exception e) {
197 throw new JapeException(
198 "couldn't create instance of action class " + actionClassName + ": "
199 + e.getMessage()
200 );
201 }
202 } // instantiateActionClass
203
204 /** Remove class files created for actions. */
205 public static void cleanUp() {
206 if(tempFiles.size() == 0) return;
207
208 // traverse the list in reverse order, coz any directories we
209 // created were done first
210 for(ListIterator i = tempFiles.listIterator(tempFiles.size()-1);
211 i.hasPrevious();
212 ) {
213 File tempFile = (File) i.previous();
214 tempFile.delete();
215 } // for each tempFile
216
217 tempFiles.clear();
218 } // cleanUp
219
220
221 /** Makes changes to the document, using LHS bindings. */
222 public void transduce(Document doc, java.util.Map bindings,
223 AnnotationSet inputAS, AnnotationSet outputAS,
224 Ontology ontology)
225 throws JapeException {
226 if(theActionObject == null) {
227 instantiateActionClass();
228 }
229
230 // run the action class
231 try {
232 ((RhsAction) theActionObject).doit(doc, bindings, outputAS,
233 inputAS, outputAS, ontology);
234
235 // if the action class throws an exception, re-throw it with a
236 // full description of the problem, inc. stack trace and the RHS
237 // action class code
238 } catch (Exception e) {
239 StringWriter stackTraceWriter = new StringWriter();
240 e.printStackTrace(new PrintWriter(stackTraceWriter));
241 throw new JapeException(
242 "Couldn't run RHS action: " + Strings.getNl() +
243 stackTraceWriter.getBuffer().toString() +
244 Strings.addLineNumbers(actionClassString.toString())
245 );
246 }
247 } // transduce
248
249 /** Create a string representation of the object. */
250 public String toString() { return toString(""); }
251
252 /** Create a string representation of the object. */
253 public String toString(String pad) {
254 String nl = Strings.getNl();
255 StringBuffer buf = new StringBuffer(
256 pad + "RHS: actionClassName(" + actionClassName + "); "
257 );
258 //buf.append("actionClassString(" + nl + actionClassString + nl);
259 buf.append(
260 "actionClassClassFileName(" + nl + actionClassClassFileName + nl
261 );
262 buf.append("actionClassJavaFileName(" + nl + actionClassJavaFileName + nl);
263 buf.append(
264 "actionClassQualifiedName(" + nl + actionClassQualifiedName + nl
265 );
266
267 buf.append("blockNames(" + blockNames.toString() + "); ");
268
269 buf.append(nl + pad + ") RHS." + nl);
270
271 return buf.toString();
272 } // toString
273
274 /** Create a string representation of the object. */
275 public String shortDesc() {
276 String res = "" + actionClassName;
277 return res;
278 }
279 public void setPhaseName(String phaseName) {
280 this.phaseName = phaseName;
281 }
282 public String getPhaseName() {
283 return phaseName;
284 }
285 public void setRuleName(String ruleName) {
286 this.ruleName = ruleName;
287 }
288 public String getRuleName() {
289 return ruleName;
290 } // toString
291
292 } // class RightHandSide
293
294
295 // $Log: RightHandSide.java,v $
296 // Revision 1.27 2004/07/21 17:10:08 akshay
297 // Changed copyright from 1998-2001 to 1998-2004
298 //
299 // Revision 1.26 2004/03/25 13:01:14 valyt
300 // Imports optimisation throughout the Java sources
301 // (to get rid of annoying warnings in Eclipse)
302 //
303 // Revision 1.25 2002/05/14 09:43:17 valyt
304 //
305 // Ontology Aware JAPE transducers
306 //
307 // Revision 1.24 2002/02/27 15:11:16 valyt
308 //
309 // bug 00011:
310 // Jape access to InputAS
311 //
312 // Revision 1.23 2002/02/26 13:27:12 valyt
313 //
314 // Error messages from the compiler
315 //
316 // Revision 1.22 2002/02/26 10:30:07 valyt
317 //
318 // new compile solution
319 //
320 // Revision 1.21 2002/02/12 11:39:03 valyt
321 //
322 // removed sate and status members for Jape generated classes
323 //
324 // Revision 1.20 2002/02/04 13:59:04 hamish
325 // added status and state members to RhsAction
326 //
327 // Revision 1.19 2001/11/16 13:03:35 hamish
328 // moved line numbers method to Strings
329 //
330 // Revision 1.18 2001/11/16 10:29:45 hamish
331 // JAPE RHS compiler errors now include the RHS code; test added
332 //
333 // Revision 1.17 2001/11/15 14:05:09 hamish
334 // better error messages from JAPE RHS problems
335 //
336 // Revision 1.16 2001/11/01 15:49:09 valyt
337 //
338 // DEBUG mode for Japes
339 //
340 // Revision 1.15 2001/09/13 12:09:50 kalina
341 // Removed completely the use of jgl.objectspace.Array and such.
342 // Instead all sources now use the new Collections, typically ArrayList.
343 // I ran the tests and I ran some documents and compared with keys.
344 // JAPE seems to work well (that's where it all was). If there are problems
345 // maybe look at those new structures first.
346 //
347 // Revision 1.14 2000/11/08 16:35:03 hamish
348 // formatting
349 //
350 // Revision 1.13 2000/10/26 10:45:30 oana
351 // Modified in the code style
352 //
353 // Revision 1.12 2000/10/16 16:44:34 oana
354 // Changed the comment of DEBUG variable
355 //
356 // Revision 1.11 2000/10/10 15:36:36 oana
357 // Changed System.out in Out and System.err in Err;
358 // Added the DEBUG variable seted on false;
359 // Added in the header the licence;
360 //
361 // Revision 1.10 2000/07/04 14:37:39 valyt
362 // Added some support for Jape-ing in a different annotations et than the default one;
363 // Changed the L&F for the JapeGUI to the System default
364 //
365 // Revision 1.9 2000/06/12 13:33:27 hamish
366 // removed japeactionclasse create code (static init block
367 //
368 // Revision 1.8 2000/05/16 10:38:25 hamish
369 // removed printout
370 //
371 // Revision 1.7 2000/05/16 10:30:33 hamish
372 // uses new gate.util.Jdk compiler
373 //
374 // Revision 1.6 2000/05/05 12:51:12 valyt
375 // Got rid of deprecation warnings
376 //
377 // Revision 1.5 2000/05/05 10:14:09 hamish
378 // added more to toString
379 //
380 // Revision 1.4 2000/05/02 16:54:47 hamish
381 // porting to new annotation API
382 //
383 // Revision 1.3 2000/04/20 13:26:42 valyt
384 // Added the graph_drawing library.
385 // Creating of the NFSM and DFSM now works.
386 //
387 // Revision 1.2 2000/02/24 17:28:48 hamish
388 // more porting to new API
389 //
390 // Revision 1.1 2000/02/23 13:46:11 hamish
391 // added
392 //
393 // Revision 1.1.1.1 1999/02/03 16:23:02 hamish
394 // added gate2
395 //
396 // Revision 1.21 1998/11/13 17:25:10 hamish
397 // stop it using sun.tools... when in 1.2
398 //
399 // Revision 1.20 1998/10/30 15:31:07 kalina
400 // Made small changes to make compile under 1.2 and 1.1.x
401 //
402 // Revision 1.19 1998/10/29 12:17:12 hamish
403 // use reflection when using sun compiler classes, so can compile without them
404 //
405 // Revision 1.18 1998/10/01 16:06:36 hamish
406 // new appelt transduction style, replacing buggy version
407 //
408 // Revision 1.17 1998/09/18 16:54:17 hamish
409 // save/restore works except for attribute seq
410 //
411 // Revision 1.16 1998/09/18 13:35:44 hamish
412 // refactored to split up createActionClass
413 //
414 // Revision 1.15 1998/09/18 12:15:40 hamish
415 // bugs fixed: anon block null ptr; no error for some non-existant labelled blocks
416 //
417 // Revision 1.14 1998/08/19 20:21:41 hamish
418 // new RHS assignment expression stuff added
419 //
420 // Revision 1.13 1998/08/17 10:43:29 hamish
421 // action classes have unique names so can be reloaded
422 //
423 // Revision 1.12 1998/08/12 15:39:42 hamish
424 // added padding toString methods
425 //
426 // Revision 1.11 1998/08/10 14:16:38 hamish
427 // fixed consumeblock bug and added batch.java
428 //
429 // Revision 1.10 1998/08/07 12:01:46 hamish
430 // parser works; adding link to backend
431 //
432 // Revision 1.9 1998/08/05 21:58:07 hamish
433 // backend works on simple test
434 //
435 // Revision 1.8 1998/08/04 12:42:56 hamish
436 // fixed annots null check bug
437 //
438 // Revision 1.7 1998/08/03 21:44:57 hamish
439 // moved parser classes to gate.jape.parser
440 //
441 // Revision 1.6 1998/08/03 19:51:26 hamish
442 // rollback added
443 //
444 // Revision 1.5 1998/07/31 16:50:18 hamish
445 // RHS compilation works; it runs - and falls over...
446 //
447 // Revision 1.4 1998/07/31 13:12:25 hamish
448 // done RHS stuff, not tested
449 //
450 // Revision 1.3 1998/07/30 11:05:24 hamish
451 // more jape
452 //
453 // Revision 1.2 1998/07/29 11:07:10 hamish
454 // first compiling version
455 //
456 // Revision 1.1.1.1 1998/07/28 16:37:46 hamish
457 // gate2 lives
458