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