blob: 9af51415cfb228d70078e1476004cb174dd04d14 [file] [log] [blame]
/*
* 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.ruta.testing.evaluator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CASException;
import org.apache.uima.cas.CASRuntimeException;
import org.apache.uima.cas.Feature;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.cas.text.AnnotationIndex;
import org.apache.uima.jcas.tcas.Annotation;
public class TemplateCasEvaluator implements ICasEvaluator {
public CAS evaluate(CAS test, CAS run, Collection<String> excludedTypes, boolean includeSubtypes)
throws CASRuntimeException, CASException {
Type falsePositiveType = run.getTypeSystem().getType(ICasEvaluator.FALSE_POSITIVE);
Type falseNegativeType = run.getTypeSystem().getType(ICasEvaluator.FALSE_NEGATIVE);
Type truePositveType = run.getTypeSystem().getType(ICasEvaluator.TRUE_POSITIVE);
Feature feature = falsePositiveType.getFeatureByBaseName(ICasEvaluator.ORIGINAL);
List<Type> allTypes = test.getTypeSystem().getProperlySubsumedTypes(
test.getTypeSystem().getTopType());
List<Type> types = new ArrayList<Type>();
TypeSystem typeSystem = test.getTypeSystem();
Type annotationType = test.getAnnotationType();
for (Type eachType : allTypes) {
if (!excludedTypes.contains(eachType.getName())) {
List<Feature> features = eachType.getFeatures();
for (Feature f : features) {
Type range = f.getRange();
if (typeSystem.subsumes(annotationType, range)) {
if (!eachType.getName().startsWith("org.apache.uima.ruta.type")) {
types.add(eachType);
break;
}
}
}
}
}
Collection<FeatureStructure> testFSs = getFeatureStructures(types, test);
Collection<FeatureStructure> runFSs = getFeatureStructures(types, run);
Collection<FeatureStructure> matched = new HashSet<FeatureStructure>();
List<FeatureStructure> fp = new ArrayList<FeatureStructure>();
List<FeatureStructure> fn = new ArrayList<FeatureStructure>();
List<FeatureStructure> tp = new ArrayList<FeatureStructure>();
for (FeatureStructure eachTest : testFSs) {
boolean found = false;
for (FeatureStructure eachRun : runFSs) {
if (match(eachTest, eachRun)) {
matched.add(eachRun);
found = true;
break;
}
}
if (!found) {
FeatureStructure createFS = run.createFS(falseNegativeType);
fillFS(eachTest, createFS, false);
Type type = run.getTypeSystem().getType(eachTest.getType().getName());
FeatureStructure original = run.createFS(type);
fillFS(eachTest, original, true);
createFS.setFeatureValue(feature, original);
fn.add(createFS);
} else {
FeatureStructure createFS = run.createFS(truePositveType);
fillFS(eachTest, createFS, false);
Type type = run.getTypeSystem().getType(eachTest.getType().getName());
FeatureStructure original = run.createFS(type);
fillFS(eachTest, original, true);
createFS.setFeatureValue(feature, original);
tp.add(createFS);
}
}
for (FeatureStructure each : runFSs) {
if (!matched.contains(each)) {
FeatureStructure createFS = run.createFS(falsePositiveType);
fillFS(each, createFS, false);
Type type = run.getTypeSystem().getType(each.getType().getName());
FeatureStructure original = run.createFS(type);
fillFS(each, original, true);
createFS.setFeatureValue(feature, original);
fp.add(createFS);
}
}
for (FeatureStructure fs : fn) {
run.addFsToIndexes(fs);
}
for (FeatureStructure fs : fp) {
run.addFsToIndexes(fs);
}
for (FeatureStructure fs : tp) {
run.addFsToIndexes(fs);
}
return run;
}
private void fillFS(FeatureStructure fs, FeatureStructure newFS, boolean withFeatures) {
if (fs instanceof AnnotationFS) {
Annotation a = (Annotation) newFS;
a.setBegin(((AnnotationFS) fs).getBegin());
a.setEnd(((AnnotationFS) fs).getEnd());
}
if (withFeatures) {
CAS testCas = fs.getCAS();
CAS runCas = newFS.getCAS();
TypeSystem testTS = testCas.getTypeSystem();
TypeSystem runTS = runCas.getTypeSystem();
Type annotationType = testCas.getAnnotationType();
List<Feature> features = fs.getType().getFeatures();
for (Feature feature : features) {
Type range = feature.getRange();
if (testTS.subsumes(annotationType, range)) {
FeatureStructure valueTest = fs.getFeatureValue(feature);
if (valueTest instanceof AnnotationFS) {
AnnotationFS a1 = (AnnotationFS) valueTest;
Feature feature2 = newFS.getType().getFeatureByBaseName(feature.getShortName());
if (feature != null) {
Type range2 = runTS.getType(range.getName());
AnnotationFS createAnnotation = runCas.createAnnotation(range2, a1.getBegin(),
a1.getEnd());
newFS.setFeatureValue(feature2, createAnnotation);
}
}
}
}
}
}
private Collection<FeatureStructure> getFeatureStructures(List<Type> types, CAS cas) {
TypeSystem typeSystem = cas.getTypeSystem();
Type annotationType = cas.getAnnotationType();
Collection<FeatureStructure> result = new HashSet<FeatureStructure>();
AnnotationIndex<AnnotationFS> annotationIndex = cas.getAnnotationIndex();
for (AnnotationFS each : annotationIndex) {
Type type = each.getType();
for (Type eachType : types) {
if(typeSystem.subsumes(eachType, type)) {
List<Feature> features = each.getType().getFeatures();
for (Feature feature : features) {
Type range = feature.getRange();
if (typeSystem.subsumes(annotationType, range)) {
result.add(each);
break;
}
}
}
}
}
return result;
}
private boolean match(FeatureStructure a1, FeatureStructure a2) {
Type type1 = a1.getType();
Type type2 = a2.getType();
if (!type1.getName().equals(type2.getName())) {
return false;
}
if (a1 instanceof AnnotationFS && a2 instanceof AnnotationFS) {
AnnotationFS a11 = (AnnotationFS) a1;
AnnotationFS a22 = (AnnotationFS) a2;
if (!(a11.getBegin() == a22.getBegin() && a11.getEnd() == a22.getEnd())) {
return false;
}
}
CAS cas = a1.getCAS();
TypeSystem typeSystem = cas.getTypeSystem();
Type annotationType = cas.getAnnotationType();
List<Feature> features1 = type1.getFeatures();
boolean result = true;
boolean allEmpty1 = true;
boolean allEmpty2 = true;
for (Feature eachFeature1 : features1) {
Type range = eachFeature1.getRange();
if (typeSystem.subsumes(annotationType, range)) {
String name = eachFeature1.getShortName();
Feature eachFeature2 = type2.getFeatureByBaseName(name);
FeatureStructure featureValue1 = a1.getFeatureValue(eachFeature1);
FeatureStructure featureValue2 = a2.getFeatureValue(eachFeature2);
allEmpty1 &= featureValue1 == null;
allEmpty2 &= featureValue2 == null;
if (featureValue1 instanceof AnnotationFS && featureValue2 instanceof AnnotationFS) {
result &= matchAnnotations((AnnotationFS) featureValue1, (AnnotationFS) featureValue2);
} else if (featureValue1 == null) {
// nothing to do
} else if (featureValue1 != null || featureValue2 != null) {
return false;
}
}
}
return result && (allEmpty1 == allEmpty2);
}
private boolean matchAnnotations(AnnotationFS a1, AnnotationFS a2) {
if (a1 != null && a2 != null) {
if (a1.getBegin() == a2.getBegin() && a1.getEnd() == a2.getEnd()
&& a1.getType().getName().equals(a2.getType().getName())) {
return true;
}
}
return false;
}
}