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    /**
030     * 8/15/2005  The type filtering was using the old Knowtator model.  Changed the code
031     *            so that the type and supertypes of the mention of the annotation are 
032     *            verified.  
033     */
034    package edu.uchsc.ccp.knowtator;
035    
036    import java.util.ArrayList;
037    import java.util.Collection;
038    import java.util.Collections;
039    import java.util.HashSet;
040    import java.util.Iterator;
041    import java.util.List;
042    import java.util.Set;
043    
044    import org.apache.log4j.Logger;
045    
046    import edu.stanford.smi.protege.model.Cls;
047    import edu.stanford.smi.protege.model.Frame;
048    import edu.stanford.smi.protege.model.Instance;
049    import edu.stanford.smi.protege.model.KnowledgeBase;
050    import edu.stanford.smi.protege.model.SimpleInstance;
051    import edu.uchsc.ccp.knowtator.util.ConsensusException;
052    
053    public class FilterUtil {
054            public static final int ANY_FILTER = 0;
055    
056            public static final int CONSENSUS_FILTER = 1;
057    
058            public static final int NONCONSENSUS_FILTER = 2;
059    
060            KnowtatorManager manager;
061    
062            KnowtatorProjectUtil kpu;
063    
064            AnnotationUtil annotationUtil;
065    
066            MentionUtil mentionUtil;
067    
068            Logger logger = Logger.getLogger(FilterUtil.class);
069    
070            /** Creates a new instance of FilterUtil */
071            public FilterUtil(KnowtatorManager manager) {
072                    this.manager = manager;
073                    this.kpu = manager.getKnowtatorProjectUtil();
074                    this.annotationUtil = manager.getAnnotationUtil();
075                    this.mentionUtil = manager.getMentionUtil();
076            }
077    
078            public Collection<SimpleInstance> filterAnnotations(Collection<SimpleInstance> annotationInstances,
079                            SimpleInstance filterInstance) {
080                    return filterAnnotations(annotationInstances, filterInstance, false);
081            }
082    
083            public boolean isClsLicensedByFilter(SimpleInstance filter, Frame frame) {
084                    Cls cls = null;
085                    if (frame instanceof Cls)
086                            cls = (Cls) frame;
087                    else
088                            cls = ((Instance) frame).getDirectType();
089    
090                    Collection goodTypes = filter.getOwnSlotValues(kpu.filterTypeSlot);
091                    if (goodTypes == null || goodTypes.size() == 0)
092                            return true;
093                    else {
094                            Collection superTypes = cls.getSuperclasses();
095                            ArrayList types = new ArrayList(superTypes);
096                            types.add(cls);
097                            for (Iterator iterator = types.iterator(); iterator.hasNext();) {
098                                    if (goodTypes.contains(iterator.next())) {
099                                            return true;
100                                    }
101                            }
102                    }
103                    return false;
104            }
105    
106            /**
107             * @param textViewerSelectable
108             *            - true if you want to filter out annotations of the types
109             *            specified in the
110             *            knowtator_types_not_selectable_from_text_viewer slot of the
111             *            filter.
112             */
113            public List<SimpleInstance> filterAnnotations(Collection<SimpleInstance> annotationInstances,
114                            SimpleInstance filterInstance, boolean ignoreTypeFilter, boolean textViewerSelectable) {
115                    logger.debug("");
116                    Collection badTypes = filterInstance.getOwnSlotValues(kpu.getFilterTypesNotSelectableFromTextViewerSlot());
117                    // logger.debug("badTypes.size()="+badTypes.size());
118                    List<SimpleInstance> annotations = filterAnnotations(annotationInstances, filterInstance, ignoreTypeFilter);
119                    // logger.debug("annotations.size()="+annotations.size());
120                    List<SimpleInstance> returnValues = new ArrayList<SimpleInstance>();
121    
122                    if (badTypes.size() > 0 && textViewerSelectable) {
123                            for (SimpleInstance annotation : annotations) {
124                                    boolean goodType = true;
125                                    SimpleInstance mention = annotationUtil.getMention(annotation);
126                                    Cls mentionCls = mentionUtil.getMentionCls(mention);
127                                    if (mentionCls != null) {
128                                            Collection superTypes = mentionCls.getSuperclasses();
129                                            ArrayList types = new ArrayList(superTypes);
130                                            types.add(mentionCls);
131                                            // logger.debug("annotation types");
132                                            // for (Object object : types) {
133                                            // logger.debug(object);
134                                            // }
135                                            for (Iterator iterator = types.iterator(); iterator.hasNext();) {
136                                                    if (badTypes.contains(iterator.next())) {
137                                                            // logger.debug(
138                                                            // "badTypes.contains superclass of annotation");
139                                                            // logger.debug("mentionCls="+mentionCls);
140                                                            goodType = false;
141                                                            break;
142                                                    }
143                                            }
144                                            if (goodType)
145                                                    returnValues.add(annotation);
146                                    }
147                            }
148                            logger.debug("returning returnValues: " + returnValues.size());
149                            return returnValues;
150                    } else
151                            return annotations;
152            }
153    
154            /**
155             * 
156             * @param annotationInstances
157             * @param filterInstance
158             * @param ignoreTypeFilter
159             *            - will ignore the type of the annotation when filtering if
160             *            true. If true, then the value of textviewerSelectable is
161             *            ignored.
162             */
163            public List<SimpleInstance> filterAnnotations(Collection<SimpleInstance> annotationInstances,
164                            SimpleInstance filterInstance, boolean ignoreTypeFilter) {
165                    Collection goodAnnotators = filterInstance.getOwnSlotValues(kpu.filterAnnotatorSlot);
166                    Collection goodAnnotationSets = filterInstance.getOwnSlotValues(kpu.filterSetSlot);
167                    Collection goodTypes = filterInstance.getOwnSlotValues(kpu.filterTypeSlot);
168    
169                    ArrayList<SimpleInstance> goodAnnotations = new ArrayList<SimpleInstance>();
170    
171                    if (annotationInstances != null) {
172                            for (SimpleInstance annotation : annotationInstances) {
173                                    boolean goodAnnotator = goodAnnotators.size() > 0 ? false : true;
174                                    boolean goodAnnotationSet = goodAnnotationSets.size() > 0 ? false : true;
175                                    boolean goodType = (goodTypes.size() > 0 && !ignoreTypeFilter) ? false : true;
176    
177                                    if (goodAnnotator && goodAnnotationSet && goodType) {
178                                            goodAnnotations.add(annotation);
179                                            continue;
180                                    }
181    
182                                    /**
183                                     * might be better to iterate through members rather than
184                                     * calling retainAll for performance reasons (can continue as
185                                     * soon as you find a match using contains)
186                                     */
187                                    if (!goodType) {
188                                            SimpleInstance mention = annotationUtil.getMention(annotation);
189                                            Cls mentionCls = mentionUtil.getMentionCls(mention);
190                                            if (mentionCls != null) {
191                                                    Collection superTypes = mentionCls.getSuperclasses();
192                                                    ArrayList types = new ArrayList(superTypes);
193                                                    types.add(mentionCls);
194                                                    for (Iterator iterator = types.iterator(); iterator.hasNext();) {
195                                                            if (goodTypes.contains(iterator.next())) {
196                                                                    goodType = true;
197                                                                    break;
198                                                            }
199                                                    }
200                                            }
201                                    }
202                                    if (!goodAnnotator) {
203                                            Collection annotators = annotation.getOwnSlotValues(kpu.getAnnotationAnnotatorSlot());
204                                            for (Iterator iterator = annotators.iterator(); iterator.hasNext();) {
205                                                    if (goodAnnotators.contains(iterator.next())) {
206                                                            goodAnnotator = true;
207                                                            break;
208                                                    }
209                                            }
210                                    }
211    
212                                    if (!goodAnnotationSet) {
213                                            Collection annotationSets = annotation.getOwnSlotValues(kpu.getSetSlot());
214                                            for (Iterator iterator = annotationSets.iterator(); iterator.hasNext();) {
215                                                    if (goodAnnotationSets.contains(iterator.next())) {
216                                                            goodAnnotationSet = true;
217                                                            break;
218                                                    }
219                                            }
220                                    }
221    
222                                    if (goodAnnotator && goodAnnotationSet && goodType) {
223                                            goodAnnotations.add(annotation);
224                                            continue;
225                                    }
226                            }
227                    }
228    
229                    return goodAnnotations;
230            }
231    
232            /**
233             * Returns the types specified by the filter. This method will not return
234             * null - but rather an empty set if no type has been specified by the
235             * filter.
236             */
237            public static Set<Cls> getTypes(SimpleInstance filter) {
238                    KnowledgeBase kb = filter.getKnowledgeBase();
239                    Collection<Cls> filterTypes = (Collection<Cls>) filter.getOwnSlotValues(kb
240                                    .getSlot(KnowtatorProjectUtil.FILTER_TYPE_SLOT_NAME));
241                    Set<Cls> types = new HashSet<Cls>();
242                    if (filterTypes != null) {
243                            types.addAll(filterTypes);
244                    }
245                    return types;
246            }
247    
248            /**
249             * Returns the annotators specified by the filter. This method will not
250             * return null - but rather an empty set if no annotator has been specified
251             * by the filter.
252             */
253            public static List<SimpleInstance> getAnnotators(SimpleInstance filter) {
254                    KnowledgeBase kb = filter.getKnowledgeBase();
255                    Collection<SimpleInstance> filterAnnotators = (Collection<SimpleInstance>) filter.getOwnSlotValues(kb
256                                    .getSlot(KnowtatorProjectUtil.FILTER_ANNOTATOR_SLOT_NAME));
257                    List<SimpleInstance> annotators = new ArrayList<SimpleInstance>();
258                    if (filterAnnotators != null) {
259                            annotators.addAll(filterAnnotators);
260                    }
261                    return annotators;
262            }
263    
264            public static Set<SimpleInstance> getSets(SimpleInstance filter) {
265                    KnowledgeBase kb = filter.getKnowledgeBase();
266                    Collection<SimpleInstance> filterSets = (Collection<SimpleInstance>) filter.getOwnSlotValues(kb
267                                    .getSlot(KnowtatorProjectUtil.FILTER_SET_SLOT_NAME));
268                    Set<SimpleInstance> sets = new HashSet<SimpleInstance>();
269                    if (filterSets != null) {
270                            sets.addAll(filterSets);
271                    }
272                    return sets;
273            }
274    
275            public static boolean isConsensusFilter(SimpleInstance filter) {
276                    if (filter == null)
277                            return false;
278                    KnowledgeBase kb = filter.getKnowledgeBase();
279                    Cls type = filter.getDirectType();
280                    if (type.equals(kb.getCls(KnowtatorProjectUtil.CONSENSUS_FILTER_CLS_NAME)))
281                            return true;
282                    return false;
283            }
284    
285            public SimpleInstance getPreviousFilter(int filterType) {
286                    int currentFilterIndex = getCurrentFilterIndex();
287                    List<SimpleInstance> activeFilters = new ArrayList<SimpleInstance>(manager.getActiveFilters());
288                    Collections.rotate(activeFilters, activeFilters.size() - currentFilterIndex); // put
289                                                                                                                                                                              // current
290                                                                                                                                                                              // filter
291                                                                                                                                                                              // at
292                                                                                                                                                                              // begin
293                                                                                                                                                                              // of
294                                                                                                                                                                              // list
295                    for (int i = activeFilters.size() - 1; i >= 0; i--) {
296                            SimpleInstance filter = activeFilters.get(i);
297                            if (filterType == ANY_FILTER)
298                                    return filter;
299                            if (filterType == CONSENSUS_FILTER) {
300                                    if (isConsensusFilter(filter))
301                                            return filter;
302                            }
303                            if (filterType == NONCONSENSUS_FILTER) {
304                                    if (!isConsensusFilter(filter))
305                                            return filter;
306                            }
307                    }
308                    return null;
309            }
310    
311            public int getCurrentFilterIndex() {
312                    SimpleInstance currentFilter = manager.getSelectedFilter();
313                    List<SimpleInstance> filterInstances = manager.getActiveFilters();
314                    if (currentFilter == null && filterInstances.size() > 0) {
315                            return 0;
316                    }
317                    for (int i = 0; i < filterInstances.size(); i++) {
318                            if (currentFilter.equals(filterInstances.get(i))) {
319                                    if (i < filterInstances.size() - 1)
320                                            return i;
321                                    else
322                                            return 0;
323                            }
324                    }
325                    return -1;
326            }
327    
328            /**
329             * 
330             * @param filterType
331             *            one of ANY_FILTER, CONSENSUS_FILTER, or NONCONSENSUS_FILTER
332             * @return the next filter of the provided type
333             */
334            public SimpleInstance getNextFilter(int filterType) {
335                    int currentFilterIndex = getCurrentFilterIndex();
336                    List<SimpleInstance> activeFilters = new ArrayList<SimpleInstance>(manager.getActiveFilters());
337                    Collections.rotate(activeFilters, activeFilters.size() - currentFilterIndex - 1);// put
338                                                                                                                                                                                     // current
339                                                                                                                                                                                     // filter
340                                                                                                                                                                                     // at
341                                                                                                                                                                                     // end
342                                                                                                                                                                                     // of
343                                                                                                                                                                                     // list
344                    for (int i = 0; i < activeFilters.size(); i++) {
345                            SimpleInstance filter = activeFilters.get(i);
346                            if (filterType == ANY_FILTER)
347                                    return filter;
348                            if (filterType == CONSENSUS_FILTER) {
349                                    if (isConsensusFilter(filter))
350                                            return filter;
351                            }
352                            if (filterType == NONCONSENSUS_FILTER) {
353                                    if (!isConsensusFilter(filter))
354                                            return filter;
355                            }
356                    }
357                    return null;
358            }
359    
360            public void selectNextFilter(int filterType) throws ConsensusException {
361                    logger.debug("");
362                    manager.setSelectedFilter(getNextFilter(filterType));
363            }
364    
365            public void selectPreviousFilter(int filterType) throws ConsensusException {
366                    logger.debug("");
367                    manager.setSelectedFilter(getNextFilter(filterType));
368            }
369    
370    }