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    
029    package edu.uchsc.ccp.iaa.matcher;
030    
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 ClassAndSpanMatcher implements Matcher {
039    
040            /**
041             * @param annotation
042             * @param compareSetName
043             * @param excludeAnnotations
044             * @param iaa
045             * @param matchResult
046             *            will be set to NONTRIVIAL_MATCH or NONTRIVIAL_NONMATCH.
047             *            Trivial matches and non-matches are not defined for this
048             *            matcher.
049             * @see edu.uchsc.ccp.iaa.matcher.Matcher#match(Annotation, String, Set,
050             *      IAA, MatchResult)
051             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_MATCH
052             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_NONMATCH
053             */
054            public Annotation match(Annotation annotation, String compareSetName, Set<Annotation> excludeAnnotations, IAA iaa,
055                            MatchResult matchResult) {
056                    Annotation match = match(annotation, compareSetName, iaa, excludeAnnotations);
057                    if (match != null) {
058                            matchResult.setResult(MatchResult.NONTRIVIAL_MATCH);
059                            return match;
060                    } else {
061                            matchResult.setResult(MatchResult.NONTRIVIAL_NONMATCH);
062                            return null;
063                    }
064            }
065    
066            /**
067             * This is a static version of the above match method that can be called by
068             * other matcher implementations.
069             * 
070             * @param annotation
071             * @param compareSetName
072             * @param iaa
073             * @param excludeAnnotations
074             * @return an annotation that matches or null.
075             */
076            public static Annotation match(Annotation annotation, String compareSetName, IAA iaa,
077                            Set<Annotation> excludeAnnotations) {
078                    Set<Annotation> singleMatchSet = matches(annotation, compareSetName, iaa, excludeAnnotations, true);
079                    if (singleMatchSet.size() == 1) {
080                            return singleMatchSet.iterator().next();
081                    } else
082                            return null;
083    
084            }
085    
086            /**
087             * 
088             * @param annotation
089             * @param compareSetName
090             * @param iaa
091             * @param excludeAnnotations
092             * @param returnFirst
093             *            if true then a set of size 1 will be returned as soon as a
094             *            match is found. If false then all matches will be returned.
095             * @return this method will not return null - but rather an empty set of no
096             *         matches are found.
097             */
098    
099            public static Set<Annotation> matches(Annotation annotation, String compareSetName, IAA iaa,
100                            Set<Annotation> excludeAnnotations, boolean returnFirst) {
101                    String type = annotation.getAnnotationClass();
102                    Set<Annotation> candidateAnnotations = new HashSet<Annotation>(iaa.getExactlyOverlappingAnnotations(annotation,
103                                    compareSetName));
104                    candidateAnnotations.removeAll(excludeAnnotations);
105                    if (candidateAnnotations.size() == 0)
106                            return Collections.emptySet();
107    
108                    Set<Annotation> returnValues = new HashSet<Annotation>();
109                    for (Annotation candidateAnnotation : candidateAnnotations) {
110                            if (!excludeAnnotations.contains(candidateAnnotation)
111                                            && candidateAnnotation.getAnnotationClass().equals(type)) {
112                                    returnValues.add(candidateAnnotation);
113                                    if (returnFirst)
114                                            return returnValues;
115                            }
116                    }
117                    return returnValues;
118            }
119    
120            public String getName() {
121                    return "Class and span matcher";
122            }
123    
124            public String getDescription() {
125    
126                    return "Annotations match if they have the same class assignment and the same spans.";
127            }
128    
129            public boolean returnsTrivials() {
130                    return false;
131            }
132    
133    }