Add support for parameter inheritance 36/74936/1
authorliamfallon <liam.fallon@est.tech>
Wed, 19 Dec 2018 19:14:35 +0000 (19:14 +0000)
committerliamfallon <liam.fallon@est.tech>
Wed, 19 Dec 2018 19:14:40 +0000 (19:14 +0000)
Common parameter support does not allow for inheritance of parameters
from a super class. This change allows inheritance of public and protected
members from a parameter superclass to a parameter subclass.

Issue-ID: POLICY-1222
Change-Id: Ia4f452abab80953b41784c44e4202e8d5405a197
Signed-off-by: liamfallon <liam.fallon@est.tech>
common-parameters/src/main/java/org/onap/policy/common/parameters/GroupValidationResult.java
policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/HttpServletServerFactory.java

index 5beef5b..283f36b 100644 (file)
@@ -25,8 +25,10 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -59,23 +61,24 @@ public class GroupValidationResult implements ValidationResult {
             return;
         }
 
-        // Add a validation result per field
+        // Add a validation result for all fields in the declared class
         for (Field field : parameterGroup.getClass().getDeclaredFields()) {
-            // Exclude system fields
-            if (field.getName().startsWith("$") || field.getName().startsWith("_")) {
-                continue;
+            // Check if a validation result should be added for this declared field
+            if (isIncludedField(field)) {
+                // Set a validation result for the field
+                validationResultMap.put(field.getName(), getValidationResult(field, parameterGroup));
             }
+        }
 
-            // Exclude static fields
-            if (Modifier.isStatic(field.getModifiers())) {
-                continue;
+        // Add a validation result for protected and public fields in super classes
+        for (Field field : getSuperclassFields(parameterGroup.getClass().getSuperclass())) {
+            // Check if a validation result should be added for this declared field
+            if (isIncludedField(field)) {
+                // Set a validation result for the field
+                validationResultMap.putIfAbsent(field.getName(), getValidationResult(field, parameterGroup));
             }
-
-            // Set the validation result
-            validationResultMap.put(field.getName(), getValidationResult(field, parameterGroup));
         }
     }
-
     /**
      * Construct a validation result for a field.
      * 
@@ -139,7 +142,7 @@ public class GroupValidationResult implements ValidationResult {
             getterMethod = targetObject.getClass().getMethod(getterMethodName, (Class<?>[]) null);
         } catch (NoSuchMethodException | SecurityException e) {
             throw new ParameterRuntimeException("could not get getter method for parameter \"" + field.getName() + "\"",
-                            e);
+                e);
         }
 
         // Invoke the getter
@@ -147,7 +150,7 @@ public class GroupValidationResult implements ValidationResult {
             return getterMethod.invoke(targetObject, (Object[]) null);
         } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
             throw new ParameterRuntimeException("error calling getter method for parameter \"" + field.getName() + "\"",
-                            e);
+                e);
         }
     }
 
@@ -168,13 +171,13 @@ public class GroupValidationResult implements ValidationResult {
             // Check the key is a string
             if (!String.class.isAssignableFrom(mapEntry.getKey().getClass())) {
                 throw new ParameterRuntimeException("map entry is not a parameter group keyed by a string, key \""
-                                + mapEntry.getKey() + "\" in map \"" + fieldName + "\" is not a string");
+                    + mapEntry.getKey() + "\" in map \"" + fieldName + "\" is not a string");
             }
 
             // Check the value is a parameter group
             if (!ParameterGroup.class.isAssignableFrom(mapEntry.getValue().getClass())) {
                 throw new ParameterRuntimeException("map entry is not a parameter group keyed by a string, value \""
-                                + mapEntry.getValue() + "\" in map \"" + fieldName + "\" is not a parameter group");
+                    + mapEntry.getValue() + "\" in map \"" + fieldName + "\" is not a parameter group");
             }
         }
     }
@@ -195,7 +198,7 @@ public class GroupValidationResult implements ValidationResult {
         for (Object collectionMember : collection2Check) {
             if (ParameterGroup.class.isAssignableFrom(collectionMember.getClass())) {
                 throw new ParameterRuntimeException("collection parameter \"" + fieldName + "\" is illegal,"
-                                + " parameter groups are not allowed as collection members");
+                    + " parameter groups are not allowed as collection members");
             }
         }
     }
@@ -307,7 +310,7 @@ public class GroupValidationResult implements ValidationResult {
      * @param nestedMapValidationResult The validation result from a nested map entry
      */
     public void setResult(final String parameterName, final String key,
-                    final ValidationResult nestedMapValidationResult) {
+        final ValidationResult nestedMapValidationResult) {
         GroupMapValidationResult groupMapValidationResult;
         try {
             groupMapValidationResult = (GroupMapValidationResult) validationResultMap.get(parameterName);
@@ -333,7 +336,7 @@ public class GroupValidationResult implements ValidationResult {
      * @param message The message for the parameter group
      */
     public void setResult(final String parameterName, final String key, final ValidationStatus status,
-                    final String message) {
+        final String message) {
         GroupMapValidationResult groupMapValidationResult;
         try {
             groupMapValidationResult = (GroupMapValidationResult) validationResultMap.get(parameterName);
@@ -384,7 +387,7 @@ public class GroupValidationResult implements ValidationResult {
 
         for (ValidationResult fieldResult : validationResultMap.values()) {
             String fieldResultMessage = fieldResult.getResult(initialIndentation + subIndentation, subIndentation,
-                            showClean);
+                showClean);
             if (fieldResultMessage != null) {
                 validationResultBuilder.append(fieldResultMessage);
             }
@@ -392,4 +395,41 @@ public class GroupValidationResult implements ValidationResult {
 
         return validationResultBuilder.toString();
     }
+    
+
+    /**
+     * Check if a field should be included for validation.
+     * 
+     * @param field the field to check for inclusion
+     * @return true of the field should be included
+     */
+    private boolean isIncludedField(final Field field) {
+        return !field.getName().startsWith("$") && !field.getName().startsWith("_")
+            && !Modifier.isStatic(field.getModifiers());
+    }
+
+    /**
+     * Get the public and protected fields of super classes.
+     * @param firstSuperClass the first superclass to check
+     *
+     * @return a set of the superclass fields
+     */
+    private List<Field> getSuperclassFields(final Class<?> firstSuperClass) {
+        List<Field> superclassFields = new ArrayList<>();
+
+        Class<?> currentClass = firstSuperClass;
+        while (currentClass.getSuperclass() != null) {
+            for (Field field : currentClass.getDeclaredFields()) {
+                // Check if this field is public or protected
+                if (Modifier.isPublic(field.getModifiers()) || Modifier.isProtected(field.getModifiers())) {
+                    superclassFields.add(field);
+                }
+            }
+            
+            // Check the next super class down
+            currentClass = currentClass.getSuperclass();
+        }
+        
+        return superclassFields;
+    }
 }
\ No newline at end of file
index 4a33f56..527ada9 100644 (file)
@@ -25,7 +25,6 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Properties;
-import org.onap.aaf.cadi.filter.CadiFilter;
 import org.onap.policy.common.endpoints.http.server.internal.JettyJerseyServer;
 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
 import org.slf4j.Logger;
@@ -50,7 +49,7 @@ public interface HttpServletServerFactory {
      * @throws IllegalArgumentException when invalid parameters are provided
      */
     HttpServletServer build(String name, boolean https, String host, int port, String contextPath, boolean swagger,
-            boolean managed);
+        boolean managed);
 
     /**
      * Builds an http server with support for servlets.
@@ -64,8 +63,7 @@ public interface HttpServletServerFactory {
      * @return http server
      * @throws IllegalArgumentException when invalid parameters are provided
      */
-    HttpServletServer build(String name, String host, int port, String contextPath, boolean swagger,
-        boolean managed);
+    HttpServletServer build(String name, String host, int port, String contextPath, boolean swagger, boolean managed);
 
     /**
      * Build a list of http servers per properties.
@@ -104,7 +102,6 @@ public interface HttpServletServerFactory {
     void destroy();
 }
 
-
 /**
  * Indexed factory implementation.
  */
@@ -123,9 +120,8 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
     protected HashMap<Integer, HttpServletServer> servers = new HashMap<>();
 
     @Override
-    public synchronized HttpServletServer build(String name, boolean https, 
-                    String host, int port, String contextPath, boolean swagger,
-            boolean managed) {
+    public synchronized HttpServletServer build(String name, boolean https, String host, int port, String contextPath,
+        boolean swagger, boolean managed) {
 
         if (servers.containsKey(port)) {
             return servers.get(port);
@@ -140,12 +136,11 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
     }
 
     @Override
-    public synchronized HttpServletServer build(String name, String host, int port, String contextPath,
-                                                boolean swagger, boolean managed) {
+    public synchronized HttpServletServer build(String name, String host, int port, String contextPath, boolean swagger,
+        boolean managed) {
         return build(name, false, host, port, contextPath, swagger, managed);
     }
 
-
     @Override
     public synchronized List<HttpServletServer> build(Properties properties) {
 
@@ -161,7 +156,7 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
 
         for (String serviceName : serviceNameList) {
             String servicePortString = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
-                    + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX);
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX);
 
             int servicePort;
             try {
@@ -180,48 +175,41 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
             }
 
             final String hostName = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX);
+                + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_HOST_SUFFIX);
 
-            final String contextUriPath = properties.getProperty(
-                    PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX);
+            final String contextUriPath = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_CONTEXT_URIPATH_SUFFIX);
 
             final String userName = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX);
+                + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX);
 
             final String password = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX);
-
-            final String authUriPath = properties.getProperty(
-                    PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_URIPATH_SUFFIX);
-
-            final String restClasses = properties.getProperty(
-                    PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX);
-
-            final String filterClasses = properties.getProperty(
-                    PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX);
-
-            final String restPackages = properties.getProperty(
-                    PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX);
-            
-            final String restUriPath = properties.getProperty(
-                    PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_REST_URIPATH_SUFFIX);
-
-            final String managedString = properties.getProperty(
-                    PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX);
+                + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_PASSWORD_SUFFIX);
+
+            final String authUriPath = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_URIPATH_SUFFIX);
+
+            final String restClasses = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_REST_CLASSES_SUFFIX);
+
+            final String filterClasses = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX);
+
+            final String restPackages = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_REST_PACKAGES_SUFFIX);
+
+            final String restUriPath = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_REST_URIPATH_SUFFIX);
+
+            final String managedString = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES
+                + "." + serviceName + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX);
             boolean managed = true;
             if (managedString != null && !managedString.isEmpty()) {
                 managed = Boolean.parseBoolean(managedString);
             }
 
             String swaggerString = properties.getProperty(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "."
-                    + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX);
+                + serviceName + PolicyEndPointProperties.PROPERTY_HTTP_SWAGGER_SUFFIX);
             boolean swagger = false;
             if (swaggerString != null && !swaggerString.isEmpty()) {
                 swagger = Boolean.parseBoolean(swaggerString);
@@ -241,8 +229,8 @@ class IndexedHttpServletServerFactory implements HttpServletServerFactory {
                 aaf = Boolean.parseBoolean(aafString);
             }
 
-            HttpServletServer service = build(serviceName, https, hostName, servicePort, 
-                    contextUriPath, swagger, managed);
+            HttpServletServer service = build(serviceName, https, hostName, servicePort, contextUriPath, swagger,
+                managed);
 
             /* authentication method either AAF or HTTP Basic Auth */