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 SpansExactComplexFeatureMatcher implements Matcher {
039            // public static final String FEATURE_NAMES =
040            // SpansExactComplexFeatureMatcher.class.getName()+".FEATURE_NAMES";
041    
042            String featureName;
043    
044            int spanComplexFeatureComparison;
045    
046            int classComplexFeatureComparison;
047    
048            int simpleFeatureComplexFeatureComparison;
049    
050            boolean allowTrivialSimpleFeatureMatches;
051    
052            /**
053             * This method will return an annotation that has the exact same spans and
054             * complex features. It is not required that the annotation class match.
055             * Preference will be given to an annotation that has the same class as well
056             * as spans and simple features. If one does not exist, then null is
057             * returned.
058             */
059            public Annotation match(Annotation annotation, String compareSetName, Set<Annotation> excludeAnnotations, IAA iaa,
060                            MatchResult matchResult) {
061                    return match(annotation, compareSetName, iaa, excludeAnnotations, matchResult);
062            }
063    
064            /**
065             * This method will return an annotation that has the exact same spans and
066             * simple features. It is not required that the annotation class match.
067             * Preference will be given to an annotation that has the same class as well
068             * as spans and simple features. If one does not exist, then null is
069             * returned.
070             * 
071             * @param annotation
072             * @param compareSetName
073             * @param iaa
074             * @param excludeAnnotations
075             * @param matchResult
076             *            will be set to:
077             *            <ul>
078             *            <li>TRIVIAL_NONMATCH if there are no exactly overlapping
079             *            annotations with the passed in annotation
080             *            <li>NONTRIVIAL_MATCH if there is an annotation that is exactly
081             *            overlapping and the Annotation.compareSimpleFeatures returns
082             *            NONTRIVIAL_MATCH
083             *            <li>TRIVIAL_MATCH if there is an annotation that is exactly
084             *            overlapping and the Annotation.compareSimpleFeatures returns
085             *            TRIVIAL_MATCH <br>
086             *            Note: if there is a trivial_match then there cannot possibly
087             *            be a NONTRIVIAL_MATCH because one of the simple features of
088             *            the passed in annotation must have a null value or there are
089             *            no simple features.
090             *            <li>NONTRIVIAL_NONMATCH if there an annotation that is exactly
091             *            overlapping and the Annotation.compareSimpleFeatures returns
092             *            NONTRIVIAL_NONMATCH
093             *            <li>TRIVIAL_NONMATCH if there is no match or non-trivial
094             *            non-match found.
095             * @return will return the first nontrivial match that it finds preferring
096             * @see edu.uchsc.ccp.iaa.matcher.Matcher#match(Annotation, String, Set,
097             *      IAA, MatchResult)
098             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_MATCH
099             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#NONTRIVIAL_NONMATCH
100             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#TRIVIAL_MATCH
101             * @see edu.uchsc.ccp.iaa.matcher.MatchResult#TRIVIAL_NONMATCH
102             */
103    
104            public static Annotation match(Annotation annotation, String compareSetName, IAA iaa,
105                            Set<Annotation> excludeAnnotations, MatchResult matchResult) {
106                    // prefer class and span matches over just span matches
107                    Set<Annotation> classAndSpanMatches = ClassAndSpanMatcher.matches(annotation, compareSetName, iaa,
108                                    excludeAnnotations, false); // no need to remove
109                    // excludeAnnotations because they
110                    // have already been removed by
111                    // ClassAndSpanMatcher
112                    Set<Annotation> exactlyOverlappingAnnotations = new HashSet<Annotation>(iaa.getExactlyOverlappingAnnotations(
113                                    annotation, compareSetName));
114                    exactlyOverlappingAnnotations.removeAll(classAndSpanMatches);
115                    exactlyOverlappingAnnotations.removeAll(excludeAnnotations);
116    
117                    List<Annotation> candidateAnnotations = new ArrayList<Annotation>(classAndSpanMatches.size()
118                                    + exactlyOverlappingAnnotations.size());
119                    candidateAnnotations.addAll(classAndSpanMatches);
120                    candidateAnnotations.addAll(exactlyOverlappingAnnotations);
121    
122                    boolean nontrivialNonmatch = false;
123    
124                    // for(Annotation candidateAnnotation : candidateAnnotations)
125                    // {
126                    // int result = Annotation.compareComplexFeature(annotation,
127                    // candidateAnnotation, );
128                    // if there is a trivial_match then there cannot possibly be a
129                    // NONTRIVIAL_MATCH
130                    // because one of the simple features of the passed in annotation must
131                    // have a null value
132                    // or there are no simple features.
133                    // if(result == MatchResult.NONTRIVIAL_MATCH ||
134                    // result == MatchResult.TRIVIAL_MATCH)
135                    // {
136                    // matchResult.setResult(result);
137                    // return candidateAnnotation;
138                    // }
139                    // if(result == MatchResult.NONTRIVIAL_NONMATCH)
140                    // {
141                    // nontrivialNonmatch = true;
142                    // }
143                    // }
144    
145                    if (nontrivialNonmatch)
146                            matchResult.setResult(MatchResult.NONTRIVIAL_NONMATCH);
147                    else
148                            matchResult.setResult(MatchResult.TRIVIAL_NONMATCH);
149                    return null;
150            }
151    
152            public String getName() {
153                    return "Simple slots matcher (with same spans)";
154            }
155    
156            public String getDescription() {
157                    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.";
158            }
159    
160            public boolean returnsTrivials() {
161                    return true;
162            }
163    
164    }