1   /*
2    *  TestPR.java
3    *
4    *  Copyright (c) 1998-2001, 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   *  Oana Hamza,
12   *
13   *  $Id: TestPR.java,v 1.29 2002/03/06 17:15:40 kalina Exp $
14   */
15  
16  package gate.creole;
17  
18  import java.util.*;
19  import java.io.*;
20  import java.net.*;
21  import junit.framework.*;
22  import gnu.regexp.*;
23  
24  import gate.*;
25  import gate.util.*;
26  import gate.corpora.TestDocument;
27  import gate.creole.tokeniser.*;
28  import gate.creole.gazetteer.*;
29  import gate.creole.splitter.*;
30  import gate.creole.orthomatcher.*;
31  import gate.persist.*;
32  import gate.annotation.*;
33  import gate.creole.ANNIEConstants;
34  
35  /** Test the PRs on three documents */
36  public class TestPR extends TestCase
37  {
38    /** Debug flag */
39    private static final boolean DEBUG = false;
40  
41    protected static Document doc1;
42    protected static Document doc2;
43    protected static Document doc3;
44  
45    protected static List annotationTypes = new ArrayList(10);
46  
47    /** Construction */
48    public TestPR(String name) { super(name); }
49  
50    /** Fixture set up */
51    public void setUp() throws Exception {
52      //get 3 documents
53      if (doc1 == null)
54        doc1 = Factory.newDocument(
55          new URL(TestDocument.getTestServerName() +
56          "tests/ft-bt-03-aug-2001.html")
57        );
58  
59      if (doc2 == null)
60        doc2 = Factory.newDocument(
61          new URL(TestDocument.getTestServerName() +
62            "tests/gu-Am-Brit-4-aug-2001.html")
63        );
64  
65      if (doc3 == null)
66        doc3 = Factory.newDocument(
67          new URL(TestDocument.getTestServerName() +
68            "tests/in-outlook-09-aug-2001.html")
69        );
70  
71      annotationTypes.add(ANNIEConstants.SENTENCE_ANNOTATION_TYPE);
72      annotationTypes.add(ANNIEConstants.ORGANIZATION_ANNOTATION_TYPE);
73      annotationTypes.add(ANNIEConstants.LOCATION_ANNOTATION_TYPE);
74      annotationTypes.add(ANNIEConstants.PERSON_ANNOTATION_TYPE);
75      annotationTypes.add(ANNIEConstants.DATE_ANNOTATION_TYPE);
76      annotationTypes.add(ANNIEConstants.MONEY_ANNOTATION_TYPE);
77      annotationTypes.add(ANNIEConstants.LOOKUP_ANNOTATION_TYPE);
78      annotationTypes.add(ANNIEConstants.TOKEN_ANNOTATION_TYPE);
79    } // setUp
80  
81    /** Put things back as they should be after running tests.
82      */
83    public void tearDown() throws Exception {
84    } // tearDown
85  
86    public void testTokenizer() throws Exception {
87      FeatureMap params = Factory.newFeatureMap();
88      DefaultTokeniser tokeniser = (DefaultTokeniser) Factory.createResource(
89                      "gate.creole.tokeniser.DefaultTokeniser", params);
90  
91  
92      //run the tokeniser for doc1
93      tokeniser.setDocument(doc1);
94      tokeniser.execute();
95      assertTrue("Found in "+doc1.getSourceUrl().getFile()+ " "+
96        doc1.getAnnotations().size() +
97        " Token annotations, instead of the expected 1284.",
98        doc1.getAnnotations().size()== 1284);
99  
100     //run the tokeniser for doc2
101     tokeniser.setDocument(doc2);
102     tokeniser.execute();
103     assertTrue("Found in "+ doc2.getSourceUrl().getFile()+ " "+
104       doc2.getAnnotations().size() +
105       " Token annotations, instead of the expected 2138.",
106       doc2.getAnnotations().size()== 2138);
107 
108     //run the tokeniser for doc3
109     tokeniser.setDocument(doc3);
110     tokeniser.execute();
111     assertTrue("Found in "+ doc3.getSourceUrl().getFile()+ " "+
112       doc3.getAnnotations().size() +
113       " Token annotations, instead of the expected 2806.",
114       doc3.getAnnotations().size()== 2806);
115 
116     Factory.deleteResource(tokeniser);
117   }// testTokenizer
118 
119   public void testGazetteer() throws Exception {
120     FeatureMap params = Factory.newFeatureMap();
121     DefaultGazetteer gaz = (DefaultGazetteer) Factory.createResource(
122                           "gate.creole.gazetteer.DefaultGazetteer", params);
123 
124     //run gazetteer for doc1
125     gaz.setDocument(doc1);
126     gaz.execute();
127     assertTrue("Found in "+ doc1.getSourceUrl().getFile()+ " "+
128       doc1.getAnnotations().get(ANNIEConstants.LOOKUP_ANNOTATION_TYPE).size() +
129       " Lookup annotations, instead of the expected 47.",
130       doc1.getAnnotations().get(ANNIEConstants.LOOKUP_ANNOTATION_TYPE).size()== 47);
131 
132     //run gazetteer for doc2
133     gaz.setDocument(doc2);
134     gaz.execute();
135     assertTrue("Found in "+ doc2.getSourceUrl().getFile()+ " "+
136       doc2.getAnnotations().get(ANNIEConstants.LOOKUP_ANNOTATION_TYPE).size() +
137       " Lookup annotations, instead of the expected 99.",
138       doc2.getAnnotations().get(ANNIEConstants.LOOKUP_ANNOTATION_TYPE).size()== 99);
139 
140     //run gazetteer for doc3
141     gaz.setDocument(doc3);
142     gaz.execute();
143     assertTrue("Found in "+ doc3.getSourceUrl().getFile()+ " "+
144       doc3.getAnnotations().get(ANNIEConstants.LOOKUP_ANNOTATION_TYPE).size() +
145       " Lookup annotations, instead of the expected 112.",
146       doc3.getAnnotations().get(ANNIEConstants.LOOKUP_ANNOTATION_TYPE).size()== 112);
147     Factory.deleteResource(gaz);
148   }//testGazetteer
149 
150   public void testSplitter() throws Exception {
151     FeatureMap params = Factory.newFeatureMap();
152     SentenceSplitter splitter = (SentenceSplitter) Factory.createResource(
153                           "gate.creole.splitter.SentenceSplitter", params);
154 
155     //run splitter for doc1
156     splitter.setDocument(doc1);
157     splitter.execute();
158     assertTrue("Found in "+ doc1.getSourceUrl().getFile()+ " "+
159       doc1.getAnnotations().get(ANNIEConstants.SENTENCE_ANNOTATION_TYPE).size() +
160       " Sentence annotations, instead of the expected 22.",
161       doc1.getAnnotations().get(ANNIEConstants.SENTENCE_ANNOTATION_TYPE).size()== 22);
162 
163     assertTrue("Found in "+ doc1.getSourceUrl().getFile()+ " "+
164       doc1.getAnnotations().get("Split").size() +
165       " Split annotations, instead of the expected 36.",
166       doc1.getAnnotations().get("Split").size()== 36);
167 
168 
169     //run splitter for doc2
170     splitter.setDocument(doc2);
171     splitter.execute();
172     assertTrue("Found in "+ doc2.getSourceUrl().getFile()+ " "+
173       doc2.getAnnotations().get(ANNIEConstants.SENTENCE_ANNOTATION_TYPE).size() +
174       " Sentence annotations, instead of the expected 53.",
175       doc2.getAnnotations().get(ANNIEConstants.SENTENCE_ANNOTATION_TYPE).size()== 53);
176 
177     assertTrue("Found in "+ doc2.getSourceUrl().getFile()+ " "+
178       doc2.getAnnotations().get("Split").size() +
179       " Split annotations, instead of the expected 71.",
180       doc2.getAnnotations().get("Split").size()== 71);
181 
182     //run splitter for doc3
183     splitter.setDocument(doc3);
184     splitter.execute();
185 
186     assertTrue("Found in "+ doc3.getSourceUrl().getFile()+ " "+
187       doc3.getAnnotations().get(ANNIEConstants.SENTENCE_ANNOTATION_TYPE).size() +
188       " Sentence annotations, instead of the expected 66.",
189       doc3.getAnnotations().get(ANNIEConstants.SENTENCE_ANNOTATION_TYPE).size()== 66);
190 
191     assertTrue("Found in "+ doc3.getSourceUrl().getFile()+ " "+
192       doc3.getAnnotations().get("Split").size() +
193       " Split annotations, instead of the expected 84.",
194       doc3.getAnnotations().get("Split").size()== 84);
195     Factory.deleteResource(splitter);
196   }//testSplitter
197 
198   public void testTagger() throws Exception {
199     FeatureMap params = Factory.newFeatureMap();
200     POSTagger tagger = (POSTagger) Factory.createResource(
201                           "gate.creole.POSTagger", params);
202 
203 
204     //run the tagger for doc1
205     tagger.setDocument(doc1);
206     tagger.execute();
207 
208     HashSet fType = new HashSet();
209     fType.add(ANNIEConstants.TOKEN_CATEGORY_FEATURE_NAME);
210     AnnotationSet annots =
211       doc1.getAnnotations().get(ANNIEConstants.TOKEN_ANNOTATION_TYPE, fType);
212 
213     assertTrue("Found in "+ doc1.getSourceUrl().getFile()+ " "+ annots.size() +
214       " Token annotations with category feature, instead of the expected 675.",
215       annots.size() == 675);
216 
217     //run the tagger for doc2
218     tagger.setDocument(doc2);
219     tagger.execute();
220     annots = doc2.getAnnotations().get(ANNIEConstants.TOKEN_ANNOTATION_TYPE, fType);
221     assertTrue("Found in "+  doc2.getSourceUrl().getFile()+ " "+annots.size() +
222       " Token annotations with category feature, instead of the expected 1131.",
223       annots.size() == 1131);
224 
225     //run the tagger for doc3
226     tagger.setDocument(doc3);
227     tagger.execute();
228     annots = doc3.getAnnotations().get(ANNIEConstants.TOKEN_ANNOTATION_TYPE, fType);
229     assertTrue("Found in "+ doc3.getSourceUrl().getFile()+ " "+ annots.size() +
230       " Token annotations with category feature, instead of the expected 1443.",
231       annots.size() == 1443);
232     Factory.deleteResource(tagger);
233   }//testTagger()
234 
235   public void testTransducer() throws Exception {
236     FeatureMap params = Factory.newFeatureMap();
237     ANNIETransducer transducer = (ANNIETransducer) Factory.createResource(
238                           "gate.creole.ANNIETransducer", params);
239 
240     //run the transducer for doc1
241     transducer.setDocument(doc1);
242     transducer.execute();
243     assertTrue("Found in "+ doc1.getSourceUrl().getFile()+ " "+
244       doc1.getAnnotations().get(ANNIEConstants.ORGANIZATION_ANNOTATION_TYPE).size() +
245       " Organization annotations, instead of the expected 17",
246       doc1.getAnnotations().get(ANNIEConstants.ORGANIZATION_ANNOTATION_TYPE).size()== 17);
247     assertTrue("Found in "+doc1.getSourceUrl().getFile()+ " "+
248       doc1.getAnnotations().get(ANNIEConstants.LOCATION_ANNOTATION_TYPE).size() +
249       " Location annotations, instead of the expected 3",
250       doc1.getAnnotations().get(ANNIEConstants.LOCATION_ANNOTATION_TYPE).size()== 3);
251     assertTrue("Found in "+doc1.getSourceUrl().getFile()+ " "+
252       doc1.getAnnotations().get(ANNIEConstants.PERSON_ANNOTATION_TYPE).size() +
253       " Person annotations, instead of the expected 3",
254       doc1.getAnnotations().get(ANNIEConstants.PERSON_ANNOTATION_TYPE).size()== 3);
255     assertTrue("Found in "+doc1.getSourceUrl().getFile()+ " "+
256       doc1.getAnnotations().get(ANNIEConstants.DATE_ANNOTATION_TYPE).size() +
257       " Date annotations, instead of the expected 6",
258       doc1.getAnnotations().get(ANNIEConstants.DATE_ANNOTATION_TYPE).size()== 6);
259     assertTrue("Found in "+doc1.getSourceUrl().getFile()+ " "+
260       doc1.getAnnotations().get(ANNIEConstants.MONEY_ANNOTATION_TYPE).size() +
261       " Money annotations, instead of the expected 1",
262       doc1.getAnnotations().get(ANNIEConstants.MONEY_ANNOTATION_TYPE).size()== 1);
263 
264     //run the transducer for doc2
265     transducer.setDocument(doc2);
266     transducer.execute();
267     assertTrue("Found in "+doc2.getSourceUrl().getFile()+ " "+
268       doc2.getAnnotations().get(ANNIEConstants.ORGANIZATION_ANNOTATION_TYPE).size() +
269       " Organization annotations, instead of the expected 18",
270       doc2.getAnnotations().get(ANNIEConstants.ORGANIZATION_ANNOTATION_TYPE).size()== 18);
271     assertTrue("Found in "+doc2.getSourceUrl().getFile()+ " "+
272       doc2.getAnnotations().get(ANNIEConstants.LOCATION_ANNOTATION_TYPE).size() +
273       " Location annotations, instead of the expected 9",
274       doc2.getAnnotations().get(ANNIEConstants.LOCATION_ANNOTATION_TYPE).size()== 9);
275     assertTrue("Found in "+doc2.getSourceUrl().getFile()+ " "+
276       doc2.getAnnotations().get(ANNIEConstants.PERSON_ANNOTATION_TYPE).size() +
277       " Person annotations, instead of the expected 1",
278       doc2.getAnnotations().get(ANNIEConstants.PERSON_ANNOTATION_TYPE).size()== 1);
279     assertTrue("Found in "+doc2.getSourceUrl().getFile()+ " "+
280       doc2.getAnnotations().get(ANNIEConstants.DATE_ANNOTATION_TYPE).size() +
281       " Date annotations, instead of the expected 6",
282       doc2.getAnnotations().get(ANNIEConstants.DATE_ANNOTATION_TYPE).size()== 6);
283     assertTrue("Found in "+doc2.getSourceUrl().getFile()+ " "+
284       doc2.getAnnotations().get(ANNIEConstants.MONEY_ANNOTATION_TYPE).size() +
285       " Money annotations, instead of the expected 3",
286       doc2.getAnnotations().get(ANNIEConstants.MONEY_ANNOTATION_TYPE).size()== 3);
287 
288     //run the transducer for doc3
289     transducer.setDocument(doc3);
290     transducer.execute();
291     assertTrue("Found in "+doc3.getSourceUrl().getFile()+ " "+
292       doc3.getAnnotations().get(ANNIEConstants.ORGANIZATION_ANNOTATION_TYPE).size() +
293       " Organization annotations, instead of the expected 9",
294       doc3.getAnnotations().get(ANNIEConstants.ORGANIZATION_ANNOTATION_TYPE).size()== 9);
295     assertTrue("Found in "+doc3.getSourceUrl().getFile()+ " "+
296       doc3.getAnnotations().get(ANNIEConstants.LOCATION_ANNOTATION_TYPE).size() +
297       " Location annotations, instead of the expected 12",
298       doc3.getAnnotations().get(ANNIEConstants.LOCATION_ANNOTATION_TYPE).size()== 12);
299     assertTrue("Found in "+doc3.getSourceUrl().getFile()+ " "+
300       doc3.getAnnotations().get(ANNIEConstants.PERSON_ANNOTATION_TYPE).size() +
301       " Person annotations, instead of the expected 8",
302       doc3.getAnnotations().get(ANNIEConstants.PERSON_ANNOTATION_TYPE).size()== 8);
303     assertTrue("Found in "+doc3.getSourceUrl().getFile()+ " "+
304       doc3.getAnnotations().get(ANNIEConstants.DATE_ANNOTATION_TYPE).size() +
305       " Date annotations, instead of the expected 7",
306       doc3.getAnnotations().get(ANNIEConstants.DATE_ANNOTATION_TYPE).size()== 7);
307     assertTrue("Found in "+doc3.getSourceUrl().getFile()+ " "+
308       doc3.getAnnotations().get(ANNIEConstants.MONEY_ANNOTATION_TYPE).size() +
309       " Money annotations, instead of the expected 4",
310       doc3.getAnnotations().get(ANNIEConstants.MONEY_ANNOTATION_TYPE).size()== 4);
311 
312     Factory.deleteResource(transducer);
313   }//testTransducer
314 
315   public void testOrthomatcher() throws Exception {
316     FeatureMap params = Factory.newFeatureMap();
317 
318     OrthoMatcher orthomatcher = (OrthoMatcher) Factory.createResource(
319                           "gate.creole.orthomatcher.OrthoMatcher", params);
320 
321 
322     // run the orthomatcher for doc1
323     orthomatcher.setDocument(doc1);
324     orthomatcher.execute();
325 
326     HashSet fType = new HashSet();
327     fType.add(ANNIEConstants.ANNOTATION_COREF_FEATURE_NAME);
328     AnnotationSet annots =
329                   doc1.getAnnotations().get(null,fType);
330 
331     assertTrue("Found in "+doc1.getSourceUrl().getFile()+ " "+ annots.size() +
332       " annotations with matches feature, instead of the expected 30.",
333       annots.size() == 30);
334 
335     //run the orthomatcher for doc2
336     orthomatcher.setDocument(doc2);
337     orthomatcher.execute();
338     annots = doc2.getAnnotations().get(null,fType);
339     assertTrue("Found in "+doc2.getSourceUrl().getFile()+ " "+ annots.size() +
340       " annotations with matches feature, instead of the expected 35.",
341       annots.size() == 33);
342 
343     //run the orthomatcher for doc3
344     orthomatcher.setDocument(doc3);
345     orthomatcher.execute();
346 
347     annots = doc3.getAnnotations().get(null,fType);
348     assertTrue("Found in "+doc3.getSourceUrl().getFile()+ " "+ annots.size() +
349       " annotations with matches feature, instead of the expected 22.",
350       annots.size() == 22);
351     Factory.deleteResource(orthomatcher);
352   }//testOrthomatcher
353 
354   /** A test for comparing the annotation sets*/
355   public void testAllPR() throws Exception {
356 
357     // verify if the saved data store is the same with the just processed file
358     // first document
359     String urlBaseName = Gate.locateGateFiles();
360 //    RE re1 = new RE("build/gate.jar!");
361 //    RE re2 = new RE("jar:");
362 //    urlBaseName = re1.substituteAll( urlBaseName,"classes");
363 //    urlBaseName = re2.substituteAll( urlBaseName,"");
364 
365     if (urlBaseName.endsWith("/gate/build/gate.jar!/")) {
366       StringBuffer buff = new StringBuffer(
367                             urlBaseName.substring(
368                               0,
369                               urlBaseName.lastIndexOf("build/gate.jar!/"))
370                             );
371       buff.append("classes/");
372       buff.delete(0, "jar:file:".length());
373       buff.insert(0, "file://");
374       urlBaseName = buff.toString();
375     }
376 
377     URL urlBase = new URL(urlBaseName + "gate/resources/gate.ac.uk/");
378 
379     URL storageDir = null;
380     storageDir = new URL(urlBase, "tests/ft");
381 
382     //open the data store
383     DataStore ds = Factory.openDataStore
384                     ("gate.persist.SerialDataStore",
385                      storageDir.toExternalForm());
386 
387     //get LR id
388     String lrId = (String)ds.getLrIds
389                                 ("gate.corpora.DocumentImpl").get(0);
390 
391 
392     // get the document from data store
393     FeatureMap features = Factory.newFeatureMap();
394     features.put(DataStore.DATASTORE_FEATURE_NAME, ds);
395     features.put(DataStore.LR_ID_FEATURE_NAME, lrId);
396     Document document = (Document) Factory.createResource(
397                                       "gate.corpora.DocumentImpl",
398                                       features);
399     compareAnnots(document, doc1);
400 
401     // second document
402     storageDir = null;
403     storageDir = new URL(urlBase, "tests/gu");
404 
405     //open the data store
406     ds = Factory.openDataStore("gate.persist.SerialDataStore",
407                                storageDir.toExternalForm());
408     //get LR id
409     lrId = (String)ds.getLrIds("gate.corpora.DocumentImpl").get(0);
410     // get the document from data store
411     features = Factory.newFeatureMap();
412     features.put(DataStore.DATASTORE_FEATURE_NAME, ds);
413     features.put(DataStore.LR_ID_FEATURE_NAME, lrId);
414     document = (Document) Factory.createResource(
415                                       "gate.corpora.DocumentImpl",
416                                       features);
417     compareAnnots(document,doc2);
418 
419     // third document
420     storageDir = null;
421     storageDir = new URL(urlBase, "tests/in");
422 
423     //open the data store
424     ds = Factory.openDataStore("gate.persist.SerialDataStore",
425                                storageDir.toExternalForm());
426     //get LR id
427     lrId = (String)ds.getLrIds("gate.corpora.DocumentImpl").get(0);
428     // get the document from data store
429     features = Factory.newFeatureMap();
430     features.put(DataStore.DATASTORE_FEATURE_NAME, ds);
431     features.put(DataStore.LR_ID_FEATURE_NAME, lrId);
432     document = (Document) Factory.createResource(
433                                 "gate.corpora.DocumentImpl",
434                                 features);
435     compareAnnots(document,doc3);
436   } // testAllPR()
437 
438   public void compareAnnots(Document keyDocument, Document responseDocument)
439               throws Exception{
440 
441     // create annotation schema
442     AnnotationSchema annotationSchema = new AnnotationSchema();
443     String annotType = null;
444 
445     // organization type
446     Iterator iteratorTypes = annotationTypes.iterator();
447     while (iteratorTypes.hasNext()){
448       // get the type of annotation
449       annotType = (String)iteratorTypes.next();
450 
451       annotationSchema.setAnnotationName(annotType);
452 
453       // create an annotation diff
454       AnnotationDiff annotDiff = new AnnotationDiff();
455       annotDiff.setKeyDocument(keyDocument);
456       annotDiff.setResponseDocument(responseDocument);
457       annotDiff.setAnnotationSchema(annotationSchema);
458       annotDiff.setKeyAnnotationSetName(null);
459       annotDiff.setResponseAnnotationSetName(null);
460 
461       Set significantFeatures = new HashSet(Arrays.asList(
462                     new String[]{"NMRule", "kind", "orgType", "rule",
463                                  "rule1", "rule2", "locType", "gender",
464                                  "majorType", "minorType", "category",
465                                  "length", "orth", "string", "subkind",
466                                  "symbolkind"}));
467       annotDiff.setKeyFeatureNamesSet(significantFeatures);
468       annotDiff.setTextMode(new Boolean(true));
469 
470       annotDiff.init();
471 
472       if (DEBUG){
473         if (annotDiff.getFMeasureAverage() != 1.0) {
474           assertTrue("missing annotations " +
475             annotDiff.getAnnotationsOfType(AnnotationDiff.MISSING_TYPE)
476             + " spurious annotations " +
477             annotDiff.getAnnotationsOfType(AnnotationDiff.SPURIOUS_TYPE)
478             + " partially-correct annotations " +
479             annotDiff.getAnnotationsOfType(
480                             AnnotationDiff.PARTIALLY_CORRECT_TYPE),false);
481         }
482       }//if
483 
484       assertTrue(annotType+ " precision average in "+
485         responseDocument.getSourceUrl().getFile()+
486         " is "+ annotDiff.getPrecisionAverage()+ " instead of 1.0 ",
487         annotDiff.getPrecisionAverage()== 1.0);
488       assertTrue(annotType+" recall average in "
489         +responseDocument.getSourceUrl().getFile()+
490         " is " + annotDiff.getRecallAverage()+ " instead of 1.0 ",
491         annotDiff.getRecallAverage()== 1.0);
492       assertTrue(annotType+" f-measure average in "
493         +responseDocument.getSourceUrl().getFile()+
494         " is "+ annotDiff.getFMeasureAverage()+ " instead of 1.0 ",
495         annotDiff.getFMeasureAverage()== 1.0);
496      }//while
497    }// public void compareAnnots
498 
499   /** Test suite routine for the test runner */
500   public static Test suite() {
501     return new TestSuite(TestPR.class);
502   } // suite
503 
504   public static void main(String[] args) {
505     try{
506 
507       Gate.init();
508       TestPR testPR = new TestPR("");
509       testPR.setUp();
510       testPR.testTokenizer();
511       testPR.testGazetteer();
512       testPR.testSplitter();
513       testPR.testTagger();
514       testPR.testTransducer();
515       testPR.testOrthomatcher();
516       testPR.testAllPR();
517       testPR.tearDown();
518     } catch(Exception e) {
519       e.printStackTrace();
520     }
521   } // main
522 } // class TestPR
523