1   package debugger.gui.debugging;
2   
3   import debugger.gui.GuiFactory;
4   import debugger.gui.debugging.debugviews.PrimaryTextPanel;
5   import debugger.resources.ResourcesFactory;
6   import debugger.resources.pr.PhaseModel;
7   import debugger.resources.pr.RuleModel;
8   import debugger.resources.pr.RuleTrace;
9   import debugger.resources.pr.TraceContainer;
10  import gate.Annotation;
11  import gate.AnnotationSet;
12  import gate.Document;
13  import gate.FeatureMap;
14  import gate.util.InvalidOffsetException;
15  import gate.util.OffsetComparator;
16  
17  import javax.swing.*;
18  import javax.swing.text.DefaultCaret;
19  import javax.swing.text.StyledEditorKit;
20  import java.awt.*;
21  import java.awt.event.ActionEvent;
22  import java.awt.event.ActionListener;
23  import java.util.*;
24  
25  /**
26   * Copyright (c) Ontos AG (http://www.ontosearch.com).
27   * This class is part of JAPE Debugger component for
28   * GATE (Copyright (c) "The University of Sheffield" see http://gate.ac.uk/) <br>
29   * This class creates GUI of debugging (now TraceHistory) part of JAPEDebugger.
30   * @author Andrey Shafirin, Vladimir Karasev
31   */
32  
33  public class TraceHistoryPanel extends JPanel {
34      private JPanel rulePanel;
35      private JLabel phaseName;
36      private JLabel ruleName;
37      private JTextPane selectedTextPane;
38      private JTextPane rulePane;
39      private JButton nextAnnotationButton;
40      private JButton previousAnnotationButton;
41  
42      private PhaseModel currentPhaseModel;
43      private RuleModel currentRuleModel;
44      private TraceContainer traceContainer;
45      private Document document;
46      private int currentStartOffset;
47      private int currentEndOffset;
48      private TraceContainer currentTraces;
49      private RuleTrace currentRuleTrace;
50      private AnnotationSet currentAnnotationCut;
51  
52      public TraceHistoryPanel() {
53          initGui();
54      }
55  
56      private void initGui() {
57          this.setLayout(new GridBagLayout());
58          GridBagConstraints c = new GridBagConstraints();
59  
60          c.gridx = 0;
61          c.gridy = 0;
62          c.weightx = 0;
63          c.weighty = 0;
64          c.gridwidth = 1;
65          c.fill = GridBagConstraints.HORIZONTAL;
66          this.add(getUpperPanel(), c);
67  
68          c.gridx = 0;
69          c.gridy = 1;
70          c.weightx = 1;
71          c.weighty = 1;
72          c.gridwidth = 1;
73          c.fill = GridBagConstraints.BOTH;
74  
75          JScrollPane ruleScrollPane = new JScrollPane(getRulePane(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
76          ruleScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Rule Text"));
77  
78          JScrollPane panelScrollPane = new JScrollPane(getRulePanel(), JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
79          panelScrollPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Rule"));
80  
81          JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, panelScrollPane, ruleScrollPane);
82          splitPane.setDividerLocation(200);
83  //        JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, splitPane, getSelectedTextPane());
84  //        sp.setDividerLocation(300);
85  //        this.add(sp, c);
86          this.add(splitPane, c);
87          c.gridy = 2;
88          c.weighty = 0;
89          c.fill = GridBagConstraints.NONE;
90  //        this.add(getSelectedTextPane(), c);
91      }
92  
93      private JTextPane getRulePane() {
94          if (rulePane == null) {
95              rulePane = new JTextPane();
96              rulePane.setEditorKit(new StyledEditorKit());
97              rulePane.setDocument(new SyntaxDocument());
98              rulePane.setEditable(false);
99              // prevents autoscrolling of the caret
100             rulePane.setCaret(new DefaultCaret() {
101                 protected void adjustVisibility(Rectangle nloc) {
102                 }
103             });
104         }
105         return rulePane;
106     }
107 
108     private JComponent getSelectedTextPane() {
109         selectedTextPane = new JTextPane();
110         selectedTextPane.setEditable(false);
111         // prevents autoscrolling of the caret
112         selectedTextPane.setCaret(new DefaultCaret() {
113             protected void adjustVisibility(Rectangle nloc) {
114             }
115         });
116         nextAnnotationButton = new JButton("Next");
117         previousAnnotationButton = new JButton("Previous");
118         JPanel panel = new JPanel(new GridBagLayout());
119         GridBagConstraints c = new GridBagConstraints();
120         c.fill = GridBagConstraints.BOTH;
121         c.gridx = 0;
122         c.gridy = 0;
123         c.weightx = 1;
124         c.weighty = 1;
125 //        panel.add(selectedTextPane, c);
126         c.fill = GridBagConstraints.NONE;
127         c.gridx = 0;//1;
128         c.weightx = 0;
129         c.weighty = 0;
130         panel.add(previousAnnotationButton, c);
131         previousAnnotationButton.setEnabled(false);
132         previousAnnotationButton.addActionListener(new ActionListener() {
133             public void actionPerformed(ActionEvent e) {
134                 if (currentTraces != null && currentRuleModel != null && currentRuleTrace != null) {
135                     int index = currentTraces.lastIndexOf(currentRuleTrace);
136                     if (index > 0) {
137                         updateRulePanel(currentRuleModel, (RuleTrace) currentTraces.get(index - 1));
138                         currentRuleTrace = (RuleTrace) currentTraces.get(index - 1);
139                     }
140                     if (index - 1 == 0) {
141                         previousAnnotationButton.setEnabled(false);
142                     } else {
143                         previousAnnotationButton.setEnabled(true);
144                     }
145                     if (index < currentTraces.size() && currentTraces.size() > 1) {
146                         nextAnnotationButton.setEnabled(true);
147                     }
148                 }
149                 GuiFactory.getResourceView().repaint();
150             }
151         });
152         c.gridx = 1;//2;
153         panel.add(nextAnnotationButton, c);
154         nextAnnotationButton.setEnabled(false);
155         nextAnnotationButton.addActionListener(new ActionListener() {
156             public void actionPerformed(ActionEvent e) {
157                 if (currentTraces != null && currentRuleModel != null && currentRuleTrace != null) {
158                     int index = currentTraces.lastIndexOf(currentRuleTrace);
159                     if (index + 1 < currentTraces.size()) {
160                         updateRulePanel(currentRuleModel, (RuleTrace) currentTraces.get(index + 1));
161                         currentRuleTrace = (RuleTrace) currentTraces.get(index + 1);
162                     }
163                     if (index + 2 >= currentTraces.size()) {
164                         nextAnnotationButton.setEnabled(false);
165                     } else {
166                         nextAnnotationButton.setEnabled(true);
167                     }
168                     if (index + 1 > 0) {
169                         previousAnnotationButton.setEnabled(true);
170                     }
171                     GuiFactory.getResourceView().repaint();
172                 }
173             }
174         });
175         return panel;
176     }
177 
178     private JComponent getRulePanel() {
179         if (rulePanel == null) {
180             rulePanel = new JPanel();
181         }
182         return rulePanel;
183     }
184 
185     private JComponent getUpperPanel() {
186         JPanel panel = new JPanel(new GridBagLayout());
187         GridBagConstraints c = new GridBagConstraints();
188         c.gridx = 0;
189         c.gridy = 0;
190         c.weightx = 0;
191         c.weighty = 0;
192         c.anchor = GridBagConstraints.WEST;
193         c.insets = new Insets(0, 4, 0, 0);
194         panel.add(new JLabel("Rule: "), c);
195 
196         c.gridx = 1;
197         ruleName = new JLabel();
198         panel.add(ruleName, c);
199 
200         c.gridx = 2;
201         c.weightx = 1;
202         panel.add(new JPanel(), c);
203         c.gridx = 3;
204         c.weightx = 0;
205         panel.add(new JPanel(), c);
206         c.gridx = 3;
207         c.gridwidth = 2;
208         panel.add(new JPanel(), c);
209 
210         c.gridx = 0;
211         c.gridy = 1;
212         c.weightx = 1;
213         c.gridwidth = 3;
214         panel.add(new JPanel(), c);
215 
216         c.gridwidth = 1;
217         c.gridx = 3;
218         c.weightx = 0;
219         c.anchor = GridBagConstraints.EAST;
220         panel.add(new JLabel("Phase: "), c);
221 
222         c.gridx = 4;
223         phaseName = new JLabel();
224         panel.add(phaseName, c);
225 
226         c.gridx = 0;
227         c.gridy = 2;
228         c.weightx = 0;
229         c.weighty = 0;
230         c.gridwidth = 2;
231         c.fill = GridBagConstraints.NONE;
232         c.anchor = GridBagConstraints.WEST;
233         c.insets = new Insets(0, 0, 4, 0);
234         panel.add(getSelectedTextPane(), c);
235 
236         return panel;
237     }
238 
239     /**
240      * This method is called from <code>ShowResultAction</code> action, when user selects
241      * text, on which he'd like to see the results of matching the rules.
242      * @param startOffset
243      * @param endOffset
244      * @param document
245      */
246     public void setText(int startOffset, int endOffset, Document document) {
247         TraceContainer traceContainer = ResourcesFactory.getPhaseController().getRuleTrace();
248         traceContainer = traceContainer.getTraceByOffset(new Long(startOffset), new Long(endOffset));
249         try {
250             this.selectedTextPane.setText(
251                 document.getContent().getContent(new Long(min(startOffset,
252                     document.getContent().size().longValue() - 1L)), 
253                     new Long(min(endOffset, 
254                         document.getContent().size().longValue() - 1L)))
255               .toString());
256         } catch (InvalidOffsetException e) {
257           System.out.println("Start offset = "+startOffset+
258               "End offset = "+endOffset);
259           System.out.println("Document size = "+document.getContent().size());
260             e.printStackTrace();
261         }
262         this.traceContainer = traceContainer;
263         this.document = document;
264         this.currentStartOffset = startOffset;
265         this.currentEndOffset = endOffset;
266         //////
267         this.updateRulePanel(null, null);
268         //////
269         this.repaint();
270     }
271 
272     /**
273      * Return whichever of two longs has the smallest value.
274      * 
275      * @param a The first of the longs.
276      * @param b The second of the longs.
277      * @return The value of the long that's smallest.
278      */
279     private long min(long a, long b) {
280       if (a < b) 
281         return a;
282       else
283         return b;
284     }
285     
286     /**
287      * This method creates a panel with annotations of the given input type, which are
288      * contained in a selected interval. All of the annotations which matched in the
289      * current selected rule are highlighted. (Input type is one of the inputs in the phase, to
290      * which current rule belongs.)
291      * @param annotations <code>AnnotationSet</code> with annotations of the given input type
292      *        from a selected interval (offsets are <code>currentStartOffset</code> and
293      *        <code>currentEndOffset</code>)
294      * @param annotationsType type of annotations, i.e. Lookup, Morph
295      * @param ruleTrace <code>RuleTrace</code> of currently selected rule, can be null,
296      *        if no rule is selected
297      * @param withHighlighting whether highlighting is on/off
298      * @return
299      */
300     private JComponent createAnnotationPanel(AnnotationSet annotations, String annotationsType, RuleTrace ruleTrace, boolean withHighlighting) {
301         JPanel panel = new JPanel(new GridBagLayout());
302         GridBagConstraints c = new GridBagConstraints();
303 
304         c.gridx = 0;
305         c.gridy = 0;
306         c.weightx = 0;
307         c.weighty = 0;
308         c.gridwidth = 1;
309         c.gridheight = 1;
310         c.anchor = GridBagConstraints.WEST;
311         c.fill = GridBagConstraints.NONE;
312 
313         // Matched annotations
314         AnnotationSet annotationsToHighlight = null;
315         if (ruleTrace != null) {
316             annotationsToHighlight = ruleTrace.getAnnotations();
317         }
318 
319         long lastNodeOffset = 0;
320         if (annotationsToHighlight != null) {
321             lastNodeOffset = annotationsToHighlight.lastNode().getOffset().longValue();
322         }
323 
324         // Annotations to display
325         HashSet annotationsToShowSet = new HashSet();
326         if (annotations != null) {
327             annotationsToShowSet.addAll(annotations);
328         }
329 
330         // Add some Token annotations to displayed annotations
331         HashSet tokensNotToBeIncluded = new HashSet();
332         for (Iterator it = annotationsToShowSet.iterator(); it.hasNext();) {
333             Annotation currentAnnotation = (Annotation) it.next();
334             AnnotationSet containedTokens = currentAnnotationCut.getContained(currentAnnotation.getStartNode().getOffset(), currentAnnotation.getEndNode().getOffset()).get("Token");
335             if (containedTokens != null) {
336                 tokensNotToBeIncluded.addAll(containedTokens);
337             }
338         }
339         AnnotationSet tokenAnnotationSet = currentAnnotationCut.get("Token", new Long(currentStartOffset), new Long(currentEndOffset));
340         if (tokenAnnotationSet != null) {
341             for (Iterator it = tokenAnnotationSet.iterator(); it.hasNext();) {
342                 Annotation currentAnnotation = (Annotation) it.next();
343                 if (!tokensNotToBeIncluded.contains(currentAnnotation)) {
344                     annotationsToShowSet.add(currentAnnotation);
345                 }
346             }
347         }
348         // end of adding tokens
349 
350         // Now let's sort all the annotations we'd like to display
351         ArrayList list = new ArrayList(annotationsToShowSet);
352         Collections.sort(list, new OffsetComparator());
353         /*
354          * Offset comparator doesn't always work as
355          * we need - the longest annotation with
356          * the same start offset should ALWAYS be first.
357          * So I have to use my own comparator.
358          */
359         Collections.sort(list, new Comparator() {
360             public int compare(Object o1, Object o2) {
361                 Annotation a1 = (Annotation) o1;
362                 Annotation a2 = (Annotation) o2;
363                 long offset1 = a1.getStartNode().getOffset().longValue();
364                 long offset2 = a2.getStartNode().getOffset().longValue();
365                 long length1 = a1.getEndNode().getOffset().longValue() - offset1;
366                 long length2 = a2.getEndNode().getOffset().longValue() - offset2;
367                 if (offset1 > offset2) {
368                     return 1;
369                 }
370                 if (offset1 < offset2) {
371                     return -1;
372                 }
373                 if (offset1 == offset2) {
374                     if (length1 > length2)
375                         return -1;
376                     else if (length1 < length2)
377                         return 1;
378                     else
379                         return 0;
380                 }
381                 return 0;
382             }
383         });
384         // end of sorting
385 
386         // Annotations of the same type, which should not be displayed -
387         // for example, if we have several lookups - only one lookup should be displayed
388         ArrayList annotationsToIgnore = new ArrayList();
389         boolean isRedSet = false;
390 
391         int x = 0;
392         for (Iterator it = list.iterator(); it.hasNext();) {
393             Annotation currentAnnotation = (Annotation) it.next();
394 
395             // Get annotations of the same type with the same offsets and leave only one to display
396             AnnotationSet containedAnnotationsOfTheSameType = currentAnnotationCut.getContained(currentAnnotation.getStartNode().getOffset(), currentAnnotation.getEndNode().getOffset()).get(annotationsType);
397             if (containedAnnotationsOfTheSameType != null) {
398                 for (Iterator iter = containedAnnotationsOfTheSameType.iterator(); iter.hasNext();) {
399                     Annotation ann = (Annotation) iter.next();
400                     if (!ann.equals(currentAnnotation)) {
401                         annotationsToIgnore.add(ann);
402                     }
403                 }
404             }
405 
406             // I get text to display from the Token annotations
407             AnnotationSet containedTokens = currentAnnotationCut.getContained(currentAnnotation.getStartNode().getOffset(), currentAnnotation.getEndNode().getOffset()).get("Token");
408             ArrayList containedTokensList = null;
409             if (containedTokens != null) {
410                 containedTokensList = new ArrayList(containedTokens);
411             } else {
412                 containedTokensList = new ArrayList();
413             }
414             Collections.sort(containedTokensList, new OffsetComparator());
415 
416             // This variable shows the number of the created panel in a row
417             int order = 0;
418             if (!annotationsToIgnore.contains(currentAnnotation)) {
419                 // At last we create the panels with (or without) text on them
420                 for (Iterator iter = containedTokensList.iterator(); iter.hasNext();) {
421                     Annotation currentTokenAnnotation = (Annotation) iter.next();
422                     String text = (String) currentTokenAnnotation.getFeatures().get("string");
423                     PrimaryTextPanel textPanel = new PrimaryTextPanel(text, false, PrimaryTextPanel.OPEN_NONE);
424                     if (containedAnnotationsOfTheSameType != null) {
425                         textPanel.setAnnotations(new ArrayList(containedAnnotationsOfTheSameType));
426                     } else {
427                         ArrayList arr = new ArrayList();
428                         arr.add(currentAnnotation);
429                         textPanel.setAnnotations(arr);
430                     }
431                     if (containedTokens.size() == 1) {
432                         textPanel.setOpenMode(PrimaryTextPanel.OPEN_NONE);
433                     } else if (order == 0 && containedTokens.size() > 1) {
434                         textPanel.setOpenMode(PrimaryTextPanel.OPEN_RIGHT);
435                     } else if (order == (containedTokens.size() - 1)) {
436                         textPanel.setOpenMode(PrimaryTextPanel.OPEN_LEFT);
437                     } else {
438                         textPanel.setOpenMode(PrimaryTextPanel.OPEN_BOTH);
439                     }
440 
441                     // highlighting
442                     if (currentTokenAnnotation.equals(currentAnnotation) && !annotationsType.equals("Token")) {
443                         textPanel.setTextVisible(false);
444                     }
445                     if (annotationsToHighlight != null && annotationsToHighlight.contains(currentAnnotation) && textPanel.isTextVisible() && withHighlighting) {
446                         textPanel.setHighlighted(true);
447                     }
448                     if (containedAnnotationsOfTheSameType != null) {
449                         for (Iterator iterator = containedAnnotationsOfTheSameType.iterator(); iterator.hasNext();) {
450                             Annotation a = (Annotation) iterator.next();
451                             if (annotationsToHighlight != null && annotationsToHighlight.contains(a) && textPanel.isTextVisible()) {
452                                 int startOffset = a.getStartNode().getOffset().intValue();
453                                 int endOffset = a.getEndNode().getOffset().intValue();
454                                 int tokenStartOffset = currentTokenAnnotation.getStartNode().getOffset().intValue();
455                                 int tokenEndOffset = currentTokenAnnotation.getEndNode().getOffset().intValue();
456                                 if (startOffset <= tokenStartOffset && tokenEndOffset <= endOffset && endOffset >= tokenStartOffset && withHighlighting) {
457                                     textPanel.setHighlighted(true);
458                                 }
459                             }
460                         }
461                     }
462                     if (ruleTrace != null && !ruleTrace.isFinished() && currentAnnotation.getStartNode().getOffset().longValue() >= lastNodeOffset
463                             && !isRedSet && textPanel.isTextVisible() && withHighlighting) {
464                         textPanel.setRed(true);
465                         if (textPanel.getOpenMode() == PrimaryTextPanel.OPEN_NONE || textPanel.getOpenMode() == PrimaryTextPanel.OPEN_LEFT) {
466                             isRedSet = true;
467                         }
468                     }
469                     // end of highlighting
470 
471                     // Set standard annotation tooltip - annotation's features
472                     String toolTipText = "";
473                     FeatureMap featureMap = null;
474                     if (ruleTrace != null) {
475                         featureMap = ruleTrace.getPattern(currentAnnotation);
476                     }
477                     if (featureMap == null && containedAnnotationsOfTheSameType != null) {
478                         if (ruleTrace != null) {
479                             for (Iterator iterator = containedAnnotationsOfTheSameType.iterator(); iterator.hasNext();) {
480                                 featureMap = ruleTrace.getPattern((Annotation) iterator.next());
481                                 if (featureMap != null)
482                                     break;
483                             }
484                         }
485                     }
486                     if (featureMap != null) {
487                         for (Iterator i = featureMap.keySet().iterator(); i.hasNext();) {
488                             toolTipText = toolTipText + " " + annotationsType + ".";
489                             Object key = i.next();
490                             toolTipText = toolTipText + key + "=" + featureMap.get(key);
491                         }
492                         if (featureMap.keySet().isEmpty()) {
493                             toolTipText = annotationsType;
494                         }
495                     }
496                     if (featureMap != null && textPanel.isTextVisible() && (textPanel.isHighlighted() || textPanel.isRed())
497                             && withHighlighting) {
498                         textPanel.setToolTipText(toolTipText);
499                     }
500                     // end of setting tooltip
501 
502                     c.gridx = x;
503                     panel.add(textPanel, c);
504                     order++;
505                     x++;
506                 }
507             }
508         }
509         return panel;
510     }
511 
512     /**
513      * Creates panels with input annotations.
514      * @param ruleModel
515      * @param currentTrace
516      */
517     public void updateRulePanel(RuleModel ruleModel, RuleTrace currentTrace) {
518         if (ruleModel != null) {
519             rulePane.setText(ruleModel.getRuleText());
520         }
521         RuleTrace ruleTrace = null;
522         if (currentTrace == null && traceContainer != null) {
523             if (traceContainer != null) {
524                 TraceContainer traces = traceContainer.getTraceByRuleModel(ruleModel);
525                 if (traces.size() > 0) {
526                     ruleTrace = (RuleTrace) traces.iterator().next();
527                 }
528                 previousAnnotationButton.setEnabled(false);
529                 nextAnnotationButton.setEnabled(false);
530                 if (traces.size() > 1) {
531                     nextAnnotationButton.setEnabled(true);
532                 }
533                 currentTraces = traces;
534                 currentRuleTrace = ruleTrace;
535             }
536         } else {
537             ruleTrace = currentTrace;
538             currentRuleTrace = ruleTrace;
539         }
540         if (traceContainer != null) {
541             currentAnnotationCut = traceContainer.getPhaseCut(currentPhaseModel);
542             JPanel panel = new JPanel();
543             panel.setLayout(new GridBagLayout());
544             GridBagConstraints c = new GridBagConstraints();
545             int i = 0;
546             c.anchor = GridBagConstraints.WEST;
547             c.insets = new Insets(2, 4, 2, 4);
548             // Create input panels
549             if (currentPhaseModel != null) {
550                 for (Iterator it = currentPhaseModel.getInput().iterator(); it.hasNext();) {
551                     String input = (String) it.next();
552                     c.fill = GridBagConstraints.NONE;
553                     c.gridx = 0;
554                     c.weightx = 0;
555                     c.gridy = i++;
556                     panel.add(new JLabel(input), c);
557                     c.gridx = 1;
558                     if (currentAnnotationCut != null) {
559                         panel.add(createAnnotationPanel(currentAnnotationCut.get(input, new Long(currentStartOffset), new Long(currentEndOffset)), input, ruleTrace, true), c);
560                     } else {
561                         panel.add(new JLabel("No annotations of type " + input + " available"), c);
562                     }
563                     c.gridx = 2;
564                     c.weightx = 1;
565                     c.fill = GridBagConstraints.HORIZONTAL;
566                     panel.add(new JPanel(), c);
567                 }
568             }
569             //end of creating input panels
570 
571             // Add divider
572             c.gridx = 0;
573             c.gridy = i;
574             c.weightx = 0;
575             c.weighty = 0;
576             c.gridwidth = 2;
577             panel.add(new JPanel() {
578                 {
579                     this.setBackground(Color.black);
580                 }
581 
582                 public Dimension getPreferredSize() {
583                     return getMaximumSize();
584                 }
585 
586                 public Dimension getMaximumSize() {
587                     return new Dimension(20, 2);
588                 }
589             },
590                     c);
591             c.gridx = 1;
592             c.weightx = 1;
593             c.gridy = i++;
594             panel.add(new JPanel(), c);
595             // end of creating divider
596 
597             // Create additional token panel
598             c.fill = GridBagConstraints.NONE;
599             c.gridx = 0;
600             c.weightx = 0;
601             c.gridy = i++;
602             panel.add(new JLabel(""), c);
603             c.gridx = 1;
604             if (document.getAnnotations().getContained(new Long(currentStartOffset), new Long(currentEndOffset)).get("Token") != null) {
605                 if (currentAnnotationCut == null) {
606                     currentAnnotationCut = document.getAnnotations().getContained(new Long(currentStartOffset), new Long(currentEndOffset)).get("Token");
607                 }
608                 panel.add(createAnnotationPanel(document.getAnnotations().getContained(new Long(currentStartOffset), new Long(currentEndOffset)).get("Token"), "Token", ruleTrace, false), c);
609             } else {
610                 panel.add(new JLabel("No annotations of type Token available"), c);
611             }
612             c.gridx = 2;
613             c.weightx = 1;
614             c.fill = GridBagConstraints.HORIZONTAL;
615             panel.add(new JPanel(), c);
616             // end of creating additional token panel
617 
618             // this panel is added to keep annotation panels on the top
619             c.gridx = 0;
620             c.gridy = i++;
621             c.weightx = 0;
622             c.weighty = 1;
623             panel.add(new JPanel(), c);
624 
625             // save changes
626             getRulePanel().removeAll();
627             getRulePanel().setLayout(new BorderLayout());
628             getRulePanel().add(panel, BorderLayout.CENTER);
629             this.revalidate();
630 
631 //            int startOffset = (int)ruleTrace.getAnnotations().firstNode().getOffset().longValue() - currentStartOffset;
632 //            int length = (int)ruleTrace.getAnnotations().lastNode().getOffset().longValue() -
633 //                    (int)ruleTrace.getAnnotations().firstNode().getOffset().longValue();
634 //            MutableAttributeSet attributeSet = new SimpleAttributeSet();
635 //            StyleConstants.setBackground(attributeSet, Color.white);
636 //            if(startOffset < 0) startOffset = 0;
637 // some bugs here...
638 //            ((DefaultStyledDocument) selectedTextPane.getDocument()).setCharacterAttributes(0, selectedTextPane.getText().length(), attributeSet, false);
639 //            StyleConstants.setBackground(attributeSet, Color.lightGray);
640 //            ((DefaultStyledDocument) selectedTextPane.getDocument()).setCharacterAttributes(0, startOffset, attributeSet, true);
641 //            StyleConstants.setBackground(attributeSet, Color.cyan);
642 //            ((DefaultStyledDocument) selectedTextPane.getDocument()).setCharacterAttributes(startOffset, length, attributeSet, false);
643         }
644 //        else
645 //        {
646 //            getRulePanel().removeAll();
647 //            getRulePanel().add(new JLabel("No annotations available"));
648 //            this.revalidate();
649 //        }
650     }
651 
652     /**
653      * Updates panel after
654      * user has selected a rule in the ResourceTree.
655      * @param ruleModel <code>RuleModel</code> which user has selected in the resources tree
656      * @see RuleModel
657      * @see debugger.gui.resources.ResourceTree
658      */
659     public void setCurrentRule(RuleModel ruleModel) {
660         currentRuleModel = ruleModel;
661         currentPhaseModel = ruleModel.getParentPhase();
662         phaseName.setText(currentPhaseModel.getName() + "   Control = " + currentPhaseModel.getControl());
663         ruleName.setText(ruleModel.getName());
664     }
665 
666     /**
667      * Updates panel after
668      * user has selected a phase in the ResourceTree.
669      * @param phaseModel <code>PhaseModel</code> which user has selected in the resources tree
670      * @see PhaseModel
671      * @see debugger.gui.resources.ResourceTree
672      */
673     public void setCurrentPhase(PhaseModel phaseModel) {
674         currentPhaseModel = phaseModel;
675         phaseName.setText(currentPhaseModel.getName() + "   Control = " + currentPhaseModel.getControl());
676         if (currentRuleModel != null && !currentRuleModel.getParentPhase().equals(currentPhaseModel)) {
677             getRulePanel().removeAll();
678             getRulePanel().add(new JLabel("No rule currently selected."));
679         }
680         ruleName.setText("");
681     }
682 
683     /**
684      * This method should be deleted later - it violates the architecture.
685      * @return
686      */
687     public RuleTrace getCurrentRuleTrace() {
688         return currentRuleTrace;
689     }
690 
691     /**
692      * This method should be deleted later - it violates the architecture.
693      * @return
694      */
695     public RuleModel getCurrentRuleModel() {
696         return currentRuleModel;
697     }
698 }
699