2 * Copyright 2017 Huawei Technologies Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.onap.cli.fw.utils;
19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import com.jayway.jsonpath.JsonPath;
21 import net.minidev.json.JSONArray;
22 import org.onap.cli.fw.OnapCommand;
23 import org.onap.cli.fw.ad.OnapCredentials;
24 import org.onap.cli.fw.ad.OnapService;
25 import org.onap.cli.fw.cmd.OnapHttpCommand;
26 import org.onap.cli.fw.cmd.OnapSwaggerCommand;
27 import org.onap.cli.fw.conf.Constants;
28 import org.onap.cli.fw.conf.OnapCommandConfg;
29 import org.onap.cli.fw.error.OnapCommandDiscoveryFailed;
30 import org.onap.cli.fw.error.OnapCommandException;
31 import org.onap.cli.fw.error.OnapCommandHelpFailed;
32 import org.onap.cli.fw.error.OnapCommandHttpHeaderNotFound;
33 import org.onap.cli.fw.error.OnapCommandHttpInvalidResponseBody;
34 import org.onap.cli.fw.error.OnapCommandInvalidDefaultParameter;
35 import org.onap.cli.fw.error.OnapCommandInvalidParameterType;
36 import org.onap.cli.fw.error.OnapCommandInvalidParameterValue;
37 import org.onap.cli.fw.error.OnapCommandInvalidPrintDirection;
38 import org.onap.cli.fw.error.OnapCommandInvalidResultAttributeScope;
39 import org.onap.cli.fw.error.OnapCommandInvalidSchema;
40 import org.onap.cli.fw.error.OnapCommandInvalidSchemaVersion;
41 import org.onap.cli.fw.error.OnapCommandParameterNameConflict;
42 import org.onap.cli.fw.error.OnapCommandParameterNotFound;
43 import org.onap.cli.fw.error.OnapCommandParameterOptionConflict;
44 import org.onap.cli.fw.error.OnapCommandResultEmpty;
45 import org.onap.cli.fw.error.OnapCommandResultMapProcessingFailed;
46 import org.onap.cli.fw.error.OnapCommandSchemaNotFound;
47 import org.onap.cli.fw.http.HttpInput;
48 import org.onap.cli.fw.http.HttpResult;
49 import org.onap.cli.fw.input.OnapCommandParameter;
50 import org.onap.cli.fw.input.ParameterType;
51 import org.onap.cli.fw.output.OnapCommandResult;
52 import org.onap.cli.fw.output.OnapCommandResultAttribute;
53 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
54 import org.onap.cli.fw.output.PrintDirection;
55 import org.onap.cli.fw.output.ResultType;
56 import org.onap.cli.fw.run.OnapCommandExecutor;
57 import org.springframework.core.io.Resource;
58 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
59 import org.springframework.core.io.support.ResourcePatternResolver;
60 import org.yaml.snakeyaml.Yaml;
63 import java.io.IOException;
64 import java.io.InputStream;
65 import java.util.ArrayList;
66 import java.util.Arrays;
67 import java.util.Collections;
68 import java.util.HashMap;
69 import java.util.HashSet;
70 import java.util.List;
72 import java.util.Map.Entry;
73 import java.util.ServiceLoader;
75 import java.util.stream.Collectors;
76 import java.util.stream.Stream;
79 * Provides helper method to parse Yaml files and produce required objects.
82 public class OnapCommandUtils {
85 * Private constructor.
87 private OnapCommandUtils() {
92 * Validates schema version.
94 * @param schemaName schema name
95 * @param version schema version
97 * @throws OnapCommandInvalidSchemaVersion invalid schema version exception
98 * @throws OnapCommandInvalidSchema invalid schema
99 * @throws OnapCommandSchemaNotFound schema not found
101 public static Map<String, ?> validateSchemaVersion(String schemaName, String version) throws OnapCommandException {
102 InputStream inputStream = OnapCommandUtils.class.getClassLoader().getResourceAsStream(schemaName);
105 Resource resource = getExternalResource(schemaName, Constants.EXTERNAL_SCHEMA_PATH_PATERN);
107 if (resource != null) {
108 inputStream = resource.getInputStream();
111 } catch (IOException e) {
112 throw new OnapCommandSchemaNotFound(schemaName, e);
114 if (inputStream == null) {
115 throw new OnapCommandSchemaNotFound(schemaName);
118 Map<String, ?> values = null;
120 values = (Map<String, ?>) new Yaml().load(inputStream);
121 } catch (Exception e) {
122 throw new OnapCommandInvalidSchema(schemaName, e);
124 String schemaVersion = "";
125 if (values.keySet().contains(Constants.ONAP_CMD_SCHEMA_VERSION)) {
126 Object obj = values.get(Constants.ONAP_CMD_SCHEMA_VERSION);
127 schemaVersion = obj.toString();
130 if (!version.equals(schemaVersion)) {
131 throw new OnapCommandInvalidSchemaVersion(schemaVersion);
138 * Retrieve OnapCommand from schema.
140 * @param cmd OnapCommand
141 * @param schemaName schema name
142 * @param includeDefault include if default
143 * @throws OnapCommandParameterNameConflict param name conflict exception
144 * @throws OnapCommandParameterOptionConflict param option conflict exception
145 * @throws OnapCommandInvalidParameterType invalid param type exception
146 * @throws OnapCommandInvalidPrintDirection invalid print direction exception
147 * @throws OnapCommandInvalidResultAttributeScope invalid scope exception
148 * @throws OnapCommandSchemaNotFound schema not found
149 * @throws OnapCommandInvalidSchema invalid schema
150 * @throws OnapCommandInvalidSchemaVersion invalid schema version
152 public static void loadSchema(OnapCommand cmd, String schemaName, boolean includeDefault)
153 throws OnapCommandException {
155 Map<String, ?> defaultParameterMap = includeDefault ?
156 validateSchemaVersion(Constants.DEFAULT_PARAMETER_FILE_NAME, cmd.getSchemaVersion()) : new HashMap<>();
157 Map<String, List<Map<String, String>>> commandYamlMap = (Map<String, List<Map<String, String>>>)validateSchemaVersion(schemaName, cmd.getSchemaVersion());
159 List<String> defParams = new ArrayList<>();
161 if (includeDefault) {
162 if (commandYamlMap.get(Constants.PARAMETERS) == null) {
163 commandYamlMap.put(Constants.PARAMETERS, (List<Map<String, String>>) defaultParameterMap.get(Constants.PARAMETERS));
165 commandYamlMap.get(Constants.PARAMETERS).addAll((List<Map<String, String>>) defaultParameterMap.get(Constants.PARAMETERS));
167 defParams = ((List<Map<String, String>>) defaultParameterMap.get(Constants.PARAMETERS)).stream()
168 .map(p -> p.get(Constants.NAME)).collect(Collectors.toList());
171 parseSchema(cmd, commandYamlMap, defParams);
172 } catch (OnapCommandException e) {
174 } catch (Exception e) {
175 throw new OnapCommandInvalidSchema(schemaName, e);
179 private static void processNoAuth(Set<String> parameterSet, final OnapCommand cmd, final List<String> includeParams,
180 final List<String> excludeParams) throws OnapCommandInvalidDefaultParameter {
181 // processing for no-auth type
182 if (cmd.getService() != null) {
183 List<String> includeAuthParams = new ArrayList();
184 List<String> excludeAuthParams = new ArrayList<>();
185 boolean noAuth = cmd.getService().isNoAuth();
187 if (cmd.isCommandInternal()) {
188 excludeAuthParams.addAll(OnapCommandConfg.getExcludeParamsForInternalCmd());
191 includeAuthParams.addAll(OnapCommandConfg.getIncludeParamsForNoAuthEnableExternalCmd());
192 excludeAuthParams.addAll(OnapCommandConfg.getExcludeParamsForNoAuthEnableExternalCmd());
194 includeAuthParams.addAll(OnapCommandConfg.getIncludeParamsForNoAuthDisableExternalCmd());
198 List<String> invalidExclude = excludeAuthParams.stream().filter(includeParams::contains)
199 .collect(Collectors.toList());
201 List<String> invalidInclude = includeAuthParams.stream().filter(excludeParams::contains)
202 .filter(p->!includeParams.contains(p)).collect(Collectors.toList());
204 if (!invalidExclude.isEmpty() || !invalidInclude.isEmpty()) {
205 throw new OnapCommandInvalidDefaultParameter(Stream.concat(invalidExclude.stream(), invalidInclude.stream())
206 .collect(Collectors.toList()));
210 parameterSet.addAll(includeAuthParams);
211 parameterSet.removeAll(excludeAuthParams);
215 private static void parseSchema(OnapCommand cmd,
216 final Map<String, ?> values,
217 final List<String> defaultParamNames) throws OnapCommandException {
219 List<String> shortOptions = new ArrayList<>();
220 List<String> longOptions = new ArrayList<>();
221 List<String> names = new ArrayList<>();
222 Set<String> filteredDefaultParams = new HashSet<>();
224 List<String> sections = Arrays.asList(Constants.NAME, Constants.DESCRIPTION, Constants.SERVICE,
225 Constants.DEFAULT_PARAMETERS, Constants.PARAMETERS, Constants.RESULTS);
227 for (String key : sections) {
229 if (Constants.NAME.equals(key)) {
230 Object val = values.get(key);
232 cmd.setName(val.toString());
234 } else if (Constants.DESCRIPTION.equals(key)) {
235 Object val = values.get(key);
237 cmd.setDescription(val.toString());
239 } else if (Constants.SERVICE.equals(key)) {
240 Map<String, String> map = (Map<String, String>) values.get(key);
242 OnapService srv = new OnapService();
244 for (Map.Entry<String, String> entry1 : map.entrySet()) {
245 String key1 = entry1.getKey();
247 if (Constants.NAME.equals(key1)) {
248 srv.setName(map.get(key1));
249 } else if (Constants.VERSION.equals(key1)) {
250 srv.setVersion(map.get(key1));
251 } else if (Constants.AUTH.equals(key1)) {
252 Object obj = map.get(key1);
253 //TODO mrkanag Validate and raise exception for invalid case
254 srv.setAuthType(obj.toString());
255 } else if (Constants.MODE.equals(key1)) {
256 Object obj = map.get(key1);
257 //TODO mrkanag Validate and raise exception for invalid case
258 srv.setMode(obj.toString());
264 } else if (Constants.DEFAULT_PARAMETERS.equals(key)) {
266 Map<String, List<String>> defParameters = (Map) values.get(Constants.DEFAULT_PARAMETERS);
267 List<String> includeParams = new ArrayList<>();
268 List<String> excludeParams = new ArrayList<>();
270 if (values.containsKey(Constants.DEFAULT_PARAMETERS) && defParameters == null) {
271 // if default parameter section is available then it must have either include
272 // or exclude sub-section.
273 throw new OnapCommandInvalidSchema(Constants.SCHEMA_INVALID_DEFAULT_PARAMS_SECTION);
277 if (defParameters != null) {
278 // validate default parameters
279 if (defParameters.containsKey(Constants.DEFAULT_PARAMETERS_INCLUDE)) {
280 includeParams = defParameters.get(Constants.DEFAULT_PARAMETERS_INCLUDE);
283 List<String> invInclude = includeParams.stream()
284 .filter(p -> !defaultParamNames.contains(p))
285 .collect(Collectors.toList());
287 if (defParameters.containsKey(Constants.DEFAULT_PARAMETERS_EXCLUDE)) {
288 excludeParams = defParameters.get(Constants.DEFAULT_PARAMETERS_EXCLUDE);
291 List<String> invExclude = excludeParams.stream().filter(p -> !defaultParamNames.contains(p))
292 .collect(Collectors.toList());
295 if (!invExclude.isEmpty() || !invInclude.isEmpty()) {
296 throw new OnapCommandInvalidDefaultParameter(Stream.concat(invInclude.stream(), invExclude.stream())
297 .collect(Collectors.toList()));
300 if (!includeParams.isEmpty()) {
301 filteredDefaultParams.addAll(includeParams);
302 } else if (!excludeParams.isEmpty()) {
303 List<String> finalExcludeParams = excludeParams;
304 defaultParamNames.stream().filter(p -> !finalExcludeParams.contains(p))
305 .forEach(filteredDefaultParams::add);
308 filteredDefaultParams.addAll(defaultParamNames);
310 processNoAuth(filteredDefaultParams, cmd, includeParams, excludeParams);
311 } else if (Constants.PARAMETERS.equals(key)) {
313 List<Map<String, String>> parameters = (List) values.get(key);
315 if (parameters != null) {
316 for (Map<String, String> map : parameters) {
317 OnapCommandParameter param = new OnapCommandParameter();
319 for (Map.Entry<String, String> entry1 : map.entrySet()) {
320 String key2 = entry1.getKey();
322 if (Constants.NAME.equals(key2)) {
323 if (names.contains(map.get(key2))) {
324 throw new OnapCommandParameterNameConflict(map.get(key2));
326 names.add(map.get(key2));
327 param.setName(map.get(key2));
328 } else if (Constants.DESCRIPTION.equals(key2)) {
329 param.setDescription(map.get(key2));
330 } else if (Constants.SHORT_OPTION.equals(key2)) {
331 if (shortOptions.contains(map.get(key2))) {
332 throw new OnapCommandParameterOptionConflict(map.get(key2));
334 shortOptions.add(map.get(key2));
335 param.setShortOption(map.get(key2));
336 } else if (Constants.LONG_OPTION.equals(key2)) {
337 if (longOptions.contains(map.get(key2))) {
338 throw new OnapCommandParameterOptionConflict(map.get(key2));
340 longOptions.add(map.get(key2));
341 param.setLongOption(map.get(key2));
342 } else if (Constants.DEFAULT_VALUE.equals(key2)) {
343 Object obj = map.get(key2);
344 param.setDefaultValue(obj.toString());
345 } else if (Constants.TYPE.equals(key2)) {
346 param.setParameterType(ParameterType.get(map.get(key2)));
347 } else if (Constants.IS_OPTIONAL.equals(key2)) {
348 if ("true".equalsIgnoreCase(String.valueOf(map.get(key2)))) {
349 param.setOptional(true);
351 param.setOptional(false);
353 } else if (Constants.IS_SECURED.equals(key2)) {
354 if ("true".equalsIgnoreCase(String.valueOf(map.get(key2)))) {
355 param.setSecured(true);
357 param.setSecured(false);
362 // Add the element to command :
363 // 1. if parameter is available in filtered parameter list.
364 // 2. otherwise, parameter p is available in command yaml file.
365 if (filteredDefaultParams.contains(param.getName()) || !defaultParamNames.contains(param.getName())) {
366 cmd.getParameters().add(param);
370 } else if (Constants.RESULTS.equals(key)) {
371 Map<String, ?> valueMap = (Map<String, ?>) values.get(key);
372 if (valueMap != null) {
373 OnapCommandResult result = new OnapCommandResult();
374 for (Map.Entry<String, ?> entry1 : valueMap.entrySet()) {
375 String key3 = entry1.getKey();
377 if (Constants.DIRECTION.equals(key3)) {
378 result.setPrintDirection(PrintDirection.get((String) valueMap.get(key3)));
379 } else if (Constants.ATTRIBUTES.equals(key3)) {
380 List<Map<String, String>> attrs = (ArrayList) valueMap.get(key3);
382 for (Map<String, String> map : attrs) {
383 OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
384 for (Map.Entry<String, String> entry4 : map.entrySet()) {
385 String key4 = entry4.getKey();
387 if (Constants.NAME.equals(key4)) {
388 attr.setName(map.get(key4));
389 } else if (Constants.DESCRIPTION.equals(key4)) {
390 attr.setDescription(map.get(key4));
391 } else if (Constants.SCOPE.equals(key4)) {
392 attr.setScope(OnapCommandResultAttributeScope.get(map.get(key4)));
393 } else if (Constants.TYPE.equals(key4)) {
394 attr.setType(ParameterType.get(map.get(key4)));
395 } else if (Constants.IS_SECURED.equals(key4)) {
396 if ("true".equals(String.valueOf(map.get(key4)))) {
397 attr.setSecured(true);
399 attr.setSecured(false);
404 result.getRecords().add(attr);
408 cmd.setResult(result);
418 * OnapSwaggerBasedCommand
421 * @throws OnapCommandParameterNameConflict
422 * param name conflict exception
423 * @throws OnapCommandParameterOptionConflict
424 * param option conflict exception
425 * @throws OnapCommandInvalidParameterType
426 * invalid param type exception
427 * @throws OnapCommandInvalidPrintDirection
428 * invalid print direction exception
429 * @throws OnapCommandInvalidResultAttributeScope
430 * invalid scope exception
431 * @throws OnapCommandSchemaNotFound
433 * @throws OnapCommandInvalidSchema
435 * @throws OnapCommandInvalidSchemaVersion
436 * invalid schema version
438 public static void loadSchema(OnapSwaggerCommand cmd, String schemaName) throws OnapCommandException {
440 Map<String, ?> values = (Map<String, ?>) validateSchemaVersion(schemaName, cmd.getSchemaVersion());
441 Map<String, String> valueMap = (Map<String, String>) values.get(Constants.EXECUTOR);
442 OnapCommandExecutor exec = new OnapCommandExecutor();
444 for (Map.Entry<String, String> entry1 : valueMap.entrySet()) {
445 String key1 = entry1.getKey();
447 if (Constants.API.equals(key1)) {
448 exec.setApi(valueMap.get(key1));
449 } else if (Constants.CLIENT.equals(key1)) {
450 exec.setClient(valueMap.get(key1));
451 } else if (Constants.ENTITY.equals(key1)) {
452 exec.setEntity(valueMap.get(key1));
453 } else if (Constants.EXCEPTION.equals(key1)) {
454 exec.setException(valueMap.get(key1));
455 } else if (Constants.METHOD.equals(key1)) {
456 exec.setMethod(valueMap.get(key1));
460 cmd.setExecutor(exec);
461 } catch (OnapCommandException e) {
463 } catch (Exception e) {
464 throw new OnapCommandInvalidSchema(schemaName, e);
475 * @throws OnapCommandParameterNameConflict
476 * param name conflict exception
477 * @throws OnapCommandParameterOptionConflict
478 * param option conflict exception
479 * @throws OnapCommandInvalidParameterType
480 * invalid param type exception
481 * @throws OnapCommandInvalidPrintDirection
482 * invalid print direction exception
483 * @throws OnapCommandInvalidResultAttributeScope
484 * invalid scope exception
485 * @throws OnapCommandSchemaNotFound
487 * @throws OnapCommandInvalidSchema
489 * @throws OnapCommandInvalidSchemaVersion
490 * invalid schema version
492 public static void loadSchema(OnapHttpCommand cmd, String schemaName) throws OnapCommandException {
494 Map<String, ?> values = (Map<String, ?>) validateSchemaVersion(schemaName, cmd.getSchemaVersion());
495 Map<String, ?> valMap = (Map<String, ?>) values.get(Constants.HTTP);
497 for (Map.Entry<String, ?> entry1 : valMap.entrySet()) {
498 String key1 = entry1.getKey();
499 if (Constants.REQUEST.equals(key1)) {
500 Map<String, ?> map = (Map<String, ?>) valMap.get(key1);
502 for (Map.Entry<String, ?> entry2 : map.entrySet()) {
503 String key2 = entry2.getKey();
505 if (Constants.URI.equals(key2)) {
506 Object obj = map.get(key2);
507 cmd.getInput().setUri(obj.toString());
508 } else if (Constants.MERHOD.equals(key2)) {
509 Object obj = map.get(key2);
510 cmd.getInput().setMethod(obj.toString());
511 } else if (Constants.BODY.equals(key2)) {
512 Object obj = map.get(key2);
513 cmd.getInput().setBody(obj.toString());
514 } else if (Constants.HEADERS.equals(key2)) {
515 Map<String, String> head = (Map<String, String>) map.get(key2);
516 cmd.getInput().setReqHeaders(head);
517 } else if (Constants.QUERIES.equals(key2)) {
518 Map<String, String> query = (Map<String, String>) map.get(key2);
520 cmd.getInput().setReqQueries(query);
523 } else if (Constants.SUCCESS_CODES.equals(key1)) {
524 cmd.setSuccessStatusCodes((ArrayList) valMap.get(key1));
525 } else if (Constants.RESULT_MAP.equals(key1)) {
526 cmd.setResultMap((Map<String, String>) valMap.get(key1));
527 } else if (Constants.SAMPLE_RESPONSE.equals(key1)) {
528 // (mrkanag) implement sample response handling
532 } catch (OnapCommandException e) {
534 } catch (Exception e) {
535 throw new OnapCommandInvalidSchema(schemaName, e);
544 * @return help string
545 * @throws OnapCommandHelpFailed
546 * help failed exception
548 public static String help(OnapCommand cmd) throws OnapCommandHelpFailed {
549 String help = "usage: onap " + cmd.getName();
552 help += "\n\n" + cmd.getDescription();
555 help += "\n\nOnap service: " + cmd.getService();
558 String commandOptions = "";
561 OnapCommandResult paramTable = new OnapCommandResult();
562 paramTable.setPrintDirection(PrintDirection.LANDSCAPE);
563 paramTable.setType(ResultType.TABLE);
564 paramTable.setIncludeTitle(false);
565 paramTable.setIncludeSeparator(false);
567 OnapCommandResultAttribute attrName = new OnapCommandResultAttribute();
568 attrName.setName(Constants.NAME);
569 attrName.setDescription(Constants.NAME);
570 attrName.setScope(OnapCommandResultAttributeScope.SHORT);
571 paramTable.getRecords().add(attrName);
573 OnapCommandResultAttribute attrDescription = new OnapCommandResultAttribute();
574 attrDescription.setName(Constants.DESCRIPTION);
575 attrDescription.setDescription(Constants.DESCRIPTION);
576 attrDescription.setScope(OnapCommandResultAttributeScope.SHORT);
577 paramTable.getRecords().add(attrDescription);
579 int newLineOptions = 0;
580 for (OnapCommandParameter param : cmd.getParameters()) {
581 // First column Option or positional args
583 if (newLineOptions == 3) {
585 commandOptions += "\n";
588 if (param.getShortOption() != null || param.getLongOption() != null) {
589 optFirstCol = OnapCommandParameter.printShortOption(param.getShortOption()) + " | "
590 + OnapCommandParameter.printLongOption(param.getLongOption());
591 commandOptions += "[" + optFirstCol + "] ";
593 optFirstCol = param.getName();
594 commandOptions += "<" + optFirstCol + "> ";
599 attrName.getValues().add(optFirstCol);
601 // Second column description
602 String optSecondCol = param.getDescription().trim();
603 if (!optSecondCol.endsWith(".")) {
606 optSecondCol += " It is of type " + param.getParameterType().name() + ".";
608 if (param.getParameterType().equals(ParameterType.JSON)
609 || param.getParameterType().equals(ParameterType.YAML)) {
610 optSecondCol += " It's recommended to input the complete path of the file, which is having the value for it.";
612 if (param.isOptional()) {
613 optSecondCol += " It is optional.";
616 String defaultMsg = " By default, it is ";
617 if (param.isDefaultValueAnEnv()) {
618 optSecondCol += defaultMsg + "read from environment variable " + param.getEnvVarNameFromDefaultValue()
620 } else if (param.getDefaultValue() != null && !((String)param.getDefaultValue()).isEmpty()) {
621 optSecondCol += defaultMsg + param.getDefaultValue() + ".";
624 if (param.isSecured()) {
625 optSecondCol += " Secured.";
627 // (mrkanag) Add help msg for reading default value from env
628 attrDescription.getValues().add(optSecondCol);
632 help += "\n\nOptions:\n" + commandOptions + "\nwhere,\n" + paramTable.print();
633 } catch (OnapCommandException e) {
634 throw new OnapCommandHelpFailed(e);
638 OnapCommandResult resultTable = new OnapCommandResult();
639 resultTable.setPrintDirection(PrintDirection.PORTRAIT);
640 resultTable.setType(ResultType.TABLE);
641 resultTable.setIncludeTitle(false);
642 resultTable.setIncludeSeparator(false);
644 for (OnapCommandResultAttribute attr : cmd.getResult().getRecords()) {
645 OnapCommandResultAttribute attrHelp = new OnapCommandResultAttribute();
646 attrHelp.setName(attr.getName());
647 attrHelp.setDescription(attr.getDescription());
648 String msg = attr.getDescription() + " and is of type " + attr.getType().name() + ".";
649 if (attr.isSecured()) {
650 msg += " It is secured.";
652 attrHelp.getValues().add(msg);
653 attrHelp.setType(attr.getType());
654 resultTable.getRecords().add(attrHelp);
657 help += "\n\nResults:\n" + resultTable.print();
658 } catch (OnapCommandException e) {
659 throw new OnapCommandHelpFailed(e);
663 help += "\n\nError:\nOn error, it prints <HTTP STATUS CODE>::<ERROR CODE>::<ERROR MESSAGE>\n";
668 * Helps to create OnapCredentials from default params.
672 * @return OnapCredentials
673 * @throws OnapCommandInvalidParameterValue
676 public static OnapCredentials fromParameters(List<OnapCommandParameter> params)
677 throws OnapCommandInvalidParameterValue {
678 Map<String, String> paramMap = new HashMap<>();
680 for (OnapCommandParameter param : params) {
681 paramMap.put(param.getName(), param.getValue().toString());
684 return new OnapCredentials(paramMap.get(Constants.DEAFULT_PARAMETER_USERNAME),
685 paramMap.get(Constants.DEAFULT_PARAMETER_PASS_WORD),
686 paramMap.get(Constants.DEAFULT_PARAMETER_HOST_URL));
690 * Create Dict from list of Parameters.
696 public static Map<String, OnapCommandParameter> getInputMap(List<OnapCommandParameter> inputs) {
697 Map<String, OnapCommandParameter> map = new HashMap<>();
698 for (OnapCommandParameter param : inputs) {
699 map.put(param.getName(), param);
705 * Discover the Onap commands.
709 public static List<Class<OnapCommand>> findOnapCommands() {
710 ServiceLoader<OnapCommand> loader = ServiceLoader.load(OnapCommand.class);
711 List<Class<OnapCommand>> clss = new ArrayList<>();
712 for (OnapCommand implClass : loader) {
713 clss.add((Class<OnapCommand>) implClass.getClass());
726 public static List<String> sort(Set<String> col) {
727 List<String> results = new ArrayList<>();
729 Collections.sort(results);
734 * Flatten the json list.
740 public static List<String> jsonFlatten(List<String> jsons) {
741 List<String> results = new ArrayList<>();
742 for (String json : jsons) {
744 results.add(JsonPath.parse(json).jsonString());
745 } catch (Exception e) { // NOSONAR
754 * Construct method name.
762 public static String formMethodNameFromAttributeName(String name, String prefix) {
763 if (name == null || name.isEmpty()) {
767 String methodName = prefix;
768 for (String tk : name.split("-")) {
769 methodName += Character.toString(tk.charAt(0)).toUpperCase();
770 methodName += tk.substring(1);
775 private static String replaceLineFromInputParameters(String line, Map<String, OnapCommandParameter> params)
776 throws OnapCommandException {
779 if (!line.contains("${")) {
784 while (currentIdx < line.length()) {
785 int idxS = line.indexOf("${", currentIdx);
787 result += line.substring(currentIdx);
790 int idxE = line.indexOf("}", idxS);
791 String paramName = line.substring(idxS + 2, idxE);
792 paramName = paramName.trim();
793 if (!params.containsKey(paramName)) {
794 throw new OnapCommandParameterNotFound(paramName);
797 String value = params.get(paramName).getValue().toString();
799 OnapCommandParameter param = params.get(paramName);
800 if (ParameterType.ARRAY.equals(param.getParameterType())
801 || ParameterType.MAP.equals(param.getParameterType())
802 || ParameterType.JSON.equals(param.getParameterType())
803 || ParameterType.YAML.equals(param.getParameterType())) {
804 // ignore the front and back double quotes in json body
805 result += line.substring(currentIdx, idxS - 1) + value;
806 currentIdx = idxE + 2;
808 result += line.substring(currentIdx, idxS) + value;
809 currentIdx = idxE + 1;
816 private static ArrayList<String> replaceLineFromOutputResults(String line, HttpResult resultHttp)
817 throws OnapCommandHttpHeaderNotFound, OnapCommandHttpInvalidResponseBody,
818 OnapCommandResultMapProcessingFailed, OnapCommandResultEmpty {
819 String headerProcessedLine = "";
821 ArrayList<String> result = new ArrayList<>();
822 if (!line.contains("$b{") && !line.contains("$h{")) {
828 * In case of empty response body [] or {}
830 if (resultHttp.getBody().length() <= 2) {
835 * Process headers macros : line: $h{abc}-$b{$.[*].xyz} , After processing line will be [abc's
836 * value]-$b{$.[*].xyz}
839 while (currentIdx < line.length()) {
840 int idxS = line.indexOf("$h{", currentIdx);
842 headerProcessedLine += line.substring(currentIdx);
845 int idxE = line.indexOf("}", idxS);
846 String headerName = line.substring(idxS + 3, idxE);
847 headerName = headerName.trim();
848 if (!resultHttp.getRespHeaders().containsKey(headerName)) {
849 throw new OnapCommandHttpHeaderNotFound(headerName);
851 String value = resultHttp.getRespHeaders().get(headerName);
853 headerProcessedLine += line.substring(currentIdx, idxS) + value;
854 currentIdx = idxE + 1;
857 // Process body jsonpath macros
858 List<Object> values = new ArrayList<>();
859 String bodyProcessedPattern = "";
861 int maxRows = 1; // in normal case, only one row will be there
862 while (currentIdx < headerProcessedLine.length()) {
863 int idxS = headerProcessedLine.indexOf("$b{", currentIdx);
865 bodyProcessedPattern += headerProcessedLine.substring(currentIdx);
868 int idxE = headerProcessedLine.indexOf("}", idxS);
869 String jsonPath = headerProcessedLine.substring(idxS + 3, idxE);
870 jsonPath = jsonPath.trim();
872 // JSONArray or String
873 Object value = JsonPath.read(resultHttp.getBody(), jsonPath);
874 if (value instanceof JSONArray) {
875 JSONArray arr = (JSONArray) value;
876 if (arr.size() > maxRows) {
877 maxRows = arr.size();
880 bodyProcessedPattern += headerProcessedLine.substring(currentIdx, idxS) + "%s";
882 currentIdx = idxE + 1;
883 } catch (Exception e) {
884 throw new OnapCommandHttpInvalidResponseBody(jsonPath, e);
888 if (bodyProcessedPattern.isEmpty()) {
889 result.add(headerProcessedLine);
892 for (int i = 0; i < maxRows; i++) {
894 String bodyProcessedLine = "";
895 int positionalIdx = 0; // %s positional idx
896 while (currentIdx < bodyProcessedPattern.length()) {
897 int idxS = bodyProcessedPattern.indexOf("%s", currentIdx);
899 bodyProcessedLine += bodyProcessedPattern.substring(currentIdx);
902 int idxE = idxS + 2; // %s
904 Object value = values.get(positionalIdx);
905 String valueS = String.valueOf(value);
906 if (value instanceof JSONArray) {
907 JSONArray arr = (JSONArray) value;
908 if (!arr.isEmpty()) {
909 valueS = arr.get(i).toString();
911 throw new OnapCommandResultEmpty();
915 bodyProcessedLine += bodyProcessedPattern.substring(currentIdx, idxS) + valueS;
918 } catch (OnapCommandResultEmpty e) {
920 } catch (Exception e) {
921 throw new OnapCommandResultMapProcessingFailed(line, e);
924 result.add(bodyProcessedLine);
932 * Set argument to param value.
939 * @throws OnapCommandParameterNotFound
941 * @throws OnapCommandInvalidParameterValue
944 public static HttpInput populateParameters(Map<String, OnapCommandParameter> params, HttpInput input)
945 throws OnapCommandException {
946 HttpInput inp = new HttpInput();
947 for (OnapCommandParameter param : params.values()) {
948 if (ParameterType.BINARY.equals(param.getParameterType())) {
949 inp.setBinaryData(true);
953 inp.setBody(replaceLineFromInputParameters(input.getBody(), params));
954 inp.setUri(replaceLineFromInputParameters(input.getUri(), params));
955 inp.setMethod(input.getMethod().toLowerCase());
956 for (String h : input.getReqHeaders().keySet()) {
957 String value = input.getReqHeaders().get(h);
958 inp.getReqHeaders().put(h, replaceLineFromInputParameters(value, params));
961 for (String h : input.getReqQueries().keySet()) {
962 String value = input.getReqQueries().get(h);
963 inp.getReqQueries().put(h, replaceLineFromInputParameters(value, params));
977 * @throws OnapCommandHttpHeaderNotFound
978 * header not found exception
979 * @throws OnapCommandHttpInvalidResponseBody
980 * invalid response body exception
981 * @throws OnapCommandResultMapProcessingFailed
982 * map processing failed exception
984 public static Map<String, ArrayList<String>> populateOutputs(Map<String, String> resultMap, HttpResult resultHttp)
985 throws OnapCommandException {
986 Map<String, ArrayList<String>> resultsProcessed = new HashMap<>();
988 for (Entry<String, String> entry : resultMap.entrySet()) {
989 String key = entry.getKey();
990 resultsProcessed.put(key, replaceLineFromOutputResults(resultMap.get(key), resultHttp));
993 return resultsProcessed;
997 * Find external schema files.
999 * @return list ExternalSchema
1000 * @throws OnapCommandDiscoveryFailed
1002 * @throws OnapCommandInvalidSchema
1005 public static List<ExternalSchema> findAllExternalSchemas() throws OnapCommandException {
1006 List<ExternalSchema> extSchemas = new ArrayList<>();
1008 Resource[] res = getExternalResources(Constants.EXTERNAL_SCHEMA_PATH_PATERN);
1009 if (res != null && res.length > 0) {
1010 Map<String, ?> resourceMap;
1011 for (Resource resource : res) {
1012 resourceMap = getExternalSchemaMap(resource);
1013 if (resourceMap != null && resourceMap.size() > 0) {
1014 ExternalSchema schema = new ExternalSchema();
1015 schema.setSchemaName(resource.getFilename());
1016 schema.setCmdName((String) resourceMap.get(Constants.NAME));
1017 Object obj = resourceMap.get(Constants.ONAP_CMD_SCHEMA_VERSION);
1018 schema.setVersion(obj.toString());
1019 extSchemas.add(schema);
1023 } catch (IOException e) {
1024 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_SCHEMA_DIRECTORY, e);
1031 * Returns all resources available under certain directory in class-path.
1035 * @return resources found resources
1036 * @throws IOException
1039 public static Resource[] getExternalResources(String pattern) throws IOException {
1040 ClassLoader cl = OnapCommandUtils.class.getClassLoader();
1041 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
1042 return resolver.getResources("classpath*:" + pattern);
1046 * Returns a resource available under certain directory in class-path.
1050 * @return found resource
1051 * @throws IOException
1054 public static Resource getExternalResource(String fileName, String pattern) throws IOException {
1055 Resource[] resources = getExternalResources(pattern);
1056 if (resources != null && resources.length > 0) {
1057 for (Resource res : resources) {
1058 if (res.getFilename().equals(fileName)) {
1073 * @throws OnapCommandInvalidSchema
1076 public static Map<String, ?> getExternalSchemaMap(Resource resource) throws OnapCommandInvalidSchema {
1077 Map<String, ?> values = null;
1079 values = (Map<String, ?>) new Yaml().load(resource.getInputStream());
1080 } catch (Exception e) {
1081 throw new OnapCommandInvalidSchema(resource.getFilename(), e);
1087 * Persist the external schema details.
1091 * @throws OnapCommandDiscoveryFailed
1094 public static void persist(List<ExternalSchema> schemas) throws OnapCommandDiscoveryFailed {
1095 if (schemas != null) {
1097 Resource[] resources = getExternalResources(Constants.EXTERNAL_DISCOVERY_DIRECTORY);
1098 if (resources != null && resources.length == 1) {
1099 String path = resources[0].getURI().getPath();
1100 File file = new File(path + File.separator + Constants.EXTERNAL_DISCOVERY_FILE);
1101 ObjectMapper mapper = new ObjectMapper();
1102 mapper.writerWithDefaultPrettyPrinter().writeValue(file, schemas);
1104 } catch (IOException e1) {
1105 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY,
1106 Constants.EXTERNAL_DISCOVERY_FILE, e1);
1112 * Check if json file discovered or not.
1115 * @throws OnapCommandDiscoveryFailed
1118 public static boolean isJsonFileDiscovered() throws OnapCommandDiscoveryFailed {
1119 Resource resource = null;
1121 resource = getExternalResource(Constants.EXTERNAL_DISCOVERY_FILE,
1122 Constants.EXTERNAL_DISCOVERY_DIRECTORY_PATTERN);
1123 if (resource != null) {
1126 } catch (IOException e) {
1127 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY,
1128 Constants.EXTERNAL_DISCOVERY_FILE, e);
1135 * Load the previous discovered json file.
1138 * @throws OnapCommandInvalidSchema
1140 * @throws OnapCommandDiscoveryFailed
1143 public static List<ExternalSchema> loadExternalSchemasFromJson() throws OnapCommandException {
1144 List<ExternalSchema> schemas = new ArrayList<>();
1145 if (!isJsonFileDiscovered()) {
1146 schemas = findAllExternalSchemas();
1147 if (!schemas.isEmpty()) {
1152 Resource resource = getExternalResource(Constants.EXTERNAL_DISCOVERY_FILE,
1153 Constants.EXTERNAL_DISCOVERY_DIRECTORY_PATTERN);
1154 if (resource != null) {
1155 File file = new File(resource.getURI().getPath());
1156 ObjectMapper mapper = new ObjectMapper();
1157 ExternalSchema[] list = mapper.readValue(file, ExternalSchema[].class);
1158 schemas.addAll(Arrays.asList(list));
1160 } catch (IOException e) {
1161 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY,
1162 Constants.EXTERNAL_DISCOVERY_FILE, e);
1170 * Fetch a particular schema details.
1174 * @return ExternalSchema obj
1175 * @throws OnapCommandInvalidSchema
1177 * @throws OnapCommandDiscoveryFailed
1180 public static ExternalSchema loadExternalSchemaFromJson(String cmd) throws OnapCommandException {
1181 List<ExternalSchema> list = loadExternalSchemasFromJson();
1182 ExternalSchema schemaStr = null;
1184 for (ExternalSchema schema : list) {
1185 if (cmd.equals(schema.getCmdName())) {