1   /*
2    *  Copyright (c) 1998-2005, The University of Sheffield.
3    *
4    *  This file is part of GATE (see http://gate.ac.uk/), and is free
5    *  software, licenced under the GNU Library General Public License,
6    *  Version 2, June 1991 (in the distribution as file licence.html,
7    *  and also available at http://gate.ac.uk/gate/licence.html).
8    *
9    *  CorefEditor.java
10   *
11   *  Niraj Aswani, 24-Jun-2004
12   *
13   *  $Id: CorefEditor.java,v 1.20 2005/10/17 17:23:04 ian_roberts Exp $
14   */
15  
16  package gate.gui.docview;
17  
18  import java.awt.*;
19  import javax.swing.*;
20  import javax.swing.tree.*;
21  import javax.swing.event.*;
22  import java.util.*;
23  import gate.*;
24  import gate.creole.*;
25  import java.io.*;
26  import java.awt.event.*;
27  import gate.swing.*;
28  import gate.event.*;
29  import javax.swing.text.Highlighter;
30  import javax.swing.text.DefaultHighlighter;
31  
32  public class CorefEditor
33      extends AbstractDocumentView
34      implements ActionListener, gate.event.FeatureMapListener,
35      gate.event.DocumentListener, AnnotationSetListener {
36  
37    // default AnnotationSet Name
38    private final static String DEFAULT_ANNOTSET_NAME = "Default";
39  
40    private JPanel mainPanel, topPanel, subPanel;
41    private JToggleButton showAnnotations;
42    private JComboBox annotSets, annotTypes;
43    private DefaultComboBoxModel annotSetsModel, annotTypesModel;
44  
45    // Co-reference Tree
46    private JTree corefTree;
47  
48    // Root node
49    private CorefTreeNode rootNode;
50  
51    // top level hashMap (corefChains)
52    // AnnotationSet(CorefTreeNode) --> (CorefTreeNode type ChainNode --> ArrayList AnnotationIds)
53    private HashMap corefChains;
54  
55    // This is used to store the annotationSet name and its respective corefTreeNode
56    // annotationSetName --> CorefTreeNode of type (AnnotationSet)
57    private HashMap corefAnnotationSetNodesMap;
58  
59    // annotationSetName --> (chainNodeString --> Boolean)
60    private HashMap selectionChainsMap;
61  
62    // chainString --> Boolean
63    private HashMap currentSelections;
64  
65    // annotationSetName --> (chainNodeString --> Color)
66    private HashMap colorChainsMap;
67  
68    // chainNodeString --> Color
69    private HashMap currentColors;
70  
71    private ColorGenerator colorGenerator;
72    private TextualDocumentView textView;
73    private JEditorPane textPane;
74  
75    /* ChainNode --> (HighlightedTags) */
76    private HashMap highlightedTags;
77  
78    /* This arraylist stores the highlighted tags for the specific selected annotation type */
79    private ArrayList typeSpecificHighlightedTags;
80    private TextPaneMouseListener textPaneMouseListener;
81  
82    /* This stores Ids of the highlighted Chain Annotations*/
83    private ArrayList highlightedChainAnnots = new ArrayList();
84    /* This stores start and end offsets of the highlightedChainAnnotations */
85    private int[] highlightedChainAnnotsOffsets;
86  
87    /* This stores Ids of the highlighted Annotations of particular type */
88    private ArrayList highlightedTypeAnnots = new ArrayList();
89    /* This stores start and end offsets of highlightedTypeAnnots */
90    private int[] highlightedTypeAnnotsOffsets;
91  
92    /* Timer for the Chain Tool tip action */
93    private ChainToolTipAction chainToolTipAction;
94    private javax.swing.Timer chainToolTipTimer;
95  
96    private NewCorefAction newCorefAction;
97    private javax.swing.Timer newCorefActionTimer;
98  
99    private Annotation annotToConsiderForChain = null;
100   private JWindow popupWindow;
101   private boolean explicitCall = false;
102   private Highlighter highlighter;
103 
104   /**
105    * This method intiates the GUI for co-reference editor
106    */
107   protected void initGUI() {
108 
109     //get a pointer to the textual view used for highlights
110     Iterator centralViewsIter = owner.getCentralViews().iterator();
111     while (textView == null && centralViewsIter.hasNext()) {
112       DocumentView aView = (DocumentView) centralViewsIter.next();
113       if (aView instanceof TextualDocumentView)
114         textView = (TextualDocumentView) aView;
115     }
116     textPane = (JEditorPane) ( (JScrollPane) textView.getGUI()).getViewport().
117                getView();
118     highlighter = textPane.getHighlighter();
119     chainToolTipAction = new ChainToolTipAction();
120     chainToolTipTimer = new javax.swing.Timer(500, chainToolTipAction);
121 
122     newCorefAction = new NewCorefAction();
123     newCorefActionTimer = new javax.swing.Timer(500, newCorefAction);
124 
125     colorGenerator = new ColorGenerator();
126 
127     // main Panel
128     mainPanel = new JPanel();
129     mainPanel.setLayout(new BorderLayout());
130 
131     // topPanel
132     topPanel = new JPanel();
133     topPanel.setLayout(new BorderLayout());
134 
135     // subPanel
136     subPanel = new JPanel();
137     subPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
138 
139     // showAnnotations Button
140     showAnnotations = new JToggleButton("Show");
141     showAnnotations.addActionListener(this);
142 
143     // annotSets
144     annotSets = new JComboBox();
145     annotSets.addActionListener(this);
146 
147     // get all the annotationSets
148     Map annotSetsMap = document.getNamedAnnotationSets();
149     annotSetsModel = new DefaultComboBoxModel();
150     if (annotSetsMap != null) {
151       Object [] array = annotSetsMap.keySet().toArray();
152       for(int i=0;i<array.length;i++) {
153         ((AnnotationSet) annotSetsMap.get((String) array[i])).addAnnotationSetListener(this);
154       }
155       annotSetsModel = new DefaultComboBoxModel(array);
156     }
157     document.getAnnotations().addAnnotationSetListener(this);
158     annotSetsModel.insertElementAt(DEFAULT_ANNOTSET_NAME, 0);
159     annotSets.setModel(annotSetsModel);
160 
161     // annotTypes
162     annotTypesModel = new DefaultComboBoxModel();
163     annotTypes = new JComboBox(annotTypesModel);
164     annotTypes.addActionListener(this);
165     subPanel.add(new JLabel("Sets : "));
166     subPanel.add(annotSets);
167     JPanel tempPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
168     tempPanel.add(new JLabel("Types : "));
169     tempPanel.add(annotTypes);
170     tempPanel.add(showAnnotations);
171     // intialises the Data
172     initData();
173 
174     // and creating the tree
175     corefTree = new JTree(rootNode);
176     corefTree.putClientProperty("JTree.lineStyle", "None");
177     corefTree.setRowHeight(corefTree.getRowHeight() * 2);
178     corefTree.setLargeModel(true);
179     corefTree.setAutoscrolls(true);
180 
181     //corefTree.setRootVisible(false);
182     //corefTree.setShowsRootHandles(false);
183     corefTree.addMouseListener(new CorefTreeMouseListener());
184     corefTree.setCellRenderer(new CorefTreeCellRenderer());
185 
186     mainPanel.add(topPanel, BorderLayout.NORTH);
187     mainPanel.add(new JScrollPane(corefTree), BorderLayout.CENTER);
188     topPanel.add(subPanel, BorderLayout.CENTER);
189     topPanel.add(tempPanel, BorderLayout.SOUTH);
190 
191     // get the highlighter
192     textPaneMouseListener = new TextPaneMouseListener();
193     annotSets.setSelectedIndex(0);
194 
195     // finally show the tree
196     //annotSetSelectionChanged();
197 
198     document.addDocumentListener(this);
199     document.getFeatures().addFeatureMapListener(this);
200   }
201 
202   public void reinitAllVariables() {
203 
204     if (highlightedChainAnnots != null)
205       highlightedChainAnnots.clear();
206     if (highlightedTypeAnnots != null)
207       highlightedTypeAnnots.clear();
208     if (typeSpecificHighlightedTags != null)
209       typeSpecificHighlightedTags.clear();
210     highlightedChainAnnotsOffsets = null;
211     highlightedTypeAnnotsOffsets = null;
212     if (highlightedTags != null && highlightedTags.values() != null) {
213       Iterator highlightsIter = highlightedTags.values().iterator();
214       while (highlightsIter.hasNext()) {
215         ArrayList tags = (ArrayList) highlightsIter.next();
216         for (int i = 0; i < tags.size(); i++) {
217           highlighter.removeHighlight(tags.get(i));
218         }
219       }
220       highlightedTags.clear();
221     }
222 
223     // we need to find out all the annotSetNodes and remove all the chainNodes
224     // under it
225     Iterator annotSetsIter = corefAnnotationSetNodesMap.keySet().iterator();
226     while (annotSetsIter.hasNext()) {
227       CorefTreeNode annotSetNode = (CorefTreeNode) corefAnnotationSetNodesMap.
228                                    get(annotSetsIter.next());
229       annotSetNode.removeAllChildren();
230       colorChainsMap.put(annotSetNode.toString(), new HashMap());
231       selectionChainsMap.put(annotSetNode.toString(), new HashMap());
232       corefChains.put(annotSetNode, new HashMap());
233     }
234   }
235 
236       /** This methods cleans up the memory by removing all listener registrations */
237   public void cleanup() {
238     document.removeDocumentListener(this);
239     document.getFeatures().removeFeatureMapListener(this);
240   }
241 
242   /** Given arrayList containing Ids of the annotations, and an annotationSet, this method
243    * returns the annotations that has longest string among the matches
244    */
245   public Annotation findOutTheLongestAnnotation(ArrayList matches,
246                                                 AnnotationSet set) {
247     if (matches == null || matches.size() == 0) {
248       return null;
249     }
250     int length = 0;
251     int index = 0;
252     for (int i = 0; i < matches.size(); i++) {
253       Annotation currAnn = (Annotation) set.get( (Integer) matches.get(i));
254       int start = currAnn.getStartNode().getOffset().intValue();
255       int end = currAnn.getEndNode().getOffset().intValue();
256       if ( (end - start) > length) {
257         length = end - start;
258         index = i;
259       }
260     }
261     // so now we now have the longest String annotations at index
262     return (Annotation) set.get( (Integer) matches.get(index));
263   }
264 
265   /**
266    * This method is called when any annotationSet is removed outside the
267    * co-reference editor..
268    * @param de
269    */
270   public void annotationSetRemoved(gate.event.DocumentEvent de) {
271     // this method removes the annotationSet from the annotSets
272     // and all chainNodes under it
273 
274     String annotSet = de.getAnnotationSetName();
275     annotSet = (annotSet == null) ? DEFAULT_ANNOTSET_NAME : annotSet;
276     // find out the currently Selected annotationSetName
277     String annotSetName = (String) annotSets.getSelectedItem();
278     // remove it from the main data store
279     corefChains.remove(corefAnnotationSetNodesMap.get(annotSet));
280     // remove it from the main data store
281     corefAnnotationSetNodesMap.remove(annotSet);
282     // remove it from the annotationSetModel (combobox)
283     annotSetsModel.removeElement(annotSet);
284     annotSets.setModel(annotSetsModel);
285     // remove it from the colorChainMap
286     colorChainsMap.remove(annotSet);
287     // remove it from the selectionChainMap
288     selectionChainsMap.remove(annotSet);
289     if (annotSetsModel.getSize() == 0) {
290       // no annotationSet to display
291       // so set visible false
292       if (popupWindow != null && popupWindow.isVisible()) {
293         popupWindow.setVisible(false);
294       }
295       corefTree.setVisible(false);
296     }
297     else {
298       if (annotSetName.equals(annotSet)) {
299         if (popupWindow != null && popupWindow.isVisible()) {
300           popupWindow.setVisible(false);
301         }
302         if (!corefTree.isVisible())
303           corefTree.setVisible(true);
304 
305         annotSets.setSelectedIndex(0);
306         //annotSetSelectionChanged();
307       }
308     }
309   }
310 
311   /**
312    * This method is called when any new annotationSet is added
313    * @param de
314    */
315   public void annotationSetAdded(gate.event.DocumentEvent de) {
316 
317     String annotSet = de.getAnnotationSetName();
318     if(annotSet == null)
319       document.getAnnotations().addAnnotationSetListener(this);
320     else
321       document.getAnnotations(annotSet).addAnnotationSetListener(this);
322 
323     annotSet = (annotSet == null) ? DEFAULT_ANNOTSET_NAME : annotSet;
324     // find out the currently Selected annotationSetName
325     String annotSetName = (String) annotSets.getSelectedItem();
326 
327     // check if newly added annotationSet is the default AnnotationSet
328     CorefTreeNode annotSetNode = null;
329 
330     if (annotSet.equals(DEFAULT_ANNOTSET_NAME))
331       annotSetNode = createAnnotSetNode(document.getAnnotations(), true);
332     else
333       annotSetNode = createAnnotSetNode(document.getAnnotations(annotSet), false);
334 
335     corefAnnotationSetNodesMap.put(annotSet, annotSetNode);
336     /*annotSetsModel.addElement(annotSet);
337     annotSets.setModel(annotSetsModel);*/
338 
339     if (annotSetName != null)
340       annotSets.setSelectedItem(annotSetName);
341     else
342       annotSets.setSelectedIndex(0);
343 
344       //annotSetSelectionChanged();
345   }
346 
347   /**Called when the content of the document has changed through an edit
348    * operation.
349    */
350   public void contentEdited(gate.event.DocumentEvent e) {
351     //ignore
352   }
353 
354   public void annotationAdded(AnnotationSetEvent ase) {
355     // ignore
356   }
357 
358   public void annotationRemoved(AnnotationSetEvent ase) {
359     Annotation delAnnot = ase.getAnnotation();
360     Integer id = delAnnot.getId();
361     Map matchesMap = null;
362     Object matchesMapObject = document.getFeatures().get(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME);
363     if(!(matchesMapObject instanceof Map)) {
364       // no need to do anything
365       // and return
366       return;
367     }
368 
369 
370     matchesMap = (Map) matchesMapObject;
371 
372     if(matchesMap == null)
373       return;
374 
375     Set keySet = matchesMap.keySet();
376     if(keySet == null)
377       return;
378 
379     Iterator iter = keySet.iterator();
380     boolean found = false;
381     while(iter.hasNext()) {
382       String currSet = (String) iter.next();
383       java.util.List matches = (java.util.List) matchesMap.get(currSet);
384       if(matches == null || matches.size() == 0)
385         continue;
386       else {
387         for(int i=0;i<matches.size();i++) {
388           ArrayList ids = (ArrayList) matches.get(i);
389           if(ids.contains(id)) {
390             // found
391             // so remove this
392             found = true;
393             ids.remove(id);
394             matches.set(i, ids);
395             break;
396           }
397         }
398         if(found) {
399           matchesMap.put(currSet, matches);
400           explicitCall = true;
401           document.getFeatures().put(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME,
402                                      matchesMap);
403           explicitCall = false;
404           break;
405         }
406       }
407     }
408     if(found)
409       featureMapUpdated();
410   }
411 
412   /**
413    * Called when features are changed outside the co-refEditor
414    */
415   public void featureMapUpdated() {
416 
417     if (explicitCall)
418       return;
419 
420     // we would first save the current settings
421     // 1. Current AnnotSet
422     // 2. Current AnnotType
423     // 3. ShowAnnotation Status
424     String currentAnnotSet = (String) annotSets.getSelectedItem();
425     String currentAnnotType = (String) annotTypes.getSelectedItem();
426     boolean currentShowAnnotationStatus = showAnnotations.isSelected();
427 
428     // there is some change in the featureMap
429     Map matchesMap = null;
430     Object matchesMapObject = document.getFeatures().get(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME);
431     if(!(matchesMapObject instanceof Map)) {
432       // no need to do anything
433       // and return
434       reinitAllVariables();
435       explicitCall = false;
436       annotSets.setSelectedIndex(0);
437       return;
438     }
439 
440     matchesMap = (Map) matchesMapObject;
441 
442     if (matchesMap == null) {
443       reinitAllVariables();
444       explicitCall = false;
445       annotSets.setSelectedIndex(0);
446       return;
447     }
448 
449     //AnnotationSetName --> List of ArrayLists
450     //each ArrayList contains Ids of related annotations
451     Iterator setIter = matchesMap.keySet().iterator();
452     HashMap annotSetsNamesMap = new HashMap();
453     for (int i = 0; i < annotSets.getItemCount(); i++) {
454       annotSetsNamesMap.put( (String) annotSets.getItemAt(i), new Boolean(false));
455     }
456     outer:while (setIter.hasNext()) {
457       String currentSet = (String) setIter.next();
458       java.util.List matches = (java.util.List) matchesMap.get(currentSet);
459       currentSet = (currentSet == null) ? DEFAULT_ANNOTSET_NAME : currentSet;
460 
461       if (matches == null)
462         continue;
463 
464       AnnotationSet currAnnotSet = getAnnotationSet(currentSet);
465       annotSetsNamesMap.put(currentSet, new Boolean(true));
466 
467       Iterator entitiesIter = matches.iterator();
468       //each entity is a list of annotation IDs
469 
470       if (corefAnnotationSetNodesMap.get(currentSet) == null) {
471         // we need to create the node for this
472         if (currentSet.equals(DEFAULT_ANNOTSET_NAME)) {
473           corefAnnotationSetNodesMap.put(DEFAULT_ANNOTSET_NAME,
474                                          createChain(document.getAnnotations(), true));
475         }
476         else {
477           corefAnnotationSetNodesMap.put(currentSet,
478                                          createChain(document.getAnnotations(
479               currentSet), false));
480         }
481         continue outer;
482       }
483 
484       HashMap chains = (HashMap) corefChains.get(corefAnnotationSetNodesMap.get(currentSet));
485       HashMap visitedList = new HashMap();
486 
487       if (chains != null) {
488         Iterator chainsList = chains.keySet().iterator();
489 
490         // intially no chainHead is visited
491         while (chainsList.hasNext()) {
492           visitedList.put( (CorefTreeNode) chainsList.next(), new Boolean(false));
493         }
494 
495         // now we need to search for the chainHead of each group
496         ArrayList idsToRemove = new ArrayList();
497         while (entitiesIter.hasNext()) {
498           ArrayList ids = (ArrayList) entitiesIter.next();
499           if (ids == null || ids.size() == 0) {
500             idsToRemove.add(ids);
501             continue;
502           }
503 
504           CorefTreeNode chainHead = null;
505           for (int i = 0; i < ids.size(); i++) {
506             Integer id = (Integer) ids.get(i);
507             // now lets find out the headnode for this, if it is available
508             chainHead = findOutTheChainHead(currAnnotSet.get(id), currentSet);
509             if (chainHead != null) {
510               visitedList.put(chainHead, new Boolean(true));
511               break;
512             }
513           }
514 
515           if (chainHead != null) {
516             // we found the chainHead for this
517             // so we would replace the ids
518             // but before that we would check if chainHead should be replaced
519             Annotation longestAnn = findOutTheLongestAnnotation(ids, getAnnotationSet(currentSet));
520             if (getString(longestAnn).equals(chainHead.toString())) {
521               chains.put(chainHead, ids);
522               corefChains.put(corefAnnotationSetNodesMap.get(currentSet),
523                               chains);
524             }
525             else {
526               // we first check if new longestAnnotation String is already available as some other chain Node head
527               if (currentColors.containsKey(getString(longestAnn))) {
528                 // yes one chainHead with this string already exists
529                 // so we need to merge them together
530                 String longestString = getString(longestAnn);
531                 CorefTreeNode tempChainHead = findOutChainNode(longestString, currentSet);
532                 // now all the ids under current chainHead should be placed under the tempChainHead
533                 ArrayList tempIds = (ArrayList) chains.get(tempChainHead);
534                 ArrayList currentChainHeadIds = (ArrayList) chains.get(
535                     chainHead);
536                 // so lets merge them
537                 tempIds.addAll(currentChainHeadIds);
538 
539                 // and update the chains
540                 chains.remove(chainHead);
541                 chains.put(tempChainHead, tempIds);
542                 corefChains.put(corefAnnotationSetNodesMap.get(currentSet),
543                                 chains);
544                 visitedList.put(chainHead, new Boolean(false));
545                 visitedList.put(tempChainHead, new Boolean(true));
546 
547               }
548               else {
549                 String previousString = chainHead.toString();
550                 String newString = getString(longestAnn);
551                 chainHead.setUserObject(newString);
552 
553                 // we need to change the colors
554                 Color color = (Color) currentColors.get(previousString);
555                 currentColors.remove(previousString);
556                 currentColors.put(newString, color);
557                 colorChainsMap.put(newString, currentColors);
558 
559                 // we need to change the selections
560                 Boolean val = (Boolean) currentSelections.get(previousString);
561                 currentSelections.remove(previousString);
562                 currentSelections.put(newString, val);
563                 selectionChainsMap.put(newString, currentSelections);
564 
565                 chains.put(chainHead, ids);
566                 corefChains.put(corefAnnotationSetNodesMap.get(currentSet),
567                                 chains);
568               }
569             }
570           }
571           else {
572             // this is something new addition
573             // so we need to create a new chainNode
574             // this is the new chain
575             // get the current annotSetNode
576             CorefTreeNode annotSetNode = (CorefTreeNode)
577                                          corefAnnotationSetNodesMap.get(
578                 currentSet);
579 
580             // we need to find out the longest string annotation
581             AnnotationSet actSet = getAnnotationSet(currentSet);
582 
583             Annotation ann = findOutTheLongestAnnotation(ids, getAnnotationSet(currentSet));
584             // so before creating a new chainNode we need to find out if
585             // any of the chainNodes has the same string that of this chainNode
586             HashMap tempSelection = (HashMap) selectionChainsMap.get(
587                 currentSet);
588             CorefTreeNode chainNode = null;
589             if (tempSelection.containsKey(getString(ann))) {
590               chainNode = findOutChainNode(getString(ann), currentSet);
591 
592               // ArrayList matches
593               HashMap newHashMap = (HashMap) corefChains.get(annotSetNode);
594               newHashMap.put(chainNode, ids);
595               corefChains.put(annotSetNode, newHashMap);
596 
597               visitedList.put(chainNode, new Boolean(true));
598             }
599             else {
600               // create the new chainNode
601               chainNode = new CorefTreeNode(getString(ann), false,
602                                             CorefTreeNode.CHAIN_NODE);
603 
604               // add this to tree
605               annotSetNode.add(chainNode);
606               corefAnnotationSetNodesMap.put(currentSet, annotSetNode);
607 
608               // ArrayList matches
609               HashMap newHashMap = (HashMap) corefChains.get(annotSetNode);
610               newHashMap.put(chainNode, ids);
611               corefChains.put(annotSetNode, newHashMap);
612 
613               boolean selectionValue = false;
614               if(currentAnnotSet.equals(currentSet))
615                 selectionValue = true;
616 
617               // entry into the selection
618               tempSelection.put(chainNode.toString(), new Boolean(selectionValue));
619               selectionChainsMap.put(currentSet, tempSelection);
620 
621               // entry into the colors
622               float components[] = colorGenerator.getNextColor().getComponents(null);
623               Color color = new Color(components[0],
624                                       components[1],
625                                       components[2],
626                                       0.5f);
627               HashMap tempColors = (HashMap) colorChainsMap.get(currentSet);
628               tempColors.put(chainNode.toString(), color);
629               colorChainsMap.put(annotSets.getSelectedItem(), tempColors);
630             }
631           }
632         }
633 
634         // ok we need to remove Idsnow
635         Iterator removeIter = idsToRemove.iterator();
636         while (removeIter.hasNext()) {
637           explicitCall = true;
638           ArrayList ids = (ArrayList) removeIter.next();
639           matches.remove(ids);
640           String set = currentSet.equals(DEFAULT_ANNOTSET_NAME) ? null :
641                        currentSet;
642           matchesMap.put(set, matches);
643           explicitCall = false;
644         }
645         explicitCall = true;
646         document.getFeatures().put(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME,
647                                    matchesMap);
648         explicitCall = false;
649 
650         // here we need to find out the chainNodes those are no longer needed
651         Iterator visitedListIter = visitedList.keySet().iterator();
652         while (visitedListIter.hasNext()) {
653           CorefTreeNode chainNode = (CorefTreeNode) visitedListIter.next();
654           if (! ( (Boolean) visitedList.get(chainNode)).booleanValue()) {
655             // yes this should be deleted
656             CorefTreeNode annotSetNode = (CorefTreeNode)
657                                          corefAnnotationSetNodesMap.get(
658                 currentSet);
659 
660             // remove from the tree
661             annotSetNode.remove(chainNode);
662             corefAnnotationSetNodesMap.put(currentSet, annotSetNode);
663 
664             // ArrayList matches
665             HashMap newHashMap = (HashMap) corefChains.get(annotSetNode);
666             newHashMap.remove(chainNode);
667             corefChains.put(annotSetNode, newHashMap);
668 
669             // remove from the selections
670             HashMap tempSelection = (HashMap) selectionChainsMap.get(
671                 currentSet);
672             tempSelection.remove(chainNode.toString());
673             selectionChainsMap.put(currentSet, tempSelection);
674 
675             // remove from the colors
676             HashMap tempColors = (HashMap) colorChainsMap.get(currentSet);
677             tempColors.remove(chainNode.toString());
678             colorChainsMap.put(currentSet, currentColors);
679           }
680         }
681       }
682     }
683 
684     Iterator tempIter = annotSetsNamesMap.keySet().iterator();
685     while (tempIter.hasNext()) {
686       String currentSet = (String) tempIter.next();
687       if (! ( (Boolean) annotSetsNamesMap.get(currentSet)).booleanValue()) {
688         String annotSet = currentSet;
689         // find out the currently Selected annotationSetName
690         String annotSetName = (String) annotSets.getSelectedItem();
691         // remove it from the main data store
692         corefChains.remove(corefAnnotationSetNodesMap.get(annotSet));
693         // remove it from the main data store
694         corefAnnotationSetNodesMap.remove(annotSet);
695         // remove it from the annotationSetModel (combobox)
696         annotSetsModel.removeElement(annotSet);
697         annotSets.setModel(annotSetsModel);
698         annotSets.updateUI();
699         // remove it from the colorChainMap
700         colorChainsMap.remove(annotSet);
701         // remove it from the selectionChainMap
702         selectionChainsMap.remove(annotSet);
703       }
704     }
705 
706     if (annotSetsModel.getSize() == 0) {
707       // no annotationSet to display
708       // so set visible false
709       if (popupWindow != null && popupWindow.isVisible()) {
710         popupWindow.setVisible(false);
711       }
712       corefTree.setVisible(false);
713 
714       // remove all highlights
715       ArrayList allHighlights = new ArrayList();
716       if(typeSpecificHighlightedTags != null)
717         allHighlights.addAll(typeSpecificHighlightedTags);
718       if(highlightedTags != null) {
719         Iterator iter = highlightedTags.values().iterator();
720         while(iter.hasNext()) {
721           ArrayList highlights = (ArrayList) iter.next();
722           allHighlights.addAll(highlights);
723         }
724       }
725       for(int i=0;i<allHighlights.size();i++) {
726         highlighter.removeHighlight(allHighlights.get(i));
727       }
728 
729       //highlighter.removeAllHighlights();
730       highlightedTags = null;
731       typeSpecificHighlightedTags = null;
732       return;
733     }
734     else {
735 
736       if (popupWindow != null && popupWindow.isVisible()) {
737         popupWindow.setVisible(false);
738       }
739 
740       // remove all highlights
741       ArrayList allHighlights = new ArrayList();
742       if(typeSpecificHighlightedTags != null)
743         allHighlights.addAll(typeSpecificHighlightedTags);
744       if(highlightedTags != null) {
745         Iterator iter = highlightedTags.values().iterator();
746         while(iter.hasNext()) {
747           ArrayList highlights = (ArrayList) iter.next();
748           allHighlights.addAll(highlights);
749         }
750       }
751       for (int i = 0; i < allHighlights.size(); i++) {
752         highlighter.removeHighlight(allHighlights.get(i));
753       }
754 
755       //highlighter.removeAllHighlights();
756       highlightedTags = null;
757       typeSpecificHighlightedTags = null;
758       if (currentAnnotSet != null) {
759         annotSets.setSelectedItem(currentAnnotSet);
760         currentSelections = (HashMap) selectionChainsMap.get(currentAnnotSet);
761         currentColors = (HashMap) colorChainsMap.get(currentAnnotSet);
762         highlightAnnotations();
763 
764         showAnnotations.setSelected(currentShowAnnotationStatus);
765         if (currentAnnotType != null)
766           annotTypes.setSelectedItem(currentAnnotType);
767         else
768         if (annotTypes.getModel().getSize() > 0) {
769           annotTypes.setSelectedIndex(0);
770         }
771       }
772       else {
773         explicitCall = false;
774         annotSets.setSelectedIndex(0);
775       }
776     }
777   }
778 
779   /**
780    * ActionPerformed Activity
781    * @param ae
782    */
783   public void actionPerformed(ActionEvent ae) {
784     // when annotationSet value changes
785     if (ae.getSource() == annotSets) {
786       if (!explicitCall) {
787         annotSetSelectionChanged();
788       }
789     }
790     else if (ae.getSource() == showAnnotations) {
791       if (!explicitCall) {
792         showTypeWiseAnnotations();
793       }
794     }
795     else if (ae.getSource() == annotTypes) {
796       if (!explicitCall) {
797         if (typeSpecificHighlightedTags != null) {
798           for (int i = 0; i < typeSpecificHighlightedTags.size(); i++) {
799             highlighter.removeHighlight(typeSpecificHighlightedTags.get(i));
800           }
801         }
802         typeSpecificHighlightedTags = null;
803         showTypeWiseAnnotations();
804       }
805     }
806   }
807 
808   /**
809    * When user preses the show Toggle button, this will show up annotations
810    * of selected Type from selected AnnotationSet
811    */
812   private void showTypeWiseAnnotations() {
813     if (typeSpecificHighlightedTags == null) {
814       highlightedTypeAnnots = new ArrayList();
815       typeSpecificHighlightedTags = new ArrayList();
816     }
817 
818     if (showAnnotations.isSelected()) {
819       // get the annotationsSet and its type
820       AnnotationSet set = getAnnotationSet( (String) annotSets.getSelectedItem());
821       String type = (String) annotTypes.getSelectedItem();
822       if (type == null) {
823         try {
824           JOptionPane.showMessageDialog(Main.getMainFrame(),
825                                         "No annotation type found to display");
826         }
827         catch (Exception e) {
828           e.printStackTrace();
829         }
830         showAnnotations.setSelected(false);
831         return;
832       }
833 
834       Color color = getColor(type);
835       if (type != null) {
836         AnnotationSet typeSet = set.get(type);
837         Iterator iter = typeSet.iterator();
838         while (iter.hasNext()) {
839           Annotation ann = (Annotation) iter.next();
840           highlightedTypeAnnots.add(ann);
841           try {
842             typeSpecificHighlightedTags.add(highlighter.addHighlight(ann.
843                 getStartNode().
844                 getOffset().intValue(),
845                 ann.getEndNode().getOffset().intValue(),
846                 new DefaultHighlighter.
847                 DefaultHighlightPainter(color)));
848           }
849           catch (Exception e) {
850             e.printStackTrace();
851           }
852           //typeSpecificHighlightedTags.add(textView.addHighlight(ann, getAnnotationSet((String)annotSets.getSelectedItem()),color));
853         }
854       }
855     }
856     else {
857       for (int i = 0; i < typeSpecificHighlightedTags.size(); i++) {
858         //textView.removeHighlight(typeSpecificHighlightedTags.get(i));
859         highlighter.removeHighlight(typeSpecificHighlightedTags.get(i));
860       }
861       typeSpecificHighlightedTags = new ArrayList();
862       highlightedTypeAnnots = new ArrayList();
863       highlightedTypeAnnotsOffsets = null;
864     }
865 
866     // This is to make process faster.. instead of accessing each annotation and
867     // its offset, we create an array with its annotation offsets to search faster
868     Collections.sort(highlightedTypeAnnots, new gate.util.OffsetComparator());
869     highlightedTypeAnnotsOffsets = new int[highlightedTypeAnnots.size() * 2];
870     for (int i = 0, j = 0; j < highlightedTypeAnnots.size(); i += 2, j++) {
871       Annotation ann1 = (Annotation) highlightedTypeAnnots.get(j);
872       highlightedTypeAnnotsOffsets[i] = ann1.getStartNode().getOffset().
873                                         intValue();
874       highlightedTypeAnnotsOffsets[i +
875           1] = ann1.getEndNode().getOffset().intValue();
876     }
877 
878   }
879 
880   /**
881    * Returns annotation Set
882    * @param annotSet
883    * @return
884    */
885   private AnnotationSet getAnnotationSet(String annotSet) {
886     return (annotSet.equals(DEFAULT_ANNOTSET_NAME)) ? document.getAnnotations() :
887         document.getAnnotations(annotSet);
888   }
889 
890   /**
891    * When annotationSet selection changes
892    */
893   private void annotSetSelectionChanged() {
894     if (annotSets.getModel().getSize() == 0) {
895       if (popupWindow != null && popupWindow.isVisible()) {
896         popupWindow.setVisible(false);
897       }
898       corefTree.setVisible(false);
899       return;
900     }
901 
902     String currentAnnotSet = (String) annotSets.getSelectedItem();
903     // get all the types of the currently Selected AnnotationSet
904     if (currentAnnotSet == null)
905       currentAnnotSet = (String) annotSets.getItemAt(0);
906     AnnotationSet temp = getAnnotationSet(currentAnnotSet);
907     Set types = temp.getAllTypes();
908     annotTypesModel = new DefaultComboBoxModel();
909     if (types != null) {
910       annotTypesModel = new DefaultComboBoxModel(types.toArray());
911     }
912     annotTypes.setModel(annotTypesModel);
913     annotTypes.updateUI();
914 
915     // and redraw the CorefTree
916     if (rootNode.getChildCount() > 0)
917       rootNode.removeAllChildren();
918 
919     CorefTreeNode annotSetNode = (CorefTreeNode) corefAnnotationSetNodesMap.get(
920         currentAnnotSet);
921 
922     if (annotSetNode != null) {
923       rootNode.add(annotSetNode);
924       currentSelections = (HashMap) selectionChainsMap.get(currentAnnotSet);
925       currentColors = (HashMap) colorChainsMap.get(currentAnnotSet);
926       if (!corefTree.isVisible()) {
927         if (popupWindow != null && popupWindow.isVisible()) {
928           popupWindow.setVisible(false);
929         }
930         corefTree.setVisible(true);
931       }
932       corefTree.repaint();
933       corefTree.updateUI();
934 
935     }
936     else {
937       corefTree.setVisible(false);
938     }
939   }
940 
941   /**
942    * This will initialise the data
943    */
944   private void initData() {
945 
946     rootNode = new CorefTreeNode("Co-reference Data", true,
947                                  CorefTreeNode.ROOT_NODE);
948     corefChains = new HashMap();
949     selectionChainsMap = new HashMap();
950     currentSelections = new HashMap();
951     colorChainsMap = new HashMap();
952     currentColors = new HashMap();
953     corefAnnotationSetNodesMap = new HashMap();
954 
955     // now we need to findout the chains
956     // for the defaultAnnotationSet
957     CorefTreeNode annotSetNode = createChain(document.getAnnotations(), true);
958     if (annotSetNode != null) {
959       corefAnnotationSetNodesMap.put(DEFAULT_ANNOTSET_NAME, annotSetNode);
960     }
961 
962     // and for the rest AnnotationSets
963     Map annotSets = document.getNamedAnnotationSets();
964     if (annotSets != null) {
965       Iterator annotSetsIter = annotSets.keySet().iterator();
966       while (annotSetsIter.hasNext()) {
967         String annotSetName = (String) annotSetsIter.next();
968         annotSetNode = createChain(document.getAnnotations(annotSetName), false);
969         if (annotSetNode != null) {
970           corefAnnotationSetNodesMap.put(annotSetName, annotSetNode);
971         }
972       }
973     }
974   }
975 
976   private CorefTreeNode createAnnotSetNode(AnnotationSet set, boolean isDefaultSet) {
977     // create the node for setName
978     String setName = isDefaultSet ? DEFAULT_ANNOTSET_NAME : set.getName();
979     CorefTreeNode annotSetNode = new CorefTreeNode(setName, true,
980         CorefTreeNode.ANNOTSET_NODE);
981 
982     // see if this setName available in the annotSets
983     boolean found = false;
984     for (int i = 0; i < annotSets.getModel().getSize(); i++) {
985       if ( ( (String) annotSets.getModel().getElementAt(i)).equals(setName)) {
986         found = true;
987         break;
988       }
989     }
990     if (!found) {
991       explicitCall = true;
992       annotSets.addItem(setName);
993       explicitCall = false;
994     }
995 
996     // the internal datastructure
997     HashMap chainLinks = new HashMap();
998     HashMap selectionMap = new HashMap();
999     HashMap colorMap = new HashMap();
1000
1001    corefChains.put(annotSetNode, chainLinks);
1002    selectionChainsMap.put(setName, selectionMap);
1003    colorChainsMap.put(setName, colorMap);
1004    return annotSetNode;
1005
1006  }
1007
1008  /**
1009   * Creates the internal data structure
1010   * @param set
1011   */
1012  private CorefTreeNode createChain(AnnotationSet set, boolean isDefaultSet) {
1013
1014    // create the node for setName
1015    String setName = isDefaultSet ? DEFAULT_ANNOTSET_NAME : set.getName();
1016    CorefTreeNode annotSetNode = new CorefTreeNode(setName, true,
1017        CorefTreeNode.ANNOTSET_NODE);
1018
1019    // see if this setName available in the annotSets
1020    boolean found = false;
1021    for (int i = 0; i < annotSets.getModel().getSize(); i++) {
1022      if ( ( (String) annotSets.getModel().getElementAt(i)).equals(setName)) {
1023        found = true;
1024        break;
1025      }
1026    }
1027    if (!found) {
1028      explicitCall = true;
1029      annotSets.addItem(setName);
1030      explicitCall = false;
1031    }
1032
1033    // the internal datastructure
1034    HashMap chainLinks = new HashMap();
1035    HashMap selectionMap = new HashMap();
1036    HashMap colorMap = new HashMap();
1037
1038    // map for all the annotations with matches feature in it
1039    Map matchesMap = null;
1040    Object matchesMapObject = document.getFeatures().get(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME);
1041    if(matchesMapObject instanceof Map) {
1042      matchesMap = (Map) matchesMapObject;
1043    }
1044
1045
1046    // what if this map is null
1047    if (matchesMap == null) {
1048      corefChains.put(annotSetNode, chainLinks);
1049      selectionChainsMap.put(setName, selectionMap);
1050      colorChainsMap.put(setName, colorMap);
1051      return annotSetNode;
1052    }
1053
1054    //AnnotationSetName --> List of ArrayLists
1055    //each ArrayList contains Ids of related annotations
1056    Iterator setIter = matchesMap.keySet().iterator();
1057    java.util.List matches1 = (java.util.List) matchesMap.get(isDefaultSet ? null :
1058        setName);
1059    if (matches1 == null) {
1060      corefChains.put(annotSetNode, chainLinks);
1061      selectionChainsMap.put(setName, selectionMap);
1062      colorChainsMap.put(setName, colorMap);
1063      return annotSetNode;
1064    }
1065
1066    Iterator tempIter = matches1.iterator();
1067
1068    while (tempIter.hasNext()) {
1069      ArrayList matches = (ArrayList) tempIter.next();
1070      int length = 0;
1071      int index = 0;
1072      if (matches == null)
1073        matches = new ArrayList();
1074
1075      if (matches.size() > 0 && set.size() > 0) {
1076
1077        String longestString = getString((Annotation) findOutTheLongestAnnotation(matches,
1078            set));
1079        // so this should become one of the tree node
1080        CorefTreeNode chainNode = new CorefTreeNode(longestString, false,
1081            CorefTreeNode.CHAIN_NODE);
1082        // and add it under the topNode
1083        annotSetNode.add(chainNode);
1084
1085        // chainNode --> All related annotIds
1086        chainLinks.put(chainNode, matches);
1087        selectionMap.put(chainNode.toString(), new Boolean(false));
1088        // and generate the color for this chainNode
1089        float components[] = colorGenerator.getNextColor().getComponents(null);
1090        Color color = new Color(components[0],
1091                                components[1],
1092                                components[2],
1093                                0.5f);
1094        colorMap.put(chainNode.toString(), color);
1095      }
1096    }
1097
1098    corefChains.put(annotSetNode, chainLinks);
1099    selectionChainsMap.put(setName, selectionMap);
1100    colorChainsMap.put(setName, colorMap);
1101    return annotSetNode;
1102  }
1103
1104  /**
1105   * Given an annotation, this method returns the string of that annotation
1106   * @param ann
1107   * @return
1108   */
1109  public String getString(Annotation ann) {
1110    return document.getContent().toString().substring(ann.
1111        getStartNode().getOffset().intValue(),
1112        ann.getEndNode().getOffset().intValue());
1113  }
1114
1115  /**
1116       * This method removes the reference of this annotatation from the current chain
1117   * @param ann
1118   */
1119  public void removeChainReference(Annotation annot, CorefTreeNode chainHead) {
1120
1121    // so we would find out the matches
1122    CorefTreeNode currentNode = chainHead;
1123    ArrayList ids = (ArrayList) ( (HashMap)
1124                                 corefChains.get(corefAnnotationSetNodesMap.get(
1125        annotSets.getSelectedItem()))).get(chainHead);
1126
1127   String currentSet = (String) annotSets.getSelectedItem();
1128   currentSet = (currentSet.equals(DEFAULT_ANNOTSET_NAME)) ? null : currentSet;
1129
1130    // we need to update the Co-reference document feature
1131    Map matchesMap = null;
1132    java.util.List matches = null;
1133    Object matchesMapObject = document.getFeatures().get(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME);
1134    if(matchesMapObject instanceof Map) {
1135      matchesMap = (Map) matchesMapObject;
1136      matches = (java.util.List) matchesMap.get(currentSet);
1137    } else {
1138      matchesMap = new HashMap();
1139    }
1140
1141    if (matches == null)
1142      matches = new ArrayList();
1143
1144    int index = matches.indexOf(ids);
1145    if (index != -1) {
1146      // yes found
1147      ids.remove(annot.getId());
1148      Annotation ann = findOutTheLongestAnnotation(ids,
1149          getAnnotationSet( (String) annotSets.getSelectedItem()));
1150
1151      matches.set(index, ids);
1152      matchesMap.put(currentSet, matches);
1153      document.getFeatures().put(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME,
1154                                 matchesMap);
1155    }
1156  }
1157
1158  /**
1159   * Given an annotation, this will find out the chainHead
1160   * @param ann
1161   * @return
1162   */
1163  private CorefTreeNode findOutTheChainHead(Annotation ann, String set) {
1164    HashMap chains = (HashMap) corefChains.get(corefAnnotationSetNodesMap.get(
1165        set));
1166    if (chains == null)
1167      return null;
1168    Iterator iter = chains.keySet().iterator();
1169    while (iter.hasNext()) {
1170      CorefTreeNode head = (CorefTreeNode) iter.next();
1171      if ( ( (ArrayList) chains.get(head)).contains(ann.getId())) {
1172        return head;
1173      }
1174    }
1175    return null;
1176  }
1177
1178  /**
1179   * This methods highlights the annotations
1180   */
1181  public void highlightAnnotations() {
1182
1183    if (highlightedTags == null) {
1184      highlightedTags = new HashMap();
1185      highlightedChainAnnots = new ArrayList();
1186    }
1187
1188    AnnotationSet annotSet = getAnnotationSet( (String) annotSets.
1189                                              getSelectedItem());
1190    CorefTreeNode annotSetNode = (CorefTreeNode) corefAnnotationSetNodesMap.get(
1191        annotSets.getSelectedItem());
1192    if (annotSetNode == null) {
1193      return;
1194    }
1195    HashMap chainMap = (HashMap) corefChains.get(annotSetNode);
1196    Iterator iter = chainMap.keySet().iterator();
1197
1198    while (iter.hasNext()) {
1199      CorefTreeNode currentNode = (CorefTreeNode) iter.next();
1200      if ( ( (Boolean) currentSelections.get(currentNode.toString())).
1201          booleanValue()) {
1202        if (!highlightedTags.containsKey(currentNode)) {
1203          // find out the arrayList
1204          ArrayList ids = (ArrayList) chainMap.get(currentNode);
1205          ArrayList highlighTag = new ArrayList();
1206          if (ids != null) {
1207            for (int i = 0; i < ids.size(); i++) {
1208              Annotation ann = annotSet.get( (Integer) ids.get(i));
1209              highlightedChainAnnots.add(ann);
1210              Color color = (Color) currentColors.get(currentNode.toString());
1211              try {
1212                highlighTag.add(highlighter.addHighlight(ann.getStartNode().
1213                    getOffset().intValue(),
1214                    ann.getEndNode().getOffset().intValue(),
1215                    new DefaultHighlighter.
1216                    DefaultHighlightPainter(color)));
1217              }
1218              catch (Exception e) {
1219                e.printStackTrace();
1220              }
1221              //highlighTag.add(textView.addHighlight(ann, getAnnotationSet((String) annotSets.getSelectedItem()), color));
1222            }
1223            highlightedTags.put(currentNode, highlighTag);
1224          }
1225        }
1226      }
1227      else {
1228        if (highlightedTags.containsKey(currentNode)) {
1229          ArrayList highlights = (ArrayList) highlightedTags.get(currentNode);
1230          for (int i = 0; i < highlights.size(); i++) {
1231            //textView.removeHighlight(highlights.get(i));
1232            highlighter.removeHighlight(highlights.get(i));
1233          }
1234          highlightedTags.remove(currentNode);
1235          ArrayList ids = (ArrayList) chainMap.get(currentNode);
1236          if (ids != null) {
1237            for (int i = 0; i < ids.size(); i++) {
1238              Annotation ann = annotSet.get( (Integer) ids.get(i));
1239              highlightedChainAnnots.remove(ann);
1240            }
1241          }
1242        }
1243      }
1244    }
1245
1246    // This is to make process faster.. instead of accessing each annotation and
1247    // its offset, we create an array with its annotation offsets to search faster
1248    Collections.sort(highlightedChainAnnots, new gate.util.OffsetComparator());
1249    highlightedChainAnnotsOffsets = new int[highlightedChainAnnots.size() * 2];
1250    for (int i = 0, j = 0; j < highlightedChainAnnots.size(); i += 2, j++) {
1251      Annotation ann1 = (Annotation) highlightedChainAnnots.get(j);
1252      highlightedChainAnnotsOffsets[i] = ann1.getStartNode().getOffset().
1253                                         intValue();
1254      highlightedChainAnnotsOffsets[i +
1255          1] = ann1.getEndNode().getOffset().intValue();
1256    }
1257  }
1258
1259  protected void registerHooks() {
1260    textPane.addMouseListener(textPaneMouseListener);
1261    textPane.addMouseMotionListener(textPaneMouseListener);
1262
1263  }
1264
1265  protected void unregisterHooks() {
1266    textPane.removeMouseListener(textPaneMouseListener);
1267    textPane.removeMouseMotionListener(textPaneMouseListener);
1268  }
1269
1270  public Component getGUI() {
1271    return mainPanel;
1272  }
1273
1274  public int getType() {
1275    return VERTICAL;
1276  }
1277
1278  //**********************************************
1279   // MouseListener and MouseMotionListener Methods
1280   //***********************************************
1281
1282    protected class TextPaneMouseListener
1283        extends MouseInputAdapter {
1284
1285      public TextPaneMouseListener() {
1286        chainToolTipTimer.setRepeats(false);
1287        newCorefActionTimer.setRepeats(false);
1288      }
1289
1290      public void mouseMoved(MouseEvent me) {
1291        int textLocation = textPane.viewToModel(me.getPoint());
1292        chainToolTipAction.setTextLocation(textLocation);
1293        chainToolTipAction.setMousePointer(me.getPoint());
1294        chainToolTipTimer.restart();
1295
1296        newCorefAction.setTextLocation(textLocation);
1297        newCorefAction.setMousePointer(me.getPoint());
1298        newCorefActionTimer.restart();
1299      }
1300    }
1301
1302  public void mouseClicked(MouseEvent me) {
1303    if (popupWindow != null && popupWindow.isVisible()) {
1304      popupWindow.setVisible(false);
1305    }
1306  }
1307
1308  public CorefTreeNode findOutChainNode(String chainNodeString, String set) {
1309    if (corefChains == null || corefAnnotationSetNodesMap == null) {
1310      return null;
1311    }
1312    HashMap chains = (HashMap) corefChains.get(corefAnnotationSetNodesMap.get(set));
1313    if (chains == null) {
1314      return null;
1315    }
1316    Iterator iter = chains.keySet().iterator();
1317    while (iter.hasNext()) {
1318      CorefTreeNode currentNode = (CorefTreeNode) iter.next();
1319      if (currentNode.toString().equals(chainNodeString))
1320        return currentNode;
1321    }
1322    return null;
1323  }
1324
1325  /**
1326   * When user hovers over the annotations which have been highlighted by
1327   * show button
1328   */
1329  protected class NewCorefAction
1330      implements ActionListener {
1331
1332    int textLocation;
1333    Point mousePoint;
1334    JLabel label = new JLabel();
1335    JPanel panel = new JPanel();
1336    JPanel subPanel = new JPanel();
1337    String field = "";
1338    JButton add = new JButton("OK");
1339    JButton cancel = new JButton("Cancel");
1340    JComboBox list = new JComboBox();
1341    JPanel mainPanel = new JPanel();
1342    JPopupMenu popup1 = new JPopupMenu();
1343    ListEditor listEditor = null;
1344    ComboBoxModel model = new DefaultComboBoxModel();
1345    boolean firstTime = true;
1346
1347    public NewCorefAction() {
1348      popupWindow = new JWindow(SwingUtilities.getWindowAncestor(textView.
1349          getGUI()));
1350      popupWindow.setBackground(UIManager.getLookAndFeelDefaults().
1351                                getColor("ToolTip.background"));
1352      mainPanel.setLayout(new BorderLayout());
1353      mainPanel.setOpaque(true);
1354      mainPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
1355      mainPanel.setBackground(UIManager.getLookAndFeelDefaults().
1356                              getColor("ToolTip.background"));
1357      popupWindow.setContentPane(mainPanel);
1358
1359      panel.setLayout(new BorderLayout());
1360      panel.setOpaque(false);
1361      panel.add(new JScrollPane(list), BorderLayout.CENTER);
1362
1363      subPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
1364      subPanel.add(add);
1365      subPanel.add(cancel);
1366      subPanel.setOpaque(false);
1367      panel.add(subPanel, BorderLayout.SOUTH);
1368      mainPanel.add(label, BorderLayout.NORTH);
1369      mainPanel.add(panel, BorderLayout.CENTER);
1370
1371      // and finally load the data for the list
1372      AddAction action = new AddAction();
1373      add.addActionListener(action);
1374      cancel.addActionListener(action);
1375      listEditor = new ListEditor(action);
1376      list.setMaximumRowCount(5);
1377      list.setEditable(true);
1378      list.setEditor(listEditor);
1379      list.setModel(model);
1380    }
1381
1382    public void actionPerformed(ActionEvent ae) {
1383      int index = -1;
1384      if (highlightedChainAnnotsOffsets != null) {
1385        for (int i = 0; i < highlightedChainAnnotsOffsets.length; i += 2) {
1386          if (textLocation >= highlightedChainAnnotsOffsets[i] &&
1387              textLocation <= highlightedChainAnnotsOffsets[i + 1]) {
1388            index = (i == 0) ? i : i / 2;
1389            break;
1390          }
1391        }
1392      }
1393
1394      // yes it is put on highlighted so show the annotationType
1395      if (highlightedChainAnnotsOffsets != null &&
1396          index < highlightedChainAnnotsOffsets.length && index >= 0) {
1397        return;
1398      }
1399
1400      if (highlightedTypeAnnotsOffsets != null) {
1401        for (int i = 0; i < highlightedTypeAnnotsOffsets.length; i += 2) {
1402          if (textLocation >= highlightedTypeAnnotsOffsets[i] &&
1403              textLocation <= highlightedTypeAnnotsOffsets[i + 1]) {
1404            index = (i == 0) ? i : i / 2;
1405            break;
1406          }
1407        }
1408      }
1409
1410      // yes it is put on highlighted so show the annotationType
1411      if (highlightedTypeAnnotsOffsets != null &&
1412          index < highlightedTypeAnnotsOffsets.length && index >= 0) {
1413        textPane.removeAll();
1414        annotToConsiderForChain = (Annotation) highlightedTypeAnnots.get(index);
1415        // now check if this annotation is already linked with something
1416        CorefTreeNode headNode = findOutTheChainHead(annotToConsiderForChain, (String) annotSets.getSelectedItem());
1417        if (headNode != null) {
1418          popup1 = new JPopupMenu();
1419          popup1.setBackground(UIManager.getLookAndFeelDefaults().
1420                               getColor("ToolTip.background"));
1421          JLabel label1 = new JLabel("Annotation co-referenced to : \"" +
1422                                     headNode.toString() + "\"");
1423          popup1.setLayout(new FlowLayout());
1424          popup1.add(label1);
1425          if (popupWindow != null && popupWindow.isVisible()) {
1426            popupWindow.setVisible(false);
1427          }
1428          popup1.setVisible(true);
1429          popup1.show(textPane, (int) mousePoint.getX(), (int) mousePoint.getY());
1430        }
1431        else {
1432          popupWindow.setVisible(false);
1433          ArrayList set = new ArrayList(currentSelections.keySet());
1434          Collections.sort(set);
1435          set.add(0, "[New Chain]");
1436          model = new DefaultComboBoxModel(set.toArray());
1437          list.setModel(model);
1438          listEditor.setItem("");
1439          label.setText("Add \"" + getString(annotToConsiderForChain) +
1440                        "\" to ");
1441          Point topLeft = textPane.getLocationOnScreen();
1442          int x = topLeft.x + (int) mousePoint.getX();
1443          int y = topLeft.y + (int) mousePoint.getY();
1444          popupWindow.setLocation(x, y);
1445          if (popup1.isVisible()) {
1446            popup1.setVisible(false);
1447          }
1448          popupWindow.pack();
1449          popupWindow.setVisible(true);
1450          listEditor.requestFocus();
1451
1452          if (firstTime) {
1453            firstTime = false;
1454            popupWindow.pack();
1455            popupWindow.repaint();
1456            listEditor.requestFocus();
1457          }
1458        }
1459      }
1460    }
1461
1462    public void setTextLocation(int textLocation) {
1463      this.textLocation = textLocation;
1464    }
1465
1466    public void setMousePointer(Point point) {
1467      this.mousePoint = point;
1468    }
1469
1470    /** Custom Editor for the ComboBox to enable key events */
1471    private class ListEditor
1472        extends KeyAdapter
1473        implements ComboBoxEditor {
1474      JTextField myField = new JTextField(20);
1475      AddAction action = null;
1476      Vector myList = new Vector();
1477
1478      public ListEditor(AddAction action) {
1479        this.action = action;
1480        myField.addKeyListener(this);
1481      }
1482
1483      public void addActionListener(ActionListener al) {
1484        myField.addActionListener(al);
1485      }
1486
1487      public void removeActionListener(ActionListener al) {
1488        myField.removeActionListener(al);
1489      }
1490
1491      public Component getEditorComponent() {
1492        return myField;
1493      }
1494
1495      public Object getItem() {
1496        return myField.getText();
1497      }
1498
1499      public void selectAll() {
1500        if (myField.getText() != null && myField.getText().length() > 0) {
1501          myField.setSelectionStart(0);
1502          myField.setSelectionEnd(myField.getText().length());
1503        }
1504      }
1505
1506      public void setItem(Object item) {
1507        myField.setText( (String) item);
1508        field = myField.getText();
1509      }
1510
1511      public void requestFocus() {
1512        myField.requestFocus();
1513      }
1514
1515      public void keyReleased(KeyEvent ke) {
1516        if (myField.getText() == null) {
1517          myField.setText("");
1518          field = myField.getText();
1519        }
1520
1521        if (ke.getKeyCode() == KeyEvent.VK_DOWN) {
1522          if (myList.size() == 1) {
1523            myField.setText( (String) myList.get(0));
1524          }
1525          else if (list.getSelectedIndex() < list.getModel().getSize() - 1) {
1526            list.setSelectedIndex(list.getSelectedIndex());
1527            myField.setText( (String) list.getSelectedItem());
1528          }
1529          field = myField.getText();
1530          myField.requestFocus();
1531          return;
1532        }
1533        else if (ke.getKeyCode() == KeyEvent.VK_UP) {
1534          if (list.getSelectedIndex() > 0) {
1535            list.setSelectedIndex(list.getSelectedIndex());
1536          }
1537          myField.setText( (String) list.getSelectedItem());
1538          field = myField.getText();
1539          return;
1540        }
1541        else if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
1542          field = myField.getText();
1543          action.actionPerformed(new ActionEvent(add,
1544                                                 ActionEvent.ACTION_PERFORMED,
1545                                                 "add"));
1546          return;
1547        }
1548        else if (ke.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
1549        }
1550        else if (Character.isJavaIdentifierPart(ke.getKeyChar()) ||
1551                 Character.isSpaceChar(ke.getKeyChar()) ||
1552                 Character.isDefined(ke.getKeyChar())) {
1553        }
1554        else {
1555          return;
1556        }
1557
1558        String startWith = myField.getText();
1559        myList = new Vector();
1560        ArrayList set = new ArrayList(currentSelections.keySet());
1561        Collections.sort(set);
1562        set.add(0, "[New Chain]");
1563        boolean first = true;
1564        for (int i = 0; i < set.size(); i++) {
1565          String currString = (String) set.get(i);
1566          if (currString.toLowerCase().startsWith(startWith.toLowerCase())) {
1567            if (first) {
1568              myField.setText(currString.substring(0, startWith.length()));
1569              first = false;
1570            }
1571            myList.add(currString);
1572          }
1573        }
1574        ComboBoxModel model = new DefaultComboBoxModel(myList);
1575        list.setModel(model);
1576        myField.setText(startWith);
1577        field = myField.getText();
1578        list.showPopup();
1579      }
1580    }
1581
1582    private class AddAction
1583        extends AbstractAction {
1584      public void actionPerformed(ActionEvent ae) {
1585        if (ae.getSource() == cancel) {
1586          popupWindow.setVisible(false);
1587          return;
1588        }
1589        else if (ae.getSource() == add) {
1590          if (field.length() == 0) {
1591            try {
1592              JOptionPane.showMessageDialog(Main.getMainFrame(),
1593                                            "No Chain Selected",
1594                                            "New Chain - Error",
1595                                            JOptionPane.ERROR_MESSAGE);
1596            }
1597            catch (Exception e) {
1598              e.printStackTrace();
1599            }
1600            return;
1601          }
1602          else {
1603            // we want to add this
1604            // now first find out the annotation
1605            Annotation ann = annotToConsiderForChain;
1606            if (ann == null)
1607              return;
1608            // yes it is available
1609            // find out the CorefTreeNode for the chain under which it is to be inserted
1610            if (field.equals("[New Chain]")) {
1611              // we want to add this
1612              // now first find out the annotation
1613              if (ann == null)
1614                return;
1615              CorefTreeNode chainNode = findOutChainNode(getString(ann), (String) annotSets.getSelectedItem());
1616              if (chainNode != null) {
1617                try {
1618                  JOptionPane.showMessageDialog(Main.getMainFrame(),
1619                                                "Chain with " + getString(ann) +
1620                                                " title already exists",
1621                                                "New Chain - Error",
1622                                                JOptionPane.ERROR_MESSAGE);
1623                }
1624                catch (Exception e) {
1625                  e.printStackTrace();
1626                }
1627                return;
1628              }
1629
1630              popupWindow.setVisible(false);
1631
1632              String currentSet = (String) annotSets.getSelectedItem();
1633              currentSet = (currentSet.equals(DEFAULT_ANNOTSET_NAME)) ? null :
1634                           currentSet;
1635
1636              Map matchesMap = null;
1637              Object matchesMapObject = document.getFeatures().get(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME);
1638              if(matchesMapObject instanceof Map) {
1639                matchesMap = (Map) matchesMapObject;
1640              }
1641
1642              if (matchesMap == null) {
1643                matchesMap = new HashMap();
1644              }
1645
1646              java.util.List matches = (java.util.List) matchesMap.get(
1647                  currentSet);
1648              ArrayList tempList = new ArrayList();
1649              tempList.add(ann.getId());
1650              if (matches == null)
1651                matches = new ArrayList();
1652              matches.add(tempList);
1653              matchesMap.put(currentSet, matches);
1654              document.getFeatures().put(ANNIEConstants.
1655                                         DOCUMENT_COREF_FEATURE_NAME,
1656                                         matchesMap);
1657              return;
1658            }
1659
1660            CorefTreeNode chainNode = findOutChainNode(field, (String) annotSets.getSelectedItem());
1661            HashMap chains = (HashMap)
1662                             corefChains.get(corefAnnotationSetNodesMap.get(
1663                annotSets.getSelectedItem()));
1664            if (chainNode == null) {
1665              try {
1666                JOptionPane.showMessageDialog(Main.getMainFrame(),
1667                                              "Incorrect Chain Title",
1668                                              "New Chain - Error",
1669                                              JOptionPane.ERROR_MESSAGE);
1670              }
1671              catch (Exception e) {
1672                e.printStackTrace();
1673              }
1674              return;
1675            }
1676            popupWindow.setVisible(false);
1677            ArrayList ids = (ArrayList) chains.get(chainNode);
1678
1679            Map matchesMap = null;
1680            Object matchesMapObject = document.getFeatures().get(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME);
1681            if(matchesMapObject instanceof Map) {
1682              matchesMap = (Map) matchesMapObject;
1683            }
1684
1685            if (matchesMap == null) {
1686              matchesMap = new HashMap();
1687            }
1688            String currentSet = (String) annotSets.getSelectedItem();
1689            currentSet = (currentSet.equals(DEFAULT_ANNOTSET_NAME)) ? null :
1690                         currentSet;
1691            java.util.List matches = (java.util.List) matchesMap.get(currentSet);
1692            if (matches == null)
1693              matches = new ArrayList();
1694            int index = matches.indexOf(ids);
1695            if (index != -1) {
1696              ArrayList tempIds = (ArrayList) matches.get(index);
1697              tempIds.add(ann.getId());
1698              matches.set(index, tempIds);
1699              matchesMap.put(currentSet, matches);
1700              document.getFeatures().put(ANNIEConstants.
1701                                         DOCUMENT_COREF_FEATURE_NAME,
1702                                         matchesMap);
1703            }
1704            return;
1705          }
1706        }
1707      }
1708    }
1709  }
1710
1711  /** When user hovers over the chainnodes */
1712  protected class ChainToolTipAction
1713      extends AbstractAction {
1714
1715    int textLocation;
1716    Point mousePoint;
1717    JPopupMenu popup = new JPopupMenu();
1718
1719    public ChainToolTipAction() {
1720      popup.setBackground(UIManager.getLookAndFeelDefaults().
1721                          getColor("ToolTip.background"));
1722    }
1723
1724    public void actionPerformed(ActionEvent ae) {
1725
1726      int index = -1;
1727      if (highlightedChainAnnotsOffsets != null) {
1728        for (int i = 0; i < highlightedChainAnnotsOffsets.length; i += 2) {
1729          if (textLocation >= highlightedChainAnnotsOffsets[i] &&
1730              textLocation <= highlightedChainAnnotsOffsets[i + 1]) {
1731            index = (i == 0) ? i : i / 2;
1732            break;
1733          }
1734        }
1735      }
1736
1737      // yes it is put on highlighted so show the annotationType
1738      if (highlightedChainAnnotsOffsets != null &&
1739          index < highlightedChainAnnotsOffsets.length && index >= 0) {
1740
1741        if (popupWindow != null && popupWindow.isVisible()) {
1742          popupWindow.setVisible(false);
1743        }
1744
1745        popup.setVisible(false);
1746        popup.removeAll();
1747        final int tempIndex = index;
1748        CorefTreeNode chainHead = findOutTheChainHead( (Annotation)
1749            highlightedChainAnnots.get(index), (String) annotSets.getSelectedItem());
1750        final HashMap tempMap = new HashMap();
1751        popup.setLayout(new FlowLayout(FlowLayout.LEFT));
1752        if (chainHead != null) {
1753          JPanel tempPanel = new JPanel();
1754          tempPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
1755          tempPanel.add(new JLabel(chainHead.toString()));
1756          tempPanel.setBackground(UIManager.getLookAndFeelDefaults().
1757                                  getColor("ToolTip.background"));
1758          final JButton deleteButton = new JButton("Delete");
1759          tempPanel.add(deleteButton);
1760          popup.add(tempPanel);
1761          deleteButton.setActionCommand(chainHead.toString());
1762          tempMap.put(chainHead.toString(), chainHead);
1763          deleteButton.addActionListener(new ActionListener() {
1764            public void actionPerformed(ActionEvent ae) {
1765              try {
1766                int confirm = JOptionPane.showConfirmDialog(Main.getMainFrame(),
1767                    "Are you sure?", "Removing reference...",
1768                    JOptionPane.YES_NO_OPTION);
1769                if (confirm == JOptionPane.YES_OPTION) {
1770                  popup.setVisible(false);
1771                  // remove it
1772                  removeChainReference( (Annotation) highlightedChainAnnots.get(
1773                      tempIndex),
1774                      (CorefTreeNode) tempMap.get(deleteButton.getActionCommand()));
1775                }
1776              }
1777              catch (Exception e1) {
1778                e1.printStackTrace();
1779              }
1780            }
1781          });
1782        }
1783        //label.setText("Remove \""+getString((Annotation) highlightedChainAnnots.get(index)) + "\" from \""+ findOutTheChainHead((Annotation) highlightedChainAnnots.get(index)).toString()+"\"");
1784        popup.revalidate();
1785        if (popupWindow != null && popupWindow.isVisible()) {
1786          popupWindow.setVisible(false);
1787        }
1788        popup.setVisible(true);
1789        popup.show(textPane, (int) mousePoint.getX(), (int) mousePoint.getY());
1790      }
1791    }
1792
1793    public void setTextLocation(int textLocation) {
1794      this.textLocation = textLocation;
1795    }
1796
1797    public void setMousePointer(Point point) {
1798      this.mousePoint = point;
1799    }
1800
1801  }
1802
1803  // Class that represents each individual tree node in the corefTree
1804  protected class CorefTreeNode
1805      extends DefaultMutableTreeNode {
1806    public final static int ROOT_NODE = 0;
1807    public final static int ANNOTSET_NODE = 1;
1808    public final static int CHAIN_NODE = 2;
1809
1810    private int type;
1811
1812    public CorefTreeNode(Object value, boolean allowsChildren, int type) {
1813      super(value, allowsChildren);
1814      this.type = type;
1815    }
1816
1817    public int getType() {
1818      return this.type;
1819    }
1820
1821  }
1822
1823  /**
1824   * Action for mouseClick on the Tree
1825   */
1826  protected class CorefTreeMouseListener
1827      extends MouseAdapter {
1828
1829    public void mouseClicked(MouseEvent me) { }
1830    public void mouseReleased(MouseEvent me) { }
1831
1832    public void mousePressed(MouseEvent me) {
1833      if (popupWindow != null && popupWindow.isVisible()) {
1834        popupWindow.setVisible(false);
1835      }
1836      textPane.removeAll();
1837      // ok now find out the currently selected node
1838      int x = me.getX();
1839      int y = me.getY();
1840      int row = corefTree.getRowForLocation(x, y);
1841      TreePath path = corefTree.getPathForRow(row);
1842
1843      if (path != null) {
1844        final CorefTreeNode node = (CorefTreeNode) path.
1845                                   getLastPathComponent();
1846
1847        // if it only chainNode
1848        if (node.getType() != CorefTreeNode.CHAIN_NODE) {
1849          return;
1850        }
1851
1852        // see if user clicked the right click
1853        if (SwingUtilities.isRightMouseButton(me)) {
1854          // it is right click
1855          // we need to show the popup window
1856          final JPopupMenu popup = new JPopupMenu();
1857          JButton delete = new JButton("Delete");
1858          delete.setToolTipText("Delete Chain");
1859          ToolTipManager.sharedInstance().registerComponent(delete);
1860          JButton cancel = new JButton("Close");
1861          cancel.setToolTipText("Closes this popup");
1862          JButton changeColor = new JButton("Change Color");
1863          changeColor.setToolTipText("Changes Color");
1864          ToolTipManager.sharedInstance().registerComponent(cancel);
1865          ToolTipManager.sharedInstance().registerComponent(changeColor);
1866          JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
1867          panel.setOpaque(false);
1868          panel.add(changeColor);
1869          panel.add(delete);
1870          panel.add(cancel);
1871          popup.setLayout(new BorderLayout());
1872          popup.setOpaque(true);
1873          popup.setBackground(UIManager.getLookAndFeelDefaults().
1874                              getColor("ToolTip.background"));
1875          popup.add(new JLabel("Chain \"" + node.toString() + "\""),
1876                    BorderLayout.NORTH);
1877          popup.add(panel, BorderLayout.SOUTH);
1878
1879          changeColor.addActionListener(new ActionListener() {
1880            public void actionPerformed(ActionEvent ae) {
1881              String currentAnnotSet = (String) annotSets.getSelectedItem();
1882              currentColors = (HashMap) colorChainsMap.get(currentAnnotSet);
1883              Color colour = (Color) currentColors.get(node.toString());
1884              Color col = JColorChooser.showDialog(getGUI(),
1885                  "Select colour for \"" + node.toString() + "\"",
1886                  colour);
1887              if (col != null) {
1888                Color colAlpha = new Color(col.getRed(), col.getGreen(),
1889                                           col.getBlue(), 128);
1890
1891                // make change in the datastructures
1892                currentColors.put(node.toString(),colAlpha);
1893                colorChainsMap.put(currentAnnotSet, currentColors);
1894                // and redraw the tree
1895                corefTree.repaint();
1896
1897                // remove all highlights
1898                ArrayList allHighlights = new ArrayList();
1899                if(typeSpecificHighlightedTags != null)
1900                  allHighlights.addAll(typeSpecificHighlightedTags);
1901                if(highlightedTags != null) {
1902                  Iterator iter = highlightedTags.values().iterator();
1903                  while(iter.hasNext()) {
1904                    ArrayList highlights = (ArrayList) iter.next();
1905                    allHighlights.addAll(highlights);
1906                  }
1907                }
1908                for (int i = 0; i < allHighlights.size(); i++) {
1909                  highlighter.removeHighlight(allHighlights.get(i));
1910                }
1911
1912                //highlighter.removeAllHighlights();
1913                highlightedTags = null;
1914                highlightAnnotations();
1915                typeSpecificHighlightedTags = null;
1916                showTypeWiseAnnotations();
1917              }
1918              popup.setVisible(false);
1919            }
1920          });
1921
1922          delete.addActionListener(new ActionListener() {
1923            public void actionPerformed(ActionEvent ae) {
1924              // get the ids of current chainNode
1925              HashMap chains = (HashMap)
1926                               corefChains.get(corefAnnotationSetNodesMap.get(
1927                  annotSets.getSelectedItem()));
1928              ArrayList ids = (ArrayList) chains.get(node);
1929
1930              String currentSet = (String) annotSets.getSelectedItem();
1931              currentSet = (currentSet.equals(DEFAULT_ANNOTSET_NAME)) ? null : currentSet;
1932
1933              // now search this in the document feature map
1934              Map matchesMap = null;
1935              java.util.List matches = null;
1936
1937              Object matchesMapObject = document.getFeatures().get(ANNIEConstants.DOCUMENT_COREF_FEATURE_NAME);
1938              if(matchesMapObject instanceof Map) {
1939                matchesMap = (Map) matchesMapObject;
1940                matches = (java.util.List) matchesMap.get(currentSet);
1941              }
1942
1943              if(matchesMap == null) {
1944                matchesMap = new HashMap();
1945              }
1946
1947              if (matches == null)
1948                matches = new ArrayList();
1949
1950              int index = matches.indexOf(ids);
1951              if (index != -1) {
1952                // yes found
1953                matches.remove(index);
1954                matchesMap.put(currentSet, matches);
1955                document.getFeatures().put(ANNIEConstants.
1956                                           DOCUMENT_COREF_FEATURE_NAME,
1957                                           matchesMap);
1958              }
1959              popup.setVisible(false);
1960            }
1961          });
1962
1963          cancel.addActionListener(new ActionListener() {
1964            public void actionPerformed(ActionEvent ae) {
1965              popup.setVisible(false);
1966            }
1967          });
1968          popup.setVisible(true);
1969          popup.show(corefTree, x, y);
1970          return;
1971        }
1972
1973        boolean isSelected = ! ( (Boolean) currentSelections.get(node.toString())).
1974                             booleanValue();
1975        currentSelections.put(node.toString(), new Boolean(isSelected));
1976
1977        // so now we need to highlight all the stuff
1978        highlightAnnotations();
1979        corefTree.repaint();
1980        corefTree.updateUI();
1981        corefTree.repaint();
1982        corefTree.updateUI();
1983
1984      }
1985    }
1986  }
1987
1988  /**
1989   * This method uses the java.util.prefs.Preferences and get the color
1990   * for particular annotationType.. This color could have been saved
1991   * by the AnnotationSetsView
1992   * @param annotationType
1993   * @return
1994   */
1995  private Color getColor(String annotationType) {
1996    java.util.prefs.Preferences prefRoot = null;
1997    try {
1998      prefRoot = java.util.prefs.Preferences.userNodeForPackage(Class.forName(
1999          "gate.gui.docview.AnnotationSetsView"));
2000    }
2001    catch (Exception e) {
2002      e.printStackTrace();
2003    }
2004    int rgba = prefRoot.getInt(annotationType, -1);
2005    Color colour;
2006    if (rgba == -1) {
2007      //initialise and save
2008      float components[] = colorGenerator.getNextColor().getComponents(null);
2009      colour = new Color(components[0],
2010                         components[1],
2011                         components[2],
2012                         0.5f);
2013      int rgb = colour.getRGB();
2014      int alpha = colour.getAlpha();
2015      rgba = rgb | (alpha << 24);
2016      prefRoot.putInt(annotationType, rgba);
2017
2018    }
2019    else {
2020      colour = new Color(rgba, true);
2021    }
2022    return colour;
2023  }
2024
2025  /**
2026   * Cell renderer to add the checkbox in the tree
2027   */
2028  protected class CorefTreeCellRenderer
2029      extends JPanel
2030      implements TreeCellRenderer {
2031
2032    private JCheckBox check;
2033    private JLabel label;
2034
2035    /**
2036     * Constructor
2037     * @param owner
2038     */
2039    public CorefTreeCellRenderer() {
2040      setOpaque(true);
2041      check = new JCheckBox();
2042      check.setBackground(Color.white);
2043      label = new JLabel();
2044      setLayout(new BorderLayout(5, 10));
2045      add(check, BorderLayout.WEST);
2046      add(label, BorderLayout.CENTER);
2047    }
2048
2049    /**
2050     * Renderer class
2051     */
2052    public Component getTreeCellRendererComponent(JTree tree, Object value,
2053                                                  boolean isSelected,
2054                                                  boolean expanded,
2055                                                  boolean leaf, int row,
2056                                                  boolean hasFocus) {
2057
2058      CorefTreeNode userObject = (CorefTreeNode) value;
2059      label.setText(userObject.toString());
2060      this.setSize(label.getWidth(),
2061                   label.getFontMetrics(label.getFont()).getHeight() * 2);
2062      tree.expandRow(row);
2063      if (userObject.getType() == CorefTreeNode.ROOT_NODE || userObject.getType() ==
2064          CorefTreeNode.ANNOTSET_NODE) {
2065        this.setBackground(Color.white);
2066        this.check.setVisible(false);
2067        return this;
2068      }
2069      else {
2070        this.setBackground( (Color) currentColors.get(userObject.toString()));
2071        check.setVisible(true);
2072        check.setBackground(Color.white);
2073      }
2074
2075      // if node should be selected
2076      boolean selected = ( (Boolean) currentSelections.get(userObject.toString())).
2077                         booleanValue();
2078      check.setSelected(selected);
2079      return this;
2080    }
2081  }
2082}
2083