1
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 import debugger.resources.pr.TraceContainer;
31 import debugger.resources.pr.RuleTrace;
32 import debugger.resources.SPTLock;
33 import debugger.resources.PhaseController;
34
36
42 public class SinglePhaseTransducer
43 extends Transducer implements JapeConstants, java.io.Serializable
44 {
45
49 protected static class SearchState {
50 Node startNode;
51 long startNodeOff;
52 long oldStartNodeOff;
53
54 SearchState (Node startNode, long startNodeOff, long oldStartNodeOff) {
55 this.startNode = startNode;
56 this.startNodeOff = startNodeOff;
57 this.oldStartNodeOff = oldStartNodeOff;
58 }
59 }
60
61
62 private static final boolean DEBUG = false;
63
64 PhaseController phaseController = null;
66 TraceContainer rulesTrace = null;
67 RuleTrace currRuleTrace = null;
68
69 public PhaseController getPhaseController() {
70 return phaseController;
71 }
72
73 public void setPhaseController(PhaseController phaseController) {
74 this.phaseController = phaseController;
75 }
76
78
79
80 public SinglePhaseTransducer(String name) {
81 this.name = name;
82 rules = new PrioritisedRuleList();
83 finishedAlready = false;
84 }
86
87 protected int ruleApplicationStyle = BRILL_STYLE;
88
89
90 public void setRuleApplicationStyle(int style) {
91 ruleApplicationStyle = style;
92 }
93
94
98 protected PrioritisedRuleList rules;
99
100 protected FSM fsm;
101
102 public FSM getFSM(){
103 return fsm;
104 }
105
106
107 public void addRule(Rule rule) {
108 rules.add(rule);
109 }
111
112 private java.util.HashMap optionSettings = new java.util.HashMap();
113
114
117 public void setOption(String name, String setting) {
118 optionSettings.put(name, setting);
119 }
121
122 public String getOption(String name) {
123 return (String) optionSettings.get(name);
124 }
126
127 protected boolean finishedAlready;
128
129
132 public void finish(){
133 if (finishedAlready)
135 return;
136 finishedAlready = true;
137
138 Map actionClasses = new HashMap(rules.size());
141 for(Iterator i = rules.iterator(); i.hasNext(); ){
142 Rule rule = (Rule)i.next();
143 rule.finish();
144 actionClasses.put(rule.getRHS().getActionClassName(),
145 rule.getRHS().getActionClassString());
146 }
147 try{
148 gate.util.Javac.loadClasses(actionClasses);
149 }catch(Exception e){
150 throw new GateRuntimeException (e);
151 }
152
153 fsm = createFSM();
155 rules.clear();
157 rules = null;
158 }
160 protected FSM createFSM() {
161 return new FSM(this);
162 }
163
164 private void addAnnotationsByOffset( SimpleSortedSet keys, Set annotations){
167 Iterator annIter = annotations.iterator();
168 while(annIter.hasNext()){
169 Annotation ann = (Annotation)annIter.next();
170 long offset = ann.getStartNode().getOffset().longValue();
172 if(offset == ann.getEndNode().getOffset().longValue())
173 continue;
174
187 keys.add(offset, ann);
189 }
190 }
192
193
197 public void transduce(Document doc, AnnotationSet inputAS,
198 AnnotationSet outputAS) throws JapeException,
199 ExecutionException {
200 interrupted = false;
201 fireProgressChanged(0);
202
203 SimpleSortedSet offsets = new SimpleSortedSet();
206 SimpleSortedSet annotationsByOffset = offsets;
207
208 if(input.isEmpty()) {
210 addAnnotationsByOffset(offsets, inputAS);
211 } else {
212 Iterator typesIter = input.iterator();
213 AnnotationSet ofOneType = null;
214 while(typesIter.hasNext()){
215 ofOneType = inputAS.get((String)typesIter.next());
216 if(ofOneType != null){
217 addAnnotationsByOffset(offsets, ofOneType);
218 }
219 }
220 }
221
222 if(annotationsByOffset.isEmpty()){
223 fireProcessFinished();
224 return;
225 }
226
227 annotationsByOffset.sort();
228 java.util.ArrayList activeFSMInstances = new java.util.ArrayList();
231
232 java.util.ArrayList acceptingFSMInstances = new ArrayList();
236 FSMInstance currentFSM;
237
238
239 Node startNode = ((Annotation)
241 ((ArrayList)annotationsByOffset.get(offsets.first())).get(0)).
242 getStartNode();
243
244 long lastNodeOff = doc.getContent().size().longValue();
246
247 long startNodeOff = startNode.getOffset().longValue();
250
251 SearchState state = new SearchState(startNode, startNodeOff, 0);
253
254 if (gate.Gate.isEnableJapeDebug()) {
256 if (null != phaseController) {
258 rulesTrace = new TraceContainer();
259 rulesTrace.putPhaseCut(this, inputAS);
260 }
261 }
262
264 while(state.startNodeOff != -1){
266 currentFSM = new FSMInstance(
270 fsm,
271 fsm.getInitialState(), state.startNode, state.startNode, new java.util.HashMap(), doc
276 );
277
278 activeFSMInstances.clear();
280 acceptingFSMInstances.clear();
281 activeFSMInstances.add(currentFSM);
282
283 while(!activeFSMInstances.isEmpty()){
285
286 boolean isFinal = attemptAdvance(activeFSMInstances, acceptingFSMInstances,
287 offsets, annotationsByOffset, doc);
288
289 if ( isFinal && ruleApplicationStyle == FIRST_STYLE )
291 break;
292 }
293
294
295 boolean keepGoing = fireRule(acceptingFSMInstances, state,
296 lastNodeOff, offsets,
297 inputAS, outputAS, doc, annotationsByOffset);
298 if (!keepGoing)
299 return;
300
301 } fireProcessFinished();
303 }
305
309
310 protected boolean attemptAdvance (java.util.ArrayList activeFSMInstances,
311 java.util.ArrayList acceptingFSMInstances,
312 SimpleSortedSet offsets,
313 SimpleSortedSet annotationsByOffset,
314 Document doc
315 ) throws ExecutionInterruptedException {
316
317
318 if(interrupted) throw new ExecutionInterruptedException(
319 "The execution of the \"" + getName() +
320 "\" Jape transducer has been abruptly interrupted!");
321
322 FSMInstance currentFSM = (FSMInstance)activeFSMInstances.remove(0);
324
325 if(currentFSM.getFSMPosition().isFinal()){
327 acceptingFSMInstances.add(currentFSM.clone());
329
330 if (ruleApplicationStyle == FIRST_STYLE) return true; }
333
334 SimpleSortedSet offsetsTailSet = offsets.tailSet(currentFSM.
336 getAGPosition().getOffset().longValue());
337 ArrayList paths;
338 long theFirst = offsetsTailSet.first();
339 if(theFirst <0) return false;
340
341 paths = (ArrayList)annotationsByOffset.get(theFirst);
342
343 if(paths.isEmpty()) return false;
344
345 Iterator pathsIter = paths.iterator();
346 Annotation onePath;
347 State currentState = currentFSM.getFSMPosition();
348 Iterator transitionsIter;
349 while(pathsIter.hasNext()){
351 onePath = (Annotation)pathsIter.next();
352 transitionsIter = currentState.getTransitions().iterator();
353 Transition currentTransition;
354 Constraint[] currentConstraints;
355 transitionsWhile:
356 while(transitionsIter.hasNext()){
357 currentTransition = (Transition)transitionsIter.next();
358 currentConstraints =
360 currentTransition.getConstraints().getConstraints();
361
362 if (!onePath.getType().equals(currentConstraints[0].getAnnotType()) ||
366 !onePath.getFeatures().subsumes( ontology, currentConstraints[0].getAttributeSeq() )) {
367 continue transitionsWhile;
368 }
369
370 Constraint oneConstraint = currentConstraints[0];
371
372 if (currentConstraints.length > 1) {
375
381
382 int maxEnding = onePath.getEndNode().getOffset().intValue();
383
384 otherConstraints:
385 for (int i = 1; i < currentConstraints.length; i++) {
386 Constraint c = currentConstraints[i];
387
388 for (Iterator j = paths.iterator(); j.hasNext();) {
390 Annotation a = (Annotation) j.next();
391 if (a.getType().equals(c.getAnnotType()) &&
392 a.getFeatures().subsumes( ontology, c.getAttributeSeq())) {
393
394 if (a.getEndNode().getOffset().intValue() > maxEnding) {
395 onePath = a;
396 oneConstraint = c;
397 maxEnding = a.getEndNode().getOffset().intValue();
398 }
399 continue otherConstraints;
400 }
401 }
402 continue transitionsWhile;
404 }
405 }
406
407 FSMInstance newFSMI = (FSMInstance)currentFSM.clone();
411 newFSMI.setAGPosition(onePath.getEndNode());
412 newFSMI.setFSMPosition(currentTransition.getTarget());
413
414 if(gate.Gate.isEnableJapeDebug()) {
416 if (null != phaseController) {
417 currRuleTrace = rulesTrace.getStateContainer(currentFSM.
418 getFSMPosition());
419 if (currRuleTrace == null) {
420 currRuleTrace = new RuleTrace(newFSMI.getFSMPosition(), doc);
421 currRuleTrace.addAnnotation(onePath);
422 currRuleTrace.putPattern(onePath,
423 oneConstraint.getAttributeSeq());
424 rulesTrace.add(currRuleTrace);
425 }
426 else {
427 currRuleTrace.addState(newFSMI.getFSMPosition());
428 currRuleTrace.addAnnotation(onePath);
429 currRuleTrace.putPattern(onePath,
430 oneConstraint.getAttributeSeq());
431 }
432 }
433 }
434
436 java.util.Map binds = newFSMI.getBindings();
438 java.util.Iterator labelsIter =
439 currentTransition.getBindings().iterator();
440 String oneLabel;
441 AnnotationSet boundAnnots, newSet;
442 while(labelsIter.hasNext()){
443 oneLabel = (String)labelsIter.next();
444 boundAnnots = (AnnotationSet)binds.get(oneLabel);
445 if(boundAnnots != null)
446 newSet = new AnnotationSetImpl(boundAnnots);
447 else
448 newSet = new AnnotationSetImpl(doc);
449 newSet.add(onePath);
450 binds.put(oneLabel, newSet);
451
452 } activeFSMInstances.add(newFSMI);
454 } }
457 return false;
458 }
460
461
465
466 protected boolean fireRule (java.util.ArrayList acceptingFSMInstances,
467 SearchState state,
468 long lastNodeOff,
469 SimpleSortedSet offsets,
470 AnnotationSet inputAS,
471 AnnotationSet outputAS,
472 Document doc,
473 SimpleSortedSet annotationsByOffset
474 ) throws JapeException, ExecutionException {
475
476 Node startNode = state.startNode;
477 long startNodeOff = state.startNodeOff;
478 long oldStartNodeOff = state.oldStartNodeOff;
479
480 long lastAGPosition = -1;
482 if(acceptingFSMInstances.isEmpty()){
483 lastAGPosition = startNodeOff + 1;
485 } else if(ruleApplicationStyle == BRILL_STYLE ||
486 ruleApplicationStyle == ALL_STYLE) {
487 java.util.Iterator accFSMIter = acceptingFSMInstances.iterator();
489 FSMInstance currentAcceptor;
490 RightHandSide currentRHS;
491 lastAGPosition = startNode.getOffset().longValue();
492
493 while(accFSMIter.hasNext()){
494 currentAcceptor = (FSMInstance) accFSMIter.next();
495 currentRHS = currentAcceptor.getFSMPosition().getAction();
496
497 if (gate.Gate.isEnableJapeDebug()) {
500 if (null != phaseController) {
501 SPTLock lock = new SPTLock();
502 phaseController.TraceTransit(rulesTrace);
503 rulesTrace = new TraceContainer();
504 phaseController.RuleMatched(lock, this, currentRHS, doc,
505 currentAcceptor.getBindings(),
506 inputAS, outputAS);
507 }
508 }
509
511 currentRHS.transduce(doc, currentAcceptor.getBindings(),
512 inputAS, outputAS, ontology);
513
514 if (gate.Gate.isEnableJapeDebug()) {
517 if (null != phaseController) {
518 SPTLock lock = new SPTLock();
519 phaseController.RuleFinished(lock, this, currentRHS, doc,
520 currentAcceptor.getBindings(),
521 inputAS, outputAS);
522 }
523 }
524 if(ruleApplicationStyle == BRILL_STYLE){
526 long currentAGPosition = currentAcceptor.getAGPosition().getOffset().longValue();
528 if(currentAGPosition > lastAGPosition)
529 lastAGPosition = currentAGPosition;
530 }
531 }
532 if(ruleApplicationStyle == ALL_STYLE){
533 lastAGPosition = lastAGPosition + 1;
535 }
536
537 } else if(ruleApplicationStyle == APPELT_STYLE ||
538 ruleApplicationStyle == FIRST_STYLE ||
539 ruleApplicationStyle == ONCE_STYLE) {
540
541 Collections.sort(acceptingFSMInstances, Collections.reverseOrder());
544 Iterator accFSMIter = acceptingFSMInstances.iterator();
545 FSMInstance currentAcceptor = (FSMInstance)accFSMIter.next();
546 if(isDebugMode()){
547 Iterator accIter = acceptingFSMInstances.iterator();
549 FSMInstance anAcceptor;
550 List conflicts = new ArrayList();
551 while(accIter.hasNext()){
552 anAcceptor = (FSMInstance)accIter.next();
553 if(anAcceptor.equals(currentAcceptor)){
554 conflicts.add(anAcceptor);
555 }else{
556 break;
557 }
558 }
559 if(conflicts.size() > 1){
560 Out.prln("\nConflicts found during matching:" +
561 "\n================================");
562 accIter = conflicts.iterator();
563 int i = 0;
564 while(accIter.hasNext()){
565 Out.prln(i++ + ") " + accIter.next().toString());
566 }
567 }
568 }
569 RightHandSide currentRHS = currentAcceptor.getFSMPosition().getAction();
570
571 if(gate.Gate.isEnableJapeDebug()) {
574 if (null != phaseController) {
575 SPTLock lock = new SPTLock();
576 rulesTrace.leaveLast(currentRHS);
577 phaseController.TraceTransit(rulesTrace);
578 rulesTrace = new TraceContainer();
579 phaseController.RuleMatched(lock, this, currentRHS, doc,
580 currentAcceptor.getBindings(),
581 inputAS, outputAS);
582 }
583 }
584
586 currentRHS.transduce(doc, currentAcceptor.getBindings(),
587 inputAS, outputAS, ontology);
588
589 if(gate.Gate.isEnableJapeDebug()) {
592 if (null != phaseController) {
593 SPTLock lock = new SPTLock();
594 phaseController.RuleFinished(lock, this, currentRHS, doc,
595 currentAcceptor.getBindings(),
596 inputAS, outputAS);
597 }
598 }
599
601 if(isMatchGroupMode()) {
603 String currentAcceptorString = null;
607 multiModeWhile: while(accFSMIter.hasNext()) {
608 FSMInstance rivalAcceptor =(FSMInstance) accFSMIter.next();
609 if(rivalAcceptor.compareTo(currentAcceptor)==0){
613 if(!rivalAcceptor.equals(currentAcceptor)){
616 if (isDebugMode()){
617 if (currentAcceptorString == null) {
618 currentAcceptorString = currentAcceptor.toString();
620 Out.prln("~Jape Grammar Transducer : "+
621 "\nConcurrent Patterns by length,priority and index (all transduced):");
622 Out.prln(currentAcceptorString);
623 Out.prln("bindings : "+currentAcceptor.getBindings());
624 Out.prln("Rivals Follow: ");
625 }
626 Out.prln(rivalAcceptor);
627 Out.prln("bindings : "+rivalAcceptor.getBindings());
628 } currentRHS = rivalAcceptor.getFSMPosition().getAction();
630
631 if(gate.Gate.isEnableJapeDebug()) {
634 if (null != phaseController) {
635 SPTLock lock = new SPTLock();
636 rulesTrace.leaveLast(currentRHS);
637 phaseController.TraceTransit(rulesTrace);
638 rulesTrace = new TraceContainer();
639 phaseController.RuleMatched(lock, this, currentRHS, doc,
640 rivalAcceptor.getBindings(),
641 inputAS, outputAS);
642 }
643 }
644
646 currentRHS.transduce(doc, rivalAcceptor.getBindings(),
647 inputAS, outputAS, ontology);
648
649 if(gate.Gate.isEnableJapeDebug()) {
652 if (null != phaseController) {
653 SPTLock lock = new SPTLock();
654 phaseController.RuleFinished(lock, this, currentRHS, doc,
655 rivalAcceptor.getBindings(),
656 inputAS, outputAS);
657 }
658 }
659 } }else{
662 break multiModeWhile;
665 }
666 } }
669 if(ruleApplicationStyle == ONCE_STYLE) {
671 state.startNodeOff = startNodeOff;
672 return false;
673 }
674
675 lastAGPosition = currentAcceptor.getAGPosition().getOffset().longValue();
677 }else throw new RuntimeException("Unknown rule application style!");
678
679
680 SimpleSortedSet OffsetsTailSet = offsets.tailSet(lastAGPosition);
682 long theFirst = OffsetsTailSet.first();
683 if( theFirst < 0){
684 startNodeOff = -1;
686 fireProcessFinished();
687 }else{
688 long nextKey = theFirst;
689 startNode = ((Annotation)
690 ((ArrayList)annotationsByOffset.get(nextKey)).get(0)). getStartNode();
692 startNodeOff = startNode.getOffset().longValue();
693
694 if(oldStartNodeOff == startNodeOff){
696 lastAGPosition = startNodeOff + 1;
698 OffsetsTailSet = offsets.tailSet(lastAGPosition);
699 theFirst = OffsetsTailSet.first();
700 if(theFirst < 0){
701 startNodeOff = -1;
703 fireProcessFinished();
704 }else{
705 nextKey = theFirst;
706 startNode = ((Annotation)
707 ((List)annotationsByOffset.get(theFirst)).get(0)).
708 getStartNode();
709 startNodeOff =startNode.getOffset().longValue();
710 }
711 } if(startNodeOff - oldStartNodeOff > 256){
714 if(isInterrupted()) throw new ExecutionInterruptedException(
715 "The execution of the \"" + getName() +
716 "\" Jape transducer has been abruptly interrupted!");
717
718 fireProgressChanged((int)(100 * startNodeOff / lastNodeOff));
719 oldStartNodeOff = startNodeOff;
720 }
721 }
722
730 state.oldStartNodeOff = oldStartNodeOff;
731 state.startNodeOff = startNodeOff;
732 state.startNode = startNode;
733 return true;
734 }
736
737 public void cleanUp() {
738 }
742
743 public String toString() {
744 return toString("");
745 }
747
748 public String toString(String pad) {
749 String newline = Strings.getNl();
750 String newPad = Strings.addPadding(pad, INDENT_PADDING);
751
752 StringBuffer buf =
753 new StringBuffer(pad + "SPT: name(" + name + "); ruleApplicationStyle(");
754
755 switch(ruleApplicationStyle) {
756 case APPELT_STYLE: buf.append("APPELT_STYLE); "); break;
757 case BRILL_STYLE: buf.append("BRILL_STYLE); "); break;
758 default: break;
759 }
760
761 buf.append("rules(" + newline);
762 Iterator rulesIterator = rules.iterator();
763 while(rulesIterator.hasNext())
764 buf.append(((Rule) rulesIterator.next()).toString(newPad) + " ");
765
766 buf.append(newline + pad + ")." + newline);
767
768 return buf.toString();
769 }
771 public PrioritisedRuleList getRules() {
773 return rules;
774 }
775
776
782 public void addInput(String ident) {
783 input.add(ident);
784 }
785 public synchronized void removeProgressListener(ProgressListener l) {
786 if (progressListeners != null && progressListeners.contains(l)) {
787 Vector v = (Vector) progressListeners.clone();
788 v.removeElement(l);
789 progressListeners = v;
790 }
791 }
792 public synchronized void addProgressListener(ProgressListener l) {
793 Vector v = progressListeners == null ? new Vector(2) : (Vector) progressListeners.clone();
794 if (!v.contains(l)) {
795 v.addElement(l);
796 progressListeners = v;
797 }
798 }
799
800
806 public java.util.Set input = new java.util.HashSet();
808 private transient Vector progressListeners;
811
812 protected void fireProgressChanged(int e) {
813 if (progressListeners != null) {
814 Vector listeners = progressListeners;
815 int count = listeners.size();
816 for (int i = 0; i < count; i++) {
817 ((ProgressListener) listeners.elementAt(i)).progressChanged(e);
818 }
819 }
820 }
821 protected void fireProcessFinished() {
822 if (progressListeners != null) {
823 Vector listeners = progressListeners;
824 int count = listeners.size();
825 for (int i = 0; i < count; i++) {
826 ((ProgressListener) listeners.elementAt(i)).processFinished();
827 }
828 }
829 }
830 public int getRuleApplicationStyle() {
831 return ruleApplicationStyle;
832 }
833
834
841
842
843 }
845
933