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.Collection; 031 import java.util.HashSet; 032 import java.util.Set; 033 034 import edu.uchsc.ccp.iaa.Annotation; 035 import edu.uchsc.ccp.iaa.IAA; 036 037 /** 038 * This matcher is very similar to ClassMatcher. 039 * 040 * @author Compaq_Owner 041 * 042 */ 043 044 public class SubclassMatcher implements Matcher { 045 046 String className; 047 048 Set<String> subclassNames; 049 050 ClassHierarchy hierarchy; 051 052 public SubclassMatcher(ClassHierarchy hierarchy) { 053 this.hierarchy = hierarchy; 054 } 055 056 /** 057 * This method will return a match from ClassMatcher. If one does not exist, 058 * then match for 059 * 060 * 061 * 062 * Otherwise, null is returned. 063 * 064 * @param annotation 065 * @param compareSetName 066 * @param excludeAnnotations 067 * @param iaa 068 * @param matchResult 069 * will be set to NONTRIVIAL_MATCH, NONTRIVIAL_NONMATCH, or 070 * TRIVIAL_NONMATCH. Trivial non-matches occur when the 071 * annotation is not of the class specified by setIAAClass or a 072 * subclass of it. Trivial non-matches should be ignored and not 073 * counted in any IAA metrics. 074 * @see edu.uchsc.ccp.iaa.matcher.Matcher#match(Annotation, String, Set, 075 * IAA, MatchResult) 076 * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_MATCH 077 * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_NONMATCH 078 * @see edu.uchsc.ccp.iaa.matcher.MatchResult#TRIVIAL_NONMATCH 079 * @see edu.uchsc.ccp.iaa.Annotation#getShortestAnnotation(Collection) 080 * @see #setIAAClass(String) 081 */ 082 public Annotation match(Annotation annotation, String compareSetName, Set<Annotation> excludeAnnotations, IAA iaa, 083 MatchResult matchResult) { 084 085 String annotationClassName = annotation.getAnnotationClass(); 086 if (!subclassNames.contains(annotationClassName)) { 087 matchResult.setResult(MatchResult.TRIVIAL_NONMATCH); 088 return null; 089 } 090 091 Annotation classMatch = ClassMatcher.match(annotation, compareSetName, iaa, excludeAnnotations); 092 if (classMatch != null) { 093 matchResult.setResult(MatchResult.NONTRIVIAL_MATCH); 094 return classMatch; 095 } 096 097 Set<Annotation> candidateAnnotations = new HashSet<Annotation>(); 098 for (String subclassName : subclassNames) { 099 candidateAnnotations.addAll(iaa.getAnnotationsOfClass(subclassName, compareSetName)); 100 } 101 102 Set<Annotation> exactlyOverlappingAnnotations = new HashSet<Annotation>(iaa.getExactlyOverlappingAnnotations( 103 annotation, compareSetName)); 104 exactlyOverlappingAnnotations.retainAll(candidateAnnotations); 105 exactlyOverlappingAnnotations.removeAll(excludeAnnotations); 106 if (exactlyOverlappingAnnotations.size() > 0) { 107 matchResult.setResult(MatchResult.NONTRIVIAL_MATCH); 108 return exactlyOverlappingAnnotations.iterator().next(); 109 } 110 111 Set<Annotation> overlappingAnnotations = new HashSet<Annotation>(iaa.getOverlappingAnnotations(annotation, 112 compareSetName)); 113 overlappingAnnotations.retainAll(candidateAnnotations); 114 overlappingAnnotations.removeAll(excludeAnnotations); 115 if (overlappingAnnotations.size() > 0) { 116 matchResult.setResult(MatchResult.NONTRIVIAL_MATCH); 117 if (overlappingAnnotations.size() == 1) 118 return overlappingAnnotations.iterator().next(); 119 return Annotation.getShortestAnnotation(overlappingAnnotations); 120 } 121 122 matchResult.setResult(MatchResult.NONTRIVIAL_NONMATCH); 123 return null; 124 } 125 126 /** 127 * Sets the class of the 128 * 129 * @param className 130 */ 131 public void setIAAClass(String className) { 132 this.className = className; 133 subclassNames = hierarchy.getSubclasses(className); 134 } 135 136 public String getIAAClass() { 137 return className; 138 } 139 140 public String getName() { 141 return "Subclass matcher for class '" + className + "'"; 142 } 143 144 public String getDescription() { 145 return "Two annotations match if their class assignments are equal to '" + className + "' or a subclass of '" 146 + className + "' and their spans overlap."; 147 } 148 149 public boolean returnsTrivials() { 150 return true; 151 } 152 153 public Set<String> getSubclasses() { 154 return hierarchy.getSubclasses(className); 155 } 156 }