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