001 /* 002 * The contents of this file are subject to the Mozilla Public 003 * License Version 1.1 (the "License"); you may not use this file 004 * except in compliance with the License. You may obtain a copy of 005 * the License at http://www.mozilla.org/MPL/ 006 * 007 * Software distributed under the License is distributed on an "AS 008 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 009 * implied. See the License for the specific language governing 010 * rights and limitations under the License. 011 * 012 * The Original Code is Knowtator. 013 * 014 * The Initial Developer of the Original Code is University of Colorado. 015 * Copyright (C) 2005 - 2008. All Rights Reserved. 016 * 017 * Knowtator was developed by the Center for Computational Pharmacology 018 * (http://compbio.uchcs.edu) at the University of Colorado Health 019 * Sciences Center School of Medicine with support from the National 020 * Library of Medicine. 021 * 022 * Current information about Knowtator can be obtained at 023 * http://knowtator.sourceforge.net/ 024 * 025 * Contributor(s): 026 * Philip V. Ogren <philip@ogren.info> (Original Author) 027 */ 028 package edu.uchsc.ccp.iaa.matcher; 029 030 import java.util.ArrayList; 031 import java.util.HashSet; 032 import java.util.List; 033 import java.util.Set; 034 035 import edu.uchsc.ccp.iaa.Annotation; 036 import edu.uchsc.ccp.iaa.IAA; 037 038 public class SpansExactSimpleFeatureMatcher implements Matcher { 039 // public static final String FEATURE_NAMES = 040 // SpansExactSimpleFeatureMatcher.class.getName()+".FEATURE_NAMES"; 041 042 /** 043 * This method will return an annotation that has the exact same spans and 044 * simple features. It is not required that the annotation class match. 045 * Preference will be given to an annotation that has the same class as well 046 * as spans and simple features. If one does not exist, then null is 047 * returned. 048 */ 049 public Annotation match(Annotation annotation, String compareSetName, Set<Annotation> excludeAnnotations, IAA iaa, 050 MatchResult matchResult) { 051 return match(annotation, compareSetName, iaa, excludeAnnotations, matchResult); 052 } 053 054 /** 055 * This method will return an annotation that has the exact same spans and 056 * simple features. It is not required that the annotation class match. 057 * Preference will be given to an annotation that has the same class as well 058 * as spans and simple features. If one does not exist, then null is 059 * returned. 060 * 061 * @param annotation 062 * @param compareSetName 063 * @param iaa 064 * @param excludeAnnotations 065 * @param matchResult 066 * will be set to: 067 * <ul> 068 * <li>TRIVIAL_NONMATCH if there are no exactly overlapping 069 * annotations with the passed in annotation 070 * <li>NONTRIVIAL_MATCH if there is an annotation that is exactly 071 * overlapping and the Annotation.compareSimpleFeatures returns 072 * NONTRIVIAL_MATCH 073 * <li>TRIVIAL_MATCH if there is an annotation that is exactly 074 * overlapping and the Annotation.compareSimpleFeatures returns 075 * TRIVIAL_MATCH <br> 076 * Note: if there is a trivial_match then there cannot possibly 077 * be a NONTRIVIAL_MATCH because one of the simple features of 078 * the passed in annotation must have a null value or there are 079 * no simple features. 080 * <li>NONTRIVIAL_NONMATCH if there an annotation that is exactly 081 * overlapping and the Annotation.compareSimpleFeatures returns 082 * NONTRIVIAL_NONMATCH 083 * <li>TRIVIAL_NONMATCH if there is no match or non-trivial 084 * non-match found. 085 * @return will return the first nontrivial match that it finds preferring 086 * @see edu.uchsc.ccp.iaa.matcher.Matcher#match(Annotation, String, Set, 087 * IAA, MatchResult) 088 * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_MATCH 089 * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_NONMATCH 090 * @see edu.uchsc.ccp.iaa.matcher.MatchResult#TRIVIAL_MATCH 091 * @see edu.uchsc.ccp.iaa.matcher.MatchResult#TRIVIAL_NONMATCH 092 */ 093 094 public static Annotation match(Annotation annotation, String compareSetName, IAA iaa, 095 Set<Annotation> excludeAnnotations, MatchResult matchResult) { 096 // prefer class and span matches over just span matches 097 Set<Annotation> classAndSpanMatches = ClassAndSpanMatcher.matches(annotation, compareSetName, iaa, 098 excludeAnnotations, false); 099 Set<Annotation> exactlyOverlappingAnnotations = new HashSet<Annotation>(iaa.getExactlyOverlappingAnnotations( 100 annotation, compareSetName)); 101 exactlyOverlappingAnnotations.removeAll(classAndSpanMatches); 102 exactlyOverlappingAnnotations.removeAll(excludeAnnotations); 103 104 List<Annotation> candidateAnnotations = new ArrayList<Annotation>(classAndSpanMatches.size() 105 + exactlyOverlappingAnnotations.size()); 106 for (Annotation candidateAnnotation : classAndSpanMatches) { 107 candidateAnnotations.add(candidateAnnotation); 108 } 109 for (Annotation candidateAnnotation : exactlyOverlappingAnnotations) { 110 candidateAnnotations.add(candidateAnnotation); 111 } 112 113 boolean nontrivialNonmatch = false; 114 115 for (Annotation candidateAnnotation : candidateAnnotations) { 116 if (!excludeAnnotations.contains(candidateAnnotation)) { 117 int result = Annotation.compareSimpleFeatures(annotation, candidateAnnotation); 118 // if there is a trivial_match then there cannot possibly be a 119 // NONTRIVIAL_MATCH 120 // because one of the simple features of the passed in 121 // annotation must have a null value 122 // or there are no simple features. 123 if (result == MatchResult.NONTRIVIAL_MATCH || result == MatchResult.TRIVIAL_MATCH) { 124 matchResult.setResult(result); 125 return candidateAnnotation; 126 } 127 if (result == MatchResult.NONTRIVIAL_NONMATCH) { 128 nontrivialNonmatch = true; 129 } 130 } 131 } 132 133 if (nontrivialNonmatch) 134 matchResult.setResult(MatchResult.NONTRIVIAL_NONMATCH); 135 else 136 matchResult.setResult(MatchResult.TRIVIAL_NONMATCH); 137 return null; 138 } 139 140 public String getName() { 141 return "Simple slots matcher (with same spans)"; 142 } 143 144 public String getDescription() { 145 return "Annotations match if they have the same spans and the same value for simple slots (e.g. slots that are primitive values such as integer and String). Only slots that are specified must match."; 146 } 147 148 public boolean returnsTrivials() { 149 return true; 150 } 151 152 }