| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.uima.fit.util; |
| |
| import static org.apache.uima.fit.util.CasUtil.select; |
| import static org.apache.uima.fit.util.CasUtil.selectCovered; |
| |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedList; |
| import java.util.Map; |
| |
| import org.apache.uima.cas.CAS; |
| import org.apache.uima.cas.text.AnnotationFS; |
| import org.apache.uima.jcas.JCas; |
| |
| /** |
| * Create a fast way of repeatedly checking whether instances of one type are contained within the |
| * boundaries on another type. |
| * |
| * |
| * @param <S> |
| * covering type. |
| * @param <U> |
| * covered type. |
| */ |
| public class ContainmentIndex<S extends AnnotationFS, U extends AnnotationFS> { |
| public static enum Type { |
| DIRECT, REVERSE, BOTH |
| } |
| |
| private final Map<AnnotationFS, Collection<AnnotationFS>> data = new LinkedHashMap<AnnotationFS, Collection<AnnotationFS>>(); |
| |
| private final Map<AnnotationFS, Collection<AnnotationFS>> dataRev = new LinkedHashMap<AnnotationFS, Collection<AnnotationFS>>(); |
| |
| /** |
| * Create a new index on the given JCas using the specified two types. The last argument indicates |
| * in which directions lookups to the index will be made. |
| * |
| * @param cas |
| * the working JCas. |
| * @param aSuper |
| * the covering type. |
| * @param aUnder |
| * the covered type. |
| * @param aType |
| * the indexing strategy. |
| */ |
| protected ContainmentIndex(CAS cas, org.apache.uima.cas.Type aSuper, |
| org.apache.uima.cas.Type aUnder, Type aType) { |
| Collection<AnnotationFS> over = select(cas, aSuper); |
| for (AnnotationFS s : over) { |
| Collection<AnnotationFS> under = selectCovered(cas, aUnder, s); |
| for (AnnotationFS u : under) { |
| switch (aType) { |
| case DIRECT: { |
| put(data, s, u); |
| break; |
| } |
| case REVERSE: |
| put(dataRev, u, s); |
| break; |
| case BOTH: |
| put(data, s, u); |
| put(dataRev, u, s); |
| break; |
| } |
| } |
| } |
| } |
| |
| private <X, Y> void put(Map<X, Collection<Y>> map, X key, Y value) { |
| Collection<Y> c = map.get(key); |
| if (c == null) { |
| c = new LinkedList<Y>(); |
| map.put(key, c); |
| } |
| c.add(value); |
| } |
| |
| /** |
| * Get all instances of the covered type contained within the boundaries of the specified instance |
| * of the covering type. |
| * |
| * @param aSuper |
| * a covering type instance. |
| * @return a collection of covered type instances. |
| */ |
| @SuppressWarnings("unchecked") |
| public Collection<U> containedIn(S aSuper) { |
| @SuppressWarnings("rawtypes") |
| Collection c = data.get(aSuper); |
| if (c == null) { |
| return Collections.emptySet(); |
| } |
| return c; |
| } |
| |
| /** |
| * Get all instances of the covering type containing the the specified instance of the covered |
| * type. |
| * |
| * @param aUnder |
| * a covered type instance. |
| * @return a collection of covering type instances. |
| */ |
| @SuppressWarnings("unchecked") |
| public Collection<S> containing(U aUnder) { |
| @SuppressWarnings("rawtypes") |
| Collection c = dataRev.get(aUnder); |
| if (c == null) { |
| return Collections.emptySet(); |
| } |
| return c; |
| } |
| |
| /** |
| * Checks if the given covered type is contained in the specified covering type. |
| * |
| * @param aSuper |
| * the covering type instance. |
| * @param aUnder |
| * the covered type instance. |
| * @return whether the covered instance is contained in the covering instance. |
| */ |
| public boolean isContainedIn(S aSuper, U aUnder) { |
| return containedIn(aSuper).contains(aUnder); |
| } |
| |
| /** |
| * Checks if the given covered type is contained in any instance of the covering type. |
| * |
| * @param aUnder |
| * the covered type instance. |
| * @return whether the covered instance is contained in any instance of the covering type. |
| */ |
| public boolean isContainedInAny(U aUnder) { |
| Collection<S> containers = containing(aUnder); |
| return containers != null && !containers.isEmpty(); |
| } |
| |
| /** |
| * Factory method to create an index instead of using the constructor. This makes used of Java's |
| * type inference capabilities and results in less verbose code. |
| * |
| * @param <A> |
| * covering type. |
| * @param <B> |
| * covered type. |
| * @param aJcas |
| * the working JCas. |
| * @param aSuper |
| * the covering type. |
| * @param aUnder |
| * the covered type. |
| * @param aType |
| * the indexing strategy. |
| * @return the index instance. |
| */ |
| @SuppressWarnings("unchecked") |
| public static <A extends AnnotationFS, B extends AnnotationFS> ContainmentIndex<A, B> create( |
| JCas aJcas, Class<A> aSuper, Class<B> aUnder, Type aType) { |
| return (ContainmentIndex<A, B>) create(aJcas.getCas(), JCasUtil.getType(aJcas, aSuper), |
| JCasUtil.getType(aJcas, aUnder), aType); |
| } |
| |
| /** |
| * Factory method to create an index instead of using the constructor. This makes used of Java's |
| * type inference capabilities and results in less verbose code. |
| * |
| * @param cas |
| * the working JCas. |
| * @param aSuper |
| * the covering type. |
| * @param aUnder |
| * the covered type. |
| * @param aType |
| * the indexing strategy. |
| * @return the index instance. |
| */ |
| public static ContainmentIndex<AnnotationFS, AnnotationFS> create(CAS cas, |
| org.apache.uima.cas.Type aSuper, org.apache.uima.cas.Type aUnder, Type aType) { |
| return new ContainmentIndex<AnnotationFS, AnnotationFS>(cas, aSuper, aUnder, aType); |
| } |
| } |