| SinglePhaseTransducer.java |
1 /*
2 * SinglePhaseTransducer.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: SinglePhaseTransducer.java,v 1.75 2004/10/28 16:34:43 valyt Exp $
14 */
15
16
17 package gate.jape;
18
19 import java.util.*;
20
21 import gate.*;
22 import gate.annotation.AnnotationSetImpl;
23 import gate.creole.ExecutionException;
24 import gate.creole.ExecutionInterruptedException;
25 import gate.event.ProgressListener;
26 import gate.fsm.*;
27 import gate.util.*;
28
29 // by Shafirin Andrey start
30 import debugger.resources.pr.TraceContainer;
31 import debugger.resources.pr.RuleTrace;
32 import debugger.resources.SPTLock;
33 import debugger.resources.PhaseController;
34 // by Shafirin Andrey end
35
36 /**
37 * Represents a complete CPSL grammar, with a phase name, options and
38 * rule set (accessible by name and by sequence).
39 * Implements a transduce method taking a Document as input.
40 * Constructs from String or File.
41 */
42 public class SinglePhaseTransducer
43 extends Transducer implements JapeConstants, java.io.Serializable
44 {
45 /** Debug flag */
46 private static final boolean DEBUG = false;
47
48 // by Shafirin Andrey start
49 PhaseController phaseController = null;
50 TraceContainer rulesTrace = null;
51 RuleTrace currRuleTrace = null;
52
53 public PhaseController getPhaseController() {
54 return phaseController;
55 }
56
57 public void setPhaseController(PhaseController phaseController) {
58 this.phaseController = phaseController;
59 }
60 // by Shafirin Andrey end
61
62
63 /** Construction from name. */
64 public SinglePhaseTransducer(String name) {
65 this.name = name;
66 rules = new PrioritisedRuleList();
67 finishedAlready = false;
68 } // Construction from name
69
70 /** Type of rule application (constants defined in JapeConstants). */
71 private int ruleApplicationStyle = BRILL_STYLE;
72
73 /** Set the type of rule application (types defined in JapeConstants). */
74 public void setRuleApplicationStyle(int style) {
75 ruleApplicationStyle = style;
76 }
77
78 /** The list of rules in this transducer. Ordered by priority and
79 * addition sequence (which will be file position if they come from
80 * a file).
81 */
82 private PrioritisedRuleList rules;
83
84 FSM fsm;
85
86 public FSM getFSM(){
87 return fsm;
88 }
89
90 /** Add a rule. */
91 public void addRule(Rule rule) {
92 rules.add(rule);
93 } // addRule
94
95 /** The values of any option settings given. */
96 private java.util.HashMap optionSettings = new java.util.HashMap();
97
98 /** Add an option setting. If this option is set already, the new
99 * value overwrites the previous one.
100 */
101 public void setOption(String name, String setting) {
102 optionSettings.put(name, setting);
103 } // setOption
104
105 /** Get the value for a particular option. */
106 public String getOption(String name) {
107 return (String) optionSettings.get(name);
108 } // getOption
109
110 /** Whether the finish method has been called or not. */
111 private boolean finishedAlready;
112
113 /** Finish: replace dynamic data structures with Java arrays; called
114 * after parsing.
115 */
116 public void finish() {
117 // both MPT and SPT have finish called on them by the parser...
118 if (finishedAlready)
119 return;
120 else
121 finishedAlready = true;
122
123 //each rule has a RHS which has a string for java code
124 //those strings need to be compiled now
125 Map actionClasses = new HashMap(rules.size());
126 for (Iterator i = rules.iterator(); i.hasNext(); ) {
127 Rule rule = (Rule) i.next();
128 rule.finish();
129 actionClasses.put(rule.getRHS().getActionClassName(),
130 rule.getRHS().getActionClassString());
131 }
132 try{
133 gate.util.Javac.loadClasses(actionClasses);
134 }catch(Exception e){
135 throw new GateRuntimeException(
136 "Compile error while loading Jape transducer \"" + name + "\"!", e);
137 }
138
139 //build the finite state machine transition graph
140 fsm = new FSM(this);
141 //clear the old style data structures
142 rules.clear();
143 rules = null;
144 } // finish
145
146 //dam: was
147 // private void addAnnotationsByOffset(Map map, SortedSet keys, Set annotations){
148 private void addAnnotationsByOffset(/*Map map,*/ SimpleSortedSet keys, Set annotations){
149 Iterator annIter = annotations.iterator();
150 while(annIter.hasNext()){
151 Annotation ann = (Annotation)annIter.next();
152 //ignore empty annotations
153 long offset = ann.getStartNode().getOffset().longValue();
154 if(offset == ann.getEndNode().getOffset().longValue())
155 continue;
156 //dam: was
157 /*
158 // Long offset = ann.getStartNode().getOffset();
159
160 List annsAtThisOffset = null;
161 if(keys.add(offset)){
162 annsAtThisOffset = new LinkedList();
163 map.put(offset, annsAtThisOffset);
164 }else{
165 annsAtThisOffset = (List)map.get(offset);
166 }
167 annsAtThisOffset.add(ann);
168 */
169 //dam: end
170 keys.add(offset, ann);
171 }
172 }//private void addAnnotationsByOffset()
173
174
175 /**
176 * Transduce a document using the annotation set provided and the current
177 * rule application style.
178 */
179 public void transduce(Document doc, AnnotationSet inputAS,
180 AnnotationSet outputAS) throws JapeException,
181 ExecutionException {
182 interrupted = false;
183 fireProgressChanged(0);
184
185 //the input annotations will be read from this map
186 //maps offset to list of annotations
187 SimpleSortedSet offsets = new SimpleSortedSet();
188 SimpleSortedSet annotationsByOffset = offsets;
189
190 //select only the annotations of types specified in the input list
191 if(input.isEmpty()) {
192 addAnnotationsByOffset(offsets, inputAS);
193 } else {
194 Iterator typesIter = input.iterator();
195 AnnotationSet ofOneType = null;
196 while(typesIter.hasNext()){
197 ofOneType = inputAS.get((String)typesIter.next());
198 if(ofOneType != null){
199 addAnnotationsByOffset(offsets, ofOneType);
200 }
201 }
202 }
203
204 if(annotationsByOffset.isEmpty()){
205 fireProcessFinished();
206 return;
207 }
208
209 annotationsByOffset.sort();
210 //define data structures
211 //FSM instances that haven't blocked yet
212 java.util.ArrayList activeFSMInstances = new java.util.ArrayList();
213
214 // FSM instances that have reached a final state
215 // This is a list and the contained objects are sorted by the length
216 // of the document content covered by the matched annotations
217 java.util.ArrayList acceptingFSMInstances = new ArrayList();
218 FSMInstance currentFSM;
219
220
221 //find the first node of the document
222 Node startNode = ((Annotation)
223 ((ArrayList)annotationsByOffset.get(offsets.first())).get(0)).
224 getStartNode();
225
226 //used to calculate the percentage of processing done
227 long lastNodeOff = doc.getContent().size().longValue();
228
229 //the offset of the node where the matching currently starts
230 //the value -1 marks no more annotations to parse
231 long startNodeOff = startNode.getOffset().longValue();
232
233 //used to decide when to fire progress events
234 long oldStartNodeOff = 0;
235
236 // by Shafirin Andrey start (according to Vladimir Karasev)
237 if (gate.Gate.isEnableJapeDebug()) {
238 // by Shafirin Andrey --> if (null != phaseController) {
239 if (null != phaseController) {
240 rulesTrace = new TraceContainer();
241 rulesTrace.putPhaseCut(this, inputAS);
242 }
243 }
244 // by Shafirin Andrey end
245
246 //the big while for the actual parsing
247 while(startNodeOff != -1){
248 //while there are more annotations to parse
249 //create initial active FSM instance starting parsing from new startNode
250 //currentFSM = FSMInstance.getNewInstance(
251 currentFSM = new FSMInstance(
252 fsm,
253 fsm.getInitialState(),//fresh start
254 startNode,//the matching starts form the current startNode
255 startNode,//current position in AG is the start position
256 new java.util.HashMap(),//no bindings yet!
257 doc
258 );
259
260 // at this point ActiveFSMInstances should always be empty!
261 activeFSMInstances.clear();
262 acceptingFSMInstances.clear();
263 activeFSMInstances.add(currentFSM);
264
265 //far each active FSM Instance, try to advance
266 whileloop2:
267 while(!activeFSMInstances.isEmpty()){
268 if(interrupted) throw new ExecutionInterruptedException(
269 "The execution of the \"" + getName() +
270 "\" Jape transducer has been abruptly interrupted!");
271
272 // take the first active FSM instance
273 currentFSM = (FSMInstance)activeFSMInstances.remove(0);
274
275 // process the current FSM instance
276 if(currentFSM.getFSMPosition().isFinal()){
277 //the current FSM is in a final state
278 acceptingFSMInstances.add(currentFSM.clone());
279 //if we're only looking for the shortest stop here
280 if(ruleApplicationStyle == FIRST_STYLE) break whileloop2;
281 }
282
283 //get all the annotations that start where the current FSM finishes
284 SimpleSortedSet offsetsTailSet = offsets.tailSet(currentFSM.
285 getAGPosition().getOffset().longValue());
286 ArrayList paths;
287 long theFirst = offsetsTailSet.first();
288 if(theFirst <0) continue;
289 paths = (ArrayList)annotationsByOffset.get(theFirst);
290 if(paths.isEmpty()) continue;
291 Iterator pathsIter = paths.iterator();
292 Annotation onePath;
293 State currentState = currentFSM.getFSMPosition();
294 Iterator transitionsIter;
295 //foreach possible annotation
296 while(pathsIter.hasNext()){
297 onePath = (Annotation)pathsIter.next();
298 transitionsIter = currentState.getTransitions().iterator();
299 Transition currentTransition;
300 Constraint[] currentConstraints;
301 transitionsWhile:
302 while(transitionsIter.hasNext()){
303 currentTransition = (Transition)transitionsIter.next();
304 //check if the current transition can use the current annotation (path)
305 currentConstraints =
306 currentTransition.getConstraints().getConstraints();
307 String annType;
308 //introduce index of the constraint to process
309 int currentConstraintsindex = -1;
310 //we assume that all annotations in a constraint are of the same type
311 for(int i = 0; i<currentConstraints.length; i++){
312 annType = currentConstraints[i].getAnnotType();
313 //if wrong type try next transition
314 if(!annType.equals(onePath.getType()))continue transitionsWhile;
315 currentConstraintsindex = i;
316 break;
317 }
318
319 /* ontotext.bp: always try to subsume using an ontology; */
320 /*if null then the ordinary subsume method is started*/
321 if(onePath.getFeatures().
322 subsumes(ontology,
323 currentConstraints[currentConstraintsindex].
324 getAttributeSeq())){
325 //we have a match
326 //create a new FSMInstance, advance it over the current annotation
327 //take care of the bindings and add it to ActiveFSM
328 FSMInstance newFSMI = (FSMInstance)currentFSM.clone();
329 newFSMI.setAGPosition(onePath.getEndNode());
330 newFSMI.setFSMPosition(currentTransition.getTarget());
331
332 // by Shafirin Andrey start (according to Vladimir Karasev)
333 if(gate.Gate.isEnableJapeDebug()) {
334 if (null != phaseController) {
335 currRuleTrace = rulesTrace.getStateContainer(currentFSM.
336 getFSMPosition());
337 if (currRuleTrace == null) {
338 currRuleTrace = new RuleTrace(newFSMI.getFSMPosition(), doc);
339 currRuleTrace.addAnnotation(onePath);
340 currRuleTrace.putPattern(onePath,
341 currentConstraints[currentConstraintsindex].
342 getAttributeSeq());
343 rulesTrace.add(currRuleTrace);
344 }
345 else {
346 currRuleTrace.addState(newFSMI.getFSMPosition());
347 currRuleTrace.addAnnotation(onePath);
348 currRuleTrace.putPattern(onePath,
349 currentConstraints[currentConstraintsindex].
350 getAttributeSeq());
351 }
352 }
353 }
354 // by Shafirin Andrey end
355
356 //bindings
357 java.util.Map binds = newFSMI.getBindings();
358 java.util.Iterator labelsIter =
359 currentTransition.getBindings().iterator();
360 String oneLabel;
361 AnnotationSet boundAnnots, newSet;
362 while(labelsIter.hasNext()){
363 oneLabel = (String)labelsIter.next();
364 boundAnnots = (AnnotationSet)binds.get(oneLabel);
365 if(boundAnnots != null)
366 newSet = new AnnotationSetImpl((AnnotationSet)boundAnnots);
367 else
368 newSet = new AnnotationSetImpl(doc);
369 newSet.add(onePath);
370 binds.put(oneLabel, newSet);
371
372 }//while(labelsIter.hasNext())
373 activeFSMInstances.add(newFSMI);
374 }//if match
375 }//while(transitionsIter.hasNext())
376 }//while(pathsIter.hasNext())
377 }//while(!activeFSMInstances.isEmpty())
378
379 //FIRE THE RULE
380 long lastAGPosition = -1;
381 if(acceptingFSMInstances.isEmpty()){
382 //no rule to fire, advance to the next input offset
383 lastAGPosition = startNodeOff + 1;
384 } else if(ruleApplicationStyle == BRILL_STYLE) {
385 // fire the rules corresponding to all accepting FSM instances
386 java.util.Iterator accFSMIter = acceptingFSMInstances.iterator();
387 FSMInstance currentAcceptor;
388 RightHandSide currentRHS;
389 lastAGPosition = startNode.getOffset().longValue();
390
391 while(accFSMIter.hasNext()){
392 currentAcceptor = (FSMInstance) accFSMIter.next();
393 currentRHS = currentAcceptor.getFSMPosition().getAction();
394
395 // by Shafirin Andrey start
396 // debugger callback
397 if (gate.Gate.isEnableJapeDebug()) {
398 if (null != phaseController) {
399 SPTLock lock = new SPTLock();
400 phaseController.TraceTransit(rulesTrace);
401 rulesTrace = new TraceContainer();
402 phaseController.RuleMatched(lock, this, currentRHS, doc,
403 currentAcceptor.getBindings(),
404 inputAS, outputAS);
405 }
406 }
407 // by Shafirin Andrey end
408
409 currentRHS.transduce(doc, currentAcceptor.getBindings(),
410 inputAS, outputAS, ontology);
411
412 // by Shafirin Andrey start
413 // debugger callback
414 if (gate.Gate.isEnableJapeDebug()) {
415 if (null != phaseController) {
416 SPTLock lock = new SPTLock();
417 phaseController.RuleFinished(lock, this, currentRHS, doc,
418 currentAcceptor.getBindings(),
419 inputAS, outputAS);
420 }
421 }
422 // by Shafirin Andrey end
423
424 long currentAGPosition = currentAcceptor.getAGPosition().getOffset().longValue();
425 if(currentAGPosition > lastAGPosition)
426 lastAGPosition = currentAGPosition;
427 }
428 } else if(ruleApplicationStyle == APPELT_STYLE ||
429 ruleApplicationStyle == FIRST_STYLE ||
430 ruleApplicationStyle == ONCE_STYLE) {
431
432 // AcceptingFSMInstances is an ordered structure:
433 // just execute the longest (last) rule
434 Collections.sort(acceptingFSMInstances, Collections.reverseOrder());
435 Iterator accFSMIter = acceptingFSMInstances.iterator();
436 FSMInstance currentAcceptor = (FSMInstance)accFSMIter.next();
437 if(isDebugMode()){
438 //see if we have any conflicts
439 Iterator accIter = acceptingFSMInstances.iterator();
440 FSMInstance anAcceptor;
441 List conflicts = new ArrayList();
442 while(accIter.hasNext()){
443 anAcceptor = (FSMInstance)accIter.next();
444 if(anAcceptor.equals(currentAcceptor)){
445 conflicts.add(anAcceptor);
446 }else{
447 break;
448 }
449 }
450 if(conflicts.size() > 1){
451 Out.prln("\nConflicts found during matching:" +
452 "\n================================");
453 accIter = conflicts.iterator();
454 int i = 0;
455 while(accIter.hasNext()){
456 Out.prln(i++ + ") " + accIter.next().toString());
457 }
458 }
459 }
460 RightHandSide currentRHS = currentAcceptor.getFSMPosition().getAction();
461
462 // by Shafirin Andrey start
463 // debugger callback
464 if(gate.Gate.isEnableJapeDebug()) {
465 if (null != phaseController) {
466 SPTLock lock = new SPTLock();
467 rulesTrace.leaveLast(currentRHS);
468 phaseController.TraceTransit(rulesTrace);
469 rulesTrace = new TraceContainer();
470 phaseController.RuleMatched(lock, this, currentRHS, doc,
471 currentAcceptor.getBindings(),
472 inputAS, outputAS);
473 }
474 }
475 // by Shafirin Andrey end
476
477 currentRHS.transduce(doc, currentAcceptor.getBindings(),
478 inputAS, outputAS, ontology);
479
480 // by Shafirin Andrey start
481 // debugger callback
482 if(gate.Gate.isEnableJapeDebug()) {
483 if (null != phaseController) {
484 SPTLock lock = new SPTLock();
485 phaseController.RuleFinished(lock, this, currentRHS, doc,
486 currentAcceptor.getBindings(),
487 inputAS, outputAS);
488 }
489 }
490 // by Shafirin Andrey end
491
492 //if in matchGroup mode check other possible patterns in this span
493 if(isMatchGroupMode()) {
494 //Out.prln("Jape grammar in MULTI application style.");
495 // ~bp: check for other matching fsm instances with same length,
496 // priority and rule index : if such execute them also.
497 String currentAcceptorString = null;
498 multiModeWhile: while(accFSMIter.hasNext()) {
499 FSMInstance rivalAcceptor =(FSMInstance) accFSMIter.next();
500 //get rivals that match the same document segment
501 //makes use of the semantic difference between the compareTo and
502 //equals methods on FSMInstance
503 if(rivalAcceptor.compareTo(currentAcceptor)==0){
504 // gets the rivals that are NOT COMPLETELY IDENTICAL with the
505 // current acceptor.
506 if(!rivalAcceptor.equals(currentAcceptor)){
507 if (isDebugMode()){ /*depends on the debug option in the transducer */
508 if (currentAcceptorString == null) {
509 // first rival
510 currentAcceptorString = currentAcceptor.toString();
511 Out.prln("~Jape Grammar Transducer : "+
512 "\nConcurrent Patterns by length,priority and index (all transduced):");
513 Out.prln(currentAcceptorString);
514 Out.prln("bindings : "+currentAcceptor.getBindings());
515 Out.prln("Rivals Follow: ");
516 }
517 Out.prln(rivalAcceptor);
518 Out.prln("bindings : "+rivalAcceptor.getBindings());
519 }// DEBUG
520 currentRHS = rivalAcceptor.getFSMPosition().getAction();
521
522 // by Shafirin Andrey start
523 // debugger callback
524 if(gate.Gate.isEnableJapeDebug()) {
525 if (null != phaseController) {
526 SPTLock lock = new SPTLock();
527 rulesTrace.leaveLast(currentRHS);
528 phaseController.TraceTransit(rulesTrace);
529 rulesTrace = new TraceContainer();
530 phaseController.RuleMatched(lock, this, currentRHS, doc,
531 rivalAcceptor.getBindings(),
532 inputAS, outputAS);
533 }
534 }
535 // by Shafirin Andrey end
536
537 currentRHS.transduce(doc, rivalAcceptor.getBindings(),
538 inputAS, outputAS, ontology);
539
540 // by Shafirin Andrey start
541 // debugger callback
542 if(gate.Gate.isEnableJapeDebug()) {
543 if (null != phaseController) {
544 SPTLock lock = new SPTLock();
545 phaseController.RuleFinished(lock, this, currentRHS, doc,
546 rivalAcceptor.getBindings(),
547 inputAS, outputAS);
548 }
549 }
550 // by Shafirin Andrey end
551 } // equal rival
552 }else{
553 //if rival is not equal this means that there are no further
554 // equal rivals (since the list is sorted)
555 break multiModeWhile;
556 }
557 } // while there are fsm instances
558 } // matchGroupMode
559
560 //if in ONCE mode stop after first match
561 if(ruleApplicationStyle == ONCE_STYLE) return;
562
563 //advance in AG
564 lastAGPosition = currentAcceptor.getAGPosition().getOffset().longValue();
565 }else throw new RuntimeException("Unknown rule application style!");
566
567
568 //advance on input
569 SimpleSortedSet OffsetsTailSet = offsets.tailSet(lastAGPosition);
570 long theFirst = OffsetsTailSet.first();
571 if( theFirst < 0){
572 //no more input, phew! :)
573 startNodeOff = -1;
574 fireProcessFinished();
575 }else{
576 long nextKey = theFirst;
577 startNode = ((Annotation)
578 ((ArrayList)annotationsByOffset.get(nextKey)).get(0)). //nextKey
579 getStartNode();
580 startNodeOff = startNode.getOffset().longValue();
581
582 //eliminate the possibility for infinite looping
583 if(oldStartNodeOff == startNodeOff){
584 //we are about to step twice in the same place, ...skip ahead
585 lastAGPosition = startNodeOff + 1;
586 OffsetsTailSet = offsets.tailSet(lastAGPosition);
587 theFirst = OffsetsTailSet.first();
588 if(theFirst < 0){
589 //no more input, phew! :)
590 startNodeOff = -1;
591 fireProcessFinished();
592 }else{
593 nextKey = theFirst;
594 startNode = ((Annotation)
595 ((List)annotationsByOffset.get(theFirst)).get(0)).
596 getStartNode();
597 startNodeOff =startNode.getOffset().longValue();
598 }
599 }//if(oldStartNodeOff == startNodeOff)
600 //fire the progress event
601 if(startNodeOff - oldStartNodeOff > 256){
602 if(isInterrupted()) throw new ExecutionInterruptedException(
603 "The execution of the \"" + getName() +
604 "\" Jape transducer has been abruptly interrupted!");
605
606 fireProgressChanged((int)(100 * startNodeOff / lastNodeOff));
607 oldStartNodeOff = startNodeOff;
608 }
609 }
610 }//while(startNodeOff != -1)
611 fireProcessFinished();
612
613 // by Shafirin Andrey start (according to Vladimir Karasev)
614 if(gate.Gate.isEnableJapeDebug()) {
615 if (null != phaseController) {
616 phaseController.TraceTransit(rulesTrace);
617 }
618 }
619 // by Shafirin Andrey end
620
621 } // transduce
622
623
624 /** Clean up (delete action class files, for e.g.). */
625 public void cleanUp() {
626 // for(DListIterator i = rules.begin(); ! i.atEnd(); i.advance())
627 // ((Rule) i.get()).cleanUp();
628 } // cleanUp
629
630 /** A string representation of this object. */
631 public String toString() {
632 return toString("");
633 } // toString()
634
635 /** A string representation of this object. */
636 public String toString(String pad) {
637 String newline = Strings.getNl();
638 String newPad = Strings.addPadding(pad, INDENT_PADDING);
639
640 StringBuffer buf =
641 new StringBuffer(pad + "SPT: name(" + name + "); ruleApplicationStyle(");
642
643 switch(ruleApplicationStyle) {
644 case APPELT_STYLE: buf.append("APPELT_STYLE); "); break;
645 case BRILL_STYLE: buf.append("BRILL_STYLE); "); break;
646 default: break;
647 }
648
649 buf.append("rules(" + newline);
650 Iterator rulesIterator = rules.iterator();
651 while(rulesIterator.hasNext())
652 buf.append(((Rule) rulesIterator.next()).toString(newPad) + " ");
653
654 buf.append(newline + pad + ")." + newline);
655
656 return buf.toString();
657 } // toString(pad)
658
659 //needed by fsm
660 public PrioritisedRuleList getRules() {
661 return rules;
662 }
663
664 /**
665 * Adds a new type of input annotations used by this transducer.
666 * If the list of input types is empty this transducer will parse all the
667 * annotations in the document otherwise the types not found in the input
668 * list will be completely ignored! To be used with caution!
669 */
670 public void addInput(String ident) {
671 input.add(ident);
672 }
673 public synchronized void removeProgressListener(ProgressListener l) {
674 if (progressListeners != null && progressListeners.contains(l)) {
675 Vector v = (Vector) progressListeners.clone();
676 v.removeElement(l);
677 progressListeners = v;
678 }
679 }
680 public synchronized void addProgressListener(ProgressListener l) {
681 Vector v = progressListeners == null ? new Vector(2) : (Vector) progressListeners.clone();
682 if (!v.contains(l)) {
683 v.addElement(l);
684 progressListeners = v;
685 }
686 }
687
688 /**
689 * Defines the types of input annotations that this transducer reads. If this
690 * set is empty the transducer will read all the annotations otherwise it
691 * will only "see" the annotations of types found in this list ignoring all
692 * other types of annotations.
693 */
694 // by Shafirin Andrey start (modifier changed to public)
695 public java.util.Set input = new java.util.HashSet();
696 //java.util.Set input = new java.util.HashSet();
697 // by Shafirin Andrey end
698 private transient Vector progressListeners;
699
700 protected void fireProgressChanged(int e) {
701 if (progressListeners != null) {
702 Vector listeners = progressListeners;
703 int count = listeners.size();
704 for (int i = 0; i < count; i++) {
705 ((ProgressListener) listeners.elementAt(i)).progressChanged(e);
706 }
707 }
708 }
709 protected void fireProcessFinished() {
710 if (progressListeners != null) {
711 Vector listeners = progressListeners;
712 int count = listeners.size();
713 for (int i = 0; i < count; i++) {
714 ((ProgressListener) listeners.elementAt(i)).processFinished();
715 }
716 }
717 }
718 public int getRuleApplicationStyle() {
719 return ruleApplicationStyle;
720 }
721
722 /*
723 private void writeObject(ObjectOutputStream oos) throws IOException {
724 Out.prln("writing spt");
725 oos.defaultWriteObject();
726 Out.prln("finished writing spt");
727 } // writeObject
728 */
729
730
731 } // class SinglePhaseTransducer
732
733 /*
734 class SimpleSortedSet {
735
736 static final int INCREMENT = 1023;
737 int[] theArray = new int[INCREMENT];
738 Object[] theObject = new Object[INCREMENT];
739 int tsindex = 0;
740 int size = 0;
741 public static int avesize = 0;
742 public static int maxsize = 0;
743 public static int avecount = 0;
744 public SimpleSortedSet()
745 {
746 avecount++;
747 java.util.Arrays.fill(theArray, Integer.MAX_VALUE);
748 }
749
750 public Object get(int elValue)
751 {
752 int index = java.util.Arrays.binarySearch(theArray, elValue);
753 if (index >=0)
754 return theObject[index];
755 return null;
756 }
757
758 public boolean add(int elValue, Object o)
759 {
760 int index = java.util.Arrays.binarySearch(theArray, elValue);
761 if (index >=0)
762 {
763 ((ArrayList)theObject[index]).add(o);
764 return false;
765 }
766 if (size == theArray.length)
767 {
768 int[] temp = new int[theArray.length + INCREMENT];
769 Object[] tempO = new Object[theArray.length + INCREMENT];
770 System.arraycopy(theArray, 0, temp, 0, theArray.length);
771 System.arraycopy(theObject, 0, tempO, 0, theArray.length);
772 java.util.Arrays.fill(temp, theArray.length, temp.length , Integer.MAX_VALUE);
773 theArray = temp;
774 theObject = tempO;
775 }
776 index = ~index;
777 System.arraycopy(theArray, index, theArray, index+1, size - index );
778 System.arraycopy(theObject, index, theObject, index+1, size - index );
779 theArray[index] = elValue;
780 theObject[index] = new ArrayList();
781 ((ArrayList)theObject[index]).add(o);
782 size++;
783 return true;
784 }
785 public int first()
786 {
787 if (tsindex >= size) return -1;
788 return theArray[tsindex];
789 }
790
791 public Object getFirst()
792 {
793 if (tsindex >= size) return null;
794 return theObject[tsindex];
795 }
796
797 public SimpleSortedSet tailSet(int elValue)
798 {
799 if (tsindex < theArray.length && elValue != theArray[tsindex])
800 {
801 if (tsindex<(size-1) && elValue > theArray[tsindex] &&
802 elValue <= theArray[tsindex+1])
803 {
804 tsindex++;
805 return this;
806 }
807 int index = java.util.Arrays.binarySearch(theArray, elValue);
808 if (index < 0)
809 index = ~index;
810 tsindex = index;
811 }
812 return this;
813 }
814
815 public boolean isEmpty()
816 {
817 return size ==0;
818 }
819 };
820 */