You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2022/02/17 14:54:40 UTC

[uima-uimaj] branch feature/UIMA-6418-Support-additional-parameters-value-types created (now 708df2c)

This is an automated email from the ASF dual-hosted git repository.

rec pushed a change to branch feature/UIMA-6418-Support-additional-parameters-value-types
in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git.


      at 708df2c  [UIMA-6418] Support additional parameters value types

This branch includes the following new commits:

     new 708df2c  [UIMA-6418] Support additional parameters value types

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[uima-uimaj] 01/01: [UIMA-6418] Support additional parameters value types

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch feature/UIMA-6418-Support-additional-parameters-value-types
in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git

commit 708df2cb39d39236eac4f628a083d3278113c207
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Thu Feb 17 15:54:33 2022 +0100

    [UIMA-6418] Support additional parameters value types
    
    - Added support for Long and Double values
    - Bit of code and test cleaning - e.g. replace if/else cascades with switch/case in some places
---
 .../impl/ConfigurationManagerImplBase.java         |  51 +--
 .../resource/impl/ConfigurationManager_impl.java   |  55 +++-
 .../resource/metadata/ConfigurationParameter.java  |  12 +-
 .../metadata/impl/ConfigurationParameter_impl.java |  54 +++-
 .../metadata/impl/ResourceMetaData_impl.java       |  30 +-
 .../resource/ConfigurableResource_implTest.java    | 351 +++++++++++----------
 .../taeconfigurator/editors/ui/ValueSection.java   |  35 +-
 7 files changed, 357 insertions(+), 231 deletions(-)

diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManagerImplBase.java b/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManagerImplBase.java
index a00a793..a0f2cb4 100644
--- a/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManagerImplBase.java
+++ b/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManagerImplBase.java
@@ -600,32 +600,45 @@ public abstract class ConfigurationManagerImplBase implements ConfigurationManag
    * @return the expected value class
    */
   protected Class<?> getParameterExpectedValueClass(ConfigurationParameter aParam) {
-    String paramType = aParam.getType();
+    if (aParam == null) {
+      throw new UIMARuntimeException();
+    }
+
     if (aParam.isMultiValued()) {
-      if (ConfigurationParameter.TYPE_STRING.equals(paramType)) {
-        return String[].class;
-      } else if (ConfigurationParameter.TYPE_BOOLEAN.equals(paramType)) {
-        return Boolean[].class;
-      } else if (ConfigurationParameter.TYPE_INTEGER.equals(paramType)) {
-        return Integer[].class;
-      } else if (ConfigurationParameter.TYPE_FLOAT.equals(paramType)) {
-        return Float[].class;
+      switch (aParam.getType()) {
+        case ConfigurationParameter.TYPE_STRING:
+          return String[].class;
+        case ConfigurationParameter.TYPE_BOOLEAN:
+          return Boolean[].class;
+        case ConfigurationParameter.TYPE_INTEGER:
+          return Integer[].class;
+        case ConfigurationParameter.TYPE_LONG:
+          return Long[].class;
+        case ConfigurationParameter.TYPE_FLOAT:
+          return Float[].class;
+        case ConfigurationParameter.TYPE_DOUBLE:
+          return Double[].class;
+        default:
+          throw new UIMARuntimeException();
       }
-    } else
-    // single-valued
-    {
-      if (ConfigurationParameter.TYPE_STRING.equals(paramType)) {
+    }
+
+    switch (aParam.getType()) {
+      case ConfigurationParameter.TYPE_STRING:
         return String.class;
-      } else if (ConfigurationParameter.TYPE_BOOLEAN.equals(paramType)) {
+      case ConfigurationParameter.TYPE_BOOLEAN:
         return Boolean.class;
-      } else if (ConfigurationParameter.TYPE_INTEGER.equals(paramType)) {
+      case ConfigurationParameter.TYPE_INTEGER:
         return Integer.class;
-      } else if (ConfigurationParameter.TYPE_FLOAT.equals(paramType)) {
+      case ConfigurationParameter.TYPE_LONG:
+        return Long.class;
+      case ConfigurationParameter.TYPE_FLOAT:
         return Float.class;
-      }
+      case ConfigurationParameter.TYPE_DOUBLE:
+        return Double.class;
+      default:
+        throw new UIMARuntimeException();
     }
-    // assert false;
-    throw new UIMARuntimeException();
   }
 
   /**
diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManager_impl.java b/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManager_impl.java
index 9a4e03c..72d1fc0 100644
--- a/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManager_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/resource/impl/ConfigurationManager_impl.java
@@ -146,26 +146,48 @@ public class ConfigurationManager_impl extends ConfigurationManagerImplBase {
    * Create the appropriate type of parameter object from the value of the external override
    */
   private Object createParam(String value, String paramType) throws ResourceConfigurationException {
-    if (paramType.equals(ConfigurationParameter.TYPE_BOOLEAN)) {
-      return createParamForClass(value, Boolean.class);
-    } else if (paramType.equals(ConfigurationParameter.TYPE_INTEGER)) {
-      return createParamForClass(value, Integer.class);
-    } else if (paramType.equals(ConfigurationParameter.TYPE_FLOAT)) {
-      return createParamForClass(value, Float.class);
-    } else { // Must be a string
-      return value;
+    if (paramType == null) {
+      throw new IllegalArgumentException("Parameter type cannot be null");
+    }
+
+    switch (paramType) {
+      case ConfigurationParameter.TYPE_STRING:
+        return value;
+      case ConfigurationParameter.TYPE_BOOLEAN:
+        return createParamForClass(value, Boolean.class);
+      case ConfigurationParameter.TYPE_INTEGER:
+        return createParamForClass(value, Integer.class);
+      case ConfigurationParameter.TYPE_LONG:
+        return createParamForClass(value, Long.class);
+      case ConfigurationParameter.TYPE_FLOAT:
+        return createParamForClass(value, Float.class);
+      case ConfigurationParameter.TYPE_DOUBLE:
+        return createParamForClass(value, Double.class);
+      default:
+        throw new IllegalArgumentException("Unsupported parameter type [" + paramType + "]");
     }
   }
 
   private Object createParams(String[] values, String paramType) {
-    if (paramType.equals(ConfigurationParameter.TYPE_BOOLEAN)) {
-      return createParamsForClass(values, Boolean.class);
-    } else if (paramType.equals(ConfigurationParameter.TYPE_INTEGER)) {
-      return createParamsForClass(values, Integer.class);
-    } else if (paramType.equals(ConfigurationParameter.TYPE_FLOAT)) {
-      return createParamsForClass(values, Float.class);
-    } else { // Must be a string
-      return values;
+    if (paramType == null) {
+      throw new IllegalArgumentException("Parameter type cannot be null");
+    }
+
+    switch (paramType) {
+      case ConfigurationParameter.TYPE_STRING:
+        return values;
+      case ConfigurationParameter.TYPE_BOOLEAN:
+        return createParamsForClass(values, Boolean.class);
+      case ConfigurationParameter.TYPE_INTEGER:
+        return createParamsForClass(values, Integer.class);
+      case ConfigurationParameter.TYPE_LONG:
+        return createParamsForClass(values, Long.class);
+      case ConfigurationParameter.TYPE_FLOAT:
+        return createParamsForClass(values, Float.class);
+      case ConfigurationParameter.TYPE_DOUBLE:
+        return createParamsForClass(values, Double.class);
+      default:
+        throw new IllegalArgumentException("Unsupported parameter type [" + paramType + "]");
     }
   }
 
@@ -186,7 +208,6 @@ public class ConfigurationManager_impl extends ConfigurationManagerImplBase {
                 ResourceConfigurationException.EXTERNAL_OVERRIDE_NUMERIC_ERROR,
                 new Object[] { value });
       }
-      e.printStackTrace();
       throw new ResourceConfigurationException(e);
     }
 
diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/metadata/ConfigurationParameter.java b/uimaj-core/src/main/java/org/apache/uima/resource/metadata/ConfigurationParameter.java
index 13ddee4..85707ee 100644
--- a/uimaj-core/src/main/java/org/apache/uima/resource/metadata/ConfigurationParameter.java
+++ b/uimaj-core/src/main/java/org/apache/uima/resource/metadata/ConfigurationParameter.java
@@ -28,7 +28,7 @@ import org.apache.uima.UIMA_UnsupportedOperationException;
  * <ul>
  * <li>Name</li>
  * <li>Description</li>
- * <li>Type (String, Boolean, Integer, or Float)</li>
+ * <li>Type (String, Boolean, Integer, Long, Float or Double)</li>
  * <li>Is the parameter multi-valued?</li>
  * <li>Is a value mandatory?</li>
  * <li>Overrides (see below)</li>
@@ -249,7 +249,17 @@ public interface ConfigurationParameter extends MetaDataObject {
   String TYPE_INTEGER = "Integer";
 
   /**
+   * Identifies the Long data type. Values of the parameter will be of type java.lang.Long.
+   */
+  String TYPE_LONG = "Long";
+
+  /**
    * Identifies the Float data type. Values of the parameter will be of type java.lang.Float.
    */
   String TYPE_FLOAT = "Float";
+
+  /**
+   * Identifies the Double data type. Values of the parameter will be of type java.lang.Double.
+   */
+  String TYPE_DOUBLE = "Double";
 }
diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameter_impl.java b/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameter_impl.java
index a249d6e..4f317e7 100644
--- a/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameter_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameter_impl.java
@@ -199,10 +199,11 @@ public class ConfigurationParameter_impl extends MetaDataObject_impl
    */
   @Override
   public void setOverrides(String[] aOverrides) {
-    if (aOverrides == null)
+    if (aOverrides == null) {
       mOverrides = Constants.EMPTY_STRING_ARRAY;
-    else
+    } else {
       mOverrides = aOverrides.clone();
+    }
   }
 
   /*
@@ -256,25 +257,36 @@ public class ConfigurationParameter_impl extends MetaDataObject_impl
    *         parameter described by <code>aTypeName</code> and <code>aMultiValued</code>.
    */
   public static boolean typeMatch(Class aClass, String aTypeName, boolean aMultiValued) {
+    if (aTypeName == null) {
+      throw new IllegalArgumentException("Parameter type cannot be null");
+    }
+
     if (aMultiValued) {
       // aClass must be an array
-      if (!aClass.isArray())
+      if (!aClass.isArray()) {
         return false;
+      }
 
       // Component Type of the array must match
       return typeMatch(aClass.getComponentType(), aTypeName, false);
-    } else // not multi-valued
-    {
-      if (aTypeName.equals(TYPE_STRING))
+    }
+
+    // not multi-valued
+    switch (aTypeName) {
+      case ConfigurationParameter.TYPE_STRING:
         return aClass == String.class;
-      else if (aTypeName.equals(TYPE_BOOLEAN))
+      case ConfigurationParameter.TYPE_BOOLEAN:
         return aClass == Boolean.class;
-      else if (aTypeName.equals(TYPE_INTEGER))
+      case ConfigurationParameter.TYPE_INTEGER:
         return aClass == Integer.class;
-      else if (aTypeName.equals(TYPE_FLOAT))
+      case ConfigurationParameter.TYPE_LONG:
+        return aClass == Long.class;
+      case ConfigurationParameter.TYPE_FLOAT:
         return aClass == Float.class;
-      else
-        return false;
+      case ConfigurationParameter.TYPE_DOUBLE:
+        return aClass == Double.class;
+      default:
+        throw new IllegalArgumentException("Unsupported parameter type [" + aTypeName + "]");
     }
   }
 
@@ -290,8 +302,21 @@ public class ConfigurationParameter_impl extends MetaDataObject_impl
    *         data type name.
    */
   protected static boolean isValidDataTypeName(Object aTypeName) {
-    return TYPE_STRING.equals(aTypeName) || TYPE_BOOLEAN.equals(aTypeName)
-            || TYPE_INTEGER.equals(aTypeName) || TYPE_FLOAT.equals(aTypeName);
+    if (!(aTypeName instanceof String)) {
+      return false;
+    }
+
+    switch ((String) aTypeName) {
+      case ConfigurationParameter.TYPE_STRING: // fall-through
+      case ConfigurationParameter.TYPE_BOOLEAN: // fall-through
+      case ConfigurationParameter.TYPE_INTEGER: // fall-through
+      case ConfigurationParameter.TYPE_LONG: // fall-through
+      case ConfigurationParameter.TYPE_FLOAT: // fall-through
+      case ConfigurationParameter.TYPE_DOUBLE: // fall-through
+        return true;
+      default:
+        return false;
+    }
   }
 
   /**
@@ -331,10 +356,11 @@ public class ConfigurationParameter_impl extends MetaDataObject_impl
             // get text of element
             String elemText = XMLUtils.getText(curElem, aOptions.expandEnvVarRefs);
             valueList.add(elemText);
-          } else
+          } else {
             // element type does not match
             throw new InvalidXMLException(InvalidXMLException.INVALID_ELEMENT_TYPE,
                     new Object[] { aPropXmlInfo.arrayElementTagName, curElem.getTagName() });
+          }
         }
       }
       // set property
diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ResourceMetaData_impl.java b/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ResourceMetaData_impl.java
index 42842ad..db86b25 100644
--- a/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ResourceMetaData_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ResourceMetaData_impl.java
@@ -386,16 +386,26 @@ public class ResourceMetaData_impl extends MetaDataObject_impl implements Resour
    * @return expected Java class for parameter values of this type
    */
   protected Class<?> getClassForParameterType(String paramType) {
-    if (ConfigurationParameter.TYPE_STRING.equals(paramType)) {
-      return String.class;
-    } else if (ConfigurationParameter.TYPE_BOOLEAN.equals(paramType)) {
-      return Boolean.class;
-    } else if (ConfigurationParameter.TYPE_INTEGER.equals(paramType)) {
-      return Integer.class;
-    } else if (ConfigurationParameter.TYPE_FLOAT.equals(paramType)) {
-      return Float.class;
-    } else
-      return null;
+    if (paramType == null) {
+      return null; // Legacy behavior - maybe better throw an IllegalArgumentException
+    }
+
+    switch (paramType) {
+      case ConfigurationParameter.TYPE_STRING:
+        return String.class;
+      case ConfigurationParameter.TYPE_BOOLEAN:
+        return Boolean.class;
+      case ConfigurationParameter.TYPE_INTEGER:
+        return Integer.class;
+      case ConfigurationParameter.TYPE_LONG:
+        return Long.class;
+      case ConfigurationParameter.TYPE_FLOAT:
+        return Float.class;
+      case ConfigurationParameter.TYPE_DOUBLE:
+        return Double.class;
+      default:
+        return null; // Legacy behavior - maybe better throw an IllegalArgumentException
+    }
   }
 
   /**
diff --git a/uimaj-core/src/test/java/org/apache/uima/resource/ConfigurableResource_implTest.java b/uimaj-core/src/test/java/org/apache/uima/resource/ConfigurableResource_implTest.java
index 8e54a23..85f0613 100644
--- a/uimaj-core/src/test/java/org/apache/uima/resource/ConfigurableResource_implTest.java
+++ b/uimaj-core/src/test/java/org/apache/uima/resource/ConfigurableResource_implTest.java
@@ -19,7 +19,14 @@
 
 package org.apache.uima.resource;
 
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.util.Arrays.array;
+
 import java.util.Map;
+import java.util.stream.Stream;
 
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.analysis_engine.AnalysisEngine;
@@ -40,174 +47,192 @@ public class ConfigurableResource_implTest {
 
   @Test
   public void testReconfigure() throws Exception {
-    try {
-      // set up some resource metadata and create a resource
-      ResourceCreationSpecifier specifier = new MyTestSpecifier();
-      ResourceMetaData md = specifier.getMetaData();
-      md.setName("TestResource");
-      md.setDescription("Resource used for Testing the Resource_impl base class");
-      ConfigurationParameter p1 = new ConfigurationParameter_impl();
-      p1.setName("StringParam");
-      p1.setDescription("parameter with String data type");
-      p1.setType(ConfigurationParameter.TYPE_STRING);
-      ConfigurationParameter p2 = new ConfigurationParameter_impl();
-      p2.setName("IntegerParam");
-      p2.setDescription("parameter with Integer data type");
-      p2.setType(ConfigurationParameter.TYPE_INTEGER);
-      ConfigurationParameter p3 = new ConfigurationParameter_impl();
-      p3.setName("BooleanParam");
-      p3.setDescription("parameter with Boolean data type");
-      p3.setType(ConfigurationParameter.TYPE_BOOLEAN);
-      ConfigurationParameter p4 = new ConfigurationParameter_impl();
-      p4.setName("FloatParam");
-      p4.setDescription("parameter with Float data type");
-      p4.setType(ConfigurationParameter.TYPE_FLOAT);
-      ConfigurationParameter p5 = new ConfigurationParameter_impl();
-      p5.setName("StringArrayParam");
-      p5.setDescription("mutli-valued parameter with String data type");
-      p5.setType(ConfigurationParameter.TYPE_STRING);
-      p5.setMultiValued(true);
-      ConfigurationParameter p6 = new ConfigurationParameter_impl();
-      p6.setName("IntegerArrayParam");
-      p6.setDescription("multi-valued parameter with Integer data type");
-      p6.setType(ConfigurationParameter.TYPE_INTEGER);
-      p6.setMultiValued(true);
-      ConfigurationParameter p7 = new ConfigurationParameter_impl();
-      p7.setName("BooleanArrayParam");
-      p7.setDescription("multi-valued parameter with Boolean data type");
-      p7.setType(ConfigurationParameter.TYPE_BOOLEAN);
-      p7.setMultiValued(true);
-      ConfigurationParameter p8 = new ConfigurationParameter_impl();
-      p8.setName("FloatArrayParam");
-      p8.setDescription("multi-valued parameter with Float data type");
-      p8.setType(ConfigurationParameter.TYPE_FLOAT);
-      p8.setMultiValued(true);
-      md.getConfigurationParameterDeclarations().setConfigurationParameters(
-              new ConfigurationParameter[] { p1, p2, p3, p4, p5, p6, p7, p8 });
-      ConfigurableResource testResource1 = new MyTestResource();
-      testResource1.initialize(specifier, null);
-
-      // valid settings
-      String[] paramNames = { "StringParam", "BooleanParam", "IntegerParam", "FloatParam",
-          "StringArrayParam", "BooleanArrayParam", "IntegerArrayParam", "FloatArrayParam" };
-
-      String theStr = "hello world";
-      Boolean theBool = Boolean.FALSE;
-      Integer theInt = 42;
-      Float theFloat = 2.718281828459045F;
-      String[] theStrArr = { "the", "quick", "brown", "fox" };
-      Boolean[] theBoolArr = { Boolean.FALSE, Boolean.TRUE };
-      Integer[] theIntArr = { 1, 2, 3 };
-      Float[] theFloatArr = { 3.0F, 3.1F, 3.14F };
-
-      Object[] values = new Object[] { theStr, theBool, theInt, theFloat, theStrArr, theBoolArr,
-          theIntArr, theFloatArr };
-
-      for (int i = 0; i < paramNames.length; i++) {
-        testResource1.setConfigParameterValue(paramNames[i], values[i]);
-      }
-      testResource1.reconfigure();
+    // set up some resource metadata and create a resource
+    ConfigurationParameter pString = new ConfigurationParameter_impl();
+    pString.setName("StringParam");
+    pString.setDescription("parameter with String data type");
+    pString.setType(ConfigurationParameter.TYPE_STRING);
 
-      // check
-      for (int i = 0; i < paramNames.length; i++) {
-        Object val = testResource1.getConfigParameterValue(paramNames[i]);
-        Assert.assertEquals(val, values[i]);
-      }
+    ConfigurationParameter pInteger = new ConfigurationParameter_impl();
+    pInteger.setName("IntegerParam");
+    pInteger.setDescription("parameter with Integer data type");
+    pInteger.setType(ConfigurationParameter.TYPE_INTEGER);
 
-      // invalid settings
-      // wrong type
-      Exception ex = null;
-      testResource1.setConfigParameterValue("StringParam", 13);
-      try {
-        testResource1.reconfigure();
-      } catch (ResourceConfigurationException e) {
-        ex = e;
-      }
-      Assert.assertNotNull(ex);
-
-      ex = null;
-      testResource1.setConfigParameterValue("IntegerArrayParam", new Object[] { "A", "B", "C" });
-      try {
-        testResource1.reconfigure();
-      } catch (ResourceConfigurationException e) {
-        ex = e;
-      }
-      Assert.assertNotNull(ex);
-
-      // inappropriate array
-      ex = null;
-      testResource1.setConfigParameterValue("FloatParam", new Float[] { 0.1F, 0.2F, 0.3F });
-      try {
-        testResource1.reconfigure();
-      } catch (ResourceConfigurationException e) {
-        ex = e;
-      }
-      Assert.assertNotNull(ex);
-
-      // array required
-      ex = null;
-      testResource1.setConfigParameterValue("BooleanArrayParam", Boolean.TRUE);
-      try {
-        testResource1.reconfigure();
-      } catch (ResourceConfigurationException e) {
-        ex = e;
-      }
-      Assert.assertNotNull(ex);
-
-      // required parameter set to null
-      ex = null;
-      testResource1.setConfigParameterValue("StringParam", null);
-      try {
-        testResource1.reconfigure();
-      } catch (ResourceConfigurationException e) {
-        ex = e;
-      }
-      Assert.assertNotNull(ex);
+    ConfigurationParameter pLong = new ConfigurationParameter_impl();
+    pLong.setName("LongParam");
+    pLong.setDescription("parameter with Long data type");
+    pLong.setType(ConfigurationParameter.TYPE_LONG);
 
-      // Now try a resource that defines configuration groups
-      // (instantiate metadata from XML TAE descriptor because it's convenient)
-      XMLInputSource in = new XMLInputSource(JUnitExtension
-              .getFile("ConfigurableResourceImplTest/AnnotatorWithConfigurationGroups.xml"));
-      AnalysisEngineDescription desc = UIMAFramework.getXMLParser()
-              .parseAnalysisEngineDescription(in);
-      ResourceMetaData metadata = desc.getMetaData();
-      MyTestSpecifier spec = new MyTestSpecifier();
-      spec.setMetaData(metadata);
-      ConfigurableResource testResource2 = new MyTestResource();
-      testResource2.initialize(spec, null);
-
-      // valid settings
-      String[] groupNames = new String[] { "en", "en-US", "de", "zh" };
-      String[][] grpParamNames = new String[][] {
-          new String[] { "StringParam", "StringArrayParam", "IntegerParam", "IntegerArrayParam" },
-          new String[] { "StringParam", "StringArrayParam", "IntegerParam", "IntegerArrayParam" },
-          new String[] { "StringParam", "StringArrayParam", "IntegerParam", "IntegerArrayParam" },
-          new String[] { "StringParam", "StringArrayParam", "FloatParam", "FloatArrayParam" } };
-      Object[][] grpValues = new Object[][] {
-          new Object[] { "test", new String[] { "foo", "bar" }, 1024, new Integer[] { 1, 3, 5 } },
-          new Object[] { "blah", new String[] { "abc", "def" }, 32768,
-              new Integer[] { -1, -3, -5 } },
-          new Object[] { "?", new String[] { "+", "-" }, 112376, new Integer[] { -1, 0, 1 } },
-          new Object[] { "different", new String[] { "test", "ing" }, 49.95F,
-              new Float[] { 3.14F, 2.71F, 1.4F } } };
-
-      for (int i = 0; i < groupNames.length; i++) {
-        String[] paramsInGrp = grpParamNames[i];
-        for (int j = 0; j < paramsInGrp.length; j++) {
-          testResource2.setConfigParameterValue(groupNames[i], paramsInGrp[j], grpValues[i][j]);
-        }
+    ConfigurationParameter pBoolean = new ConfigurationParameter_impl();
+    pBoolean.setName("BooleanParam");
+    pBoolean.setDescription("parameter with Boolean data type");
+    pBoolean.setType(ConfigurationParameter.TYPE_BOOLEAN);
+
+    ConfigurationParameter pFloat = new ConfigurationParameter_impl();
+    pFloat.setName("FloatParam");
+    pFloat.setDescription("parameter with Float data type");
+    pFloat.setType(ConfigurationParameter.TYPE_FLOAT);
+
+    ConfigurationParameter pDouble = new ConfigurationParameter_impl();
+    pDouble.setName("DoubleParam");
+    pDouble.setDescription("parameter with Double data type");
+    pDouble.setType(ConfigurationParameter.TYPE_DOUBLE);
+
+    ConfigurationParameter pStringArray = new ConfigurationParameter_impl();
+    pStringArray.setName("StringArrayParam");
+    pStringArray.setDescription("mutli-valued parameter with String data type");
+    pStringArray.setType(ConfigurationParameter.TYPE_STRING);
+    pStringArray.setMultiValued(true);
+
+    ConfigurationParameter pIntegerArray = new ConfigurationParameter_impl();
+    pIntegerArray.setName("IntegerArrayParam");
+    pIntegerArray.setDescription("multi-valued parameter with Integer data type");
+    pIntegerArray.setType(ConfigurationParameter.TYPE_INTEGER);
+    pIntegerArray.setMultiValued(true);
+
+    ConfigurationParameter pLongArray = new ConfigurationParameter_impl();
+    pLongArray.setName("LongArrayParam");
+    pLongArray.setDescription("multi-valued parameter with Long data type");
+    pLongArray.setType(ConfigurationParameter.TYPE_LONG);
+    pLongArray.setMultiValued(true);
+
+    ConfigurationParameter pBooleanArray = new ConfigurationParameter_impl();
+    pBooleanArray.setName("BooleanArrayParam");
+    pBooleanArray.setDescription("multi-valued parameter with Boolean data type");
+    pBooleanArray.setType(ConfigurationParameter.TYPE_BOOLEAN);
+    pBooleanArray.setMultiValued(true);
+
+    ConfigurationParameter pFloatArray = new ConfigurationParameter_impl();
+    pFloatArray.setName("FloatArrayParam");
+    pFloatArray.setDescription("multi-valued parameter with Float data type");
+    pFloatArray.setType(ConfigurationParameter.TYPE_FLOAT);
+    pFloatArray.setMultiValued(true);
+
+    ConfigurationParameter pDoubleArray = new ConfigurationParameter_impl();
+    pDoubleArray.setName("DoubleArrayParam");
+    pDoubleArray.setDescription("multi-valued parameter with Double data type");
+    pDoubleArray.setType(ConfigurationParameter.TYPE_DOUBLE);
+    pDoubleArray.setMultiValued(true);
+
+    ConfigurationParameter[] allParameters = array(pString, pBoolean, pInteger, pLong, pFloat,
+            pDouble, pStringArray, pBooleanArray, pIntegerArray, pLongArray, pFloatArray,
+            pDoubleArray);
+
+    ResourceCreationSpecifier specifier = new MyTestSpecifier();
+    ResourceMetaData md = specifier.getMetaData();
+    md.setName("TestResource");
+    md.setDescription("Resource used for Testing the Resource_impl base class");
+    md.getConfigurationParameterDeclarations().setConfigurationParameters(allParameters);
+    ConfigurableResource testResource1 = new MyTestResource();
+    testResource1.initialize(specifier, null);
+
+    String[] paramNames = Stream.of(allParameters) //
+            .map(ConfigurationParameter::getName) //
+            .toArray(String[]::new);
+
+    // valid settings
+    String theStr = "hello world";
+    Boolean theBool = FALSE;
+    Integer theInt = 42;
+    Long theLong = 43l;
+    Float theFloat = 2.718281828459045F;
+    Double theDouble = Double.MAX_VALUE;
+    String[] theStrArr = { "the", "quick", "brown", "fox" };
+    Boolean[] theBoolArr = { FALSE, TRUE };
+    Integer[] theIntArr = { 1, 2, 3 };
+    Long[] theLongArr = { Long.MIN_VALUE, Long.MAX_VALUE, 716231278687123l };
+    Float[] theFloatArr = { 3.0F, 3.1F, 3.14F };
+    Double[] theDoubleArr = { Double.MIN_VALUE, Double.MAX_VALUE, Double.POSITIVE_INFINITY,
+        Double.NEGATIVE_INFINITY, Double.NaN, 0.3123289172312d };
+
+    Object[] values = new Object[] { theStr, theBool, theInt, theLong, theFloat, theDouble,
+        theStrArr, theBoolArr, theIntArr, theLongArr, theFloatArr, theDoubleArr };
+
+    for (int i = 0; i < paramNames.length; i++) {
+      testResource1.setConfigParameterValue(paramNames[i], values[i]);
+    }
+    testResource1.reconfigure();
+
+    // check
+    for (int i = 0; i < paramNames.length; i++) {
+      assertThat(testResource1.getConfigParameterValue(paramNames[i])).isEqualTo(values[i]);
+    }
+
+    // invalid settings
+    // wrong type
+    assertThatExceptionOfType(ResourceConfigurationException.class)
+            .as("Parameter must reject value of inappropriate type").isThrownBy(() -> {
+              testResource1.setConfigParameterValue("StringParam", 13);
+              testResource1.reconfigure();
+            });
+
+    assertThatExceptionOfType(ResourceConfigurationException.class)
+            .as("Array parameter must reject array value containing inappropriate types")
+            .isThrownBy(() -> {
+              testResource1.setConfigParameterValue("IntegerArrayParam",
+                      new Object[] { "A", "B", "C" });
+              testResource1.reconfigure();
+            });
+
+    assertThatExceptionOfType(ResourceConfigurationException.class)
+            .as("Single-valued features require a primitive value, not an array").isThrownBy(() -> {
+              testResource1.setConfigParameterValue("FloatParam", new Float[] { 0.1F, 0.2F, 0.3F });
+              testResource1.reconfigure();
+            });
+
+    assertThatExceptionOfType(ResourceConfigurationException.class)
+            .as("Multi-valued features require an array type, not a primitive value")
+            .isThrownBy(() -> {
+              testResource1.setConfigParameterValue("BooleanArrayParam", TRUE);
+              testResource1.reconfigure();
+            });
+
+    assertThatExceptionOfType(ResourceConfigurationException.class)
+            .as("Required parameter cannot ben ull").isThrownBy(() -> {
+              testResource1.setConfigParameterValue("StringParam", null);
+              testResource1.reconfigure();
+            });
+
+    // Now try a resource that defines configuration groups
+    // (instantiate metadata from XML TAE descriptor because it's convenient)
+    XMLInputSource in = new XMLInputSource(JUnitExtension
+            .getFile("ConfigurableResourceImplTest/AnnotatorWithConfigurationGroups.xml"));
+    AnalysisEngineDescription desc = UIMAFramework.getXMLParser()
+            .parseAnalysisEngineDescription(in);
+    ResourceMetaData metadata = desc.getMetaData();
+    MyTestSpecifier spec = new MyTestSpecifier();
+    spec.setMetaData(metadata);
+    ConfigurableResource testResource2 = new MyTestResource();
+    testResource2.initialize(spec, null);
+
+    // valid settings
+    String[] groupNames = new String[] { "en", "en-US", "de", "zh" };
+    String[][] grpParamNames = {
+        new String[] { "StringParam", "StringArrayParam", "IntegerParam", "IntegerArrayParam" },
+        new String[] { "StringParam", "StringArrayParam", "IntegerParam", "IntegerArrayParam" },
+        new String[] { "StringParam", "StringArrayParam", "IntegerParam", "IntegerArrayParam" },
+        new String[] { "StringParam", "StringArrayParam", "FloatParam", "FloatArrayParam" } };
+    Object[][] grpValues = {
+        new Object[] { "test", new String[] { "foo", "bar" }, 1024, new Integer[] { 1, 3, 5 } },
+        new Object[] { "blah", new String[] { "abc", "def" }, 32768, new Integer[] { -1, -3, -5 } },
+        new Object[] { "?", new String[] { "+", "-" }, 112376, new Integer[] { -1, 0, 1 } },
+        new Object[] { "different", new String[] { "test", "ing" }, 49.95F,
+            new Float[] { 3.14F, 2.71F, 1.4F } } };
+
+    for (int i = 0; i < groupNames.length; i++) {
+      String[] paramsInGrp = grpParamNames[i];
+      for (int j = 0; j < paramsInGrp.length; j++) {
+        testResource2.setConfigParameterValue(groupNames[i], paramsInGrp[j], grpValues[i][j]);
       }
-      testResource2.reconfigure();
-
-      for (int i = 0; i < groupNames.length; i++) {
-        String[] paramsInGrp = grpParamNames[i];
-        for (int j = 0; j < paramsInGrp.length; j++) {
-          Object val = testResource2.getConfigParameterValue(groupNames[i], paramsInGrp[j]);
-          Assert.assertEquals(val, grpValues[i][j]);
-        }
+    }
+    testResource2.reconfigure();
+
+    for (int i = 0; i < groupNames.length; i++) {
+      String[] paramsInGrp = grpParamNames[i];
+      for (int j = 0; j < paramsInGrp.length; j++) {
+        Object val = testResource2.getConfigParameterValue(groupNames[i], paramsInGrp[j]);
+        Assert.assertEquals(val, grpValues[i][j]);
       }
-    } catch (Exception e) {
-      JUnitExtension.handleException(e);
     }
   }
 
diff --git a/uimaj-ep-configurator/src/main/java/org/apache/uima/taeconfigurator/editors/ui/ValueSection.java b/uimaj-ep-configurator/src/main/java/org/apache/uima/taeconfigurator/editors/ui/ValueSection.java
index 47f5e25..082bd94 100644
--- a/uimaj-ep-configurator/src/main/java/org/apache/uima/taeconfigurator/editors/ui/ValueSection.java
+++ b/uimaj-ep-configurator/src/main/java/org/apache/uima/taeconfigurator/editors/ui/ValueSection.java
@@ -261,8 +261,9 @@ public class ValueSection extends AbstractSectionParm {
       CommonInputDialog dialog = new CommonInputDialog(this, "Add value", "Enter a value",
               validationFilter);
 
-      if (dialog.open() == Window.CANCEL)
+      if (dialog.open() == Window.CANCEL) {
         return;
+      }
       TableItem item = new TableItem(valueTable, SWT.NONE);
       item.setText(dialog.getValue());
       // update model
@@ -275,8 +276,9 @@ public class ValueSection extends AbstractSectionParm {
       CommonInputDialog dialog = new CommonInputDialog(this, "Add value", "Enter a value",
               CommonInputDialog.ALLOK, item.getText());
 
-      if (dialog.open() == Window.CANCEL)
+      if (dialog.open() == Window.CANCEL) {
         return;
+      }
 
       item.setText(dialog.getValue());
       // update model
@@ -319,8 +321,9 @@ public class ValueSection extends AbstractSectionParm {
    */
   private void setParmValue(String value) {
     if (null != value) {
-      if ("".equals(value))
+      if ("".equals(value)) {
         value = null; // means clear the value
+      }
       setCurrentParameterValue(value);
     }
   }
@@ -390,8 +393,12 @@ public class ValueSection extends AbstractSectionParm {
           value = aValueString;
         } else if (ConfigurationParameter.TYPE_INTEGER.equals(paramType)) {
           value = Integer.valueOf(aValueString);
+        } else if (ConfigurationParameter.TYPE_LONG.equals(paramType)) {
+          value = Long.valueOf(aValueString);
         } else if (ConfigurationParameter.TYPE_FLOAT.equals(paramType)) {
           value = Float.valueOf(aValueString);
+        } else if (ConfigurationParameter.TYPE_DOUBLE.equals(paramType)) {
+          value = Double.valueOf(aValueString);
         } else if (ConfigurationParameter.TYPE_BOOLEAN.equals(paramType)) {
           value = Boolean.valueOf(aValueString);
         }
@@ -427,18 +434,29 @@ public class ValueSection extends AbstractSectionParm {
         for (int i = 0; i < valueArr.length; i++) {
           valueArr[i] = Integer.valueOf(aValues[i].getText());
         }
+      } else if (ConfigurationParameter.TYPE_LONG.equals(paramType)) {
+        valueArr = new Long[aValues.length];
+        for (int i = 0; i < valueArr.length; i++) {
+          valueArr[i] = Long.valueOf(aValues[i].getText());
+        }
       } else if (ConfigurationParameter.TYPE_FLOAT.equals(paramType)) {
         valueArr = new Float[aValues.length];
         for (int i = 0; i < valueArr.length; i++) {
           valueArr[i] = Float.valueOf(aValues[i].getText());
         }
+      } else if (ConfigurationParameter.TYPE_DOUBLE.equals(paramType)) {
+        valueArr = new Double[aValues.length];
+        for (int i = 0; i < valueArr.length; i++) {
+          valueArr[i] = Double.valueOf(aValues[i].getText());
+        }
       } else if (ConfigurationParameter.TYPE_BOOLEAN.equals(paramType)) {
         valueArr = new Boolean[aValues.length];
         for (int i = 0; i < valueArr.length; i++) {
           valueArr[i] = Boolean.valueOf(aValues[i].getText());
         }
-      } else
+      } else {
         throw new InternalErrorCDE("invalid state");
+      }
     } catch (NumberFormatException e) {
       Utility.popMessage("Invalid Number",
               "One or more values is not of the proper kind of number."
@@ -467,8 +485,9 @@ public class ValueSection extends AbstractSectionParm {
         String[] groupNames = groups[i].getNames();
         for (int j = 0; j < groupNames.length; j++) {
           if (isSameValue(value,
-                  modelSettings.getParameterValue(groupNames[j], selectedCP.getName())))
+                  modelSettings.getParameterValue(groupNames[j], selectedCP.getName()))) {
             continue;
+          }
           modelSettings.setParameterValue(groupNames[j], selectedCP.getName(), value);
           changed = true;
         }
@@ -484,8 +503,9 @@ public class ValueSection extends AbstractSectionParm {
         changed = true;
       }
     }
-    if (changed)
+    if (changed) {
       editor.setFileDirty();
+    }
   }
 
   /**
@@ -501,8 +521,9 @@ public class ValueSection extends AbstractSectionParm {
     if (v1 instanceof Object[]) {
       return (Arrays.equals((Object[]) v1, (Object[]) v2));
     } else {
-      if (null == v1)
+      if (null == v1) {
         return null == v2;
+      }
       return v1.equals(v2);
     }
   }