Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java Wed Jan 16 11:45:02 2019 @@ -21,17 +21,23 @@ package org.apache.uima.ruta.expression. import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; +import org.apache.uima.cas.ArrayFS; import org.apache.uima.cas.CAS; 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.ruta.RutaStream; import org.apache.uima.ruta.expression.IRutaExpression; import org.apache.uima.ruta.expression.MatchReference; import org.apache.uima.ruta.expression.RutaExpression; +import org.apache.uima.ruta.expression.annotation.IAnnotationExpression; +import org.apache.uima.ruta.expression.annotation.IAnnotationListExpression; import org.apache.uima.ruta.expression.bool.IBooleanExpression; import org.apache.uima.ruta.expression.number.INumberExpression; import org.apache.uima.ruta.expression.string.IStringExpression; @@ -71,51 +77,56 @@ public class FeatureMatchExpression exte public boolean checkFeatureValue(FeatureStructure fs, MatchContext context, RutaStream stream) { Feature feature = getFeature(context, stream); + if (feature instanceof LazyFeature) { + LazyFeature lazyFeature = (LazyFeature) feature; + feature = lazyFeature.initialize(fs); + } return checkFeatureValue(fs, feature, context, stream); } public boolean checkFeatureValue(FeatureStructure fs, Feature feature, MatchContext context, RutaStream stream) { - String rn = null; - if(feature instanceof CoveredTextFeature) { - rn = CAS.TYPE_NAME_STRING; - } else if (feature != null){ - rn = feature.getRange().getName(); + Type featureRangeType = null; + TypeSystem typeSystem = stream.getCas().getTypeSystem(); + if (feature instanceof CoveredTextFeature) { + featureRangeType = typeSystem.getType(CAS.TYPE_NAME_STRING); + } else if (feature != null) { + featureRangeType = feature.getRange(); } - - if (rn.equals(CAS.TYPE_NAME_BOOLEAN)) { + String rangeName = featureRangeType.getName(); + if (rangeName.equals(CAS.TYPE_NAME_BOOLEAN)) { Boolean v1 = fs.getBooleanValue(feature); if (getArg() instanceof IBooleanExpression) { IBooleanExpression expr = (IBooleanExpression) getArg(); Boolean v2 = expr.getBooleanValue(context, stream); return compare(v1, v2); } - } else if (rn.equals(CAS.TYPE_NAME_INTEGER) || rn.equals(CAS.TYPE_NAME_BYTE) - || rn.equals(CAS.TYPE_NAME_SHORT) || rn.equals(CAS.TYPE_NAME_LONG)) { + } else if (rangeName.equals(CAS.TYPE_NAME_INTEGER) || rangeName.equals(CAS.TYPE_NAME_BYTE) + || rangeName.equals(CAS.TYPE_NAME_SHORT) || rangeName.equals(CAS.TYPE_NAME_LONG)) { Integer v1 = fs.getIntValue(feature); if (getArg() instanceof INumberExpression) { INumberExpression expr = (INumberExpression) getArg(); Integer v2 = expr.getIntegerValue(context, stream); return compare(v1, v2); } - } else if (rn.equals(CAS.TYPE_NAME_DOUBLE)) { + } else if (rangeName.equals(CAS.TYPE_NAME_DOUBLE)) { Double v1 = fs.getDoubleValue(feature); if (getArg() instanceof INumberExpression) { INumberExpression expr = (INumberExpression) getArg(); Double v2 = expr.getDoubleValue(context, stream); return compare(v1, v2); } - } else if (rn.equals(CAS.TYPE_NAME_FLOAT)) { + } else if (rangeName.equals(CAS.TYPE_NAME_FLOAT)) { Float v1 = fs.getFloatValue(feature); if (getArg() instanceof INumberExpression) { INumberExpression expr = (INumberExpression) getArg(); Float v2 = expr.getFloatValue(context, stream); return compare(v1, v2); } - } else if (rn.equals(CAS.TYPE_NAME_STRING)) { + } else if (typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_STRING), featureRangeType)) { String v1 = null; // null is possibly coveredText - if(feature instanceof CoveredTextFeature && fs instanceof AnnotationFS) { + if (feature instanceof CoveredTextFeature && fs instanceof AnnotationFS) { v1 = ((AnnotationFS) fs).getCoveredText(); } else if (feature != null) { v1 = fs.getStringValue(feature); @@ -125,13 +136,27 @@ public class FeatureMatchExpression exte String v2 = expr.getStringValue(context, stream); return compare(v1, v2); } - } else if (!feature.getRange().isPrimitive() && getArg() instanceof FeatureExpression) { - FeatureExpression fe = (FeatureExpression) getArg(); - List<FeatureStructure> list = new ArrayList<>(1); - list.add(fs); - Collection<? extends FeatureStructure> featureAnnotations = fe.getFeatureStructures(list, false, context, - stream); - return compare(fs.getFeatureValue(feature), featureAnnotations); + } else { + FeatureStructure featureValue = fs.getFeatureValue(feature); + if (!feature.getRange().isPrimitive() && getArg() instanceof FeatureExpression) { + FeatureExpression fe = (FeatureExpression) getArg(); + List<FeatureStructure> list = new ArrayList<>(1); + list.add(fs); + Collection<? extends FeatureStructure> featureAnnotations = fe.getFeatureStructures(list, + false, context, stream); + return compare(featureValue, featureAnnotations); + } else if (!feature.getRange().isPrimitive() && getArg() instanceof IAnnotationExpression) { + IAnnotationExpression ae = (IAnnotationExpression) getArg(); + AnnotationFS compareAnnotation = ae.getAnnotation(context, stream); + return compare(featureValue, compareAnnotation); + } else if (!feature.getRange().isPrimitive() + && typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_FS_ARRAY), featureRangeType) + && getArg() instanceof IAnnotationListExpression) { + ArrayFS fsArray = (ArrayFS) featureValue; + IAnnotationListExpression ale = (IAnnotationListExpression) getArg(); + List<AnnotationFS> annotationList = ale.getAnnotationList(context, stream); + return compare(Arrays.asList(fsArray.toArray()), annotationList); + } } return false; } @@ -188,13 +213,13 @@ public class FeatureMatchExpression exte @Override public String toString() { String result = super.toString(); - if(op != null) { + if (op != null) { result += op; } - if(arg != null) { + if (arg != null) { result += arg.toString(); } return result; } - + }
Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java Wed Jan 16 11:45:02 2019 @@ -21,6 +21,7 @@ package org.apache.uima.ruta.expression. import org.apache.uima.cas.Feature; import org.apache.uima.cas.FeatureStructure; import org.apache.uima.cas.Type; +import org.apache.uima.ruta.block.RutaBlock; public class LazyFeature implements Feature { @@ -30,9 +31,12 @@ public class LazyFeature implements Feat private String initializedWith; - public LazyFeature(String featureName) { + private RutaBlock parent; + + public LazyFeature(String featureName, RutaBlock parent) { super(); this.featureName = featureName; + this.parent = parent; } public Feature initialize(FeatureStructure featureStructure) { @@ -94,7 +98,8 @@ public class LazyFeature implements Feat private void checkDelegate() { if (delegate == null) { throw new RuntimeException("Feature with name '" + featureName - + "' has not yet been resolved. Most likely, it is not defined for the given type: " + initializedWith); + + "' has not yet been resolved in script " + parent.getName() + + ". Most likely, it is not defined for the given type: " + initializedWith); } } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java Wed Jan 16 11:45:02 2019 @@ -6,9 +6,9 @@ * 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 @@ -43,24 +43,28 @@ public class SimpleFeatureExpression ext private MatchReference mr; public SimpleFeatureExpression(MatchReference mr) { + super(); this.mr = mr; } @Override public Feature getFeature(MatchContext context, RutaStream stream) { - List<Feature> features = getFeatures(context, stream); + + List<Feature> features = this.getFeatures(context, stream); if (features != null && !features.isEmpty()) { Feature feature = features.get(features.size() - 1); if (feature instanceof LazyFeature) { LazyFeature lazyFeature = (LazyFeature) feature; AnnotationFS annotation = context.getAnnotation(); - List<AnnotationFS> targetAnnotation = getTargetAnnotation(annotation, this, context, + List<AnnotationFS> targetAnnotation = this.getTargetAnnotation(annotation, this, context, stream); if (targetAnnotation != null && !targetAnnotation.isEmpty()) { annotation = targetAnnotation.get(0); } - feature = lazyFeature.initialize(annotation); + if (features.size() == 1) { + feature = lazyFeature.initialize(annotation); + } } return feature; } else { @@ -70,24 +74,25 @@ public class SimpleFeatureExpression ext @Override public List<Feature> getFeatures(MatchContext context, RutaStream stream) { + List<Feature> result = new ArrayList<Feature>(); - Type type = getInitialType(context, stream); + Type type = this.getInitialType(context, stream); Feature feature = null; - for (String each : getFeatureStringList(context, stream)) { + for (String each : this.getFeatureStringList(context, stream)) { IndexedReference indexedReference = ParsingUtils.parseIndexedReference(each); if (indexedReference.index != -1) { Feature delegate = type.getFeatureByBaseName(indexedReference.reference); if (delegate != null) { feature = new IndexedFeature(delegate, indexedReference.index); } else { - throw new IllegalArgumentException( - "Not able to access feature " + each + " of type " + type.getName()); + throw new IllegalArgumentException("Not able to access feature " + each + " of type " + + type.getName() + "in script " + context.getParent().getName()); } } else if (StringUtils.equals(each, UIMAConstants.FEATURE_COVERED_TEXT) || StringUtils.equals(each, UIMAConstants.FEATURE_COVERED_TEXT_SHORT)) { if (type != null) { feature = type.getFeatureByBaseName(each); - if(feature == null) { + if (feature == null) { // there is no explicit feature for coveredText feature = new CoveredTextFeature(); } @@ -97,12 +102,12 @@ public class SimpleFeatureExpression ext } } else if (type == null || type.isArray()) { // lazy check of range - feature = new LazyFeature(each); + feature = new LazyFeature(each, context.getParent()); } else { feature = type.getFeatureByBaseName(each); if (feature == null) { // type maybe not specific enough - feature = new LazyFeature(each); + feature = new LazyFeature(each, context.getParent()); } } result.add(feature); @@ -117,17 +122,19 @@ public class SimpleFeatureExpression ext @Override public Type getInitialType(MatchContext context, RutaStream stream) { - ITypeExpression typeExpression = mr.getTypeExpression(context, stream); - IAnnotationExpression annotationExpression = mr.getAnnotationExpression(context, stream); - IAnnotationExpression annotationListExpression = mr.getAnnotationExpression(context, stream); - if (typeExpression!= null) { + + ITypeExpression typeExpression = this.mr.getTypeExpression(context, stream); + IAnnotationExpression annotationExpression = this.mr.getAnnotationExpression(context, stream); + IAnnotationExpression annotationListExpression = this.mr.getAnnotationExpression(context, + stream); + if (typeExpression != null) { return typeExpression.getType(context, stream); - } else if(annotationExpression != null) { - AnnotationFS annotation = annotationExpression.getAnnotation(context, stream); - if (annotation != null) { - return annotation.getType(); - } - } else if(annotationListExpression != null) { + } else if (annotationExpression != null) { + AnnotationFS annotation = annotationExpression.getAnnotation(context, stream); + if (annotation != null) { + return annotation.getType(); + } + } else if (annotationListExpression != null) { AnnotationFS annotation = annotationListExpression.getAnnotation(context, stream); if (annotation != null) { return annotation.getType(); @@ -138,7 +145,8 @@ public class SimpleFeatureExpression ext @Override public List<String> getFeatureStringList(MatchContext context, RutaStream stream) { - return mr.getFeatureList(); + + return this.mr.getFeatureList(); } @Override @@ -147,13 +155,13 @@ public class SimpleFeatureExpression ext MatchContext context, RutaStream stream) { Collection<AnnotationFS> result = new ArrayList<>(); - List<Feature> features = getFeatures(context, stream); + List<Feature> features = this.getFeatures(context, stream); if (features != null && !features.isEmpty()) { - collectFeatureStructures(featureStructures, features, checkOnFeatureValue, true, result, + this.collectFeatureStructures(featureStructures, features, checkOnFeatureValue, true, result, stream, context); return result; } else { - return filterAnnotations(featureStructures); + return this.filterAnnotations(featureStructures); } } @@ -161,10 +169,11 @@ public class SimpleFeatureExpression ext public Collection<? extends FeatureStructure> getFeatureStructures( Collection<? extends FeatureStructure> featureStructures, boolean checkOnFeatureValue, MatchContext context, RutaStream stream) { + Collection<FeatureStructure> result = new ArrayList<>(); - List<Feature> features = getFeatures(context, stream); + List<Feature> features = this.getFeatures(context, stream); if (features != null && !features.isEmpty()) { - collectFeatureStructures(featureStructures, features, checkOnFeatureValue, false, result, + this.collectFeatureStructures(featureStructures, features, checkOnFeatureValue, false, result, stream, context); return result; } else { @@ -172,25 +181,28 @@ public class SimpleFeatureExpression ext } } - private <T> void collectFeatureStructures(Collection<? extends FeatureStructure> featureStructures, - List<Feature> features, boolean checkOnFeatureValue, boolean onlyAnnotations, - Collection<T> result, RutaStream stream, MatchContext context) { + private <T> void collectFeatureStructures( + Collection<? extends FeatureStructure> featureStructures, List<Feature> features, + boolean checkOnFeatureValue, boolean onlyAnnotations, Collection<T> result, + RutaStream stream, MatchContext context) { + for (FeatureStructure each : featureStructures) { - collectFeatureStructures(each, features, checkOnFeatureValue, onlyAnnotations, null, result, - stream, context); + this.collectFeatureStructures(each, features, checkOnFeatureValue, onlyAnnotations, null, + result, stream, context); } } @SuppressWarnings("unchecked") - private <T> void collectFeatureStructures(FeatureStructure featureStructure, List<Feature> features, - boolean checkOnFeatureValue, boolean collectOnlyAnnotations, - T lastValidFeatureStructure, Collection<T> result, - RutaStream stream, MatchContext context) { + private <T> void collectFeatureStructures(FeatureStructure featureStructure, + List<Feature> features, boolean checkOnFeatureValue, boolean collectOnlyAnnotations, + T lastValidFeatureStructure, Collection<T> result, RutaStream stream, + MatchContext context) { + if (featureStructure == null) { return; } if (!collectOnlyAnnotations) { - if(!featureStructure.getType().isArray()) { + if (!featureStructure.getType().isArray()) { lastValidFeatureStructure = (T) featureStructure; } } else if (featureStructure instanceof AnnotationFS) { @@ -207,7 +219,8 @@ public class SimpleFeatureExpression ext Feature delegate = lazyFeature.initialize(featureStructure); if (delegate == null) { throw new RuntimeException("Invalid feature! Feature '" + lazyFeature.getFeatureName() - + "' is not defined for type '" + featureStructure.getType() + "'."); + + "' is not defined for type '" + featureStructure.getType() + "' in script " + + context.getParent().getName() + "."); } else { currentFeature = delegate; } @@ -231,15 +244,15 @@ public class SimpleFeatureExpression ext result.add(lastValidFeatureStructure); } } else { - collectFeatureStructures(featureStructure, currentFeature, tail, checkOnFeatureValue, + this.collectFeatureStructures(featureStructure, currentFeature, tail, checkOnFeatureValue, collectOnlyAnnotations, lastValidFeatureStructure, result, stream, context); } } - private <T> void collectFeatureStructures(FeatureStructure featureStructure, Feature currentFeature, - List<Feature> tail, boolean checkOnFeatureValue, boolean collectOnlyAnnotations, - T lastValidFeatureStructure, Collection<T> result, RutaStream stream, - MatchContext context) { + private <T> void collectFeatureStructures(FeatureStructure featureStructure, + Feature currentFeature, List<Feature> tail, boolean checkOnFeatureValue, + boolean collectOnlyAnnotations, T lastValidFeatureStructure, Collection<T> result, + RutaStream stream, MatchContext context) { // stop early for match expressions if (this instanceof FeatureMatchExpression && (tail == null || tail.isEmpty())) { @@ -264,7 +277,7 @@ public class SimpleFeatureExpression ext FeatureStructure value = featureStructure.getFeatureValue(currentFeature); if (value instanceof AnnotationFS) { AnnotationFS next = (AnnotationFS) value; - collectFeatureStructures(next, tail, checkOnFeatureValue, collectOnlyAnnotations, + this.collectFeatureStructures(next, tail, checkOnFeatureValue, collectOnlyAnnotations, lastValidFeatureStructure, result, stream, context); } else if (value instanceof FSArray && index >= 0) { FSArray array = (FSArray) value; @@ -272,7 +285,7 @@ public class SimpleFeatureExpression ext FeatureStructure fs = array.get(index); if (fs instanceof AnnotationFS) { AnnotationFS next = (AnnotationFS) fs; - collectFeatureStructures(next, tail, checkOnFeatureValue, collectOnlyAnnotations, + this.collectFeatureStructures(next, tail, checkOnFeatureValue, collectOnlyAnnotations, lastValidFeatureStructure, result, stream, context); } } @@ -280,12 +293,12 @@ public class SimpleFeatureExpression ext FSArray array = (FSArray) value; for (int i = 0; i < array.size(); i++) { FeatureStructure fs = array.get(i); - collectFeatureStructures(fs, tail, checkOnFeatureValue, collectOnlyAnnotations, + this.collectFeatureStructures(fs, tail, checkOnFeatureValue, collectOnlyAnnotations, lastValidFeatureStructure, result, stream, context); } } else if (value != null && !value.getType().isPrimitive()) { // feature structure feature values - collectFeatureStructures(value, tail, checkOnFeatureValue, collectOnlyAnnotations, + this.collectFeatureStructures(value, tail, checkOnFeatureValue, collectOnlyAnnotations, lastValidFeatureStructure, result, stream, context); } else if (value != null) { // primitive? -> return last annotation for further processing @@ -296,16 +309,19 @@ public class SimpleFeatureExpression ext } public MatchReference getMatchReference() { - return mr; + + return this.mr; } @Override public String toString() { - return mr.getMatch(); + + return this.mr.getMatch(); } private Collection<AnnotationFS> filterAnnotations( Collection<? extends FeatureStructure> featureStructures) { + Collection<AnnotationFS> result = new ArrayList<>(featureStructures.size()); for (FeatureStructure featureStructure : featureStructures) { Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java Wed Jan 16 11:45:02 2019 @@ -29,6 +29,7 @@ import org.apache.uima.cas.Type; import org.apache.uima.cas.text.AnnotationFS; import org.apache.uima.ruta.RutaStream; import org.apache.uima.ruta.expression.feature.FeatureExpression; +import org.apache.uima.ruta.expression.feature.LazyFeature; import org.apache.uima.ruta.rule.MatchContext; public class NumberFeatureExpression extends AbstractNumberExpression { @@ -70,12 +71,16 @@ public class NumberFeatureExpression ext false, context, stream); if (!featureStructures.isEmpty()) { Feature feature = this.fe.getFeature(context, stream); - Type range = feature.getRange(); FeatureStructure next = featureStructures.iterator().next(); - if (next instanceof AnnotationFS && !next.getType().equals(annotation.getType())) { - feature = this.fe.getFeature(new MatchContext((AnnotationFS) next, context.getElement(), - context.getRuleMatch(), context.getDirection()), stream); + if (feature instanceof LazyFeature) { + LazyFeature lazyFeature = (LazyFeature) feature; + feature = lazyFeature.initialize(next); } + Type range = feature.getRange(); +// if (next instanceof AnnotationFS && !next.getType().equals(annotation.getType())) { +// feature = this.fe.getFeature(new MatchContext((AnnotationFS) next, context.getElement(), +// context.getRuleMatch(), context.getDirection()), stream); +// } if (CAS.TYPE_NAME_BYTE.equals(range.getName())) { result = next.getByteValue(feature); } else if (CAS.TYPE_NAME_DOUBLE.equals(range.getName())) { Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java Wed Jan 16 11:45:02 2019 @@ -34,6 +34,7 @@ import org.apache.uima.cas.IntArrayFS; import org.apache.uima.cas.text.AnnotationFS; import org.apache.uima.ruta.RutaStream; import org.apache.uima.ruta.expression.feature.FeatureExpression; +import org.apache.uima.ruta.expression.feature.LazyFeature; import org.apache.uima.ruta.rule.MatchContext; /** @@ -64,9 +65,13 @@ public class NumberListFeatureExpression List<Number> result = new ArrayList<>(); for (FeatureStructure each : featureStructures) { - if (each instanceof AnnotationFS && !each.getType().equals(annotation.getType())) { - feature = this.fe.getFeature(new MatchContext((AnnotationFS) each, context.getElement(), - context.getRuleMatch(), context.getDirection()), stream); +// if (each instanceof AnnotationFS && !each.getType().equals(annotation.getType())) { +// feature = this.fe.getFeature(new MatchContext((AnnotationFS) each, context.getElement(), +// context.getRuleMatch(), context.getDirection()), stream); +// } + if (feature instanceof LazyFeature) { + LazyFeature lazyFeature = (LazyFeature) feature; + feature = lazyFeature.initialize(each); } FeatureStructure featureValue = each.getFeatureValue(feature); if (featureValue instanceof IntArrayFS) { Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/ComposedStringExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/ComposedStringExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/ComposedStringExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/ComposedStringExpression.java Wed Jan 16 11:45:02 2019 @@ -26,15 +26,22 @@ import org.apache.uima.ruta.rule.MatchCo public class ComposedStringExpression extends LiteralStringExpression { - private final List<IStringExpression> epxressions; + private final List<IStringExpression> expressions; public ComposedStringExpression(List<IStringExpression> expressions) { super(); - this.epxressions = expressions; + this.expressions = expressions; } @Override public String getStringValue(MatchContext context, RutaStream stream) { + if (expressions == null) { + return null; + } + if (expressions.size() == 1) { + IStringExpression stringExpression = expressions.get(0); + return stringExpression.getStringValue(context, stream); + } StringBuilder result = new StringBuilder(); for (IStringExpression each : getExpressions()) { result.append(each.getStringValue(context, stream)); @@ -43,7 +50,7 @@ public class ComposedStringExpression ex } public List<IStringExpression> getExpressions() { - return epxressions; + return expressions; } } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/RemoveFunction.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/RemoveFunction.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/RemoveFunction.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/RemoveFunction.java Wed Jan 16 11:45:02 2019 @@ -44,9 +44,11 @@ public class RemoveFunction extends Stri String value = parent.getEnvironment().getVariableValue(var, String.class, stream); for (IStringExpression each : list) { String string = each.getStringValue(context, stream); - String[] split = value.split(string); - for (String r : split) { - result.append(r); + if (string != null) { + String[] split = value.split(string); + for (String r : split) { + result.append(r); + } } } return result.toString(); Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java Wed Jan 16 11:45:02 2019 @@ -28,6 +28,7 @@ import org.apache.uima.cas.text.Annotati import org.apache.uima.ruta.RutaStream; import org.apache.uima.ruta.expression.feature.CoveredTextFeature; import org.apache.uima.ruta.expression.feature.FeatureExpression; +import org.apache.uima.ruta.expression.feature.LazyFeature; import org.apache.uima.ruta.rule.MatchContext; public class StringFeatureExpression extends AbstractStringExpression { @@ -35,6 +36,7 @@ public class StringFeatureExpression ext private FeatureExpression fe; public StringFeatureExpression(FeatureExpression fe) { + super(); this.fe = fe; } @@ -49,9 +51,13 @@ public class StringFeatureExpression ext false, context, stream); if (!featureStructures.isEmpty()) { FeatureStructure next = featureStructures.iterator().next(); - if (next instanceof AnnotationFS && !next.getType().equals(annotation.getType())) { - feature = this.fe.getFeature(new MatchContext((AnnotationFS) next, context.getElement(), - context.getRuleMatch(), context.getDirection()), stream); + // if (next instanceof AnnotationFS && !next.getType().equals(annotation.getType())) { + // feature = this.fe.getFeature(new MatchContext((AnnotationFS) next, context.getElement(), + // context.getRuleMatch(), context.getDirection()), stream); + // } + if (feature instanceof LazyFeature) { + LazyFeature lazyFeature = (LazyFeature) feature; + feature = lazyFeature.initialize(next); } if (next instanceof AnnotationFS && feature instanceof CoveredTextFeature) { return ((AnnotationFS) next).getCoveredText(); Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java Wed Jan 16 11:45:02 2019 @@ -32,6 +32,7 @@ import org.apache.uima.cas.StringArrayFS import org.apache.uima.cas.text.AnnotationFS; import org.apache.uima.ruta.RutaStream; import org.apache.uima.ruta.expression.feature.FeatureExpression; +import org.apache.uima.ruta.expression.feature.LazyFeature; import org.apache.uima.ruta.rule.MatchContext; /** @@ -63,9 +64,13 @@ public class StringListFeatureExpression List<String> result = new ArrayList<>(); for (FeatureStructure each : featureStructures) { - if (each instanceof AnnotationFS && !each.getType().equals(annotation.getType())) { - feature = this.fe.getFeature(new MatchContext((AnnotationFS) each, context.getElement(), - context.getRuleMatch(), context.getDirection()), stream); +// if (each instanceof AnnotationFS && !each.getType().equals(annotation.getType())) { +// feature = this.fe.getFeature(new MatchContext((AnnotationFS) each, context.getElement(), +// context.getRuleMatch(), context.getDirection()), stream); +// } + if (feature instanceof LazyFeature) { + LazyFeature lazyFeature = (LazyFeature) feature; + feature = lazyFeature.initialize(each); } FeatureStructure featureValue = each.getFeatureValue(feature); if (featureValue instanceof StringArrayFS) { Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/ITypeListExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/ITypeListExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/ITypeListExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/ITypeListExpression.java Wed Jan 16 11:45:02 2019 @@ -23,10 +23,11 @@ import java.util.List; import org.apache.uima.cas.Type; import org.apache.uima.ruta.RutaStream; +import org.apache.uima.ruta.expression.string.IStringExpression; import org.apache.uima.ruta.rule.MatchContext; -public interface ITypeListExpression { - +public interface ITypeListExpression extends IStringExpression { + List<Type> getTypeList(MatchContext context, RutaStream stream); - + } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/SimpleTypeExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/SimpleTypeExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/SimpleTypeExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/SimpleTypeExpression.java Wed Jan 16 11:45:02 2019 @@ -45,7 +45,8 @@ public class SimpleTypeExpression extend RutaBlock parent = context.getParent(); Type type = parent.getEnvironment().getType(typeString); if (type == null) { - throw new IllegalArgumentException("Not able to resolve type: " + typeString); + throw new IllegalArgumentException("Not able to resolve type: " + typeString + + " in script "+context.getParent().getName()); } return type; } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeListVariableExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeListVariableExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeListVariableExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeListVariableExpression.java Wed Jan 16 11:45:02 2019 @@ -52,7 +52,8 @@ public class TypeListVariableExpression if(type != null) { result.add(type); } else { - throw new IllegalArgumentException("Not able to resolve type: " + each); + throw new IllegalArgumentException("Not able to resolve type: " + each + + " in script " +context.getParent().getName()); } } } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeVariableExpression.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeVariableExpression.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeVariableExpression.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/type/TypeVariableExpression.java Wed Jan 16 11:45:02 2019 @@ -53,9 +53,6 @@ public class TypeVariableExpression exte public Type getType(MatchContext context, RutaStream stream) { RutaBlock parent = context.getParent(); Type type = parent.getEnvironment().getVariableValue(var, Type.class, stream); - if (type == null) { - throw new IllegalArgumentException("Not able to resolve type variable: " + var); - } return type; } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/AnonymousWordList.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/AnonymousWordList.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/AnonymousWordList.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/AnonymousWordList.java Wed Jan 16 11:45:02 2019 @@ -54,12 +54,11 @@ public class AnonymousWordList implement List<AnnotationFS> result = new ArrayList<AnnotationFS>(); for (String each : list) { stream.moveToFirst(); - while (stream.isValid()) { - RutaBasic next = (RutaBasic) stream.get(); + while (stream.hasNext()) { + RutaBasic next = (RutaBasic) stream.next(); if (each.equals(next.getCoveredText())) { result.add(next); } - stream.moveToNext(); } } return result; Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/CSVTable.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/CSVTable.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/CSVTable.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/CSVTable.java Wed Jan 16 11:45:02 2019 @@ -29,6 +29,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Scanner; +import java.util.regex.Pattern; import org.apache.uima.ruta.block.RutaBlock; import org.apache.uima.ruta.engine.RutaEngine; @@ -36,18 +37,25 @@ import org.springframework.core.io.FileS import org.springframework.core.io.Resource; public class CSVTable implements RutaTable { + public static final String DEFAULT_CSV_SEPARATOR = ";"; private List<List<String>> tableData; private Map<Integer, RutaWordList> columnWordLists = new HashMap<Integer, RutaWordList>(2); + private final String separator; + /** * @param table * A CSV table. + * @param selectedSeparator + * The separator that should be used to splitup between columns in the CSV file + * * @throws IOException * When there is a problem opening, reading or closing the table. */ - public CSVTable(Resource table) throws IOException { + public CSVTable(Resource table, String selectedSeparator) throws IOException { + separator = selectedSeparator; InputStream stream = null; try { stream = table.getInputStream(); @@ -59,12 +67,13 @@ public class CSVTable implements RutaTab } } - public CSVTable(String location) throws IOException { - this(new FileSystemResource(location)); + public CSVTable(String location, String selectedSeparator) throws IOException { + this(new FileSystemResource(location), selectedSeparator); } - public CSVTable(InputStream stream) throws IOException { + public CSVTable(InputStream stream, String selectedSeparator) throws IOException { super(); + separator = selectedSeparator; buildTable(stream); } @@ -74,8 +83,11 @@ public class CSVTable implements RutaTab tableData = new ArrayList<List<String>>(); while (sc.hasNext()) { String line = sc.next().trim(); - line = line.replaceAll(";;", "; ;"); - String[] lineElements = line.split(";"); + // Quote separator to ignore special characters in regex + String quotedSeparator = Pattern.quote(separator); + // add spacer between 2 followed separators without any other characters + line = line.replaceAll(quotedSeparator + quotedSeparator, separator + " " + separator); + String[] lineElements = line.split(quotedSeparator); List<String> row = Arrays.asList(lineElements); tableData.add(row); } @@ -117,22 +129,23 @@ public class CSVTable implements RutaTab } @Override - public List<String> getRowWhere(int column, String value) { + public List<String> getRowWhere(int column, String lookupValue, boolean ignoreCase) { List<String> columnData = getColumnData(column); int i = 0; - for (String string : columnData) { - if (string.toLowerCase().equals(value.toLowerCase())) { + for (String tableValue : columnData) { + if (ignoreCase ? tableValue.equalsIgnoreCase(lookupValue) : tableValue.equals(lookupValue)) { return tableData.get(i); } i++; } i = 0; - for (String string : columnData) { - if (string.toLowerCase().replaceAll("\\s", "").equals(value.toLowerCase())) { + for (String tableValue : columnData) { + String tableValueWithoutSpacers = tableValue.replaceAll("\\s", ""); + if (ignoreCase ? tableValueWithoutSpacers.equalsIgnoreCase(lookupValue) : tableValueWithoutSpacers.equals(lookupValue)) { return tableData.get(i); } i++; } - return new ArrayList<String>(); + return new ArrayList<>(); } } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordList.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordList.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordList.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordList.java Wed Jan 16 11:45:02 2019 @@ -38,9 +38,9 @@ import java.util.Set; import org.apache.commons.io.IOUtils; import org.apache.uima.cas.CAS; -import org.apache.uima.cas.FSIterator; import org.apache.uima.cas.Feature; import org.apache.uima.cas.Type; +import org.apache.uima.cas.TypeSystem; import org.apache.uima.cas.text.AnnotationFS; import org.apache.uima.ruta.RutaStream; import org.apache.uima.ruta.type.RutaBasic; @@ -66,7 +66,9 @@ public class MultiTreeWordList implement /** * Default constructor. - * @throws IOException - should not happen but required by called constructor + * + * @throws IOException + * - should not happen but required by called constructor */ public MultiTreeWordList() throws IOException { this(new String[] {}, null); @@ -80,7 +82,7 @@ public class MultiTreeWordList implement * @param base * the relative base * @throws IOException - * When there is a problem reading pathname. + * When there is a problem reading pathname. */ public MultiTreeWordList(String pathname, File base) throws IOException { this(new FileSystemResource(pathname)); @@ -143,7 +145,8 @@ public class MultiTreeWordList implement * * @param pathnames * path of the file to create a TextWordList from - * @param base - the relative base + * @param base + * - the relative base * @throws IOException * When there is a problem reading a path. */ @@ -157,9 +160,12 @@ public class MultiTreeWordList implement } /** - * @param files - the input files - * @param base - the relative base - * @throws IOException - When there is a problem reading the files. + * @param files + * - the input files + * @param base + * - the relative base + * @throws IOException + * - When there is a problem reading the files. */ public MultiTreeWordList(List<File> files, File base) throws IOException { this.root = new MultiTextNode(); @@ -215,7 +221,8 @@ public class MultiTreeWordList implement } else if (name.endsWith(".mtwl")) { persistence.readMTWL(root, stream, "UTF-8"); } else { - throw new IllegalArgumentException("File name should end with .mtwl or .txt, found " + name); + throw new IllegalArgumentException( + "File name should end with .mtwl or .txt, found " + name); } } finally { IOUtils.closeQuietly(stream); @@ -225,8 +232,10 @@ public class MultiTreeWordList implement /** * Creates a new Tree in the existing treeWordList from a file with path pathname * - * @param stream - Input stream for the file containing the words for the treeWordList - * @param name - Associated name for the file + * @param stream + * - Input stream for the file containing the words for the treeWordList + * @param name + * - Associated name for the file * @throws IOException * When there is a problem reading the inputstream. */ @@ -573,8 +582,8 @@ public class MultiTreeWordList implement Map<String, Set<String>> resultMap = null; if (!edit) { - return recursiveContains2(root, string, 0, ignoreCase && string.length() > ignoreLength, - true, ignoreToken.toCharArray(), ignoreLength); + return recursiveContains2(root, string, 0, ignoreCase && string.length() > ignoreLength, true, + ignoreToken.toCharArray(), ignoreLength); } else { if (string.length() >= ignoreLength && ignoreCase) { resultMap = editDistance(string, (int) distance, true, ignoreToken, true); @@ -798,7 +807,7 @@ public class MultiTreeWordList implement Collection<AnnotationFS> results = new HashSet<AnnotationFS>(); stream.moveToFirst(); - FSIterator<AnnotationFS> streamPointer = stream.copy().getCurrentIt(); + RutaStream streamPointer = stream.copy(); while (stream.isValid()) { RutaBasic anchorBasic = (RutaBasic) stream.get(); @@ -823,8 +832,8 @@ public class MultiTreeWordList implement } List<String> types = null; if (!skip) { - types = containsFragment(candidate.toString(), ignoreCase, ignoreLength, edit, - distance, ignoreToken); + types = containsFragment(candidate.toString(), ignoreCase, ignoreLength, edit, distance, + ignoreToken); } if (skip || types != null) { streamPointer.moveToNext(); @@ -909,7 +918,7 @@ public class MultiTreeWordList implement int end = basicsToAdd.get(basicsToAdd.size() - 1).getEnd(); AnnotationFS newFS = stream.getCas().createAnnotation(type, begin, end); Feature feature = type.getFeatureByBaseName(featureString); - setFeatureValue(newFS, feature, value); + setFeatureValue(newFS, feature, value, stream); results.add(newFS); } } @@ -920,11 +929,14 @@ public class MultiTreeWordList implement } } - private void setFeatureValue(AnnotationFS annotationFS, Feature feature, Object o) { + private void setFeatureValue(AnnotationFS annotationFS, Feature feature, Object o, + RutaStream stream) { + TypeSystem typeSystem = stream.getCas().getTypeSystem(); if (feature != null && o != null) { Type range = feature.getRange(); String rangeName = range.getName(); - if (rangeName.equals(CAS.TYPE_NAME_STRING) && o instanceof String) { + if (typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_STRING), range) + && o instanceof String) { annotationFS.setStringValue(feature, (String) o); } else if (rangeName.equals(CAS.TYPE_NAME_INTEGER) && o instanceof Number) { annotationFS.setIntValue(feature, ((Number) o).intValue()); @@ -940,12 +952,13 @@ public class MultiTreeWordList implement annotationFS.setLongValue(feature, ((Number) o).longValue()); } else if (rangeName.equals(CAS.TYPE_NAME_BOOLEAN) && o instanceof Boolean) { annotationFS.setBooleanValue(feature, (Boolean) o); - } else if (rangeName.equals(CAS.TYPE_NAME_STRING) & o instanceof Type) { + } else if (typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_STRING), range) + & o instanceof Type) { annotationFS.setStringValue(feature, ((Type) o).getName()); } } else { - throw new IllegalArgumentException("Not able to assign feature value: " + o + " -> " - + feature); + throw new IllegalArgumentException( + "Not able to assign feature value: " + o + " -> " + feature); } } @@ -953,8 +966,10 @@ public class MultiTreeWordList implement * Returns a map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. * - * @param query - The query string. - * @param distance - The specified edit distance. + * @param query + * - The query string. + * @param distance + * - The specified edit distance. * @return A map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. */ @@ -966,10 +981,14 @@ public class MultiTreeWordList implement * Returns a map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. * - * @param query - The query string. - * @param distance - The specified edit distance. - * @param ignoreCase - Indicates whether we search case sensitive or not. - * @param ignoreToken - Indicates the characters to ignore + * @param query + * - The query string. + * @param distance + * - The specified edit distance. + * @param ignoreCase + * - Indicates whether we search case sensitive or not. + * @param ignoreToken + * - Indicates the characters to ignore * @return A map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. */ @@ -982,11 +1001,16 @@ public class MultiTreeWordList implement * Returns a map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. * - * @param query - The query string. - * @param distance - The specified edit distance. - * @param ignoreCase - Indicates whether we search case sensitive or not. - * @param ignoreToken - the characters to ignore - * @param fragment - Indicates whether we search for fragments of the query string or not. + * @param query + * - The query string. + * @param distance + * - The specified edit distance. + * @param ignoreCase + * - Indicates whether we search case sensitive or not. + * @param ignoreToken + * - the characters to ignore + * @param fragment + * - Indicates whether we search for fragments of the query string or not. * @return A map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. */ @@ -1013,7 +1037,8 @@ public class MultiTreeWordList implement result = editDistanceClever(root, query.toLowerCase(), "", distance, 0, true, fragment, edcm, false, false); } else { - result = editDistanceClever(root, query, "", distance, 0, false, fragment, edcm, false, false); + result = editDistanceClever(root, query, "", distance, 0, false, fragment, edcm, false, + false); } // Restoring of the old insert costs. @@ -1028,16 +1053,26 @@ public class MultiTreeWordList implement * Returns a map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. * - * @param node - The MultiTextNode which is under consideration at the moment. - * @param query - The query string. - * @param result - The result which matched until now. - * @param distance - The remaining edit distance. - * @param index - The index of the query string at the moment. - * @param ignoreCase - Indicates whether we search case sensitive or not. - * @param fragment - Indicates whether we search for fragments of the query string or not. - * @param edm - The edit distance cost map we are using. - * @param lastActionInsert - Indicates whether the last action was an insert action. - * @param lastActionDelete - Indicates whether the last action was a delete action. + * @param node + * - The MultiTextNode which is under consideration at the moment. + * @param query + * - The query string. + * @param result + * - The result which matched until now. + * @param distance + * - The remaining edit distance. + * @param index + * - The index of the query string at the moment. + * @param ignoreCase + * - Indicates whether we search case sensitive or not. + * @param fragment + * - Indicates whether we search for fragments of the query string or not. + * @param edm + * - The edit distance cost map we are using. + * @param lastActionInsert + * - Indicates whether the last action was an insert action. + * @param lastActionDelete + * - Indicates whether the last action was a delete action. * @return A map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. */ @@ -1094,8 +1129,8 @@ public class MultiTreeWordList implement if (index < query.length()) { if (ignoreCase) { - if (Character.toLowerCase(tempNode.getValue()) == Character.toLowerCase(query - .charAt(index))) { + if (Character.toLowerCase(tempNode.getValue()) == Character + .toLowerCase(query.charAt(index))) { resultMap.putAll(editDistanceClever(tempNode, query, result + tempNode.getValue(), distance, index + 1, ignoreCase, fragment, edm, false, false)); } @@ -1110,9 +1145,9 @@ public class MultiTreeWordList implement if (distance - edm.getReplaceCosts(node.getValue(), tempNode.getValue()) >= 0) { // Substitute. - resultMap.putAll(editDistanceClever(tempNode, query, result + tempNode.getValue(), distance - - edm.getReplaceCosts(node.getValue(), tempNode.getValue()), index + 1, ignoreCase, - fragment, edm, false, false)); + resultMap.putAll(editDistanceClever(tempNode, query, result + tempNode.getValue(), + distance - edm.getReplaceCosts(node.getValue(), tempNode.getValue()), index + 1, + ignoreCase, fragment, edm, false, false)); } if (!lastActionDelete) { @@ -1131,19 +1166,27 @@ public class MultiTreeWordList implement /** * Checks if a string is contained by the MultiTreeWordList. * - * @param node - The MultiTextNode which is under consideration at the moment. - * @param query - The query string. - * @param result - The result which matched until now. - * @param distance - The remaining edit distance. - * @param index - The index of the query string at the moment. - * @param ignoreCase - Indicates whether we search case sensitive or not. - * @param fragment - Indicates whether we search for fragments of the query string or not. - * @param edm - The edit distance cost map we are using. + * @param node + * - The MultiTextNode which is under consideration at the moment. + * @param query + * - The query string. + * @param result + * - The result which matched until now. + * @param distance + * - The remaining edit distance. + * @param index + * - The index of the query string at the moment. + * @param ignoreCase + * - Indicates whether we search case sensitive or not. + * @param fragment + * - Indicates whether we search for fragments of the query string or not. + * @param edm + * - The edit distance cost map we are using. * @return A map with all strings with a specified edit distance to the string query as keys and * the files they belong to as values. */ - private boolean editDistanceBool(MultiTextNode node, String query, String result, - double distance, int index, boolean ignoreCase, boolean fragment, EditDistanceCostMap edm) { + private boolean editDistanceBool(MultiTextNode node, String query, String result, double distance, + int index, boolean ignoreCase, boolean fragment, EditDistanceCostMap edm) { boolean deletion = false; boolean insertion = false; @@ -1188,8 +1231,8 @@ public class MultiTreeWordList implement if (index < query.length()) { if (ignoreCase) { - if (Character.toLowerCase(tempNode.getValue()) == Character.toLowerCase(query - .charAt(index))) { + if (Character.toLowerCase(tempNode.getValue()) == Character + .toLowerCase(query.charAt(index))) { noop = editDistanceBool(tempNode, query, result + tempNode.getValue(), distance, index + 1, ignoreCase, fragment, edm); } @@ -1208,9 +1251,9 @@ public class MultiTreeWordList implement if (distance - edm.getReplaceCosts(node.getValue(), tempNode.getValue()) >= 0) { // Substitute. - substitution = editDistanceBool(tempNode, query, result + tempNode.getValue(), distance - - edm.getReplaceCosts(node.getValue(), tempNode.getValue()), index + 1, ignoreCase, - fragment, edm); + substitution = editDistanceBool(tempNode, query, result + tempNode.getValue(), + distance - edm.getReplaceCosts(node.getValue(), tempNode.getValue()), index + 1, + ignoreCase, fragment, edm); if (substitution) { return true; @@ -1233,7 +1276,6 @@ public class MultiTreeWordList implement return false; } - @Override public int hashCode() { final int prime = 31; Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordListPersistence.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordListPersistence.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordListPersistence.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/MultiTreeWordListPersistence.java Wed Jan 16 11:45:02 2019 @@ -32,10 +32,9 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; +import org.apache.uima.ruta.utils.XmlUtils; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; @@ -90,18 +89,16 @@ public class MultiTreeWordListPersistenc } InputStreamReader streamReader = new InputStreamReader(is, encoding); TrieXMLEventHandler handler = new TrieXMLEventHandler(root); - SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); - SAXParser saxParser = saxParserFactory.newSAXParser(); + SAXParser saxParser = XmlUtils.createSaxParser(); XMLReader reader = saxParser.getXMLReader(); - // was: - // XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setFeature("http://xml.org/sax/features/external-general-entities", false); + reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",false); reader.setContentHandler(handler); reader.setErrorHandler(handler); reader.parse(new InputSource(streamReader)); } catch (SAXException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); + throw new IllegalStateException(e); } } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/RutaTable.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/RutaTable.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/RutaTable.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/RutaTable.java Wed Jan 16 11:45:02 2019 @@ -29,6 +29,6 @@ public interface RutaTable { String getEntry(int row, int column); - List<String> getRowWhere(int column, String value); + List<String> getRowWhere(int column, String value, boolean ignoreCase); } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/TreeWordList.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/TreeWordList.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/TreeWordList.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/resource/TreeWordList.java Wed Jan 16 11:45:02 2019 @@ -36,21 +36,18 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; import org.apache.commons.lang3.StringEscapeUtils; -import org.apache.uima.cas.FSIterator; import org.apache.uima.cas.text.AnnotationFS; import org.apache.uima.jcas.tcas.Annotation; import org.apache.uima.ruta.RutaStream; import org.apache.uima.ruta.type.RutaBasic; +import org.apache.uima.ruta.utils.XmlUtils; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; public class TreeWordList implements RutaWordList { @@ -70,10 +67,14 @@ public class TreeWordList implements Rut /** * Constructs a TreeWordList from a resource. * - * @param resource - Resource to create a TextWordList from - * @param dictRemoveWS - option to remove whitespaces fromt he resource - * @throws IOException - when there is a problem reading the resource - * @throws IllegalArgumentException - for an invalid name or file ending + * @param resource + * - Resource to create a TextWordList from + * @param dictRemoveWS + * - option to remove whitespaces fromt he resource + * @throws IOException + * - when there is a problem reading the resource + * @throws IllegalArgumentException + * - for an invalid name or file ending */ public TreeWordList(Resource resource, boolean dictRemoveWS) throws IOException { this.dictRemoveWS = dictRemoveWS; @@ -102,9 +103,12 @@ public class TreeWordList implements Rut /** * Constructs a TreeWordList from a file with path = filename * - * @param pathname - path of the file to create a TextWordList from - * @param dictRemoveWS - remove whitespaces - * @throws IOException - when there is a problem reading the pathname + * @param pathname + * - path of the file to create a TextWordList from + * @param dictRemoveWS + * - remove whitespaces + * @throws IOException + * - when there is a problem reading the pathname */ public TreeWordList(String pathname, boolean dictRemoveWS) throws IOException { this(new FileSystemResource(pathname), dictRemoveWS); @@ -115,9 +119,12 @@ public class TreeWordList implements Rut * * @param stream * path of the file to create a TextWordList from - * @param name - the name of the resource in the stream - * @param dictRemoveWS - remove whitespaces - * @throws IOException - when there is a problem reading the stream + * @param name + * - the name of the resource in the stream + * @param dictRemoveWS + * - remove whitespaces + * @throws IOException + * - when there is a problem reading the stream */ public TreeWordList(InputStream stream, String name, boolean dictRemoveWS) throws IOException { this.dictRemoveWS = dictRemoveWS; @@ -149,7 +156,8 @@ public class TreeWordList implements Rut * @param stream * Open InputStream containing the word for the treeWordList, this method will close the * stream. - * @throws IOException - when there is a problem reading the stream + * @throws IOException + * - when there is a problem reading the stream */ public void buildNewTree(InputStream stream) throws IOException { Scanner scan = new Scanner(stream, "UTF-8"); @@ -266,9 +274,11 @@ public class TreeWordList implements Rut maxIgnoreChars, ignoreWS); } else { result |= recursiveContains(childNodeL, text, next, ignoreCase, fragment, ignoreChars, - maxIgnoreChars, ignoreWS) - | recursiveContains(childNodeU, text, next, ignoreCase, fragment, ignoreChars, - maxIgnoreChars, ignoreWS); + maxIgnoreChars, ignoreWS); + if (childNodeL != childNodeU) { // Do not go into the same tree. + result |= recursiveContains(childNodeU, text, next, ignoreCase, fragment, ignoreChars, + maxIgnoreChars, ignoreWS); + } } } else { TextNode wsNode = pointer.getChildNode(' '); @@ -310,7 +320,7 @@ public class TreeWordList implements Rut char[] ignoreChars, int maxIgnoredChars, boolean ignoreWS) { ArrayList<AnnotationFS> results = new ArrayList<AnnotationFS>(); stream.moveToFirst(); - FSIterator<AnnotationFS> streamPointer = stream.copy().getCurrentIt(); + RutaStream streamPointer = stream.copy(); while (stream.isValid()) { RutaBasic anchorBasic = (RutaBasic) stream.get(); streamPointer.moveTo(anchorBasic); @@ -352,7 +362,8 @@ public class TreeWordList implements Rut return results; } - public List<AnnotationFS> find(RutaStream stream, boolean ignoreCase, int size, boolean ignoreWS) { + public List<AnnotationFS> find(RutaStream stream, boolean ignoreCase, int size, + boolean ignoreWS) { return find(stream, ignoreCase, size, null, 0, ignoreWS); } @@ -362,8 +373,8 @@ public class TreeWordList implements Rut if (basicsToAdd.size() >= 1 && contains(lastCandidate, ignoreCase, size, ignoreChars, maxIgnoredChars, ignoreWS)) { - results.add(new Annotation(stream.getJCas(), basicsToAdd.get(0).getBegin(), basicsToAdd.get( - basicsToAdd.size() - 1).getEnd())); + results.add(new Annotation(stream.getJCas(), basicsToAdd.get(0).getBegin(), + basicsToAdd.get(basicsToAdd.size() - 1).getEnd())); } else if (interResult != null) { results.add(interResult); } @@ -380,25 +391,16 @@ public class TreeWordList implements Rut InputStreamReader streamReader = new InputStreamReader(is, encoding); this.root = new TextNode(); XMLEventHandler handler = new XMLEventHandler(root); - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser parser = factory.newSAXParser(); + SAXParser parser = XmlUtils.createSaxParser(); XMLReader reader = parser.getXMLReader(); - // XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setFeature("http://xml.org/sax/features/external-general-entities", false); + reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); reader.setContentHandler(handler); reader.setErrorHandler(handler); reader.parse(new InputSource(streamReader)); - } catch (SAXParseException spe) { - StringBuffer sb = new StringBuffer(spe.toString()); - sb.append("\n Line number: " + spe.getLineNumber()); - sb.append("\n Column number: " + spe.getColumnNumber()); - sb.append("\n Public ID: " + spe.getPublicId()); - sb.append("\n System ID: " + spe.getSystemId() + "\n"); - System.out.println(sb.toString()); - } catch (SAXException se) { - System.out.println("loadDOM threw " + se); - se.printStackTrace(System.out); - } catch (ParserConfigurationException e) { - e.printStackTrace(); + } catch (SAXException e) { + throw new IllegalStateException(e); } } @@ -451,8 +453,8 @@ public class TreeWordList implements Rut public void writeNode(Writer writer, TextNode node) throws IOException { String value = StringEscapeUtils.escapeXml11(String.valueOf(node.getValue())); - String output = "<node char=\"" + value + "\" isWordEnd=\"" - + Boolean.toString(node.isWordEnd()) + "\">"; + String output = "<node char=\"" + value + "\" isWordEnd=\"" + Boolean.toString(node.isWordEnd()) + + "\">"; writer.write(output); for (TextNode child : node.getChildren().values()) { writeNode(writer, child); @@ -467,8 +469,8 @@ public class TreeWordList implements Rut } @Override - public List<AnnotationFS> find(RutaStream stream, Map<String, Object> typeMap, - boolean ignoreCase, int ignoreLength, boolean edit, double distance, String ignoreToken) { + public List<AnnotationFS> find(RutaStream stream, Map<String, Object> typeMap, boolean ignoreCase, + int ignoreLength, boolean edit, double distance, String ignoreToken) { return null; } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/AbstractRuleElement.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/AbstractRuleElement.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/AbstractRuleElement.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/AbstractRuleElement.java Wed Jan 16 11:45:02 2019 @@ -54,9 +54,9 @@ public abstract class AbstractRuleElemen @SuppressWarnings("unchecked") protected final InferenceCrowd emptyCrowd = new InferenceCrowd(Collections.EMPTY_LIST); - protected List<RutaStatement> inlinedConditionRules; + protected List<List<RutaStatement>> inlinedConditionRuleBlocks = new ArrayList<>(); - protected List<RutaStatement> inlinedActionRules; + protected List<List<RutaStatement>> inlinedActionRuleBlocks = new ArrayList<>(); public AbstractRuleElement(RuleElementQuantifier quantifier, List<AbstractRutaCondition> conditions, List<AbstractRutaAction> actions, @@ -81,7 +81,7 @@ public abstract class AbstractRuleElemen protected void doneMatching(RuleMatch ruleMatch, RuleApply ruleApply, RutaStream stream, InferenceCrowd crowd) { if (!ruleMatch.isApplied()) { - ruleApply.add(ruleMatch); + ruleApply.add(ruleMatch, stream); if (ruleMatch.matchedCompletely()) { ruleMatch.getRule().getRoot().applyRuleElements(ruleMatch, stream, crowd); } @@ -89,25 +89,25 @@ public abstract class AbstractRuleElemen } } - protected List<ScriptApply> processInlinedActionRules(RuleMatch ruleMatch, RutaStream stream, + protected List<List<ScriptApply>> processInlinedActionRules(RuleMatch ruleMatch, RutaStream stream, InferenceCrowd crowd) { - if (inlinedActionRules != null && !inlinedActionRules.isEmpty()) { - return processInlinedRules(inlinedActionRules, ruleMatch, stream, crowd); + if (inlinedActionRuleBlocks != null && !inlinedActionRuleBlocks.isEmpty()) { + return processInlinedRules(inlinedActionRuleBlocks, ruleMatch, stream, crowd); } return null; } - protected List<ScriptApply> processInlinedConditionRules(RuleMatch ruleMatch, RutaStream stream, + protected List<List<ScriptApply>> processInlinedConditionRules(RuleMatch ruleMatch, RutaStream stream, InferenceCrowd crowd) { - if (inlinedConditionRules != null && !inlinedConditionRules.isEmpty()) { - return processInlinedRules(inlinedConditionRules, ruleMatch, stream, crowd); + if (inlinedConditionRuleBlocks != null && !inlinedConditionRuleBlocks.isEmpty()) { + return processInlinedRules(inlinedConditionRuleBlocks, ruleMatch, stream, crowd); } return null; } - protected List<ScriptApply> processInlinedRules(List<RutaStatement> inlinedRules, + protected List<List<ScriptApply>> processInlinedRules(List<List<RutaStatement>> inlinedRuleBlocks, RuleMatch ruleMatch, RutaStream stream, InferenceCrowd crowd) { - List<ScriptApply> result = new ArrayList<ScriptApply>(); + List<List<ScriptApply>> result = new ArrayList<>(); List<AnnotationFS> matchedAnnotationsOf = ruleMatch.getMatchedAnnotationsOfElement(this); // TODO where to implement the explanation of inlined rules? // BlockApply blockApply = new BlockApply(this); @@ -116,11 +116,15 @@ public abstract class AbstractRuleElemen // ruleMatch.addDelegateApply(this, blockApply); for (AnnotationFS annotationFS : matchedAnnotationsOf) { RutaStream windowStream = stream.getWindowStream(annotationFS, annotationFS.getType()); - for (RutaStatement each : inlinedRules) { - ScriptApply apply = each.apply(windowStream, crowd); - // blockApply.add(apply); - ruleMatch.addDelegateApply(this, apply); - result.add(apply); + for (List<RutaStatement> inlinedRules : inlinedRuleBlocks) { + List<ScriptApply> blockResult = new ArrayList<>(); + for (RutaStatement each : inlinedRules) { + ScriptApply apply = each.apply(windowStream, crowd); + // blockApply.add(apply); + ruleMatch.addDelegateApply(this, apply); + blockResult.add(apply); + } + result.add(blockResult); } } return result; @@ -137,20 +141,29 @@ public abstract class AbstractRuleElemen } protected boolean matchInnerRules(RuleMatch ruleMatch, RutaStream stream, InferenceCrowd crowd) { - boolean inlinedRulesMatched = true; - List<ScriptApply> list = processInlinedConditionRules(ruleMatch, stream, crowd); - if (list != null) { - inlinedRulesMatched = false; - for (ScriptApply scriptApply : list) { - if (scriptApply instanceof RuleApply) { - RuleApply ra = (RuleApply) scriptApply; - if (ra.applied > 0) { - inlinedRulesMatched = true; - } + + List<List<ScriptApply>> blockResults = processInlinedConditionRules(ruleMatch, stream, crowd); + if (blockResults == null) { + return true; + } + + boolean matched = true; + for (List<ScriptApply> list : blockResults) { + matched &= atLeastOneRuleMatched(list); + } + return matched; + } + + private boolean atLeastOneRuleMatched(List<ScriptApply> list) { + for (ScriptApply scriptApply : list) { + if (scriptApply instanceof RuleApply) { + RuleApply ra = (RuleApply) scriptApply; + if (ra.applied > 0) { + return true; } } } - return inlinedRulesMatched; + return false; } protected List<RuleElementMatch> getMatch(RuleMatch ruleMatch, @@ -210,7 +223,12 @@ public abstract class AbstractRuleElemen return false; } - private boolean isAlreadyCovered(AnnotationFS eachAnchor, RuleApply ruleApply, RutaStream stream) { + private boolean isAlreadyCovered(AnnotationFS eachAnchor, RuleApply ruleApply, + RutaStream stream) { + if (eachAnchor == null) { + return false; + } + List<AbstractRuleMatch<? extends AbstractRule>> list = ruleApply.getList(); Collections.reverse(list); for (AbstractRuleMatch<? extends AbstractRule> each : list) { @@ -304,23 +322,23 @@ public abstract class AbstractRuleElemen } @Override - public void setInlinedConditionRules(List<RutaStatement> innerRules) { - this.inlinedConditionRules = innerRules; + public void addInlinedConditionRules(List<RutaStatement> innerRules) { + this.inlinedConditionRuleBlocks.add(innerRules); } @Override - public List<RutaStatement> getInlinedConditionRules() { - return inlinedConditionRules; + public List<List<RutaStatement>> getInlinedConditionRuleBlocks() { + return inlinedConditionRuleBlocks; } @Override - public void setInlinedActionRules(List<RutaStatement> innerRules) { - this.inlinedActionRules = innerRules; + public void addInlinedActionRules(List<RutaStatement> innerRules) { + this.inlinedActionRuleBlocks.add(innerRules); } @Override - public List<RutaStatement> getInlinedActionRules() { - return inlinedActionRules; + public List<List<RutaStatement>> getInlinedActionRuleBlocks() { + return inlinedActionRuleBlocks; } } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElement.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElement.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElement.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElement.java Wed Jan 16 11:45:02 2019 @@ -32,6 +32,7 @@ import java.util.TreeMap; import org.apache.uima.cas.text.AnnotationFS; import org.apache.uima.jcas.JCas; +import org.apache.uima.ruta.RutaEnvironment; import org.apache.uima.ruta.RutaStream; import org.apache.uima.ruta.action.AbstractRutaAction; import org.apache.uima.ruta.block.RutaBlock; @@ -552,7 +553,8 @@ public class ComposedRuleElement extends begin, end); MatchContext context = new MatchContext(annotation, this, ruleMatch, after); - context.getParent().getEnvironment().addMatchToVariable(ruleMatch, this, context, stream); + RutaEnvironment environment = context.getParent().getEnvironment(); + environment.addMatchToVariable(ruleMatch, this, context, stream); List<EvaluatedCondition> evaluatedConditions = new ArrayList<EvaluatedCondition>( conditions.size()); @@ -567,8 +569,13 @@ public class ComposedRuleElement extends } match.setConditionInfo(evaluatedConditions); match.evaluateInnerMatches(true, stream); - boolean inlinedRulesMatched = matchInnerRules(ruleMatch, stream, crowd); - match.setInlinedRulesMatched(inlinedRulesMatched); + if (match.matched()) { + boolean inlinedRulesMatched = matchInnerRules(ruleMatch, stream, crowd); + match.setInlinedRulesMatched(inlinedRulesMatched); + } else { + // update label for failed match after evaluating conditions + environment.addAnnotationsToVariable(null, getLabel(), context); + } } @Override Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElementMatch.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElementMatch.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElementMatch.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ComposedRuleElementMatch.java Wed Jan 16 11:45:02 2019 @@ -29,6 +29,7 @@ import java.util.TreeMap; import java.util.TreeSet; import org.apache.uima.cas.text.AnnotationFS; +import org.apache.uima.ruta.RutaProcessRuntimeException; import org.apache.uima.ruta.RutaStream; public class ComposedRuleElementMatch extends RuleElementMatch { @@ -79,6 +80,11 @@ public class ComposedRuleElementMatch ex innerMatches.put(ruleElement, list); } list.add(ruleElementMatch); + + if (list.size() > stream.getMaxRuleElementMatches()) { + throw new RutaProcessRuntimeException("Rule element exceeded the allowed amount of matches (" + + stream.getMaxRuleElementMatches() + "): " + ruleElement.toString()); + } evaluateInnerMatches(included, stream); enforceUpdate(); } Modified: uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ConjunctRulesRuleElement.java URL: http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ConjunctRulesRuleElement.java?rev=1851430&r1=1851429&r2=1851430&view=diff ============================================================================== --- uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ConjunctRulesRuleElement.java (original) +++ uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/ConjunctRulesRuleElement.java Wed Jan 16 11:45:02 2019 @@ -58,10 +58,10 @@ public class ConjunctRulesRuleElement ex } } allMatched &= oneMatched; - + // only the matches that actually matched successfully for (RuleMatch eachRuleMatch : startMatch) { - if(eachRuleMatch.matched()) { + if (eachRuleMatch.matched()) { result.add(eachRuleMatch); } } @@ -70,7 +70,7 @@ public class ConjunctRulesRuleElement ex for (RuleMatch each : result) { if (!each.isApplied()) { each.setMatched(allMatched); - ruleApply.add(each); + ruleApply.add(each, stream); if (each.matched() && allMatched) { each.getRule().getRoot().applyRuleElements(each, stream, crowd); }