1
15
16 package gate.gui;
17
18 import java.awt.*;
19 import java.awt.event.*;
20 import java.io.*;
21 import java.io.File;
22 import java.io.FileWriter;
23 import java.text.NumberFormat;
24 import java.util.*;
25 import java.util.List;
26 import javax.swing.*;
27 import javax.swing.JTable;
28 import javax.swing.filechooser.FileFilter;
29 import javax.swing.plaf.FileChooserUI;
30 import javax.swing.table.AbstractTableModel;
31 import javax.swing.table.DefaultTableCellRenderer;
32 import gate.*;
33 import gate.Annotation;
34 import gate.Document;
35 import gate.swing.XJTable;
36 import gate.util.*;
37
38
40 public class AnnotationDiffGUI extends JFrame{
41
42 public AnnotationDiffGUI(String title){
43 super(title);
44 initLocalData();
45 initGUI();
46 initListeners();
47 populateGUI();
48 }
49
50 protected void initLocalData(){
51 differ = new AnnotationDiffer();
52 pairings = new ArrayList();
53 significantFeatures = new HashSet();
54 keyDoc = null;
55 resDoc = null;
56 }
57
58
59 protected void initGUI(){
60 getContentPane().setLayout(new GridBagLayout());
61 GridBagConstraints constraints = new GridBagConstraints();
62 constraints.gridy = 0;
64 constraints.gridx = GridBagConstraints.RELATIVE;
65 constraints.weightx = 0;
66 constraints.weighty = 0;
67 constraints.anchor = GridBagConstraints.WEST;
68 constraints.fill = GridBagConstraints.HORIZONTAL;
69 constraints.insets = new Insets(2,4,2,4);
70 constraints.gridx = 1;
72 getContentPane().add(new JLabel("Document"), constraints);
73 constraints.gridx = GridBagConstraints.RELATIVE;
74 getContentPane().add(new JLabel("Annotation Set"), constraints);
75 constraints.gridy = 1;
77 constraints.gridx = GridBagConstraints.RELATIVE;
78 constraints.gridwidth = 1;
79 getContentPane().add(new JLabel("Key:"), constraints);
80 keyDocCombo = new JComboBox();
81 getContentPane().add(keyDocCombo, constraints);
82 keySetCombo = new JComboBox();
83 getContentPane().add(keySetCombo, constraints);
84 getContentPane().add(new JLabel("Annotation Type:"), constraints);
85 annTypeCombo = new JComboBox();
86 constraints.gridwidth = 3;
87 getContentPane().add(annTypeCombo, constraints);
88 constraints.gridwidth = 1;
89 getContentPane().add(new JLabel("F-Measure Weight"), constraints);
90 constraints.gridheight = 2;
91 doDiffBtn = new JButton(new DiffAction());
92 getContentPane().add(doDiffBtn, constraints);
93 constraints.weightx = 1;
94 getContentPane().add(Box.createHorizontalGlue(), constraints);
95 constraints.gridy = 2;
97 constraints.gridx = 0;
98 constraints.gridheight = 1;
99 constraints.weightx = 0;
100 getContentPane().add(new JLabel("Response:"), constraints);
101 constraints.gridx = GridBagConstraints.RELATIVE;
102 resDocCombo = new JComboBox();
103 getContentPane().add(resDocCombo, constraints);
104 resSetCombo = new JComboBox();
105 getContentPane().add(resSetCombo, constraints);
106 getContentPane().add(new JLabel("Features:"), constraints);
107 ButtonGroup btnGrp = new ButtonGroup();
108 allFeaturesBtn = new JRadioButton("All");
109 allFeaturesBtn.setOpaque(false);
110 btnGrp.add(allFeaturesBtn);
111 getContentPane().add(allFeaturesBtn, constraints);
112 someFeaturesBtn = new JRadioButton("Some");
113 someFeaturesBtn.setOpaque(false);
114 btnGrp.add(someFeaturesBtn);
115 getContentPane().add(someFeaturesBtn, constraints);
116 noFeaturesBtn = new JRadioButton("None");
117 noFeaturesBtn.setOpaque(false);
118 btnGrp.add(noFeaturesBtn);
119 getContentPane().add(noFeaturesBtn, constraints);
120 noFeaturesBtn.setSelected(true);
121 weightTxt = new JTextField("1.00");
122 getContentPane().add(weightTxt, constraints);
123 constraints.gridy = 3;
125 constraints.gridx = 0;
126 constraints.gridwidth = 10;
127 constraints.weightx = 1;
128 constraints.weighty = 1;
129 constraints.fill = GridBagConstraints.BOTH;
130 diffTableModel = new DiffTableModel();
131 diffTable = new XJTable(diffTableModel);
132 diffTable.setDefaultRenderer(String.class, new DiffTableCellRenderer());
133 diffTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
134 diffTable.setComparator(DiffTableModel.COL_MATCH, new Comparator(){
135 public int compare(Object o1, Object o2){
136 String label1 = (String)o1;
137 String label2 = (String)o2;
138 int match1 = 0;
139 while(!label1.equals(matchLabel[match1])) match1++;
140 int match2 = 0;
141 while(!label2.equals(matchLabel[match2])) match2++;
142
143 return match1 - match2;
144 }
145 });
146
147
148 Comparator startEndComparator = new Comparator() {
149 public int compare(Object o1, Object o2) {
150 String no1 = (String) o1;
151 String no2 = (String) o2;
152 if (no1.trim().equals("") && no2.trim().equals("")) {
153 return 0;
154 }
155 else if (no1.trim().equals("")) {
156 return -1;
157 }
158 else if (no2.trim().equals("")) {
159 return 1;
160 }
161 int n1 = Integer.parseInt(no1);
162 int n2 = Integer.parseInt(no2);
163 if(n1 == n2)
164 return 0;
165 else if(n1 > n2)
166 return 1;
167 else
168 return -1;
169 }
170 };
171
172 diffTable.setComparator(diffTableModel.COL_KEY_START, startEndComparator);
173 diffTable.setComparator(diffTableModel.COL_KEY_END, startEndComparator);
174 diffTable.setComparator(diffTableModel.COL_RES_START, startEndComparator);
175 diffTable.setComparator(diffTableModel.COL_RES_END, startEndComparator);
176
177
178 diffTable.setSortable(true);
179 diffTable.setSortedColumn(DiffTableModel.COL_MATCH);
180 diffTable.setAscending(false);
181 scroller = new JScrollPane(diffTable);
182 getContentPane().add(scroller, constraints);
183
184 resultsPane = new JPanel();
186 resultsPane.setLayout(new GridBagLayout());
187 constraints.gridy = GridBagConstraints.RELATIVE;
189 constraints.gridx = 0;
190 constraints.weightx = 0;
191 constraints.weighty = 0;
192 constraints.gridwidth = 1;
193 constraints.gridheight = 1;
194 constraints.anchor = GridBagConstraints.WEST;
195 constraints.fill = GridBagConstraints.NONE;
196 JLabel lbl = new JLabel("Correct:");
197 lbl.setBackground(diffTable.getBackground());
198 resultsPane.add(lbl, constraints);
199 lbl = new JLabel("Partially Correct:");
200 lbl.setBackground(PARTIALLY_CORRECT_BG);
201 lbl.setOpaque(true);
202 resultsPane.add(lbl, constraints);
203 lbl = new JLabel("Missing:");
204 lbl.setBackground(MISSING_BG);
205 lbl.setOpaque(true);
206 resultsPane.add(lbl, constraints);
207 lbl = new JLabel("False Positives:");
208 lbl.setBackground(FALSE_POZITIVE_BG);
209 lbl.setOpaque(true);
210 resultsPane.add(lbl, constraints);
211
212 constraints.gridx = 1;
214 correctLbl = new JLabel("0");
215 resultsPane.add(correctLbl, constraints);
216 partiallyCorrectLbl = new JLabel("0");
217 resultsPane.add(partiallyCorrectLbl, constraints);
218 missingLbl = new JLabel("0");
219 resultsPane.add(missingLbl, constraints);
220 falsePozLbl = new JLabel("0");
221 resultsPane.add(falsePozLbl, constraints);
222
223 constraints.gridx = 2;
225 constraints.insets = new Insets(4, 30, 4, 4);
226 resultsPane.add(Box.createGlue());
227 lbl = new JLabel("Strict:");
228 resultsPane.add(lbl, constraints);
229 lbl = new JLabel("Lenient:");
230 resultsPane.add(lbl, constraints);
231 lbl = new JLabel("Average:");
232 resultsPane.add(lbl, constraints);
233
234 constraints.gridx = 3;
236 constraints.insets = new Insets(4, 4, 4, 4);
237 lbl = new JLabel("Recall");
238 resultsPane.add(lbl, constraints);
239 recallStrictLbl = new JLabel("0.0000");
240 resultsPane.add(recallStrictLbl, constraints);
241 recallLenientLbl = new JLabel("0.0000");
242 resultsPane.add(recallLenientLbl, constraints);
243 recallAveLbl = new JLabel("0.0000");
244 resultsPane.add(recallAveLbl, constraints);
245
246 constraints.gridx = 4;
248 lbl = new JLabel("Precision");
249 resultsPane.add(lbl, constraints);
250 precisionStrictLbl = new JLabel("0.0000");
251 resultsPane.add(precisionStrictLbl, constraints);
252 precisionLenientLbl = new JLabel("0.0000");
253 resultsPane.add(precisionLenientLbl, constraints);
254 precisionAveLbl = new JLabel("0.0000");
255 resultsPane.add(precisionAveLbl, constraints);
256
257 constraints.gridx = 5;
259 lbl = new JLabel("F-Measure");
260 resultsPane.add(lbl, constraints);
261 fmeasureStrictLbl = new JLabel("0.0000");
262 resultsPane.add(fmeasureStrictLbl, constraints);
263 fmeasureLenientLbl = new JLabel("0.0000");
264 resultsPane.add(fmeasureLenientLbl, constraints);
265 fmeasureAveLbl = new JLabel("0.0000");
266 resultsPane.add(fmeasureAveLbl, constraints);
267
268 constraints.gridx = 6;
270 resultsPane.add(new JButton(new HTMLExportAction()), constraints);
271
272
275
276 constraints.gridy = 4;
278 constraints.gridx = 0;
279 constraints.weightx = 0;
280 constraints.weighty = 0;
281 constraints.gridwidth = 9;
282 constraints.gridheight = 1;
283 constraints.anchor = GridBagConstraints.WEST;
284 constraints.fill = GridBagConstraints.NONE;
285 getContentPane().add(resultsPane, constraints);
286
287
288 Color background = diffTable.getBackground();
290 getContentPane().setBackground(background);
291 scroller.setBackground(background);
292 scroller.getViewport().setBackground(background);
293 resultsPane.setBackground(background);
294
295 featureslistModel = new DefaultListModel();
296 featuresList = new JList(featureslistModel);
297 featuresList.
298 setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
299 }
300
301 protected void initListeners(){
302 keyDocCombo.addActionListener(new ActionListener(){
303 public void actionPerformed(ActionEvent evt){
304 Document newDoc = (Document)documents.get(keyDocCombo.getSelectedIndex());
305 if(keyDoc != newDoc){
306 pairings.clear();
307 diffTableModel.fireTableDataChanged();
308 keyDoc = newDoc;
309 keySets = new ArrayList();
310 List keySetNames = new ArrayList();
311 keySets.add(keyDoc.getAnnotations());
312 keySetNames.add("[Default set]");
313 Iterator setIter = keyDoc.getNamedAnnotationSets().keySet().iterator();
314 while(setIter.hasNext()){
315 String name = (String)setIter.next();
316 keySetNames.add(name);
317 keySets.add(keyDoc.getAnnotations(name));
318 }
319 keySetCombo.setModel(new DefaultComboBoxModel(keySetNames.toArray()));
320 if(!keySetNames.isEmpty())keySetCombo.setSelectedIndex(0);
321
322 }
323 }
324 });
325
326 resDocCombo.addActionListener(new ActionListener(){
327 public void actionPerformed(ActionEvent evt){
328 Document newDoc = (Document)documents.get(resDocCombo.getSelectedIndex());
329 if(resDoc != newDoc){
330 resDoc = newDoc;
331 pairings.clear();
332 diffTableModel.fireTableDataChanged();
333 resSets = new ArrayList();
334 List resSetNames = new ArrayList();
335 resSets.add(resDoc.getAnnotations());
336 resSetNames.add("[Default set]");
337 Iterator setIter = resDoc.getNamedAnnotationSets().keySet().iterator();
338 while(setIter.hasNext()){
339 String name = (String)setIter.next();
340 resSetNames.add(name);
341 resSets.add(resDoc.getAnnotations(name));
342 }
343 resSetCombo.setModel(new DefaultComboBoxModel(resSetNames.toArray()));
344 if(!resSetNames.isEmpty())resSetCombo.setSelectedIndex(0);
345
346 }
347 }
348 });
349
350
353 ActionListener setComboActionListener = new ActionListener(){
354 public void actionPerformed(ActionEvent evt){
355 keySet = keySets == null || keySets.isEmpty()?
356 null :
357 (AnnotationSet)keySets.get(keySetCombo.getSelectedIndex());
358 resSet = resSets == null || resSets.isEmpty()?
359 null :
360 (AnnotationSet)resSets.get(resSetCombo.getSelectedIndex());
361 Set keyTypes = (keySet == null || keySet.isEmpty()) ?
362 new HashSet() : keySet.getAllTypes();
363 Set resTypes = (resSet == null || resSet.isEmpty()) ?
364 new HashSet() : resSet.getAllTypes();
365 Set types = new HashSet(keyTypes);
366 types.retainAll(resTypes);
367 List typesList = new ArrayList(types);
368 Collections.sort(typesList);
369 annTypeCombo.setModel(new DefaultComboBoxModel(typesList.toArray()));
370 if(typesList.size() > 0) annTypeCombo.setSelectedIndex(0);
371 }
372 };
373 keySetCombo.addActionListener(setComboActionListener);
374
375 resSetCombo.addActionListener(setComboActionListener);
376
377 someFeaturesBtn.addActionListener(new ActionListener(){
378 public void actionPerformed(ActionEvent evt){
379 if(someFeaturesBtn.isSelected()){
380 if(keySet == null || keySet.isEmpty() ||
381 annTypeCombo.getSelectedItem() == null) return;
382 Iterator annIter = keySet.
383 get((String)annTypeCombo.getSelectedItem()).iterator();
384 Set featureSet = new HashSet();
385 while(annIter.hasNext()){
386 Annotation ann = (Annotation)annIter.next();
387 Map someFeatures = ann.getFeatures();
388 if(someFeatures != null) featureSet.addAll(someFeatures.keySet());
389 }
390 List featureLst = new ArrayList(featureSet);
391 Collections.sort(featureLst);
392 featureslistModel.clear();
393 Iterator featIter = featureLst.iterator();
394 int index = 0;
395 while(featIter.hasNext()){
396 String aFeature = (String)featIter.next();
397 featureslistModel.addElement(aFeature);
398 if(significantFeatures.contains(aFeature))
399 featuresList.addSelectionInterval(index, index);
400 index ++;
401 }
402 int ret = JOptionPane.showConfirmDialog(AnnotationDiffGUI.this,
403 new JScrollPane(featuresList),
404 "Select features",
405 JOptionPane.OK_CANCEL_OPTION,
406 JOptionPane.QUESTION_MESSAGE);
407 if(ret == JOptionPane.OK_OPTION){
408 significantFeatures.clear();
409 int[] selIdxs = featuresList.getSelectedIndices();
410 for(int i = 0; i < selIdxs.length; i++){
411 significantFeatures.add(featureslistModel.get(selIdxs[i]));
412 }
413 }
414 }
415 }
416 });
417 }
418
419
420 public void pack(){
421 super.pack();
422
423 setSize(getWidth(), getHeight() + 100);
424 }
425 protected void populateGUI(){
426 try{
427 documents = Gate.getCreoleRegister().getAllInstances("gate.Document");
428 }catch(GateException ge){
429 throw new GateRuntimeException(ge);
430 }
431 List documentNames = new ArrayList(documents.size());
432 for(int i =0; i < documents.size(); i++){
433 Document doc = (Document)documents.get(i);
434 documentNames.add(doc.getName());
435 }
436 keyDocCombo.setModel(new DefaultComboBoxModel(documentNames.toArray()));
437 resDocCombo.setModel(new DefaultComboBoxModel(documentNames.toArray()));
438 if(!documents.isEmpty()){
439 keyDocCombo.setSelectedIndex(0);
440 resDocCombo.setSelectedIndex(0);
441 }
442 }
443
444
445 protected class DiffAction extends AbstractAction{
446 public DiffAction(){
447 super("Do Diff");
448 putValue(SHORT_DESCRIPTION, "Performs the diff");
449 }
450
451 public void actionPerformed(ActionEvent evt){
452 Set keys = keySet.get((String)annTypeCombo.getSelectedItem());
453 Set responses = resSet.get((String)annTypeCombo.getSelectedItem());
454 if(keys == null) keys = new HashSet();
455 if(responses == null) responses = new HashSet();
456 if(someFeaturesBtn.isSelected())
457 differ.setSignificantFeaturesSet(significantFeatures);
458 else if(allFeaturesBtn.isSelected())
459 differ.setSignificantFeaturesSet(null);
460 else differ.setSignificantFeaturesSet(new HashSet());
461 pairings.clear();
462 pairings.addAll(differ.calculateDiff(keys, responses));
463 diffTableModel.fireTableDataChanged();
464 correctLbl.setText(Integer.toString(differ.getCorrectMatches()));
465 partiallyCorrectLbl.setText(
466 Integer.toString(differ.getPartiallyCorrectMatches()));
467 missingLbl.setText(Integer.toString(differ.getMissing()));
468 falsePozLbl.setText(Integer.toString(differ.getSpurious()));
469
470 NumberFormat formatter = NumberFormat.getInstance();
471 formatter.setMaximumFractionDigits(4);
472 formatter.setMinimumFractionDigits(2);
473 recallStrictLbl.setText(formatter.format(differ.getRecallStrict()));
474 recallLenientLbl.setText(formatter.format(differ.getRecallLenient()));
475 recallAveLbl.setText(formatter.format(differ.getRecallAverage()));
476 precisionStrictLbl.setText(formatter.format(differ.getPrecisionStrict()));
477 precisionLenientLbl.setText(formatter.format(differ.getPrecisionLenient()));
478 precisionAveLbl.setText(formatter.format(differ.getPrecisionAverage()));
479
480 double weight = Double.parseDouble(weightTxt.getText());
481 fmeasureStrictLbl.setText(formatter.format(differ.getFMeasureStrict(weight)));
482 fmeasureLenientLbl.setText(formatter.format(differ.getFMeasureLenient(weight)));
483 fmeasureAveLbl.setText(formatter.format(differ.getFMeasureAverage(weight)));
484 }
485 }
486
487 protected class HTMLExportAction extends AbstractAction{
488 public HTMLExportAction(){
489 super("Export to HTML");
490 }
491 public void actionPerformed(ActionEvent evt){
492 JFileChooser fileChooser = MainFrame.getFileChooser();
493 File currentFile = fileChooser.getSelectedFile();
494 String nl = Strings.getNl();
495 String parent = (currentFile != null) ? currentFile.getParent() :
496 System.getProperty("user.home");
497 String fileName = (resDoc.getSourceUrl() != null) ?
498 resDoc.getSourceUrl().getFile() :
499 resDoc.getName();
500 fileName += "_" + annTypeCombo.getSelectedItem().toString();
501 fileName += ".html";
502 fileChooser.setSelectedFile(new File(parent, fileName));
503 ExtensionFileFilter fileFilter = new ExtensionFileFilter();
504 fileFilter.addExtension(".html");
505 fileChooser.setFileFilter(fileFilter);
506 fileChooser.setAcceptAllFileFilterUsed(true);
507 fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
508 int res = fileChooser.showSaveDialog(AnnotationDiffGUI.this);
509 if(res == JFileChooser.APPROVE_OPTION){
510 File saveFile = fileChooser.getSelectedFile();
511 try{
512 Writer fw = new BufferedWriter(new FileWriter(saveFile));
513 fw.write(HEADER_1);
515 fw.write(resDoc.getName() + " " +
516 annTypeCombo.getSelectedItem().toString() +
517 " annotations");
518 fw.write(HEADER_2 + nl);
519 fw.write("<H2>Annotation Diff - comparing " +
520 annTypeCombo.getSelectedItem().toString() +
521 " annotations" + "</H2>");
522 fw.write("<TABLE cellpadding=\"5\" border=\"0\"");
523 fw.write(nl);
524 fw.write("<TR>" + nl);
525 fw.write("\t<TH align=\"left\"> </TH>" + nl);
526 fw.write("\t<TH align=\"left\">Document</TH>" + nl);
527 fw.write("\t<TH align=\"left\">Annotation Set</TH>" + nl);
528 fw.write("</TR>" + nl);
529
530 fw.write("<TR>" + nl);
531 fw.write("\t<TH align=\"left\">Key</TH>" + nl);
532 fw.write("\t<TD align=\"left\">" + keyDoc.getName() + "</TD>" + nl);
533 fw.write("\t<TD align=\"left\">" + keySet.getName() + "</TD>" + nl);
534 fw.write("</TR>" + nl);
535 fw.write("<TR>" + nl);
536 fw.write("\t<TH align=\"left\">Response</TH>" + nl);
537 fw.write("\t<TD align=\"left\">" + resDoc.getName() + "</TD>" + nl);
538 fw.write("\t<TD align=\"left\">" + resSet.getName() + "</TD>" + nl);
539 fw.write("</TR>" + nl);
540 fw.write("</TABLE>" + nl);
541 fw.write("<BR><BR><BR>" + nl);
542 java.text.NumberFormat format = java.text.NumberFormat.getInstance();
544 format.setMaximumFractionDigits(4);
545 fw.write("Recall: " + format.format(differ.getRecallStrict()) + "<br>" + nl);
546 fw.write("Precision: " + format.format(differ.getPrecisionStrict()) + "<br>" + nl);
547 fw.write("F-measure: " + format.format(differ.getFMeasureStrict(1)) + "<br>" + nl);
548 fw.write("<br>");
549 fw.write("Correct matches: " + differ.getCorrectMatches() + "<br>" + nl);
550 fw.write("Partially Correct matches: " +
551 differ.getPartiallyCorrectMatches() + "<br>" + nl);
552 fw.write("Missing: " + differ.getMissing() + "<br>" + nl);
553 fw.write("False positives: " + differ.getSpurious() + "<br>" + nl);
554 int[] cols = new int[diffTableModel.getColumnCount()];
557 int maxColIdx = -1;
558 for(int i = 0; i < cols.length; i++){
559 if(!diffTable.isColumnHidden(i)){
560 maxColIdx ++;
561 cols[maxColIdx] = i;
562 }
563 }
564 fw.write(HEADER_3 + nl + "<TR>" + nl);
565 for(int col = 0; col <= maxColIdx; col++){
566 fw.write("\t<TH align=\"left\">" + diffTable.getColumnName(cols[col]) +
567 "</TH>" + nl);
568 }
569 fw.write("</TR>");
570 int rowCnt = diffTableModel.getRowCount();
571 for(int row = 0; row < rowCnt; row ++){
572 fw.write("<TR>");
573 for(int col = 0; col <= maxColIdx; col++){
574 Color bgCol = diffTableModel.getBackgroundAt(
575 diffTable.rowViewToModel(row),
576 diffTable.convertColumnIndexToModel(cols[col]));
577 fw.write("\t<TD bgcolor=\"#" +
578 Integer.toHexString(bgCol.getRGB()).substring(2) +
579 "\">" +
580 diffTable.getValueAt(row, cols[col]) +
581 "</TD>" + nl);
582 }
583 fw.write("</TR>");
584 }
585 fw.write(FOOTER);
586 fw.flush();
587 fw.close();
588
589 }catch(IOException ioe){
590 JOptionPane.showMessageDialog(AnnotationDiffGUI.this, ioe.toString(),
591 "GATE", JOptionPane.ERROR_MESSAGE);
592 ioe.printStackTrace();
593 }
594 }
595 }
596
597 static final String HEADER_1 = "<html><head><title>";
598 static final String HEADER_2 = "</title></head><body>";
599 static final String HEADER_3 = "<table cellpadding=\"0\" border=\"1\">";
600 static final String FOOTER = "</table></body></html>";
601 }
602
603 protected class DiffTableCellRenderer extends DefaultTableCellRenderer{
604 public Component getTableCellRendererComponent(JTable table,
605 Object value,
606 boolean isSelected,
607 boolean hasFocus,
608 int row,
609 int column){
610 Component res = super.getTableCellRendererComponent(table,
611 value, false, hasFocus, row, column);
612 res.setBackground(isSelected ? table.getSelectionBackground() :
613 diffTableModel.getBackgroundAt(diffTable.rowViewToModel(row),
614 column));
615 res.setForeground(isSelected ? table.getSelectionForeground() :
616 table.getForeground());
617 return res;
618 }
619 }
620
621 protected class DiffTableModel extends AbstractTableModel{
622 public int getRowCount(){
623 return pairings.size();
624 }
625
626 public Class getColumnClass(int columnIndex){
627 return String.class;
628 }
629
630 public int getColumnCount(){
631 return COL_CNT;
632 }
633
634 public String getColumnName(int column){
635 switch(column){
636 case COL_KEY_START: return "Start";
637 case COL_KEY_END: return "End";
638 case COL_KEY_STRING: return "Key";
639 case COL_KEY_FEATURES: return "Features";
640 case COL_MATCH: return "";
641 case COL_RES_START: return "Start";
642 case COL_RES_END: return "End";
643 case COL_RES_STRING: return "Response";
644 case COL_RES_FEATURES: return "Features";
645 default: return "?";
646 }
647 }
648
649 public Color getBackgroundAt(int row, int column){
650 AnnotationDiffer.Pairing pairing =
651 (AnnotationDiffer.Pairing)pairings.get(row);
652 Color colKey = pairing.getType() == AnnotationDiffer.CORRECT ?
653 diffTable.getBackground() :
654 (pairing.getType() == AnnotationDiffer.PARTIALLY_CORRECT ?
655 PARTIALLY_CORRECT_BG :
656 MISSING_BG);
657 if(pairing.getKey() == null) colKey = diffTable.getBackground();
658 Color colRes = pairing.getType() == AnnotationDiffer.CORRECT ?
659 diffTable.getBackground() :
660 (pairing.getType() == AnnotationDiffer.PARTIALLY_CORRECT ?
661 PARTIALLY_CORRECT_BG :
662 FALSE_POZITIVE_BG);
663 if(pairing.getResponse() == null) colRes = diffTable.getBackground();
664 switch(column){
665 case COL_KEY_START: return colKey;
666 case COL_KEY_END: return colKey;
667 case COL_KEY_STRING: return colKey;
668 case COL_KEY_FEATURES: return colKey;
669 case COL_MATCH: return diffTable.getBackground();
670 case COL_RES_START: return colRes;
671 case COL_RES_END: return colRes;
672 case COL_RES_STRING: return colRes;
673 case COL_RES_FEATURES: return colRes;
674 default: return diffTable.getBackground();
675 }
676 }
677
678 public Object getValueAt(int row, int column){
679 AnnotationDiffer.Pairing pairing =
680 (AnnotationDiffer.Pairing)pairings.get(row);
681 Annotation key = pairing.getKey();
682 String keyStr = "";
683 try{
684 if(key != null && keyDoc != null){
685 keyStr = keyDoc.getContent().getContent(key.getStartNode().getOffset(),
686 key.getEndNode().getOffset()).toString();
687 }
688 }catch(InvalidOffsetException ioe){
689 throw new GateRuntimeException(ioe);
691 }
692 Annotation res = pairing.getResponse();
693 String resStr = "";
694 try{
695 if(res != null && resDoc != null){
696 resStr = resDoc.getContent().getContent(res.getStartNode().getOffset(),
697 res.getEndNode().getOffset()).toString();
698 }
699 }catch(InvalidOffsetException ioe){
700 throw new GateRuntimeException(ioe);
702 }
703
704 switch(column){
705 case COL_KEY_START: return key == null ? "" :
706 key.getStartNode().getOffset().toString();
707 case COL_KEY_END: return key == null ? "" :
708 key.getEndNode().getOffset().toString();
709 case COL_KEY_STRING: return keyStr;
710 case COL_KEY_FEATURES: return key == null ? "" :
711 key.getFeatures().toString();
712 case COL_MATCH: return matchLabel[pairing.getType()];
713 case COL_RES_START: return res == null ? "" :
714 res.getStartNode().getOffset().toString();
715 case COL_RES_END: return res == null ? "" :
716 res.getEndNode().getOffset().toString();
717 case COL_RES_STRING: return resStr;
718 case COL_RES_FEATURES: return res == null ? "" :
719 res.getFeatures().toString();
720 default: return "?";
721 }
722 }
723
724 protected static final int COL_CNT = 9;
725 protected static final int COL_KEY_START = 0;
726 protected static final int COL_KEY_END = 1;
727 protected static final int COL_KEY_STRING = 2;
728 protected static final int COL_KEY_FEATURES = 3;
729 protected static final int COL_MATCH = 4;
730 protected static final int COL_RES_START = 5;
731 protected static final int COL_RES_END = 6;
732 protected static final int COL_RES_STRING = 7;
733 protected static final int COL_RES_FEATURES = 8;
734 }
735
736 protected AnnotationDiffer differ;
737 protected List pairings;
738 protected Document keyDoc;
739 protected Document resDoc;
740 protected Set significantFeatures;
741 protected List documents;
742 protected List keySets;
743 protected List resSets;
744 protected AnnotationSet keySet;
745 protected AnnotationSet resSet;
746
747 protected JList featuresList;
748 protected DefaultListModel featureslistModel;
749 protected DiffTableModel diffTableModel;
750 protected XJTable diffTable;
751 protected JScrollPane scroller;
752 protected JComboBox keyDocCombo;
753 protected JComboBox keySetCombo;
754 protected JComboBox annTypeCombo;
755 protected JComboBox resDocCombo;
756 protected JComboBox resSetCombo;
757
758 protected JRadioButton allFeaturesBtn;
759 protected JRadioButton someFeaturesBtn;
760 protected JRadioButton noFeaturesBtn;
761 protected JTextField weightTxt;
762 protected JButton doDiffBtn;
763
764 protected JPanel resultsPane;
765 protected JLabel correctLbl;
766 protected JLabel partiallyCorrectLbl;
767 protected JLabel missingLbl;
768 protected JLabel falsePozLbl;
769 protected JLabel recallStrictLbl;
770 protected JLabel precisionStrictLbl;
771 protected JLabel fmeasureStrictLbl;
772 protected JLabel recallLenientLbl;
773 protected JLabel precisionLenientLbl;
774 protected JLabel fmeasureLenientLbl;
775 protected JLabel recallAveLbl;
776 protected JLabel precisionAveLbl;
777 protected JLabel fmeasureAveLbl;
778
779 protected static final Color PARTIALLY_CORRECT_BG = new Color(173,215,255);
780 protected static final Color MISSING_BG = new Color(255,173,181);;
781 protected static final Color FALSE_POZITIVE_BG = new Color(255,231,173);
782 protected static final String[] matchLabel;
783 static{
784 matchLabel = new String[3];
785 matchLabel[AnnotationDiffer.CORRECT] = "=";
786 matchLabel[AnnotationDiffer.PARTIALLY_CORRECT] = "~";
787 matchLabel[AnnotationDiffer.WRONG] = "!=";
788 }
789 }
790