|
AnnotationDiff |
|
1 /* 2 * AnnotationDiff.java 3 * 4 * Copyright (c) 1998-2001, The University of Sheffield. 5 * 6 * This file is part of GATE (see http://gate.ac.uk/), and is free 7 * software, licenced under the GNU Library General Public License, 8 * Version 2, June 1991 (in the distribution as file licence.html, 9 * and also available at http://gate.ac.uk/gate/licence.html). 10 * 11 * Cristian URSU, 27/Oct/2000 12 * 13 * $Id: AnnotationDiff.java,v 1.43 2002/10/21 14:45:01 kalina Exp $ 14 */ 15 16 package gate.annotation; 17 18 import java.util.*; 19 import java.awt.*; 20 import java.text.NumberFormat; 21 import java.awt.event.*; 22 import javax.swing.*; 23 import javax.swing.table.*; 24 25 import gate.util.*; 26 import gate.annotation.*; 27 import gate.*; 28 import gate.gui.*; 29 import gate.swing.*; 30 import gate.creole.*; 31 import java.beans.*; 32 33 /** 34 * This class compare two annotation sets on annotation type given by the 35 * AnnotationSchema object. It also deals with graphic representation of the 36 * result. 37 */ 38 public class AnnotationDiff extends AbstractVisualResource 39 implements Scrollable{ 40 41 // number of pixels to be used as increment by scroller 42 protected int maxUnitIncrement = 10; 43 44 /** Debug flag */ 45 private static final boolean DEBUG = false; 46 47 /** This document contains the key annotation set which is taken as reference 48 * in comparison*/ 49 private Document keyDocument = null; 50 51 /** The name of the annotation set. If is null then the default annotation set 52 * will be considered. 53 */ 54 private String keyAnnotationSetName = null; 55 56 /** This document contains the response annotation set which is being 57 * compared against the key annotation set. 58 */ 59 private Document responseDocument = null; 60 61 /** The name of the annotation set. If is null then the default annotation set 62 * will be considered. 63 */ 64 private String responseAnnotationSetName = null; 65 66 /** The name of the annotation set considered in calculating FalsePozitive. 67 * If is null then the default annotation set will be considered. 68 */ 69 private String responseAnnotationSetNameFalsePoz = null; 70 71 /** The annotation schema object used to get the annotation name*/ 72 private AnnotationSchema annotationSchema = null; 73 74 /** A set of feature names bellonging to annotations from keyAnnotList 75 * used in isCompatible() and isPartiallyCompatible() methods 76 */ 77 private Set keyFeatureNamesSet = null; 78 79 /** The precision strict value (see NLP Information Extraction)*/ 80 private double precisionStrict = 0.0; 81 /** The precision lenient value (see NLP Information Extraction)*/ 82 private double precisionLenient = 0.0; 83 /** The precision average value (see NLP Information Extraction)*/ 84 private double precisionAverage = 0.0; 85 86 /** The Recall strict value (see NLP Information Extraction)*/ 87 private double recallStrict = 0.0; 88 /** The Recall lenient value (see NLP Information Extraction)*/ 89 private double recallLenient = 0.0; 90 /** The Recall average value (see NLP Information Extraction)*/ 91 private double recallAverage = 0.0; 92 93 /** The False positive strict (see NLP Information Extraction)*/ 94 private double falsePositiveStrict = 0.0; 95 /** The False positive lenient (see NLP Information Extraction)*/ 96 private double falsePositiveLenient = 0.0; 97 /** The False positive average (see NLP Information Extraction)*/ 98 private double falsePositiveAverage = 0.0; 99 100 /** The F-measure strict (see NLP Information Extraction)*/ 101 private double fMeasureStrict = 0.0; 102 /** The F-measure lenient (see NLP Information Extraction)*/ 103 private double fMeasureLenient = 0.0; 104 /** The F-measure average (see NLP Information Extraction)*/ 105 private double fMeasureAverage = 0.0; 106 /** The weight used in F-measure (see NLP Information Extraction)*/ 107 public static double weight = 0.5; 108 109 /** This string represents the type of annotations used to play the roll of 110 * total number of words needed to calculate the False Positive. 111 */ 112 private String annotationTypeForFalsePositive = null; 113 114 /** A number formater for displaying precision and recall*/ 115 protected static NumberFormat formatter = NumberFormat.getInstance(); 116 117 /** The components that will stay into diffPanel*/ 118 private XJTable diffTable = null; 119 120 /** Used to represent the result of diff. See DiffSetElement class.*/ 121 private Set diffSet = null; 122 123 /** This field is used in doDiff() and detectKeyType() methods and holds all 124 * partially correct keys */ 125 private Set keyPartiallySet = null; 126 /** This field is used in doDiff() and detectResponseType() methods*/ 127 private Set responsePartiallySet = null; 128 129 /** This list is created from keyAnnotationSet at init() time*/ 130 private java.util.List keyAnnotList = null; 131 /** This list is created from responseAnnotationSet at init() time*/ 132 private java.util.List responseAnnotList = null; 133 134 /** This field indicates wheter or not the annot diff should run int the text 135 * mode*/ 136 private boolean textMode = false; 137 138 /** Field designated to represent the max nr of annot types and coolors for 139 * each type 140 **/ 141 public static final int MAX_TYPES = 5; 142 /** A default type when all annotation are the same represented by White color*/ 143 public static final int DEFAULT_TYPE = 0; 144 /** A correct type when all annotation are corect represented by Green color*/ 145 public static final int CORRECT_TYPE = 1; 146 /** A partially correct type when all annotation are corect represented 147 * by Blue color*/ 148 public static final int PARTIALLY_CORRECT_TYPE = 2; 149 /** A spurious type when annotations in response were not present in key. 150 * Represented by Red color*/ 151 public static final int SPURIOUS_TYPE = 3; 152 /** A missing type when annotations in key were not present in response 153 * Represented by Yellow color*/ 154 public static final int MISSING_TYPE = 4; 155 156 /** Red used for SPURIOUS_TYPE*/ 157 private final Color RED = new Color(255,173,181); 158 /** Green used for CORRECT_TYPE*/ 159 private final Color GREEN = new Color(173,255,214); 160 /** White used for DEFAULT_TYPE*/ 161 private final Color WHITE = new Color(255,255,255); 162 /** Blue used for PARTIALLY_CORRECT_TYPE*/ 163 private final Color BLUE = new Color(173,215,255); 164 /** Yellow used for MISSING_TYPE*/ 165 private final Color YELLOW = new Color(255,231,173); 166 167 /** Used in DiffSetElement to represent an empty raw in the table*/ 168 private final int NULL_TYPE = -1; 169 /** Used in some setForeground() methods*/ 170 private final Color BLACK = new Color(0,0,0); 171 /** The array holding the colours according to the annotation types*/ 172 private Color colors[] = new Color[MAX_TYPES]; 173 174 /** A scroll for the AnnotDiff's table*/ 175 private JScrollPane scrollPane = null; 176 177 /** Used to store the no. of annotations from response,identified as belonging 178 * to one of the previous types. 179 */ 180 private long typeCounter[] = new long[MAX_TYPES]; 181 182 /** Constructs a AnnotationDif*/ 183 public AnnotationDiff(){ 184 } //AnnotationDiff 185 186 /** Sets the annotation type needed to calculate the falsePossitive measure 187 * @param anAnnotType is the annotation type needed to calculate a special 188 * mesure called falsePossitive. Usualy the value is "token", but it can be 189 * any other string with the same semantic. 190 */ 191 public void setAnnotationTypeForFalsePositive(String anAnnotType){ 192 annotationTypeForFalsePositive = anAnnotType; 193 } // setAnnotationTypeForFalsePositive 194 195 /** Gets the annotation type needed to calculate the falsePossitive measure 196 * @return annotation type needed to calculate a special 197 * mesure called falsePossitive. 198 */ 199 public String getAnnotationTypeForFalsePositive(){ 200 return annotationTypeForFalsePositive; 201 } // getAnnotationTypeForFalsePositive 202 203 /** Sets the keyDocument in AnnotDiff 204 * @param aKeyDocument The GATE document used as a key in annotation diff. 205 */ 206 public void setKeyDocument(Document aKeyDocument) { 207 keyDocument = aKeyDocument; 208 } // setKeyDocument 209 210 /** @return the keyDocument used in AnnotDiff process */ 211 public Document getKeyDocument(){ 212 return keyDocument; 213 } // getKeyDocument 214 215 /** Sets the keyAnnotationSetName in AnnotDiff 216 * @param aKeyAnnotationSetName The name of the annotation set from the 217 * keyDocument.If aKeyAnnotationSetName is null then the default annotation 218 * set will be used. 219 */ 220 public void setKeyAnnotationSetName(String aKeyAnnotationSetName){ 221 keyAnnotationSetName = aKeyAnnotationSetName; 222 } // setKeyAnnotationSetName(); 223 224 /** Gets the keyAnnotationSetName. 225 * @return The name of the keyAnnotationSet used in AnnotationDiff. If 226 * returns null then the the default annotation set will be used. 227 */ 228 public String getKeyAnnotationSetName(){ 229 return keyAnnotationSetName; 230 } // getKeyAnnotationSetName() 231 232 /** Sets the keyFeatureNamesSet in AnnotDiff. 233 * @param aKeyFeatureNamesSet a set containing the feature names from key 234 * that will be used in isPartiallyCompatible() 235 */ 236 public void setKeyFeatureNamesSet(Set aKeyFeatureNamesSet){ 237 keyFeatureNamesSet = aKeyFeatureNamesSet; 238 }//setKeyFeatureNamesSet(); 239 240 /** Gets the keyFeatureNamesSet in AnnotDiff. 241 * @return A set containing the feature names from key 242 * that will be used in isPartiallyCompatible() 243 */ 244 public Set getKeyFeatureNamesSet(){ 245 return keyFeatureNamesSet; 246 }//getKeyFeatureNamesSet(); 247 248 /** Sets the responseAnnotationSetName in AnnotDiff 249 * @param aResponseAnnotationSetName The name of the annotation set from the 250 * responseDocument.If aResponseAnnotationSetName is null then the default 251 * annotation set will be used. 252 */ 253 public void setResponseAnnotationSetName(String aResponseAnnotationSetName){ 254 responseAnnotationSetName = aResponseAnnotationSetName; 255 } // setResponseAnnotationSetName(); 256 257 /** gets the responseAnnotationSetName. 258 * @return The name of the responseAnnotationSet used in AnnotationDiff. If 259 * returns null then the the default annotation set will be used. 260 */ 261 public String getResponseAnnotationSetName(){ 262 return responseAnnotationSetName; 263 } // getResponseAnnotationSetName() 264 265 /** Sets the responseAnnotationSetNameFalsePoz in AnnotDiff 266 * @param aResponseAnnotationSetNameFalsePoz The name of the annotation set 267 * from the responseDocument.If aResponseAnnotationSetName is null 268 * then the default annotation set will be used. 269 */ 270 public void setResponseAnnotationSetNameFalsePoz( 271 String aResponseAnnotationSetNameFalsePoz){ 272 responseAnnotationSetNameFalsePoz = aResponseAnnotationSetNameFalsePoz; 273 } // setResponseAnnotationSetNameFalsePoz(); 274 275 /** gets the responseAnnotationSetNameFalsePoz. 276 * @return The name of the responseAnnotationSetFalsePoz used in 277 * AnnotationDiff. If returns null then the the default annotation 278 * set will be used. 279 */ 280 public String getResponseAnnotationSetNameFalsePoz(){ 281 return responseAnnotationSetNameFalsePoz; 282 } // getResponseAnnotationSetNamefalsePoz() 283 284 /** Sets the annot diff to work in the text mode.This would not initiate the 285 * GUI part of annot diff but it would calculate precision etc 286 */ 287 public void setTextMode(Boolean aTextMode){ 288 //it needs to be a Boolean and not boolean, because you cannot put 289 //in the parameters hashmap a boolean, it needs an object 290 textMode = aTextMode.booleanValue(); 291 }// End setTextMode(); 292 293 /** Gets the annot diff textmode.True means that the text mode is activated.*/ 294 public boolean isTextMode(){ 295 return textMode; 296 }// End setTextMode(); 297 298 /** Returns a set with all annotations of a specific type*/ 299 public Set getAnnotationsOfType(int annotType){ 300 HashSet results = new HashSet(); 301 if (diffSet == null) return results; 302 Iterator diffIter = diffSet.iterator(); 303 while(diffIter.hasNext()){ 304 DiffSetElement diffElem = (DiffSetElement)diffIter.next(); 305 switch(annotType){ 306 case CORRECT_TYPE:{ 307 if (diffElem.getRightType() == CORRECT_TYPE) 308 results.add(diffElem.getRightAnnotation()); 309 }break; 310 case PARTIALLY_CORRECT_TYPE:{ 311 if (diffElem.getRightType() == PARTIALLY_CORRECT_TYPE) 312 results.add(diffElem.getRightAnnotation()); 313 }break; 314 case SPURIOUS_TYPE:{ 315 if (diffElem.getRightType() == SPURIOUS_TYPE) 316 results.add(diffElem.getRightAnnotation()); 317 }break; 318 case MISSING_TYPE:{ 319 if (diffElem.getLeftType() == MISSING_TYPE) 320 results.add(diffElem.getLeftAnnotation()); 321 }break; 322 case DEFAULT_TYPE:{ 323 if (diffElem.getLeftType() == DEFAULT_TYPE) 324 results.add(diffElem.getLeftAnnotation()); 325 }break; 326 }// End switch 327 }// End while 328 return results; 329 }//getAnnotationsOfType 330 331 //Prameters utility methods 332 /** 333 * Gets the value of a parameter of this resource. 334 * @param paramaterName the name of the parameter 335 * @return the current value of the parameter 336 */ 337 public Object getParameterValue(String paramaterName) 338 throws ResourceInstantiationException{ 339 return AbstractResource.getParameterValue(this, paramaterName); 340 } 341 342 /** 343 * Sets the value for a specified parameter. 344 * 345 * @param paramaterName the name for the parameteer 346 * @param parameterValue the value the parameter will receive 347 */ 348 public void setParameterValue(String paramaterName, Object parameterValue) 349 throws ResourceInstantiationException{ 350 // get the beaninfo for the resource bean, excluding data about Object 351 BeanInfo resBeanInf = null; 352 try { 353 resBeanInf = Introspector.getBeanInfo(this.getClass(), Object.class); 354 } catch(Exception e) { 355 throw new ResourceInstantiationException( 356 "Couldn't get bean info for resource " + this.getClass().getName() 357 + Strings.getNl() + "Introspector exception was: " + e 358 ); 359 } 360 AbstractResource.setParameterValue(this, resBeanInf, paramaterName, parameterValue); 361 } 362 363 /** 364 * Sets the values for more parameters in one step. 365 * 366 * @param parameters a feature map that has paramete names as keys and 367 * parameter values as values. 368 */ 369 public void setParameterValues(FeatureMap parameters) 370 throws ResourceInstantiationException{ 371 AbstractResource.setParameterValues(this, parameters); 372 } 373 374 375 376 /////////////////////////////////////////////////// 377 // PRECISION methods 378 /////////////////////////////////////////////////// 379 380 /** @return the precisionStrict field*/ 381 public double getPrecisionStrict(){ 382 return precisionStrict; 383 } // getPrecisionStrict 384 385 /** @return the precisionLenient field*/ 386 public double getPrecisionLenient(){ 387 return precisionLenient; 388 } // getPrecisionLenient 389 390 /** @return the precisionAverage field*/ 391 public double getPrecisionAverage(){ 392 return precisionAverage; 393 } // getPrecisionAverage 394 395 /** @return the fMeasureStrict field*/ 396 public double getFMeasureStrict(){ 397 return fMeasureStrict; 398 } // getFMeasureStrict 399 400 /** @return the fMeasureLenient field*/ 401 public double getFMeasureLenient(){ 402 return fMeasureLenient; 403 } // getFMeasureLenient 404 405 /** @return the fMeasureAverage field*/ 406 public double getFMeasureAverage(){ 407 return fMeasureAverage; 408 } // getFMeasureAverage 409 410 /////////////////////////////////////////////////// 411 // RECALL methods 412 /////////////////////////////////////////////////// 413 414 /** @return the recallStrict field*/ 415 public double getRecallStrict(){ 416 return recallStrict; 417 } // getRecallStrict 418 419 /** @return the recallLenient field*/ 420 public double getRecallLenient(){ 421 return recallLenient; 422 } // getRecallLenient 423 424 /** @return the recallAverage field*/ 425 public double getRecallAverage(){ 426 return recallAverage; 427 } // getRecallAverage 428 429 /////////////////////////////////////////////////// 430 // Missing, spurious, etc methods 431 /////////////////////////////////////////////////// 432 433 public long getCorrectCount() { 434 return typeCounter[CORRECT_TYPE]; 435 } 436 437 public long getPartiallyCorrectCount() { 438 return typeCounter[PARTIALLY_CORRECT_TYPE]; 439 } 440 441 public long getSpuriousCount() { 442 return typeCounter[SPURIOUS_TYPE]; 443 } 444 445 public long getMissingCount() { 446 return typeCounter[MISSING_TYPE]; 447 } 448 449 /////////////////////////////////////////////////// 450 // FALSE POSITIVE methods 451 /////////////////////////////////////////////////// 452 453 /** @return the falsePositiveStrict field*/ 454 public double getFalsePositiveStrict(){ 455 return falsePositiveStrict; 456 } // getFalsePositiveStrict 457 458 /** @return the falsePositiveLenient field*/ 459 public double getFalsePositiveLenient(){ 460 return falsePositiveLenient; 461 } // getFalsePositiveLenient 462 463 /** @return the falsePositiveAverage field*/ 464 public double getFalsePositiveAverage(){ 465 return falsePositiveAverage; 466 } // getFalsePositive 467 468 /** 469 * @param aResponseDocument the GATE response Document 470 * containing the annotation Set being compared against the annotation from 471 * the keyDocument. 472 */ 473 public void setResponseDocument(Document aResponseDocument) { 474 responseDocument = aResponseDocument; 475 } //setResponseDocument 476 477 /** 478 * @param anAnnotationSchema the annotation type being compared. 479 * This type is found in annotationSchema object as field 480 * {@link gate.creole.AnnotationSchema#getAnnotationName()}. If is <b>null<b> 481 * then AnnotDiff will throw an exception when it comes to do the diff. 482 */ 483 public void setAnnotationSchema(AnnotationSchema anAnnotationSchema) { 484 annotationSchema = anAnnotationSchema; 485 } // setAnnotationType 486 487 /** @return the annotation schema object used in annotation diff process */ 488 public AnnotationSchema getAnnotationSchema(){ 489 return annotationSchema; 490 } // AnnotationSchema 491 492 public Dimension getPreferredScrollableViewportSize() { 493 return getPreferredSize(); 494 }// public Dimension getPreferredScrollableViewportSize() 495 496 public int getScrollableUnitIncrement(Rectangle visibleRect, 497 int orientation, int direction) { 498 return maxUnitIncrement; 499 }// public int getScrollableUnitIncrement 500 501 public int getScrollableBlockIncrement(Rectangle visibleRect, 502 int orientation, int direction) { 503 if (orientation == SwingConstants.HORIZONTAL) 504 return visibleRect.width - maxUnitIncrement; 505 else 506 return visibleRect.height - maxUnitIncrement; 507 }// public int getScrollableBlockIncrement 508 509 public boolean getScrollableTracksViewportWidth() { 510 return false; 511 }// public boolean getScrollableTracksViewportWidth() 512 513 public boolean getScrollableTracksViewportHeight() { 514 return false; 515 } 516 517 /** 518 * This method does the diff, Precision,Recall,FalsePositive 519 * calculation and so on. 520 */ 521 public Resource init() throws ResourceInstantiationException { 522 colors[DEFAULT_TYPE] = WHITE; 523 colors[CORRECT_TYPE] = GREEN; 524 colors[SPURIOUS_TYPE] = RED; 525 colors[PARTIALLY_CORRECT_TYPE] = BLUE; 526 colors[MISSING_TYPE] = YELLOW; 527 528 // Initialize the partially sets... 529 keyPartiallySet = new HashSet(); 530 responsePartiallySet = new HashSet(); 531 532 // Do the diff, P&R calculation and so on 533 AnnotationSet keyAnnotSet = null; 534 AnnotationSet responseAnnotSet = null; 535 536 if(annotationSchema == null) 537 throw new ResourceInstantiationException("No annotation schema defined !"); 538 539 if(keyDocument == null) 540 throw new ResourceInstantiationException("No key document defined !"); 541 542 if(responseDocument == null) 543 throw new ResourceInstantiationException("No response document defined !"); 544 545 if (keyAnnotationSetName == null) 546 // Get the default key AnnotationSet from the keyDocument 547 keyAnnotSet = keyDocument.getAnnotations().get( 548 annotationSchema.getAnnotationName()); 549 else 550 keyAnnotSet = keyDocument.getAnnotations(keyAnnotationSetName). 551 get(annotationSchema.getAnnotationName()); 552 553 if (keyAnnotSet == null) 554 // The diff will run with an empty set.All annotations from response 555 // would be spurious. 556 keyAnnotList = new LinkedList(); 557 else 558 // The alghoritm will modify this annotation set. It is better to make a 559 // separate copy of them. 560 keyAnnotList = new LinkedList(keyAnnotSet); 561 562 if (responseAnnotationSetName == null) 563 // Get the response AnnotationSet from the default set 564 responseAnnotSet = responseDocument.getAnnotations().get( 565 annotationSchema.getAnnotationName()); 566 else 567 responseAnnotSet = responseDocument.getAnnotations(responseAnnotationSetName). 568 get(annotationSchema.getAnnotationName()); 569 570 if (responseAnnotSet == null) 571 // The diff will run with an empty set.All annotations from key 572 // would be missing. 573 responseAnnotList = new LinkedList(); 574 else 575 // The alghoritm will modify this annotation set. It is better to make a 576 // separate copy of them. 577 responseAnnotList = new LinkedList(responseAnnotSet); 578 579 // Sort them ascending on Start offset (the comparator does that) 580 AnnotationSetComparator asComparator = new AnnotationSetComparator(); 581 Collections.sort(keyAnnotList, asComparator); 582 Collections.sort(responseAnnotList, asComparator); 583 584 for (int type=0; type < MAX_TYPES; type++) 585 typeCounter[type] = 0; 586 587 // Calculate the diff Set. This set will be used later with graphic 588 // visualisation. 589 doDiff(keyAnnotList, responseAnnotList); 590 591 // If it runs under text mode just stop here. 592 if (textMode) return this; 593 594 //Show it 595 // Configuring the formatter object. It will be used later to format 596 // precision and recall 597 formatter.setMaximumIntegerDigits(1); 598 formatter.setMinimumFractionDigits(4); 599 formatter.setMinimumFractionDigits(4); 600 601 // Create an Annotation diff table model 602 AnnotationDiffTableModel diffModel = new AnnotationDiffTableModel(diffSet); 603 // Create a XJTable based on this model 604 diffTable = new XJTable(diffModel); 605 diffTable.setAlignmentX(Component.LEFT_ALIGNMENT); 606 // Set the cell renderer for this table. 607 AnnotationDiffCellRenderer cellRenderer = new AnnotationDiffCellRenderer(); 608 diffTable.setDefaultRenderer(java.lang.String.class,cellRenderer); 609 diffTable.setDefaultRenderer(java.lang.Long.class,cellRenderer); 610 // Put the table into a JScroll 611 612 // Arange all components on a this JPanel 613 SwingUtilities.invokeLater(new Runnable(){ 614 public void run(){ 615 arangeAllComponents(); 616 } 617 }); 618 619 if (DEBUG) 620 printStructure(diffSet); 621 622 return this; 623 } //init() 624 625 /** This method creates the graphic components and aranges them on 626 * <b>this</b> JPanel 627 */ 628 protected void arangeAllComponents(){ 629 this.removeAll(); 630 // Setting the box layout for diffpanel 631 BoxLayout boxLayout = new BoxLayout(this,BoxLayout.Y_AXIS); 632 this.setLayout(boxLayout); 633 634 JTableHeader tableHeader = diffTable.getTableHeader(); 635 tableHeader.setAlignmentX(Component.LEFT_ALIGNMENT); 636 this.add(tableHeader); 637 diffTable.setAlignmentX(Component.LEFT_ALIGNMENT); 638 // Add the tableScroll to the diffPanel 639 this.add(diffTable); 640 641 642 // ADD the LEGEND 643 //Lay out the JLabels from left to right. 644 //Box infoBox = new Box(BoxLayout.X_AXIS); 645 JPanel infoBox = new JPanel(); 646 infoBox.setLayout(new BoxLayout(infoBox,BoxLayout.X_AXIS)); 647 infoBox.setAlignmentX(Component.LEFT_ALIGNMENT); 648 // Keep the components together 649 //box.add(Box.createHorizontalGlue()); 650 651 Box box = new Box(BoxLayout.Y_AXIS); 652 JLabel jLabel = new JLabel("LEGEND"); 653 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 654 jLabel.setOpaque(true); 655 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 656 box.add(jLabel); 657 658 jLabel = new JLabel("Missing (present in Key but not in Response): " + 659 typeCounter[MISSING_TYPE]); 660 jLabel.setForeground(BLACK); 661 jLabel.setBackground(colors[MISSING_TYPE]); 662 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 663 jLabel.setOpaque(true); 664 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 665 box.add(jLabel); 666 667 // Add a space 668 box.add(Box.createRigidArea(new Dimension(0,5))); 669 670 jLabel = new JLabel("Correct (total match): " + typeCounter[CORRECT_TYPE]); 671 jLabel.setForeground(BLACK); 672 jLabel.setBackground(colors[CORRECT_TYPE]); 673 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 674 jLabel.setOpaque(true); 675 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 676 box.add(jLabel); 677 678 // Add a space 679 box.add(Box.createRigidArea(new Dimension(0,5))); 680 681 jLabel =new JLabel("Partially correct (overlap in Key and Response): "+ 682 typeCounter[PARTIALLY_CORRECT_TYPE]); 683 jLabel.setForeground(BLACK); 684 jLabel.setBackground(colors[PARTIALLY_CORRECT_TYPE]); 685 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 686 jLabel.setOpaque(true); 687 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 688 box.add(jLabel); 689 690 // Add a space 691 box.add(Box.createRigidArea(new Dimension(0,5))); 692 693 jLabel = new JLabel("Spurious (present in Response but not in Key): " + 694 typeCounter[SPURIOUS_TYPE]); 695 jLabel.setForeground(BLACK); 696 jLabel.setBackground(colors[SPURIOUS_TYPE]); 697 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 698 jLabel.setOpaque(true); 699 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 700 box.add(jLabel); 701 702 infoBox.add(box); 703 // Add a space 704 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 705 706 // Precision measure 707 //Lay out the JLabels from left to right. 708 box = new Box(BoxLayout.Y_AXIS); 709 710 jLabel = new JLabel("Precision strict: " + 711 formatter.format(precisionStrict)); 712 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 713 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 714 box.add(jLabel); 715 716 jLabel = new JLabel("Precision average: " + 717 formatter.format(precisionAverage)); 718 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 719 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 720 box.add(jLabel); 721 722 jLabel = new JLabel("Precision lenient: " + 723 formatter.format(precisionLenient)); 724 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 725 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 726 box.add(jLabel); 727 728 infoBox.add(box); 729 // Add a space 730 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 731 732 // RECALL measure 733 //Lay out the JLabels from left to right. 734 box = new Box(BoxLayout.Y_AXIS); 735 736 jLabel = new JLabel("Recall strict: " + formatter.format(recallStrict)); 737 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 738 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 739 box.add(jLabel); 740 741 jLabel = new JLabel("Recall average: " + formatter.format(recallAverage)); 742 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 743 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 744 box.add(jLabel); 745 746 jLabel = new JLabel("Recall lenient: " + formatter.format(recallLenient)); 747 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 748 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 749 box.add(jLabel); 750 751 infoBox.add(box); 752 // Add a space 753 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 754 755 // F-Measure 756 //Lay out the JLabels from left to right. 757 box = new Box(BoxLayout.Y_AXIS); 758 759 jLabel = new JLabel("F-Measure strict: " + 760 formatter.format(fMeasureStrict)); 761 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 762 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 763 box.add(jLabel); 764 765 jLabel = new JLabel("F-Measure average: " + 766 formatter.format(fMeasureAverage)); 767 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 768 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 769 box.add(jLabel); 770 771 jLabel = new JLabel("F-Measure lenient: " + 772 formatter.format(fMeasureLenient)); 773 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 774 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 775 box.add(jLabel); 776 infoBox.add(box); 777 778 // Add a space 779 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 780 781 // FALSE POZITIVE measure 782 //Lay out the JLabels from left to right. 783 box = new Box(BoxLayout.Y_AXIS); 784 785 jLabel = new JLabel("False positive strict: " + 786 formatter.format(falsePositiveStrict)); 787 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 788 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 789 box.add(jLabel); 790 791 jLabel = new JLabel("False positive average: " + 792 formatter.format(falsePositiveAverage)); 793 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 794 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 795 box.add(jLabel); 796 797 jLabel = new JLabel("False positive lenient: " + 798 formatter.format(falsePositiveLenient)); 799 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 800 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 801 box.add(jLabel); 802 infoBox.add(box); 803 804 // Add a space 805 infoBox.add(Box.createRigidArea(new Dimension(10,0))); 806 807 this.add(infoBox); 808 } //arangeAllComponents 809 810 /** Used internally for debugging */ 811 protected void printStructure(Set aDiffSet){ 812 Iterator iterator = aDiffSet.iterator(); 813 String leftAnnot = null; 814 String rightAnnot = null; 815 while(iterator.hasNext()){ 816 DiffSetElement diffElem = (DiffSetElement) iterator.next(); 817 if (diffElem.getLeftAnnotation() == null) 818 leftAnnot = "NULL "; 819 else 820 leftAnnot = diffElem.getLeftAnnotation().toString(); 821 if (diffElem.getRightAnnotation() == null) 822 rightAnnot = " NULL"; 823 else 824 rightAnnot = diffElem.getRightAnnotation().toString(); 825 Out.prln( leftAnnot + "|" + rightAnnot); 826 } // end while 827 } // printStructure 828 829 /** This method is the brain of the AnnotationSet diff and creates a set with 830 * diffSetElement objects. 831 * @param aKeyAnnotList a list containing the annotations from key. If this 832 * param is <b>null</b> then the method will simply return and will not do a 833 * thing. 834 * @param aResponseAnnotList a list containing the annotation from response. 835 * If this param is <b>null</b> the method will return. 836 */ 837 protected void doDiff(java.util.List aKeyAnnotList, 838 java.util.List aResponseAnnotList){ 839 840 // If one of the annotation sets is null then is no point in doing the diff. 841 if (aKeyAnnotList == null || aResponseAnnotList == null) 842 return; 843 844 int responseSize = aResponseAnnotList.size(); 845 846 diffSet = new HashSet(); 847 // Iterate throught all elements from keyList and find those in the response 848 // list which satisfies isCompatible() and isPartiallyCompatible() relations 849 Iterator keyIterator = aKeyAnnotList.iterator(); 850 while(keyIterator.hasNext()){ 851 Annotation keyAnnot = (Annotation) keyIterator.next(); 852 Iterator responseIterator = aResponseAnnotList.iterator(); 853 854 DiffSetElement diffElement = null; 855 while(responseIterator.hasNext()){ 856 Annotation responseAnnot = (Annotation) responseIterator.next(); 857 858 if(keyAnnot.isPartiallyCompatible(responseAnnot,keyFeatureNamesSet)){ 859 keyPartiallySet.add(keyAnnot); 860 responsePartiallySet.add(responseAnnot); 861 if (keyAnnot.coextensive(responseAnnot)){ 862 // Found two compatible annotations 863 // Create a new DiffSetElement and add it to the diffSet 864 diffElement = new DiffSetElement( keyAnnot, 865 responseAnnot, 866 DEFAULT_TYPE, 867 CORRECT_TYPE); 868 869 // Add this element to the DiffSet 870 addToDiffset(diffElement); 871 } // End if (keyAnnot.coextensive(responseAnnot)) 872 }else if (keyAnnot.coextensive(responseAnnot)){ 873 // Found two aligned annotations. We have to find out if the response 874 // is partialy compatible with another key annotation. 875 // Create a new DiffSetElement and add it to the diffSet 876 diffElement = new DiffSetElement( keyAnnot, 877 responseAnnot, 878 detectKeyType(keyAnnot), 879 detectResponseType(responseAnnot)); 880 // Add this element to the DiffSet 881 addToDiffset(diffElement); 882 } // End if (keyAnnot.coextensive(responseAnnot)){ 883 884 if (diffElement != null){ 885 // Eliminate the response annotation from the list. 886 responseIterator.remove(); 887 break; 888 } // End if 889 } // end while responseIterator 890 891 // If diffElement != null it means that break was used 892 if (diffElement == null){ 893 if (keyPartiallySet.contains(keyAnnot)) 894 diffElement = new DiffSetElement( keyAnnot, 895 null, 896 DEFAULT_TYPE, 897 NULL_TYPE); 898 else{ 899 // If keyAnnot is not in keyPartiallySet then it has to be checked 900 // agains all annotations in DiffSet to see if there is 901 // a previous annotation from response set which is partially 902 // compatible with the keyAnnot 903 Iterator respParIter = diffSet.iterator(); 904 while (respParIter.hasNext()){ 905 DiffSetElement diffElem = (DiffSetElement) respParIter.next(); 906 Annotation respAnnot = diffElem.getRightAnnotation(); 907 if (respAnnot != null && keyAnnot.isPartiallyCompatible(respAnnot, 908 keyFeatureNamesSet)){ 909 diffElement = new DiffSetElement( keyAnnot, 910 null, 911 DEFAULT_TYPE, 912 NULL_TYPE); 913 break; 914 } // End if 915 } // End while 916 // If is still nul then it means that the key annotation is missing 917 if (diffElement == null) 918 diffElement = new DiffSetElement( keyAnnot, 919 null, 920 MISSING_TYPE, 921 NULL_TYPE); 922 } // End if 923 addToDiffset(diffElement); 924 } // End if 925 926 keyIterator.remove(); 927 } // end while keyIterator 928 929 DiffSetElement diffElem = null; 930 Iterator responseIter = aResponseAnnotList.iterator(); 931 while (responseIter.hasNext()){ 932 Annotation respAnnot = (Annotation) responseIter.next(); 933 if (responsePartiallySet.contains(respAnnot)) 934 diffElem = new DiffSetElement( null, 935 respAnnot, 936 NULL_TYPE, 937 PARTIALLY_CORRECT_TYPE); 938 else 939 diffElem = new DiffSetElement( null, 940 respAnnot, 941 NULL_TYPE, 942 SPURIOUS_TYPE); 943 addToDiffset(diffElem); 944 responseIter.remove(); 945 } // End while 946 947 // CALCULATE ALL (NLP) MEASURES like: 948 // Precistion, Recall, FalsePositive and F-Measure 949 long possible = typeCounter[CORRECT_TYPE] + // this comes from Key or Resp 950 typeCounter[PARTIALLY_CORRECT_TYPE] + // this comes from Resp 951 typeCounter[MISSING_TYPE]; // this comes from Key 952 953 long actual = typeCounter[CORRECT_TYPE] + // this comes from Key or Resp 954 typeCounter[PARTIALLY_CORRECT_TYPE] + // this comes from Resp 955 typeCounter[SPURIOUS_TYPE]; // this comes from Resp 956 957 if (actual != responseSize) 958 Err.prln("AnnotDiff warning: The response size(" + responseSize + 959 ") is not the same as the computed value of" + 960 " actual(Correct[resp or key]+Partial[resp]+Spurious[resp]=" + actual +")"); 961 962 if (actual != 0){ 963 precisionStrict = ((double)typeCounter[CORRECT_TYPE])/((double)actual); 964 precisionLenient = ((double)(typeCounter[CORRECT_TYPE] + 965 typeCounter[PARTIALLY_CORRECT_TYPE]))/((double)actual); 966 precisionAverage = ((double)(precisionStrict + precisionLenient)) / 967 ((double) 2); 968 } // End if 969 if (possible != 0){ 970 recallStrict = ((double)typeCounter[CORRECT_TYPE])/((double)possible); 971 recallLenient = ((double)(typeCounter[CORRECT_TYPE] + 972 typeCounter[PARTIALLY_CORRECT_TYPE]))/((double)possible); 973 recallAverage = ((double)(recallStrict + recallLenient)) / ((double)2); 974 } // End if 975 976 977 int no = 0; 978 // If an annotation type for false poz was selected calculate the number of 979 // Annotations 980 if (annotationTypeForFalsePositive != null) 981 // Was it the default set ? 982 if (responseAnnotationSetNameFalsePoz == null){ 983 AnnotationSet aSet = responseDocument.getAnnotations().get( 984 annotationTypeForFalsePositive); 985 no = aSet == null ? 0 : aSet.size(); 986 }else{ 987 AnnotationSet aSet = responseDocument.getAnnotations(responseAnnotationSetNameFalsePoz).get( 988 annotationTypeForFalsePositive); 989 no = aSet == null? 0 : aSet.size(); 990 } 991 if (no != 0){ 992 // No error here: the formula is the opposite to recall or precission 993 falsePositiveStrict = ((double)(typeCounter[SPURIOUS_TYPE] + 994 typeCounter[PARTIALLY_CORRECT_TYPE])) /((double)no); 995 falsePositiveLenient = ((double)typeCounter[SPURIOUS_TYPE]) /((double) no); 996 falsePositiveAverage = ((double)(falsePositiveStrict + 997 falsePositiveLenient))/((double)2) ; 998 } // End if 999 1000 // Calculate F-Measure Strict 1001 double denominator = weight * (precisionStrict + recallStrict); 1002 if (denominator != 0) 1003 fMeasureStrict = (precisionStrict * recallStrict) / denominator ; 1004 else fMeasureStrict = 0.0; 1005 // Calculate F-Measure Lenient 1006 denominator = weight * (precisionLenient + recallLenient); 1007 if (denominator != 0) 1008 fMeasureLenient = (precisionLenient * recallLenient) / denominator ; 1009 else fMeasureLenient = 0.0; 1010 // Calculate F-Measure Average 1011 fMeasureAverage = (fMeasureStrict + fMeasureLenient) / (double)2; 1012 1013 } // doDiff 1014 1015 /** Decide what type is the keyAnnotation (DEFAULT_TYPE, MISSING or NULL_TYPE) 1016 * This method must be applied only on annotation from key set. 1017 * @param anAnnot is an annotation from the key set. 1018 * @return three possible value(DEFAULT_TYPE, MISSING or NULL_TYPE) 1019 */ 1020 private int detectKeyType(Annotation anAnnot){ 1021 if (anAnnot == null) return NULL_TYPE; 1022 1023 if (keyPartiallySet.contains(anAnnot)) return DEFAULT_TYPE; 1024 Iterator iter = responsePartiallySet.iterator(); 1025 while(iter.hasNext()){ 1026 Annotation a = (Annotation) iter.next(); 1027 if (anAnnot.isPartiallyCompatible(a,keyFeatureNamesSet)) 1028 return DEFAULT_TYPE; 1029 } // End while 1030 1031 iter = responseAnnotList.iterator(); 1032 while(iter.hasNext()){ 1033 Annotation a = (Annotation) iter.next(); 1034 if (anAnnot.isPartiallyCompatible(a,keyFeatureNamesSet)){ 1035 responsePartiallySet.add(a); 1036 keyPartiallySet.add(anAnnot); 1037 return DEFAULT_TYPE; 1038 } // End if 1039 } // End while 1040 return MISSING_TYPE; 1041 } //detectKeyType 1042 1043 /** Decide what type is the responseAnnotation 1044 * (PARTIALLY_CORRECT_TYPE, SPURIOUS or NULL_TYPE) 1045 * This method must be applied only on annotation from response set. 1046 * @param anAnnot is an annotation from the key set. 1047 * @return three possible value(PARTIALLY_CORRECT_TYPE, SPURIOUS or NULL_TYPE) 1048 */ 1049 private int detectResponseType(Annotation anAnnot){ 1050 if (anAnnot == null) return NULL_TYPE; 1051 1052 if (responsePartiallySet.contains(anAnnot)) return PARTIALLY_CORRECT_TYPE; 1053 Iterator iter = keyPartiallySet.iterator(); 1054 while(iter.hasNext()){ 1055 Annotation a = (Annotation) iter.next(); 1056 if (a.isPartiallyCompatible(anAnnot,keyFeatureNamesSet)) 1057 return PARTIALLY_CORRECT_TYPE; 1058 } // End while 1059 1060 iter = keyAnnotList.iterator(); 1061 while(iter.hasNext()){ 1062 Annotation a = (Annotation) iter.next(); 1063 if (a.isPartiallyCompatible(anAnnot,keyFeatureNamesSet)){ 1064 responsePartiallySet.add(anAnnot); 1065 keyPartiallySet.add(a); 1066 return PARTIALLY_CORRECT_TYPE; 1067 } // End if 1068 } // End while 1069 return SPURIOUS_TYPE; 1070 } //detectResponseType 1071 1072 /** This method add an DiffsetElement to the DiffSet and also counts the 1073 * number of compatible, partialCompatible, Incorect and Missing annotations. 1074 */ 1075 private void addToDiffset(DiffSetElement aDiffSetElement){ 1076 if (aDiffSetElement == null) return; 1077 1078 diffSet.add(aDiffSetElement); 1079 // For the Right side (response) the type can be one of the following: 1080 // PC, I, C 1081 if (NULL_TYPE != aDiffSetElement.getRightType()) 1082 typeCounter[aDiffSetElement.getRightType()]++; 1083 // For the left side (key) the type can be : D or M 1084 if (NULL_TYPE != aDiffSetElement.getLeftType() && 1085 CORRECT_TYPE != aDiffSetElement.getLeftType()) 1086 typeCounter[aDiffSetElement.getLeftType()]++; 1087 } // addToDiffset 1088 1089 /* ******************************************************************** 1090 * INNER CLASS 1091 * ********************************************************************/ 1092 1093 /** 1094 * A custom table model used to render a table containing the two annotation 1095 * sets. The columns will be: 1096 * (KEY) Type, Start, End, Features, empty column,(Response) Type,Start, End, Features 1097 */ 1098 protected class AnnotationDiffTableModel extends AbstractTableModel{ 1099 1100 /** Constructs an AnnotationDiffTableModel given a data Collection */ 1101 public AnnotationDiffTableModel(Collection data){ 1102 modelData = new ArrayList(); 1103 modelData.addAll(data); 1104 } // AnnotationDiffTableModel 1105 1106 /** Constructs an AnnotationDiffTableModel */ 1107 public AnnotationDiffTableModel(){ 1108 modelData = new ArrayList(); 1109 } // AnnotationDiffTableModel 1110 1111 /** Return the size of data.*/ 1112 public int getRowCount(){ 1113 return modelData.size(); 1114 } //getRowCount 1115 1116 /** Return the number of columns.*/ 1117 public int getColumnCount(){ 1118 return 9; 1119 } //getColumnCount 1120 1121 /** Returns the name of each column in the model*/ 1122 public String getColumnName(int column){ 1123 switch(column){ 1124 case 0: return "String - Key"; 1125 case 1: return "Start - Key"; 1126 case 2: return "End - Key"; 1127 case 3: return "Features - Key"; 1128 case 4: return " "; 1129 case 5: return "String - Response"; 1130 case 6: return "Start - Response"; 1131 case 7: return "End -Response"; 1132 case 8: return "Features - Response"; 1133 default:return "?"; 1134 } 1135 } //getColumnName 1136 1137 /** Return the class type for each column. */ 1138 public Class getColumnClass(int column){ 1139 switch(column){ 1140 case 0: return String.class; 1141 case 1: return Long.class; 1142 case 2: return Long.class; 1143 case 3: return String.class; 1144 case 4: return String.class; 1145 case 5: return String.class; 1146 case 6: return Long.class; 1147 case 7: return Long.class; 1148 case 8: return String.class; 1149 default:return Object.class; 1150 } 1151 } //getColumnClass 1152 1153 /**Returns a value from the table model */ 1154 public Object getValueAt(int row, int column){ 1155 DiffSetElement diffSetElement = (DiffSetElement) modelData.get(row); 1156 if (diffSetElement == null) return null; 1157 switch(column){ 1158 // Left Side (Key) 1159 //Type - Key 1160 case 0:{ 1161 if (diffSetElement.getLeftAnnotation() == null) return null; 1162// return diffSetElement.getLeftAnnotation().getType(); 1163 Annotation annot = diffSetElement.getLeftAnnotation(); 1164 String theString = ""; 1165 try { 1166 theString = keyDocument.getContent().getContent( 1167 annot.getStartNode().getOffset(), 1168 annot.getEndNode().getOffset()).toString(); 1169 } catch (gate.util.InvalidOffsetException ex) { 1170 Err.prln(ex.getMessage()); 1171 } 1172 return theString; 1173 } 1174 // Start - Key 1175 case 1:{ 1176 if (diffSetElement.getLeftAnnotation() == null) return null; 1177 return diffSetElement.getLeftAnnotation().getStartNode().getOffset(); 1178 } 1179 // End - Key 1180 case 2:{ 1181 if (diffSetElement.getLeftAnnotation() == null) return null; 1182 return diffSetElement.getLeftAnnotation().getEndNode().getOffset(); 1183 } 1184 // Features - Key 1185 case 3:{ 1186 if (diffSetElement.getLeftAnnotation() == null) return null; 1187 if (diffSetElement.getLeftAnnotation().getFeatures() == null) 1188 return null; 1189 return diffSetElement.getLeftAnnotation().getFeatures().toString(); 1190 } 1191 // Empty column 1192 case 4:{ 1193 return " "; 1194 } 1195 // Right Side (Response) 1196 //Type - Response 1197 case 5:{ 1198 if (diffSetElement.getRightAnnotation() == null) return null; 1199// return diffSetElement.getRightAnnotation().getType(); 1200 Annotation annot = diffSetElement.getRightAnnotation(); 1201 String theString = ""; 1202 try { 1203 theString = responseDocument.getContent().getContent( 1204 annot.getStartNode().getOffset(), 1205 annot.getEndNode().getOffset()).toString(); 1206 } catch (gate.util.InvalidOffsetException ex) { 1207 Err.prln(ex.getMessage()); 1208 } 1209 return theString; 1210 } 1211 // Start - Response 1212 case 6:{ 1213 if (diffSetElement.getRightAnnotation() == null) return null; 1214 return diffSetElement.getRightAnnotation().getStartNode().getOffset(); 1215 } 1216 // End - Response 1217 case 7:{ 1218 if (diffSetElement.getRightAnnotation() == null) return null; 1219 return diffSetElement.getRightAnnotation().getEndNode().getOffset(); 1220 } 1221 // Features - resonse 1222 case 8:{ 1223 if (diffSetElement.getRightAnnotation() == null) return null; 1224 return diffSetElement.getRightAnnotation().getFeatures().toString(); 1225 } 1226 // The hidden column 1227 case 9:{ 1228 return diffSetElement; 1229 } 1230 default:{return null;} 1231 } // End switch 1232 } //getValueAt 1233 1234 public Object getRawObject(int row){ 1235 return modelData.get(row); 1236 } //getRawObject 1237 1238 /** Holds the data for TableDiff*/ 1239 private java.util.List modelData = null; 1240 1241 } //Inner class AnnotationDiffTableModel 1242 1243 /* ******************************************************************** 1244 * INNER CLASS 1245 * ********************************************************************/ 1246 /** 1247 * This class defines a Cell renderer for the AnnotationDiff table 1248 */ 1249 public class AnnotationDiffCellRenderer extends DefaultTableCellRenderer{ 1250 1251 /** Constructs a randerer with a table model*/ 1252 public AnnotationDiffCellRenderer() { } //AnnotationDiffCellRenderer 1253 1254 private Color background = WHITE; 1255 1256 private Color foreground = BLACK; 1257 1258 /** This method is called by JTable*/ 1259 1260 public Component getTableCellRendererComponent( 1261 JTable table, Object value, boolean isSelected, boolean hasFocus, 1262 int row, int column 1263 ) { 1264 JComponent defaultComp = null; 1265 defaultComp = (JComponent) super.getTableCellRendererComponent( 1266 table, value, isSelected, hasFocus, row, column 1267 ); 1268 1269 // The column number four will be randered using a blank component 1270 if (column == 4 || value == null) 1271 return new JPanel(); 1272 1273 if (!(table.getModel().getValueAt(row,9) instanceof DiffSetElement)) 1274 return defaultComp; 1275 1276 DiffSetElement diffSetElement = 1277 (DiffSetElement) table.getModel().getValueAt(row,9); 1278 1279 if (diffSetElement == null) 1280 return defaultComp; 1281 1282 if (column < 4){ 1283 if (NULL_TYPE != diffSetElement.getLeftType()) 1284 background = colors[diffSetElement.getLeftType()]; 1285 else return new JPanel(); 1286 }else{ 1287 if (NULL_TYPE != diffSetElement.getRightType()) 1288 background = colors[diffSetElement.getRightType()]; 1289 else return new JPanel(); 1290 } 1291 1292 defaultComp.setBackground(background); 1293 defaultComp.setForeground(BLACK); 1294 1295 defaultComp.setOpaque(true); 1296 return defaultComp; 1297 } //getTableCellRendererComponent 1298 1299 } // class AnnotationDiffCellRenderer 1300 1301 /* ******************************************************************** 1302 * INNER CLASS 1303 * ********************************************************************/ 1304 class AnnotationSetComparator implements java.util.Comparator { 1305 1306 public AnnotationSetComparator(){} 1307 1308 public int compare(Object o1, Object o2) { 1309 if ( !(o1 instanceof gate.Annotation) || 1310 !(o2 instanceof gate.Annotation)) return 0; 1311 1312 gate.Annotation a1 = (gate.Annotation) o1; 1313 gate.Annotation a2 = (gate.Annotation) o2; 1314 1315 Long l1 = a1.getStartNode().getOffset(); 1316 Long l2 = a2.getStartNode().getOffset(); 1317 if (l1 != null) 1318 return l1.compareTo(l2); 1319 else 1320 return -1; 1321 } //compare 1322 } // class AnnotationSetComparator 1323 1324 /* ******************************************************************** 1325 * INNER CLASS 1326 * ********************************************************************/ 1327 1328 /** 1329 * This class is used for internal purposes. It represents a row from the 1330 * table. 1331 */ 1332 protected class DiffSetElement { 1333 /** This field represent a key annotation*/ 1334 private Annotation leftAnnotation = null; 1335 /** This field represent a response annotation*/ 1336 private Annotation rightAnnotation = null; 1337 /** Default initialization of the key type*/ 1338 private int leftType = DEFAULT_TYPE; 1339 /** Default initialization of the response type*/ 1340 private int rightType = DEFAULT_TYPE; 1341 1342 /** Constructor for DiffSetlement*/ 1343 public DiffSetElement() {} 1344 1345 /** Constructor for DiffSetlement*/ 1346 public DiffSetElement( Annotation aLeftAnnotation, 1347 Annotation aRightAnnotation, 1348 int aLeftType, 1349 int aRightType){ 1350 leftAnnotation = aLeftAnnotation; 1351 rightAnnotation = aRightAnnotation; 1352 leftType = aLeftType; 1353 rightType = aRightType; 1354 } // DiffSetElement 1355 1356 /** Sets the left annotation*/ 1357 public void setLeftAnnotation(Annotation aLeftAnnotation){ 1358 leftAnnotation = aLeftAnnotation; 1359 } // setLeftAnnot 1360 1361 /** Gets the left annotation*/ 1362 public Annotation getLeftAnnotation(){ 1363 return leftAnnotation; 1364 } // getLeftAnnotation 1365 1366 /** Sets the right annotation*/ 1367 public void setRightAnnotation(Annotation aRightAnnotation){ 1368 rightAnnotation = aRightAnnotation; 1369 } // setRightAnnot 1370 1371 /** Gets the right annotation*/ 1372 public Annotation getRightAnnotation(){ 1373 return rightAnnotation; 1374 } // getRightAnnotation 1375 1376 /** Sets the left type*/ 1377 public void setLeftType(int aLeftType){ 1378 leftType = aLeftType; 1379 } // setLeftType 1380 1381 /** Get the left type */ 1382 public int getLeftType() { 1383 return leftType; 1384 } // getLeftType 1385 1386 /** Sets the right type*/ 1387 public void setRightType(int aRightType) { 1388 rightType = aRightType; 1389 } // setRightType 1390 1391 /** Get the right type*/ 1392 public int getRightType() { 1393 return rightType; 1394 } // getRightType 1395 } // classs DiffSetElement 1396} // class AnnotationDiff 1397
|
AnnotationDiff |
|