Optimize version option output
[cli.git] / framework / src / main / java / org / onap / cli / fw / utils / OnapCommandUtils.java
1 /*
2  * Copyright 2017 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.cli.fw.utils;
18
19 import static org.onap.cli.fw.conf.Constants.API;
20 import static org.onap.cli.fw.conf.Constants.ATTRIBUTES;
21 import static org.onap.cli.fw.conf.Constants.AUTH;
22 import static org.onap.cli.fw.conf.Constants.AUTH_VALUES;
23 import static org.onap.cli.fw.conf.Constants.BODY;
24 import static org.onap.cli.fw.conf.Constants.BOOLEAN_VALUE;
25 import static org.onap.cli.fw.conf.Constants.CLIENT;
26 import static org.onap.cli.fw.conf.Constants.COMMAND_TYPE_VALUES;
27 import static org.onap.cli.fw.conf.Constants.DATA_DIRECTORY;
28 import static org.onap.cli.fw.conf.Constants.DATA_PATH_JSON_PATTERN;
29 import static org.onap.cli.fw.conf.Constants.DEAFULT_PARAMETER_PASSWORD;
30 import static org.onap.cli.fw.conf.Constants.DEAFULT_PARAMETER_USERNAME;
31 import static org.onap.cli.fw.conf.Constants.DEFAULT_PARAMETER_FILE_NAME;
32 import static org.onap.cli.fw.conf.Constants.DEFAULT_PARAMETER_HTTP_FILE_NAME;
33 import static org.onap.cli.fw.conf.Constants.DEFAULT_PARAMETER_NO_AUTH;
34 import static org.onap.cli.fw.conf.Constants.DEFAULT_VALUE;
35 import static org.onap.cli.fw.conf.Constants.DESCRIPTION;
36 import static org.onap.cli.fw.conf.Constants.DIRECTION;
37 import static org.onap.cli.fw.conf.Constants.DISCOVERY_FILE;
38 import static org.onap.cli.fw.conf.Constants.ENTITY;
39 import static org.onap.cli.fw.conf.Constants.EXCEPTION;
40 import static org.onap.cli.fw.conf.Constants.EXECUTOR;
41 import static org.onap.cli.fw.conf.Constants.HEADERS;
42 import static org.onap.cli.fw.conf.Constants.HTTP;
43 import static org.onap.cli.fw.conf.Constants.HTTP_BODY_FAILED_PARSING;
44 import static org.onap.cli.fw.conf.Constants.HTTP_BODY_JSON_EMPTY;
45 import static org.onap.cli.fw.conf.Constants.HTTP_MANDATORY_SECTIONS;
46 import static org.onap.cli.fw.conf.Constants.HTTP_METHODS;
47 import static org.onap.cli.fw.conf.Constants.HTTP_REQUEST_MANDATORY_PARAMS;
48 import static org.onap.cli.fw.conf.Constants.HTTP_REQUEST_PARAMS;
49 import static org.onap.cli.fw.conf.Constants.HTTP_SECTIONS;
50 import static org.onap.cli.fw.conf.Constants.HTTP_SUCCESS_CODE_INVALID;
51 import static org.onap.cli.fw.conf.Constants.INFO;
52 import static org.onap.cli.fw.conf.Constants.INFO_AUTHOR;
53 import static org.onap.cli.fw.conf.Constants.INFO_PARAMS_LIST;
54 import static org.onap.cli.fw.conf.Constants.INFO_PARAMS_MANDATORY_LIST;
55 import static org.onap.cli.fw.conf.Constants.INFO_PRODUCT;
56 import static org.onap.cli.fw.conf.Constants.INFO_SERVICE;
57 import static org.onap.cli.fw.conf.Constants.INFO_TYPE;
58 import static org.onap.cli.fw.conf.Constants.INPUT_PARAMS_LIST;
59 import static org.onap.cli.fw.conf.Constants.INPUT_PARAMS_MANDATORY_LIST;
60 import static org.onap.cli.fw.conf.Constants.IS_INCLUDE;
61 import static org.onap.cli.fw.conf.Constants.IS_OPTIONAL;
62 import static org.onap.cli.fw.conf.Constants.IS_SECURED;
63 import static org.onap.cli.fw.conf.Constants.LONG_OPTION;
64 import static org.onap.cli.fw.conf.Constants.METHOD;
65 import static org.onap.cli.fw.conf.Constants.METHOD_TYPE;
66 import static org.onap.cli.fw.conf.Constants.MODE;
67 import static org.onap.cli.fw.conf.Constants.MODE_VALUES;
68 import static org.onap.cli.fw.conf.Constants.MULTIPART_ENTITY_NAME;
69 import static org.onap.cli.fw.conf.Constants.NAME;
70 import static org.onap.cli.fw.conf.Constants.OPEN_CLI_SCHEMA_VERSION;
71 import static org.onap.cli.fw.conf.Constants.PARAMETERS;
72 import static org.onap.cli.fw.conf.Constants.QUERIES;
73 import static org.onap.cli.fw.conf.Constants.REQUEST;
74 import static org.onap.cli.fw.conf.Constants.RESULTS;
75 import static org.onap.cli.fw.conf.Constants.RESULT_MAP;
76 import static org.onap.cli.fw.conf.Constants.RESULT_PARAMS_LIST;
77 import static org.onap.cli.fw.conf.Constants.RESULT_PARAMS_MANDATORY_LIST;
78 import static org.onap.cli.fw.conf.Constants.SAMPLE_RESPONSE;
79 import static org.onap.cli.fw.conf.Constants.SCHEMA_DIRECTORY;
80 import static org.onap.cli.fw.conf.Constants.SCHEMA_FILE_NOT_EXIST;
81 import static org.onap.cli.fw.conf.Constants.SCHEMA_FILE_WRONG_EXTN;
82 import static org.onap.cli.fw.conf.Constants.SCHEMA_PATH_PATERN;
83 import static org.onap.cli.fw.conf.Constants.SCOPE;
84 import static org.onap.cli.fw.conf.Constants.SERVICE;
85 import static org.onap.cli.fw.conf.Constants.SERVICE_PARAMS_LIST;
86 import static org.onap.cli.fw.conf.Constants.SERVICE_PARAMS_MANDATORY_LIST;
87 import static org.onap.cli.fw.conf.Constants.SHORT_OPTION;
88 import static org.onap.cli.fw.conf.Constants.SUCCESS_CODES;
89 import static org.onap.cli.fw.conf.Constants.TOP_LEVEL_MANDATORY_LIST;
90 import static org.onap.cli.fw.conf.Constants.TOP_LEVEL_PARAMS_LIST;
91 import static org.onap.cli.fw.conf.Constants.TYPE;
92 import static org.onap.cli.fw.conf.Constants.URI;
93 import static org.onap.cli.fw.conf.Constants.VERSION;
94
95 import java.io.File;
96 import java.io.FileInputStream;
97 import java.io.FileNotFoundException;
98 import java.io.IOException;
99 import java.io.InputStream;
100 import java.util.ArrayList;
101 import java.util.Arrays;
102 import java.util.Collections;
103 import java.util.HashMap;
104 import java.util.HashSet;
105 import java.util.List;
106 import java.util.Map;
107 import java.util.Map.Entry;
108 import java.util.ServiceLoader;
109 import java.util.Set;
110 import java.util.UUID;
111 import java.util.jar.Attributes;
112 import java.util.jar.JarFile;
113 import java.util.jar.Manifest;
114 import java.util.stream.Collectors;
115
116 import org.onap.cli.fw.OnapCommand;
117 import org.onap.cli.fw.ad.OnapService;
118 import org.onap.cli.fw.cmd.CommandType;
119 import org.onap.cli.fw.cmd.OnapHttpCommand;
120 import org.onap.cli.fw.cmd.OnapSwaggerCommand;
121 import org.onap.cli.fw.conf.Constants;
122 import org.onap.cli.fw.conf.OnapCommandConfg;
123 import org.onap.cli.fw.error.OnapCommandDiscoveryFailed;
124 import org.onap.cli.fw.error.OnapCommandException;
125 import org.onap.cli.fw.error.OnapCommandHelpFailed;
126 import org.onap.cli.fw.error.OnapCommandHttpHeaderNotFound;
127 import org.onap.cli.fw.error.OnapCommandHttpInvalidResponseBody;
128 import org.onap.cli.fw.error.OnapCommandHttpInvalidResultMap;
129 import org.onap.cli.fw.error.OnapCommandInvalidParameterType;
130 import org.onap.cli.fw.error.OnapCommandInvalidParameterValue;
131 import org.onap.cli.fw.error.OnapCommandInvalidPrintDirection;
132 import org.onap.cli.fw.error.OnapCommandInvalidResultAttributeScope;
133 import org.onap.cli.fw.error.OnapCommandInvalidSchema;
134 import org.onap.cli.fw.error.OnapCommandInvalidSchemaVersion;
135 import org.onap.cli.fw.error.OnapCommandLoadProfileFailed;
136 import org.onap.cli.fw.error.OnapCommandParameterNameConflict;
137 import org.onap.cli.fw.error.OnapCommandParameterNotFound;
138 import org.onap.cli.fw.error.OnapCommandParameterOptionConflict;
139 import org.onap.cli.fw.error.OnapCommandPersistProfileFailed;
140 import org.onap.cli.fw.error.OnapCommandResultEmpty;
141 import org.onap.cli.fw.error.OnapCommandResultMapProcessingFailed;
142 import org.onap.cli.fw.error.OnapCommandSchemaNotFound;
143 import org.onap.cli.fw.http.HttpInput;
144 import org.onap.cli.fw.http.HttpResult;
145 import org.onap.cli.fw.info.OnapCommandInfo;
146 import org.onap.cli.fw.input.OnapCommandParameter;
147 import org.onap.cli.fw.input.ParameterType;
148 import org.onap.cli.fw.input.cache.Param;
149 import org.onap.cli.fw.output.OnapCommandResult;
150 import org.onap.cli.fw.output.OnapCommandResultAttribute;
151 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
152 import org.onap.cli.fw.output.PrintDirection;
153 import org.onap.cli.fw.output.ResultType;
154 import org.onap.cli.fw.run.OnapCommandExecutor;
155 import org.slf4j.Logger;
156 import org.slf4j.LoggerFactory;
157 import org.springframework.core.io.Resource;
158 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
159 import org.springframework.core.io.support.ResourcePatternResolver;
160 import org.yaml.snakeyaml.Yaml;
161
162 import com.fasterxml.jackson.databind.ObjectMapper;
163 import com.jayway.jsonpath.JsonPath;
164
165 import net.minidev.json.JSONArray;
166 import net.minidev.json.JSONObject;
167
168 /**
169  * Provides helper method to parse Yaml files and produce required objects.
170  *
171  */
172 public class OnapCommandUtils {
173
174     private static Logger LOG = LoggerFactory.getLogger(OnapCommandUtils.class);
175     /**
176      * Private constructor.
177      */
178     private OnapCommandUtils() {
179
180     }
181
182     /**
183      * Validates schema version.
184      *
185      * @param schemaName schema name
186      * @param version    schema version
187      * @return map
188      * @throws OnapCommandInvalidSchemaVersion invalid schema version exception
189      * @throws OnapCommandInvalidSchema        invalid schema
190      * @throws OnapCommandSchemaNotFound       schema not found
191      */
192     public static Map<String, ?> validateSchemaVersion(String schemaName, String version) throws OnapCommandException {
193         InputStream inputStream = OnapCommandUtils.class.getClassLoader().getResourceAsStream(schemaName);
194
195         try {
196             Resource resource = findResource(schemaName, SCHEMA_PATH_PATERN);
197
198             if (resource != null) {
199                 inputStream = resource.getInputStream();
200             }
201
202         } catch (IOException e) {
203             throw new OnapCommandSchemaNotFound(schemaName, e);
204         }
205         if (inputStream == null) {
206             inputStream = loadSchemaFromFile(schemaName);
207         }
208
209         Map<String, ?> values = null;
210         try {
211             values = (Map<String, ?>) new Yaml().load(inputStream);
212         } catch (Exception e) {
213             throw new OnapCommandInvalidSchema(schemaName, e);
214         }
215         String schemaVersion = "";
216         if (values.keySet().contains(OPEN_CLI_SCHEMA_VERSION)) {
217             Object obj = values.get(OPEN_CLI_SCHEMA_VERSION);
218             schemaVersion = obj.toString();
219         }
220
221         if (!version.equals(schemaVersion)) {
222             throw new OnapCommandInvalidSchemaVersion(schemaVersion);
223         }
224
225         return values;
226     }
227
228     private static InputStream loadSchemaFromFile(String schemaLocation) throws OnapCommandInvalidSchema {
229         File schemaFile = new File(schemaLocation);
230         try {
231             FileInputStream inputFileStream = new FileInputStream(schemaFile);
232             if (!schemaFile.isFile()) {
233                 throw new OnapCommandInvalidSchema(schemaFile.getName(), SCHEMA_FILE_NOT_EXIST);
234             }
235
236             if (!schemaFile.getName().endsWith(".yaml")) {
237                 throw new OnapCommandInvalidSchema(schemaFile.getName(), SCHEMA_FILE_WRONG_EXTN);
238             }
239             return inputFileStream;
240         }catch (FileNotFoundException e) {
241             throw new OnapCommandInvalidSchema(schemaFile.getName(), e);
242         }
243     }
244
245     /**
246      * Retrieve OnapCommand from schema.
247      *
248      * @param cmd            OnapCommand
249      * @param schemaName     schema name
250      * @param includeDefault include if default
251      * @param validateSchema flag to represent validation
252      * @throws OnapCommandException  on error
253      */
254     public static List<String> loadSchema(OnapCommand cmd, String schemaName, boolean includeDefault,
255                                           boolean validateSchema) throws OnapCommandException {
256         try {
257             List<String> errors = new ArrayList<>();
258             if (includeDefault) {
259                 Map<String, ?> defaultParameterMap = includeDefault ?
260                         validateSchemaVersion(DEFAULT_PARAMETER_FILE_NAME, cmd.getSchemaVersion()) : new HashMap<>();
261                 errors.addAll(parseSchema(cmd, defaultParameterMap, validateSchema));
262             }
263
264             Map<String, List<Map<String, String>>> commandYamlMap =
265                     (Map<String, List<Map<String, String>>>)validateSchemaVersion(schemaName, cmd.getSchemaVersion());
266
267             errors.addAll(parseSchema(cmd, commandYamlMap, validateSchema));
268
269             return errors;
270         } catch (OnapCommandException e) {
271             throw e;
272         } catch (Exception e) {
273             throw new OnapCommandInvalidSchema(schemaName, e);
274         }
275     }
276
277
278     public static List<String> loadHttpSchema(OnapHttpCommand cmd, String schemaName, boolean includeDefault,
279                                           boolean validateSchema) throws OnapCommandException {
280         try {
281             List<String> errors = new ArrayList<>();
282             if (includeDefault) {
283                 Map<String, ?> defaultParameterMap = includeDefault ?
284                         validateSchemaVersion(DEFAULT_PARAMETER_HTTP_FILE_NAME, cmd.getSchemaVersion()) : new HashMap<>();
285                 errors.addAll(parseSchema(cmd, defaultParameterMap, validateSchema));
286             }
287
288             Map<String, List<Map<String, String>>> commandYamlMap =
289                     (Map<String, List<Map<String, String>>>)validateSchemaVersion(schemaName, cmd.getSchemaVersion());
290
291             errors.addAll(parseHttpSchema(cmd, commandYamlMap, validateSchema));
292
293             return errors;
294
295         } catch (OnapCommandException e) {
296             throw e;
297         } catch (Exception e) {
298             throw new OnapCommandInvalidSchema(schemaName, e);
299         }
300     }
301
302     private static List<String> parseSchema(OnapCommand cmd,
303                                             final Map<String, ?> values,
304                                             boolean validate) throws OnapCommandException {
305
306         List<String> exceptionList = new ArrayList<>();
307         List<String> shortOptions = new ArrayList<>();
308         List<String> longOptions = new ArrayList<>();
309
310         if (validate) {
311             validateTags(exceptionList, (Map<String, Object>) values, OnapCommandConfg.getSchemaAttrInfo(TOP_LEVEL_PARAMS_LIST),
312                     OnapCommandConfg.getSchemaAttrInfo(TOP_LEVEL_MANDATORY_LIST), "root level");
313         }
314
315
316         List<String> sections = Arrays.asList(NAME, DESCRIPTION, INFO, PARAMETERS, RESULTS);
317
318         for (String key : sections) {
319
320             switch (key) {
321                 case NAME:
322                     Object val = values.get(key);
323                     if (val != null) {
324                         cmd.setName(val.toString());
325                     }
326                     break;
327
328                 case DESCRIPTION:
329                     Object description = values.get(key);
330                     if (description != null) {
331                         cmd.setDescription(description.toString());
332                     }
333                     break;
334
335                 case INFO:
336                     Map<String, String> infoMap = (Map<String, String>) values.get(key);
337
338                     if (infoMap != null) {
339                         if (validate) {
340                             validateTags(exceptionList, (Map<String, Object>) values.get(key),
341                                     OnapCommandConfg.getSchemaAttrInfo(INFO_PARAMS_LIST),
342                                     OnapCommandConfg.getSchemaAttrInfo(INFO_PARAMS_MANDATORY_LIST), INFO);
343
344                             HashMap<String, String> validationMap = new HashMap<>();
345                             validationMap.put(INFO_TYPE, COMMAND_TYPE_VALUES);
346
347                             for (String secKey : validationMap.keySet()) {
348                                 if (infoMap.containsKey(secKey)) {
349                                     Object obj = infoMap.get(secKey);
350                                     if (obj == null) {
351                                         exceptionList.add("Attribute '" + secKey + "' under '" + INFO + "' is empty");
352                                     } else {
353                                         String value = String.valueOf(obj);
354                                         if (!OnapCommandConfg.getSchemaAttrInfo(validationMap.get(secKey)).contains(value)) {
355                                             exceptionList.add("Attribute '" + secKey + "' contains invalid value. Valide values are "
356                                                     + OnapCommandConfg.getSchemaAttrInfo(validationMap.get(key))); //
357                                         }
358                                     }
359                                 }
360                             }
361                         }
362
363                         OnapCommandInfo info = new OnapCommandInfo();
364
365                         for (Map.Entry<String, String> entry1 : infoMap.entrySet()) {
366                             String key1 = entry1.getKey();
367
368                             switch (key1) {
369                                 case INFO_PRODUCT:
370                                     info.setProduct(infoMap.get(key1));
371                                     break;
372
373                                 case INFO_SERVICE:
374                                     info.setService(infoMap.get(key1).toString());
375                                     break;
376
377                                 case INFO_TYPE:
378                                     Object obj = infoMap.get(key1);
379                                     info.setCommandType(CommandType.get(obj.toString()));
380                                     break;
381
382                                 case INFO_AUTHOR:
383                                     Object mode = infoMap.get(key1);
384                                     info.setAuthor(mode.toString());
385                                     break;
386                             }
387                         }
388
389                         cmd.setInfo(info);
390                     }
391                     break;
392
393                 case PARAMETERS:
394
395                     List<Map<String, String>> parameters = (List) values.get(key);
396
397                     if (parameters != null) {
398                         Set<String> names = new HashSet<>();
399
400                         //To support overriding of the parameters, if command is already
401                         //having the same named parameters, means same parameter is
402                         //Overridden from included template into current template
403                         Set<String> existingParamNames =  cmd.getParametersMap().keySet();
404
405                         for (Map<String, String> parameter : parameters) {
406                             boolean isOverriding = false;
407                             OnapCommandParameter param = new OnapCommandParameter();
408
409                             //Override the parameters from its base such as default parameters list
410                             if (existingParamNames.contains(parameter.getOrDefault(NAME, ""))) {
411                                 param = cmd.getParametersMap().get(parameter.getOrDefault(NAME, ""));
412                                 isOverriding = true;
413                             }
414
415                             if (validate) {
416                                 validateTags(exceptionList, parameter, OnapCommandConfg.getSchemaAttrInfo(INPUT_PARAMS_LIST),
417                                         OnapCommandConfg.getSchemaAttrInfo(INPUT_PARAMS_MANDATORY_LIST), PARAMETERS);
418                             }
419
420                             for (Map.Entry<String, String> entry1 : parameter.entrySet()) {
421                                 String key2 = entry1.getKey();
422
423                                 switch (key2) {
424                                     case NAME:
425                                         if (names.contains(parameter.get(key2))) {
426                                             throwOrCollect(new OnapCommandParameterNameConflict(parameter.get(key2)), exceptionList, validate);
427                                         } else {
428                                             names.add(parameter.get(key2));
429                                         }
430
431                                         param.setName(parameter.get(key2));
432                                         break;
433
434                                     case DESCRIPTION:
435                                         param.setDescription(parameter.get(key2));
436                                         break;
437
438                                     case SHORT_OPTION:
439                                         if (shortOptions.contains(parameter.get(key2))) {
440                                             throwOrCollect(new OnapCommandParameterOptionConflict(parameter.get(key2)), exceptionList, validate);
441                                         }
442                                         shortOptions.add(parameter.get(key2));
443                                         param.setShortOption(parameter.get(key2));
444                                         break;
445
446                                     case LONG_OPTION:
447                                         if (longOptions.contains(parameter.get(key2))) {
448                                             throwOrCollect(new OnapCommandParameterOptionConflict(parameter.get(key2)), exceptionList, validate);
449                                         }
450                                         longOptions.add(parameter.get(key2));
451                                         param.setLongOption(parameter.get(key2));
452                                         break;
453
454                                     case DEFAULT_VALUE:
455                                         Object obj = parameter.get(key2);
456                                         param.setDefaultValue(obj.toString());
457                                         break;
458
459                                     case TYPE:
460                                         try {
461                                             param.setParameterType(ParameterType.get(parameter.get(key2)));
462                                         } catch (OnapCommandException ex) {
463                                             throwOrCollect(ex, exceptionList, validate);
464                                         }
465                                         break;
466
467                                     case IS_OPTIONAL:
468                                         if (validate) {
469                                             if (!validateBoolean(String.valueOf(parameter.get(key2)))) {
470                                                 exceptionList.add(invalidBooleanValueMessage(parameter.get(NAME),
471                                                         IS_SECURED, parameter.get(key2)));
472                                             }
473                                         }
474                                         if ("true".equalsIgnoreCase(String.valueOf(parameter.get(key2)))) {
475                                             param.setOptional(true);
476                                         } else {
477                                             param.setOptional(false);
478                                         }
479                                         break;
480
481                                     case IS_SECURED:
482                                         if (validate) {
483                                             if (!validateBoolean(String.valueOf(parameter.get(key2)))) {
484                                                 exceptionList.add(invalidBooleanValueMessage(parameter.get(NAME),
485                                                         IS_SECURED, parameter.get(key2)));
486                                             }
487                                         }
488
489                                         if ("true".equalsIgnoreCase(String.valueOf(parameter.get(key2)))) {
490                                             param.setSecured(true);
491                                         } else {
492                                             param.setSecured(false);
493                                         }
494                                         break;
495
496                                     case IS_INCLUDE:
497                                         if (validate) {
498                                             if (!validateBoolean(String.valueOf(parameter.get(key2)))) {
499                                                 exceptionList.add(invalidBooleanValueMessage(parameter.get(NAME),
500                                                         IS_INCLUDE, parameter.get(key2)));
501                                             }
502                                         }
503
504                                         if ("true".equalsIgnoreCase(String.valueOf(parameter.get(key2)))) {
505                                             param.setInclude(true);
506                                         } else {
507                                             param.setInclude(false);
508                                         }
509                                         break;
510                                 }
511                             }
512
513                             if ( !isOverriding) {
514                                 cmd.getParameters().add(param);
515                             } else {
516                                 cmd.getParametersMap().replace(param.getName(), param);
517                             }
518                         }
519                     }
520                     break;
521
522                 case RESULTS:
523                     Map<String, ?> valueMap = (Map<String, ?>) values.get(key);
524                     if (valueMap != null) {
525                         OnapCommandResult result = new OnapCommandResult();
526                         for (Map.Entry<String, ?> entry1 : valueMap.entrySet()) {
527                             String key3 = entry1.getKey();
528
529                             switch (key3) {
530                                 case DIRECTION:
531                                     try {
532                                         result.setPrintDirection(PrintDirection.get((String) valueMap.get(key3)));
533                                     } catch (OnapCommandException ex) {
534                                         throwOrCollect(ex, exceptionList, validate);
535                                     }
536                                     break;
537
538                                 case ATTRIBUTES:
539                                     List<Map<String, String>> attrs = (ArrayList) valueMap.get(key3);
540
541                                     for (Map<String, String> map : attrs) {
542                                         OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
543                                         if (validate) {
544                                             validateTags(exceptionList, map, OnapCommandConfg.getSchemaAttrInfo(RESULT_PARAMS_LIST),
545                                                     OnapCommandConfg.getSchemaAttrInfo(RESULT_PARAMS_MANDATORY_LIST), ATTRIBUTES);
546                                         }
547
548                                         Set<String> resultParamNames = new HashSet<>();
549
550                                         for (Map.Entry<String, String> entry4 : map.entrySet()) {
551                                             String key4 = entry4.getKey();
552
553                                             switch (key4) {
554                                                 case NAME:
555                                                     if (resultParamNames.contains(map.get(key4))) {
556                                                         exceptionList.add("Attribute name='" + map.get(key4) + "' under '"
557                                                                 + ATTRIBUTES + ":' is already used, Take different one.");
558
559                                                     } else {
560                                                         attr.setName(map.get(key4));
561                                                         resultParamNames.add(map.get(key4));
562                                                     }
563                                                     break;
564
565                                                 case DESCRIPTION:
566                                                     attr.setDescription(map.get(key4));
567                                                     break;
568
569                                                 case SCOPE:
570                                                     try {
571                                                         attr.setScope(OnapCommandResultAttributeScope.get(map.get(key4)));
572                                                     } catch (OnapCommandException ex) {
573                                                         throwOrCollect(ex, exceptionList, validate);
574                                                     }
575                                                     break;
576
577                                                 case TYPE:
578                                                     try {
579                                                         attr.setType(ParameterType.get(map.get(key4)));
580                                                     } catch (OnapCommandException ex) {
581                                                         throwOrCollect(ex, exceptionList, validate);
582                                                     }
583                                                     break;
584
585                                                 case DEFAULT_VALUE:
586                                                     Object obj = map.get(key4);
587                                                     attr.setDefaultValue(obj.toString());
588                                                     break;
589
590                                                 case IS_SECURED:
591                                                     if (validate) {
592                                                         if (!validateBoolean(String.valueOf(map.get(key4)))) {
593                                                             exceptionList.add(invalidBooleanValueMessage(ATTRIBUTES,
594                                                                     IS_SECURED, map.get(key4)));
595                                                         }
596                                                     }
597                                                     if ("true".equals(String.valueOf(map.get(key4)))) {
598                                                         attr.setSecured(true);
599                                                     } else {
600                                                         attr.setSecured(false);
601                                                     }
602                                                     break;
603                                             }
604
605                                         }
606                                         result.getRecords().add(attr);
607                                     }
608                                     break;
609                             }
610                         }
611                         cmd.setResult(result);
612                     }
613                     break;
614             }
615         }
616         return exceptionList;
617     }
618
619     /**
620      * Load the schema.
621      *
622      * @param cmd
623      *            OnapSwaggerBasedCommand
624      * @param schemaName
625      *            schema name
626      * @throws OnapCommandParameterNameConflict
627      *             param name conflict exception
628      * @throws OnapCommandParameterOptionConflict
629      *             param option conflict exception
630      * @throws OnapCommandInvalidParameterType
631      *             invalid param type exception
632      * @throws OnapCommandInvalidPrintDirection
633      *             invalid print direction exception
634      * @throws OnapCommandInvalidResultAttributeScope
635      *             invalid scope exception
636      * @throws OnapCommandSchemaNotFound
637      *             schema not found
638      * @throws OnapCommandInvalidSchema
639      *             invalid schema
640      * @throws OnapCommandInvalidSchemaVersion
641      *             invalid schema version
642      */
643     public static void loadSchema(OnapSwaggerCommand cmd, String schemaName) throws OnapCommandException {
644         try {
645             Map<String, ?> values = (Map<String, ?>) validateSchemaVersion(schemaName, cmd.getSchemaVersion());
646             Map<String, String> valueMap = (Map<String, String>) values.get(EXECUTOR);
647             OnapCommandExecutor exec = new OnapCommandExecutor();
648
649             for (Map.Entry<String, String> entry1 : valueMap.entrySet()) {
650                 String key1 = entry1.getKey();
651
652                 if (API.equals(key1)) {
653                     exec.setApi(valueMap.get(key1));
654                 } else if (CLIENT.equals(key1)) {
655                     exec.setClient(valueMap.get(key1));
656                 } else if (ENTITY.equals(key1)) {
657                     exec.setEntity(valueMap.get(key1));
658                 } else if (EXCEPTION.equals(key1)) {
659                     exec.setException(valueMap.get(key1));
660                 } else if (METHOD.equals(key1)) {
661                     exec.setMethod(valueMap.get(key1));
662                 }
663             }
664
665             cmd.setExecutor(exec);
666         } catch (OnapCommandException e) {
667             throw e;
668         } catch (Exception e) {
669             throw new OnapCommandInvalidSchema(schemaName, e);
670         }
671     }
672
673     /**
674      * Load the schema.
675      *
676      * @param cmd
677      *            OnapHttpCommand
678      * @param schemaName
679      *            schema name
680      * @throws OnapCommandException
681      *             on error
682      */
683     private static ArrayList<String> parseHttpSchema(OnapHttpCommand cmd,
684                                                     final Map<String, ?> values,
685                                                     boolean validate) throws OnapCommandException {
686         ArrayList<String> errorList = new ArrayList<>();
687         try {
688             Map<String, ?> valMap = (Map<String, ?>) values.get(HTTP);
689
690             if (valMap != null) {
691                 if (validate) {
692                     validateTags(errorList, valMap, OnapCommandConfg.getSchemaAttrInfo(HTTP_SECTIONS),
693                             OnapCommandConfg.getSchemaAttrInfo(HTTP_MANDATORY_SECTIONS), PARAMETERS);
694                     errorList.addAll(validateHttpSchemaSection(values));
695                 }
696                 for (Map.Entry<String, ?> entry1 : valMap.entrySet()) {
697                     String key1 = entry1.getKey();
698
699                     switch (key1) {
700                         case REQUEST:
701                             Map<String, ?> map = (Map<String, ?>) valMap.get(key1);
702
703                             for (Map.Entry<String, ?> entry2 : map.entrySet()) {
704                                 try {
705                                     String key2 = entry2.getKey();
706
707                                     switch (key2) {
708                                         case URI:
709                                             Object obj = map.get(key2);
710                                             cmd.getInput().setUri(obj.toString());
711                                             break;
712                                         case METHOD_TYPE:
713                                             Object method = map.get(key2);
714                                             cmd.getInput().setMethod(method.toString());
715                                             break;
716                                         case BODY:
717                                             Object body = map.get(key2);
718                                             cmd.getInput().setBody(body.toString());
719                                             break;
720                                         case HEADERS:
721                                             Map<String, String> head = (Map<String, String>) map.get(key2);
722                                             cmd.getInput().setReqHeaders(head);
723                                             break;
724                                         case QUERIES:
725                                             Map<String, String> query = (Map<String, String>) map.get(key2);
726
727                                             cmd.getInput().setReqQueries(query);
728                                             break;
729                                         case MULTIPART_ENTITY_NAME:
730                                             Object multipartEntityName = map.get(key2);
731                                             cmd.getInput().setMultipartEntityName(multipartEntityName.toString());
732                                             break;
733                                     }
734                                 }catch (Exception ex) {
735                                     throwOrCollect(new OnapCommandInvalidSchema(cmd.getSchemaName(), ex), errorList, validate);
736                                 }
737                             }
738                             break;
739
740                         case SERVICE:
741                             Map<String, String> serviceMap = (Map<String, String>) valMap.get(key1);
742
743                             if (serviceMap != null) {
744                                 if (validate) {
745                                     validateTags(errorList, (Map<String, Object>) valMap.get(key1),
746                                             OnapCommandConfg.getSchemaAttrInfo(SERVICE_PARAMS_LIST),
747                                             OnapCommandConfg.getSchemaAttrInfo(SERVICE_PARAMS_MANDATORY_LIST), SERVICE);
748
749                                     HashMap<String, String> validationMap = new HashMap<>();
750                                     validationMap.put(AUTH, AUTH_VALUES);
751                                     validationMap.put(MODE, MODE_VALUES);
752
753                                     for (String secKey : validationMap.keySet()) {
754                                         if (serviceMap.containsKey(secKey)) {
755                                             Object obj = serviceMap.get(secKey);
756                                             if (obj == null) {
757                                                 errorList.add("Attribute '" + secKey + "' under '" + SERVICE + "' is empty");
758                                             } else {
759                                                 String value = String.valueOf(obj);
760                                                 if (!OnapCommandConfg.getSchemaAttrInfo(validationMap.get(secKey)).contains(value)) {
761                                                     errorList.add("Attribute '" + secKey + "' contains invalid value. Valide values are "
762                                                             + OnapCommandConfg.getSchemaAttrInfo(validationMap.get(key1))); //
763                                                 }
764                                             }
765                                         }
766                                     }
767                                 }
768
769                                 OnapService srv = new OnapService();
770
771                                 for (Map.Entry<String, String> entry : serviceMap.entrySet()) {
772                                     String key = entry.getKey();
773
774                                     switch (key) {
775                                         case NAME:
776                                             srv.setName(serviceMap.get(key));
777                                             break;
778
779                                         case VERSION:
780                                             srv.setVersion(serviceMap.get(key).toString());
781                                             break;
782
783                                         case AUTH:
784                                             Object obj = serviceMap.get(key);
785                                             srv.setAuthType(obj.toString());
786
787                                             //On None type, username, password and no_auth are invalid
788                                             if (srv.isNoAuth()) {
789                                                 cmd.getParametersMap().get(DEAFULT_PARAMETER_USERNAME).setInclude(false);
790                                                 cmd.getParametersMap().get(DEAFULT_PARAMETER_PASSWORD).setInclude(false);
791                                                 cmd.getParametersMap().get(DEFAULT_PARAMETER_NO_AUTH).setInclude(false);
792                                             }
793                                             break;
794
795                                         case MODE:
796                                             Object mode = serviceMap.get(key);
797                                             srv.setMode(mode.toString());
798                                             break;
799                                     }
800                                 }
801                                 cmd.setService(srv);
802                             }
803                             break;
804
805                         case SUCCESS_CODES:
806                             if (validate) {
807                                 validateHttpSccessCodes(errorList, (List<Object>) valMap.get(key1));
808                             }
809                             cmd.setSuccessStatusCodes((ArrayList) valMap.get(key1));
810                             break;
811
812                         case RESULT_MAP:
813                             if (validate) {
814                                 validateHttpResultMap(errorList, values);
815                             }
816                             cmd.setResultMap((Map<String, String>) valMap.get(key1));
817                             break;
818
819                         case SAMPLE_RESPONSE:
820                             // (mrkanag) implement sample response handling
821                             break;
822                     }
823                 }
824             }
825         }catch (OnapCommandException e) {
826             throwOrCollect(e, errorList, validate);
827         }
828         return errorList;
829     }
830
831
832     private static void throwOrCollect(OnapCommandException ex, List<String> list, boolean shouldCollectException)
833             throws OnapCommandException {
834         if (shouldCollectException) {
835             list.add(ex.getMessage());
836         } else {
837             throw ex;
838         }
839     }
840
841     private static void validateTags(List<String> schemaErrors, Map<String, ?> yamlMap, List<String> totalParams,
842             List<String> mandatoryParams, String section) {
843         // mrkanag capture invalid entries as well
844         for (String param : totalParams) {
845             boolean isMandatory = mandatoryParams.contains(param);
846             boolean isYamlContains = yamlMap.containsKey(param);
847             if (isMandatory) {
848                 if (!isYamlContains) {
849                     schemaErrors.add("Mandatory attribute '" + param + "' is missing under '" + section + "'");
850                 } else {
851                     String value = String.valueOf(yamlMap.get(param));
852                     if (value == null || value.isEmpty()) {
853                         schemaErrors.add("Mandatory attribute '" + param + "' under '" + section
854                                 + "' shouldn't be null or empty");
855                     }
856                 }
857             }
858         }
859     }
860
861     /**
862      * Validate Boolean.
863      *
864      * @param toValidate
865      *            string
866      * @return boolean
867      */
868     protected static boolean validateBoolean(String toValidate) {
869         return OnapCommandConfg.getSchemaAttrInfo(BOOLEAN_VALUE).contains(toValidate.toLowerCase());
870     }
871
872     private static String emptySection(String section) {
873         return "The section '" + section + ":' cann't be null or empty";
874     }
875
876     private static String invalidBooleanValueMessage(String section, String attribute, String value) {
877         return "The value '" + value + "' of '" + attribute + "' present under '" + section + "' should be boolean";
878     }
879
880     private static Set<String> validateHttpQueries(Map<String, Object> requestMap) {
881         Map<String, Object> queries = (Map<String, Object>) requestMap.get(QUERIES);
882         Set<String> queryParamNames = new HashSet<>();
883         if (queries != null) {
884             for (Entry<String, Object> entry : queries.entrySet()) {
885                 parseParameters(String.valueOf(entry.getValue()), queryParamNames);
886             }
887         }
888         return queryParamNames;
889     }
890
891
892     private static Set<String> validateHttpHeaders(Map<String, Object> requestMap) {
893
894         Map<String, Object> headers = (Map<String, Object>) requestMap.get(HEADERS);
895         Set<String> headerParamNames = new HashSet<>();
896         if (headers != null) {
897             for (Entry<String, Object> entry : headers.entrySet()) {
898                 parseParameters(String.valueOf(entry.getValue()), headerParamNames);
899             }
900         }
901         return headerParamNames;
902     }
903
904     private static Set<String> validateHttpBody(List<String> errorList, Map<String, Object> requestMap) {
905         Set<String> bodyParamNames = new HashSet<>();
906         Object bodyString = requestMap.get(BODY);
907         if (bodyString == null) {
908             return bodyParamNames;
909         }
910
911         String body = String.valueOf(bodyString);
912         JSONObject obj = null;
913         try {
914             obj = new ObjectMapper().readValue(body, JSONObject.class);
915         } catch (IOException e1) { // NOSONAR
916             errorList.add(HTTP_BODY_FAILED_PARSING);
917         }
918         if (obj == null || "".equals(obj.toString())) {
919             errorList.add(HTTP_BODY_JSON_EMPTY);
920         }
921         parseParameters(body, bodyParamNames);
922
923         return bodyParamNames;
924     }
925
926     private static Set<String> validateHttpUri(List<String> errorList, Map<String, Object> requestMap) {
927         Set<String> uriParamNames = new HashSet<>();
928         String uri = (String) requestMap.get(URI);
929         if (uri == null || uri.isEmpty()) {
930             errorList.add(emptySection(URI));
931             return uriParamNames;
932         }
933         parseParameters(uri, uriParamNames);
934         return uriParamNames;
935     }
936
937     private static void parseParameters(String line, Set<String> paramNames) {
938
939         int currentIdx = 0;
940         while (currentIdx < line.length()) {
941             int idxS = line.indexOf("${", currentIdx);
942             if (idxS == -1) {
943                 break;
944             }
945             int idxE = line.indexOf("}", idxS);
946             String paramName = line.substring(idxS + 2, idxE);
947             paramNames.add(paramName.trim());
948
949             currentIdx = idxE + 1;
950         }
951
952     }
953
954     private static Set<String> getRequestParams(Map<String, ?> yamlMap) {
955
956         Set<String> set = new HashSet<>();
957
958         @SuppressWarnings("unchecked")
959         List<Map<String, Object>> inputParams = (List<Map<String, Object>>) yamlMap.get(PARAMETERS);
960
961         if (inputParams != null) {
962             for (Map<String, Object> map : inputParams) {
963                 for (Entry<String, Object> entry : map.entrySet()) {
964                     Object key = entry.getKey();
965
966                     if (NAME.equals(key)) {
967                         set.add(String.valueOf(entry.getValue()));
968                         break;
969                     }
970                 }
971             }
972         }
973
974         return set;
975     }
976
977     private static void validateHttpResultMap(List<String> errorList, Map<String, ?> values) throws OnapCommandException {
978         Map<String, ?> valMap = (Map<String, ?>) values.get(HTTP);
979         List<Map<String, String>> attributes = (List<Map<String, String>>) ((Map<String, ?>)values.get(RESULTS)).get(ATTRIBUTES);
980         Set<String> resultMapParams = ((Map<String, String>) valMap.get(RESULT_MAP)).keySet();
981
982         Set<String> resultAttNames = attributes.stream().map(map -> map.get(NAME))
983                 .collect(Collectors.toSet());
984
985         List<String> invaliResultMapParams = resultMapParams.stream()
986                 .filter(p -> !resultAttNames.contains(p)).collect(Collectors.toList());
987
988         if (!invaliResultMapParams.isEmpty()) {
989             throwOrCollect(new OnapCommandHttpInvalidResultMap(invaliResultMapParams), errorList, true);
990         }
991     }
992
993     private static void validateHttpSccessCodes(List<String> errorList, List<Object> requestSuccessCodes) {
994
995         if (requestSuccessCodes == null || requestSuccessCodes.isEmpty()) {
996             errorList.add(HTTP_SUCCESS_CODE_INVALID);
997             return;
998         }
999
1000         for (Object successCode : requestSuccessCodes) {
1001             Integer code = (Integer) successCode;
1002             if (code < 200 || code >= 300) {
1003                 if ( code != 404) {
1004                     errorList.add(HTTP_SUCCESS_CODE_INVALID);
1005                 }
1006             }
1007         }
1008
1009     }
1010
1011
1012     private static ArrayList<String> validateHttpSchemaSection(Map<String, ?> values) {
1013
1014         ArrayList<String> errorList = new ArrayList<>();
1015         Map<String, ?> map = (Map<String, ?>) values.get(HTTP);
1016         Map<String, Object> requestMap = (Map<String, Object>) map.get(REQUEST);
1017
1018         if (requestMap != null && !requestMap.isEmpty()) {
1019             validateTags(errorList, requestMap, OnapCommandConfg.getSchemaAttrInfo(HTTP_REQUEST_PARAMS),
1020                     OnapCommandConfg.getSchemaAttrInfo(HTTP_REQUEST_MANDATORY_PARAMS), REQUEST);
1021             String method = (String) requestMap.get(METHOD);
1022             if (method != null && !method.isEmpty()) {
1023                 if (!OnapCommandConfg.getSchemaAttrInfo(HTTP_METHODS).contains(method.toLowerCase())) {
1024                     errorList.add("Attribute '" + METHOD + "' under '" + REQUEST + "' is invalid, correct types are "
1025                             + OnapCommandConfg.getSchemaAttrInfo(HTTP_METHODS).toString());
1026                 }
1027             } else {
1028                 errorList.add("Http request method cann't be null or empty");
1029             }
1030
1031             Set<String> requestParams = getRequestParams(values);
1032
1033             Set<String> uriParams = validateHttpUri(errorList, requestMap);
1034
1035             Set<String> bodyParams = validateHttpBody(errorList, requestMap);
1036
1037             Set<String> headerParams = validateHttpHeaders(requestMap);
1038
1039             Set<String> queryParams = validateHttpQueries(requestMap);
1040
1041             HashSet<String> totoalParams = new HashSet<>(uriParams);
1042             totoalParams.addAll(bodyParams);
1043             totoalParams.addAll(headerParams);
1044             totoalParams.addAll(queryParams);
1045
1046             List<String> nonDeclaredParams = totoalParams.stream().filter(param -> !requestParams.contains(param))
1047                     .collect(Collectors.toList());
1048
1049             nonDeclaredParams.stream().forEach(p -> errorList.add("The parameter '" + p
1050                     + "' declared under 'parameters:' section is not mapped into request section."));
1051         } else {
1052             errorList.add(emptySection(REQUEST));
1053         }
1054         return errorList;
1055     }
1056
1057
1058     /**
1059      * Returns Help.
1060      *
1061      * @param cmd
1062      *            OnapCommand
1063      * @return help string
1064      * @throws OnapCommandHelpFailed
1065      *             help failed exception
1066      */
1067     public static String help(OnapCommand cmd) throws OnapCommandHelpFailed {
1068
1069         String help = "usage: oclip " + cmd.getName();
1070
1071         // Add description
1072         help += "\n\n" + cmd.getDescription();
1073
1074         // Add service
1075         help += "\n\nService: " + cmd.getInfo().getService();
1076
1077         // Add whole command
1078         String commandOptions = "";
1079
1080         // Add parameters
1081         OnapCommandResult paramTable = new OnapCommandResult();
1082         paramTable.setPrintDirection(PrintDirection.LANDSCAPE);
1083         paramTable.setType(ResultType.TABLE);
1084         paramTable.setIncludeTitle(false);
1085         paramTable.setIncludeSeparator(false);
1086
1087         OnapCommandResultAttribute attrName = new OnapCommandResultAttribute();
1088         attrName.setName(NAME);
1089         attrName.setDescription(NAME);
1090         attrName.setScope(OnapCommandResultAttributeScope.SHORT);
1091         paramTable.getRecords().add(attrName);
1092
1093         OnapCommandResultAttribute attrDescription = new OnapCommandResultAttribute();
1094         attrDescription.setName(DESCRIPTION);
1095         attrDescription.setDescription(DESCRIPTION);
1096         attrDescription.setScope(OnapCommandResultAttributeScope.SHORT);
1097         paramTable.getRecords().add(attrDescription);
1098
1099         int newLineOptions = 0;
1100         for (OnapCommandParameter param : cmd.getParameters()) {
1101             if (!param.isInclude()) {
1102                 continue;
1103             }
1104
1105             // First column Option or positional args
1106             String optFirstCol;
1107             if (newLineOptions == 3) {
1108                 newLineOptions = 0;
1109                 commandOptions += "\n";
1110             }
1111
1112             if (param.getShortOption() != null || param.getLongOption() != null) {
1113                 optFirstCol = OnapCommandParameter.printShortOption(param.getShortOption()) + " | "
1114                         + OnapCommandParameter.printLongOption(param.getLongOption());
1115                 commandOptions += " [" + optFirstCol + "]";
1116             } else {
1117                 optFirstCol = param.getName();
1118                 commandOptions += " <" + optFirstCol + ">";
1119             }
1120
1121             newLineOptions++;
1122
1123             attrName.getValues().add(" " + optFirstCol);
1124
1125             // Second column description
1126             String optSecondCol = param.getDescription().trim();
1127             if (!optSecondCol.endsWith(".")) {
1128                 optSecondCol += ".";
1129             }
1130             optSecondCol += " It is of type " + param.getParameterType().name() + ".";
1131
1132             if (param.getParameterType().equals(ParameterType.JSON)
1133                     || param.getParameterType().equals(ParameterType.YAML)) {
1134                 optSecondCol += " It's recommended to input the complete path of the file, which is having the value for it.";
1135             }
1136             if (param.isOptional()) {
1137                 optSecondCol += " It is optional.";
1138             }
1139
1140             String defaultMsg = " By default, it is ";
1141             if (param.isRawDefaultValueAnEnv()) {
1142                 optSecondCol += defaultMsg + "read from environment variable " + param.getEnvVarNameFromrRawDefaultValue()
1143                         + ".";
1144             } else if (param.getDefaultValue() != null && !((String)param.getDefaultValue()).isEmpty()) {
1145                 optSecondCol += defaultMsg + param.getDefaultValue() + ".";
1146             }
1147
1148             if (param.isSecured()) {
1149                 optSecondCol += " Secured.";
1150             }
1151             // (mrkanag) Add help msg for reading default value from env
1152             attrDescription.getValues().add(optSecondCol);
1153         }
1154
1155         try {
1156             help += "\n\nOptions::\n\n" + commandOptions + "\n\nwhere::\n\n" + paramTable.print();
1157         } catch (OnapCommandException e) {
1158             throw new OnapCommandHelpFailed(e);
1159         }
1160
1161         // Add results
1162         OnapCommandResult resultTable = new OnapCommandResult();
1163         resultTable.setPrintDirection(PrintDirection.PORTRAIT);
1164         resultTable.setType(ResultType.TABLE);
1165         resultTable.setIncludeTitle(false);
1166         resultTable.setIncludeSeparator(false);
1167
1168         for (OnapCommandResultAttribute attr : cmd.getResult().getRecords()) {
1169             OnapCommandResultAttribute attrHelp = new OnapCommandResultAttribute();
1170             attrHelp.setName(" " + attr.getName());
1171             attrHelp.setDescription(attr.getDescription());
1172             String msg = attr.getDescription() + " and is of type " + attr.getType().name() + ".";
1173             if (attr.isSecured()) {
1174                 msg += " It is secured.";
1175             }
1176             attrHelp.getValues().add(msg);
1177             attrHelp.setType(attr.getType());
1178             resultTable.getRecords().add(attrHelp);
1179         }
1180
1181         if (cmd.getResult().getRecords().size() > 0) {
1182             try {
1183                 help += "\n\nResults::\n\n" + resultTable.print();
1184             } catch (OnapCommandException e) {
1185                 throw new OnapCommandHelpFailed(e);
1186             }
1187         }
1188
1189         // Error
1190         help += "\n\nError::\n\n On error, it prints <HTTP STATUS CODE>::<ERROR CODE>::<ERROR MESSAGE>\n";
1191         return help;
1192     }
1193
1194     /**
1195      * Create Dict from list of Parameters.
1196      *
1197      * @param inputs
1198      *            list of parameters
1199      * @return map
1200      */
1201     public static Map<String, OnapCommandParameter> getInputMap(List<OnapCommandParameter> inputs) {
1202         Map<String, OnapCommandParameter> map = new HashMap<>();
1203         for (OnapCommandParameter param : inputs) {
1204             map.put(param.getName(), param);
1205         }
1206         return map;
1207     }
1208
1209     /**
1210      * Discover the Oclip commands.
1211      *
1212      * @return list
1213      */
1214     public static List<Class<OnapCommand>> discoverCommandPlugins() {
1215         ServiceLoader<OnapCommand> loader = ServiceLoader.load(OnapCommand.class);
1216         List<Class<OnapCommand>> clss = new ArrayList<>();
1217         for (OnapCommand implClass : loader) {
1218             clss.add((Class<OnapCommand>) implClass.getClass());
1219         }
1220
1221         return clss;
1222     }
1223
1224     /**
1225      * sort the set.
1226      *
1227      * @param col
1228      *            set
1229      * @return list
1230      */
1231     public static List<String> sort(Set<String> col) {
1232         List<String> results = new ArrayList<>();
1233         results.addAll(col);
1234         Collections.sort(results);
1235         return results;
1236     }
1237
1238     /**
1239      * Flatten the json list.
1240      *
1241      * @param jsons
1242      *            list json strings
1243      * @return list
1244      */
1245     public static List<String> jsonFlatten(List<String> jsons) {
1246         List<String> results = new ArrayList<>();
1247         for (String json : jsons) {
1248             try {
1249                 results.add(JsonPath.parse(json).jsonString());
1250             } catch (Exception e) { // NOSONAR
1251                 results.add(json);
1252             }
1253         }
1254
1255         return results;
1256     }
1257
1258     /**
1259      * Construct method name.
1260      *
1261      * @param name
1262      *            name
1263      * @param prefix
1264      *            prefix
1265      * @return string
1266      */
1267     public static String formMethodNameFromAttributeName(String name, String prefix) {
1268         if (name == null || name.isEmpty()) {
1269             return name;
1270         }
1271
1272         String methodName = prefix;
1273         for (String tk : name.split("-")) {
1274             methodName += Character.toString(tk.charAt(0)).toUpperCase();
1275             methodName += tk.substring(1);
1276         }
1277         return methodName;
1278     }
1279
1280     /**
1281      * There are unique values like uuid is supported, so when input, output (default) values has
1282      * these special entries, then it will get replaced with it's value
1283      *
1284      * @param line
1285      * @return
1286      */
1287     public static String replaceLineForSpecialValues(String line) {
1288         String result = "";
1289
1290         if (!line.contains("$s{")) {
1291             return line;
1292         }
1293
1294         int currentIdx = 0;
1295         while (currentIdx < line.length()) {
1296             int idxS = line.indexOf("$s{", currentIdx);
1297             if (idxS == -1) {
1298                 result += line.substring(currentIdx);
1299                 break;
1300             }
1301             int idxE = line.indexOf("}", idxS);
1302             String splEntry = line.substring(idxS + 3, idxE);
1303             splEntry = splEntry.trim();
1304
1305             String value = "";
1306
1307             switch (splEntry) {
1308                 case Constants.SPL_ENTRY_UUID:
1309                     value = UUID.randomUUID().toString();
1310                     break;
1311
1312                 default:
1313
1314                     if (splEntry.startsWith(Constants.SPL_ENTRY_ENV)) {
1315                         //start to read after env:ENV_VAR_NAME
1316                         String envVarName = splEntry.substring(4);
1317                         value = System.getenv(envVarName);
1318                         if (value == null) {
1319                             //when env is not defined, assign the same env:ENV_VAR_NAME
1320                             //so that it will given hit to user that ENV_VAR_NAME to be
1321                             //defined.
1322                             value = splEntry;
1323                         }
1324                     } else {
1325                         value = splEntry;
1326                     }
1327             }
1328
1329             result += line.substring(currentIdx, idxS) + value;
1330             currentIdx = idxE + 1;
1331         }
1332
1333         return result;
1334     }
1335
1336     public static String replaceLineFromInputParameters(String line, Map<String, OnapCommandParameter> params)
1337             throws OnapCommandException {
1338         String result = "";
1339
1340         if (!line.contains("${")) {
1341             return line;
1342         }
1343
1344         int currentIdx = 0;
1345         while (currentIdx < line.length()) {
1346             int idxS = line.indexOf("${", currentIdx);
1347             if (idxS == -1) {
1348                 result += line.substring(currentIdx);
1349                 break;
1350             }
1351             int idxE = line.indexOf("}", idxS);
1352             String paramName = line.substring(idxS + 2, idxE);
1353             paramName = paramName.trim();
1354             if (!params.containsKey(paramName)) {
1355                 throw new OnapCommandParameterNotFound(paramName);
1356             }
1357
1358             String value = params.get(paramName).getValue().toString();
1359
1360             OnapCommandParameter param = params.get(paramName);
1361             if (ParameterType.ARRAY.equals(param.getParameterType())
1362                     || ParameterType.MAP.equals(param.getParameterType())
1363                     || ParameterType.JSON.equals(param.getParameterType())
1364                     || ParameterType.YAML.equals(param.getParameterType())) {
1365                 // ignore the front and back double quotes in json body
1366                 result += line.substring(currentIdx, idxS - 1) + value;
1367                 currentIdx = idxE + 2;
1368             } else {
1369                 result += line.substring(currentIdx, idxS) + value;
1370                 currentIdx = idxE + 1;
1371             }
1372         }
1373
1374         return result;
1375     }
1376
1377     private static ArrayList<String> replaceLineFromOutputResults(String line, HttpResult resultHttp)
1378             throws OnapCommandHttpHeaderNotFound, OnapCommandHttpInvalidResponseBody,
1379             OnapCommandResultMapProcessingFailed, OnapCommandResultEmpty {
1380         String headerProcessedLine = "";
1381
1382         ArrayList<String> result = new ArrayList<>();
1383         if (!line.contains("$b{") && !line.contains("$h{")) {
1384             result.add(line);
1385             return result;
1386         }
1387
1388         /**
1389          * In case of empty response body [] or {}
1390          **/
1391         if (resultHttp.getBody().length() <= 2) {
1392             return result;
1393         }
1394
1395         /**
1396          * Process headers macros : line: $h{abc}-$b{$.[*].xyz} , After processing line will be [abc's
1397          * value]-$b{$.[*].xyz}
1398          **/
1399         int currentIdx = 0;
1400         while (currentIdx < line.length()) {
1401             int idxS = line.indexOf("$h{", currentIdx);
1402             if (idxS == -1) {
1403                 headerProcessedLine += line.substring(currentIdx);
1404                 break;
1405             }
1406             int idxE = line.indexOf("}", idxS);
1407             String headerName = line.substring(idxS + 3, idxE);
1408             headerName = headerName.trim();
1409             if (!resultHttp.getRespHeaders().containsKey(headerName)) {
1410                 throw new OnapCommandHttpHeaderNotFound(headerName);
1411             }
1412             String value = resultHttp.getRespHeaders().get(headerName);
1413
1414             headerProcessedLine += line.substring(currentIdx, idxS) + value;
1415             currentIdx = idxE + 1;
1416         }
1417
1418         // Process body jsonpath macros
1419         List<Object> values = new ArrayList<>();
1420         String bodyProcessedPattern = "";
1421         currentIdx = 0;
1422         int maxRows = 1; // in normal case, only one row will be there
1423         while (currentIdx < headerProcessedLine.length()) {
1424             int idxS = headerProcessedLine.indexOf("$b{", currentIdx);
1425             if (idxS == -1) {
1426                 bodyProcessedPattern += headerProcessedLine.substring(currentIdx);
1427                 break;
1428             }
1429             int idxE = headerProcessedLine.indexOf("}", idxS);
1430             String jsonPath = headerProcessedLine.substring(idxS + 3, idxE);
1431             jsonPath = jsonPath.trim();
1432             try {
1433                 // JSONArray or String
1434                 Object value = JsonPath.read(resultHttp.getBody(), jsonPath);
1435                 if (value instanceof JSONArray) {
1436                     JSONArray arr = (JSONArray) value;
1437                     if (arr.size() > maxRows) {
1438                         maxRows = arr.size();
1439                     }
1440                 }
1441                 bodyProcessedPattern += headerProcessedLine.substring(currentIdx, idxS) + "%s";
1442                 values.add(value);
1443                 currentIdx = idxE + 1;
1444             } catch (Exception e) {
1445                 throw new OnapCommandHttpInvalidResponseBody(jsonPath, e);
1446             }
1447         }
1448
1449         if (bodyProcessedPattern.isEmpty()) {
1450             result.add(headerProcessedLine);
1451             return result;
1452         } else {
1453             for (int i = 0; i < maxRows; i++) {
1454                 currentIdx = 0;
1455                 String bodyProcessedLine = "";
1456                 int positionalIdx = 0; // %s positional idx
1457                 while (currentIdx < bodyProcessedPattern.length()) {
1458                     int idxS = bodyProcessedPattern.indexOf("%s", currentIdx);
1459                     if (idxS == -1) {
1460                         bodyProcessedLine += bodyProcessedPattern.substring(currentIdx);
1461                         break;
1462                     }
1463                     int idxE = idxS + 2; // %s
1464                     try {
1465                         Object value = values.get(positionalIdx);
1466                         String valueS = String.valueOf(value);
1467                         if (value instanceof JSONArray) {
1468                             JSONArray arr = (JSONArray) value;
1469                             if (!arr.isEmpty()) {
1470                                 valueS = arr.get(i).toString();
1471                             } else {
1472                                 throw new OnapCommandResultEmpty();
1473                             }
1474                         }
1475
1476                         bodyProcessedLine += bodyProcessedPattern.substring(currentIdx, idxS) + valueS;
1477                         currentIdx = idxE;
1478                         positionalIdx++;
1479                     } catch (OnapCommandResultEmpty e) {
1480                         throw e;
1481                     } catch (Exception e) {
1482                         throw new OnapCommandResultMapProcessingFailed(line, e);
1483                     }
1484                 }
1485                 result.add(bodyProcessedLine);
1486             }
1487
1488             return result;
1489         }
1490     }
1491
1492     /**
1493      * Set argument to param value.
1494      *
1495      * @param params
1496      *            map
1497      * @param input
1498      *            HttpInput
1499      * @return HttpInput
1500      * @throws OnapCommandParameterNotFound
1501      *             exception
1502      * @throws OnapCommandInvalidParameterValue
1503      *             exception
1504      */
1505     public static HttpInput populateParameters(Map<String, OnapCommandParameter> params, HttpInput input)
1506             throws OnapCommandException {
1507         HttpInput inp = new HttpInput();
1508         for (OnapCommandParameter param : params.values()) {
1509             if (ParameterType.BINARY.equals(param.getParameterType())) {
1510                 inp.setBinaryData(true);
1511                 break;
1512             }
1513         }
1514         inp.setBody(replaceLineFromInputParameters(input.getBody(), params));
1515         inp.setUri(replaceLineFromInputParameters(input.getUri(), params));
1516         inp.setMethod(input.getMethod().toLowerCase());
1517         for (String h : input.getReqHeaders().keySet()) {
1518             String value = input.getReqHeaders().get(h);
1519             inp.getReqHeaders().put(h, replaceLineFromInputParameters(value, params));
1520         }
1521
1522         for (String h : input.getReqQueries().keySet()) {
1523             String value = input.getReqQueries().get(h);
1524             inp.getReqQueries().put(h, replaceLineFromInputParameters(value, params));
1525         }
1526
1527         return inp;
1528     }
1529
1530     /**
1531      * Populate result.
1532      *
1533      * @param resultMap
1534      *            map
1535      * @param resultHttp
1536      *            HttpResult
1537      * @return map
1538      * @throws OnapCommandHttpHeaderNotFound
1539      *             header not found exception
1540      * @throws OnapCommandHttpInvalidResponseBody
1541      *             invalid response body exception
1542      * @throws OnapCommandResultMapProcessingFailed
1543      *             map processing failed exception
1544      */
1545     public static Map<String, ArrayList<String>> populateOutputs(Map<String, String> resultMap, HttpResult resultHttp)
1546             throws OnapCommandException {
1547         Map<String, ArrayList<String>> resultsProcessed = new HashMap<>();
1548
1549         for (Entry<String, String> entry : resultMap.entrySet()) {
1550             String key = entry.getKey();
1551             try {
1552                 resultsProcessed.put(key, replaceLineFromOutputResults(resultMap.get(key), resultHttp));
1553             } catch(OnapCommandResultEmpty e) {
1554                 // pass // NOSONAR
1555             }
1556         }
1557
1558         return resultsProcessed;
1559     }
1560
1561     /**
1562      * Populate result from input parameters.
1563      *
1564      * @param resultMap
1565      *            map
1566      * @param params
1567      *            Map<String, OnapCommandParameter>
1568      * @return map
1569      * @throws OnapCommandHttpHeaderNotFound
1570      *             header not found exception
1571      * @throws OnapCommandHttpInvalidResponseBody
1572      *             invalid response body exception
1573      * @throws OnapCommandResultMapProcessingFailed
1574      *             map processing failed exception
1575      */
1576     public static Map<String, ArrayList<String>> populateOutputsFromInputParameters(
1577             Map<String, ArrayList<String>> resultMap,
1578             Map<String, OnapCommandParameter> params)
1579             throws OnapCommandException {
1580         Map<String, ArrayList<String>> resultsProcessed = new HashMap<>();
1581
1582         for (Entry<String, ArrayList<String>> entry : resultMap.entrySet()) {
1583             String key = entry.getKey();
1584             resultsProcessed.put(key, new ArrayList<>());
1585             for (String value: entry.getValue()) {
1586                 try {
1587                     value = replaceLineFromInputParameters(value, params);
1588                 } catch(OnapCommandResultEmpty e) {
1589                     // pass // NOSONAR
1590                 }
1591                 resultsProcessed.get(key).add(value);
1592             }
1593         }
1594
1595         return resultsProcessed;
1596     }
1597
1598     /**
1599      * Find external schema files.
1600      *
1601      * @return list ExternalSchema
1602      * @throws OnapCommandDiscoveryFailed
1603      *             exception
1604      * @throws OnapCommandInvalidSchema
1605      *             exception
1606      */
1607     public static List<SchemaInfo> discoverSchemas() throws OnapCommandException {
1608         List<SchemaInfo> extSchemas = new ArrayList<>();
1609         try {
1610             Resource[] res = findResources(SCHEMA_PATH_PATERN);
1611             if (res != null && res.length > 0) {
1612                 Map<String, ?> resourceMap;
1613
1614                 for (Resource resource : res) {
1615                     try {
1616                         resourceMap = loadSchema(resource);
1617                     } catch (OnapCommandException e) {
1618                         LOG.error("Invalid schema " + resource.getURI().toString(), e);
1619                         continue;
1620                     }
1621
1622                     if (resourceMap != null && resourceMap.size() > 0) {
1623                         SchemaInfo schema = new SchemaInfo();
1624
1625                         schema.setSchemaURI(resource.getURI().toString());
1626
1627                         Object obj = resourceMap.get(OPEN_CLI_SCHEMA_VERSION);
1628                         schema.setVersion(obj.toString());
1629
1630                         if (!schema.getVersion().equalsIgnoreCase(Constants.OPEN_CLI_SCHEMA_VERSION_VALUE_1_0)) {
1631                             LOG.info("Unsupported Schema version found " + schema.getSchemaURI());
1632                             continue;
1633                         }
1634
1635                         schema.setSchemaName(resource.getFilename());
1636                         schema.setCmdName((String) resourceMap.get(NAME));
1637
1638                         Map<String, ?> infoMap = (Map<String, ?>) resourceMap.get(Constants.INFO);
1639                         if (infoMap != null && infoMap.get(Constants.INFO_TYPE) != null) {
1640                             schema.setType(infoMap.get(Constants.INFO_TYPE).toString());
1641                         }
1642
1643                         if (infoMap != null && infoMap.get(Constants.INFO_PRODUCT) != null) {
1644                             schema.setProduct(infoMap.get(Constants.INFO_PRODUCT).toString());
1645                         }
1646
1647                         schema.setSchemaProfile(identitySchemaProfileType(resourceMap));
1648
1649                         extSchemas.add(schema);
1650                     }
1651                 }
1652             }
1653         } catch (IOException e) {
1654             throw new OnapCommandDiscoveryFailed(SCHEMA_DIRECTORY, e);
1655         }
1656
1657         return extSchemas;
1658     }
1659
1660     private static String identitySchemaProfileType(Map<String, ?> schemaYamlMap) {
1661         if (schemaYamlMap.get(Constants.HTTP) != null) {
1662             return Constants.HTTP_SCHEMA_PROFILE;
1663         }
1664
1665         return Constants.BASIC_SCHEMA_PROFILE;
1666     }
1667
1668     /**
1669      * Returns all resources available under certain directory in class-path.
1670      *
1671      * @param pattern
1672      *            search pattern
1673      * @return resources found resources
1674      * @throws IOException
1675      *             exception
1676      */
1677     public static Resource[] findResources(String pattern) throws IOException {
1678         ClassLoader cl = OnapCommandUtils.class.getClassLoader();
1679         ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
1680         return resolver.getResources("classpath*:" + pattern);
1681     }
1682
1683     /**
1684      * Returns a resource available under certain directory in class-path.
1685      *
1686      * @param pattern
1687      *            search pattern
1688      * @return found resource
1689      * @throws IOException
1690      *             exception
1691      */
1692     public static Resource findResource(String fileName, String pattern) throws IOException {
1693         Resource[] resources = findResources(pattern);
1694         if (resources != null && resources.length > 0) {
1695             for (Resource res : resources) {
1696                 if (res.getFilename().equals(fileName)) {
1697                     return res;
1698                 }
1699             }
1700         }
1701
1702         return null;
1703     }
1704
1705     /**
1706      * Get schema map.
1707      *
1708      * @param resource
1709      *            resource obj
1710      * @return map
1711      * @throws OnapCommandInvalidSchema
1712      *             exception
1713      */
1714     public static Map<String, ?> loadSchema(Resource resource) throws OnapCommandInvalidSchema {
1715         Map<String, ?> values = null;
1716         try {
1717             values = (Map<String, ?>) new Yaml().load(resource.getInputStream());
1718         } catch (Exception e) {
1719             throw new OnapCommandInvalidSchema(resource.getFilename(), e);
1720         }
1721         return values;
1722     }
1723
1724     /**
1725      * Persist the external schema details.
1726      *
1727      * @param schemas
1728      *            list
1729      * @throws OnapCommandDiscoveryFailed
1730      *             exception
1731      */
1732     public static void persistSchemaInfo(List<SchemaInfo> schemas) throws OnapCommandDiscoveryFailed {
1733         if (schemas != null) {
1734             try {
1735                 Resource[] resources = findResources(DATA_DIRECTORY);
1736                 if (resources != null && resources.length == 1) {
1737                     String path = resources[0].getURI().getPath();
1738                     File file = new File(path + File.separator + DISCOVERY_FILE);
1739                     ObjectMapper mapper = new ObjectMapper();
1740                     mapper.writerWithDefaultPrettyPrinter().writeValue(file, schemas);
1741                 }
1742             } catch (IOException e1) {
1743                 throw new OnapCommandDiscoveryFailed(DATA_DIRECTORY,
1744                         DISCOVERY_FILE, e1);
1745             }
1746         }
1747     }
1748
1749     public static void persistProfile(List<Param> params, String profileName) throws OnapCommandPersistProfileFailed {
1750         if (params != null) {
1751             try {
1752                 Resource[] resources = findResources(DATA_DIRECTORY);
1753                 if (resources != null && resources.length == 1) {
1754                     String path = resources[0].getURI().getPath();
1755                     File file = new File(path + File.separator + profileName + ".json");
1756                     ObjectMapper mapper = new ObjectMapper();
1757                     mapper.writerWithDefaultPrettyPrinter().writeValue(file, params);
1758                 }
1759             } catch (IOException e1) {
1760                 throw new OnapCommandPersistProfileFailed(e1);
1761             }
1762         }
1763     }
1764
1765     /**
1766      * Check if json file discovered or not.
1767      *
1768      * @return boolean
1769      * @throws OnapCommandDiscoveryFailed
1770      *             exception
1771      */
1772     public static boolean isAlreadyDiscovered() throws OnapCommandDiscoveryFailed {
1773         Resource resource = null;
1774         try {
1775             resource = findResource(DISCOVERY_FILE,
1776                     DATA_PATH_JSON_PATTERN);
1777             if (resource != null) {
1778                 return true;
1779             }
1780         } catch (IOException e) {
1781             throw new OnapCommandDiscoveryFailed(DATA_DIRECTORY,
1782                     DISCOVERY_FILE, e);
1783         }
1784
1785         return false;
1786     }
1787
1788     /**
1789      * Load the previous discovered json file.
1790      *
1791      * @return list
1792      * @throws OnapCommandInvalidSchema
1793      *             exception
1794      * @throws OnapCommandDiscoveryFailed
1795      *             exception
1796      */
1797     public static List<SchemaInfo> discoverOrLoadSchemas() throws OnapCommandException {
1798         List<SchemaInfo> schemas = new ArrayList<>();
1799         if (OnapCommandConfg.isDiscoverAlways() || !isAlreadyDiscovered()) {
1800             schemas = discoverSchemas();
1801             if (!schemas.isEmpty()) {
1802                 persistSchemaInfo(schemas);
1803             }
1804         } else {
1805             try {
1806                 Resource resource = findResource(DISCOVERY_FILE,
1807                         DATA_PATH_JSON_PATTERN);
1808                 if (resource != null) {
1809                     File file = new File(resource.getURI().getPath());
1810                     ObjectMapper mapper = new ObjectMapper();
1811                     SchemaInfo[] list = mapper.readValue(file, SchemaInfo[].class);
1812                     schemas.addAll(Arrays.asList(list));
1813                 }
1814             } catch (IOException e) {
1815                 throw new OnapCommandDiscoveryFailed(DATA_DIRECTORY,
1816                         DISCOVERY_FILE, e);
1817             }
1818         }
1819
1820         return schemas;
1821     }
1822
1823     public static List<Param> loadParamFromCache(String profileName) throws OnapCommandLoadProfileFailed {
1824         List<Param> params = new ArrayList<>();
1825
1826         try {
1827             Resource resource = findResource(profileName + ".json",
1828                     DATA_PATH_JSON_PATTERN);
1829             if (resource != null) {
1830                 File file = new File(resource.getURI().getPath());
1831                 ObjectMapper mapper = new ObjectMapper();
1832                 Param[] list = mapper.readValue(file, Param[].class);
1833                 params.addAll(Arrays.asList(list));
1834             }
1835         } catch (IOException e) {
1836             throw new OnapCommandLoadProfileFailed(e);
1837         }
1838
1839         return params;
1840     }
1841
1842     /**
1843      * Fetch a particular schema details.
1844      *
1845      * @param cmd
1846      *            command name
1847      * @return ExternalSchema obj
1848      * @throws OnapCommandInvalidSchema
1849      *             exception
1850      * @throws OnapCommandDiscoveryFailed
1851      *             exception
1852      */
1853     public static SchemaInfo getSchemaInfo(String cmd, String version) throws OnapCommandException {
1854         List<SchemaInfo> list = discoverOrLoadSchemas();
1855         SchemaInfo schemaStr = null;
1856         if (list != null) {
1857             for (SchemaInfo schema : list) {
1858                 if (cmd.equals(schema.getCmdName()) && version.equals(schema.getProduct())) {
1859                     schemaStr = schema;
1860                     break;
1861                 }
1862             }
1863         }
1864         return schemaStr;
1865     }
1866
1867     /**
1868      * Copy the parameters across the commands, mainly used for catalog, login and logout commands
1869      *
1870      * @throws OnapCommandInvalidParameterValue
1871      */
1872     public static void copyParamsFrom(OnapHttpCommand from, OnapCommand to) throws OnapCommandInvalidParameterValue {
1873         for (OnapCommandParameter param: to.getParameters()) {
1874
1875             OnapCommandParameter fromParam = from.getParametersMap().get(param.getName());
1876
1877             if (fromParam != null) {
1878                 param.setValue(fromParam.getValue());
1879                 param.setDefaultValue(fromParam.getDefaultValue());
1880             } else if (param.getName().equalsIgnoreCase(Constants.CATALOG_SERVICE_NAME)) { // for catalog cmd
1881                 param.setValue(from.getService().getName());
1882             } else if (param.getName().equalsIgnoreCase(Constants.CATALOG_SERVICE_VERSION)) {  // for catalog cmd
1883                 param.setValue(from.getService().getVersion());
1884             }
1885         }
1886     }
1887
1888     /**
1889      * Returns the build time from manifest.mf
1890      */
1891     public static String findLastBuildTime() {
1892         String impBuildDate = "";
1893         try
1894         {
1895             String path = OnapCommandUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath();
1896             JarFile jar = new JarFile(path);
1897             Manifest manifest = jar.getManifest();
1898             jar.close();
1899
1900             Attributes attributes = manifest.getMainAttributes();
1901
1902             impBuildDate = attributes.getValue("Build-Time");
1903         }
1904         catch (IOException e)
1905         {
1906             //Ignore it as it will never occur
1907         }
1908
1909         return impBuildDate;
1910     }
1911 }
1912