You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by pk...@apache.org on 2016/01/05 15:32:30 UTC

svn commit: r1723085 - in /uima/ruta/trunk/ruta-core/src: main/java/org/apache/uima/ruta/engine/ main/java/org/apache/uima/ruta/expression/feature/ main/java/org/apache/uima/ruta/rule/ test/java/org/apache/uima/ruta/expression/annotation/

Author: pkluegl
Date: Tue Jan  5 14:32:30 2016
New Revision: 1723085

URL: http://svn.apache.org/viewvc?rev=1723085&view=rev
Log:
UIMA-4399
- matching on fsarrays

Modified:
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaTypeMatcher.java
    uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpressionTest.java

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java?rev=1723085&r1=1723084&r2=1723085&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java Tue Jan  5 14:32:30 2016
@@ -257,6 +257,14 @@ public class RutaTestUtils {
     return cas;
   }
 
+  public static void printAnnotations(CAS cas, int typeId) {
+    Type t = getTestType(cas, typeId);
+    AnnotationIndex<AnnotationFS> ai = cas.getAnnotationIndex(t);
+    for (AnnotationFS annotationFS : ai) {
+      System.out.println(annotationFS.getCoveredText());
+    }
+  }
+  
   /**
    * Helper for common assertion in JUnit tests
    * 

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java?rev=1723085&r1=1723084&r2=1723085&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/SimpleFeatureExpression.java Tue Jan  5 14:32:30 2016
@@ -29,6 +29,7 @@ import org.apache.uima.cas.Feature;
 import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.Type;
 import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.jcas.cas.FSArray;
 import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.UIMAConstants;
 import org.apache.uima.ruta.expression.IRutaExpression;
@@ -86,6 +87,9 @@ public class SimpleFeatureExpression ext
       if (StringUtils.equals(each, UIMAConstants.FEATURE_COVERED_TEXT)) {
         // there is no explicit feature for coveredText
         feature = null;
+      } else if(type.isArray()) {
+        // lazy check of range
+        feature = null;
       } else {
         feature = type.getFeatureByBaseName(each);
         if (feature == null) {
@@ -126,55 +130,89 @@ public class SimpleFeatureExpression ext
 
   public Collection<AnnotationFS> getFeatureAnnotations(Collection<AnnotationFS> annotations,
           RutaStream stream, MatchContext context, boolean checkOnFeatureValue) {
+
     Collection<AnnotationFS> result = new TreeSet<AnnotationFS>(comparator);
     List<Feature> features = getFeatures(context, stream);
+    collectFeatureAnnotations(annotations, features, checkOnFeatureValue, result, stream, context);
+    return result;
+  }
 
-    for (AnnotationFS eachBase : annotations) {
-      AnnotationFS afs = eachBase;
-      if (features != null) {
-        for (Feature feature : features) {
-          if (afs == null) {
-            break;
-          }
-          if (feature == null || feature.getRange().isPrimitive()) {
-            // feature == null -> this is the coveredText "feature"
-            if (this instanceof FeatureMatchExpression) {
-              FeatureMatchExpression fme = (FeatureMatchExpression) this;
-              if (checkOnFeatureValue) {
-                if (fme.checkFeatureValue(afs, context, feature, stream)) {
-                  result.add(afs);
-                }
-              } else {
-                result.add(afs);
-              }
-              break;
-            } else {
-              result.add(afs);
-            }
-          } else {
-            FeatureStructure value = afs.getFeatureValue(feature);
-            if (value instanceof AnnotationFS) {
-              afs = (AnnotationFS) value;
-            } else if (value != null) {
-              throw new IllegalArgumentException(value.getType()
-                      + " is not supported in a feature match expression (" + mr.getMatch() + ").");
-            }
+  private void collectFeatureAnnotations(Collection<AnnotationFS> annotations,
+          List<Feature> features, boolean checkOnFeatureValue, Collection<AnnotationFS> result,
+          RutaStream stream, MatchContext context) {
+    for (AnnotationFS each : annotations) {
+      collectFeatureAnnotations(each, features, checkOnFeatureValue, result, stream, context);
+    }
+  }
+
+  private void collectFeatureAnnotations(AnnotationFS annotation, List<Feature> features,
+          boolean checkOnFeatureValue, Collection<AnnotationFS> result, RutaStream stream,
+          MatchContext context) {
+    if (annotation == null) {
+      return;
+    }
+
+    Feature currentFeature = null;
+    List<Feature> tail = null;
+
+    if (features != null && !features.isEmpty()) {
+      currentFeature = features.get(0);
+      tail = features.subList(1, features.size());
+    }
+
+    if (currentFeature == null || currentFeature.getRange().isPrimitive()) {
+      // feature == null -> this is the coveredText "feature"
+      if (this instanceof FeatureMatchExpression) {
+        FeatureMatchExpression fme = (FeatureMatchExpression) this;
+        if (checkOnFeatureValue) {
+          if (fme.checkFeatureValue(annotation, context, currentFeature, stream)) {
+            result.add(annotation);
           }
+        } else {
+          result.add(annotation);
         }
+      } else {
+        result.add(annotation);
       }
-      if (!(this instanceof FeatureMatchExpression)) {
-        if (stream.isVisible(afs, true)) {
-          result.add(afs);
+    } else {
+      collectFeatureAnnotations(annotation, currentFeature, tail, checkOnFeatureValue, result, stream, context);
+    }
+  }
+
+  private void collectFeatureAnnotations(AnnotationFS annotation, Feature currentFeature,
+          List<Feature> tail, boolean checkOnFeatureValue, Collection<AnnotationFS> result,
+          RutaStream stream, MatchContext context) {
+    // stop early for match expressions
+    if (this instanceof FeatureMatchExpression && (tail== null || tail.isEmpty())) {
+      FeatureMatchExpression fme = (FeatureMatchExpression) this;
+      if (checkOnFeatureValue) {
+        if (fme.checkFeatureValue(annotation, context, currentFeature, stream)) {
+          result.add(annotation);
         }
       } else {
-        // exploit expression for null assignments
-        IRutaExpression arg = ((FeatureMatchExpression) this).getArg();
-        if (arg instanceof NullExpression) {
-          result.addAll(annotations);
+        result.add(annotation);
+      }
+      return;
+    }
+    
+    FeatureStructure value = annotation.getFeatureValue(currentFeature);
+    if (value instanceof AnnotationFS) {
+      AnnotationFS next = (AnnotationFS) value;
+      collectFeatureAnnotations(next, tail, checkOnFeatureValue, result, stream, context);
+    } else if (value instanceof FSArray) {
+      FSArray array = (FSArray) value;
+      for (int i = 0; i < array.size(); i++) {
+        // TODO: also feature structures or only annotations?
+        FeatureStructure fs = array.get(i);
+        if (fs instanceof AnnotationFS) {
+          AnnotationFS next = (AnnotationFS) fs;
+          collectFeatureAnnotations(next, tail, checkOnFeatureValue, result, stream, context);
         }
       }
+    } else if (value != null) {
+      throw new IllegalArgumentException(value.getType()
+              + " is not supported in a feature match expression (" + mr.getMatch() + ").");
     }
-    return result;
   }
 
   public MatchReference getMatchReference() {

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaTypeMatcher.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaTypeMatcher.java?rev=1723085&r1=1723084&r2=1723085&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaTypeMatcher.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaTypeMatcher.java Tue Jan  5 14:32:30 2016
@@ -79,8 +79,7 @@ public class RutaTypeMatcher implements
         annotations.addAll(stream.getAnnotations(type));
       }
     }
-    MatchContext context = new MatchContext(null, null, true);
-    context.setParent(parent);
+    MatchContext context = new MatchContext(parent);
     if (featureExpression != null) {
       return featureExpression
               .getFeatureAnnotations(annotations, stream, context, CHECK_ON_FEATURE);
@@ -249,6 +248,9 @@ public class RutaTypeMatcher implements
       if (checkFeatureValue) {
         return true;
       }
+    } else if(feature == null || feature.getRange().isArray()) {
+      // do not check on arrays
+      return true;
     } else {
       TypeSystem typeSystem = stream.getCas().getTypeSystem();
       boolean subsumes = typeSystem.subsumes(feature.getRange(), annotation.getType());

Modified: uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpressionTest.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpressionTest.java?rev=1723085&r1=1723084&r2=1723085&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpressionTest.java (original)
+++ uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpressionTest.java Tue Jan  5 14:32:30 2016
@@ -32,47 +32,48 @@ import org.junit.Test;
 
 public class AnnotationFeatureExpressionTest {
 
-//  @Test
-//  public void testList() {
-//    String document = "Some text.";
-//    String script = "";
-//    script += "W{-> CREATE(Inner, \"a\"=W)};";
-//    script += "Document{-> CREATE(Struct, \"as\"=W)};";
-//    script += "Struct.as{->T1};";
-//    script += "Struct.as.a{->T2};";
-//    script += "Struct.as{->T3} @PERIOD;";
-//    script += "Struct.as.a{->T4} @PERIOD;";
-//
-//    Map<String, String> typeMap = new TreeMap<String, String>();
-//    String typeName1 = "Struct";
-//    typeMap.put(typeName1, "uima.tcas.Annotation");
-//    String typeName2 = "Inner";
-//    typeMap.put(typeName2, "uima.tcas.Annotation");
-//
-//    Map<String, List<TestFeature>> featureMap = new TreeMap<String, List<TestFeature>>();
-//    List<TestFeature> list = new ArrayList<RutaTestUtils.TestFeature>();
-//    featureMap.put(typeName1, list);
-//    String fn1 = "as";
-//    list.add(new TestFeature(fn1, "", "uima.cas.FSArray"));
-//    list = new ArrayList<RutaTestUtils.TestFeature>();
-//    featureMap.put(typeName2, list);
-//    String fn2 = "a";
-//    list.add(new TestFeature(fn2, "", "uima.cas.FSArray"));
-//
-//    CAS cas = null;
-//    try {
-//      cas = RutaTestUtils.getCAS(document, typeMap, featureMap);
-//      Ruta.apply(cas, script);
-//    } catch (Exception e) {
-//      e.printStackTrace();
-//    }
-//
-//    RutaTestUtils.assertAnnotationsEquals(cas, 1, 2, "Some", "text");
-//    RutaTestUtils.assertAnnotationsEquals(cas, 2, 2, "Some", "text");
-//    RutaTestUtils.assertAnnotationsEquals(cas, 3, 2, "Some", "text");
-//    RutaTestUtils.assertAnnotationsEquals(cas, 4, 2, "Some", "text");
-//
-//    
-//  }
+  @Test
+  public void testList() {
+    String document = "Some text.";
+    String script = "";
+    script += "W{-> CREATE(Inner, \"a\"=W)};";
+    script += "Document{-> CREATE(Struct, \"as\"=W)};";
+    script += "Struct.as{->T1};";
+    script += "Struct.as.a{->T2};";
+    script += "Struct{-> TRIM(PERIOD)};";
+    script += "Struct.as{->T3} @PERIOD;";
+    script += "Struct.as.a{->T4} @PERIOD;";
+
+    Map<String, String> typeMap = new TreeMap<String, String>();
+    String typeName1 = "Struct";
+    typeMap.put(typeName1, "uima.tcas.Annotation");
+    String typeName2 = "Inner";
+    typeMap.put(typeName2, "uima.tcas.Annotation");
+
+    Map<String, List<TestFeature>> featureMap = new TreeMap<String, List<TestFeature>>();
+    List<TestFeature> list = new ArrayList<RutaTestUtils.TestFeature>();
+    featureMap.put(typeName1, list);
+    String fn1 = "as";
+    list.add(new TestFeature(fn1, "", "uima.cas.FSArray"));
+    list = new ArrayList<RutaTestUtils.TestFeature>();
+    featureMap.put(typeName2, list);
+    String fn2 = "a";
+    list.add(new TestFeature(fn2, "", "uima.cas.FSArray"));
+
+    CAS cas = null;
+    try {
+      cas = RutaTestUtils.getCAS(document, typeMap, featureMap);
+      Ruta.apply(cas, script);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+
+    RutaTestUtils.assertAnnotationsEquals(cas, 1, 2, "Some", "text");
+    RutaTestUtils.assertAnnotationsEquals(cas, 2, 2, "Some", "text");
+    RutaTestUtils.assertAnnotationsEquals(cas, 3, 2, "Some", "text");
+    RutaTestUtils.assertAnnotationsEquals(cas, 4, 2, "Some", "text");
+
+    
+  }
   
 }