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/09/29 15:01:06 UTC

svn commit: r1762792 - in /uima/ruta/trunk/ruta-core/src: main/java/org/apache/uima/ruta/ main/java/org/apache/uima/ruta/action/ main/java/org/apache/uima/ruta/condition/ main/java/org/apache/uima/ruta/expression/ main/java/org/apache/uima/ruta/express...

Author: pkluegl
Date: Thu Sep 29 15:01:06 2016
New Revision: 1762792

URL: http://svn.apache.org/viewvc?rev=1762792&view=rev
Log:
UIMA-5108
- support feature structures in annotation and feature expressions

Added:
    uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/feature/
    uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/feature/FeatureStructureTest.java   (with props)
Modified:
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/action/ImplicitFeatureAction.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/condition/ImplicitCondition.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/AnnotationTypeExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/NullExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AbstractAnnotationExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationAddressExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationListVariableIndexExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationVariableExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/IAnnotationExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanListFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/GenericFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.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/expression/number/NumberFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java
    uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.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/RutaStream.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java Thu Sep 29 15:01:06 2016
@@ -951,7 +951,7 @@ public class RutaStream extends FSIterat
     return result.toString();
   }
 
-  public void assignFeatureValues(AnnotationFS annotation,
+  public void assignFeatureValues(FeatureStructure annotation,
           Map<IStringExpression, IRutaExpression> map, MatchContext context) {
     Type type = annotation.getType();
     Set<Entry<IStringExpression, IRutaExpression>> entrySet = map.entrySet();
@@ -964,20 +964,21 @@ public class RutaStream extends FSIterat
     }
   }
 
-  public void assignFeatureValue(AnnotationFS annotation, Feature feature, IRutaExpression value,
+  public void assignFeatureValue(FeatureStructure annotation, Feature feature, IRutaExpression value,
           MatchContext context) {
     if (feature == null) {
       throw new IllegalArgumentException("Not able to assign feature value (e.g., coveredText).");
     }
     CAS cas = annotation.getCAS();
-    String range = feature.getRange().getName();
-    if (range.equals(UIMAConstants.TYPE_STRING)) {
+    Type range = feature.getRange();
+    String rangeName = range.getName();
+    if (rangeName.equals(UIMAConstants.TYPE_STRING)) {
       if (value instanceof IStringExpression) {
         IStringExpression stringExpr = (IStringExpression) value;
         String string = stringExpr.getStringValue(context, this);
         annotation.setStringValue(feature, string);
       }
-    } else if (range.equals(UIMAConstants.TYPE_STRINGARRAY)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_STRINGARRAY)) {
       if (value instanceof IStringListExpression) {
         IStringListExpression stringListExpr = (IStringListExpression) value;
         List<String> stringList = stringListExpr.getStringList(context, this);
@@ -989,20 +990,20 @@ public class RutaStream extends FSIterat
         StringArrayFS array = FSCollectionFactory.createStringArray(cas, new String[] { string });
         annotation.setFeatureValue(feature, array);
       }
-    } else if (range.equals(UIMAConstants.TYPE_INTEGER) || range.equals(UIMAConstants.TYPE_LONG)
-            || range.equals(UIMAConstants.TYPE_SHORT) || range.equals(UIMAConstants.TYPE_BYTE)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_INTEGER) || rangeName.equals(UIMAConstants.TYPE_LONG)
+            || rangeName.equals(UIMAConstants.TYPE_SHORT) || rangeName.equals(UIMAConstants.TYPE_BYTE)) {
       if (value instanceof INumberExpression) {
         INumberExpression numberExpr = (INumberExpression) value;
         int v = numberExpr.getIntegerValue(context, this);
-        if (StringUtils.equals(feature.getShortName(), CAS.FEATURE_BASE_NAME_BEGIN)) {
-          changeBegin(annotation, v, context.getRuleMatch());
-        } else if(StringUtils.equals(feature.getShortName(), CAS.FEATURE_BASE_NAME_END)) {
-          changeEnd(annotation, v, context.getRuleMatch());
+        if (annotation instanceof AnnotationFS && StringUtils.equals(feature.getShortName(), CAS.FEATURE_BASE_NAME_BEGIN)) {
+          changeBegin((AnnotationFS) annotation, v, context.getRuleMatch());
+        } else if(annotation instanceof AnnotationFS && StringUtils.equals(feature.getShortName(), CAS.FEATURE_BASE_NAME_END)) {
+          changeEnd((AnnotationFS) annotation, v, context.getRuleMatch());
         } else {
           annotation.setIntValue(feature, v);
         }
       }
-    } else if (range.equals(UIMAConstants.TYPE_INTARRAY)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_INTARRAY)) {
       if (value instanceof INumberExpression) {
         INumberExpression numberExpr = (INumberExpression) value;
         int v = numberExpr.getIntegerValue(context, this);
@@ -1014,13 +1015,13 @@ public class RutaStream extends FSIterat
         IntArrayFS array = FSCollectionFactory.createIntArray(cas, RutaListUtils.toIntArray(list));
         annotation.setFeatureValue(feature, array);
       }
-    } else if (range.equals(UIMAConstants.TYPE_DOUBLE)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_DOUBLE)) {
       if (value instanceof INumberExpression) {
         INumberExpression numberExpr = (INumberExpression) value;
         double v = numberExpr.getDoubleValue(context, this);
         annotation.setDoubleValue(feature, v);
       }
-    } else if (range.equals(UIMAConstants.TYPE_DOUBLEARRAY)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_DOUBLEARRAY)) {
       if (value instanceof INumberExpression) {
         INumberExpression numberExpr = (INumberExpression) value;
         double v = numberExpr.getDoubleValue(context, this);
@@ -1033,13 +1034,13 @@ public class RutaStream extends FSIterat
                 RutaListUtils.toDoubleArray(list));
         annotation.setFeatureValue(feature, array);
       }
-    } else if (range.equals(UIMAConstants.TYPE_FLOAT)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_FLOAT)) {
       if (value instanceof INumberExpression) {
         INumberExpression numberExpr = (INumberExpression) value;
         float v = numberExpr.getFloatValue(context, this);
         annotation.setFloatValue(feature, v);
       }
-    } else if (range.equals(UIMAConstants.TYPE_FLOATARRAY)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_FLOATARRAY)) {
       if (value instanceof INumberExpression) {
         INumberExpression numberExpr = (INumberExpression) value;
         float v = numberExpr.getFloatValue(context, this);
@@ -1052,13 +1053,13 @@ public class RutaStream extends FSIterat
                 RutaListUtils.toFloatArray(list));
         annotation.setFeatureValue(feature, array);
       }
-    } else if (range.equals(UIMAConstants.TYPE_BOOLEAN)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_BOOLEAN)) {
       if (value instanceof IBooleanExpression) {
         IBooleanExpression expr = (IBooleanExpression) value;
         Boolean v = expr.getBooleanValue(context, this);
         annotation.setBooleanValue(feature, v);
       }
-    } else if (range.equals(UIMAConstants.TYPE_BOOLEANARRAY)) {
+    } else if (rangeName.equals(UIMAConstants.TYPE_BOOLEANARRAY)) {
       if (value instanceof IBooleanListExpression) {
         IBooleanListExpression expr = (IBooleanListExpression) value;
         List<Boolean> list = expr.getBooleanList(context, this);
@@ -1070,31 +1071,37 @@ public class RutaStream extends FSIterat
         BooleanArrayFS array = FSCollectionFactory.createBooleanArray(cas, new boolean[] { v });
         annotation.setFeatureValue(feature, array);
       }
-    } else if (value instanceof AnnotationTypeExpression && !feature.getRange().isPrimitive()) {
+    } else if (value instanceof AnnotationTypeExpression && !range.isPrimitive()) {
       AnnotationTypeExpression ate = (AnnotationTypeExpression) value;
-      if (feature.getRange().isArray()) {
+      if (range.isArray()) {
         List<AnnotationFS> annotations = ate.getAnnotationList(context, this);
         annotation.setFeatureValue(feature, UIMAUtils.toFSArray(this.getJCas(), annotations));
       } else {
         AnnotationFS a = ate.getAnnotation(context, this);
         annotation.setFeatureValue(feature, a);
       }
-    } else if (value instanceof IAnnotationExpression && !feature.getRange().isPrimitive()) {
+    } else if (value instanceof IAnnotationExpression && !range.isPrimitive()) {
       IAnnotationExpression ae = (IAnnotationExpression) value;
-      AnnotationFS a = ae.getAnnotation(context, this);
-      // TODO support annotation list expressions
-      if (feature.getRange().isArray()) {
-        List<AnnotationFS> c = new ArrayList<AnnotationFS>();
+      boolean rangeSubsumesAnnotation = cas.getTypeSystem().subsumes(cas.getAnnotationType(), range);
+      
+      FeatureStructure a = null;
+      if(rangeSubsumesAnnotation) {
+        a = ae.getAnnotation(context, this);
+      } else {
+        a = ae.getFeatureStructure(context, this);
+      }
+      if (range.isArray()) {
+        List<FeatureStructure> c = new ArrayList<>();
         c.add(a);
         annotation.setFeatureValue(feature, UIMAUtils.toFSArray(this.getJCas(), c));
       } else {
         annotation.setFeatureValue(feature, a);
       }
-    } else if (value instanceof IAnnotationListExpression && !feature.getRange().isPrimitive()) {
+    } else if (value instanceof IAnnotationListExpression && !range.isPrimitive()) {
       IAnnotationListExpression ale = (IAnnotationListExpression) value;
       List<AnnotationFS> annotations = ale.getAnnotationList(context, this);
       if (annotations != null) {
-        if (feature.getRange().isArray()) {
+        if (range.isArray()) {
           annotation.setFeatureValue(feature, UIMAUtils.toFSArray(this.getJCas(), annotations));
         } else {
           if (annotations.isEmpty()) {
@@ -1106,30 +1113,32 @@ public class RutaStream extends FSIterat
       } else {
         annotation.setFeatureValue(feature, null);
       }
-    } else if (value instanceof ITypeExpression && !feature.getRange().isPrimitive()) {
+    } else if (value instanceof ITypeExpression && !range.isPrimitive()) {
       ITypeExpression typeExpr = (ITypeExpression) value;
       Type t = typeExpr.getType(context, this);
       assignAnnotationByTypeInWindow(annotation, feature, context, t);
-    } else if (value instanceof GenericFeatureExpression && !feature.getRange().isPrimitive()) {
+    } else if (value instanceof GenericFeatureExpression && !range.isPrimitive()) {
       FeatureExpression fe = ((GenericFeatureExpression) value).getFeatureExpression();
       Type t = fe.getInitialType(context, this);
       List<AnnotationFS> inWindow = this.getAnnotationsInWindow(context.getAnnotation(), t);
       if (fe instanceof SimpleFeatureExpression) {
         SimpleFeatureExpression sfe = (SimpleFeatureExpression) fe;
-        List<AnnotationFS> featureAnnotations = inWindow;
+        List<? extends FeatureStructure> featureAnnotations = null;
         if (fe.getFeatures(context, this) != null) {
-          featureAnnotations = new ArrayList<AnnotationFS>(
-                  sfe.getAnnotations(inWindow, false, context, this));
+          featureAnnotations = new ArrayList<>(
+                  sfe.getFeatureStructures(inWindow, false, context, this));
+        } else {
+          featureAnnotations = inWindow;
         }
-        if (feature.getRange().isArray()) {
+        if (range.isArray()) {
           annotation.setFeatureValue(feature,
                   UIMAUtils.toFSArray(this.getJCas(), featureAnnotations));
         } else if (!featureAnnotations.isEmpty()) {
-          AnnotationFS a = featureAnnotations.get(0);
+          FeatureStructure a = featureAnnotations.get(0);
           annotation.setFeatureValue(feature, a);
         }
       } else {
-        if (feature.getRange().isArray()) {
+        if (range.isArray()) {
           annotation.setFeatureValue(feature, UIMAUtils.toFSArray(this.getJCas(), inWindow));
         } else {
           AnnotationFS a = inWindow.get(0);
@@ -1139,7 +1148,7 @@ public class RutaStream extends FSIterat
     }
   }
 
-  private void assignAnnotationByTypeInWindow(AnnotationFS annotation, Feature feature,
+  private void assignAnnotationByTypeInWindow(FeatureStructure annotation, Feature feature,
           MatchContext context, Type type) {
 
     List<AnnotationFS> inWindow = this.getAnnotationsInWindow(context.getAnnotation(), type);

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/action/ImplicitFeatureAction.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/action/ImplicitFeatureAction.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/action/ImplicitFeatureAction.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/action/ImplicitFeatureAction.java Thu Sep 29 15:01:06 2016
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.TreeSet;
 
 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.ruta.RutaStream;
@@ -75,7 +76,7 @@ public class ImplicitFeatureAction exten
     for (AnnotationFS each : annotations) {
       stream.getCas().removeFsFromIndexes(each);
     }
-    Collection<? extends AnnotationFS> featureAnnotations = expr.getAnnotations(annotations, false,
+    Collection<? extends FeatureStructure> featureAnnotations = expr.getFeatureStructures(annotations, false,
             context, stream);
     if (featureAnnotations.isEmpty()) {
       // null value in feature, but we require the host
@@ -83,7 +84,7 @@ public class ImplicitFeatureAction exten
     }
     Feature feature = expr.getFeature(context, stream);
     IRutaExpression arg = expr.getArg();
-    for (AnnotationFS each : featureAnnotations) {
+    for (FeatureStructure each : featureAnnotations) {
       stream.assignFeatureValue(each, feature, arg, context);
     }
     for (AnnotationFS each : annotations) {

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/condition/ImplicitCondition.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/condition/ImplicitCondition.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/condition/ImplicitCondition.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/condition/ImplicitCondition.java Thu Sep 29 15:01:06 2016
@@ -24,6 +24,7 @@ import java.util.Collection;
 import java.util.List;
 
 import org.apache.commons.collections.CollectionUtils;
+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;
@@ -70,7 +71,7 @@ public class ImplicitCondition extends A
       } else if(annotationExpr!=null) {
         annotations.add(annotationExpr.getAnnotation(context, stream));
       }
-      Collection<? extends AnnotationFS> featureAnnotations = fme.getAnnotations(annotations, true,
+      Collection<? extends FeatureStructure> featureAnnotations = fme.getFeatureStructures(annotations, true,
               context, stream);
       return new EvaluatedCondition(this, !featureAnnotations.isEmpty());
     }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/AnnotationTypeExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/AnnotationTypeExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/AnnotationTypeExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/AnnotationTypeExpression.java Thu Sep 29 15:01:06 2016
@@ -23,6 +23,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.Type;
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.ruta.RutaStream;
@@ -98,6 +99,15 @@ public class AnnotationTypeExpression ex
   }
 
   @Override
+  public FeatureStructure getFeatureStructure(MatchContext context, RutaStream stream) {
+    if (annotationExpression != null) {
+      return annotationExpression.getFeatureStructure(context, stream);
+    }
+    return getAnnotation(context, stream);
+  }
+  
+  
+  @Override
   public Type getType(MatchContext context, RutaStream stream) {
     if (!initialized) {
       initialize(context, stream);

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/NullExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/NullExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/NullExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/NullExpression.java Thu Sep 29 15:01:06 2016
@@ -82,5 +82,10 @@ public class NullExpression extends Feat
     return null;
   }
 
+  @Override
+  public FeatureStructure getFeatureStructure(MatchContext context, RutaStream stream) {
+    return null;
+  }
+
  
 }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AbstractAnnotationExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AbstractAnnotationExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AbstractAnnotationExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AbstractAnnotationExpression.java Thu Sep 29 15:01:06 2016
@@ -19,6 +19,7 @@
 
 package org.apache.uima.ruta.expression.annotation;
 
+import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.expression.RutaExpression;
@@ -27,6 +28,11 @@ import org.apache.uima.ruta.rule.MatchCo
 public abstract class AbstractAnnotationExpression extends RutaExpression implements IAnnotationExpression {
 
   @Override
+  public FeatureStructure getFeatureStructure(MatchContext context, RutaStream stream) {
+    return getAnnotation(context, stream);
+  }
+  
+  @Override
   public String getStringValue(MatchContext context, RutaStream stream) {
     AnnotationFS annotation = getAnnotation(context, stream);
     if(annotation != null) {

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationAddressExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationAddressExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationAddressExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationAddressExpression.java Thu Sep 29 15:01:06 2016
@@ -27,40 +27,43 @@ import org.apache.uima.cas.text.Annotati
 import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.rule.MatchContext;
 
-
 /**
- *  An expression referring to an annotation identified by its address.  
+ * An expression referring to an annotation identified by its address.
  *
  */
 public class AnnotationAddressExpression extends AbstractAnnotationExpression {
 
   private String address;
-  
+
   public AnnotationAddressExpression(String address) {
     super();
     this.address = address;
   }
-  
-  
+
   @Override
   public AnnotationFS getAnnotation(MatchContext context, RutaStream stream) {
+    FeatureStructure featureStructure = getFeatureStructure(context, stream);
+    if(featureStructure instanceof AnnotationFS) {
+      return (AnnotationFS) featureStructure;
+    }
+    return null;
+  }
+
+  @Override
+  public FeatureStructure getFeatureStructure(MatchContext context, RutaStream stream) {
     Integer ref = Integer.valueOf(address);
     CAS cas = stream.getCas();
-    if(cas instanceof CASImpl) {
+    if (cas instanceof CASImpl) {
       CASImpl casImpl = (CASImpl) cas;
       LowLevelCAS lowLevelCAS = casImpl.getLowLevelCAS();
       FeatureStructure fs = lowLevelCAS.ll_getFSForRef(ref);
-      if(fs instanceof AnnotationFS) {
-        return (AnnotationFS) fs;
-      }
+      return fs;
     }
     return null;
   }
 
-
   public String getAddress() {
     return address;
   }
-  
 
 }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -22,6 +22,7 @@ package org.apache.uima.ruta.expression.
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.expression.feature.FeatureExpression;
@@ -39,20 +40,30 @@ public class AnnotationFeatureExpression
     super();
     this.fe = fe;
   }
-  
+
   @Override
   public AnnotationFS getAnnotation(MatchContext context, RutaStream stream) {
-    AnnotationFS annotation = context.getAnnotation();
-    List<AnnotationFS> list = getTargetAnnotation(annotation, fe, context, stream);
+    List<AnnotationFS> list = getTargetAnnotation(context.getAnnotation(), fe, context, stream);
     Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
             stream);
     if (!featureAnnotations.isEmpty()) {
       AnnotationFS next = featureAnnotations.iterator().next();
-        return next;
+      return next;
     }
     return null;
   }
 
+  @Override
+  public FeatureStructure getFeatureStructure(MatchContext context, RutaStream stream) {
+    List<AnnotationFS> list = getTargetAnnotation(context.getAnnotation(), fe, context, stream);
+    Collection<? extends FeatureStructure> featureAnnotations = fe.getFeatureStructures(list, false,
+            context, stream);
+    if (!featureAnnotations.isEmpty()) {
+      FeatureStructure next = featureAnnotations.iterator().next();
+      return next;
+    }
+    return null;
+  }
 
   public FeatureExpression getFeatureExpression() {
     return fe;
@@ -62,6 +73,4 @@ public class AnnotationFeatureExpression
     this.fe = fe;
   }
 
-  
-
 }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationListVariableIndexExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationListVariableIndexExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationListVariableIndexExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationListVariableIndexExpression.java Thu Sep 29 15:01:06 2016
@@ -32,28 +32,27 @@ import org.apache.uima.ruta.rule.MatchCo
  */
 public class AnnotationListVariableIndexExpression extends AbstractAnnotationExpression {
 
-private String var;
+  private String var;
+
   private int index;
-  
+
   public AnnotationListVariableIndexExpression(String var, int index) {
     super();
     this.var = var;
     this.index = index;
   }
-  
-  
+
   @Override
   public AnnotationFS getAnnotation(MatchContext context, RutaStream stream) {
     RutaBlock parent = context.getParent();
     @SuppressWarnings("unchecked")
     List<AnnotationFS> list = parent.getEnvironment().getVariableValue(var, List.class, stream);
-    if(list != null && index >= 0 && index < list.size()) {
+    if (list != null && index >= 0 && index < list.size()) {
       return list.get(index);
     }
     return null;
   }
 
-
   public String getVar() {
     return var;
   }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationVariableExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationVariableExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationVariableExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/AnnotationVariableExpression.java Thu Sep 29 15:01:06 2016
@@ -54,5 +54,6 @@ private String var;
   public String toString() {
     return var;
   }
+ 
   
 }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/IAnnotationExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/IAnnotationExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/IAnnotationExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/annotation/IAnnotationExpression.java Thu Sep 29 15:01:06 2016
@@ -19,6 +19,7 @@
 
 package org.apache.uima.ruta.expression.annotation;
 
+import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.expression.string.IStringExpression;
@@ -32,5 +33,7 @@ import org.apache.uima.ruta.rule.MatchCo
 public interface IAnnotationExpression extends IStringExpression {
 
   AnnotationFS getAnnotation(MatchContext context, RutaStream stream);
+  
+  FeatureStructure getFeatureStructure(MatchContext context, RutaStream stream);
 
 }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.List;
 
 import org.apache.uima.cas.Feature;
+import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.expression.feature.FeatureExpression;
@@ -42,10 +43,10 @@ public class BooleanFeatureExpression ex
     AnnotationFS annotation = context.getAnnotation();
     Feature feature = fe.getFeature(context, stream);
     List<AnnotationFS> list = getTargetAnnotation(annotation, fe, context, stream);
-    Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
+    Collection<? extends FeatureStructure> featureStructures = fe.getFeatureStructures(list, false, context,
             stream);
-    if (!featureAnnotations.isEmpty()) {
-      AnnotationFS next = featureAnnotations.iterator().next();
+    if (!featureStructures.isEmpty()) {
+      FeatureStructure next = featureStructures.iterator().next();
       return next.getBooleanValue(feature);
     }
     return false;

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanListFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanListFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanListFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/bool/BooleanListFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -56,11 +56,11 @@ public class BooleanListFeatureExpressio
       return Collections.emptyList();
     }
     List<AnnotationFS> list = getTargetAnnotation(annotation, fe, context, stream);
-    Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
+    Collection<? extends FeatureStructure> featureStructures = fe.getFeatureStructures(list, false, context,
             stream);
     List<Boolean> result = new ArrayList<>();
 
-    for (AnnotationFS each : featureAnnotations) {
+    for (FeatureStructure each : featureStructures) {
       FeatureStructure featureValue = each.getFeatureValue(feature);
       if(featureValue instanceof BooleanArrayFS) {
         BooleanArrayFS array = (BooleanArrayFS) featureValue;

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/FeatureMatchExpression.java Thu Sep 29 15:01:06 2016
@@ -130,7 +130,7 @@ public class FeatureMatchExpression exte
       FeatureExpression fe = (FeatureExpression) getArg();
       List<FeatureStructure> list = new ArrayList<>(1);
       list.add(fs);
-      Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
+      Collection<? extends FeatureStructure> featureAnnotations = fe.getFeatureStructures(list, false, context,
               stream);
       return compare(fs.getFeatureValue(feature), featureAnnotations);
     }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/GenericFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/GenericFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/GenericFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/GenericFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.commons.lang3.StringUtils;
 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.ruta.RutaStream;
@@ -118,6 +119,15 @@ public class GenericFeatureExpression ex
   }
 
   @Override
+  public FeatureStructure getFeatureStructure(MatchContext context, RutaStream stream) {
+    if (annotationExpression == null) {
+      annotationExpression = ExpressionFactory.createAnnotationFeatureExpression(featureExpression);
+    }
+    return annotationExpression.getFeatureStructure(context, stream);
+  }
+  
+  
+  @Override
   public Type getType(MatchContext context, RutaStream stream) {
     // special case where an argument is interpreted as a type expression
     return featureExpression.getInitialType(context, stream);
@@ -187,6 +197,5 @@ public class GenericFeatureExpression ex
     return result;
   }
 
-  
 
 }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/feature/LazyFeature.java Thu Sep 29 15:01:06 2016
@@ -25,26 +25,32 @@ import org.apache.uima.cas.Type;
 public class LazyFeature implements Feature {
 
   private Feature delegate;
-  
+
   private String featureName;
-  
+
+  private String initializedWith;
+
   public LazyFeature(String featureName) {
     super();
     this.featureName = featureName;
   }
-  
-  public Feature initialize(Type type) {
-   delegate = type.getFeatureByBaseName(featureName);
-   if(delegate == null) {
-     return this;
-   }
-   return delegate;
-  }
-  
+
   public Feature initialize(FeatureStructure featureStructure) {
     return initialize(featureStructure.getType());
-   }
-  
+  }
+
+  public Feature initialize(Type type) {
+    if (type == null) {
+      return this;
+    }
+    delegate = type.getFeatureByBaseName(featureName);
+    initializedWith = type.getName();
+    if (delegate == null) {
+      return this;
+    }
+    return delegate;
+  }
+
   @Override
   public int compareTo(Feature o) {
     checkDelegate();
@@ -86,10 +92,11 @@ 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.");
+    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);
     }
-    
+
   }
 
 }

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=1762792&r1=1762791&r2=1762792&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 Thu Sep 29 15:01:06 2016
@@ -183,7 +183,9 @@ public class SimpleFeatureExpression ext
       return;
     }
     if (!collectOnlyAnnotations) {
-      lastValidFeatureStructure = (T) featureStructure;
+      if(!featureStructure.getType().isArray()) {
+        lastValidFeatureStructure = (T) featureStructure;
+      }
     } else if (featureStructure instanceof AnnotationFS) {
       lastValidFeatureStructure = (T) featureStructure;
     }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.List;
 
 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.ruta.RutaStream;
@@ -61,12 +62,12 @@ public class NumberFeatureExpression ext
     AnnotationFS annotation = context.getAnnotation();
     Number result = null;
     List<AnnotationFS> list = getTargetAnnotation(annotation, fe, context, stream);
-    Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
+    Collection<? extends FeatureStructure> featureStructures = fe.getFeatureStructures(list, false, context,
             stream);
-    if (!featureAnnotations.isEmpty()) {
+    if (!featureStructures.isEmpty()) {
       Feature feature = fe.getFeature(context, stream);
       Type range = feature.getRange();
-      AnnotationFS next = featureAnnotations.iterator().next();
+      FeatureStructure next = featureStructures.iterator().next();
       if (UIMAConstants.TYPE_BYTE.equals(range.getName())) {
         result = next.getByteValue(feature);
       } else if (UIMAConstants.TYPE_DOUBLE.equals(range.getName())) {

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/number/NumberListFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -58,11 +58,11 @@ public class NumberListFeatureExpression
       return Collections.emptyList();
     }
     List<AnnotationFS> list = getTargetAnnotation(annotation, fe, context, stream);
-    Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
+    Collection<? extends FeatureStructure> featureStructures = fe.getFeatureStructures(list, false, context,
             stream);
     List<Number> result = new ArrayList<>();
 
-    for (AnnotationFS each : featureAnnotations) {
+    for (FeatureStructure each : featureStructures) {
       FeatureStructure featureValue = each.getFeatureValue(feature);
       if (featureValue instanceof IntArrayFS) {
         IntArrayFS array = (IntArrayFS) featureValue;

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.List;
 
 import org.apache.uima.cas.Feature;
+import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.expression.feature.CoveredTextFeature;
@@ -43,12 +44,11 @@ public class StringFeatureExpression ext
     AnnotationFS annotation = context.getAnnotation();
     Feature feature = fe.getFeature(context, stream);
     List<AnnotationFS> list = getTargetAnnotation(annotation, fe, context, stream);
-    Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
-            stream);
-    if (!featureAnnotations.isEmpty()) {
-      AnnotationFS next = featureAnnotations.iterator().next();
-      if (feature instanceof CoveredTextFeature) {
-        return next.getCoveredText();
+    Collection<? extends FeatureStructure> featureStructures = fe.getFeatureStructures(list, false, context, stream);
+    if (!featureStructures.isEmpty()) {
+      FeatureStructure next = featureStructures.iterator().next();
+      if (next instanceof AnnotationFS && feature instanceof CoveredTextFeature) {
+        return ((AnnotationFS) next).getCoveredText();
       } else {
         return next.getStringValue(feature);
       }

Modified: uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java?rev=1762792&r1=1762791&r2=1762792&view=diff
==============================================================================
--- uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java (original)
+++ uima/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/expression/string/StringListFeatureExpression.java Thu Sep 29 15:01:06 2016
@@ -56,11 +56,11 @@ public class StringListFeatureExpression
       return Collections.emptyList();
     }
     List<AnnotationFS> list = getTargetAnnotation(annotation, fe, context, stream);
-    Collection<? extends AnnotationFS> featureAnnotations = fe.getAnnotations(list, false, context,
+    Collection<? extends FeatureStructure> featureStructures = fe.getFeatureStructures(list, false, context,
             stream);
     List<String> result = new ArrayList<>();
 
-    for (AnnotationFS each : featureAnnotations) {
+    for (FeatureStructure each : featureStructures) {
       FeatureStructure featureValue = each.getFeatureValue(feature);
       if(featureValue instanceof StringArrayFS) {
         StringArrayFS array = (StringArrayFS) featureValue;

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=1762792&r1=1762791&r2=1762792&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 Thu Sep 29 15:01:06 2016
@@ -200,6 +200,8 @@ public class AnnotationFeatureExpression
     script.append("A1.fss.fs.fs{-> T6};");
     script.append("A1.fss.fs.fs.s == \"1\"{-> T7};");
     script.append("A1.fss.fss.s == \"1\"{-> T8};");
+    script.append("a:A1 {a.fss.fss.s == \"1\" -> T9};");
+    script.append("a:A1 {a.fs.s==\"1\" -> T10};");
 
     Ruta.apply(cas, script.toString());
 
@@ -211,6 +213,8 @@ public class AnnotationFeatureExpression
     RutaTestUtils.assertAnnotationsEquals(cas, 6, 4, "Some", "Some", "text", "text");
     RutaTestUtils.assertAnnotationsEquals(cas, 7, 2, "Some", "Some");
     RutaTestUtils.assertAnnotationsEquals(cas, 8, 4, "Some", "Some", "text", "text");
+    RutaTestUtils.assertAnnotationsEquals(cas, 9, 2, "Some", "text");
+    RutaTestUtils.assertAnnotationsEquals(cas, 10, 1, "Some");
 
   }
 

Added: uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/feature/FeatureStructureTest.java
URL: http://svn.apache.org/viewvc/uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/feature/FeatureStructureTest.java?rev=1762792&view=auto
==============================================================================
--- uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/feature/FeatureStructureTest.java (added)
+++ uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/feature/FeatureStructureTest.java Thu Sep 29 15:01:06 2016
@@ -0,0 +1,109 @@
+/*
+ * 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.expression.feature;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+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.text.AnnotationFS;
+import org.apache.uima.fit.util.FSCollectionFactory;
+import org.apache.uima.jcas.cas.FSArray;
+import org.apache.uima.ruta.engine.Ruta;
+import org.apache.uima.ruta.engine.RutaTestUtils;
+import org.apache.uima.ruta.engine.RutaTestUtils.TestFeature;
+import org.junit.Test;
+
+public class FeatureStructureTest {
+
+
+  @Test
+  public void testFeatureStructureFeature() throws Exception {
+
+    String document = "Some text.";
+
+    Map<String, String> typeMap = new TreeMap<String, String>();
+    String typeName1 = "A1";
+    typeMap.put(typeName1, "uima.tcas.Annotation");
+    String typeName2 = "FS1";
+    typeMap.put(typeName2, "uima.cas.TOP");
+
+    Map<String, List<TestFeature>> featureMap = new TreeMap<String, List<TestFeature>>();
+    List<TestFeature> list = new ArrayList<RutaTestUtils.TestFeature>();
+    featureMap.put(typeName1, list);
+    String fn1 = "fss";
+    list.add(new TestFeature(fn1, "", "uima.cas.FSArray"));
+    String fn2 = "fs";
+    list.add(new TestFeature(fn2, "", "uima.cas.TOP"));
+
+    list = new ArrayList<RutaTestUtils.TestFeature>();
+    featureMap.put(typeName2, list);
+    String fn3 = "fss";
+    list.add(new TestFeature(fn3, "", "uima.cas.FSArray"));
+    String fn4 = "fs";
+    list.add(new TestFeature(fn4, "", "uima.cas.TOP"));
+    String fn5 = "s";
+    list.add(new TestFeature(fn5, "", "uima.cas.String"));
+
+    CAS cas = RutaTestUtils.getCAS(document, typeMap, featureMap);
+    Type type1 = cas.getTypeSystem().getType(typeName1);
+    Feature type1fss = type1.getFeatureByBaseName(fn1);
+    Feature type1fs = type1.getFeatureByBaseName(fn2);
+    Type type2 = cas.getTypeSystem().getType(typeName2);
+    Feature type2fss = type2.getFeatureByBaseName(fn3);
+    Feature type2fs = type2.getFeatureByBaseName(fn4);
+    Feature type2s = type2.getFeatureByBaseName(fn5);
+    AnnotationFS a1 = cas.createAnnotation(type1, 0, 4);
+    AnnotationFS a2 = cas.createAnnotation(type1, 5, 9);
+    FeatureStructure fs1 = cas.createFS(type2);
+    FeatureStructure fs2 = cas.createFS(type2);
+    FSArray fsArray1 = FSCollectionFactory.createFSArray(cas.getJCas(),
+            new FeatureStructure[] { fs1, fs2 });
+    fs1.setStringValue(type2s, "1");
+    fs2.setStringValue(type2s, "2");
+    fs1.setFeatureValue(type2fs, a2);
+    fs2.setFeatureValue(type2fs, a1);
+    fs1.setFeatureValue(type2fss, fsArray1);
+    fs2.setFeatureValue(type2fss, fsArray1);
+    a1.setFeatureValue(type1fs, fs1);
+    a1.setFeatureValue(type1fss, fsArray1);
+    a2.setFeatureValue(type1fs, fs2);
+    a2.setFeatureValue(type1fss, fsArray1);
+
+    cas.addFsToIndexes(a1);
+    cas.addFsToIndexes(a2);
+
+    StringBuilder script = new StringBuilder();
+    script.append("Document{-> A1, A1.fs = i.fs}<-{i:A1 PERIOD;};");
+    script.append("a:A1{IS(Document), a.fs.s == \"1\" -> T1};");
+    script.append("a:A1{IS(Document), a.fs.s == \"2\" -> T2};");
+    Ruta.apply(cas, script.toString());
+
+    RutaTestUtils.assertAnnotationsEquals(cas, 1, 0);
+    RutaTestUtils.assertAnnotationsEquals(cas, 2, 1, "Some text.");
+
+  }
+
+}

Propchange: uima/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/expression/feature/FeatureStructureTest.java
------------------------------------------------------------------------------
    svn:eol-style = native