|
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.42 2002/03/06 17:44:44 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 int typeCounter[] = new int[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 // FALSE POSITIVE methods 431 /////////////////////////////////////////////////// 432 433 /** @return the falsePositiveStrict field*/ 434 public double getFalsePositiveStrict(){ 435 return falsePositiveStrict; 436 } // getFalsePositiveStrict 437 438 /** @return the falsePositiveLenient field*/ 439 public double getFalsePositiveLenient(){ 440 return falsePositiveLenient; 441 } // getFalsePositiveLenient 442 443 /** @return the falsePositiveAverage field*/ 444 public double getFalsePositiveAverage(){ 445 return falsePositiveAverage; 446 } // getFalsePositive 447 448 /** 449 * @param aResponseDocument the GATE response Document 450 * containing the annotation Set being compared against the annotation from 451 * the keyDocument. 452 */ 453 public void setResponseDocument(Document aResponseDocument) { 454 responseDocument = aResponseDocument; 455 } //setResponseDocument 456 457 /** 458 * @param anAnnotationSchema the annotation type being compared. 459 * This type is found in annotationSchema object as field 460 * {@link gate.creole.AnnotationSchema#getAnnotationName()}. If is <b>null<b> 461 * then AnnotDiff will throw an exception when it comes to do the diff. 462 */ 463 public void setAnnotationSchema(AnnotationSchema anAnnotationSchema) { 464 annotationSchema = anAnnotationSchema; 465 } // setAnnotationType 466 467 /** @return the annotation schema object used in annotation diff process */ 468 public AnnotationSchema getAnnotationSchema(){ 469 return annotationSchema; 470 } // AnnotationSchema 471 472 public Dimension getPreferredScrollableViewportSize() { 473 return getPreferredSize(); 474 }// public Dimension getPreferredScrollableViewportSize() 475 476 public int getScrollableUnitIncrement(Rectangle visibleRect, 477 int orientation, int direction) { 478 return maxUnitIncrement; 479 }// public int getScrollableUnitIncrement 480 481 public int getScrollableBlockIncrement(Rectangle visibleRect, 482 int orientation, int direction) { 483 if (orientation == SwingConstants.HORIZONTAL) 484 return visibleRect.width - maxUnitIncrement; 485 else 486 return visibleRect.height - maxUnitIncrement; 487 }// public int getScrollableBlockIncrement 488 489 public boolean getScrollableTracksViewportWidth() { 490 return false; 491 }// public boolean getScrollableTracksViewportWidth() 492 493 public boolean getScrollableTracksViewportHeight() { 494 return false; 495 } 496 497 /** 498 * This method does the diff, Precision,Recall,FalsePositive 499 * calculation and so on. 500 */ 501 public Resource init() throws ResourceInstantiationException { 502 colors[DEFAULT_TYPE] = WHITE; 503 colors[CORRECT_TYPE] = GREEN; 504 colors[SPURIOUS_TYPE] = RED; 505 colors[PARTIALLY_CORRECT_TYPE] = BLUE; 506 colors[MISSING_TYPE] = YELLOW; 507 508 // Initialize the partially sets... 509 keyPartiallySet = new HashSet(); 510 responsePartiallySet = new HashSet(); 511 512 // Do the diff, P&R calculation and so on 513 AnnotationSet keyAnnotSet = null; 514 AnnotationSet responseAnnotSet = null; 515 516 if(annotationSchema == null) 517 throw new ResourceInstantiationException("No annotation schema defined !"); 518 519 if(keyDocument == null) 520 throw new ResourceInstantiationException("No key document defined !"); 521 522 if(responseDocument == null) 523 throw new ResourceInstantiationException("No response document defined !"); 524 525 if (keyAnnotationSetName == null) 526 // Get the default key AnnotationSet from the keyDocument 527 keyAnnotSet = keyDocument.getAnnotations().get( 528 annotationSchema.getAnnotationName()); 529 else 530 keyAnnotSet = keyDocument.getAnnotations(keyAnnotationSetName). 531 get(annotationSchema.getAnnotationName()); 532 533 if (keyAnnotSet == null) 534 // The diff will run with an empty set.All annotations from response 535 // would be spurious. 536 keyAnnotList = new LinkedList(); 537 else 538 // The alghoritm will modify this annotation set. It is better to make a 539 // separate copy of them. 540 keyAnnotList = new LinkedList(keyAnnotSet); 541 542 if (responseAnnotationSetName == null) 543 // Get the response AnnotationSet from the default set 544 responseAnnotSet = responseDocument.getAnnotations().get( 545 annotationSchema.getAnnotationName()); 546 else 547 responseAnnotSet = responseDocument.getAnnotations(responseAnnotationSetName). 548 get(annotationSchema.getAnnotationName()); 549 550 if (responseAnnotSet == null) 551 // The diff will run with an empty set.All annotations from key 552 // would be missing. 553 responseAnnotList = new LinkedList(); 554 else 555 // The alghoritm will modify this annotation set. It is better to make a 556 // separate copy of them. 557 responseAnnotList = new LinkedList(responseAnnotSet); 558 559 // Sort them ascending on Start offset (the comparator does that) 560 AnnotationSetComparator asComparator = new AnnotationSetComparator(); 561 Collections.sort(keyAnnotList, asComparator); 562 Collections.sort(responseAnnotList, asComparator); 563 564 for (int type=0; type < MAX_TYPES; type++) 565 typeCounter[type] = 0; 566 567 // Calculate the diff Set. This set will be used later with graphic 568 // visualisation. 569 doDiff(keyAnnotList, responseAnnotList); 570 571 // If it runs under text mode just stop here. 572 if (textMode) return this; 573 574 //Show it 575 // Configuring the formatter object. It will be used later to format 576 // precision and recall 577 formatter.setMaximumIntegerDigits(1); 578 formatter.setMinimumFractionDigits(4); 579 formatter.setMinimumFractionDigits(4); 580 581 // Create an Annotation diff table model 582 AnnotationDiffTableModel diffModel = new AnnotationDiffTableModel(diffSet); 583 // Create a XJTable based on this model 584 diffTable = new XJTable(diffModel); 585 diffTable.setAlignmentX(Component.LEFT_ALIGNMENT); 586 // Set the cell renderer for this table. 587 AnnotationDiffCellRenderer cellRenderer = new AnnotationDiffCellRenderer(); 588 diffTable.setDefaultRenderer(java.lang.String.class,cellRenderer); 589 diffTable.setDefaultRenderer(java.lang.Long.class,cellRenderer); 590 // Put the table into a JScroll 591 592 // Arange all components on a this JPanel 593 SwingUtilities.invokeLater(new Runnable(){ 594 public void run(){ 595 arangeAllComponents(); 596 } 597 }); 598 599 if (DEBUG) 600 printStructure(diffSet); 601 602 return this; 603 } //init() 604 605 /** This method creates the graphic components and aranges them on 606 * <b>this</b> JPanel 607 */ 608 protected void arangeAllComponents(){ 609 this.removeAll(); 610 // Setting the box layout for diffpanel 611 BoxLayout boxLayout = new BoxLayout(this,BoxLayout.Y_AXIS); 612 this.setLayout(boxLayout); 613 614 JTableHeader tableHeader = diffTable.getTableHeader(); 615 tableHeader.setAlignmentX(Component.LEFT_ALIGNMENT); 616 this.add(tableHeader); 617 diffTable.setAlignmentX(Component.LEFT_ALIGNMENT); 618 // Add the tableScroll to the diffPanel 619 this.add(diffTable); 620 621 622 // ADD the LEGEND 623 //Lay out the JLabels from left to right. 624 //Box infoBox = new Box(BoxLayout.X_AXIS); 625 JPanel infoBox = new JPanel(); 626 infoBox.setLayout(new BoxLayout(infoBox,BoxLayout.X_AXIS)); 627 infoBox.setAlignmentX(Component.LEFT_ALIGNMENT); 628 // Keep the components together 629 //box.add(Box.createHorizontalGlue()); 630 631 Box box = new Box(BoxLayout.Y_AXIS); 632 JLabel jLabel = new JLabel("LEGEND"); 633 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 634 jLabel.setOpaque(true); 635 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 636 box.add(jLabel); 637 638 jLabel = new JLabel("Missing (present in Key but not in Response): " + 639 typeCounter[MISSING_TYPE]); 640 jLabel.setForeground(BLACK); 641 jLabel.setBackground(colors[MISSING_TYPE]); 642 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 643 jLabel.setOpaque(true); 644 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 645 box.add(jLabel); 646 647 // Add a space 648 box.add(Box.createRigidArea(new Dimension(0,5))); 649 650 jLabel = new JLabel("Correct (total match): " + typeCounter[CORRECT_TYPE]); 651 jLabel.setForeground(BLACK); 652 jLabel.setBackground(colors[CORRECT_TYPE]); 653 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 654 jLabel.setOpaque(true); 655 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 656 box.add(jLabel); 657 658 // Add a space 659 box.add(Box.createRigidArea(new Dimension(0,5))); 660 661 jLabel =new JLabel("Partially correct (overlap in Key and Response): "+ 662 typeCounter[PARTIALLY_CORRECT_TYPE]); 663 jLabel.setForeground(BLACK); 664 jLabel.setBackground(colors[PARTIALLY_CORRECT_TYPE]); 665 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 666 jLabel.setOpaque(true); 667 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 668 box.add(jLabel); 669 670 // Add a space 671 box.add(Box.createRigidArea(new Dimension(0,5))); 672 673 jLabel = new JLabel("Spurious (present in Response but not in Key): " + 674 typeCounter[SPURIOUS_TYPE]); 675 jLabel.setForeground(BLACK); 676 jLabel.setBackground(colors[SPURIOUS_TYPE]); 677 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 678 jLabel.setOpaque(true); 679 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 680 box.add(jLabel); 681 682 infoBox.add(box); 683 // Add a space 684 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 685 686 // Precision measure 687 //Lay out the JLabels from left to right. 688 box = new Box(BoxLayout.Y_AXIS); 689 690 jLabel = new JLabel("Precision strict: " + 691 formatter.format(precisionStrict)); 692 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 693 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 694 box.add(jLabel); 695 696 jLabel = new JLabel("Precision average: " + 697 formatter.format(precisionAverage)); 698 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 699 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 700 box.add(jLabel); 701 702 jLabel = new JLabel("Precision lenient: " + 703 formatter.format(precisionLenient)); 704 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 705 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 706 box.add(jLabel); 707 708 infoBox.add(box); 709 // Add a space 710 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 711 712 // RECALL measure 713 //Lay out the JLabels from left to right. 714 box = new Box(BoxLayout.Y_AXIS); 715 716 jLabel = new JLabel("Recall strict: " + formatter.format(recallStrict)); 717 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 718 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 719 box.add(jLabel); 720 721 jLabel = new JLabel("Recall average: " + formatter.format(recallAverage)); 722 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 723 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 724 box.add(jLabel); 725 726 jLabel = new JLabel("Recall lenient: " + formatter.format(recallLenient)); 727 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 728 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 729 box.add(jLabel); 730 731 infoBox.add(box); 732 // Add a space 733 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 734 735 // F-Measure 736 //Lay out the JLabels from left to right. 737 box = new Box(BoxLayout.Y_AXIS); 738 739 jLabel = new JLabel("F-Measure strict: " + 740 formatter.format(fMeasureStrict)); 741 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 742 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 743 box.add(jLabel); 744 745 jLabel = new JLabel("F-Measure average: " + 746 formatter.format(fMeasureAverage)); 747 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 748 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 749 box.add(jLabel); 750 751 jLabel = new JLabel("F-Measure lenient: " + 752 formatter.format(fMeasureLenient)); 753 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 754 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 755 box.add(jLabel); 756 infoBox.add(box); 757 758 // Add a space 759 infoBox.add(Box.createRigidArea(new Dimension(40,0))); 760 761 // FALSE POZITIVE measure 762 //Lay out the JLabels from left to right. 763 box = new Box(BoxLayout.Y_AXIS); 764 765 jLabel = new JLabel("False positive strict: " + 766 formatter.format(falsePositiveStrict)); 767 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 768 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 769 box.add(jLabel); 770 771 jLabel = new JLabel("False positive average: " + 772 formatter.format(falsePositiveAverage)); 773 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 774 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 775 box.add(jLabel); 776 777 jLabel = new JLabel("False positive lenient: " + 778 formatter.format(falsePositiveLenient)); 779 jLabel.setAlignmentX(Component.LEFT_ALIGNMENT); 780 jLabel.setFont(jLabel.getFont().deriveFont(Font.BOLD)); 781 box.add(jLabel); 782 infoBox.add(box); 783 784 // Add a space 785 infoBox.add(Box.createRigidArea(new Dimension(10,0))); 786 787 this.add(infoBox); 788 } //arangeAllComponents 789 790 /** Used internally for debugging */ 791 protected void printStructure(Set aDiffSet){ 792 Iterator iterator = aDiffSet.iterator(); 793 String leftAnnot = null; 794 String rightAnnot = null; 795 while(iterator.hasNext()){ 796 DiffSetElement diffElem = (DiffSetElement) iterator.next(); 797 if (diffElem.getLeftAnnotation() == null) 798 leftAnnot = "NULL "; 799 else 800 leftAnnot = diffElem.getLeftAnnotation().toString(); 801 if (diffElem.getRightAnnotation() == null) 802 rightAnnot = " NULL"; 803 else 804 rightAnnot = diffElem.getRightAnnotation().toString(); 805 Out.prln( leftAnnot + "|" + rightAnnot); 806 } // end while 807 } // printStructure 808 809 /** This method is the brain of the AnnotationSet diff and creates a set with 810 * diffSetElement objects. 811 * @param aKeyAnnotList a list containing the annotations from key. If this 812 * param is <b>null</b> then the method will simply return and will not do a 813 * thing. 814 * @param aResponseAnnotList a list containing the annotation from response. 815 * If this param is <b>null</b> the method will return. 816 */ 817 protected void doDiff(java.util.List aKeyAnnotList, 818 java.util.List aResponseAnnotList){ 819 820 // If one of the annotation sets is null then is no point in doing the diff. 821 if (aKeyAnnotList == null || aResponseAnnotList == null) 822 return; 823 824 int responseSize = aResponseAnnotList.size(); 825 826 diffSet = new HashSet(); 827 // Iterate throught all elements from keyList and find those in the response 828 // list which satisfies isCompatible() and isPartiallyCompatible() relations 829 Iterator keyIterator = aKeyAnnotList.iterator(); 830 while(keyIterator.hasNext()){ 831 Annotation keyAnnot = (Annotation) keyIterator.next(); 832 Iterator responseIterator = aResponseAnnotList.iterator(); 833 834 DiffSetElement diffElement = null; 835 while(responseIterator.hasNext()){ 836 Annotation responseAnnot = (Annotation) responseIterator.next(); 837 838 if(keyAnnot.isPartiallyCompatible(responseAnnot,keyFeatureNamesSet)){ 839 keyPartiallySet.add(keyAnnot); 840 responsePartiallySet.add(responseAnnot); 841 if (keyAnnot.coextensive(responseAnnot)){ 842 // Found two compatible annotations 843 // Create a new DiffSetElement and add it to the diffSet 844 diffElement = new DiffSetElement( keyAnnot, 845 responseAnnot, 846 DEFAULT_TYPE, 847 CORRECT_TYPE); 848 849 // Add this element to the DiffSet 850 addToDiffset(diffElement); 851 } // End if (keyAnnot.coextensive(responseAnnot)) 852 }else if (keyAnnot.coextensive(responseAnnot)){ 853 // Found two aligned annotations. We have to find out if the response 854 // is partialy compatible with another key annotation. 855 // Create a new DiffSetElement and add it to the diffSet 856 diffElement = new DiffSetElement( keyAnnot, 857 responseAnnot, 858 detectKeyType(keyAnnot), 859 detectResponseType(responseAnnot)); 860 // Add this element to the DiffSet 861 addToDiffset(diffElement); 862 } // End if (keyAnnot.coextensive(responseAnnot)){ 863 864 if (diffElement != null){ 865 // Eliminate the response annotation from the list. 866 responseIterator.remove(); 867 break; 868 } // End if 869 } // end while responseIterator 870 871 // If diffElement != null it means that break was used 872 if (diffElement == null){ 873 if (keyPartiallySet.contains(keyAnnot)) 874 diffElement = new DiffSetElement( keyAnnot, 875 null, 876 DEFAULT_TYPE, 877 NULL_TYPE); 878 else{ 879 // If keyAnnot is not in keyPartiallySet then it has to be checked 880 // agains all annotations in DiffSet to see if there is 881 // a previous annotation from response set which is partially 882 // compatible with the keyAnnot 883 Iterator respParIter = diffSet.iterator(); 884 while (respParIter.hasNext()){ 885 DiffSetElement diffElem = (DiffSetElement) respParIter.next(); 886 Annotation respAnnot = diffElem.getRightAnnotation(); 887 if (respAnnot != null && keyAnnot.isPartiallyCompatible(respAnnot, 888 keyFeatureNamesSet)){ 889 diffElement = new DiffSetElement( keyAnnot, 890 null, 891 DEFAULT_TYPE, 892 NULL_TYPE); 893 break; 894 } // End if 895 } // End while 896 // If is still nul then it means that the key annotation is missing 897 if (diffElement == null) 898 diffElement = new DiffSetElement( keyAnnot, 899 null, 900 MISSING_TYPE, 901 NULL_TYPE); 902 } // End if 903 addToDiffset(diffElement); 904 } // End if 905 906 keyIterator.remove(); 907 } // end while keyIterator 908 909 DiffSetElement diffElem = null; 910 Iterator responseIter = aResponseAnnotList.iterator(); 911 while (responseIter.hasNext()){ 912 Annotation respAnnot = (Annotation) responseIter.next(); 913 if (responsePartiallySet.contains(respAnnot)) 914 diffElem = new DiffSetElement( null, 915 respAnnot, 916 NULL_TYPE, 917 PARTIALLY_CORRECT_TYPE); 918 else 919 diffElem = new DiffSetElement( null, 920 respAnnot, 921 NULL_TYPE, 922 SPURIOUS_TYPE); 923 addToDiffset(diffElem); 924 responseIter.remove(); 925 } // End while 926 927 // CALCULATE ALL (NLP) MEASURES like: 928 // Precistion, Recall, FalsePositive and F-Measure 929 int possible = typeCounter[CORRECT_TYPE] + // this comes from Key or Resp 930 typeCounter[PARTIALLY_CORRECT_TYPE] + // this comes from Resp 931 typeCounter[MISSING_TYPE]; // this comes from Key 932 933 int actual = typeCounter[CORRECT_TYPE] + // this comes from Key or Resp 934 typeCounter[PARTIALLY_CORRECT_TYPE] + // this comes from Resp 935 typeCounter[SPURIOUS_TYPE]; // this comes from Resp 936 937 if (actual != responseSize) 938 Err.prln("AnnotDiff warning: The response size(" + responseSize + 939 ") is not the same as the computed value of" + 940 " actual(Correct[resp or key]+Partial[resp]+Spurious[resp]=" + actual +")"); 941 942 if (actual != 0){ 943 precisionStrict = ((double)typeCounter[CORRECT_TYPE])/((double)actual); 944 precisionLenient = ((double)(typeCounter[CORRECT_TYPE] + 945 typeCounter[PARTIALLY_CORRECT_TYPE]))/((double)actual); 946 precisionAverage = ((double)(precisionStrict + precisionLenient)) / 947 ((double) 2); 948 } // End if 949 if (possible != 0){ 950 recallStrict = ((double)typeCounter[CORRECT_TYPE])/((double)possible); 951 recallLenient = ((double)(typeCounter[CORRECT_TYPE] + 952 typeCounter[PARTIALLY_CORRECT_TYPE]))/((double)possible); 953 recallAverage = ((double)(recallStrict + recallLenient)) / ((double)2); 954 } // End if 955 956 957 int no = 0; 958 // If an annotation type for false poz was selected calculate the number of 959 // Annotations 960 if (annotationTypeForFalsePositive != null) 961 // Was it the default set ? 962 if (responseAnnotationSetNameFalsePoz == null){ 963 AnnotationSet aSet = responseDocument.getAnnotations().get( 964 annotationTypeForFalsePositive); 965 no = aSet == null ? 0 : aSet.size(); 966 }else{ 967 AnnotationSet aSet = responseDocument.getAnnotations(responseAnnotationSetNameFalsePoz).get( 968 annotationTypeForFalsePositive); 969 no = aSet == null? 0 : aSet.size(); 970 } 971 if (no != 0){ 972 // No error here: the formula is the opposite to recall or precission 973 falsePositiveStrict = ((double)(typeCounter[SPURIOUS_TYPE] + 974 typeCounter[PARTIALLY_CORRECT_TYPE])) /((double)no); 975 falsePositiveLenient = ((double)typeCounter[SPURIOUS_TYPE]) /((double) no); 976 falsePositiveAverage = ((double)(falsePositiveStrict + 977 falsePositiveLenient))/((double)2) ; 978 } // End if 979 980 // Calculate F-Measure Strict 981 double denominator = weight * (precisionStrict + recallStrict); 982 if (denominator != 0) 983 fMeasureStrict = (precisionStrict * recallStrict) / denominator ; 984 else fMeasureStrict = 0.0; 985 // Calculate F-Measure Lenient 986 denominator = weight * (precisionLenient + recallLenient); 987 if (denominator != 0) 988 fMeasureLenient = (precisionLenient * recallLenient) / denominator ; 989 else fMeasureLenient = 0.0; 990 // Calculate F-Measure Average 991 fMeasureAverage = (fMeasureStrict + fMeasureLenient) / (double)2; 992 993 } // doDiff 994 995 /** Decide what type is the keyAnnotation (DEFAULT_TYPE, MISSING or NULL_TYPE) 996 * This method must be applied only on annotation from key set. 997 * @param anAnnot is an annotation from the key set. 998 * @return three possible value(DEFAULT_TYPE, MISSING or NULL_TYPE) 999 */ 1000 private int detectKeyType(Annotation anAnnot){ 1001 if (anAnnot == null) return NULL_TYPE; 1002 1003 if (keyPartiallySet.contains(anAnnot)) return DEFAULT_TYPE; 1004 Iterator iter = responsePartiallySet.iterator(); 1005 while(iter.hasNext()){ 1006 Annotation a = (Annotation) iter.next(); 1007 if (anAnnot.isPartiallyCompatible(a,keyFeatureNamesSet)) 1008 return DEFAULT_TYPE; 1009 } // End while 1010 1011 iter = responseAnnotList.iterator(); 1012 while(iter.hasNext()){ 1013 Annotation a = (Annotation) iter.next(); 1014 if (anAnnot.isPartiallyCompatible(a,keyFeatureNamesSet)){ 1015 responsePartiallySet.add(a); 1016 keyPartiallySet.add(anAnnot); 1017 return DEFAULT_TYPE; 1018 } // End if 1019 } // End while 1020 return MISSING_TYPE; 1021 } //detectKeyType 1022 1023 /** Decide what type is the responseAnnotation 1024 * (PARTIALLY_CORRECT_TYPE, SPURIOUS or NULL_TYPE) 1025 * This method must be applied only on annotation from response set. 1026 * @param anAnnot is an annotation from the key set. 1027 * @return three possible value(PARTIALLY_CORRECT_TYPE, SPURIOUS or NULL_TYPE) 1028 */ 1029 private int detectResponseType(Annotation anAnnot){ 1030 if (anAnnot == null) return NULL_TYPE; 1031 1032 if (responsePartiallySet.contains(anAnnot)) return PARTIALLY_CORRECT_TYPE; 1033 Iterator iter = keyPartiallySet.iterator(); 1034 while(iter.hasNext()){ 1035 Annotation a = (Annotation) iter.next(); 1036 if (a.isPartiallyCompatible(anAnnot,keyFeatureNamesSet)) 1037 return PARTIALLY_CORRECT_TYPE; 1038 } // End while 1039 1040 iter = keyAnnotList.iterator(); 1041 while(iter.hasNext()){ 1042 Annotation a = (Annotation) iter.next(); 1043 if (a.isPartiallyCompatible(anAnnot,keyFeatureNamesSet)){ 1044 responsePartiallySet.add(anAnnot); 1045 keyPartiallySet.add(a); 1046 return PARTIALLY_CORRECT_TYPE; 1047 } // End if 1048 } // End while 1049 return SPURIOUS_TYPE; 1050 } //detectResponseType 1051 1052 /** This method add an DiffsetElement to the DiffSet and also counts the 1053 * number of compatible, partialCompatible, Incorect and Missing annotations. 1054 */ 1055 private void addToDiffset(DiffSetElement aDiffSetElement){ 1056 if (aDiffSetElement == null) return; 1057 1058 diffSet.add(aDiffSetElement); 1059 // For the Right side (response) the type can be one of the following: 1060 // PC, I, C 1061 if (NULL_TYPE != aDiffSetElement.getRightType()) 1062 typeCounter[aDiffSetElement.getRightType()]++; 1063 // For the left side (key) the type can be : D or M 1064 if (NULL_TYPE != aDiffSetElement.getLeftType() && 1065 CORRECT_TYPE != aDiffSetElement.getLeftType()) 1066 typeCounter[aDiffSetElement.getLeftType()]++; 1067 } // addToDiffset 1068 1069 /* ******************************************************************** 1070 * INNER CLASS 1071 * ********************************************************************/ 1072 1073 /** 1074 * A custom table model used to render a table containing the two annotation 1075 * sets. The columns will be: 1076 * (KEY) Type, Start, End, Features, empty column,(Response) Type,Start, End, Features 1077 */ 1078 protected class AnnotationDiffTableModel extends AbstractTableModel{ 1079 1080 /** Constructs an AnnotationDiffTableModel given a data Collection */ 1081 public AnnotationDiffTableModel(Collection data){ 1082 modelData = new ArrayList(); 1083 modelData.addAll(data); 1084 } // AnnotationDiffTableModel 1085 1086 /** Constructs an AnnotationDiffTableModel */ 1087 public AnnotationDiffTableModel(){ 1088 modelData = new ArrayList(); 1089 } // AnnotationDiffTableModel 1090 1091 /** Return the size of data.*/ 1092 public int getRowCount(){ 1093 return modelData.size(); 1094 } //getRowCount 1095 1096 /** Return the number of columns.*/ 1097 public int getColumnCount(){ 1098 return 9; 1099 } //getColumnCount 1100 1101 /** Returns the name of each column in the model*/ 1102 public String getColumnName(int column){ 1103 switch(column){ 1104 case 0: return "String - Key"; 1105 case 1: return "Start - Key"; 1106 case 2: return "End - Key"; 1107 case 3: return "Features - Key"; 1108 case 4: return " "; 1109 case 5: return "String - Response"; 1110 case 6: return "Start - Response"; 1111 case 7: return "End -Response"; 1112 case 8: return "Features - Response"; 1113 default:return "?"; 1114 } 1115 } //getColumnName 1116 1117 /** Return the class type for each column. */ 1118 public Class getColumnClass(int column){ 1119 switch(column){ 1120 case 0: return String.class; 1121 case 1: return Long.class; 1122 case 2: return Long.class; 1123 case 3: return String.class; 1124 case 4: return String.class; 1125 case 5: return String.class; 1126 case 6: return Long.class; 1127 case 7: return Long.class; 1128 case 8: return String.class; 1129 default:return Object.class; 1130 } 1131 } //getColumnClass 1132 1133 /**Returns a value from the table model */ 1134 public Object getValueAt(int row, int column){ 1135 DiffSetElement diffSetElement = (DiffSetElement) modelData.get(row); 1136 if (diffSetElement == null) return null; 1137 switch(column){ 1138 // Left Side (Key) 1139 //Type - Key 1140 case 0:{ 1141 if (diffSetElement.getLeftAnnotation() == null) return null; 1142// return diffSetElement.getLeftAnnotation().getType(); 1143 Annotation annot = diffSetElement.getLeftAnnotation(); 1144 String theString = ""; 1145 try { 1146 theString = keyDocument.getContent().getContent( 1147 annot.getStartNode().getOffset(), 1148 annot.getEndNode().getOffset()).toString(); 1149 } catch (gate.util.InvalidOffsetException ex) { 1150 Err.prln(ex.getMessage()); 1151 } 1152 return theString; 1153 } 1154 // Start - Key 1155 case 1:{ 1156 if (diffSetElement.getLeftAnnotation() == null) return null; 1157 return diffSetElement.getLeftAnnotation().getStartNode().getOffset(); 1158 } 1159 // End - Key 1160 case 2:{ 1161 if (diffSetElement.getLeftAnnotation() == null) return null; 1162 return diffSetElement.getLeftAnnotation().getEndNode().getOffset(); 1163 } 1164 // Features - Key 1165 case 3:{ 1166 if (diffSetElement.getLeftAnnotation() == null) return null; 1167 if (diffSetElement.getLeftAnnotation().getFeatures() == null) 1168 return null; 1169 return diffSetElement.getLeftAnnotation().getFeatures().toString(); 1170 } 1171 // Empty column 1172 case 4:{ 1173 return " "; 1174 } 1175 // Right Side (Response) 1176 //Type - Response 1177 case 5:{ 1178 if (diffSetElement.getRightAnnotation() == null) return null; 1179// return diffSetElement.getRightAnnotation().getType(); 1180 Annotation annot = diffSetElement.getRightAnnotation(); 1181 String theString = ""; 1182 try { 1183 theString = responseDocument.getContent().getContent( 1184 annot.getStartNode().getOffset(), 1185 annot.getEndNode().getOffset()).toString(); 1186 } catch (gate.util.InvalidOffsetException ex) { 1187 Err.prln(ex.getMessage()); 1188 } 1189 return theString; 1190 } 1191 // Start - Response 1192 case 6:{ 1193 if (diffSetElement.getRightAnnotation() == null) return null; 1194 return diffSetElement.getRightAnnotation().getStartNode().getOffset(); 1195 } 1196 // End - Response 1197 case 7:{ 1198 if (diffSetElement.getRightAnnotation() == null) return null; 1199 return diffSetElement.getRightAnnotation().getEndNode().getOffset(); 1200 } 1201 // Features - resonse 1202 case 8:{ 1203 if (diffSetElement.getRightAnnotation() == null) return null; 1204 return diffSetElement.getRightAnnotation().getFeatures().toString(); 1205 } 1206 // The hidden column 1207 case 9:{ 1208 return diffSetElement; 1209 } 1210 default:{return null;} 1211 } // End switch 1212 } //getValueAt 1213 1214 public Object getRawObject(int row){ 1215 return modelData.get(row); 1216 } //getRawObject 1217 1218 /** Holds the data for TableDiff*/ 1219 private java.util.List modelData = null; 1220 1221 } //Inner class AnnotationDiffTableModel 1222 1223 /* ******************************************************************** 1224 * INNER CLASS 1225 * ********************************************************************/ 1226 /** 1227 * This class defines a Cell renderer for the AnnotationDiff table 1228 */ 1229 public class AnnotationDiffCellRenderer extends DefaultTableCellRenderer{ 1230 1231 /** Constructs a randerer with a table model*/ 1232 public AnnotationDiffCellRenderer() { } //AnnotationDiffCellRenderer 1233 1234 private Color background = WHITE; 1235 1236 private Color foreground = BLACK; 1237 1238 /** This method is called by JTable*/ 1239 1240 public Component getTableCellRendererComponent( 1241 JTable table, Object value, boolean isSelected, boolean hasFocus, 1242 int row, int column 1243 ) { 1244 JComponent defaultComp = null; 1245 defaultComp = (JComponent) super.getTableCellRendererComponent( 1246 table, value, isSelected, hasFocus, row, column 1247 ); 1248 1249 // The column number four will be randered using a blank component 1250 if (column == 4 || value == null) 1251 return new JPanel(); 1252 1253 if (!(table.getModel().getValueAt(row,9) instanceof DiffSetElement)) 1254 return defaultComp; 1255 1256 DiffSetElement diffSetElement = 1257 (DiffSetElement) table.getModel().getValueAt(row,9); 1258 1259 if (diffSetElement == null) 1260 return defaultComp; 1261 1262 if (column < 4){ 1263 if (NULL_TYPE != diffSetElement.getLeftType()) 1264 background = colors[diffSetElement.getLeftType()]; 1265 else return new JPanel(); 1266 }else{ 1267 if (NULL_TYPE != diffSetElement.getRightType()) 1268 background = colors[diffSetElement.getRightType()]; 1269 else return new JPanel(); 1270 } 1271 1272 defaultComp.setBackground(background); 1273 defaultComp.setForeground(BLACK); 1274 1275 defaultComp.setOpaque(true); 1276 return defaultComp; 1277 } //getTableCellRendererComponent 1278 1279 } // class AnnotationDiffCellRenderer 1280 1281 /* ******************************************************************** 1282 * INNER CLASS 1283 * ********************************************************************/ 1284 class AnnotationSetComparator implements java.util.Comparator { 1285 1286 public AnnotationSetComparator(){} 1287 1288 public int compare(Object o1, Object o2) { 1289 if ( !(o1 instanceof gate.Annotation) || 1290 !(o2 instanceof gate.Annotation)) return 0; 1291 1292 gate.Annotation a1 = (gate.Annotation) o1; 1293 gate.Annotation a2 = (gate.Annotation) o2; 1294 1295 Long l1 = a1.getStartNode().getOffset(); 1296 Long l2 = a2.getStartNode().getOffset(); 1297 if (l1 != null) 1298 return l1.compareTo(l2); 1299 else 1300 return -1; 1301 } //compare 1302 } // class AnnotationSetComparator 1303 1304 /* ******************************************************************** 1305 * INNER CLASS 1306 * ********************************************************************/ 1307 1308 /** 1309 * This class is used for internal purposes. It represents a row from the 1310 * table. 1311 */ 1312 protected class DiffSetElement { 1313 /** This field represent a key annotation*/ 1314 private Annotation leftAnnotation = null; 1315 /** This field represent a response annotation*/ 1316 private Annotation rightAnnotation = null; 1317 /** Default initialization of the key type*/ 1318 private int leftType = DEFAULT_TYPE; 1319 /** Default initialization of the response type*/ 1320 private int rightType = DEFAULT_TYPE; 1321 1322 /** Constructor for DiffSetlement*/ 1323 public DiffSetElement() {} 1324 1325 /** Constructor for DiffSetlement*/ 1326 public DiffSetElement( Annotation aLeftAnnotation, 1327 Annotation aRightAnnotation, 1328 int aLeftType, 1329 int aRightType){ 1330 leftAnnotation = aLeftAnnotation; 1331 rightAnnotation = aRightAnnotation; 1332 leftType = aLeftType; 1333 rightType = aRightType; 1334 } // DiffSetElement 1335 1336 /** Sets the left annotation*/ 1337 public void setLeftAnnotation(Annotation aLeftAnnotation){ 1338 leftAnnotation = aLeftAnnotation; 1339 } // setLeftAnnot 1340 1341 /** Gets the left annotation*/ 1342 public Annotation getLeftAnnotation(){ 1343 return leftAnnotation; 1344 } // getLeftAnnotation 1345 1346 /** Sets the right annotation*/ 1347 public void setRightAnnotation(Annotation aRightAnnotation){ 1348 rightAnnotation = aRightAnnotation; 1349 } // setRightAnnot 1350 1351 /** Gets the right annotation*/ 1352 public Annotation getRightAnnotation(){ 1353 return rightAnnotation; 1354 } // getRightAnnotation 1355 1356 /** Sets the left type*/ 1357 public void setLeftType(int aLeftType){ 1358 leftType = aLeftType; 1359 } // setLeftType 1360 1361 /** Get the left type */ 1362 public int getLeftType() { 1363 return leftType; 1364 } // getLeftType 1365 1366 /** Sets the right type*/ 1367 public void setRightType(int aRightType) { 1368 rightType = aRightType; 1369 } // setRightType 1370 1371 /** Get the right type*/ 1372 public int getRightType() { 1373 return rightType; 1374 } // getRightType 1375 } // classs DiffSetElement 1376} // class AnnotationDiff 1377
|
AnnotationDiff |
|