Merge "Remove unused property"
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupMapValidationResult.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupMapValidationResult.java
index e607ff9..3baacb1 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupMapValidationResult.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupMapValidationResult.java
@@ -89,7 +89,7 @@
      * @param message The validation message explaining the validation status
      */
     @Override
-    public void setResult(ValidationStatus status, String message) {
+    public void setResult(final ValidationStatus status, final String message) {
         setResult(status);
         this.message = message;
     }
@@ -112,9 +112,28 @@
      * Set the validation result on a parameter map entry.
      * 
      * @param entryName The name of the parameter map entry
+     * @param status The validation status for the entry
+     * @param message The validation message for the entry
+     */
+    public void setResult(final String entryName, final ValidationStatus status, final String message) {
+        ValidationResult validationResult = validationResultMap.get(entryName);
+        if (validationResult == null) {
+            throw new ParameterRuntimeException("no entry with name \"" + entryName + "\" exists");
+        }
+
+        // Set the status of the parameter group and replace the field result
+        validationResult.setResult(status, message); 
+        this.setResult(status);
+    }
+
+
+    /**
+     * Set the validation result on a parameter map entry.
+     * 
+     * @param entryName The name of the parameter map entry
      * @param mapEntryValidationResult The validation result for the entry
      */
-    public void setResult(String entryName, ValidationResult mapEntryValidationResult) {
+    public void setResult(final String entryName, final ValidationResult mapEntryValidationResult) {
         ValidationResult validationResult = validationResultMap.get(entryName);
         if (validationResult == null) {
             throw new ParameterRuntimeException("no entry with name \"" + entryName + "\" exists");
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupValidationResult.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupValidationResult.java
index ac9dc7b..fc2f6ca 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupValidationResult.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/GroupValidationResult.java
@@ -48,6 +48,11 @@
     public GroupValidationResult(final ParameterGroup parameterGroup) {
         this.parameterGroup = parameterGroup;
 
+        // Parameter group definitions may be optional
+        if (parameterGroup == null) {
+            return;
+        }
+
         // Add a validation result per field
         for (Field field : parameterGroup.getClass().getDeclaredFields()) {
             // Exclude system fields
@@ -86,15 +91,15 @@
 
         // Nested parameter groups are allowed
         if (ParameterGroup.class.isAssignableFrom(fieldType)) {
-            return new GroupValidationResult((ParameterGroup) field.get(parameterGroup));
+            return new GroupValidationResult((ParameterGroup) fieldObject);
         }
-        
+
         // Nested maps of parameter groups are allowed
         if (Map.class.isAssignableFrom(field.getType())) {
             checkMapIsParameterGroupMap(fieldName, fieldObject);
             return new GroupMapValidationResult(field, fieldObject);
         }
-        
+
         // Collections of parameter groups are not allowed
         if (Collection.class.isAssignableFrom(field.getType())) {
             checkCollection4ParameterGroups(fieldName, fieldObject);
@@ -115,7 +120,7 @@
         if (mapObject == null) {
             throw new ParameterRuntimeException("map parameter \"" + fieldName + "\" is null");
         }
-        
+
         Map<?, ?> incomingMap = (Map<?, ?>) mapObject;
 
         for (Entry<?, ?> mapEntry : incomingMap.entrySet()) {
@@ -184,7 +189,7 @@
     }
 
     /**
-     * Set the validation result on on a parameter group.
+     * Set the validation result on a parameter group.
      * 
      * @param status The validation status the parameter group is receiving
      * @param message The validation message explaining the validation status
@@ -196,9 +201,8 @@
     }
 
     /**
-     * Set the validation result on on a parameter group.
-     * On a sequence of calls, the most serious validation status is recorded, assuming the status enum ordinal increase
-     * in order of severity
+     * Set the validation result on a parameter group. On a sequence of calls, the most serious validation status is
+     * recorded, assuming the status enum ordinal increase in order of severity
      * 
      * @param status The validation status the parameter group is receiving
      */
@@ -211,27 +215,23 @@
     }
 
     /**
-     * Set the validation result on a parameter group.
+     * Set the validation result on a parameter in a parameter group.
      * 
-     * @param parameterGroupName The name of the parameter group
+     * @param parameterName The name of the parameter
      * @param status The validation status the field is receiving
      * @param message The validation message explaining the validation status
      */
-    public void setResult(final String parameterGroupName, final ValidationStatus status, final String message) {
-        ParameterValidationResult parameterValidationResult;
-        try {
-            parameterValidationResult = (ParameterValidationResult) validationResultMap.get(parameterGroupName);
-        } catch (ClassCastException e) {
-            throw new ParameterRuntimeException("parameter not a regular parameter: " + parameterGroupName, e);
+    public void setResult(final String parameterName, final ValidationStatus status, final String message) {
+        ValidationResult validationResult = validationResultMap.get(parameterName);
+
+        if (validationResult == null) {
+            throw new ParameterRuntimeException("no parameter field exists for parameter: " + parameterName);
         }
 
-        if (parameterValidationResult == null) {
-            throw new ParameterRuntimeException(
-                            "no regular parameter field exists for parameter: " + parameterGroupName);
-        }
+        // Set the status and the message on the result irrespective of validation result type
+        validationResult.setResult(status, message);
 
-        // Set the status of the parameter group and the field
-        parameterValidationResult.setResult(status, message);
+        // Set the status of this result
         this.setResult(status);
     }
 
@@ -241,7 +241,7 @@
      * @param parameterName The name of the parameter field
      * @param nestedValidationResult The validation result from a nested field
      */
-    public void setResult(String parameterName, ValidationResult nestedValidationResult) {
+    public void setResult(final String parameterName, final ValidationResult nestedValidationResult) {
         GroupValidationResult groupValidationResult;
         try {
             groupValidationResult = (GroupValidationResult) validationResultMap.get(parameterName);
@@ -284,6 +284,32 @@
     }
 
     /**
+     * Set the validation status on a group map entry.
+     * 
+     * @param parameterName The name of the parameter field
+     * @param key The key of the map entry
+     * @param status The validation status of the entry
+     * @param message The message for the parameter group
+     */
+    public void setResult(final String parameterName, final String key, final ValidationStatus status,
+                    final String message) {
+        GroupMapValidationResult groupMapValidationResult;
+        try {
+            groupMapValidationResult = (GroupMapValidationResult) validationResultMap.get(parameterName);
+        } catch (ClassCastException e) {
+            throw new ParameterRuntimeException("parameter is not a nested group map parameter: " + parameterName, e);
+        }
+
+        if (groupMapValidationResult == null) {
+            throw new ParameterRuntimeException("no group map parameter field exists for parameter: " + parameterName);
+        }
+
+        // Set the status of the parameter group and the field
+        groupMapValidationResult.setResult(key, status, message);
+        this.setResult(status);
+    }
+
+    /**
      * Gets the validation result.
      *
      * @param initialIndentation the indentation to use on the main result output
@@ -301,9 +327,15 @@
 
         validationResultBuilder.append(initialIndentation);
         validationResultBuilder.append("parameter group \"");
-        validationResultBuilder.append(parameterGroup.getName());
-        validationResultBuilder.append("\" type \"");
-        validationResultBuilder.append(parameterGroup.getClass().getCanonicalName());
+        
+        if (parameterGroup != null) {
+            validationResultBuilder.append(parameterGroup.getName());
+            validationResultBuilder.append("\" type \"");
+            validationResultBuilder.append(parameterGroup.getClass().getCanonicalName());
+        }
+        else {
+            validationResultBuilder.append("UNDEFINED");
+        }
         validationResultBuilder.append("\" ");
         validationResultBuilder.append(status);
         validationResultBuilder.append(", ");
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterException.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterException.java
index 3a6e17e..0b29a4e 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterException.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterException.java
@@ -88,7 +88,7 @@
      * @param throwable the top level exception
      * @return cascaded message string
      */
-    public static String buildCascadedMessage(Throwable throwable) {
+    public static String buildCascadedMessage(final Throwable throwable) {
         final StringBuilder builder = new StringBuilder();
         builder.append(throwable.getMessage());
 
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterGroup.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterGroup.java
index 48e8379..8bfa183 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterGroup.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterGroup.java
@@ -35,6 +35,13 @@
     public String getName();
 
     /**
+     * Set the group name.
+     * 
+     * @param name the group name
+     */
+    public void setName(final String name);
+
+    /**
      * Validate parameters.
      * 
      * @return the result of the parameter validation
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterService.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterService.java
index db6995c..358e553 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterService.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/ParameterService.java
@@ -61,6 +61,20 @@
     }
 
     /**
+     * Register a parameter group with the parameter service.
+     *
+     * @param parameterGroup the parameter group
+     * @param overwrite if true, overwrite the current value if set
+     */
+    public static void register(final ParameterGroup parameterGroup, final boolean overwrite) {
+        if (overwrite && parameterGroupMap.containsKey(parameterGroup.getName())) {
+            deregister(parameterGroup);
+        }
+        
+        register(parameterGroup);
+    }
+
+    /**
      * Remove a parameter group from the parameter service.
      *
      * @param parameterGroupName the name of the parameter group
@@ -74,13 +88,23 @@
     }
 
     /**
+     * Remove a parameter group from the parameter service.
+     *
+     * @param parameterGroup the parameter group
+     */
+    public static void deregister(final ParameterGroup parameterGroup) {
+        deregister(parameterGroup.getName());
+    }
+
+    /**
      * Get a parameter group from the parameter service.
      *
      * @param parameterGroupName the name of the parameter group
      * @return The parameter group
      */
-    public static ParameterGroup get(final String parameterGroupName) {
-        final ParameterGroup parameterGroup = parameterGroupMap.get(parameterGroupName);
+    public static <T extends ParameterGroup> T get(final String parameterGroupName) {
+        @SuppressWarnings("unchecked")
+        final T parameterGroup = (T) parameterGroupMap.get(parameterGroupName);
 
         if (parameterGroup == null) {
             throw new ParameterRuntimeException("\"" + parameterGroupName + "\" not found in parameter service");
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationResult.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationResult.java
index b97ccda..309fd00 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationResult.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationResult.java
@@ -48,6 +48,15 @@
     }
 
     /**
+     * Checks if the result is clean.
+     *
+     * @return true, if is clean
+     */
+    default boolean isClean() {
+        return getStatus().isClean(); 
+    }
+
+    /**
      * Gets the validation result.
      *
      * @return the full validation result
diff --git a/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationStatus.java b/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationStatus.java
index ff453a1..8692506 100644
--- a/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationStatus.java
+++ b/common-parameters/src/main/java/org/onap/policy/common/parameters/ValidationStatus.java
@@ -33,4 +33,12 @@
     public boolean isValid() {
         return !this.equals(INVALID);
     }
+    
+    /**
+     * Check if the validation was clean.
+     * @return true if the validation is clean
+     */
+    public boolean isClean() {
+        return this.equals(CLEAN);
+    }
 }
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestParameterService.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestParameterService.java
index 0b7e46c..2dad428 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestParameterService.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestParameterService.java
@@ -57,9 +57,34 @@
             assertEquals("\"Empty Group\" already registered in parameter service", e.getMessage());
         }
 
+        try {
+            ParameterService.register(new EmptyParameterGroup("Empty Group"), false);
+            fail("this test should throw an exception");
+        }
+        catch (ParameterRuntimeException e) {
+            assertEquals("\"Empty Group\" already registered in parameter service", e.getMessage());
+        }
+
+        ParameterService.register(new EmptyParameterGroup("Empty Group"), true);
+        assertTrue(ParameterService.contains("Empty Group"));
+
         ParameterService.deregister("Empty Group");
         assertFalse(ParameterService.contains("Empty Group"));
 
+        ParameterService.register(new EmptyParameterGroup("Empty Group"), true);
+        assertTrue(ParameterService.contains("Empty Group"));
+
+        ParameterService.deregister("Empty Group");
+        assertFalse(ParameterService.contains("Empty Group"));
+
+        EmptyParameterGroup epg = new EmptyParameterGroup("Empty Group");
+        ParameterService.register(epg);
+        assertTrue(ParameterService.contains("Empty Group"));
+        assertNotNull(ParameterService.get("Empty Group"));
+
+        ParameterService.deregister(epg);
+        assertFalse(ParameterService.contains("Empty Group"));
+
         try {
             ParameterService.deregister("Empty Group");
             fail("this test should throw an exception");
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidation.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidation.java
index 2ca24a0..fe750b2 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidation.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidation.java
@@ -39,6 +39,7 @@
 
         GroupValidationResult validationResult = l0Parameters.validate();
         assertTrue(validationResult.isValid());
+        assertTrue(validationResult.isClean());
         assertNull(validationResult.getResult());
         assertEquals(l0Parameters, validationResult.getParameterGroup());
         assertEquals(l0Parameters.getName(), validationResult.getName());
@@ -61,6 +62,7 @@
 
         GroupValidationResult validationResult = l0Parameters.validate();
         assertTrue(validationResult.isValid());
+        assertFalse(validationResult.isClean());
         assertEquals(expectedResult, validationResult.getResult().replaceAll("\\s+", ""));
         
         l0Parameters.triggerValidationStatus(ValidationStatus.CLEAN, 3);
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationErrors.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationErrors.java
index 6b78147..a489cc3 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationErrors.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationErrors.java
@@ -21,6 +21,7 @@
 package org.onap.policy.common.parameters;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -31,6 +32,7 @@
 import org.onap.policy.common.parameters.testclasses.ParameterGroupWithIllegalMapValue;
 import org.onap.policy.common.parameters.testclasses.ParameterGroupWithNullCollection;
 import org.onap.policy.common.parameters.testclasses.ParameterGroupWithNullMapValue;
+import org.onap.policy.common.parameters.testclasses.ParameterGroupWithNullSubGroup;
 import org.onap.policy.common.parameters.testclasses.ParameterGroupWithParameterGroupCollection;
 
 public class TestValidationErrors {
@@ -69,6 +71,14 @@
     }
 
     @Test
+    public void testMapNullSubGroupValidation() {
+        ParameterGroupWithNullSubGroup nullSub = new ParameterGroupWithNullSubGroup("Null sub group value");
+
+        nullSub.isValid();
+        assertNull(nullSub.getSubGroup());
+    }
+
+    @Test
     public void testMapNullValueValidation() {
         ParameterGroupWithNullMapValue nullMap = new ParameterGroupWithNullMapValue("Null Map value");
         try {
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationResults.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationResults.java
index 8f22765..f745105 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationResults.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/TestValidationResults.java
@@ -103,15 +103,11 @@
             result.setResult("nonExistantParameter", ValidationStatus.OBSERVATION, "Something was observed");
             fail("test shold throw an exception here");
         } catch (Exception e) {
-            assertEquals("no regular parameter field exists for parameter: nonExistantParameter", e.getMessage());
+            assertEquals("no parameter field exists for parameter: nonExistantParameter", e.getMessage());
         }
 
-        try {
-            result.setResult("l10LGenericNestedMap", ValidationStatus.OBSERVATION, "Something was observed");
-            fail("test shold throw an exception here");
-        } catch (Exception e) {
-            assertEquals("parameter not a regular parameter: l10LGenericNestedMap", e.getMessage());
-        }
+        result.setResult("l10IntField", ValidationStatus.OBSERVATION, "Something was observed");
+        assertTrue(result.isValid());
 
         try {
             result.setResult("nonExistantParameter", new GroupValidationResult(pg));
@@ -143,5 +139,33 @@
         } catch (Exception e) {
             assertEquals("parameter is not a nested group map parameter: l10IntField", e.getMessage());
         }
+
+        result.setResult("l10LGenericNestedMap", "l10LGenericNestedMapVal0", ValidationStatus.INVALID,
+                        "This value is invalid");
+        assertEquals(ValidationStatus.INVALID, result.getStatus());
+        
+        try {
+            result.setResult("l10IntField", "l10LGenericNestedMapVal0", ValidationStatus.INVALID,
+                            "This value is invalid");
+            fail("test shold throw an exception here");
+        } catch (Exception e) {
+            assertEquals("parameter is not a nested group map parameter: l10IntField", e.getMessage());
+        }
+        
+        try {
+            result.setResult("nonExistantParameter", "l10LGenericNestedMapVal0", ValidationStatus.INVALID,
+                            "This value is invalid");
+            fail("test shold throw an exception here");
+        } catch (Exception e) {
+            assertEquals("no group map parameter field exists for parameter: nonExistantParameter", e.getMessage());
+        }
+        
+        try {
+            result.setResult("l10LGenericNestedMap", "NonExistantKey", ValidationStatus.INVALID,
+                            "This value is invalid");
+            fail("test shold throw an exception here");
+        } catch (Exception e) {
+            assertEquals("no entry with name \"NonExistantKey\" exists", e.getMessage());
+        }
     }
 }
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/EmptyParameterGroup.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/EmptyParameterGroup.java
index 681eb69..505b2ce 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/EmptyParameterGroup.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/EmptyParameterGroup.java
@@ -36,6 +36,11 @@
     }
     
     @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+    
+    @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
     }
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithArray.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithArray.java
index fcb2bb1..c448cea 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithArray.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithArray.java
@@ -34,12 +34,17 @@
     public int[] getIntArray() {
         return intArray;
     }
-    
+
     @Override
     public String getName() {
         return name;
     }
-    
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
     @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithCollection.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithCollection.java
index 75ae45b..7f2c0ab 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithCollection.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithCollection.java
@@ -53,6 +53,11 @@
     }
 
     @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+    
+    @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
     }
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapKey.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapKey.java
index ca44106..57a5a11 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapKey.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapKey.java
@@ -52,6 +52,11 @@
     }
     
     @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+    
+    @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
     }
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapValue.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapValue.java
index 9253f15..39e35d9 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapValue.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithIllegalMapValue.java
@@ -52,6 +52,11 @@
     }
     
     @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+    
+    @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
     }
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullCollection.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullCollection.java
index 0d113dc..9b661bd 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullCollection.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullCollection.java
@@ -40,12 +40,17 @@
     public List<Integer> getNullList() {
         return nullList;
     }
-    
+
     @Override
     public String getName() {
         return name;
     }
-    
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
     @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullMapValue.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullMapValue.java
index 9e1601c..ac863a4 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullMapValue.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullMapValue.java
@@ -40,12 +40,17 @@
     public Map<String, Integer> getNullMap() {
         return nullMap;
     }
-    
+
     @Override
     public String getName() {
         return name;
     }
-    
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
     @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullSubGroup.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullSubGroup.java
new file mode 100644
index 0000000..830c811
--- /dev/null
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithNullSubGroup.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2018 Ericsson. All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.common.parameters.testclasses;
+
+import org.onap.policy.common.parameters.GroupValidationResult;
+import org.onap.policy.common.parameters.ParameterGroup;
+
+public class ParameterGroupWithNullSubGroup implements ParameterGroup {
+    private String name;
+    private ParameterGroup subGroup = null;
+
+    /**
+     * Create a test parameter group.
+     * @param name the parameter group name
+     */
+    public ParameterGroupWithNullSubGroup(final String name) {
+        this.name = name;
+    }
+
+    public ParameterGroup getSubGroup() {
+        return subGroup;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public GroupValidationResult validate() {
+        return new GroupValidationResult(this);
+    }
+}
diff --git a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithParameterGroupCollection.java b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithParameterGroupCollection.java
index 5ece07b..dadf727 100644
--- a/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithParameterGroupCollection.java
+++ b/common-parameters/src/test/java/org/onap/policy/common/parameters/testclasses/ParameterGroupWithParameterGroupCollection.java
@@ -52,6 +52,11 @@
     }
     
     @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+    
+    @Override
     public GroupValidationResult validate() {
         return new GroupValidationResult(this);
     }
diff --git a/policy-endpoints/pom.xml b/policy-endpoints/pom.xml
index aedb56d..03b3d59 100644
--- a/policy-endpoints/pom.xml
+++ b/policy-endpoints/pom.xml
@@ -139,6 +139,12 @@
             <artifactId>jersey-client</artifactId>
             <version>${jersey.version}</version>
         </dependency>
+        
+        <dependency>
+            <groupId>org.glassfish.jersey.core</groupId>
+            <artifactId>jersey-common</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
 
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java
index f886e5c..6e8865f 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/HttpClient.java
@@ -20,6 +20,9 @@
 
 package org.onap.policy.common.endpoints.http.client;
 
+import java.util.Map;
+
+import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Response;
 
 import org.onap.policy.common.capabilities.Startable;
@@ -30,6 +33,8 @@
 
     public Response get();
 
+    public Response put(String path, Entity<?> entity, Map<String, Object> headers);
+
     public static <T> T getBody(Response response, Class<T> entityType) {
         return response.readEntity(entityType);
     }
@@ -54,4 +59,5 @@
 
 
     public static final HttpClientFactory factory = new IndexedHttpClientFactory();
+
 }
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
index c227071..0be8109 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java
@@ -28,12 +28,16 @@
 import java.security.SecureRandom;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation.Builder;
 import javax.ws.rs.core.Response;
 
 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
@@ -66,14 +70,9 @@
     /**
      * Constructor.
      * 
-     * name the name
-     * https is it https or not
-     * selfSignedCerts are there self signed certs
-     * hostname the hostname
-     * port port being used
-     * basePath base context
-     * userName user
-     * password password
+     * name the name https is it https or not selfSignedCerts are there self signed certs hostname
+     * the hostname port port being used basePath base context userName user password password
+     * 
      * @param busTopicParams Input parameters object
      * @throws KeyManagementException key exception
      * @throws NoSuchAlgorithmException no algorithm exception
@@ -163,6 +162,14 @@
         return this.client.target(this.baseUrl).request().get();
     }
 
+    @Override
+    public Response put(String path, Entity<?> entity, Map<String, Object> headers) {
+        Builder builder = this.client.target(this.baseUrl).path(path).request();
+        for (Entry<String, Object> header : headers.entrySet()) {
+            builder.header(header.getKey(), header.getValue());
+        }
+        return builder.put(entity);
+    }
 
     @Override
     public boolean start() {
diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
index 7d37521..3b8c08f 100644
--- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
+++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java
@@ -23,7 +23,9 @@
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
 import java.util.EnumSet;
+
 import javax.servlet.DispatcherType;
+
 import org.eclipse.jetty.security.ConstraintMapping;
 import org.eclipse.jetty.security.ConstraintSecurityHandler;
 import org.eclipse.jetty.security.HashLoginService;
@@ -164,7 +166,7 @@
         } else {
             this.connector = httpConnector();
         }
-        
+
         this.connector.setName(srvName);
         this.connector.setReuseAddress(true);
         this.connector.setPort(port);
@@ -189,8 +191,7 @@
             tempFilterPath = "/*";
         }
 
-        context.addFilter(filterClass, tempFilterPath,
-                EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
+        context.addFilter(filterClass, tempFilterPath, EnumSet.of(DispatcherType.INCLUDE, DispatcherType.REQUEST));
     }
 
     /**
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpClientTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpClientTest.java
index 1248744..61525c3 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpClientTest.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpClientTest.java
@@ -21,13 +21,17 @@
 
 package org.onap.policy.common.endpoints.http.server.test;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Properties;
 
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 import org.junit.AfterClass;
@@ -51,7 +55,7 @@
      * Setup before class method.
      *
      * @throws InterruptedException can be interrupted
-     * @throws IOException          can have an IO exception
+     * @throws IOException can have an IO exception
      */
     @BeforeClass
     public static void setUp() throws InterruptedException, IOException {
@@ -76,21 +80,20 @@
         String keyStorePasswordSystemProperty =
                 System.getProperty(JettyJerseyServer.SYSTEM_KEYSTORE_PASSWORD_PROPERTY_NAME);
         if (keyStorePasswordSystemProperty != null) {
-            savedValuesMap.put(
-                    JettyJerseyServer.SYSTEM_KEYSTORE_PASSWORD_PROPERTY_NAME, keyStorePasswordSystemProperty);
+            savedValuesMap.put(JettyJerseyServer.SYSTEM_KEYSTORE_PASSWORD_PROPERTY_NAME,
+                    keyStorePasswordSystemProperty);
         }
 
         String trustStoreSystemProperty = System.getProperty(JettyJerseyServer.SYSTEM_TRUSTSTORE_PROPERTY_NAME);
         if (trustStoreSystemProperty != null) {
-            savedValuesMap
-                    .put(JettyJerseyServer.SYSTEM_TRUSTSTORE_PROPERTY_NAME, trustStoreSystemProperty);
+            savedValuesMap.put(JettyJerseyServer.SYSTEM_TRUSTSTORE_PROPERTY_NAME, trustStoreSystemProperty);
         }
 
         String trustStorePasswordSystemProperty =
                 System.getProperty(JettyJerseyServer.SYSTEM_TRUSTSTORE_PASSWORD_PROPERTY_NAME);
         if (trustStorePasswordSystemProperty != null) {
-            savedValuesMap
-                    .put(JettyJerseyServer.SYSTEM_TRUSTSTORE_PASSWORD_PROPERTY_NAME, trustStorePasswordSystemProperty);
+            savedValuesMap.put(JettyJerseyServer.SYSTEM_TRUSTSTORE_PASSWORD_PROPERTY_NAME,
+                    trustStorePasswordSystemProperty);
         }
 
         System.setProperty(JettyJerseyServer.SYSTEM_KEYSTORE_PROPERTY_NAME, "src/test/resources/keystore-test");
@@ -158,14 +161,12 @@
     }
 
     @Test
-    public void testHttpNoAuthClient() throws Exception {
+    public void testHttpGetNoAuthClient() throws Exception {
         logger.info("-- testHttpNoAuthClient() --");
 
         final HttpClient client = HttpClient.factory.build(BusTopicParams.builder().clientName("testHttpNoAuthClient")
-                .useHttps(false)
-                .allowSelfSignedCerts(false)
-                .hostname("localhost")
-                .port(6666).basePath("junit/echo").userName(null).password(null).managed(true).build());
+                .useHttps(false).allowSelfSignedCerts(false).hostname("localhost").port(6666).basePath("junit/echo")
+                .userName(null).password(null).managed(true).build());
         final Response response = client.get("hello");
         final String body = HttpClient.getBody(response, String.class);
 
@@ -174,18 +175,28 @@
     }
 
     @Test
-    public void testHttpAuthClient() throws Exception {
+    public void testHttpPutNoAuthClient() throws Exception {
+        logger.info("-- testHttpNoAuthClient() --");
+
+        final HttpClient client = HttpClient.factory.build(BusTopicParams.builder().clientName("testHttpNoAuthClient")
+                .useHttps(false).allowSelfSignedCerts(false).hostname("localhost").port(6666).basePath("junit/echo")
+                .userName(null).password(null).managed(true).build());
+
+        Entity<MyEntity> entity = Entity.entity(new MyEntity("myValue"), MediaType.APPLICATION_JSON);
+        final Response response = client.put("hello", entity, Collections.emptyMap());
+        final String body = HttpClient.getBody(response, String.class);
+
+        assertTrue(response.getStatus() == 200);
+        assertTrue(body.equals("hello:{myParameter=myValue}"));
+    }
+
+    @Test
+    public void testHttpGetAuthClient() throws Exception {
         logger.info("-- testHttpAuthClient() --");
 
         final HttpClient client = HttpClient.factory.build(BusTopicParams.builder().clientName("testHttpAuthClient")
-                .useHttps(true)
-                .allowSelfSignedCerts(true)
-                .hostname("localhost")
-                .port(6667)
-                .basePath("junit/echo")
-                .userName("x")
-                .password("y")
-                .managed(true).build());
+                .useHttps(true).allowSelfSignedCerts(true).hostname("localhost").port(6667).basePath("junit/echo")
+                .userName("x").password("y").managed(true).build());
 
         final Response response = client.get("hello");
         final String body = HttpClient.getBody(response, String.class);
@@ -195,20 +206,30 @@
     }
 
     @Test
+    public void testHttpPutAuthClient() throws Exception {
+        logger.info("-- testHttpAuthClient() --");
+
+        final HttpClient client = HttpClient.factory.build(BusTopicParams.builder().clientName("testHttpAuthClient")
+                .useHttps(true).allowSelfSignedCerts(true).hostname("localhost").port(6667).basePath("junit/echo")
+                .userName("x").password("y").managed(true).build());
+
+        Entity<MyEntity> entity = Entity.entity(new MyEntity("myValue"), MediaType.APPLICATION_JSON);
+        final Response response = client.put("hello", entity, Collections.emptyMap());
+        final String body = HttpClient.getBody(response, String.class);
+
+        assertTrue(response.getStatus() == 200);
+        assertTrue(body.equals("hello:{myParameter=myValue}"));
+    }
+
+    @Test
     public void testHttpAuthClient401() throws Exception {
         logger.info("-- testHttpAuthClient401() --");
 
         final HttpClient client = HttpClient.factory.build(BusTopicParams.builder().clientName("testHttpAuthClient401")
-                .useHttps(true)
-                .allowSelfSignedCerts(true)
-                .hostname("localhost")
-                .port(6667)
-                .basePath("junit/echo")
-                .userName(null)
-                .password(null)
-                .managed(true).build());
+                .useHttps(true).allowSelfSignedCerts(true).hostname("localhost").port(6667).basePath("junit/echo")
+                .userName(null).password(null).managed(true).build());
         final Response response = client.get("hello");
-        assertTrue(response.getStatus() == 401);
+        assertEquals(new Integer(response.getStatus()).toString(), response.getStatus(), 401);
     }
 
     @Test
@@ -298,5 +319,22 @@
         assertTrue(response2.getStatus() == 500);
     }
 
+    class MyEntity {
+
+        private String myParameter;
+
+        public MyEntity(final String myParameter) {
+            this.myParameter = myParameter;
+        }
+
+        public void setMyParameter(final String myParameter) {
+            this.myParameter = myParameter;
+        }
+
+        public String getMyParameter() {
+            return myParameter;
+        }
+
+    }
 
 }
diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoService.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoService.java
index fdb8770..56ed893 100644
--- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoService.java
+++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoService.java
@@ -22,12 +22,15 @@
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+
 import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 
+
 @Api(value = "echo")
 @Path("/junit/echo")
 public class RestEchoService {
@@ -35,11 +38,17 @@
     @GET
     @Path("{word}")
     @Produces(MediaType.TEXT_PLAIN)
-    @ApiOperation(
-        value = "echoes back whatever received"
-                    )
-    public String echo(@PathParam("word") String word) {   
+    @ApiOperation(value = "echoes back whatever received")
+    public String echo(@PathParam("word") String word) {
         return word;
     }
 
+    @PUT
+    @Path("{word}")
+    @Produces(MediaType.TEXT_PLAIN)
+    @ApiOperation(value = "echoes back whatever received")
+    public String echoPut(@PathParam("word") String word, Object entity) {
+        return word + ":" + entity.toString();
+    }
+
 }