| /* |
| * 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 java.util.Arrays.asList; |
| import static org.assertj.core.api.Assertions.assertThat; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Random; |
| import java.util.function.Function; |
| |
| import org.apache.uima.UIMAFramework; |
| import org.apache.uima.cas.CAS; |
| import org.apache.uima.cas.Type; |
| import org.apache.uima.cas.text.AnnotationFS; |
| import org.apache.uima.fit.util.AnnotationPredicateTestData.RelativePosition; |
| import org.apache.uima.resource.metadata.TypeSystemDescription; |
| import org.apache.uima.util.CasCreationUtils; |
| import org.assertj.core.api.AutoCloseableSoftAssertions; |
| |
| public class SelectionAssert { |
| public static void assertSelection(RelativePosition aCondition, RelativeAnnotationPredicate aPredicate, |
| List<TestCase> aTestCases) |
| throws Exception { |
| CAS cas = CasCreationUtils.createCas((TypeSystemDescription) null, null, null); |
| Type type = cas.getAnnotationType(); |
| |
| try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { |
| for (TestCase testCase : aTestCases) { |
| cas.reset(); |
| |
| // Create annotations |
| AnnotationFS x = cas.createAnnotation(type, 0, 0); |
| AnnotationFS y = cas.createAnnotation(type, 0, 0); |
| |
| // Position the annotations according to the test data |
| testCase.getTest().apply((beginA, endA, beginB, endB) -> { |
| FSUtil.setFeature(x, CAS.FEATURE_BASE_NAME_BEGIN, beginA); |
| FSUtil.setFeature(x, CAS.FEATURE_BASE_NAME_END, endA); |
| FSUtil.setFeature(y, CAS.FEATURE_BASE_NAME_BEGIN, beginB); |
| FSUtil.setFeature(y, CAS.FEATURE_BASE_NAME_END, endB); |
| cas.addFsToIndexes(x); |
| cas.addFsToIndexes(y); |
| return true; |
| }); |
| |
| softly.assertThat(aPredicate.apply(cas, type, x, y)).as(testCase.getDescription()) |
| .isEqualTo(testCase.getValidPositions().contains(aCondition)); |
| } |
| } |
| } |
| |
| public static void assertSelectionIsEqualOnRandomData(TypeByContextSelector aExpected, TypeByContextSelector aActual) |
| throws Exception { |
| final int ITERATIONS = 30; |
| final int TYPES = 5; |
| |
| TypeSystemDescription tsd = UIMAFramework.getResourceSpecifierFactory().createTypeSystemDescription(); |
| |
| Map<String, Type> types = new LinkedHashMap<>(); |
| for (int i = 0; i < TYPES; i++) { |
| String typeName = "test.Type" + (i + 1); |
| tsd.addType(typeName, "", CAS.TYPE_NAME_ANNOTATION); |
| types.put(typeName, null); |
| } |
| |
| CAS randomCas = CasCreationUtils.createCas(tsd, null, null, null); |
| |
| for (String typeName : types.keySet()) { |
| types.put(typeName, randomCas.getTypeSystem().getType(typeName)); |
| } |
| |
| System.out.print("Iteration: "); |
| try { |
| Iterator<Type> ti = types.values().iterator(); |
| Type type1 = ti.next(); |
| Type type2 = ti.next(); |
| |
| for (int i = 0; i < ITERATIONS; i++) { |
| if (i % 10 == 0) { |
| System.out.print(i); |
| } |
| else { |
| System.out.print("."); |
| } |
| |
| initRandomCas(randomCas, 3 * i, 0, types.values().toArray(new Type[types.size()])); |
| |
| for (AnnotationFS context : randomCas.getAnnotationIndex(type1)) { |
| List<AnnotationFS> expected = aExpected.select(randomCas, type2, context); |
| List<AnnotationFS> actual = aActual.select(randomCas, type2, context); |
| |
| assertThat(actual) |
| .as("Selected [%s] with context [%s]@[%d..%d]", type2.getShortName(), |
| type1.getShortName(), context.getBegin(), context.getEnd()) |
| .containsExactlyElementsOf(expected); |
| } |
| } |
| System.out.print(ITERATIONS); |
| } |
| finally { |
| System.out.println(); |
| } |
| } |
| |
| private static void initRandomCas(CAS aCas, int aSize, int aMinimumWidth, Type... aTypes) { |
| Random rnd = new Random(); |
| |
| List<Type> types = new ArrayList<>(asList(aTypes)); |
| |
| // Shuffle the types |
| for (int n = 0; n < 10; n++) { |
| Type t = types.remove(rnd.nextInt(types.size())); |
| types.add(t); |
| } |
| |
| // Randomly generate annotations |
| for (int n = 0; n < aSize; n++) { |
| for (Type t : types) { |
| int begin = rnd.nextInt(100); |
| int end = begin + rnd.nextInt(30) + aMinimumWidth; |
| aCas.addFsToIndexes(aCas.createAnnotation(t, begin, end)); |
| } |
| } |
| } |
| |
| @FunctionalInterface |
| public static interface RelativeAnnotationPredicate { |
| boolean apply(CAS cas, Type type, AnnotationFS x, AnnotationFS y); |
| } |
| |
| @FunctionalInterface |
| public static interface TypeByContextSelector { |
| List<AnnotationFS> select(CAS aCas, Type aType, AnnotationFS aContext); |
| } |
| |
| @FunctionalInterface |
| public static interface RelativePositionPredicate { |
| boolean apply(int beginA, int endA, int beginB, int endB); |
| } |
| |
| public static class TestCase { |
| private final String description; |
| |
| private final Function<RelativePositionPredicate, Boolean> predicate; |
| |
| private final List<RelativePosition> validPositions; |
| |
| public TestCase(String aDescription, Function<RelativePositionPredicate, Boolean> aPredicate, List<RelativePosition> aValidPositions) { |
| description = aDescription; |
| predicate = aPredicate; |
| validPositions = aValidPositions; |
| } |
| |
| public String getDescription() { |
| return description; |
| } |
| |
| public Function<RelativePositionPredicate, Boolean> getTest() { |
| return predicate; |
| } |
| |
| public List<RelativePosition> getValidPositions() { |
| return validPositions; |
| } |
| } |
| } |