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.knowtator.stats;
029    
030    import java.io.File;
031    import java.io.IOException;
032    import java.io.PrintStream;
033    import java.text.NumberFormat;
034    import java.util.ArrayList;
035    import java.util.Collection;
036    import java.util.HashMap;
037    import java.util.HashSet;
038    import java.util.Iterator;
039    import java.util.List;
040    import java.util.Map;
041    import java.util.Set;
042    
043    import edu.stanford.smi.protege.model.Cls;
044    import edu.stanford.smi.protege.model.Project;
045    import edu.stanford.smi.protege.model.SimpleInstance;
046    import edu.stanford.smi.protege.model.Slot;
047    import edu.uchsc.ccp.iaa.Annotation;
048    import edu.uchsc.ccp.iaa.IAA;
049    import edu.uchsc.ccp.iaa.IAAException;
050    import edu.uchsc.ccp.iaa.html.IAA2HTML;
051    import edu.uchsc.ccp.iaa.html.SpanMatcherHTML;
052    import edu.uchsc.ccp.iaa.html.SubclassMatcherHTML;
053    import edu.uchsc.ccp.iaa.matcher.ClassAndSpanMatcher;
054    import edu.uchsc.ccp.iaa.matcher.ClassHierarchy;
055    import edu.uchsc.ccp.iaa.matcher.ClassHierarchyImpl;
056    import edu.uchsc.ccp.iaa.matcher.ClassMatcher;
057    import edu.uchsc.ccp.iaa.matcher.ComplexFeatureMatchCriteria;
058    import edu.uchsc.ccp.iaa.matcher.FeatureMatcher;
059    import edu.uchsc.ccp.iaa.matcher.SpanMatcher;
060    import edu.uchsc.ccp.iaa.matcher.SubclassMatcher;
061    import edu.uchsc.ccp.knowtator.AnnotationUtil;
062    import edu.uchsc.ccp.knowtator.FilterUtil;
063    import edu.uchsc.ccp.knowtator.KnowtatorManager;
064    import edu.uchsc.ccp.knowtator.KnowtatorProjectUtil;
065    import edu.uchsc.ccp.knowtator.MentionUtil;
066    import edu.uchsc.ccp.knowtator.Span;
067    import edu.uchsc.ccp.knowtator.textsource.TextSource;
068    import edu.uchsc.ccp.knowtator.textsource.TextSourceAccessException;
069    import edu.uchsc.ccp.knowtator.textsource.TextSourceCollection;
070    
071    public class KnowtatorIAA {
072            File outputDirectory;
073    
074            SimpleInstance filter;
075    
076            Collection<SimpleInstance> textSources;
077    
078            Collection<Slot> simpleFeatureSlots;
079    
080            Collection<Slot> complexFeatureSlots;
081    
082            Project project;
083    
084            KnowtatorManager manager;
085    
086            KnowtatorProjectUtil kpu;
087    
088            TextSourceCollection tsc;
089    
090            AnnotationUtil annotationUtil;
091    
092            MentionUtil mentionUtil;
093    
094            FilterUtil filterUtil;
095    
096            Map<Annotation, String> annotationTexts;
097    
098            Map<Annotation, String> annotationTextNames;
099    
100            Map<String, Set<Annotation>> textSourceAnnotationsMap;
101    
102            PrintStream html;
103    
104            boolean setNameDeterminedByAnnotators;
105    
106            Set<String> setNames;
107    
108            public KnowtatorIAA(File outputDirectory, SimpleInstance filter, Collection<SimpleInstance> textSources,
109                            Project project, Collection<Slot> simpleFeatureSlots, Collection<Slot> complexFeatureSlots,
110                            KnowtatorManager manager, TextSourceCollection tsc, AnnotationUtil annotationUtil, MentionUtil mentionUtil,
111                            FilterUtil filterUtil) throws IAAException
112    
113            {
114                    this.outputDirectory = outputDirectory;
115                    this.filter = filter;
116                    this.textSources = textSources;
117                    if (simpleFeatureSlots != null)
118                            this.simpleFeatureSlots = simpleFeatureSlots;
119                    else
120                            this.simpleFeatureSlots = new HashSet<Slot>();
121                    if (complexFeatureSlots != null)
122                            this.complexFeatureSlots = complexFeatureSlots;
123                    else
124                            this.complexFeatureSlots = new HashSet<Slot>();
125    
126                    this.project = project;
127                    this.manager = manager;
128                    this.tsc = tsc;
129                    this.annotationUtil = annotationUtil;
130                    this.mentionUtil = mentionUtil;
131                    this.filterUtil = filterUtil;
132    
133                    kpu = manager.getKnowtatorProjectUtil();
134                    annotationTexts = new HashMap<Annotation, String>();
135                    annotationTextNames = new HashMap<Annotation, String>();
136    
137                    setNameDeterminedByAnnotators = FilterUtil.getAnnotators(filter).size() > 1 ? true : false;
138                    initSetNames();
139                    initTextSourceAnnotations();
140                    initHTML();
141            }
142    
143            private void initHTML() throws IAAException {
144                    try {
145                            html = new PrintStream(new File(outputDirectory, "index.html"));
146                            html.println("<html><head><title>Inter-Annotator Agreement</title></head>");
147                            html.println("<body><ul>");
148                    } catch (IOException ioe) {
149                            throw new IAAException(ioe);
150                    }
151            }
152    
153            public void closeHTML() {
154                    html.println("</ul>");
155                    html.println("</body></html>");
156                    html.flush();
157                    html.close();
158            }
159    
160            private void initTextSourceAnnotations() throws IAAException {
161                    textSourceAnnotationsMap = new HashMap<String, Set<Annotation>>();
162                    for (SimpleInstance textSourceInstance : textSources) {
163                            Collection<SimpleInstance> tsAnnotations = annotationUtil.getAnnotations(textSourceInstance);
164                            tsAnnotations = filterUtil.filterAnnotations(tsAnnotations, filter);
165                            Set<Annotation> annotations = convertAnnotations(tsAnnotations);
166                            textSourceAnnotationsMap.put(textSourceInstance.getName(), annotations);
167                    }
168            }
169    
170            private void initSetNames() {
171                    setNames = new HashSet<String>();
172                    Set<SimpleInstance> setNameInstances;
173                    if (setNameDeterminedByAnnotators)
174                            setNameInstances = new HashSet<SimpleInstance>(FilterUtil.getAnnotators(filter));
175                    else
176                            setNameInstances = FilterUtil.getSets(filter);
177    
178                    for (SimpleInstance setNameInstance : setNameInstances) {
179                            setNames.add(setNameInstance.getBrowserText());
180                    }
181            }
182    
183            private String getAnnotationSetName(SimpleInstance knowtatorAnnotation) {
184                    if (setNameDeterminedByAnnotators) {
185                            String annotatorName = annotationUtil.getAnnotator(knowtatorAnnotation).getBrowserText();
186                            return annotatorName;
187                    } else {
188                            Set<SimpleInstance> sets = annotationUtil.getSets(knowtatorAnnotation);
189                            for (SimpleInstance set : sets) {
190                                    String setName = set.getBrowserText();
191                                    if (setNames.contains(setName))
192                                            return setName;
193                            }
194                    }
195                    return null;
196            }
197    
198            public Map<Annotation, String> getAnnotationTexts() {
199                    return annotationTexts;
200            }
201    
202            public Annotation convertAnnotation(SimpleInstance knowtatorAnnotation, boolean convertComplexFeatures)
203                            throws IAAException {
204                    try {
205                            Annotation annotation = new Annotation();
206    
207                            SimpleInstance textSourceInstance = annotationUtil.getTextSource(knowtatorAnnotation);
208                            TextSource textSource = tsc.get(textSourceInstance.getName());
209    
210                            annotationTexts.put(annotation, textSource.getText());
211                            annotationTextNames.put(annotation, textSource.getName());
212                            annotation.setDocID(textSource.getName());
213    
214                            List<Span> knowtatorSpans = annotationUtil.getSpans(knowtatorAnnotation);
215                            List<edu.uchsc.ccp.iaa.Span> iaaSpans = new ArrayList<edu.uchsc.ccp.iaa.Span>(knowtatorSpans.size());
216                            for (Span knowtatorSpan : knowtatorSpans) {
217                                    edu.uchsc.ccp.iaa.Span iaaSpan = new edu.uchsc.ccp.iaa.Span(knowtatorSpan.getStart(), knowtatorSpan
218                                                    .getEnd());
219                                    iaaSpans.add(iaaSpan);
220                            }
221                            annotation.setSpans(iaaSpans);
222    
223                            String annotationSetName = getAnnotationSetName(knowtatorAnnotation);
224                            annotation.setSetName(annotationSetName);
225    
226                            SimpleInstance mention = annotationUtil.getMention(knowtatorAnnotation);
227                            Cls mentionType = mentionUtil.getMentionCls(mention);
228                            if (mentionType != null)
229                                    annotation.setAnnotationClass(mentionType.getBrowserText());
230    
231                            for (Slot simpleFeatureSlot : simpleFeatureSlots) {
232                                    SimpleInstance slotMention = mentionUtil.getSlotMention(mention, simpleFeatureSlot);
233                                    if (slotMention != null && mentionUtil.isSimpleSlotMention(slotMention)) {
234                                            List<Object> values = mentionUtil.getSlotMentionValues(slotMention);
235                                            Set<Object> valuesSet = new HashSet<Object>(values);
236                                            annotation.setSimpleFeature(simpleFeatureSlot.getBrowserText(), valuesSet);
237                                    }
238                                    if (slotMention != null && !mentionUtil.isSimpleSlotMention(slotMention)) {
239                                            throw new IAAException("The slot " + simpleFeatureSlot.getBrowserText()
240                                                            + " in slot matcher config is not a 'simple' slot.");
241                                    }
242                            }
243    
244                            if (convertComplexFeatures) {
245                                    for (Slot complexFeatureSlot : complexFeatureSlots) {
246                                            List<SimpleInstance> relatedMentions = mentionUtil.getRelatedMentions(mention, complexFeatureSlot);
247                                            Set<Annotation> featureAnnotations = new HashSet<Annotation>();
248                                            for (SimpleInstance relatedMention : relatedMentions) {
249                                                    SimpleInstance relatedAnnotation = mentionUtil.getMentionAnnotation(relatedMention);
250                                                    featureAnnotations.add(convertAnnotation(relatedAnnotation, false));
251                                            }
252                                            annotation.setComplexFeature(complexFeatureSlot.getBrowserText(), featureAnnotations);
253                                    }
254                            }
255                            return annotation;
256                    } catch (TextSourceAccessException tsae) {
257                            throw new IAAException(tsae);
258                    }
259            }
260    
261            private Set<Annotation> convertAnnotations(Collection<SimpleInstance> knowtatorAnnotations) throws IAAException {
262                    Set<Annotation> annotations = new HashSet<Annotation>();
263                    for (SimpleInstance knowtatorAnnotation : knowtatorAnnotations) {
264                            annotations.add(convertAnnotation(knowtatorAnnotation, true));
265                    }
266                    return annotations;
267            }
268    
269            private static int convertMatchSpans(String matchSpans) throws IAAException {
270                    if (matchSpans.equals("SpansMatchExactly"))
271                            return Annotation.SPANS_EXACT_COMPARISON;
272                    else if (matchSpans.equals("SpansOverlap"))
273                            return Annotation.SPANS_OVERLAP_COMPARISON;
274                    else if (matchSpans.equals("IgnoreSpans"))
275                            return Annotation.IGNORE_SPANS_COMPARISON;
276                    else
277                            throw new IAAException(
278                                            "Span match criteria of slot matcher must be one of SpansMatchExactly, SpansOverlap, or IgnoreSpans");
279            }
280    
281            public static FeatureMatcher createFeatureMatcher(SimpleInstance slotMatcherConfig, KnowtatorProjectUtil kpu,
282                            String matcherName) throws IAAException {
283                    FeatureMatcher featureMatcher = new FeatureMatcher(matcherName);
284                    if (!slotMatcherConfig.getDirectType().equals(kpu.getSlotMatcherConfigCls()))
285                            throw new IAAException("Unable to create slot matcher from instance='" + slotMatcherConfig.getBrowserText()
286                                            + "'");
287    
288                    Boolean matchClasses = (Boolean) slotMatcherConfig.getOwnSlotValue(kpu.getClassMatchCriteriaSlot());
289                    if (matchClasses != null)
290                            featureMatcher.setMatchClasses(matchClasses.booleanValue());
291                    else
292                            featureMatcher.setMatchClasses(false);
293    
294                    String matchSpans = (String) slotMatcherConfig.getOwnSlotValue(kpu.getSpanMatchCriteriaSlot());
295                    if (matchSpans != null) {
296                            featureMatcher.setMatchSpans(convertMatchSpans(matchSpans));
297                    } else
298                            throw new IAAException("Slot matcher must specify how to compare spans.");
299    
300                    Collection<SimpleInstance> slotMatchCriteria = (Collection<SimpleInstance>) slotMatcherConfig
301                                    .getOwnSlotValues(kpu.getSlotMatchCriteriaSlot());
302    
303                    for (SimpleInstance slotMatchCriterium : slotMatchCriteria) {
304                            if (slotMatchCriterium.getDirectType().equals(kpu.getSimpleSlotMatchCriteriaCls())) {
305                                    Slot slotMatcherSlot = (Slot) slotMatchCriterium.getOwnSlotValue(kpu.getSlotMatcherSlotSlot());
306                                    featureMatcher.addComparedSimpleFeatures(slotMatcherSlot.getBrowserText());
307                            } else if (slotMatchCriterium.getDirectType().equals(kpu.getComplexSlotMatchCriteriaCls())) {
308                                    Slot slotMatcherSlot = (Slot) slotMatchCriterium.getOwnSlotValue(kpu.getSlotMatcherSlotSlot());
309                                    Boolean b = (Boolean) slotMatchCriterium.getOwnSlotValue(kpu.getClassMatchCriteriaSlot());
310                                    boolean matchSlotClasses = b != null ? b.booleanValue() : false;
311    
312                                    String str = (String) slotMatchCriterium.getOwnSlotValue(kpu.getSpanMatchCriteriaSlot());
313                                    if (str == null)
314                                            throw new IAAException("Slot matcher must specify how to compare spans of complex slot "
315                                                            + slotMatcherSlot.getBrowserText());
316                                    int matchSlotSpans = convertMatchSpans(str);
317    
318                                    Collection<Slot> comparedSimpleSlots = (Collection<Slot>) slotMatchCriterium.getOwnSlotValues(kpu
319                                                    .getSlotMatcherSimpleSlotsSlot());
320                                    Set<String> comparedSimpleFeatures = new HashSet<String>();
321                                    for (Slot comparedSimpleSlot : comparedSimpleSlots) {
322                                            comparedSimpleFeatures.add(comparedSimpleSlot.getBrowserText());
323                                    }
324    
325                                    Boolean propogateTrivialMatch = (Boolean) slotMatchCriterium.getOwnSlotValue(kpu
326                                                    .getPropogateTrivialMatchSlot());
327                                    boolean trivialSimpleFeatureMatchesCauseTrivialMatch = propogateTrivialMatch != null ? propogateTrivialMatch
328                                                    .booleanValue()
329                                                    : false;
330    
331                                    ComplexFeatureMatchCriteria matchCriteria = new ComplexFeatureMatchCriteria(matchSlotClasses,
332                                                    matchSlotSpans, comparedSimpleFeatures, trivialSimpleFeatureMatchesCauseTrivialMatch);
333                                    featureMatcher.addComparedComplexFeature(slotMatcherSlot.getBrowserText(), matchCriteria);
334                            }
335                    }
336    
337                    return featureMatcher;
338            }
339    
340            public IAA runFeatureMatcherIAA(SimpleInstance slotMatcherConfig) throws IAAException {
341                    return runFeatureMatcherIAA(slotMatcherConfig, "Feature Matcher");
342            }
343    
344            public IAA runFeatureMatcherIAA(SimpleInstance slotMatcherConfig, String matcherName) throws IAAException {
345                    try {
346                            FeatureMatcher featureMatcher = createFeatureMatcher(slotMatcherConfig, kpu, matcherName);
347                            IAA featureIAA = new IAA(setNames);
348                            for (Set<Annotation> annotations : textSourceAnnotationsMap.values()) {
349                                    featureIAA.setAnnotations(annotations);
350                                    featureIAA.allwayIAA(featureMatcher);
351                                    featureIAA.pairwiseIAA(featureMatcher);
352                            }
353    
354                            IAA2HTML.printIAA(featureIAA, featureMatcher, outputDirectory, textSources.size(), annotationTexts,
355                                            annotationTextNames);
356                            html.println("<li><a href=\"" + featureMatcher.getName() + ".html\">" + featureMatcher.getName()
357                                            + "</a></li>");
358                            return featureIAA;
359                    } catch (Exception exception) {
360                            throw new IAAException(exception);
361                    }
362            }
363    
364            public IAA runClassIAA() throws IAAException {
365                    try {
366                            ClassMatcher classMatcher = new ClassMatcher();
367                            IAA classIAA = new IAA(setNames);
368    
369                            for (Set<Annotation> annotations : textSourceAnnotationsMap.values()) {
370                                    classIAA.setAnnotations(annotations);
371                                    classIAA.allwayIAA(classMatcher);
372                                    classIAA.pairwiseIAA(classMatcher);
373                            }
374    
375                            IAA2HTML.printIAA(classIAA, classMatcher, outputDirectory, textSources.size(), annotationTexts,
376                                            annotationTextNames);
377                            html.println("<li><a href=\"" + classMatcher.getName() + ".html\">" + classMatcher.getName() + "</a></li>");
378                            return classIAA;
379                    } catch (Exception e) {
380                            throw new IAAException(e);
381                    }
382            }
383    
384            public IAA runSpanIAA() throws IAAException {
385                    try {
386                            SpanMatcher spanMatcher = new SpanMatcher();
387                            IAA spanIAA = new IAA(setNames);
388    
389                            for (Set<Annotation> annotations : textSourceAnnotationsMap.values()) {
390                                    spanIAA.setAnnotations(annotations);
391                                    spanIAA.allwayIAA(spanMatcher);
392                                    spanIAA.pairwiseIAA(spanMatcher);
393                            }
394                            SpanMatcherHTML.printIAA(spanIAA, spanMatcher, outputDirectory, textSources.size(), annotationTexts,
395                                            annotationTextNames);
396                            html.println("<li><a href=\"" + spanMatcher.getName() + ".html\">" + spanMatcher.getName() + "</a></li>");
397                            return spanIAA;
398                    } catch (Exception e) {
399                            throw new IAAException(e);
400                    }
401            }
402    
403            public IAA runClassAndSpanIAA() throws IAAException {
404                    try {
405                            ClassAndSpanMatcher classAndSpanMatcher = new ClassAndSpanMatcher();
406                            IAA classAndSpanIAA = new IAA(setNames);
407    
408                            for (Set<Annotation> annotations : textSourceAnnotationsMap.values()) {
409                                    classAndSpanIAA.setAnnotations(annotations);
410                                    classAndSpanIAA.allwayIAA(classAndSpanMatcher);
411                                    classAndSpanIAA.pairwiseIAA(classAndSpanMatcher);
412                            }
413                            IAA2HTML.printIAA(classAndSpanIAA, classAndSpanMatcher, outputDirectory, textSources.size(),
414                                            annotationTexts, annotationTextNames);
415                            html.println("<li><a href=\"" + classAndSpanMatcher.getName() + ".html\">" + classAndSpanMatcher.getName()
416                                            + "</a></li>");
417                            return classAndSpanIAA;
418                    } catch (Exception e) {
419                            throw new IAAException(e);
420                    }
421            }
422    
423            public void runSubclassIAA() throws IAAException {
424                    try {
425                            Set<Cls> topLevelClses = getTopLevelClses();
426                            Set<Cls> parentClses = new HashSet<Cls>();
427                            for (Cls topLevelCls : topLevelClses) {
428                                    parentClses.add(topLevelCls);
429                                    Collection subclasses = topLevelCls.getSubclasses();
430                                    if (subclasses != null) {
431                                            Iterator subclassesItr = subclasses.iterator();
432                                            while (subclassesItr.hasNext()) {
433                                                    Cls subclass = (Cls) subclassesItr.next();
434                                                    Collection subsubclasses = subclass.getSubclasses();
435                                                    if (subsubclasses != null && subsubclasses.size() > 0) {
436                                                            parentClses.add(subclass);
437                                                    }
438                                            }
439                                    }
440                            }
441    
442                            html.println("<li><a href=\"subclassMatcher.html\">subclass matcher</a></li>");
443    
444                            PrintStream subclassHTML = new PrintStream(new File(outputDirectory, "subclassMatcher.html"));
445                            subclassHTML.println(IAA2HTML.initHTML("Subclass Matcher", ""));
446                            subclassHTML.println("Subclass matcher");
447                            subclassHTML.println("<table border=1>\n");
448                            subclassHTML
449                                            .println("<tr><td><b>Class</b></td><td><b>IAA</b></td><td><b>matches</b></td><td><b>non-matches</b></td></tr>");
450    
451                            SubclassMatcher subclassMatcher = new SubclassMatcher(createClassHierarchy(topLevelClses));
452                            edu.uchsc.ccp.iaa.IAA subclassIAA = new edu.uchsc.ccp.iaa.IAA(setNames);
453    
454                            NumberFormat percentageFormat = NumberFormat.getPercentInstance();
455                            percentageFormat.setMinimumFractionDigits(2);
456    
457                            for (Cls parentCls : parentClses) {
458                                    calculateSubclassIAA(parentCls, subclassMatcher, subclassIAA, textSourceAnnotationsMap);
459                                    SubclassMatcherHTML.printIAA(subclassIAA, subclassMatcher, outputDirectory, textSources.size(),
460                                                    annotationTexts, annotationTextNames);
461    
462                                    Map<String, Set<Annotation>> allwayMatches = subclassIAA.getNontrivialAllwayMatches();
463                                    Set<Annotation> matches = IAA2HTML.getSingleSet(allwayMatches);
464    
465                                    Map<String, Set<Annotation>> allwayNonmatches = subclassIAA.getNontrivialAllwayNonmatches();
466                                    Set<Annotation> nonmatches = IAA2HTML.getSingleSet(allwayNonmatches);
467    
468                                    double subclsIAA = (double) matches.size() / ((double) matches.size() + (double) nonmatches.size());
469    
470                                    subclassHTML.println("<tr><td><a href=\"" + subclassMatcher.getName() + ".html\">"
471                                                    + parentCls.getName() + "</a></td>" + "<td>" + percentageFormat.format(subclsIAA) + "</td><td>"
472                                                    + matches.size() + "</td><td>" + nonmatches.size() + "</td></tr>");
473                            }
474                            subclassHTML.println("</table>");
475                            subclassHTML.println("</body></html>");
476                            subclassHTML.flush();
477                            subclassHTML.close();
478                    } catch (Exception e) {
479                            throw new IAAException(e);
480                    }
481            }
482    
483            private static void calculateSubclassIAA(Cls cls, SubclassMatcher subclassMatcher,
484                            edu.uchsc.ccp.iaa.IAA subclassIAA, Map<String, Set<Annotation>> textSourceAnnotationsMap)
485                            throws edu.uchsc.ccp.iaa.IAAException {
486                    subclassIAA.reset();
487                    subclassMatcher.setIAAClass(cls.getName());
488                    for (Set<Annotation> annotations : textSourceAnnotationsMap.values()) {
489                            subclassIAA.setAnnotations(annotations);
490                            subclassIAA.allwayIAA(subclassMatcher);
491                            subclassIAA.pairwiseIAA(subclassMatcher);
492                    }
493            }
494    
495            private Set<Cls> getTopLevelClses() {
496                    Set<Cls> topLevelClses = new HashSet<Cls>(FilterUtil.getTypes(filter));
497                    if (topLevelClses.size() == 0) {
498                            topLevelClses.addAll(manager.getRootClses());
499                    }
500                    return topLevelClses;
501            }
502    
503            private static ClassHierarchy createClassHierarchy(Set<Cls> topLevelClses) {
504                    Map<String, Set<String>> subclassMap = new HashMap<String, Set<String>>();
505                    for (Cls topLevelCls : topLevelClses) {
506                            populateSubclassMap(topLevelCls, subclassMap);
507                    }
508                    return new ClassHierarchyImpl(subclassMap);
509            }
510    
511            private static void populateSubclassMap(Cls cls, Map<String, Set<String>> subclassMap) {
512                    String clsName = cls.getName();
513                    if (!subclassMap.containsKey(clsName)) {
514                            Collection subclses = cls.getDirectSubclasses();
515                            if (subclses != null && subclses.size() > 0) {
516                                    subclassMap.put(clsName, new HashSet<String>());
517                                    for (Iterator subclsItr = subclses.iterator(); subclsItr.hasNext();) {
518                                            Cls subcls = (Cls) subclsItr.next();
519                                            String subclsName = subcls.getName();
520                                            subclassMap.get(clsName).add(subclsName);
521                                            populateSubclassMap(subcls, subclassMap);
522                                    }
523                            }
524                    }
525            }
526    
527            public static Set<Slot> getSimpleSlotsFromMatcherConfig(SimpleInstance slotMatcherConfig, KnowtatorProjectUtil kpu) {
528                    Set<Slot> returnValues = new HashSet<Slot>();
529    
530                    Collection<SimpleInstance> slotMatchCriteria = (Collection<SimpleInstance>) slotMatcherConfig
531                                    .getOwnSlotValues(kpu.getSlotMatchCriteriaSlot());
532    
533                    for (SimpleInstance slotMatchCriterium : slotMatchCriteria) {
534                            if (slotMatchCriterium.getDirectType().equals(kpu.getSimpleSlotMatchCriteriaCls())) {
535                                    Slot slotMatcherSlot = (Slot) slotMatchCriterium.getOwnSlotValue(kpu.getSlotMatcherSlotSlot());
536                                    returnValues.add(slotMatcherSlot);
537                            } else if (slotMatchCriterium.getDirectType().equals(kpu.getComplexSlotMatchCriteriaCls())) {
538                                    Collection<Slot> comparedSimpleSlots = (Collection<Slot>) slotMatchCriterium.getOwnSlotValues(kpu
539                                                    .getSlotMatcherSimpleSlotsSlot());
540                                    if (comparedSimpleSlots != null)
541                                            returnValues.addAll(comparedSimpleSlots);
542                            }
543                    }
544                    return returnValues;
545            }
546    
547            public static Set<Slot> getComplexSlotsFromMatcherConfig(SimpleInstance slotMatcherConfig, KnowtatorProjectUtil kpu) {
548                    Set<Slot> returnValues = new HashSet<Slot>();
549    
550                    Collection<SimpleInstance> slotMatchCriteria = (Collection<SimpleInstance>) slotMatcherConfig
551                                    .getOwnSlotValues(kpu.getSlotMatchCriteriaSlot());
552    
553                    for (SimpleInstance slotMatchCriterium : slotMatchCriteria) {
554                            if (slotMatchCriterium.getDirectType().equals(kpu.getComplexSlotMatchCriteriaCls())) {
555                                    Slot slotMatcherSlot = (Slot) slotMatchCriterium.getOwnSlotValue(kpu.getSlotMatcherSlotSlot());
556                                    returnValues.add(slotMatcherSlot);
557                            }
558                    }
559                    return returnValues;
560            }
561    
562            public Map<String, Set<Annotation>> getTextSourceAnnotationsMap() {
563                    return textSourceAnnotationsMap;
564            }
565    
566    }