You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by ap...@apache.org on 2013/09/24 05:03:56 UTC

svn commit: r1525767 - in /uima/sandbox/ruta/trunk/ruta-core/src: main/java/org/apache/uima/ruta/ test/java/org/apache/uima/ruta/ test/resources/org/apache/uima/ruta/

Author: apatry
Date: Tue Sep 24 03:03:56 2013
New Revision: 1525767

URL: http://svn.apache.org/r1525767
Log:
[UIMA-3292] Conflicting types are not flagged by RUTA

- Raise an IllegalArgumentException when an ambiguous type is used.
- Add a unit test

Added:
    uima/sandbox/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ConflictingTypeTest.java
    uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeSystem.xml
    uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeTest.ruta
Modified:
    uima/sandbox/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaEnvironment.java

Modified: uima/sandbox/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaEnvironment.java
URL: http://svn.apache.org/viewvc/uima/sandbox/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaEnvironment.java?rev=1525767&r1=1525766&r2=1525767&view=diff
==============================================================================
--- uima/sandbox/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaEnvironment.java (original)
+++ uima/sandbox/ruta/trunk/ruta-core/src/main/java/org/apache/uima/ruta/RutaEnvironment.java Tue Sep 24 03:03:56 2013
@@ -23,6 +23,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -69,10 +70,18 @@ public class RutaEnvironment {
 
   private RutaBlock owner;
 
+  /**
+   * Mapping from short type name (e.g. {@code W}) to their disambiguated long type names
+   * (e.g. {@code org.apache.uima.ruta.type.W}).
+   */
   private Map<String, String> namespaces;
 
-  private Map<String, Object> variableValues;
+  /**
+   * Mapping from ambiguous short type names to all their possible long type names.
+   */
+  private Map<String, Set<String>> ambiguousTypeAlias;
 
+  private Map<String, Object> variableValues;
   private Map<String, Class<?>> variableTypes;
 
   private Map<String, Class<?>> availableTypes;
@@ -92,6 +101,7 @@ public class RutaEnvironment {
     this.owner = owner;
     types = new HashMap<String, Type>();
     namespaces = new HashMap<String, String>();
+    ambiguousTypeAlias = new HashMap<String, Set<String>>();
     wordLists = new HashMap<String, RutaWordList>();
     tables = new HashMap<String, CSVTable>();
     variableValues = new HashMap<String, Object>();
@@ -136,8 +146,14 @@ public class RutaEnvironment {
           addType(type);
         }
       }
+
+      // "Document" can be resolved to "uima.tcas.DocumentAnnotation" or "org.apache.uima.ruta.type.Document",
+      // we force it to the former
+      ambiguousTypeAlias.remove("Document");
+      namespaces.remove("Document");
       Type documentType = cas.getTypeSystem().getType(UIMAConstants.TYPE_DOCUMENT);
       addType("Document", documentType);
+
       Type annotationType = cas.getJCas().getCasType(org.apache.uima.jcas.tcas.Annotation.type);
       addType("Annotation", annotationType);
     } catch (CASException e) {
@@ -175,12 +191,31 @@ public class RutaEnvironment {
       complete = string;
       String[] split = complete.split("\\p{Punct}");
       String name = split[split.length - 1];
-      namespaces.put(name, complete);
+      importType(complete, name);
     }
     return complete;
   }
 
+  /**
+   * Resolves an annotation type.
+   *
+   * @param match Annotation type to resolve.
+   * @return Resolved annotation type or null if match is unknown.
+   * @throws IllegalArgumentException When {@code match} is ambiguous.
+   */
   public Type getType(String match) {
+    // make sure that match is not ambiguous
+    Set<String> ambiguousTargets = ambiguousTypeAlias.get(match);
+    if (ambiguousTargets != null) {
+      StringBuilder message = new StringBuilder(match);
+      message.append(" is ambiguous, use one of the following instead : ");
+      for (String target : ambiguousTargets) {
+        message.append(target).append(' ');
+      }
+      throw new IllegalArgumentException(message.toString());
+    }
+
+    // try to resolve match
     String expanded = expand(match);
     Type type = types.get(expanded);
     if (type == null) {
@@ -189,11 +224,12 @@ public class RutaEnvironment {
         type = parent.getEnvironment().getType(match);
       }
     }
+
     return type;
   }
 
   public void addType(String string, Type type) {
-    namespaces.put(string, type.getName());
+    importType(type.getName(), string);
     types.put(type.getName(), type);
   }
 
@@ -201,6 +237,35 @@ public class RutaEnvironment {
     addType(type.getShortName(), type);
   }
 
+  /**
+   * Import a type in the current namespace.
+   *
+   * @param longName  Complete type name.
+   * @param shortName Short type name (without namespace).
+   */
+  private void importType(String longName, String shortName) {
+    Set<String> targets = ambiguousTypeAlias.get(shortName);
+    if (targets != null) {
+      // shortName is already ambiguous, add longName to its list of possible targets
+      targets.add(longName);
+    } else {
+      String existing = namespaces.put(shortName, longName);
+
+      if (existing != null && !existing.equals(longName)) {
+        // shortName can now be resolved to "existing" or "longName"
+        targets = new HashSet<String>(2);
+        targets.add(existing);
+        targets.add(longName);
+
+        // add existing mapping and longName to its list of possible targets
+        ambiguousTypeAlias.put(shortName, targets);
+
+        // remove shortName from the namespace because it is ambiguous
+        namespaces.remove(shortName);
+      }
+    }
+  }
+
   public RutaWordList getWordList(String list) {
     RutaWordList result = wordLists.get(list);
     if (result == null) {
@@ -313,7 +378,7 @@ public class RutaEnvironment {
   public boolean isVariableOfType(String name, String type) {
     return ownsVariableOfType(name, type)
             || (owner.getParent() != null && owner.getParent().getEnvironment()
-                    .isVariableOfType(name, type));
+            .isVariableOfType(name, type));
   }
 
   public Class<?> getVariableType(String name) {

Added: uima/sandbox/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ConflictingTypeTest.java
URL: http://svn.apache.org/viewvc/uima/sandbox/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ConflictingTypeTest.java?rev=1525767&view=auto
==============================================================================
--- uima/sandbox/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ConflictingTypeTest.java (added)
+++ uima/sandbox/ruta/trunk/ruta-core/src/test/java/org/apache/uima/ruta/ConflictingTypeTest.java Tue Sep 24 03:03:56 2013
@@ -0,0 +1,85 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+
+import org.apache.uima.analysis_engine.AnalysisEngine;
+import org.apache.uima.analysis_engine.AnalysisEngineDescription;
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
+import org.apache.uima.cas.CAS;
+import org.apache.uima.fit.factory.AnalysisEngineFactory;
+import org.apache.uima.fit.factory.TypeSystemDescriptionFactory;
+import org.apache.uima.resource.ResourceInitializationException;
+import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.apache.uima.ruta.engine.RutaEngine;
+import org.apache.uima.util.InvalidXMLException;
+import org.junit.Test;
+
+/**
+ * There is no warning when short type names are ambiguous.
+ */
+public class ConflictingTypeTest {
+  /**
+   * Create an analysis engine for a Ruta script.
+   *
+   * @param script Script path.
+   * @return Analysis engine.
+   */
+  private AnalysisEngine createAE(String script) throws ResourceInitializationException, IOException, InvalidXMLException {
+    final TypeSystemDescription tsd = TypeSystemDescriptionFactory.createTypeSystemDescription(
+            "org.apache.uima.ruta.BasicTypeSystem",
+            "org.apache.uima.ruta.ConflictingTypeSystem");
+    final AnalysisEngineDescription ruta = AnalysisEngineFactory.createEngineDescription(
+            "org.apache.uima.ruta.engine.BasicEngine",
+            RutaEngine.PARAM_MAIN_SCRIPT, script);
+
+    ruta.getAnalysisEngineMetaData().setTypeSystem(tsd);
+    ruta.getAnalysisEngineMetaData()
+            .getTypeSystem()
+            .addType("org.apache.uima.T1", "Type for Testing", "uima.tcas.Annotation");
+
+    return AnalysisEngineFactory.createEngine(ruta);
+  }
+
+  @Test
+  public void test() throws ResourceInitializationException, IOException, InvalidXMLException, AnalysisEngineProcessException {
+    final String name = getClass().getSimpleName();
+    final String namespace = getClass().getPackage().getName();
+    final AnalysisEngine ae = createAE(namespace + "." + name);
+    final CAS cas = ae.newCAS();
+
+    cas.setDocumentText("text is not relevant here");
+
+    try {
+      ae.process(cas);
+      fail("An IllegalArgumentException should be triggered because W is ambiguous.");
+    } catch (AnalysisEngineProcessException e) {
+      // we are expecting an IllegalArgumentException because both org.apache.uima.ruta.type.W and
+      // org.apache.uima.ruta.type.conflicting.W are imported into RUTA's namespace as W;
+      assertTrue(e.getCause() instanceof IllegalArgumentException);
+    } finally {
+        cas.release();
+        ae.destroy();
+    }
+  }
+}

Added: uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeSystem.xml
URL: http://svn.apache.org/viewvc/uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeSystem.xml?rev=1525767&view=auto
==============================================================================
--- uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeSystem.xml (added)
+++ uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeSystem.xml Tue Sep 24 03:03:56 2013
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+
+<typeSystemDescription xmlns="http://uima.apache.org/resourceSpecifier">
+    <name>ConflictingTypeSystem</name>
+    <description>
+        A type system having type whose short names conflict with BasicTypeSystem.
+    </description>
+    <version>1.0</version>
+    <vendor/>
+    <types>
+        <typeDescription>
+            <name>org.apache.uima.ruta.type.conflicting.W</name>
+            <description/>
+            <supertypeName>org.apache.uima.ruta.type.ANY</supertypeName>
+        </typeDescription>
+    </types>
+</typeSystemDescription>

Added: uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeTest.ruta
URL: http://svn.apache.org/viewvc/uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeTest.ruta?rev=1525767&view=auto
==============================================================================
--- uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeTest.ruta (added)
+++ uima/sandbox/ruta/trunk/ruta-core/src/test/resources/org/apache/uima/ruta/ConflictingTypeTest.ruta Tue Sep 24 03:03:56 2013
@@ -0,0 +1,6 @@
+PACKAGE org.apache.uima;
+
+DECLARE T1;
+
+// there is no way to know if this matches org.apache.uima.ruta.ConflictingTypeSystem.W or org.apache.uima.ruta.W
+W{->T1};
\ No newline at end of file