1   /*  CorpusAnnotDiffDialog.java
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    *  Angel Kirilov (mod AnnotDiffDialog), 22/Aug/2002
10   *
11   *  $Id: CorpusAnnotDiffDialog.java,v 1.8 2005/01/11 13:51:34 ian Exp $
12   *
13   */
14  package gate.gui;
15  
16  import java.awt.*;
17  import java.awt.event.*;
18  import java.util.*;
19  
20  import javax.swing.*;
21  
22  import gate.*;
23  import gate.annotation.AnnotationDiff;
24  import gate.annotation.CorpusAnnotationDiff;
25  import gate.creole.*;
26  
27  /** This class wraps the {@link gate.annotation.CorpusAnnotationDiff} one. It adds the
28    * the GUI functionality needed to set up params for CorpusAnnotationDiff and also
29    * adds the CorpusAnnotationDiff as a tool in GATE.
30    */
31  class CorpusAnnotDiffDialog extends JFrame {
32    // Local data needed in initLocalData() method
33  
34    /** A map from documentName 2 GATE document It is used to display names in
35      * combo boxes
36      */
37    Map  corpusMap = null;
38    /** A map from AnnotationSetNames 2 AnnotationSets, used to display AnnotSets
39      * in combo boxes
40      */
41    Map keyAnnotationSetMap = null;
42    /** A map from AnnotationSetNames 2 AnnotationSets, used to display AnnotSets
43      * in combo boxes
44      */
45    Map responseAnnotationSetMap = null;
46    /** A map from Annotation types 2 AnnotationSchema,
47      * used to display annotations in combo boxes
48      */
49    Map  typesMap = null;
50    /** A set containing annot types for calculating falsePoz measure*/
51    Set  falsePozTypes = null;
52    /** AnnotDiff's tool parent frame*/
53    MainFrame mainFrame = null;
54    /** A pointer to this object used in some internal classes*/
55    CorpusAnnotDiffDialog thisAnnotDiffDialog = null;
56  
57    // GUI components used in initGuiComponents()
58    /** Renders key documents*/
59    JComboBox keyDocComboBox = null;
60    /** Renders response documents*/
61    JComboBox responseDocComboBox = null;
62    /** Renders annot types which come from intersecting keyAnnotSet with
63      * responseAnnotSet
64      */
65    JComboBox typesComboBox = null;
66    /** Renders annot types used in calculating falsPoz measure*/
67    JComboBox falsePozTypeComboBox = null;
68    /** Renders the annotation sets that come from the response document and
69      * used in calculating falsePoz measure
70      */
71    JComboBox responseDocAnnotSetFalsePozComboBox = null;
72    /** Renders the annotation sets that come from the key document*/
73    JComboBox keyDocAnnotSetComboBox = null;
74    /** Renders the annotation sets that come from the response document*/
75    JComboBox responseDocAnnotSetComboBox = null;
76    /** Renders the text label for keyDocAnnotSetComboBox*/
77    JLabel keyLabel = null;
78    /** Renders the text label for responseDocAnnotSetComboBox*/
79    JLabel responseLabel = null;
80    /** Renders the text label for typesComboBox*/
81    JLabel typesLabel = null;
82    /** Renders the text label for falsePozTypeComboBox*/
83    JLabel falsePozLabel = null;
84    /** Renders the text label for keyDocComboBox*/
85    JLabel keyDocAnnotSetLabel = null;
86    /** Renders the text label for responseDocComboBox*/
87    JLabel responseDocAnnotSetLabel = null;
88    /** Renders the text label for responseDocComboBox used in calc falsePoz.*/
89    JLabel responseDocAnnotSetFalsePozLabel = null;
90    /** Renders the label for weightTextField*/
91    JLabel weightLabel = null;
92    /** Renders the value of weight used in calculating F measure*/
93    JTextField weightTextField = null;
94    /** Renders the button which triggers the diff process*/
95    JButton evalButton = null;
96    /** A reference to annotDiff object that does the diff*/
97    CorpusAnnotationDiff annotDiff = null;
98    /** A split between configuration pannel and AnnotDifff*/
99    JSplitPane jSplit = null;
100   /** A Radio button for selecting certian features that would be used in diff*/
101   JRadioButton someFeaturesRadio = null;
102   /** A Radio button for selecting no features that would be used in diff*/
103   JRadioButton noFeaturesRadio = null;
104   /** A Radio button for selecting all features that would be used in diff*/
105   JRadioButton allFeaturesRadio = null;
106   /** A group buttons for the 3 Radio buttons above*/
107   ButtonGroup groupRadios = null;
108   /** A label for Radio Buttons selection*/
109   JLabel selectFeaturesLabel = null;
110   /** A selection dialog used in case that the user selects some radio button*/
111   CollectionSelectionDialog featureSelectionDialog = null;
112 
113   /** Constructs an annotDiffDialog object having as parent aMainFrame
114     * @param aMainFrame the parent frame for this AnnotDiffDialog. If can be
115     * <b>null</b>, meaning no parent.
116     */
117   public CorpusAnnotDiffDialog(MainFrame aMainFrame){
118     mainFrame = aMainFrame;
119     thisAnnotDiffDialog = this;
120     initLocalData();
121     initGuiComponents();
122     initListeners();
123   }//CorpusAnnotDiffDialog
124 
125   /** This method is called when adding or removing a document*/
126   public void updateData(){
127     corpusMap = null;
128     typesMap = null;
129     falsePozTypes = null;
130     this.removeAll();
131 
132     SwingUtilities.invokeLater(new Runnable(){
133       public void run(){
134         initLocalData();
135         initGuiComponents();
136         initListeners();
137       }
138     });
139   }//updateData()
140 
141   /** Initialises the data needed to set up {@link gate.annotation.AnnotationDiff}
142     * GUI components will be build using this data.
143     */
144   public void initLocalData(){
145     annotDiff = new CorpusAnnotationDiff();
146     // Get all available documents and construct the documentsMap
147     // (docName, gate.Document) pairs
148     corpusMap = new HashMap();
149 
150     CreoleRegister registry =  Gate.getCreoleRegister();
151 
152     java.util.List instantiations;
153     Iterator iter;
154     Resource resource;
155     String corpName;
156 
157     corpusMap.put("Not selected", null);
158     ResourceData resourceData =
159                         (ResourceData)registry.get("gate.corpora.CorpusImpl");
160     if(resourceData != null && !resourceData.getInstantiations().isEmpty()){
161 
162       instantiations = resourceData.getInstantiations();
163       iter = instantiations.iterator();
164       while (iter.hasNext()) {
165         resource = (Resource) iter.next();
166         corpName = resource.getName();
167         gate.Corpus corp = (Corpus) resource;
168         // add it to the Map
169         corpusMap.put(corpName, corp);
170       }// while
171     } // if
172 
173     // add serialized one
174     resourceData = (ResourceData)registry.get("gate.corpora.SerialCorpusImpl");
175     if(resourceData != null && !resourceData.getInstantiations().isEmpty()){
176 
177       instantiations = resourceData.getInstantiations();
178       iter = instantiations.iterator();
179       while (iter.hasNext()) {
180         resource = (Resource) iter.next();
181         corpName = resource.getName();
182         gate.Corpus corp = (Corpus) resource;
183         // add it to the Map
184         corpusMap.put(corpName, corp);
185       }// while
186     } // if
187 
188     // add database one
189     resourceData = (ResourceData)registry.get("gate.corpora.DatabaseCorpusImpl");
190     if(resourceData != null && !resourceData.getInstantiations().isEmpty()){
191 
192       instantiations = resourceData.getInstantiations();
193       iter = instantiations.iterator();
194       while (iter.hasNext()) {
195         resource = (Resource) iter.next();
196         corpName = resource.getName();
197         gate.Corpus corp = (Corpus) resource;
198         // add it to the Map
199         corpusMap.put(corpName, corp);
200       }// while
201     } // if
202 
203 //    if(corpusMap.isEmpty()) corpusMap.put("No corpuses found",null);
204 
205     keyAnnotationSetMap = new TreeMap();
206     responseAnnotationSetMap = new TreeMap();
207 
208     typesMap = new TreeMap();
209     // init types map with Type,AnnotationSchema pairs
210     typesMap.put("No annot.",null);
211 
212     // init falsePozTypes
213     falsePozTypes = new TreeSet();
214     falsePozTypes.add("No annot.");
215   }// initLocalData
216 
217   /**
218     * This method initializes the GUI components. Data is loaded from localData
219     * fields.
220     */
221   public void initGuiComponents(){
222 
223     //Initialise GUI components
224     //this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
225     this.getContentPane().setLayout(new BorderLayout());
226     // init keyDocComboBox
227     Object[] corpuses = corpusMap.keySet().toArray();
228     String corpusName;
229     int noneindex = 0;
230     for(int i=0; i<corpuses.length; ++i) {
231       corpusName = (String) corpuses[i];
232       if("Not selected".equalsIgnoreCase(corpusName)) {
233         noneindex = i;
234         break;
235       } // if
236     } // for
237     keyDocComboBox = new JComboBox(corpuses);
238     keyDocComboBox.setSelectedIndex(noneindex);
239     keyDocComboBox.setEditable(false);
240     keyDocComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
241     Dimension dim = new Dimension(150,keyDocComboBox.getPreferredSize().height);
242     keyDocComboBox.setPreferredSize(dim);
243     keyDocComboBox.setMaximumSize(dim);
244     keyDocComboBox.setMinimumSize(dim);
245     keyDocComboBox.setRenderer(new MyCellRenderer(Color.green, Color.black));
246     // init its label
247     keyLabel = new JLabel("Select the KEY corpus");
248     keyLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
249     keyLabel.setOpaque(true);
250     keyLabel.setFont(keyLabel.getFont().deriveFont(Font.BOLD));
251     keyLabel.setForeground(Color.black);
252     keyLabel.setBackground(Color.green);
253 
254     // init keyDocAnnotSetComboBox
255     Set comboAsCont = new TreeSet(keyAnnotationSetMap.keySet());
256     keyDocAnnotSetComboBox = new JComboBox(comboAsCont.toArray());
257     keyDocAnnotSetComboBox.setEditable(false);
258     keyDocAnnotSetComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
259     // init its label
260     keyDocAnnotSetLabel = new JLabel("Select the KEY annotation set");
261     keyDocAnnotSetLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
262     keyDocAnnotSetLabel.setOpaque(true);
263     keyDocAnnotSetLabel.setFont(
264                   keyDocAnnotSetLabel.getFont().deriveFont(Font.BOLD));
265     keyDocAnnotSetLabel.setForeground(Color.black);
266     keyDocAnnotSetLabel.setBackground(Color.green);
267 
268     // init responseDocComboBox
269     responseDocComboBox = new JComboBox(corpuses);
270     responseDocComboBox.setSelectedIndex(noneindex);
271     responseDocComboBox.setEditable(false);
272     responseDocComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
273     responseDocComboBox.setPreferredSize(dim);
274     responseDocComboBox.setMaximumSize(dim);
275     responseDocComboBox.setMinimumSize(dim);
276     responseDocComboBox.setRenderer(new MyCellRenderer(Color.red, Color.black));
277     // init its label
278     responseLabel = new JLabel("Select the RESPONSE corpus");
279     responseLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
280     responseLabel.setOpaque(true);
281     responseLabel.setFont(responseLabel.getFont().deriveFont(Font.BOLD));
282     responseLabel.setBackground(Color.red);
283     responseLabel.setForeground(Color.black);
284 
285     // init responseDocAnnotSetComboBox
286     comboAsCont = new TreeSet(responseAnnotationSetMap.keySet());
287     responseDocAnnotSetComboBox = new JComboBox(comboAsCont.toArray());
288     responseDocAnnotSetComboBox.setEditable(false);
289     responseDocAnnotSetComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
290     // init its label
291     responseDocAnnotSetLabel = new JLabel("Select the RESPONSE annot set");
292     responseDocAnnotSetLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
293     responseDocAnnotSetLabel.setOpaque(true);
294     responseDocAnnotSetLabel.setFont(
295                   responseDocAnnotSetLabel.getFont().deriveFont(Font.BOLD));
296     responseDocAnnotSetLabel.setForeground(Color.black);
297     responseDocAnnotSetLabel.setBackground(Color.red);
298 
299     // init responseDocAnnotSetFalsePozComboBox
300     // This combo is used in calculating False Poz
301     comboAsCont = new TreeSet(responseAnnotationSetMap.keySet());
302     responseDocAnnotSetFalsePozComboBox = new JComboBox(comboAsCont.toArray());
303     responseDocAnnotSetFalsePozComboBox.setEditable(false);
304     responseDocAnnotSetFalsePozComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
305     // init its label
306     responseDocAnnotSetFalsePozLabel = new JLabel("Select the RESPONSE annot set");
307     responseDocAnnotSetFalsePozLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
308     responseDocAnnotSetFalsePozLabel.setOpaque(true);
309     responseDocAnnotSetFalsePozLabel.setFont(
310               responseDocAnnotSetFalsePozLabel.getFont().deriveFont(Font.BOLD));
311     responseDocAnnotSetFalsePozLabel.setForeground(Color.black);
312     responseDocAnnotSetFalsePozLabel.setBackground(Color.red);
313 
314 
315     // init typesComboBox
316     Vector typesCont = new Vector(typesMap.keySet());
317     Collections.sort(typesCont);
318     typesComboBox = new JComboBox(typesCont);
319     typesComboBox.setEditable(false);
320     typesComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
321     // init its label
322     typesLabel = new JLabel("Select annot. type");
323     typesLabel.setFont(typesLabel.getFont().deriveFont(Font.BOLD));
324     typesLabel.setOpaque(true);
325     typesLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
326 
327     // init falsePozTypeComboBox
328     falsePozTypeComboBox = new JComboBox(falsePozTypes.toArray());
329     falsePozTypeComboBox.setEditable(false);
330     falsePozTypeComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
331     // init its label
332     falsePozLabel = new JLabel("Select annot. type for FalsePoz");
333     falsePozLabel.setFont(falsePozLabel.getFont().deriveFont(Font.BOLD));
334     falsePozLabel.setOpaque(true);
335     falsePozLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
336 
337     // init weightTextField
338     weightTextField = new JTextField(
339                               (new Double(AnnotationDiff.weight)).toString());
340     weightTextField.setAlignmentX(Component.LEFT_ALIGNMENT);
341     // init its label
342     weightLabel = new JLabel("Weight for F-Measure");
343     weightLabel.setFont(falsePozLabel.getFont().deriveFont(Font.BOLD));
344     weightLabel.setOpaque(true);
345     weightLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
346 
347     // Set initial dimmension for weightTextField
348     Dimension d = new Dimension(weightLabel.getPreferredSize().width,
349                                     weightTextField.getPreferredSize().height);
350     weightTextField.setMinimumSize(d);
351     weightTextField.setMaximumSize(d);
352     weightTextField.setPreferredSize(d);
353 
354     // evaluate button
355     evalButton = new JButton("Evaluate");
356     evalButton.setFont(evalButton.getFont().deriveFont(Font.BOLD));
357 
358     // Some features radio Button
359     someFeaturesRadio = new JRadioButton("Some");
360     someFeaturesRadio.setToolTipText("Select some features from the key"+
361       " annotation set, that will be taken into consideration"+
362       " in the diff process.");
363     // No features RB
364     noFeaturesRadio = new JRadioButton("None");
365     noFeaturesRadio.setToolTipText("No features from the key"+
366       " annotation set will be taken into consideration"+
367       " in the diff process.");
368     // All features RB
369     allFeaturesRadio = new JRadioButton("All");
370     allFeaturesRadio.setSelected(true);
371     allFeaturesRadio.setToolTipText("All features from the key"+
372       " annotation set will be taken into consideration"+
373       " in the diff process.");
374     // Add radio buttons to the group
375     groupRadios = new ButtonGroup();
376     groupRadios.add(allFeaturesRadio);
377     groupRadios.add(someFeaturesRadio);
378     groupRadios.add(noFeaturesRadio);
379     // The label for the Features radio buttons group
380     selectFeaturesLabel = new JLabel("Features");
381     selectFeaturesLabel.setFont(falsePozLabel.getFont().deriveFont(Font.BOLD));
382     selectFeaturesLabel.setOpaque(true);
383     selectFeaturesLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
384     // ***************************************************************
385     // Put all those components at their place
386     // ***************************************************************
387     Box northBox = new Box(BoxLayout.X_AXIS);
388     // Arange Key Document components
389     Box currentBox = new Box(BoxLayout.Y_AXIS);
390     currentBox.add(keyLabel);
391     currentBox.add(keyDocComboBox);
392     currentBox.add(Box.createVerticalStrut(10));
393     currentBox.add(responseLabel);
394     currentBox.add(responseDocComboBox);
395     northBox.add(currentBox);
396 
397     northBox.add(Box.createRigidArea(new Dimension(10,0)));
398 
399     // Arange annotation set components
400     currentBox = new Box(BoxLayout.Y_AXIS);
401     currentBox.add(keyDocAnnotSetLabel);
402     currentBox.add(keyDocAnnotSetComboBox);
403     currentBox.add(Box.createVerticalStrut(10));
404     currentBox.add(responseDocAnnotSetLabel);
405     currentBox.add(responseDocAnnotSetComboBox);
406     northBox.add(currentBox);
407 
408     northBox.add(Box.createRigidArea(new Dimension(10,0)));
409 
410     // Arange annotation types components
411     currentBox = new Box(BoxLayout.Y_AXIS);
412     currentBox.add(typesLabel);
413     currentBox.add(typesComboBox);
414     northBox.add(currentBox);
415 
416     northBox.add(Box.createRigidArea(new Dimension(10,0)));
417 
418     // Arrange the radio buttons
419     currentBox = new Box(BoxLayout.Y_AXIS);
420     currentBox.add(selectFeaturesLabel);
421     currentBox.add(allFeaturesRadio);
422     currentBox.add(someFeaturesRadio);
423     currentBox.add(noFeaturesRadio);
424     northBox.add(currentBox);
425 
426     northBox.add(Box.createRigidArea(new Dimension(10,0)));
427 
428     // Arange F-Measure weight components
429     currentBox = new Box(BoxLayout.Y_AXIS);
430     currentBox.add(weightLabel);
431     currentBox.add(weightTextField);
432     northBox.add(currentBox);
433 
434     northBox.add(Box.createRigidArea(new Dimension(10,0)));
435 
436     // Arange false poz components
437     currentBox = new Box(BoxLayout.Y_AXIS);
438     currentBox.add(falsePozLabel);
439     currentBox.add(falsePozTypeComboBox);
440     currentBox.add(Box.createVerticalStrut(10));
441     currentBox.add(responseDocAnnotSetFalsePozLabel);
442     currentBox.add(responseDocAnnotSetFalsePozComboBox);
443     northBox.add(currentBox);
444 
445     northBox.add(Box.createRigidArea(new Dimension(10,0)));
446     northBox.add(evalButton);
447 
448     initKeyAnnotSetNames();
449     initResponseAnnotSetNames();
450     initAnnotTypes();
451     initAnnotTypesFalsePoz();
452 
453     this.getContentPane().setLayout(new BoxLayout(this.getContentPane(),
454                                                             BoxLayout.Y_AXIS));
455     Dimension maxDimm = Toolkit.getDefaultToolkit().getScreenSize();
456     Dimension newDim = new Dimension(maxDimm.width/3, maxDimm.height/3);
457     JScrollPane upperScrolPane = new JScrollPane(northBox);
458     upperScrolPane.getViewport().
459                     putClientProperty("EnableWindowBlit", new Boolean(true));
460     JScrollPane lowerScrolPane = new JScrollPane(annotDiff);
461     lowerScrolPane.getViewport().
462                     putClientProperty("EnableWindowBlit", new Boolean(true));
463     lowerScrolPane.setMaximumSize(newDim);
464     lowerScrolPane.setPreferredSize(newDim);
465 
466     jSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
467                                upperScrolPane,
468                                lowerScrolPane);
469     jSplit.setOneTouchExpandable(true);
470     jSplit.setOpaque(true);
471     jSplit.setAlignmentY(Component.TOP_ALIGNMENT);
472     this.getContentPane().add(jSplit);
473     this.pack();
474     ////////////////////////////////
475     // Center it on screen
476     ///////////////////////////////
477     Dimension ownerSize;
478     Point ownerLocation;
479     if(getOwner() == null){
480       ownerSize = Toolkit.getDefaultToolkit().getScreenSize();
481       ownerLocation = new Point(0, 0);
482     }else{
483       ownerSize = getOwner().getSize();
484       ownerLocation = getOwner().getLocation();
485       if(ownerSize.height == 0 ||
486          ownerSize.width == 0 ||
487          !getOwner().isVisible()){
488         ownerSize = Toolkit.getDefaultToolkit().getScreenSize();
489         ownerLocation = new Point(0, 0);
490       }
491     }
492     //Center the window
493     Dimension frameSize = getSize();
494     if (frameSize.height > ownerSize.height)
495       frameSize.height = ownerSize.height;
496     if (frameSize.width > ownerSize.width)
497       frameSize.width = ownerSize.width;
498     setLocation(ownerLocation.x + (ownerSize.width - frameSize.width) / 2,
499                 ownerLocation.y + (ownerSize.height - frameSize.height) / 2);
500 
501   }//initGuiComponents
502 
503   /** This method is called when the user want to close the tool. See
504     * initListeners() method for more details
505     */
506   void this_windowClosing(WindowEvent e){
507     this.setVisible(false);
508   }//this_windowClosing();
509 
510   /** This method starts AnnotationDiff tool in a separate thread.*/
511   private void doDiff(){
512     try{
513       Double d = new Double(thisAnnotDiffDialog.getCurrentWeight());
514       CorpusAnnotationDiff.weight = d.doubleValue();
515     }catch (NumberFormatException e){
516         JOptionPane.showMessageDialog(thisAnnotDiffDialog,
517                      "The weight for F-Measure should be a double !",
518                      "Annotation Diff initialization error !",
519                      JOptionPane.ERROR_MESSAGE);
520         return;
521     }// End try
522     Thread thread = new Thread(Thread.currentThread().getThreadGroup(),
523                                new DiffRunner(),
524                                "AnnotDiffDialog1");
525     thread.setPriority(Thread.MIN_PRIORITY);
526     thread.start();
527   }//doDiff();
528 
529   /**This one initializes the listeners fot the GUI components */
530   public void initListeners(){
531 
532     this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
533     this.addWindowListener(new java.awt.event.WindowAdapter() {
534       public void windowClosing(WindowEvent e) {
535         this_windowClosing(e);
536       }// windowClosing();
537     });// addWindowListener();
538 
539     evalButton.addActionListener(new java.awt.event.ActionListener() {
540       public void actionPerformed(ActionEvent e) {
541          thisAnnotDiffDialog.doDiff();
542       }// actionPerformed();
543     });//addActionListener();
544 
545     keyDocComboBox.addActionListener(new ActionListener() {
546       public void actionPerformed(ActionEvent e) {
547         initKeyAnnotSetNames();
548         initAnnotTypes();
549       }// actionPerformed();
550     });//addActionListener();
551 
552     responseDocComboBox.addActionListener(new ActionListener() {
553       public void actionPerformed(ActionEvent e) {
554         initResponseAnnotSetNames();
555         initAnnotTypes();
556       }// actionPerformed();
557     });//addActionListener();
558 
559     keyDocAnnotSetComboBox.addActionListener(new ActionListener() {
560       public void actionPerformed(ActionEvent e) {
561         initAnnotTypes();
562       }// actionPerformed();
563     });//addActionListener();
564 
565     responseDocAnnotSetComboBox.addActionListener(new ActionListener() {
566       public void actionPerformed(ActionEvent e) {
567         initAnnotTypes();
568       }// actionPerformed();
569     });//addActionListener();
570 
571     responseDocAnnotSetFalsePozComboBox.addActionListener(new ActionListener() {
572       public void actionPerformed(ActionEvent e) {
573         initAnnotTypesFalsePoz();
574       }// actionPerformed();
575     });//addActionListener();
576 
577     typesComboBox.addActionListener(new ActionListener() {
578       public void actionPerformed(ActionEvent e){
579         if (featureSelectionDialog != null) featureSelectionDialog = null;
580       }// actionPerformed();
581     });//addActionListener();
582 
583     someFeaturesRadio.addActionListener(new ActionListener() {
584       public void actionPerformed(ActionEvent e){
585         collectSomeFeatures();
586       }// actionPerformed();
587     });//addActionListener();
588 
589   }//initListeners();
590 
591   /** Activates the CollectionSelectionDialog in order to colect those feature
592     * from key that will take part in the diff process
593     */
594   private void collectSomeFeatures(){
595     if (featureSelectionDialog == null){
596       featureSelectionDialog = new CollectionSelectionDialog(
597                                                 thisAnnotDiffDialog,true);
598     }else{
599       featureSelectionDialog.setVisible(true);
600       return;
601     }// End if
602     // For the current annotation type take all the features that appear in the
603     // key set and initialize the featureSelectionDialog
604     gate.Corpus keyCorpus = null;
605     keyCorpus = (gate.Corpus) corpusMap.get(
606                                  (String)keyDocComboBox.getSelectedItem());
607     if (keyCorpus == null){
608       JOptionPane.showMessageDialog(this,
609                                     "Select a key corpus first !",
610                                     "GATE", JOptionPane.ERROR_MESSAGE);
611       featureSelectionDialog = null;
612       return;
613     }//End if
614 
615     if(0 == keyCorpus.size()) {
616       JOptionPane.showMessageDialog(this,
617                                     "Select a nonempty key corpus first !",
618                                     "GATE", JOptionPane.ERROR_MESSAGE);
619       featureSelectionDialog = null;
620       return;
621     }
622 
623     AnnotationSet keySet = null;
624     if (keyDocAnnotSetComboBox.getSelectedItem()== null ||
625         keyAnnotationSetMap.get(keyDocAnnotSetComboBox.getSelectedItem())==null) {
626       // First add to the keySet all annotations from default set
627       AnnotationSet tempSet;
628       Document doc;
629       for(int i=0; i<keyCorpus.size(); ++i) {
630         doc = (Document) keyCorpus.get(i);
631         tempSet = doc.getAnnotations();
632         if(null == keySet) keySet = tempSet;
633         else keySet.addAll(tempSet);
634       } // for
635     }
636     else{
637       // Get all types of annotation from the selected keyAnnotationSet
638       AnnotationSet as = (AnnotationSet) keyAnnotationSetMap.get(
639                                   keyDocAnnotSetComboBox.getSelectedItem());
640       keySet = as;
641     }// End if
642     if (keySet == null){
643       JOptionPane.showMessageDialog(this,
644                                     "Select some annotation sets first !",
645                                     "GATE", JOptionPane.ERROR_MESSAGE);
646       featureSelectionDialog = null;
647       return;
648     }// End if
649     AnnotationSchema annotSchema = (AnnotationSchema)
650                                 typesMap.get(typesComboBox.getSelectedItem());
651     if (annotSchema == null){
652       JOptionPane.showMessageDialog(this,
653                                     "Select some annotation types first !",
654                                     "GATE", JOptionPane.ERROR_MESSAGE);
655       featureSelectionDialog = null;
656       return;
657     }// End if
658 
659     AnnotationSet selectedTypeSet = keySet.get(annotSchema.getAnnotationName());
660     Set featureNamesSet = new TreeSet();
661     // Iterate this set and get all feature keys.
662     Iterator selectedTypeIterator = selectedTypeSet.iterator();
663     while(selectedTypeIterator.hasNext()){
664       Annotation a = (Annotation) selectedTypeIterator.next();
665       if (a.getFeatures() != null)
666         featureNamesSet.addAll(a.getFeatures().keySet());
667     }// End while
668     featureSelectionDialog.show("Select features for annotation type \"" +
669         annotSchema.getAnnotationName()+ "\" that would be used in diff proces",
670         featureNamesSet);
671   }//collectSomeFeatures();
672 
673   /** Initializes the annotations for false Poz masure*/
674   private void initAnnotTypesFalsePoz(){
675     gate.Corpus responseCorpus = null;
676     responseCorpus = (gate.Corpus) corpusMap.get(
677                                  (String)responseDocComboBox.getSelectedItem());
678     falsePozTypes.clear();
679     if (responseCorpus == null || 0 == responseCorpus.size()){
680       // init falsePozTypes
681       falsePozTypes.add("No annot.");
682       DefaultComboBoxModel cbm = new DefaultComboBoxModel(falsePozTypes.toArray());
683       falsePozTypeComboBox.setModel(cbm);
684       return;
685     }//End if
686 
687     // Fill the responseSet
688     Set responseSet = null;
689     if (responseDocAnnotSetFalsePozComboBox.getSelectedItem() == null ||
690         responseAnnotationSetMap.get(
691                  responseDocAnnotSetFalsePozComboBox.getSelectedItem())==null) {
692       responseSet = new HashSet();
693       Document doc;
694       Set docTypeSet;
695       for(int i=0; i<responseCorpus.size(); ++i) {
696         doc = (Document) responseCorpus.get(i);
697         docTypeSet = doc.getAnnotations().getAllTypes();
698         responseSet.addAll(docTypeSet);
699       } // for
700     }
701     else{
702       // Get all types of annotation from the selected responseAnnotationSet
703       AnnotationSet as = (AnnotationSet) responseAnnotationSetMap.get(
704                          responseDocAnnotSetFalsePozComboBox.getSelectedItem());
705       responseSet = new HashSet(as.getAllTypes());
706     }// End if
707 
708     // Init falsePozTypes
709     falsePozTypes.addAll(responseSet);
710     if (falsePozTypes.isEmpty())
711       falsePozTypes.add("No annot.");
712     DefaultComboBoxModel cbm = new DefaultComboBoxModel(falsePozTypes.toArray());
713     falsePozTypeComboBox.setModel(cbm);
714   }//initAnnotTypesFalsePoz();
715 
716   /** Reads the selected keyDocument + the selected responseDocument and
717     * also reads the selected annotation sets from Key and response and
718     * intersects the annotation types. The result is the typesComboBox which
719     * is filled with the intersected types.
720     */
721   private void initAnnotTypes(){
722     gate.Corpus keyCorpus = null;
723     gate.Corpus responseCorpus = null;
724 
725     keyCorpus = (gate.Corpus) corpusMap.get(
726                                  (String)keyDocComboBox.getSelectedItem());
727     responseCorpus = (gate.Corpus) corpusMap.get(
728                                  (String)responseDocComboBox.getSelectedItem());
729 
730     typesMap.clear();
731 
732     if (keyCorpus == null || responseCorpus == null
733         || 0 == keyCorpus.size() || 0 == responseCorpus.size()){
734       // init types map with Type,AnnotationSchema pairs
735       typesMap.put("No annot.",null);
736       ComboBoxModel cbm = new DefaultComboBoxModel(typesMap.keySet().toArray());
737       typesComboBox.setModel(cbm);
738       return;
739     }//End if
740 
741     // Do intersection for annotation types...
742     // First fill the keySet;
743     Set keySet = null;
744     if (keyDocAnnotSetComboBox.getSelectedItem()== null ||
745         keyAnnotationSetMap.get(keyDocAnnotSetComboBox.getSelectedItem())==null) {
746       // First add to the keySet all annotations from default set
747       keySet = new HashSet();
748       Document doc;
749       Set docTypeSet;
750       for(int i=0; i<keyCorpus.size(); ++i) {
751         doc = (Document) keyCorpus.get(i);
752         docTypeSet = doc.getAnnotations().getAllTypes();
753         keySet.addAll(docTypeSet);
754       } // for
755     }
756     else{
757       // Get all types of annotation from the selected keyAnnotationSet
758       keySet = new HashSet();
759       Document doc;
760       Set docTypeSet;
761       for(int i=0; i<keyCorpus.size(); ++i) {
762         doc = (Document) keyCorpus.get(i);
763         docTypeSet = doc.getAnnotations( (String)
764                         keyDocAnnotSetComboBox.getSelectedItem()).getAllTypes();
765         keySet.addAll(docTypeSet);
766       } // for
767     }// End if
768 
769     // Do the same thing for the responseSet
770     // Fill the responseSet
771     Set responseSet = null;
772     if (responseDocAnnotSetComboBox.getSelectedItem() == null ||
773         responseAnnotationSetMap.get( (String)
774                           responseDocAnnotSetComboBox.getSelectedItem())==null) {
775       responseSet = new HashSet();
776       Document doc;
777       Set docTypeSet;
778       for(int i=0; i<responseCorpus.size(); ++i) {
779         doc = (Document) responseCorpus.get(i);
780         docTypeSet = doc.getAnnotations().getAllTypes();
781         responseSet.addAll(docTypeSet);
782       } // for
783     }
784     else{
785       // Get all types of annotation from the selected responseAnnotationSet
786       responseSet = new HashSet();
787       Document doc;
788       Set docTypeSet;
789       for(int i=0; i<responseCorpus.size(); ++i) {
790         doc = (Document) responseCorpus.get(i);
791         docTypeSet = doc.getAnnotations( (String)
792                         keyDocAnnotSetComboBox.getSelectedItem()).getAllTypes();
793         responseSet.addAll(docTypeSet);
794       } // for
795     }// End if
796 
797     // DO intersection between keySet & responseSet
798     keySet.retainAll(responseSet);
799     Set intersectSet = keySet;
800 
801     Iterator iter = intersectSet.iterator();
802     while (iter.hasNext()){
803       String annotName = (String) iter.next();
804 
805       AnnotationSchema schema = new AnnotationSchema();
806       schema.setAnnotationName(annotName);
807 
808       typesMap.put(annotName,schema);
809     }// while
810 
811     if (typesMap.isEmpty())
812       typesMap.put("No annot.",null);
813 
814     DefaultComboBoxModel cbm = new DefaultComboBoxModel(
815                                               typesMap.keySet().toArray());
816     typesComboBox.setModel(cbm);
817   }//initAnnotTypes();
818 
819   /** Reads the selected keyDocument + the selected responseDocument and fill
820     * the two combo boxes called keyDocAnnotSetComboBox and
821     * responseDocAnnotSetComboBox.
822     */
823   private void initKeyAnnotSetNames(){
824     gate.Corpus keyCorpus = null;
825     keyCorpus = (gate.Corpus) corpusMap.get(
826                                  (String)keyDocComboBox.getSelectedItem());
827     keyAnnotationSetMap.clear();
828 
829     if (keyCorpus != null && 0 != keyCorpus.size()){
830       Map namedAnnotSets;
831       Document doc;
832       for(int i=0; i<keyCorpus.size(); ++i) {
833         doc = (Document) keyCorpus.get(i);
834         namedAnnotSets = doc.getNamedAnnotationSets();
835         if (namedAnnotSets != null)
836           keyAnnotationSetMap.putAll(namedAnnotSets);
837       } // for
838 
839       keyAnnotationSetMap.put("Default set",null);
840       DefaultComboBoxModel cbm = new DefaultComboBoxModel(
841                                         keyAnnotationSetMap.keySet().toArray());
842       keyDocAnnotSetComboBox.setModel(cbm);
843     }// End if
844   }//initKeyAnnotSetNames();
845 
846   /** Reads the selected responseDocument and fill
847     * the combo box called responseDocAnnotSetFalsePozComboBox as well as
848     * responseDocAnnotSetComboBox.
849     */
850   private void initResponseAnnotSetNames(){
851     gate.Corpus responseCorpus = null;
852     responseCorpus = (gate.Corpus) corpusMap.get(
853                                  (String)responseDocComboBox.getSelectedItem());
854     responseAnnotationSetMap.clear();
855 
856     if (responseCorpus != null && 0 != responseCorpus.size()){
857       Map namedAnnotSets;
858       Document doc;
859       for(int i=0; i<responseCorpus.size(); ++i) {
860         doc = (Document) responseCorpus.get(i);
861         namedAnnotSets = doc.getNamedAnnotationSets();
862         if (namedAnnotSets != null)
863           responseAnnotationSetMap.putAll(namedAnnotSets);
864       } // for
865 
866       responseAnnotationSetMap.put("Default set",null);
867       DefaultComboBoxModel cbm = new DefaultComboBoxModel(
868                                   responseAnnotationSetMap.keySet().toArray());
869       responseDocAnnotSetComboBox.setModel(cbm);
870       cbm = new DefaultComboBoxModel(
871                                   responseAnnotationSetMap.keySet().toArray());
872       responseDocAnnotSetFalsePozComboBox.setModel(cbm);
873     }// End if
874   }//initResponseAnnotSetNames();
875 
876   /** It returns the selected KEY gate.Document*/
877   public gate.Corpus getSelectedKeyCorpus(){
878     return (gate.Corpus) corpusMap.get(
879                                 (String)keyDocComboBox.getSelectedItem());
880   }//getSelectedKeyCorpus
881 
882   /** It returns the selected RESPONSE gate.Document*/
883   public gate.Corpus getSelectedResponseCorpus(){
884     return (gate.Corpus) corpusMap.get(
885                                 (String)responseDocComboBox.getSelectedItem());
886   }//getSelectedResponseCorpus
887 
888   /** It returns the selected SCHEMA  */
889   public AnnotationSchema getSelectedSchema(){
890     return (AnnotationSchema) typesMap.get(
891                                 (String)typesComboBox.getSelectedItem());
892   }//getSelectedSchema
893 
894   /** It returns the current weight  */
895   public String getCurrentWeight(){
896     return weightTextField.getText();
897   }//getCurrentWeight
898 
899   /** It returns the selected Annotation to calculate the False Pozitive  */
900   public String getSelectedFalsePozAnnot(){
901     return (String) falsePozTypeComboBox.getSelectedItem();
902   }//getSelectedFalsePozAnnot
903 
904   /** It returns the selected key AnnotationSet name. It returns null for the
905     * default annotation set.
906     */
907   public String getSelectedKeyAnnotationSetName(){
908    String asName = (String) keyDocAnnotSetComboBox.getSelectedItem();
909    if ("Default set".equals(asName)) return null;
910    else return asName;
911   }//getSelectedKeyAnnotationSetName()
912 
913   /** It returns the selected response AnnotationSet name.It returns null for the
914     * default annotation set.
915     */
916   public String getSelectedResponseAnnotationSetName(){
917    String asName = (String) responseDocAnnotSetComboBox.getSelectedItem();
918    if ("Default set".equals(asName)) return null;
919    else return asName;
920   }//getSelectedResponseAnnotationSetName()
921 
922   /** It returns the selected response AnnotationSet name for False Poz.
923     * It returns null for the default annotation set.
924     */
925   public String getSelectedResponseAnnotationSetNameFalsePoz(){
926    String asName = (String) responseDocAnnotSetFalsePozComboBox.getSelectedItem();
927    if ("Default set".equals(asName)) return null;
928    else return asName;
929   }//getSelectedResponseAnnotationSetNameFalsePoz()
930 
931   /**  Inner class that adds a tool tip to the combo boxes with key and response
932     *  documents. The tool tip represents the full path of the documents.
933     */
934   class MyCellRenderer extends JLabel implements ListCellRenderer {
935 
936      Color background = null;
937      Color foreground = null;
938      /** Constructs a renderer*/
939      public MyCellRenderer(Color aBackground, Color aForeground){
940          setOpaque(true);
941          background = aBackground;
942          foreground = aForeground;
943      }// MyCellRenderer();
944 
945      /** This method is overridden in order to implement the needed behaviour*/
946      public Component getListCellRendererComponent(
947                                                    JList list,
948                                                    Object value,
949                                                    int index,
950                                                    boolean isSelected,
951                                                    boolean cellHasFocus){
952          // should be done only once...
953          ToolTipManager.sharedInstance().registerComponent(list);
954          setText(value.toString());
955          setBackground(isSelected ? background : Color.white);
956          setForeground(isSelected ? foreground : Color.black);
957          if (isSelected)
958              list.setToolTipText(value.toString());
959          return this;
960      }// getListCellRendererComponent()
961   }//MyCellRenderer
962 
963   /**Inner class used to run an annot. diff in a new thread*/
964   class DiffRunner implements Runnable{
965     /** Constructor */
966     public DiffRunner(){}// DiffRuner
967     /** This method is overridden in order to implement the needed behaviour*/
968     public void run(){
969       annotDiff.setKeyCorpus(thisAnnotDiffDialog.getSelectedKeyCorpus());
970       annotDiff.setResponseCorpus(
971                           thisAnnotDiffDialog.getSelectedResponseCorpus());
972       annotDiff.setAnnotationSchema(thisAnnotDiffDialog.getSelectedSchema());
973       annotDiff.setKeyAnnotationSetName(
974                       thisAnnotDiffDialog.getSelectedKeyAnnotationSetName());
975       annotDiff.setResponseAnnotationSetName(
976                   thisAnnotDiffDialog.getSelectedResponseAnnotationSetName());
977       annotDiff.setResponseAnnotationSetNameFalsePoz(
978             thisAnnotDiffDialog.getSelectedResponseAnnotationSetNameFalsePoz());
979 
980       // Only one of those radio buttons can be selected
981       if (allFeaturesRadio.isSelected())
982         annotDiff.setKeyFeatureNamesSet(null);
983       if (noFeaturesRadio.isSelected())
984         annotDiff.setKeyFeatureNamesSet(new HashSet());
985       // If someFeaturesRadio is selected, then featureSelectionDialog is not
986       // null because of the collectSomeFeatures() method
987       if (someFeaturesRadio.isSelected())
988         annotDiff.setKeyFeatureNamesSet(
989                    new HashSet(featureSelectionDialog.getSelectedCollection()));
990       String falsePozAnnot = thisAnnotDiffDialog.getSelectedFalsePozAnnot();
991       if ("No annot.".equals(falsePozAnnot))
992             falsePozAnnot = null;
993       annotDiff.setAnnotationTypeForFalsePositive(falsePozAnnot);
994       try{
995         annotDiff.init();
996       } catch (ResourceInstantiationException e){
997         JOptionPane.showMessageDialog(thisAnnotDiffDialog,
998                      e.getMessage() + "\n Annotation diff stopped !",
999                      "Annotation Diff initialization error !",
1000                     JOptionPane.ERROR_MESSAGE);
1001      }finally {
1002        SwingUtilities.invokeLater(new Runnable(){
1003          public void run(){
1004            doLayout();
1005            pack();
1006          }// run
1007        });//invokeLater
1008      }// End try
1009    }// run();
1010  }//DiffRunner
1011}//CorpusAnnotDiffDialog
1012