Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RegExpRule.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RegExpRule.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RegExpRule.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RegExpRule.java
 Wed Jan 16 11:45:02 2019
@@ -72,6 +72,12 @@ public class RegExpRule extends Abstract
     crowd.beginVisit(this, ruleApply);
     MatchContext context = new MatchContext(getParent());
     String regexpString = regexpExpr.getStringValue(context, stream);
+
+    if (regexpString == null) {
+      crowd.endVisit(this, ruleApply);
+      return ruleApply;
+    }
+
     AnnotationFS documentAnnotation = stream.getDocumentAnnotation();
     String document = documentAnnotation.getCoveredText();
     int delta = documentAnnotation.getBegin();
@@ -93,14 +99,14 @@ public class RegExpRule extends Abstract
           createAnnotations(i, delta, begin, end, types, fa, matchResult, 
ruleMatch, stream);
         } else if (i == 0) {
           CAS cas = stream.getCas();
-          AnnotationFS afs = cas.createAnnotation(cas.getAnnotationType(), 
delta + begin, delta
-                  + end);
+          AnnotationFS afs = cas.createAnnotation(cas.getAnnotationType(), 
delta + begin,
+                  delta + end);
           ruleMatch.addMatched(0, afs);
         }
       }
       List<AnnotationFS> matchedAnnotationsOfRoot = 
ruleMatch.getMatchedAnnotationsOfRoot();
       if (matchedAnnotationsOfRoot != null && 
!matchedAnnotationsOfRoot.isEmpty()) {
-        ruleApply.add(ruleMatch);
+        ruleApply.add(ruleMatch, stream);
       }
     }
 
@@ -196,7 +202,7 @@ public class RegExpRule extends Abstract
             if (argExpr instanceof INumberExpression) {
               INumberExpression ne = (INumberExpression) argExpr;
               int cg = ne.getIntegerValue(context, stream);
-              if (range.getName().equals(CAS.TYPE_NAME_STRING)) {
+              if 
(typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_STRING), range)) {
                 String s = matchResult.group(cg);
                 afs.setStringValue(feature, s);
               } else if (range.getName().equals(CAS.TYPE_NAME_BOOLEAN)) {
@@ -224,7 +230,7 @@ public class RegExpRule extends Abstract
               }
             } else {
               if (argExpr instanceof ITypeExpression
-                      && range.getName().equals(CAS.TYPE_NAME_STRING)) {
+                      && 
typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_STRING), range)) {
                 ITypeExpression typeExpr = (ITypeExpression) argExpr;
                 List<AnnotationFS> annotationsInWindow = 
stream.getAnnotationsInWindow(afs,
                         typeExpr.getType(context, stream));
@@ -233,7 +239,7 @@ public class RegExpRule extends Abstract
                   afs.setStringValue(feature, annotation.getCoveredText());
                 }
               } else if (argExpr instanceof AbstractStringExpression
-                      && range.getName().equals(CAS.TYPE_NAME_STRING)) {
+                      && 
typeSystem.subsumes(typeSystem.getType(CAS.TYPE_NAME_STRING), range)) {
                 afs.setStringValue(feature,
                         ((AbstractStringExpression) 
argExpr).getStringValue(context, stream));
                 // numbers are reserved for capturing groups
@@ -302,7 +308,8 @@ public class RegExpRule extends Abstract
     this.regexpExpr = regexp;
   }
 
-  public void setFeatureAssignments(Map<ITypeExpression, 
Map<IStringExpression, IRutaExpression>> fa) {
+  public void setFeatureAssignments(
+          Map<ITypeExpression, Map<IStringExpression, IRutaExpression>> fa) {
     this.featureAssignments = fa;
   }
 

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleApply.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleApply.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleApply.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleApply.java
 Wed Jan 16 11:45:02 2019
@@ -22,7 +22,9 @@ package org.apache.uima.ruta.rule;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.uima.ruta.RutaProcessRuntimeException;
 import org.apache.uima.ruta.RutaStatement;
+import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.ScriptApply;
 
 public class RuleApply extends ScriptApply {
@@ -45,7 +47,7 @@ public class RuleApply extends ScriptApp
     return list;
   }
 
-  public void add(AbstractRuleMatch<? extends AbstractRule> match) {
+  public void add(AbstractRuleMatch<? extends AbstractRule> match, RutaStream 
stream) {
     if (match.matchedCompletely()) {
       applied++;
     }
@@ -53,6 +55,10 @@ public class RuleApply extends ScriptApp
     if (acceptMatches) {
       list.add(match);
     }
+    if (tried > stream.getMaxRuleMatches()) {
+      throw new RutaProcessRuntimeException("Rule exceeded the allowed amount 
of matches ("
+              + stream.getMaxRuleMatches() + "): " + 
match.getRule().toString());
+    }
   }
 
   public int getTried() {
@@ -71,9 +77,9 @@ public class RuleApply extends ScriptApp
     this.acceptMatches = acceptMatches;
   }
 
-  public void addAll(List<RuleMatch> matches) {
+  public void addAll(List<RuleMatch> matches, RutaStream stream) {
     for (RuleMatch ruleMatch : matches) {
-      add(ruleMatch);
+      add(ruleMatch, stream);
     }
   }
 

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleElement.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleElement.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleElement.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RuleElement.java
 Wed Jan 16 11:45:02 2019
@@ -78,16 +78,16 @@ public interface RuleElement {
 
   boolean isStartAnchor();
 
-  void setInlinedActionRules(List<RutaStatement> innerRules);
+  void addInlinedActionRules(List<RutaStatement> innerRules);
 
-  void setInlinedConditionRules(List<RutaStatement> innerRules);
+  void addInlinedConditionRules(List<RutaStatement> innerRules);
 
   void setLabel(String label);
 
   String getLabel();
   
-  List<RutaStatement> getInlinedConditionRules();
+  List<List<RutaStatement>> getInlinedConditionRuleBlocks();
   
-  List<RutaStatement> getInlinedActionRules();
+  List<List<RutaStatement>> getInlinedActionRuleBlocks();
 
 }

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaAnnotationTypeMatcher.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaAnnotationTypeMatcher.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaAnnotationTypeMatcher.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaAnnotationTypeMatcher.java
 Wed Jan 16 11:45:02 2019
@@ -59,24 +59,39 @@ public class RutaAnnotationTypeMatcher i
     } else if (expression.getAnnotationListExpression() != null) {
       result = expression.getAnnotationList(context, stream);
     } else {
-      Type type = getType(parent, stream);
-      if (type == null) {
-        return Collections.emptyList();
-      }
-      Type overallDAType = stream.getCas().getDocumentAnnotation().getType();
-      String name = type.getName();
-      if (StringUtils.equals(CAS.TYPE_NAME_DOCUMENT_ANNOTATION, name)
-              || "org.apache.uima.ruta.type.Document".equals(name) || 
overallDAType.equals(type)) {
-        // TODO what about dynamic windowing?
-        result = new ArrayList<>(1);
-        result.add(stream.getDocumentAnnotation());
+
+      // TODO defer to getter of expression?
+      List<Type> types = null;
+      if (expression.getTypeListExpression() != null) {
+        types = expression.getTypeListExpression().getTypeList(context, 
stream);
       } else {
-        result = stream.getAnnotations(type);
-      }
-      if (expression.getFeatureExpression() != null) {
-        return expression.getFeatureExpression().getAnnotations(result, 
CHECK_ON_FEATURE, context,
-                stream);
+        Type type = getType(context.getParent(), stream);
+        types = new ArrayList<>(1);
+        if (type != null) {
+          types.add(type);
+        }
+      }
+      result = new ArrayList<>();
+      for (Type type : types) {
+        if (type != null) {
+
+          Type overallDAType = 
stream.getCas().getDocumentAnnotation().getType();
+          String name = type.getName();
+          if (StringUtils.equals(CAS.TYPE_NAME_DOCUMENT_ANNOTATION, name)
+                  || "org.apache.uima.ruta.type.Document".equals(name)
+                  || overallDAType.equals(type)) {
+            // TODO what about dynamic windowing?
+            result.add(stream.getDocumentAnnotation());
+          } else {
+            result.addAll(stream.getAnnotations(type));
+          }
+          if (expression.getFeatureExpression() != null) {
+            result = new 
ArrayList<>(expression.getFeatureExpression().getAnnotations(result,
+                    CHECK_ON_FEATURE, context, stream));
+          }
+        }
       }
+
     }
     return result;
   }
@@ -96,7 +111,10 @@ public class RutaAnnotationTypeMatcher i
     } else {
       end = lastBasic.getEnd();
     }
-    if (annotation.getEnd() > 0) {
+    if (end == stream.getDocumentAnnotation().getBegin()) {
+      // non existing wildcard match
+      stream.moveToFirst();
+    } else if (annotation.getEnd() > 0) {
       stream.moveTo(lastBasic);
       if (stream.isVisible(lastBasic) && stream.isValid()
               && stream.get().getEnd() == lastBasic.getEnd()) {
@@ -141,24 +159,35 @@ public class RutaAnnotationTypeMatcher i
         }
         return result;
       } else {
-        Type type = getType(parent, stream);
-        Collection<AnnotationFS> anchors = new ArrayList<>();
-        Collection<AnnotationFS> beginAnchors = 
nextBasic.getBeginAnchors(type);
-        if (beginAnchors != null) {
-          for (AnnotationFS afs : beginAnchors) {
-            if (afs.getBegin() >= stream.getDocumentAnnotation().getBegin()
-                    && afs.getEnd() <= 
stream.getDocumentAnnotation().getEnd()) {
-              anchors.add(afs);
+        List<Type> types = null;
+        if (expression.getTypeListExpression() != null) {
+          types = expression.getTypeListExpression().getTypeList(context, 
stream);
+        } else {
+          Type type = getType(context.getParent(), stream);
+          types = new ArrayList<>(1);
+          types.add(type);
+        }
+        List<AnnotationFS> annotations = new ArrayList<>();
+        for (Type type : types) {
+          Collection<AnnotationFS> anchors = new ArrayList<>();
+          Collection<AnnotationFS> beginAnchors = 
nextBasic.getBeginAnchors(type);
+          if (beginAnchors != null) {
+            for (AnnotationFS afs : beginAnchors) {
+              if (afs.getBegin() >= stream.getDocumentAnnotation().getBegin()
+                      && afs.getEnd() <= 
stream.getDocumentAnnotation().getEnd()) {
+                anchors.add(afs);
+              }
             }
           }
-        }
-        if (expression.getFeatureExpression() != null) {
-          return expression.getFeatureExpression().getAnnotations(anchors, 
CHECK_ON_FEATURE,
-                  context, stream);
-        } else {
-          return anchors;
-        }
+          if (expression.getFeatureExpression() != null) {
+            
annotations.addAll(expression.getFeatureExpression().getAnnotations(anchors,
+                    CHECK_ON_FEATURE, context, stream));
+          } else {
+            annotations.addAll(anchors);
+          }
 
+        }
+        return annotations;
       }
 
     }
@@ -179,6 +208,10 @@ public class RutaAnnotationTypeMatcher i
     if (stream.isVisible(firstBasic)) {
       stream.moveToPrevious();
     }
+    if (firstBasic.getBegin() == stream.getDocumentAnnotation().getEnd()) {
+      // non existing wildcard match
+      stream.moveToLast();
+    }
 
     if (stream.isValid()) {
       RutaBasic nextBasic = (RutaBasic) stream.get();
@@ -213,22 +246,33 @@ public class RutaAnnotationTypeMatcher i
           }
         }
       } else {
-        Type type = getType(parent, stream);
-        Collection<AnnotationFS> anchors = new ArrayList<>();
-        Collection<AnnotationFS> endAnchors = nextBasic.getEndAnchors(type);
-        if (endAnchors != null) {
-          for (AnnotationFS afs : endAnchors) {
-            if (afs.getBegin() >= stream.getDocumentAnnotation().getBegin()) {
-              anchors.add(afs);
+        List<Type> types = null;
+        if (expression.getTypeListExpression() != null) {
+          types = expression.getTypeListExpression().getTypeList(context, 
stream);
+        } else {
+          Type type = getType(context.getParent(), stream);
+          types = new ArrayList<>(1);
+          types.add(type);
+        }
+        List<AnnotationFS> annotations = new ArrayList<>();
+        for (Type type : types) {
+          Collection<AnnotationFS> anchors = new ArrayList<>();
+          Collection<AnnotationFS> endAnchors = nextBasic.getEndAnchors(type);
+          if (endAnchors != null) {
+            for (AnnotationFS afs : endAnchors) {
+              if (afs.getBegin() >= stream.getDocumentAnnotation().getBegin()) 
{
+                anchors.add(afs);
+              }
             }
           }
+          if (expression.getFeatureExpression() != null) {
+            
annotations.addAll(expression.getFeatureExpression().getAnnotations(anchors,
+                    CHECK_ON_FEATURE, context, stream));
+          } else {
+            annotations.addAll(anchors);
+          }
         }
-        if (expression.getFeatureExpression() != null) {
-          return expression.getFeatureExpression().getAnnotations(anchors, 
CHECK_ON_FEATURE,
-                  context, stream);
-        } else {
-          return anchors;
-        }
+        return annotations;
       }
     }
     return Collections.emptyList();

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaLiteralMatcher.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaLiteralMatcher.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaLiteralMatcher.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaLiteralMatcher.java
 Wed Jan 16 11:45:02 2019
@@ -92,7 +92,7 @@ public class RutaLiteralMatcher implemen
     MatchContext context = new MatchContext(annotation, null, null, !before);
     context.setParent(parent);
     String stringValue = expression.getStringValue(context, stream);
-    if (stringValue.equals(basicNextTo.getCoveredText())) {
+    if (stringValue != null && 
stringValue.equals(basicNextTo.getCoveredText())) {
       result.add(basicNextTo);
     }
     return result;

Added: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaOptionalRuleElement.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaOptionalRuleElement.java?rev=1851430&view=auto
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaOptionalRuleElement.java
 (added)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaOptionalRuleElement.java
 Wed Jan 16 11:45:02 2019
@@ -0,0 +1,121 @@
+/*
+ * 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.rule;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.ruta.RutaEnvironment;
+import org.apache.uima.ruta.RutaProcessRuntimeException;
+import org.apache.uima.ruta.RutaStream;
+import org.apache.uima.ruta.action.AbstractRutaAction;
+import org.apache.uima.ruta.block.RutaBlock;
+import org.apache.uima.ruta.condition.AbstractRutaCondition;
+import org.apache.uima.ruta.rule.quantifier.NormalQuantifier;
+import org.apache.uima.ruta.visitor.InferenceCrowd;
+
+public class RutaOptionalRuleElement extends RutaRuleElement {
+
+  public RutaOptionalRuleElement(List<AbstractRutaCondition> conditions,
+          List<AbstractRutaAction> actions, RuleElementContainer container, 
RutaBlock parent) {
+
+    super(null, new NormalQuantifier(), conditions, actions, container, 
parent);
+  }
+
+  @Override
+  public Collection<? extends AnnotationFS> getAnchors(RutaStream stream) {
+    throw new RutaProcessRuntimeException(
+            "Using an optional rule lement as anchor is not allowed!");
+  }
+
+  @Override
+  public List<RuleMatch> startMatch(RuleMatch ruleMatch, RuleApply ruleApply,
+          ComposedRuleElementMatch containerMatch, RuleElement entryPoint, 
RutaStream stream,
+          InferenceCrowd crowd) {
+    throw new RutaProcessRuntimeException(
+            "Using an optional rule lement as anchor is not allowed!");
+  }
+
+  @Override
+  protected void doMatch(boolean after, AnnotationFS annotation, RuleMatch 
ruleMatch,
+          ComposedRuleElementMatch containerMatch, boolean ruleAnchor, 
RutaStream stream,
+          InferenceCrowd crowd) {
+    RuleElementMatch result = new RuleElementMatch(this, containerMatch);
+    result.setRuleAnchor(ruleAnchor);
+    List<EvaluatedCondition> evaluatedConditions = new 
ArrayList<EvaluatedCondition>(
+            conditions.size());
+    boolean base = true;
+    MatchContext context = new MatchContext(annotation, this, ruleMatch, 
after);
+
+    List<AnnotationFS> textsMatched = new ArrayList<AnnotationFS>(1);
+    if (annotation != null) {
+      textsMatched.add(annotation);
+    }
+    // already set the matched text and inform others
+    result.setMatchInfo(base, textsMatched, stream);
+    RutaEnvironment environment = context.getParent().getEnvironment();
+    environment.addMatchToVariable(ruleMatch, this, context, stream);
+    if (base) {
+      for (AbstractRutaCondition condition : conditions) {
+        crowd.beginVisit(condition, null);
+        EvaluatedCondition eval = condition.eval(context, stream, crowd);
+        crowd.endVisit(condition, null);
+        evaluatedConditions.add(eval);
+        if (!eval.isValue()) {
+          break;
+        }
+      }
+    }
+    result.setConditionInfo(base, evaluatedConditions);
+    if (result.matched()) {
+      boolean inlinedRulesMatched = matchInnerRules(ruleMatch, stream, crowd);
+      result.setInlinedRulesMatched(inlinedRulesMatched);
+    } else {
+      // update label for failed match after evaluating conditions
+      environment.addAnnotationsToVariable(null, getLabel(), context);
+    }
+    ruleMatch.setMatched(ruleMatch.matched() && result.matched());
+  }
+
+  @Override
+  protected boolean isNotConsumable(Collection<? extends AnnotationFS> 
nextAnnotations) {
+    return false;
+  }
+
+  @Override
+  public String toString() {
+    return "_";
+  }
+
+  @Override
+  public long estimateAnchors(RutaStream stream) {
+    return Integer.MAX_VALUE;
+  }
+
+  @Override
+  public Collection<? extends AnnotationFS> getNextAnnotations(boolean after,
+          AnnotationFS annotation, RutaStream stream) {
+    return Arrays.asList(stream.getBasicNextTo(!after, annotation));
+  }
+
+}

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRule.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRule.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRule.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRule.java
 Wed Jan 16 11:45:02 2019
@@ -30,6 +30,7 @@ import org.apache.uima.ruta.RutaConstant
 import org.apache.uima.ruta.RutaEnvironment;
 import org.apache.uima.ruta.RutaStatement;
 import org.apache.uima.ruta.RutaStream;
+import org.apache.uima.ruta.action.AbstractRutaAction;
 import org.apache.uima.ruta.block.RutaBlock;
 import org.apache.uima.ruta.visitor.InferenceCrowd;
 
@@ -38,8 +39,8 @@ public class RutaRule extends AbstractRu
   private ComposedRuleElement root;
 
   /**
-   *  labels of all rule elements including those in inlined rules.
-   *  The values store the values of overridden variables.
+   * labels of all rule elements including those in inlined rules. The values 
store the values of
+   * overridden variables.
    */
   private Map<String, Object> labels;
 
@@ -100,6 +101,7 @@ public class RutaRule extends AbstractRu
     if (!StringUtils.isBlank(ruleElement.getLabel())) {
       labels.put(ruleElement.getLabel(), null);
     }
+    fillLabelMapWithActions(ruleElement.getActions());
     if (ruleElement instanceof ComposedRuleElement) {
       ComposedRuleElement cre = (ComposedRuleElement) ruleElement;
       List<RuleElement> ruleElements = cre.getRuleElements();
@@ -107,24 +109,36 @@ public class RutaRule extends AbstractRu
         fillLabelMap(each);
       }
     }
-    fillLabelMapWithInlinedRules(ruleElement.getInlinedConditionRules());
-    fillLabelMapWithInlinedRules(ruleElement.getInlinedActionRules());
+    fillLabelMapWithInlinedRules(ruleElement.getInlinedConditionRuleBlocks());
+    fillLabelMapWithInlinedRules(ruleElement.getInlinedActionRuleBlocks());
   }
 
-  private void fillLabelMapWithInlinedRules(List<RutaStatement> rules) {
-    if (rules != null) {
-      for (RutaStatement eachInlined : rules) {
-        if (eachInlined instanceof RutaRule) {
-          RutaRule inlinedRule = (RutaRule) eachInlined;
-          inlinedRule.setInlined(true);
-          fillLabelMap(inlinedRule.getRoot());
+  private void fillLabelMapWithActions(List<AbstractRutaAction> actions) {
+    if (actions != null) {
+      for (AbstractRutaAction action : actions) {
+        if (action != null && !StringUtils.isBlank(action.getLabel())) {
+          labels.put(action.getLabel(), null);
+        }
+      }
+    }
+  }
+
+  private void fillLabelMapWithInlinedRules(List<List<RutaStatement>> blocks) {
+    if (blocks != null) {
+      for (List<RutaStatement> list : blocks) {
+        for (RutaStatement eachInlined : list) {
+          if (eachInlined instanceof RutaRule) {
+            RutaRule inlinedRule = (RutaRule) eachInlined;
+            inlinedRule.setInlined(true);
+            fillLabelMap(inlinedRule.getRoot());
+          }
         }
       }
     }
   }
 
   private void prepareEnvironment(MatchContext context, RutaStream stream) {
-    if(isInlined()) {
+    if (isInlined()) {
       // only the actual rule may setup the environment
       return;
     }
@@ -132,15 +146,19 @@ public class RutaRule extends AbstractRu
     RutaEnvironment environment = parent.getEnvironment();
     for (Entry<String, Object> entry : labels.entrySet()) {
       String label = entry.getKey();
-      if(environment.isVariable(label)) {
+      if (environment.isVariable(label)) {
         Class<?> variableType = environment.getVariableType(label);
         Class<?> variableGenericType = 
environment.getVariableGenericType(label);
-        if(variableType != null && variableGenericType!= null && 
variableType.isAssignableFrom(List.class) && 
variableGenericType.isAssignableFrom(AnnotationFS.class)) {
+        if (variableType != null && variableGenericType != null
+                && variableType.isAssignableFrom(List.class)
+                && variableGenericType.isAssignableFrom(AnnotationFS.class)) {
           labels.put(label, environment.getVariableValue(label, stream));
-        } else if(variableType != null && 
variableType.isAssignableFrom(AnnotationFS.class)) {
+        } else if (variableType != null && 
variableType.isAssignableFrom(AnnotationFS.class)) {
         } else {
-          String type = variableType== null ? "unknown" : 
variableType.getSimpleName();
-          throw new RuntimeException("Overriding global variable '"+label+"' 
of type '"+ type+ "' with a local label variable is not allowed!");
+          String type = variableType == null ? "unknown" : 
variableType.getSimpleName();
+          throw new RuntimeException("Overriding global variable '" + label + 
"' of type '" + type
+                  + "' with a local label variable is not allowed (in script "
+                  + context.getParent().getName() + ")!");
         }
       } else {
         environment.addVariable(label, 
RutaConstants.RUTA_VARIABLE_ANNOTATION_LIST);
@@ -149,7 +167,7 @@ public class RutaRule extends AbstractRu
   }
 
   private void cleanupEnvironment(MatchContext context, RutaStream stream) {
-    if(isInlined()) {
+    if (isInlined()) {
       // only the actual rule may revert the environment
       return;
     }
@@ -158,15 +176,14 @@ public class RutaRule extends AbstractRu
     for (Entry<String, Object> entry : labels.entrySet()) {
       String label = entry.getKey();
       Object value = entry.getValue();
-      if(value == null) {
+      if (value == null) {
         environment.removeVariable(label);
       } else {
         environment.setVariableValue(label, value);
       }
     }
   }
-  
-  
+
   public ComposedRuleElement getRoot() {
     return root;
   }

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRuleElement.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRuleElement.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRuleElement.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/RutaRuleElement.java
 Wed Jan 16 11:45:02 2019
@@ -25,6 +25,7 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.uima.cas.text.AnnotationFS;
+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;
@@ -113,9 +114,9 @@ public class RutaRuleElement extends Abs
       } else {
         if (getContainer() instanceof ComposedRuleElement) {
           ComposedRuleElement composed = (ComposedRuleElement) getContainer();
-          List<RuleMatch> fallbackContinue = composed
-                  .fallbackContinue(true, true, eachAnchor, extendedMatch, 
ruleApply,
-                          extendedContainerMatch, null, entryPoint, stream, 
crowd);
+          List<RuleMatch> fallbackContinue = composed.fallbackContinue(true, 
true, eachAnchor,
+                  extendedMatch, ruleApply, extendedContainerMatch, null, 
entryPoint, stream,
+                  crowd);
           result.addAll(fallbackContinue);
         }
       }
@@ -145,7 +146,8 @@ public class RutaRuleElement extends Abs
                   sideStepOrigin, stream, crowd, entryPoint);
           break;
         }
-        Collection<? extends AnnotationFS> nextAnnotations = 
getNextAnnotations(after, eachAnchor, stream);
+        Collection<? extends AnnotationFS> nextAnnotations = 
getNextAnnotations(after, eachAnchor,
+                stream);
         if (nextAnnotations.size() == 0) {
           stopMatching = true;
           result = stepbackMatch(after, eachAnchor, extendedMatch, ruleApply,
@@ -157,8 +159,8 @@ public class RutaRuleElement extends Abs
           if (this.equals(entryPoint)) {
             result.add(extendedMatch);
           } else if (extendedMatch.matched()) {
-            if (quantifier.continueMatch(after, context, eachAnchor, 
extendedContainerMatch,
-                    stream, crowd)) {
+            if (quantifier.continueMatch(after, context, eachAnchor, 
extendedContainerMatch, stream,
+                    crowd)) {
               // continue in while loop
             } else {
               stopMatching = true;
@@ -183,7 +185,7 @@ public class RutaRuleElement extends Abs
     return result;
   }
 
-  private List<RuleMatch> continueMatchSomewhereElse(boolean after, boolean 
failed,
+  protected List<RuleMatch> continueMatchSomewhereElse(boolean after, boolean 
failed,
           AnnotationFS eachAnchor, RuleMatch extendedMatch, RuleApply 
ruleApply,
           ComposedRuleElementMatch extendedContainerMatch, RutaRuleElement 
sideStepOrigin,
           RuleElement entryPoint, RutaStream stream, InferenceCrowd crowd) {
@@ -209,12 +211,13 @@ public class RutaRuleElement extends Abs
     // if() for really lazy quantifiers
     MatchContext context = new MatchContext(this, ruleMatch, after);
     if (quantifier.continueMatch(after, context, annotation, containerMatch, 
stream, crowd)) {
-      Collection<? extends AnnotationFS> nextAnnotations = 
getNextAnnotations(after, annotation, stream);
-      if (nextAnnotations.isEmpty()) {
+      Collection<? extends AnnotationFS> nextAnnotations = 
getNextAnnotations(after, annotation,
+              stream);
+      if (isNotConsumable(nextAnnotations)) {
         result = stepbackMatch(after, annotation, ruleMatch, ruleApply, 
containerMatch,
                 sideStepOrigin, stream, crowd, entryPoint);
       }
-      boolean useAlternatives = nextAnnotations.size() != 1;
+      boolean useAlternatives = nextAnnotations.size() > 1;
       for (AnnotationFS eachAnchor : nextAnnotations) {
         if (earlyExit(eachAnchor, ruleApply, stream)) {
           // ... for different matching paradigms that avoid some matches
@@ -262,7 +265,11 @@ public class RutaRuleElement extends Abs
     return result;
   }
 
-  private List<RuleMatch> stepbackMatch(boolean after, AnnotationFS annotation,
+  protected boolean isNotConsumable(Collection<? extends AnnotationFS> 
nextAnnotations) {
+    return nextAnnotations.isEmpty();
+  }
+
+  protected List<RuleMatch> stepbackMatch(boolean after, AnnotationFS 
annotation,
           RuleMatch ruleMatch, RuleApply ruleApply, ComposedRuleElementMatch 
containerMatch,
           RutaRuleElement sideStepOrigin, RutaStream stream, InferenceCrowd 
crowd,
           RuleElement entryPoint) {
@@ -280,8 +287,8 @@ public class RutaRuleElement extends Abs
                 containerMatch, sideStepOrigin, entryPoint, stream, crowd);
       } else if (getContainer() instanceof ComposedRuleElement) {
         ComposedRuleElement cre = (ComposedRuleElement) getContainer();
-        result = cre.fallbackContinue(after, true, annotation, ruleMatch, 
ruleApply,
-                containerMatch, sideStepOrigin, entryPoint, stream, crowd);
+        result = cre.fallbackContinue(after, true, annotation, ruleMatch, 
ruleApply, containerMatch,
+                sideStepOrigin, entryPoint, stream, crowd);
         // was:
         // [Peter] why only check the parent? the grandparent could be 
optional!
         // should we add the second part again for the explanation component?
@@ -365,7 +372,7 @@ public class RutaRuleElement extends Abs
     return result;
   }
 
-  private void doMatch(boolean after, AnnotationFS annotation, RuleMatch 
ruleMatch,
+  protected void doMatch(boolean after, AnnotationFS annotation, RuleMatch 
ruleMatch,
           ComposedRuleElementMatch containerMatch, boolean ruleAnchor, 
RutaStream stream,
           InferenceCrowd crowd) {
     RuleElementMatch result = new RuleElementMatch(this, containerMatch);
@@ -382,21 +389,27 @@ public class RutaRuleElement extends Abs
     }
     // already set the matched text and inform others
     result.setMatchInfo(base, textsMatched, stream);
-    context.getParent().getEnvironment().addMatchToVariable(ruleMatch, this, 
context, stream);
+    RutaEnvironment environment = context.getParent().getEnvironment();
+    environment.addMatchToVariable(ruleMatch, this, context, stream);
     if (base) {
       for (AbstractRutaCondition condition : conditions) {
         crowd.beginVisit(condition, null);
         EvaluatedCondition eval = condition.eval(context, stream, crowd);
         crowd.endVisit(condition, null);
         evaluatedConditions.add(eval);
-        if(!eval.isValue()) {
+        if (!eval.isValue()) {
           break;
         }
       }
     }
     result.setConditionInfo(base, evaluatedConditions);
-    boolean inlinedRulesMatched = matchInnerRules(ruleMatch, stream, crowd);
-    result.setInlinedRulesMatched(inlinedRulesMatched);
+    if (result.matched()) {
+      boolean inlinedRulesMatched = matchInnerRules(ruleMatch, stream, crowd);
+      result.setInlinedRulesMatched(inlinedRulesMatched);
+    } else {
+      // update label for failed match after evaluating conditions
+      environment.addAnnotationsToVariable(null, getLabel(), context);
+    }
     ruleMatch.setMatched(ruleMatch.matched() && result.matched());
   }
 
@@ -437,8 +450,8 @@ public class RutaRuleElement extends Abs
     return matcher.estimateAnchors(parent, stream);
   }
 
-  public Collection<? extends AnnotationFS> getNextAnnotations(boolean after, 
AnnotationFS annotation,
-          RutaStream stream) {
+  public Collection<? extends AnnotationFS> getNextAnnotations(boolean after,
+          AnnotationFS annotation, RutaStream stream) {
     if (after) {
       return matcher.getAnnotationsAfter(this, annotation, getParent(), 
stream);
     } else {

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/WildCardRuleElement.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/WildCardRuleElement.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/WildCardRuleElement.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/WildCardRuleElement.java
 Wed Jan 16 11:45:02 2019
@@ -30,6 +30,7 @@ import org.apache.uima.cas.FSIterator;
 import org.apache.uima.cas.Type;
 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;
@@ -235,7 +236,7 @@ public class WildCardRuleElement extends
           RutaStream stream, RuleElement element, AnnotationFS result) {
     RutaRuleElement re = (RutaRuleElement) element;
     RutaMatcher matcher = re.getMatcher();
-      
+
     if (matcher instanceof RutaLiteralMatcher) {
       RutaLiteralMatcher lm = (RutaLiteralMatcher) matcher;
       IStringExpression expression = lm.getExpression();
@@ -256,7 +257,7 @@ public class WildCardRuleElement extends
       if (iterator == null) {
         return null;
       }
-      
+
       if (iterator.isValid()) {
         result = iterator.get();
         if (annotation != null && (after && result.getEnd() == 
annotation.getEnd())
@@ -359,9 +360,12 @@ public class WildCardRuleElement extends
         // TODO match and containermatch should be on the correct level!
         result = nextElement.continueMatch(after, anchor, extendedMatch, 
ruleApply,
                 nextContainerMatch, sideStepOrigin, nextElement, stream, 
crowd);
-        List<RuleElementMatch> nextList = 
nextContainerMatch.getInnerMatches().get(nextElement);
-        if (nextList == null || nextList.isEmpty()
-                || !nextList.get(nextList.size() - 1).matched()) {
+//        List<RuleElementMatch> nextList = 
nextContainerMatch.getInnerMatches().get(nextElement);
+
+        // cannot use container match since there could be new alternatives in 
the depth search
+        boolean nextElementDidMatch = nextElementDidMatch(result, nextElement);
+
+        if (!nextElementDidMatch) {
           moveOn(after, iterator, stream);
         } else {
           doneHere = true;
@@ -375,6 +379,32 @@ public class WildCardRuleElement extends
     return result;
   }
 
+  private boolean nextElementDidMatch(List<RuleMatch> result, RuleElement 
nextElement) {
+    if (result == null || result.isEmpty()) {
+      return false;
+    }
+
+    for (RuleMatch ruleMatch : result) {
+      if (ruleMatch.matched()) {
+        return true;
+      }
+    }
+    for (RuleMatch ruleMatch : result) {
+      List<List<RuleElementMatch>> matchInfo = 
ruleMatch.getMatchInfo(nextElement);
+      List<RuleElementMatch> matches = matchInfo.get(matchInfo.size() - 1);
+      if (matches != null) {
+        for (RuleElementMatch ruleElementMatch : matches) {
+          if (ruleElementMatch != null && ruleElementMatch.matched()) {
+            return true;
+          }
+        }
+      }
+
+    }
+
+    return false;
+  }
+
   private ComposedRuleElementMatch getContainerMatchOfNextElement(
           ComposedRuleElementMatch extendedContainerMatch, int nextDepth) {
     ComposedRuleElementMatch result = extendedContainerMatch;
@@ -424,10 +454,10 @@ public class WildCardRuleElement extends
     if (stream.getDocumentAnnotation().equals(cas.getDocumentAnnotation())) {
       // no windowing needed
       if (annotation == null) {
-        result = cas.getAnnotationIndex(type).iterator();
+        result = 
cas.getAnnotationIndex(type).withSnapshotIterators().iterator();
       } else {
         AnnotationFS pointer = stream.getAnchor(after, annotation);
-        result = cas.getAnnotationIndex(type).iterator(pointer);
+        result = 
cas.getAnnotationIndex(type).withSnapshotIterators().iterator(pointer);
         if (!result.isValid()) {
           if (after) {
             // result.moveToFirst();
@@ -654,7 +684,8 @@ public class WildCardRuleElement extends
       textsMatched.add(annotation);
     }
     result.setMatchInfo(base, textsMatched, stream);
-    context.getParent().getEnvironment().addMatchToVariable(ruleMatch, this, 
context, stream);
+    RutaEnvironment environment = context.getParent().getEnvironment();
+    environment.addMatchToVariable(ruleMatch, this, context, stream);
     if (base) {
       for (AbstractRutaCondition condition : conditions) {
         crowd.beginVisit(condition, null);
@@ -667,6 +698,13 @@ public class WildCardRuleElement extends
       }
     }
     result.setConditionInfo(base, evaluatedConditions);
+    if (result.matched()) {
+      boolean inlinedRulesMatched = matchInnerRules(ruleMatch, stream, crowd);
+      result.setInlinedRulesMatched(inlinedRulesMatched);
+    } else {
+      // update label for failed match after evaluating conditions
+      environment.addAnnotationsToVariable(null, getLabel(), context);
+    }
     ruleMatch.setMatched(ruleMatch.matched() && result.matched());
   }
 

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/AbstractRuleElementQuantifier.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/AbstractRuleElementQuantifier.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/AbstractRuleElementQuantifier.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/AbstractRuleElementQuantifier.java
 Wed Jan 16 11:45:02 2019
@@ -21,7 +21,12 @@ package org.apache.uima.ruta.rule.quanti
 
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.ruta.RutaEnvironment;
+import org.apache.uima.ruta.RutaStream;
 import org.apache.uima.ruta.rule.ComposedRuleElement;
+import org.apache.uima.ruta.rule.MatchContext;
 import org.apache.uima.ruta.rule.RuleElement;
 import org.apache.uima.ruta.rule.RuleElementContainer;
 import org.apache.uima.ruta.rule.RuleElementMatch;
@@ -54,12 +59,32 @@ public abstract class AbstractRuleElemen
     RuleElement nextElement = null;
     RuleElementContainer container = ruleElement.getContainer();
     RuleElement previousElement = ruleElement;
-    while(nextElement == null && container instanceof ComposedRuleElement) {
+    while (nextElement == null && container instanceof ComposedRuleElement) {
       nextElement = container.getNextElement(after, previousElement);
-      previousElement = ((ComposedRuleElement)container);
-      container = ((ComposedRuleElement)container).getContainer();
+      previousElement = ((ComposedRuleElement) container);
+      container = ((ComposedRuleElement) container).getContainer();
     }
     return nextElement;
   }
-  
+
+  protected void updateLabelAssignment(List<RuleElementMatch> matches, 
MatchContext context,
+          RutaStream stream) {
+
+    RutaEnvironment environment = context.getParent().getEnvironment();
+    RuleElement ruleElement = context.getElement();
+    String label = ruleElement.getLabel();
+
+    if (matches == null || matches.isEmpty()) {
+      environment.addAnnotationsToVariable(null, label, context);
+      return;
+    }
+
+    if (!StringUtils.isBlank(label)) {
+
+      RuleElementMatch ruleElementMatch = matches.get(matches.size() - 1);
+      List<AnnotationFS> textsMatched = ruleElementMatch.getTextsMatched();
+      environment.addAnnotationsToVariable(textsMatched, label, context);
+    }
+  }
+
 }

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxGreedy.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxGreedy.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxGreedy.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxGreedy.java
 Wed Jan 16 11:45:02 2019
@@ -60,6 +60,7 @@ public class MinMaxGreedy extends Abstra
       RuleElementMatch ruleElementMatch = matches.get(matches.size() - 1);
       if (!ruleElementMatch.matched()) {
         matches.remove(ruleElementMatch);
+        updateLabelAssignment(matches, context, stream);
       }
     }
 

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxReluctant.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxReluctant.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxReluctant.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/MinMaxReluctant.java
 Wed Jan 16 11:45:02 2019
@@ -69,6 +69,7 @@ public class MinMaxReluctant extends Abs
       RuleElementMatch ruleElementMatch = matches.get(matches.size() - 1);
       if (!ruleElementMatch.matched()) {
         matches.remove(ruleElementMatch);
+        updateLabelAssignment(matches, context, stream);
       }
     }
     int matchedSize = matches.size();

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusGreedy.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusGreedy.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusGreedy.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusGreedy.java
 Wed Jan 16 11:45:02 2019
@@ -48,7 +48,11 @@ public class PlusGreedy extends Abstract
       result &= match.matched();
     }
     if (!result && matches.size() > 1) {
+      RuleElementMatch ruleElementMatch = matches.get(matches.size() - 1);
       matches.remove(matches.size() - 1);
+      if (!ruleElementMatch.getTextsMatched().isEmpty()) {
+        updateLabelAssignment(matches, context, stream);
+      }
       result = true;
     }
     if (matches.size() < 1 || allEmpty) {

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusReluctant.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusReluctant.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusReluctant.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/PlusReluctant.java
 Wed Jan 16 11:45:02 2019
@@ -44,6 +44,7 @@ public class PlusReluctant extends Abstr
     }
     if (!result && matches.size() > 1) {
       matches.remove(matches.size() - 1);
+      updateLabelAssignment(matches, context, stream);
       result = true;
     }
     if (matches.size() < 1 || allEmpty) {
@@ -68,7 +69,7 @@ public class PlusReluctant extends Abstr
     if (ownList == null || ownList.isEmpty()) {
       return true;
     }
-    
+
     RuleElement nextElement = getNextRuleElement(after, ruleElement);
     if (nextElement == null) {
       return false;

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionGreedy.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionGreedy.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionGreedy.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionGreedy.java
 Wed Jan 16 11:45:02 2019
@@ -40,11 +40,12 @@ public class QuestionGreedy extends Abst
       return Collections.emptyList();
     }
     for (RuleElementMatch match : matches) {
-      result &= match.matched()
-              || (!(match instanceof ComposedRuleElementMatch) && 
match.getTextsMatched().isEmpty());
+      result &= match.matched() || (!(match instanceof 
ComposedRuleElementMatch)
+              && match.getTextsMatched().isEmpty());
     }
     if (!result) {
       matches.remove(0);
+      updateLabelAssignment(matches, context, stream);
       result = true;
     }
     if (result) {

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionReluctant.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionReluctant.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionReluctant.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/QuestionReluctant.java
 Wed Jan 16 11:45:02 2019
@@ -41,6 +41,7 @@ public class QuestionReluctant extends A
     }
     if (!result) {
       matches.remove(0);
+      updateLabelAssignment(matches, context, stream);
       result = true;
     }
     if (result) {

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/StarGreedy.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/StarGreedy.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/StarGreedy.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/rule/quantifier/StarGreedy.java
 Wed Jan 16 11:45:02 2019
@@ -42,11 +42,12 @@ public class StarGreedy extends Abstract
       return null;
     }
     for (RuleElementMatch match : matches) {
-      result &= match.matched()
-              || (!(match instanceof ComposedRuleElementMatch) && 
match.getTextsMatched().isEmpty());
+      result &= match.matched() || (!(match instanceof 
ComposedRuleElementMatch)
+              && match.getTextsMatched().isEmpty());
     }
     if (!result && matches.size() > 0) {
       matches.remove(matches.size() - 1);
+      updateLabelAssignment(matches, context, stream);
       result = true;
     }
     if (result) {

Added: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/utils/XmlUtils.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/utils/XmlUtils.java?rev=1851430&view=auto
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/utils/XmlUtils.java
 (added)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/utils/XmlUtils.java
 Wed Jan 16 11:45:02 2019
@@ -0,0 +1,64 @@
+/*
+ * 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.utils;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+
+public final class XmlUtils {
+
+  private XmlUtils() {
+    // nothing here
+  }
+
+  public static DocumentBuilder createDocumentBuilder() {
+    
+    DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();
+    
+    try {
+      
+      
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+      return documentBuilderFactory.newDocumentBuilder();
+    } catch (ParserConfigurationException e) {
+      
+      throw new IllegalStateException(e);
+    }
+  }
+
+  public static SAXParser createSaxParser() {
+    
+    SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
+    
+    try {
+      
+      saxParserFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 
true);
+      return saxParserFactory.newSAXParser();
+    } catch (ParserConfigurationException | SAXException e) {
+      
+      throw new IllegalStateException(e);
+    }
+  }
+
+}

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ScriptVerbalizer.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ScriptVerbalizer.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ScriptVerbalizer.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ScriptVerbalizer.java
 Wed Jan 16 11:45:02 2019
@@ -42,6 +42,7 @@ import org.apache.uima.ruta.rule.Conjunc
 import org.apache.uima.ruta.rule.RegExpRule;
 import org.apache.uima.ruta.rule.RuleElement;
 import org.apache.uima.ruta.rule.RutaMatcher;
+import org.apache.uima.ruta.rule.RutaOptionalRuleElement;
 import org.apache.uima.ruta.rule.RutaRule;
 import org.apache.uima.ruta.rule.RutaRuleElement;
 import org.apache.uima.ruta.rule.WildCardRuleElement;
@@ -149,31 +150,33 @@ public class ScriptVerbalizer {
       result.append(verbalizeConjunct((ConjunctRulesRuleElement) re));
     } else if (re instanceof ComposedRuleElement) {
       result.append(verbalizeComposed((ComposedRuleElement) re));
+    } else if (re instanceof RutaOptionalRuleElement) {
+      result.append("_");
     } else if (re instanceof RutaRuleElement) {
       RutaRuleElement tmre = (RutaRuleElement) re;
       RutaMatcher matcher = tmre.getMatcher();
       // action-only rule
-        IRutaExpression expression = matcher.getExpression();
-        boolean actionOnlyRule = expression == null;
-        if(expression != null) {
-          String verbalize = verbalizer.verbalize(expression);
-          if(StringUtils.isBlank(verbalize)) {
-            actionOnlyRule = true;
-          } else {
-            result.append(verbalize);
-          }
+      IRutaExpression expression = matcher.getExpression();
+      boolean actionOnlyRule = expression == null;
+      if (expression != null) {
+        String verbalize = verbalizer.verbalize(expression);
+        if (StringUtils.isBlank(verbalize)) {
+          actionOnlyRule = true;
+        } else {
+          result.append(verbalize);
         }
-        if (actionOnlyRule) {
-          Iterator<AbstractRutaAction> ait = actions.iterator();
-          while (ait.hasNext()) {
-            AbstractRutaAction each = ait.next();
-            result.append(verbalizer.verbalize(each));
-            if (ait.hasNext()) {
-              result.append(",");
-            }
+      }
+      if (actionOnlyRule) {
+        Iterator<AbstractRutaAction> ait = actions.iterator();
+        while (ait.hasNext()) {
+          AbstractRutaAction each = ait.next();
+          result.append(verbalizer.verbalize(each));
+          if (ait.hasNext()) {
+            result.append(",");
           }
-          return result.toString();
         }
+        return result.toString();
+      }
     } else if (re instanceof WildCardRuleElement) {
       result.append("#");
     }
@@ -204,23 +207,27 @@ public class ScriptVerbalizer {
     }
     if (re instanceof AbstractRuleElement) {
       AbstractRuleElement are = (AbstractRuleElement) re;
-      List<RutaStatement> inlinedConditionRules = 
are.getInlinedConditionRules();
-      if (inlinedConditionRules != null && !inlinedConditionRules.isEmpty()) {
-        result.append(THEN2);
-        result.append(CBOPEN);
-        for (RutaStatement rutaStatement : inlinedConditionRules) {
-          result.append(verbalize(rutaStatement));
+      List<List<RutaStatement>> inlinedConditionRuleBlocks = 
are.getInlinedConditionRuleBlocks();
+      for (List<RutaStatement> inlinedConditionRules : 
inlinedConditionRuleBlocks) {
+        if (inlinedConditionRules != null && !inlinedConditionRules.isEmpty()) 
{
+          result.append(THEN2);
+          result.append(CBOPEN);
+          for (RutaStatement rutaStatement : inlinedConditionRules) {
+            result.append(verbalize(rutaStatement));
+          }
+          result.append(CBCLOSE);
         }
-        result.append(CBCLOSE);
       }
-      List<RutaStatement> inlinedActionRules = are.getInlinedActionRules();
-      if (inlinedActionRules != null && !inlinedActionRules.isEmpty()) {
-        result.append(THEN);
-        result.append(CBOPEN);
-        for (RutaStatement rutaStatement : inlinedActionRules) {
-          result.append(verbalize(rutaStatement));
+      List<List<RutaStatement>> inlinedActionRuleBlocks = 
are.getInlinedActionRuleBlocks();
+      for (List<RutaStatement> inlinedActionRules : inlinedActionRuleBlocks) {
+        if (inlinedActionRules != null && !inlinedActionRules.isEmpty()) {
+          result.append(THEN);
+          result.append(CBOPEN);
+          for (RutaStatement rutaStatement : inlinedActionRules) {
+            result.append(verbalize(rutaStatement));
+          }
+          result.append(CBCLOSE);
         }
-        result.append(CBCLOSE);
       }
     }
     return result.toString();
@@ -262,10 +269,13 @@ public class ScriptVerbalizer {
     return result.toString();
   }
 
-  public String verbalizeMatcher(RutaRuleElement tmre) {
+  public String verbalizeMatcher(RutaRuleElement re) {
+
     StringBuilder result = new StringBuilder();
-    RutaMatcher matcher = tmre.getMatcher();
-    result.append(verbalizer.verbalize(matcher.getExpression()));
+    RutaMatcher matcher = re.getMatcher();
+    if (matcher != null) {
+      result.append(verbalizer.verbalize(matcher.getExpression()));
+    }
     return result.toString();
   }
 
@@ -337,8 +347,7 @@ public class ScriptVerbalizer {
           sb.append("(");
           Iterator<Entry<IStringExpression, IRutaExpression>> fit = 
map.entrySet().iterator();
           while (fit.hasNext()) {
-            Map.Entry<IStringExpression, IRutaExpression> entry = fit
-                    .next();
+            Map.Entry<IStringExpression, IRutaExpression> entry = fit.next();
             sb.append(verbalizer.verbalize(entry.getKey()));
             sb.append(" = ");
             sb.append(verbalizer.verbalize(entry.getValue()));

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoCollectorVisitor.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoCollectorVisitor.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoCollectorVisitor.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoCollectorVisitor.java
 Wed Jan 16 11:45:02 2019
@@ -168,6 +168,7 @@ public class DebugInfoCollectorVisitor i
 
       DebugScriptApply debugScriptApply = 
debugFactory.createDebugScriptApply(rootApply, stream,
               false, withMatches, timeInfo);
+      debugScriptApply.setTimestamp(System.currentTimeMillis());
       debugScriptApply.addToIndexes();
     }
   }

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoFactory.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoFactory.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoFactory.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/java/org/apache/uima/ruta/visitor/DebugInfoFactory.java
 Wed Jan 16 11:45:02 2019
@@ -71,8 +71,8 @@ public class DebugInfoFactory {
           boolean addToIndex, boolean withMatches, Map<RutaElement, Long> 
timeInfo) {
     JCas cas = stream.getJCas();
     DebugBlockApply dba = new DebugBlockApply(cas);
-    AnnotationFS matchedAnnotation = ruleMatch.getMatchedAnnotationsOfElement(
-            ruleMatch.getRule().getRoot()).get(0);
+    AnnotationFS matchedAnnotation = ruleMatch
+            
.getMatchedAnnotationsOfElement(ruleMatch.getRule().getRoot()).get(0);
     dba.setElement(matchedAnnotation.getCoveredText());
     dba.setBegin(matchedAnnotation.getBegin());
     dba.setEnd(matchedAnnotation.getEnd());
@@ -127,8 +127,8 @@ public class DebugInfoFactory {
       }
       dba.setInnerApply(UIMAUtils.toFSArray(cas, innerApply));
       dba.setElement(verbalize);
-      DebugRuleApply ruleApply = 
createDebugRuleApply(blockApply.getRuleApply(), stream,
-              addToIndex, withMatches, timeInfo);
+      DebugRuleApply ruleApply = 
createDebugRuleApply(blockApply.getRuleApply(), stream, addToIndex,
+              withMatches, timeInfo);
       dba.setApplied(ruleApply.getApplied());
       dba.setTried(ruleApply.getTried());
       dba.setRules(ruleApply.getRules());
@@ -148,8 +148,8 @@ public class DebugInfoFactory {
       }
       dba.setInnerApply(UIMAUtils.toFSArray(cas, innerApply));
       dba.setElement(verbalize);
-      DebugRuleApply ruleApply = 
createDebugRuleApply(blockApply.getRuleApply(), stream,
-              addToIndex, withMatches, timeInfo);
+      DebugRuleApply ruleApply = 
createDebugRuleApply(blockApply.getRuleApply(), stream, addToIndex,
+              withMatches, timeInfo);
       dba.setApplied(ruleApply.getApplied());
       dba.setTried(ruleApply.getTried());
       dba.setRules(ruleApply.getRules());
@@ -176,8 +176,8 @@ public class DebugInfoFactory {
     int end = 0;
     if (withMatches) {
       for (AbstractRuleMatch<? extends AbstractRule> match : 
ruleApply.getList()) {
-        DebugRuleMatch debugRuleMatch = createDebugRuleMatch(match, stream, 
addToIndex,
-                withMatches, timeInfo);
+        DebugRuleMatch debugRuleMatch = createDebugRuleMatch(match, stream, 
addToIndex, withMatches,
+                timeInfo);
         begin = Math.min(begin, debugRuleMatch.getBegin());
         end = Math.max(end, debugRuleMatch.getEnd());
         ruleMatches.add(debugRuleMatch);

Added: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/jflex/org/apache/uima/ruta/seed/SeedLexer.flex
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/jflex/org/apache/uima/ruta/seed/SeedLexer.flex?rev=1851430&view=auto
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/jflex/org/apache/uima/ruta/seed/SeedLexer.flex
 (added)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/jflex/org/apache/uima/ruta/seed/SeedLexer.flex
 Wed Jan 16 11:45:02 2019
@@ -0,0 +1,215 @@
+/*
+ * 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.seed;
+import java.util.*;
+import java.util.regex.*;
+
+import org.apache.uima.cas.text.AnnotationFS;
+import org.apache.uima.jcas.JCas;
+
+import org.apache.uima.ruta.type.AMP;
+import org.apache.uima.ruta.type.BREAK;
+import org.apache.uima.ruta.type.CAP;
+import org.apache.uima.ruta.type.COLON;
+import org.apache.uima.ruta.type.COMMA;
+import org.apache.uima.ruta.type.CW;
+import org.apache.uima.ruta.type.EXCLAMATION;
+import org.apache.uima.ruta.type.MARKUP;
+import org.apache.uima.ruta.type.NBSP;
+import org.apache.uima.ruta.type.NUM;
+import org.apache.uima.ruta.type.PERIOD;
+import org.apache.uima.ruta.type.QUESTION;
+import org.apache.uima.ruta.type.SEMICOLON;
+import org.apache.uima.ruta.type.SPACE;
+import org.apache.uima.ruta.type.SPECIAL;
+import org.apache.uima.ruta.type.SW;
+
+%%
+
+%{
+    private JCas cas;
+        
+    public void setJCas(JCas cas) {
+        this.cas = cas;
+    }
+%}
+
+%unicode
+%line
+%char
+%type AnnotationFS
+%class SeedLexer
+
+ALPHA=[A-Za-z]
+DIGIT=[0-9]
+WHITE_SPACE_CHAR=[\n\r\ \t\b\012]
+BREAK=[\n\r\b\012\u000b]
+SPACE=[ \t]
+
+%%
+
+
+<YYINITIAL> {
+    
+    \<[/][!][^>]*> {
+                MARKUP t = new MARKUP(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+                    
+    \<[!][^>]*> {
+                MARKUP t = new MARKUP(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+    
+                                       
+    \u00A0|\u202F|\uFEFF|\u2007|\u180E|&nbsp;|&NBSP; {
+                NBSP t = new NBSP(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    &{ALPHA}+; {
+                AMP t = new AMP(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    {BREAK} {
+                BREAK t = new BREAK(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    {SPACE} {
+                SPACE t = new SPACE(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    ":" {
+                COLON t = new COLON(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    "," {
+                COMMA t = new COMMA(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    "." {
+                PERIOD t = new PERIOD(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    
+    "!" {
+                EXCLAMATION t = new EXCLAMATION(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;    
+    }
+
+    ";" {
+                SEMICOLON t = new SEMICOLON(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    "?" {
+                QUESTION t = new QUESTION(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    [:lowercase:]+ {
+                SW t = new SW(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    [:uppercase:][:lowercase:]* {
+                CW t = new CW(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    [:uppercase:]+ {
+                CAP t = new CAP(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    {DIGIT}+ {
+                NUM t = new NUM(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    . {
+                SPECIAL t = new SPECIAL(cas);
+                t.setBegin(yychar);
+                t.setEnd(yychar + yytext().length());
+                
+                return t;
+    }
+
+    <<EOF>> {
+                return null;
+    }
+
+}
+

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/resources/org/apache/uima/ruta/engine/BasicEngine.xml
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/main/resources/org/apache/uima/ruta/engine/BasicEngine.xml?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/resources/org/apache/uima/ruta/engine/BasicEngine.xml
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/main/resources/org/apache/uima/ruta/engine/BasicEngine.xml
 Wed Jan 16 11:45:02 2019
@@ -240,6 +240,12 @@
         <multiValued>false</multiValued>
         <mandatory>false</mandatory>
     </configurationParameter>
+    <configurationParameter>
+        <name>csvSeparator</name>
+        <type>String</type>
+        <multiValued>false</multiValued>
+        <mandatory>false</mandatory>
+    </configurationParameter>
     </configurationParameters>
     <configurationParameterSettings>
       <nameValuePair>

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/FeatureMatch1Test.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/FeatureMatch1Test.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/FeatureMatch1Test.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/FeatureMatch1Test.java
 Wed Jan 16 11:45:02 2019
@@ -19,25 +19,33 @@
 
 package org.apache.uima.ruta;
 
+import java.io.IOException;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
 import org.apache.uima.cas.CAS;
+import org.apache.uima.resource.ResourceConfigurationException;
+import org.apache.uima.resource.ResourceInitializationException;
 import org.apache.uima.ruta.engine.RutaEngine;
 import org.apache.uima.ruta.engine.RutaTestUtils;
 import org.apache.uima.ruta.engine.RutaTestUtils.TestFeature;
+import org.apache.uima.util.InvalidXMLException;
 import org.junit.Test;
 
 public class FeatureMatch1Test {
 
   @Test
-  public void test() {
+  public void test() throws AnalysisEngineProcessException, 
InvalidXMLException,
+          ResourceInitializationException, ResourceConfigurationException, 
URISyntaxException,
+          IOException {
     String name = this.getClass().getSimpleName();
     String namespace = 
this.getClass().getPackage().getName().replaceAll("\\.", "/");
-    CAS cas = null;
+
     Map<String, String> complexTypes = new HashMap<String, String>();
     Map<String, List<TestFeature>> features = new TreeMap<String, 
List<TestFeature>>();
     String typeNameA = "org.apache.uima.ruta.FeatureMatchTest.A";
@@ -69,13 +77,8 @@ public class FeatureMatch1Test {
     String fnds = "ds";
     listD.add(new TestFeature(fnds, "", "uima.cas.String"));
 
-    try {
-      cas = RutaTestUtils.process(namespace + "/" + name + 
RutaEngine.SCRIPT_FILE_EXTENSION,
-              namespace + "/" + name + ".txt", 50, false, false, complexTypes, 
features, null);
-    } catch (Exception e) {
-      e.printStackTrace();
-      assert (false);
-    }
+    CAS cas = RutaTestUtils.process(namespace + "/" + name + 
RutaEngine.SCRIPT_FILE_EXTENSION,
+            namespace + "/" + name + ".txt", 50, false, false, complexTypes, 
features, null);
 
     RutaTestUtils.assertAnnotationsEquals(cas, 1, 1, "Marshall");
     RutaTestUtils.assertAnnotationsEquals(cas, 2, 1, "Marshall");
@@ -93,8 +96,10 @@ public class FeatureMatch1Test {
     RutaTestUtils.assertAnnotationsEquals(cas, 14, 3, "Kluegl", "Kottmann", 
"Schor");
     RutaTestUtils.assertAnnotationsEquals(cas, 15, 3, "Peter", "Joern", 
"Marshall");
     RutaTestUtils.assertAnnotationsEquals(cas, 16, 1, "Peter Kluegl, Joern 
Kottmann, Marshall");
-    RutaTestUtils.assertAnnotationsEquals(cas, 17, 1, "Peter Kluegl, Joern 
Kottmann, Marshall Schor");
-    RutaTestUtils.assertAnnotationsEquals(cas, 18, 1, "Peter Kluegl, Joern 
Kottmann, Marshall Schor");
+    RutaTestUtils.assertAnnotationsEquals(cas, 17, 1,
+            "Peter Kluegl, Joern Kottmann, Marshall Schor");
+    RutaTestUtils.assertAnnotationsEquals(cas, 18, 1,
+            "Peter Kluegl, Joern Kottmann, Marshall Schor");
 
     cas.release();
   }

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ImportStatementsTest.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ImportStatementsTest.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ImportStatementsTest.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ImportStatementsTest.java
 Wed Jan 16 11:45:02 2019
@@ -27,6 +27,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.uima.analysis_engine.AnalysisEngine;
 import org.apache.uima.analysis_engine.AnalysisEngineDescription;
 import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
@@ -35,10 +36,18 @@ import org.apache.uima.cas.text.Annotati
 import org.apache.uima.fit.factory.AnalysisEngineFactory;
 import org.apache.uima.fit.factory.TypeSystemDescriptionFactory;
 import org.apache.uima.fit.util.CasUtil;
+import org.apache.uima.fit.util.JCasUtil;
 import org.apache.uima.resource.ResourceInitializationException;
 import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.apache.uima.ruta.descriptor.RutaBuildOptions;
+import org.apache.uima.ruta.descriptor.RutaDescriptorFactory;
+import org.apache.uima.ruta.descriptor.RutaDescriptorInformation;
 import org.apache.uima.ruta.engine.RutaEngine;
+import org.apache.uima.ruta.type.FalsePositive;
+import org.apache.uima.ruta.type.TruePositive;
 import org.apache.uima.util.InvalidXMLException;
+import org.junit.Assert;
+import org.junit.Ignore;
 import org.junit.Test;
 
 /**
@@ -46,25 +55,28 @@ import org.junit.Test;
  */
 public class ImportStatementsTest {
   private final String NAME = this.getClass().getSimpleName();
+
   private final String NAMESPACE = 
this.getClass().getPackage().getName().replaceAll("\\.", "/");
 
   /**
    * Create an analysis engine for a Ruta script.
    *
-   * @param script       Script path.
-   * @param strictImport {@link 
org.apache.uima.ruta.engine.RutaEngine#PARAM_STRICT_IMPORTS} value.
+   * @param script
+   *          Script path.
+   * @param strictImport
+   *          {@link 
org.apache.uima.ruta.engine.RutaEngine#PARAM_STRICT_IMPORTS} value.
    * @return Analysis engine.
    */
-  private AnalysisEngine createAE(String script, boolean strictImport) throws 
ResourceInitializationException, IOException, InvalidXMLException {
+  private AnalysisEngine createAE(String script, boolean strictImport)
+          throws ResourceInitializationException, IOException, 
InvalidXMLException {
     final TypeSystemDescription tsd = 
TypeSystemDescriptionFactory.createTypeSystemDescription(
-        "org.apache.uima.ruta.engine.BasicTypeSystem",
-        "org.apache.uima.ruta.ImportStatementsTestTypeSystem",
-        
"org.apache.uima.ruta.ImportStatementsTestTypeSystemWithAmbiguousShortNames",
-        "org.apache.uima.ruta.ImportStatementsTestTypeSystemWithManyPackages");
+            "org.apache.uima.ruta.engine.BasicTypeSystem",
+            "org.apache.uima.ruta.ImportStatementsTestTypeSystem",
+            
"org.apache.uima.ruta.ImportStatementsTestTypeSystemWithAmbiguousShortNames",
+            
"org.apache.uima.ruta.ImportStatementsTestTypeSystemWithManyPackages");
     final AnalysisEngineDescription ruta = 
AnalysisEngineFactory.createEngineDescription(
-        "org.apache.uima.ruta.engine.BasicEngine",
-        RutaEngine.PARAM_MAIN_SCRIPT, script,
-        RutaEngine.PARAM_STRICT_IMPORTS, strictImport);
+            "org.apache.uima.ruta.engine.BasicEngine", 
RutaEngine.PARAM_MAIN_SCRIPT, script,
+            RutaEngine.PARAM_STRICT_IMPORTS, strictImport);
 
     ruta.getAnalysisEngineMetaData().setTypeSystem(tsd);
 
@@ -241,7 +253,8 @@ public class ImportStatementsTest {
 
   @Test
   public void testImportAllPackagesWithAliasFromTypeSystem() throws Exception {
-    AnalysisEngine ae = createAE(NAMESPACE + "/" + NAME + 
"ImportAllPackagesWithAliasFromTypeSystem", true);
+    AnalysisEngine ae = createAE(
+            NAMESPACE + "/" + NAME + 
"ImportAllPackagesWithAliasFromTypeSystem", true);
     try {
       CAS cas = ae.newCAS();
       cas.setDocumentText("First Second");
@@ -256,7 +269,9 @@ public class ImportStatementsTest {
 
   @Test
   public void testImportAllPackagesFromTypeSystemWithAmbiguousShortNames() 
throws Exception {
-    AnalysisEngine ae = createAE(NAMESPACE + "/" + NAME + 
"ImportAllPackagesFromTypeSystemWithAmbiguousShortNames", true);
+    AnalysisEngine ae = createAE(
+            NAMESPACE + "/" + NAME + 
"ImportAllPackagesFromTypeSystemWithAmbiguousShortNames",
+            true);
     try {
       CAS cas = ae.newCAS();
       cas.setDocumentText("First Second");
@@ -274,6 +289,38 @@ public class ImportStatementsTest {
     }
   }
 
+  @Test
+  @Ignore
+  public void testDeclareWithAliasParent() throws Exception {
+
+    String document = "This is a test.";
+    String script = "PACKAGE test.package;\n";
+    script += "IMPORT PACKAGE * FROM 
org.apache.uima.ruta.engine.PlainTextTypeSystem AS pt;\n";
+    script += "IMPORT org.apache.uima.ruta.type.Paragraph FROM 
org.apache.uima.ruta.engine.PlainTextTypeSystem AS Para;\n";
+    script += "DECLARE pt.Line SubLine;\n";
+    script += "DECLARE Para SubPara;\n";
+    script += "Document{-> SubLine, SubPara};\n";
+    script += "SubLine{-> TruePositive};";
+    script += "SubPara{-> FalsePositive};";
+
+    RutaDescriptorFactory factory = new RutaDescriptorFactory();
+    RutaDescriptorInformation descriptorInformation = 
factory.parseDescriptorInformation(script);
+    RutaBuildOptions options = new RutaBuildOptions();
+    Pair<AnalysisEngineDescription, TypeSystemDescription> descriptions = 
factory
+            .createDescriptions(null, null, descriptorInformation, options, 
null, null, null);
+
+    AnalysisEngineDescription analysisEngineDescription = 
descriptions.getKey();
+    AnalysisEngine analysisEngine = 
AnalysisEngineFactory.createEngine(analysisEngineDescription);
+
+    CAS cas = analysisEngine.newCAS();
+    cas.setDocumentText(document);
+
+    analysisEngine.process(cas);
+
+    Assert.assertEquals(1, JCasUtil.select(cas.getJCas(), 
TruePositive.class).size());
+    Assert.assertEquals(1, JCasUtil.select(cas.getJCas(), 
FalsePositive.class).size());
+  }
+
   private List<String> selectText(CAS cas, String type) {
     List<String> values = new ArrayList<String>();
     for (AnnotationFS annotation : CasUtil.select(cas, 
cas.getTypeSystem().getType(type))) {

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/LoadResourceFromClassPathTest.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/LoadResourceFromClassPathTest.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/LoadResourceFromClassPathTest.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/LoadResourceFromClassPathTest.java
 Wed Jan 16 11:45:02 2019
@@ -21,10 +21,7 @@ package org.apache.uima.ruta;
 
 import static org.junit.Assert.assertEquals;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
+import java.util.*;
 
 import org.apache.uima.cas.CAS;
 import org.apache.uima.cas.FSIterator;
@@ -33,6 +30,7 @@ import org.apache.uima.cas.Type;
 import org.apache.uima.cas.text.AnnotationFS;
 import org.apache.uima.cas.text.AnnotationIndex;
 import org.apache.uima.ruta.engine.Ruta;
+import org.apache.uima.ruta.engine.RutaEngine;
 import org.apache.uima.ruta.engine.RutaTestUtils;
 import org.apache.uima.ruta.engine.RutaTestUtils.TestFeature;
 import org.junit.Test;
@@ -60,14 +58,8 @@ public class LoadResourceFromClassPathTe
     list.add(new TestFeature(fn1, "", "uima.cas.String"));
     String fn2 = "system";
     list.add(new TestFeature(fn2, "", "uima.cas.String"));
-    
-    CAS cas = null;
-    try {
-      cas = RutaTestUtils.getCAS(document, complexTypes, features);
-      Ruta.apply(cas, script);
-    } catch (Exception e) {
-      e.printStackTrace();
-    }
+
+    CAS cas = executeAnalysis(document, script, complexTypes, features);
     
     RutaTestUtils.assertAnnotationsEquals(cas, 1, 3, "Peter", "Marshall", 
"Joern");
     RutaTestUtils.assertAnnotationsEquals(cas, 2, 3, "Kluegl", "Schor", 
"Kottmann");
@@ -130,13 +122,7 @@ public class LoadResourceFromClassPathTe
     String fn2 = "system";
     list.add(new TestFeature(fn2, "", "uima.cas.String"));
 
-    CAS cas = null;
-    try {
-      cas = RutaTestUtils.getCAS(document, complexTypes, features);
-      Ruta.apply(cas, script);
-    } catch (Exception e) {
-      e.printStackTrace();
-    }
+    CAS cas = executeAnalysis(document, script, complexTypes, features);
 
     RutaTestUtils.assertAnnotationsEquals(cas, 1, 3, "Peter", "Marshall", 
"Joern");
     RutaTestUtils.assertAnnotationsEquals(cas, 2, 3, "Kluegl", "Schor", 
"Kottmann");
@@ -176,4 +162,18 @@ public class LoadResourceFromClassPathTe
 
     cas.release();
   }
+
+  private CAS executeAnalysis(String document, String script, Map<String, 
String> complexTypes, Map<String, List<TestFeature>> features) {
+    CAS cas = null;
+    try {
+      Map<String, Object> map = new HashMap<>();
+      map.put(RutaEngine.PARAM_DICT_REMOVE_WS, true);
+
+      cas = RutaTestUtils.getCAS(document, complexTypes, features);
+      Ruta.apply(cas, script, map);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return cas;
+  }
 }

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/WSDictionaryTest.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/WSDictionaryTest.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/WSDictionaryTest.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/WSDictionaryTest.java
 Wed Jan 16 11:45:02 2019
@@ -70,7 +70,8 @@ public class WSDictionaryTest {
     document += "Peter<x>Kluegl, Marshall<x>Schor, Joern<x>Kottmann\n";
     String script = "WORDLIST list = 
'org/apache/uima/ruta/WSDictionaryTestList.txt';";
     script += "MARKFAST(T1, list, true, 0, false);";
-    Map<String, Object> map = new HashMap<String, Object>();
+
+    Map<String, Object> map = new HashMap<>();
     map.put(RutaEngine.PARAM_DICT_REMOVE_WS, true);
     CAS cas = RutaTestUtils.getCAS(document);
     Ruta.apply(cas, script, map);
@@ -104,7 +105,9 @@ public class WSDictionaryTest {
     CAS cas = null;
     try {
       cas = RutaTestUtils.getCAS(document, complexTypes, features);
-      Ruta.apply(cas, script);
+      Map<String, Object> map = new HashMap<>();
+      map.put(RutaEngine.PARAM_DICT_REMOVE_WS, true);
+      Ruta.apply(cas, script, map);
     } catch (Exception e) {
       e.printStackTrace();
     }

Modified: 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/action/ConfigureTest.java
URL: 
http://svn.apache.org/viewvc/uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/action/ConfigureTest.java?rev=1851430&r1=1851429&r2=1851430&view=diff
==============================================================================
--- 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/action/ConfigureTest.java
 (original)
+++ 
uima/uv3/ruta-v3/trunk/ruta-core/src/test/java/org/apache/uima/ruta/action/ConfigureTest.java
 Wed Jan 16 11:45:02 2019
@@ -28,25 +28,31 @@ import org.apache.uima.ruta.engine.Ruta;
 import org.apache.uima.ruta.engine.RutaTestUtils;
 import org.apache.uima.ruta.type.Statistics;
 import org.junit.Assert;
+import org.junit.Ignore;
 import org.junit.Test;
 
-
 public class ConfigureTest {
 
   @Test
   public void test() throws Exception {
-    
+
     String script = "ENGINE org.apache.uima.ruta.engine.CWEngine;";
     script += "CONFIGURE(CWEngine, \"profile\"= true, \"statistics\"=true);";
-    script +="EXEC(CWEngine);";
+    script += "EXEC(CWEngine);";
     CAS cas = RutaTestUtils.getCAS("Some test.");
     Ruta.apply(cas, script);
-    
+
     JCas jcas = cas.getJCas();
     Collection<Statistics> statistics = JCasUtil.select(jcas, 
Statistics.class);
-    
+
     Assert.assertFalse(statistics.isEmpty());
   }
-  
-  
+
+  @Test
+  @Ignore
+  public void testSelfConfigure() throws Exception {
+
+    RutaTestUtils.processTestScript(this.getClass());
+  }
+
 }


Reply via email to