Merge branch 'maintenance/3.1.x' into bugfix/UIMA-6405-Local-variable-not-captured-properly-in-a-wildcard-matching-condition
diff --git a/ruta-core/.gitignore b/ruta-core/.gitignore
new file mode 100644
index 0000000..862d276
--- /dev/null
+++ b/ruta-core/.gitignore
@@ -0,0 +1,2 @@
+input/
+TypeSystem.xml
diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java b/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java
index 3778925..a6e28b1 100644
--- a/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java
+++ b/ruta-core/src/main/java/org/apache/uima/ruta/RutaStream.java
@@ -1151,7 +1151,11 @@
 

     if (cas.getTypeSystem().subsumes(type, windowAnnotation.getType())) {

       if (!sensitiveToVisibility || isVisible(windowAnnotation)) {

-        result.add(windowAnnotation);

+        // the window defined by a BLOCK could actually have already been removed, thus we do not

+        // want to return it

+        if (cas.getAnnotationIndex(windowAnnotation.getType()).contains(windowAnnotation)) {

+          result.add(windowAnnotation);

+        }

       }

     }

 

diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java b/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java
index 5769578..d5230a4 100644
--- a/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java
+++ b/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaTestUtils.java
@@ -19,14 +19,18 @@
 

 package org.apache.uima.ruta.engine;

 

+import static org.apache.uima.fit.factory.TypeSystemDescriptionFactory.createTypeSystemDescription;

+

 import java.io.File;

 import java.io.FileOutputStream;

 import java.io.IOException;

 import java.io.OutputStream;

+import java.lang.management.ManagementFactory;

 import java.net.URISyntaxException;

 import java.net.URL;

 import java.util.ArrayList;

 import java.util.Collection;

+import java.util.Collections;

 import java.util.HashMap;

 import java.util.Iterator;

 import java.util.LinkedHashMap;

@@ -34,6 +38,7 @@
 import java.util.Map;

 import java.util.Map.Entry;

 import java.util.Set;

+import java.util.regex.Pattern;

 

 import org.apache.uima.UIMAFramework;

 import org.apache.uima.analysis_engine.AnalysisEngine;

@@ -60,6 +65,19 @@
 

 public class RutaTestUtils {

 

+  public static final boolean DEBUG_MODE = isDebugging();

+

+  private static boolean isDebugging() {

+

+    Pattern debugPattern = Pattern.compile("-Xdebug|jdwp");

+    for (String arg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {

+      if (debugPattern.matcher(arg).find()) {

+        return true;

+      }

+    }

+    return false;

+  }

+

   public static class TestFeature {

     public String name;

 

@@ -151,24 +169,8 @@
     AnalysisEngineDescription aed = (AnalysisEngineDescription) specifier;

 

     TypeSystemDescription basicTypeSystem = aed.getAnalysisEngineMetaData().getTypeSystem();

-    for (int i = 1; i <= amount; i++) {

-      basicTypeSystem.addType(TYPE + i, "Type for Testing", "uima.tcas.Annotation");

-    }

-

-    if (complexTypes != null) {

-      Set<Entry<String, String>> entrySet = complexTypes.entrySet();

-      for (Entry<String, String> entry : entrySet) {

-        String name = entry.getKey();

-        TypeDescription addType = basicTypeSystem.addType(name, "Type for Testing",

-                entry.getValue());

-        if (features != null) {

-          List<TestFeature> list = features.get(name);

-          for (TestFeature f : list) {

-            addType.addFeature(f.name, f.description, f.range);

-          }

-        }

-      }

-    }

+    addTestTypes(basicTypeSystem);

+    addAdditionalTypes(complexTypes, features, basicTypeSystem);

 

     Collection<TypeSystemDescription> tsds = new ArrayList<TypeSystemDescription>();

     tsds.add(basicTypeSystem);

@@ -248,23 +250,8 @@
     ResourceSpecifier specifier = UIMAFramework.getXMLParser().parseResourceSpecifier(in);

     AnalysisEngineDescription aed = (AnalysisEngineDescription) specifier;

     TypeSystemDescription basicTypeSystem = aed.getAnalysisEngineMetaData().getTypeSystem();

-    for (int i = 1; i <= 50; i++) {

-      basicTypeSystem.addType("org.apache.uima.T" + i, "Type for Testing", "uima.tcas.Annotation");

-    }

-    if (complexTypes != null) {

-      Set<Entry<String, String>> entrySet = complexTypes.entrySet();

-      for (Entry<String, String> entry : entrySet) {

-        String name = entry.getKey();

-        TypeDescription addType = basicTypeSystem.addType(name, "Type for Testing",

-                entry.getValue());

-        if (features != null) {

-          List<TestFeature> list = features.get(name);

-          for (TestFeature f : list) {

-            addType.addFeature(f.name, f.description, f.range);

-          }

-        }

-      }

-    }

+    addTestTypes(basicTypeSystem);

+    addAdditionalTypes(complexTypes, features, basicTypeSystem);

     Collection<TypeSystemDescription> tsds = new ArrayList<TypeSystemDescription>();

     tsds.add(basicTypeSystem);

     TypeSystemDescription mergeTypeSystems = CasCreationUtils.mergeTypeSystems(tsds);

@@ -282,6 +269,31 @@
     return cas;

   }

 

+  public static void addTestTypes(TypeSystemDescription typeSystemDescription) {

+    for (int i = 1; i <= 50; i++) {

+      typeSystemDescription.addType("org.apache.uima.T" + i, "Type for Testing",

+              "uima.tcas.Annotation");

+    }

+  }

+

+  private static void addAdditionalTypes(Map<String, String> complexTypes,

+          Map<String, List<TestFeature>> features, TypeSystemDescription typeSystemDescription) {

+    if (complexTypes != null) {

+      Set<Entry<String, String>> entrySet = complexTypes.entrySet();

+      for (Entry<String, String> entry : entrySet) {

+        String name = entry.getKey();

+        TypeDescription addType = typeSystemDescription.addType(name, "Type for Testing",

+                entry.getValue());

+        if (features != null) {

+          List<TestFeature> list = features.get(name);

+          for (TestFeature f : list) {

+            addType.addFeature(f.name, f.description, f.range);

+          }

+        }

+      }

+    }

+  }

+

   public static void printAnnotations(CAS cas, int typeId) {

     Type t = getTestType(cas, typeId);

     AnnotationIndex<AnnotationFS> ai = cas.getAnnotationIndex(t);

@@ -366,4 +378,34 @@
     }

   }

 

+  public static void storeTypeSystem() {

+    storeTypeSystem(Collections.emptyMap(), Collections.emptyMap());

+  }

+

+  public static void storeTypeSystem(Map<String, String> complexTypes,

+          Map<String, List<TestFeature>> features) {

+

+    File tsFile = new File("TypeSystem.xml");

+

+    try {

+

+      TypeSystemDescription typeSystemDescription = createTypeSystemDescription();

+      addTestTypes(typeSystemDescription);

+      addAdditionalTypes(complexTypes, features, typeSystemDescription);

+      try (OutputStream os = new FileOutputStream(tsFile)) {

+        typeSystemDescription.toXML(os);

+      }

+    } catch (Exception e) {

+      throw new IllegalStateException(e);

+    }

+  }

+

+  public static Map<String, Object> getDebugParams() {

+    Map<String, Object> params = new LinkedHashMap<>();

+    params.put(RutaEngine.PARAM_DEBUG, true);

+    params.put(RutaEngine.PARAM_DEBUG_WITH_MATCHES, true);

+    params.put(RutaEngine.PARAM_CREATED_BY, true);

+    return params;

+  }

+

 }

diff --git a/ruta-core/src/test/java/org/apache/uima/ruta/action/UnmarkTest.java b/ruta-core/src/test/java/org/apache/uima/ruta/action/UnmarkTest.java
index 64b7152..3eb4289 100644
--- a/ruta-core/src/test/java/org/apache/uima/ruta/action/UnmarkTest.java
+++ b/ruta-core/src/test/java/org/apache/uima/ruta/action/UnmarkTest.java
@@ -20,6 +20,7 @@
 package org.apache.uima.ruta.action;

 

 import java.util.ArrayList;

+import java.util.LinkedHashMap;

 import java.util.List;

 import java.util.Map;

 import java.util.TreeMap;

@@ -43,45 +44,70 @@
 

     cas.release();

   }

-  

-  

+

   @Test

   public void testAnnotationExpression() throws Exception {

-    Map<String, String> typeMap = new TreeMap<String, String>();

+    Map<String, String> typeMap = new LinkedHashMap<String, String>();

     typeMap.put("Complex", "uima.tcas.Annotation");

     Map<String, List<TestFeature>> featureMap = new TreeMap<String, List<TestFeature>>();

-    List<TestFeature> list = new ArrayList<RutaTestUtils.TestFeature>();

+    List<TestFeature> list = new ArrayList<>();

     featureMap.put("Complex", list);

     list.add(new TestFeature("inner", "", "uima.tcas.Annotation"));

-    

+

     CAS cas = RutaTestUtils.getCAS("This is a test.", typeMap, featureMap);

     String script = "";

     script += "CW{->T1};t:T1 SW SW{-> UNMARK(t)};";

     script += "CW{->T2};\n t:T2 # PERIOD{-> Complex, Complex.inner=t};\n Complex{-> UNMARK(Complex.inner)};\n";

     Ruta.apply(cas, script);

-    

+

     RutaTestUtils.assertAnnotationsEquals(cas, 1, 0);

     RutaTestUtils.assertAnnotationsEquals(cas, 2, 0);

-    

+

   }

-  

+

   @Test

-  public void testAnnotationListExpression()  throws Exception {

-    Map<String, String> typeMap = new TreeMap<String, String>();

+  public void testAnnotationListExpression() throws Exception {

+    Map<String, String> typeMap = new LinkedHashMap<String, String>();

     typeMap.put("Complex", "uima.tcas.Annotation");

     Map<String, List<TestFeature>> featureMap = new TreeMap<String, List<TestFeature>>();

-    List<TestFeature> list = new ArrayList<RutaTestUtils.TestFeature>();

+    List<TestFeature> list = new ArrayList<>();

     featureMap.put("Complex", list);

     list.add(new TestFeature("inner", "", "uima.cas.FSArray"));

-    

+

     CAS cas = RutaTestUtils.getCAS("This is a test.", typeMap, featureMap);

     String script = "";

     script += "W{->T1}; Document{-> Complex, Complex.inner = T1};";

     script += "Complex{-> UNMARK(Complex.inner)};\n";

     Ruta.apply(cas, script);

-    

+

     RutaTestUtils.assertAnnotationsEquals(cas, 1, 0);

     RutaTestUtils.assertAnnotationsEquals(cas, 2, 0);

   }

-  

+

+  @Test

+  public void testUnmarkWithFeatureMatchInBlock() throws Exception {

+

+    Map<String, String> typeMap = new LinkedHashMap<String, String>();

+    typeMap.put("Struct", "uima.tcas.Annotation");

+    Map<String, List<TestFeature>> featureMap = new TreeMap<String, List<TestFeature>>();

+    List<TestFeature> list = new ArrayList<>();

+    featureMap.put("Struct", list);

+    list.add(new TestFeature("s", "", CAS.TYPE_NAME_STRING));

+

+    CAS cas = RutaTestUtils.getCAS("This is a test.", typeMap, featureMap);

+    String script = "\"a\"{->s:Struct,Struct.s=\"foo\"};";

+    script += "BLOCK(SoftRemove) Struct.s==\"foo\"{} {\r\n"

+            + "    t:Struct.s==\"foo\"{-> UNMARK(t)};\r\n" //

+            + "    t:Struct.s==\"foo\"{-> T1}; \r\n" + "}";

+

+    Ruta.apply(cas, script, RutaTestUtils.getDebugParams());

+

+    if (RutaTestUtils.DEBUG_MODE) {

+      RutaTestUtils.storeTypeSystem(typeMap, featureMap);

+      RutaTestUtils.storeCas(cas, "testUnmarkWithFeatureMatchInBlock");

+    }

+

+    RutaTestUtils.assertAnnotationsEquals(cas, 1, 0);

+  }

+

 }