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