Merge default params files 57/26857/2
authorKanagaraj Manickam k00365106 <kanagaraj.manickam@huawei.com>
Mon, 25 Dec 2017 09:58:52 +0000 (15:28 +0530)
committerKanagaraj Manickam k00365106 <kanagaraj.manickam@huawei.com>
Tue, 26 Dec 2017 04:51:55 +0000 (10:21 +0530)
Issue-ID: CLI-66

Change-Id: I320e21ff3b25d0c38c196b49f2ed320174396e4a
Signed-off-by: Kanagaraj Manickam k00365106 <kanagaraj.manickam@huawei.com>
14 files changed:
framework/src/main/java/org/onap/cli/fw/cmd/OnapCommand.java
framework/src/main/java/org/onap/cli/fw/registrar/OnapCommandRegistrar.java
framework/src/main/java/org/onap/cli/fw/schema/OnapCommandSchemaLoader.java
framework/src/main/java/org/onap/cli/fw/schema/OnapCommandSchemaMerger.java [new file with mode: 0644]
framework/src/main/java/org/onap/cli/fw/utils/OnapCommandDiscoveryUtils.java
framework/src/main/java/org/onap/cli/fw/utils/OnapCommandUtils.java
framework/src/main/resources/open-cli-schema/default_input_parameters.yaml
framework/src/main/resources/open-cli.properties
framework/src/test/java/org/onap/cli/fw/schema/ValidateSchemaTest.java
framework/src/test/resources/test-command-to-valdiate-merge.yaml [new file with mode: 0644]
profiles/http/src/main/java/org/onap/cli/fw/http/cmd/OnapHttpCommand.java
profiles/http/src/main/java/org/onap/cli/fw/http/schema/OnapCommandSchemaHttpLoader.java
profiles/http/src/main/resources/open-cli-schema/http/default_input_parameters_http.yaml
validate/validation/src/test/java/org/onap/cli/validation/OnapValidationTest.java

index 5479b51..8db3ab7 100644 (file)
@@ -33,6 +33,7 @@ import org.onap.cli.fw.output.OnapCommandResultAttribute;
 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
 import org.onap.cli.fw.output.OnapCommandResultType;
 import org.onap.cli.fw.schema.OnapCommandSchemaLoader;
+import org.onap.cli.fw.schema.OnapCommandSchemaMerger;
 import org.onap.cli.fw.utils.OnapCommandHelperUtils;
 import org.onap.cli.fw.utils.OnapCommandUtils;
 import org.slf4j.Logger;
@@ -58,8 +59,21 @@ public abstract class OnapCommand {
 
     private OnapCommandResult cmdResult = new OnapCommandResult();
 
+    private List<String> defaultSchemas = new ArrayList<>();
+
     protected boolean isInitialzied = false;
 
+    protected OnapCommand() {
+        this.addDefaultSchemas(OnapCommandConstants.DEFAULT_PARAMETER_FILE_NAME);
+    }
+
+    public List<String> getSchemas() throws OnapCommandException {
+        List<String> schemas = new ArrayList<>();
+        schemas.addAll(this.defaultSchemas);
+        schemas.add(this.getSchemaName());
+        return schemas;
+    }
+
     public String getSchemaVersion() {
         return OnapCommandConstants.OPEN_CLI_SCHEMA_VERSION_VALUE_1_0;
     }
@@ -116,6 +130,14 @@ public abstract class OnapCommand {
         this.cmdSchemaName = schemaName;
     }
 
+    protected void addDefaultSchemas(String schema) {
+        this.defaultSchemas.add(schema);
+    }
+
+    public List<String> getDefaultSchema() {
+        return this.defaultSchemas;
+    }
+
     /**
      * Initialize this command from command schema and assumes schema is already validated.
      *
@@ -127,11 +149,13 @@ public abstract class OnapCommand {
         return this.initializeSchema(schema, false);
     }
 
+
     public List<String> initializeSchema(String schema, boolean validate) throws OnapCommandException {
         this.setSchemaName(schema);
 
-        List<String> errors = OnapCommandSchemaLoader.loadSchema(this, schema, true, validate);
-        errors.addAll(this.initializeProfileSchema(validate));
+        Map<String, ?> schemaMap = OnapCommandSchemaMerger.mergeSchemas(this);
+        List<String> errors = OnapCommandSchemaLoader.parseSchema(this, schemaMap, validate);
+        errors.addAll(this.initializeProfileSchema(schemaMap, validate));
         this.isInitialzied = true;
 
         return errors;
@@ -139,7 +163,7 @@ public abstract class OnapCommand {
     /**
      * Any additional profile based such as http schema could be initialized.
      */
-    protected List<String> initializeProfileSchema(boolean validate) throws OnapCommandException {
+    protected List<String> initializeProfileSchema(Map<String, ?> schemaMap, boolean validate) throws OnapCommandException {
         return new ArrayList<>();
     }
 
index e9dc288..19dc3f5 100644 (file)
@@ -45,6 +45,8 @@ import org.onap.cli.fw.schema.OnapCommandSchemaInfo;
 import org.onap.cli.fw.utils.OnapCommandDiscoveryUtils;
 import org.onap.cli.fw.utils.OnapCommandHelperUtils;
 import org.onap.cli.fw.utils.OnapCommandUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -53,6 +55,9 @@ import org.onap.cli.fw.utils.OnapCommandUtils;
  *
  */
 public class OnapCommandRegistrar {
+
+    private static Logger LOG = LoggerFactory.getLogger(OnapCommandRegistrar.class);
+
     private Map<String, Class<? extends OnapCommand>> registry = new HashMap<>();
 
     private Map<String, Class<? extends OnapCommand>> registryProfilePlugins = new HashMap<>();
@@ -271,6 +276,7 @@ public class OnapCommandRegistrar {
 
         for (OnapCommandSchemaInfo schema : schemas) {
             if (schema.isIgnore()) {
+                LOG.info("Ignoring schema " + schema.getSchemaURI());
                 continue;
             }
 
@@ -280,7 +286,7 @@ public class OnapCommandRegistrar {
              } else if (plugins.containsKey(schema.getSchemaProfile())) {
                 this.register(schema.getCmdName(), schema.getProduct(), plugins.get(schema.getSchemaProfile()));
             } else {
-                throw new OnapUnsupportedSchemaProfile(schema.getSchemaURI());
+                LOG.info("Ignoring schema " + schema.getSchemaURI());
             }
         }
     }
index 0c4af80..bcf9326 100644 (file)
@@ -33,11 +33,11 @@ import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_SERVICE;
 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_TYPE;
 import static org.onap.cli.fw.conf.OnapCommandConstants.INPUT_PARAMS_LIST;
 import static org.onap.cli.fw.conf.OnapCommandConstants.INPUT_PARAMS_MANDATORY_LIST;
+import static org.onap.cli.fw.conf.OnapCommandConstants.IS_DEFAULT_ATTR;
+import static org.onap.cli.fw.conf.OnapCommandConstants.IS_DEFAULT_PARAM;
 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_INCLUDE;
 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_OPTIONAL;
 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_SECURED;
-import static org.onap.cli.fw.conf.OnapCommandConstants.IS_DEFAULT_ATTR;
-import static org.onap.cli.fw.conf.OnapCommandConstants.IS_DEFAULT_PARAM;
 import static org.onap.cli.fw.conf.OnapCommandConstants.LONG_OPTION;
 import static org.onap.cli.fw.conf.OnapCommandConstants.NAME;
 import static org.onap.cli.fw.conf.OnapCommandConstants.OPEN_CLI_SCHEMA_VERSION;
@@ -81,7 +81,6 @@ import org.onap.cli.fw.info.OnapCommandInfo;
 import org.onap.cli.fw.input.OnapCommandParameter;
 import org.onap.cli.fw.input.OnapCommandParameterType;
 import org.onap.cli.fw.output.OnapCommandPrintDirection;
-import org.onap.cli.fw.output.OnapCommandResult;
 import org.onap.cli.fw.output.OnapCommandResultAttribute;
 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
 import org.onap.cli.fw.utils.OnapCommandDiscoveryUtils;
@@ -272,21 +271,9 @@ public class OnapCommandSchemaLoader {
                     if (parameters != null) {
                         Set<String> names = new HashSet<>();
 
-                        //To support overriding of the parameters, if command is already
-                        //having the same named parameters, means same parameter is
-                        //Overridden from included template into current template
-                        Set<String> existingParamNames =  cmd.getParametersMap().keySet();
-
                         for (Map<String, String> parameter : parameters) {
-                            boolean isOverriding = false;
                             OnapCommandParameter param = new OnapCommandParameter();
 
-                            //Override the parameters from its base such as default parameters list
-                            if (existingParamNames.contains(parameter.getOrDefault(NAME, ""))) {
-                                param = cmd.getParametersMap().get(parameter.getOrDefault(NAME, ""));
-                                isOverriding = true;
-                            }
-
                             if (validate) {
                                 OnapCommandUtils.validateTags(exceptionList, parameter, OnapCommandConfig.getCommaSeparatedList(INPUT_PARAMS_LIST),
                                         OnapCommandConfig.getCommaSeparatedList(INPUT_PARAMS_MANDATORY_LIST), PARAMETERS);
@@ -404,11 +391,7 @@ public class OnapCommandSchemaLoader {
                                 }
                             }
 
-                            if ( !isOverriding) {
-                                cmd.getParameters().add(param);
-                            } else {
-                                cmd.getParametersMap().replace(param.getName(), param);
-                            }
+                            cmd.getParameters().add(param);
                         }
                     }
                     break;
diff --git a/framework/src/main/java/org/onap/cli/fw/schema/OnapCommandSchemaMerger.java b/framework/src/main/java/org/onap/cli/fw/schema/OnapCommandSchemaMerger.java
new file mode 100644 (file)
index 0000000..97ca4c1
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2017 Huawei Technologies Co., Ltd.
+ *
+ * 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.
+ */
+
+package org.onap.cli.fw.schema;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.onap.cli.fw.cmd.OnapCommand;
+import org.onap.cli.fw.conf.OnapCommandConstants;
+import org.onap.cli.fw.error.OnapCommandException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helps to merge two yaml schemas
+ *
+ */
+public class OnapCommandSchemaMerger {
+
+    static Logger LOG = LoggerFactory.getLogger(OnapCommandSchemaMerger.class);
+
+    public static Map<String, ?> mergeSchemas(OnapCommand cmd) throws OnapCommandException {
+        Map<String, Object> mergedResult = new LinkedHashMap<String, Object>();
+
+        for (String schema: cmd.getSchemas()) {
+            Map<String , Object> schemaMap = (Map<String, Object>) OnapCommandSchemaLoader.validateSchemaVersion(schema, cmd.getSchemaVersion());
+            mergeYamlMap(mergedResult, schemaMap);
+        }
+
+        return mergedResult;
+
+    }
+
+    public static void mergeYamlMap(Map<String, Object> mergedResult, Map<String, Object> yamlContents) {
+        if (yamlContents == null) return;
+
+        for (String key : yamlContents.keySet()) {
+
+            Object yamlValue = yamlContents.get(key);
+            if (yamlValue == null) {
+                mergedResult.put(key, yamlValue);
+                continue;
+            }
+
+            Object existingValue = mergedResult.get(key);
+            if (existingValue != null) {
+                if (yamlValue instanceof Map) {
+                    if (existingValue instanceof Map) {
+                        mergeYamlMap((Map<String, Object>) existingValue, (Map<String, Object>)  yamlValue);
+                    } else if (existingValue instanceof String) {
+                        throw new IllegalArgumentException("Cannot merge complex element into a simple element: "+key);
+                    } else {
+                        throw unknownValueType(key, yamlValue);
+                    }
+                } else if (yamlValue instanceof List) {
+                    mergeYamlLists(mergedResult, key, yamlValue);
+
+                } else if (yamlValue instanceof String
+                        || yamlValue instanceof Boolean
+                        || yamlValue instanceof Double
+                        || yamlValue instanceof Integer) {
+                    mergedResult.put(key, yamlValue);
+
+                } else {
+                    throw unknownValueType(key, yamlValue);
+                }
+
+            } else {
+                if (yamlValue instanceof Map
+                        || yamlValue instanceof List
+                        || yamlValue instanceof String
+                        || yamlValue instanceof Boolean
+                        || yamlValue instanceof Integer
+                        || yamlValue instanceof Double) {
+                    mergedResult.put(key, yamlValue);
+                } else {
+                    throw unknownValueType(key, yamlValue);
+                }
+            }
+        }
+    }
+
+    private static IllegalArgumentException unknownValueType(String key, Object yamlValue) {
+        final String msg = "Cannot merge element of unknown type: " + key + ": " + yamlValue.getClass().getName();
+        return new IllegalArgumentException(msg);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void mergeYamlLists(Map<String, Object> mergedResult, String key, Object yamlValue) {
+        if (! (yamlValue instanceof List && mergedResult.get(key) instanceof List)) {
+            throw new IllegalArgumentException("Cannot merge a list with a non-list: "+key);
+        }
+
+        List<Object> originalList = (List<Object>) mergedResult.get(key);
+
+        for (Object o: (List<Object>) yamlValue) {
+            Map<String, Object> oN = (Map) o;
+            String nameN = (String)oN.getOrDefault(OnapCommandConstants.NAME, null);
+
+            //Name should be existing in the map, otherwise continue as don't know how to compare
+            if (nameN == null) {
+                continue;
+            }
+
+            boolean existing = false;
+            for (Object e: originalList) {
+                Map<String, Object> oE = (Map) e;
+                String nameE = (String)oE.getOrDefault(OnapCommandConstants.NAME, null);
+
+                //Name should be existing in the map, otherwise continue as don't know how to compare
+                if (nameE == null) {
+                    continue;
+                }
+
+                if (nameN.equals(nameE)) {
+                    for (Entry<String, Object> oNe : oN.entrySet()) {
+                           oE.put(oNe.getKey(), oNe.getValue());
+                    }
+                    existing = true;
+                    break;
+                }
+            }
+
+            if (!existing) {
+                originalList.add(o);
+            }
+        }
+    }
+}
+
index 7d305a8..30a7ac6 100644 (file)
@@ -30,9 +30,11 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
+import java.util.Map.Entry;
 
 import org.onap.cli.fw.cmd.OnapCommand;
 import org.onap.cli.fw.conf.OnapCommandConfig;
index 44c71e5..bb35ac2 100644 (file)
@@ -1,10 +1,5 @@
 open_cli_schema_version: 1.0
 
-info:
-  product: open-cli
-  service: default-param
-  ignore: true
-
 parameters:
   - name: help
     type: bool
index 0e8b2af..2ae1b14 100644 (file)
@@ -3,7 +3,7 @@ cli.version=1.0
 cli.discover_always=false
 
 #schema validation
-cli.schema.top_level_params_list=open_cli_schema_version,name,description,parameters,results,http,info
+cli.schema.top_level_params_list=open_cli_schema_version,name,description,parameters,results,info
 cli.schema.top_level_mandatory_list=open_cli_schema_version
 
 cli.schema.info_params_list=product,service,type,author,ignore
index 8153b6d..a33b785 100644 (file)
@@ -37,6 +37,17 @@ public class ValidateSchemaTest {
         OnapCommandSchemaLoader.loadSchema(cmd, "fdsfds.yaml", true, true);
     }
 
+
+    @Test
+    public void validateTestMerge() throws OnapCommandException {
+
+        OnapCommand cmd = new OnapCommand() {
+            @Override
+            protected void run() throws OnapCommandException {}
+        };
+        cmd.initializeSchema("test-command-to-valdiate-merge.yaml", true);
+    }
+
     @Test(expected = OnapCommandInvalidSchema.class)
     public void invalidateTest2() throws OnapCommandException {
         OnapCommand cmd = new OnapCommand() {
diff --git a/framework/src/test/resources/test-command-to-valdiate-merge.yaml b/framework/src/test/resources/test-command-to-valdiate-merge.yaml
new file mode 100644 (file)
index 0000000..1a381a4
--- /dev/null
@@ -0,0 +1,15 @@
+open_cli_schema_version: 1.0
+
+name: test-command-to-valdiate-merge
+
+description: cli catalog command to find the base path for service.
+
+info:
+  product: open-cli
+  service: test
+  type: cmd
+  author: Kanagaraj Manickam kanagaraj.manickam@huawei.com
+
+parameters:
+  - name: help
+    is_include: false
index 1230934..17d9c73 100644 (file)
@@ -61,6 +61,10 @@ public class OnapHttpCommand extends OnapCommand {
 
     private OnapCommandHttpService oclipService = new OnapCommandHttpService();
 
+    public OnapHttpCommand() {
+        super.addDefaultSchemas(OnapCommandHttpConstants.DEFAULT_PARAMETER_HTTP_FILE_NAME);
+    }
+
     public void setInput(HttpInput input) {
         this.input = input;
     }
@@ -102,8 +106,8 @@ public class OnapHttpCommand extends OnapCommand {
     }
 
     @Override
-    protected List<String> initializeProfileSchema(boolean validate) throws OnapCommandException {
-        return OnapCommandSchemaHttpLoader.loadHttpSchema(this, this.getSchemaName(), true, validate);
+    protected List<String> initializeProfileSchema(Map<String, ?> schemaMap, boolean validate) throws OnapCommandException {
+        return OnapCommandSchemaHttpLoader.parseHttpSchema(this, schemaMap, validate);
     }
 
     @Override
index 08a7078..6dd1588 100644 (file)
@@ -87,7 +87,7 @@ public class OnapCommandSchemaHttpLoader {
      * @throws OnapCommandException
      *             on error
      */
-    static ArrayList<String> parseHttpSchema(OnapHttpCommand cmd,
+    public static ArrayList<String> parseHttpSchema(OnapHttpCommand cmd,
                                                     final Map<String, ?> values,
                                                     boolean validate) throws OnapCommandException {
         ArrayList<String> errorList = new ArrayList<>();
@@ -98,6 +98,7 @@ public class OnapCommandSchemaHttpLoader {
                 if (validate) {
                     OnapCommandUtils.validateTags(errorList, valMap, OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_SECTIONS),
                             OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_MANDATORY_SECTIONS), OnapCommandHttpConstants.HTTP);
+                    errorList.addAll(validateHttpSchemaSection(values));
                 }
                 for (Map.Entry<String, ?> entry1 : valMap.entrySet()) {
                     String key1 = entry1.getKey();
index d8e2632..6f84c95 100644 (file)
@@ -53,7 +53,7 @@ public class OnapValidationTest {
                 if (sch.isIgnore()) {
                     continue;
                 }
-                if (sch.getProduct().equals(version)) {
+                if (sch.getProduct() != null && sch.getProduct().equals(version)) {
                     System.out.println(
                     "************************* validate '" + sch.getCmdName() + "' *******************************");
                     OnapCommandRegistrar.getRegistrar().setEnabledProductVersion("open-cli");
@@ -74,7 +74,7 @@ public class OnapValidationTest {
                 if (sch.isIgnore()) {
                     continue;
                 }
-                if (sch.getProduct().equals(version)) {
+                if (sch.getProduct() != null && sch.getProduct().equals(version)) {
                     System.out.println("[" + i++ + "] " + sch.getCmdName());
                     System.out.println("-----------------------------------------------\n\n");
                     this.handle(new String[] { sch.getCmdName(), "-h"});