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.Collections;
032    import java.util.HashSet;
033    import java.util.Set;
034    
035    import edu.uchsc.ccp.iaa.Annotation;
036    import edu.uchsc.ccp.iaa.IAA;
037    
038    public class ClassMatcher implements Matcher {
039            /**
040             * This method will return an annotation with the same class and spans. If
041             * one does not exist, then it will return an annotation with the same class
042             * and overlapping spans. If more than one of these exists, then the
043             * shortest annotation with the same class and overlapping spans will be
044             * returned. Otherwise, null is returned.
045             * 
046             * @param annotation
047             * @param compareSetName
048             * @param excludeAnnotations
049             * @param iaa
050             * @param matchResult
051             *            will be set to NONTRIVIAL_MATCH or NONTRIVIAL_NONMATCH.
052             *            Trivial matches and non-matches are not defined for this
053             *            matcher.
054             * @see edu.uchsc.ccp.iaa.matcher.Matcher#match(Annotation, String, Set,
055             *      IAA, MatchResult)
056             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_MATCH
057             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_NONMATCH
058             * @see edu.uchsc.ccp.iaa.Annotation#getShortestAnnotation(Collection)
059             */
060    
061            public Annotation match(Annotation annotation, String compareSetName, Set<Annotation> excludeAnnotations, IAA iaa,
062                            MatchResult matchResult) {
063                    Annotation match = match(annotation, compareSetName, iaa, excludeAnnotations);
064                    if (match != null) {
065                            matchResult.setResult(MatchResult.NONTRIVIAL_MATCH);
066                            return match;
067                    } else {
068                            matchResult.setResult(MatchResult.NONTRIVIAL_NONMATCH);
069                            return null;
070                    }
071            }
072    
073            public static Annotation match(Annotation annotation, String compareSetName, IAA iaa,
074                            Set<Annotation> excludeAnnotations) {
075                    Annotation spanAndClassMatch = ClassAndSpanMatcher.match(annotation, compareSetName, iaa, excludeAnnotations);
076                    if (spanAndClassMatch != null) {
077                            return spanAndClassMatch;
078                    }
079    
080                    Set<Annotation> matches = matches(annotation, compareSetName, iaa, excludeAnnotations);
081                    if (matches.size() > 0) {
082                            if (matches.size() == 1)
083                                    return matches.iterator().next();
084                            else {
085                                    Annotation shortestAnnotation = Annotation.getShortestAnnotation(matches);
086                                    return shortestAnnotation;
087                            }
088                    } else {
089                            return null;
090                    }
091            }
092    
093            public static Set<Annotation> matches(Annotation annotation, String compareSetName, IAA iaa,
094                            Set<Annotation> excludeAnnotations) {
095    
096                    Set<Annotation> overlappingAnnotations = iaa.getOverlappingAnnotations(annotation, compareSetName);
097                    Set<Annotation> annotationsOfSameType = iaa.getAnnotationsOfSameType(annotation, compareSetName);
098                    Set<Annotation> candidateAnnotations = new HashSet<Annotation>(overlappingAnnotations);
099                    candidateAnnotations.retainAll(annotationsOfSameType);
100                    candidateAnnotations.removeAll(excludeAnnotations);
101    
102                    if (candidateAnnotations.size() > 0) {
103                            return Collections.unmodifiableSet(candidateAnnotations);
104                    } else {
105                            return Collections.emptySet();
106                    }
107            }
108    
109            public String getName() {
110                    return "Class matcher";
111            }
112    
113            public String getDescription() {
114                    return "Annotations match if they have the same class assignment and their spans overlap.";
115            }
116    
117            public boolean returnsTrivials() {
118                    return false;
119            }
120    
121    }