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.NO_AUTH.equals(key1)) {
252 Object obj = map.get(key1);
253 srv.setNoAuth("true".equalsIgnoreCase(obj.toString()));
254 } else if (Constants.MODE.equals(key1)) {
255 Object obj = map.get(key1);
256 //TODO mrkanag Validate and raise exception for invalid case
257 srv.setMode(obj.toString());
263 } else if (Constants.DEFAULT_PARAMETERS.equals(key)) {
265 Map<String, List<String>> defParameters = (Map) values.get(Constants.DEFAULT_PARAMETERS);
266 List<String> includeParams = new ArrayList<>();
267 List<String> excludeParams = new ArrayList<>();
269 if (values.containsKey(Constants.DEFAULT_PARAMETERS) && defParameters == null) {
270 // if default parameter section is available then it must have either include
271 // or exclude sub-section.
272 throw new OnapCommandInvalidSchema(Constants.SCHEMA_INVALID_DEFAULT_PARAMS_SECTION);
276 if (defParameters != null) {
277 // validate default parameters
278 if (defParameters.containsKey(Constants.DEFAULT_PARAMETERS_INCLUDE)) {
279 includeParams = defParameters.get(Constants.DEFAULT_PARAMETERS_INCLUDE);
282 List<String> invInclude = includeParams.stream()
283 .filter(p -> !defaultParamNames.contains(p))
284 .collect(Collectors.toList());
286 if (defParameters.containsKey(Constants.DEFAULT_PARAMETERS_EXCLUDE)) {
287 excludeParams = defParameters.get(Constants.DEFAULT_PARAMETERS_EXCLUDE);
290 List<String> invExclude = excludeParams.stream().filter(p -> !defaultParamNames.contains(p))
291 .collect(Collectors.toList());
294 if (!invExclude.isEmpty() || !invInclude.isEmpty()) {
295 throw new OnapCommandInvalidDefaultParameter(Stream.concat(invInclude.stream(), invExclude.stream())
296 .collect(Collectors.toList()));
299 if (!includeParams.isEmpty()) {
300 filteredDefaultParams.addAll(includeParams);
301 } else if (!excludeParams.isEmpty()) {
302 List<String> finalExcludeParams = excludeParams;
303 defaultParamNames.stream().filter(p -> !finalExcludeParams.contains(p))
304 .forEach(filteredDefaultParams::add);
307 filteredDefaultParams.addAll(defaultParamNames);
309 processNoAuth(filteredDefaultParams, cmd, includeParams, excludeParams);
310 } else if (Constants.PARAMETERS.equals(key)) {
312 List<Map<String, String>> parameters = (List) values.get(key);
314 if (parameters != null) {
315 for (Map<String, String> map : parameters) {
316 OnapCommandParameter param = new OnapCommandParameter();
318 for (Map.Entry<String, String> entry1 : map.entrySet()) {
319 String key2 = entry1.getKey();
321 if (Constants.NAME.equals(key2)) {
322 if (names.contains(map.get(key2))) {
323 throw new OnapCommandParameterNameConflict(map.get(key2));
325 names.add(map.get(key2));
326 param.setName(map.get(key2));
327 } else if (Constants.DESCRIPTION.equals(key2)) {
328 param.setDescription(map.get(key2));
329 } else if (Constants.SHORT_OPTION.equals(key2)) {
330 if (shortOptions.contains(map.get(key2))) {
331 throw new OnapCommandParameterOptionConflict(map.get(key2));
333 shortOptions.add(map.get(key2));
334 param.setShortOption(map.get(key2));
335 } else if (Constants.LONG_OPTION.equals(key2)) {
336 if (longOptions.contains(map.get(key2))) {
337 throw new OnapCommandParameterOptionConflict(map.get(key2));
339 longOptions.add(map.get(key2));
340 param.setLongOption(map.get(key2));
341 } else if (Constants.DEFAULT_VALUE.equals(key2)) {
342 Object obj = map.get(key2);
343 param.setDefaultValue(obj.toString());
344 } else if (Constants.TYPE.equals(key2)) {
345 param.setParameterType(ParameterType.get(map.get(key2)));
346 } else if (Constants.IS_OPTIONAL.equals(key2)) {
347 if ("true".equalsIgnoreCase(String.valueOf(map.get(key2)))) {
348 param.setOptional(true);
350 param.setOptional(false);
352 } else if (Constants.IS_SECURED.equals(key2)) {
353 if ("true".equalsIgnoreCase(String.valueOf(map.get(key2)))) {
354 param.setSecured(true);
356 param.setSecured(false);
361 // Add the element to command :
362 // 1. if parameter is available in filtered parameter list.
363 // 2. otherwise, parameter p is available in command yaml file.
364 if (filteredDefaultParams.contains(param.getName()) || !defaultParamNames.contains(param.getName())) {
365 cmd.getParameters().add(param);
369 } else if (Constants.RESULTS.equals(key)) {
370 Map<String, ?> valueMap = (Map<String, ?>) values.get(key);
371 if (valueMap != null) {
372 OnapCommandResult result = new OnapCommandResult();
373 for (Map.Entry<String, ?> entry1 : valueMap.entrySet()) {
374 String key3 = entry1.getKey();
376 if (Constants.DIRECTION.equals(key3)) {
377 result.setPrintDirection(PrintDirection.get((String) valueMap.get(key3)));
378 } else if (Constants.ATTRIBUTES.equals(key3)) {
379 List<Map<String, String>> attrs = (ArrayList) valueMap.get(key3);
381 for (Map<String, String> map : attrs) {
382 OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
383 for (Map.Entry<String, String> entry4 : map.entrySet()) {
384 String key4 = entry4.getKey();
386 if (Constants.NAME.equals(key4)) {
387 attr.setName(map.get(key4));
388 } else if (Constants.DESCRIPTION.equals(key4)) {
389 attr.setDescription(map.get(key4));
390 } else if (Constants.SCOPE.equals(key4)) {
391 attr.setScope(OnapCommandResultAttributeScope.get(map.get(key4)));
392 } else if (Constants.TYPE.equals(key4)) {
393 attr.setType(ParameterType.get(map.get(key4)));
394 } else if (Constants.IS_SECURED.equals(key4)) {
395 if ("true".equals(String.valueOf(map.get(key4)))) {
396 attr.setSecured(true);
398 attr.setSecured(false);
403 result.getRecords().add(attr);
407 cmd.setResult(result);
417 * OnapSwaggerBasedCommand
420 * @throws OnapCommandParameterNameConflict
421 * param name conflict exception
422 * @throws OnapCommandParameterOptionConflict
423 * param option conflict exception
424 * @throws OnapCommandInvalidParameterType
425 * invalid param type exception
426 * @throws OnapCommandInvalidPrintDirection
427 * invalid print direction exception
428 * @throws OnapCommandInvalidResultAttributeScope
429 * invalid scope exception
430 * @throws OnapCommandSchemaNotFound
432 * @throws OnapCommandInvalidSchema
434 * @throws OnapCommandInvalidSchemaVersion
435 * invalid schema version
437 public static void loadSchema(OnapSwaggerCommand cmd, String schemaName) throws OnapCommandException {
439 Map<String, ?> values = (Map<String, ?>) validateSchemaVersion(schemaName, cmd.getSchemaVersion());
440 Map<String, String> valueMap = (Map<String, String>) values.get(Constants.EXECUTOR);
441 OnapCommandExecutor exec = new OnapCommandExecutor();
443 for (Map.Entry<String, String> entry1 : valueMap.entrySet()) {
444 String key1 = entry1.getKey();
446 if (Constants.API.equals(key1)) {
447 exec.setApi(valueMap.get(key1));
448 } else if (Constants.CLIENT.equals(key1)) {
449 exec.setClient(valueMap.get(key1));
450 } else if (Constants.ENTITY.equals(key1)) {
451 exec.setEntity(valueMap.get(key1));
452 } else if (Constants.EXCEPTION.equals(key1)) {
453 exec.setException(valueMap.get(key1));
454 } else if (Constants.METHOD.equals(key1)) {
455 exec.setMethod(valueMap.get(key1));
459 cmd.setExecutor(exec);
460 } catch (OnapCommandException e) {
462 } catch (Exception e) {
463 throw new OnapCommandInvalidSchema(schemaName, e);
474 * @throws OnapCommandParameterNameConflict
475 * param name conflict exception
476 * @throws OnapCommandParameterOptionConflict
477 * param option conflict exception
478 * @throws OnapCommandInvalidParameterType
479 * invalid param type exception
480 * @throws OnapCommandInvalidPrintDirection
481 * invalid print direction exception
482 * @throws OnapCommandInvalidResultAttributeScope
483 * invalid scope exception
484 * @throws OnapCommandSchemaNotFound
486 * @throws OnapCommandInvalidSchema
488 * @throws OnapCommandInvalidSchemaVersion
489 * invalid schema version
491 public static void loadSchema(OnapHttpCommand cmd, String schemaName) throws OnapCommandException {
493 Map<String, ?> values = (Map<String, ?>) validateSchemaVersion(schemaName, cmd.getSchemaVersion());
494 Map<String, ?> valMap = (Map<String, ?>) values.get(Constants.HTTP);
496 for (Map.Entry<String, ?> entry1 : valMap.entrySet()) {
497 String key1 = entry1.getKey();
498 if (Constants.REQUEST.equals(key1)) {
499 Map<String, ?> map = (Map<String, ?>) valMap.get(key1);
501 for (Map.Entry<String, ?> entry2 : map.entrySet()) {
502 String key2 = entry2.getKey();
504 if (Constants.URI.equals(key2)) {
505 Object obj = map.get(key2);
506 cmd.getInput().setUri(obj.toString());
507 } else if (Constants.MERHOD.equals(key2)) {
508 Object obj = map.get(key2);
509 cmd.getInput().setMethod(obj.toString());
510 } else if (Constants.BODY.equals(key2)) {
511 Object obj = map.get(key2);
512 cmd.getInput().setBody(obj.toString());
513 } else if (Constants.HEADERS.equals(key2)) {
514 Map<String, String> head = (Map<String, String>) map.get(key2);
515 cmd.getInput().setReqHeaders(head);
516 } else if (Constants.QUERIES.equals(key2)) {
517 Map<String, String> query = (Map<String, String>) map.get(key2);
519 cmd.getInput().setReqQueries(query);
522 } else if (Constants.SUCCESS_CODES.equals(key1)) {
523 cmd.setSuccessStatusCodes((ArrayList) valMap.get(key1));
524 } else if (Constants.RESULT_MAP.equals(key1)) {
525 cmd.setResultMap((Map<String, String>) valMap.get(key1));
526 } else if (Constants.SAMPLE_RESPONSE.equals(key1)) {
527 // (mrkanag) implement sample response handling
531 } catch (OnapCommandException e) {
533 } catch (Exception e) {
534 throw new OnapCommandInvalidSchema(schemaName, e);
543 * @return help string
544 * @throws OnapCommandHelpFailed
545 * help failed exception
547 public static String help(OnapCommand cmd) throws OnapCommandHelpFailed {
548 String help = "usage: onap " + cmd.getName();
551 help += "\n\n" + cmd.getDescription();
554 help += "\n\nOnap service: " + cmd.getService();
557 String commandOptions = "";
560 OnapCommandResult paramTable = new OnapCommandResult();
561 paramTable.setPrintDirection(PrintDirection.LANDSCAPE);
562 paramTable.setType(ResultType.TABLE);
563 paramTable.setIncludeTitle(false);
564 paramTable.setIncludeSeparator(false);
566 OnapCommandResultAttribute attrName = new OnapCommandResultAttribute();
567 attrName.setName(Constants.NAME);
568 attrName.setDescription(Constants.NAME);
569 attrName.setScope(OnapCommandResultAttributeScope.SHORT);
570 paramTable.getRecords().add(attrName);
572 OnapCommandResultAttribute attrDescription = new OnapCommandResultAttribute();
573 attrDescription.setName(Constants.DESCRIPTION);
574 attrDescription.setDescription(Constants.DESCRIPTION);
575 attrDescription.setScope(OnapCommandResultAttributeScope.SHORT);
576 paramTable.getRecords().add(attrDescription);
578 int newLineOptions = 0;
579 for (OnapCommandParameter param : cmd.getParameters()) {
580 // First column Option or positional args
582 if (newLineOptions == 3) {
584 commandOptions += "\n";
587 if (param.getShortOption() != null || param.getLongOption() != null) {
588 optFirstCol = OnapCommandParameter.printShortOption(param.getShortOption()) + " | "
589 + OnapCommandParameter.printLongOption(param.getLongOption());
590 commandOptions += "[" + optFirstCol + "] ";
592 optFirstCol = param.getName();
593 commandOptions += "<" + optFirstCol + "> ";
598 attrName.getValues().add(optFirstCol);
600 // Second column description
601 String optSecondCol = param.getDescription().trim();
602 if (!optSecondCol.endsWith(".")) {
605 optSecondCol += " It is of type " + param.getParameterType().name() + ".";
607 if (param.getParameterType().equals(ParameterType.JSON)
608 || param.getParameterType().equals(ParameterType.YAML)) {
609 optSecondCol += " It's recommended to input the complete path of the file, which is having the value for it.";
611 if (param.isOptional()) {
612 optSecondCol += " It is optional.";
615 String defaultMsg = " By default, it is ";
616 if (param.isDefaultValueAnEnv()) {
617 optSecondCol += defaultMsg + "read from environment variable " + param.getEnvVarNameFromDefaultValue()
619 } else if (param.getDefaultValue() != null && !((String)param.getDefaultValue()).isEmpty()) {
620 optSecondCol += defaultMsg + param.getDefaultValue() + ".";
623 if (param.isSecured()) {
624 optSecondCol += " Secured.";
626 // (mrkanag) Add help msg for reading default value from env
627 attrDescription.getValues().add(optSecondCol);
631 help += "\n\nOptions:\n" + commandOptions + "\nwhere,\n" + paramTable.print();
632 } catch (OnapCommandException e) {
633 throw new OnapCommandHelpFailed(e);
637 OnapCommandResult resultTable = new OnapCommandResult();
638 resultTable.setPrintDirection(PrintDirection.PORTRAIT);
639 resultTable.setType(ResultType.TABLE);
640 resultTable.setIncludeTitle(false);
641 resultTable.setIncludeSeparator(false);
643 for (OnapCommandResultAttribute attr : cmd.getResult().getRecords()) {
644 OnapCommandResultAttribute attrHelp = new OnapCommandResultAttribute();
645 attrHelp.setName(attr.getName());
646 attrHelp.setDescription(attr.getDescription());
647 String msg = attr.getDescription() + " and is of type " + attr.getType().name() + ".";
648 if (attr.isSecured()) {
649 msg += " It is secured.";
651 attrHelp.getValues().add(msg);
652 attrHelp.setType(attr.getType());
653 resultTable.getRecords().add(attrHelp);
656 help += "\n\nResults:\n" + resultTable.print();
657 } catch (OnapCommandException e) {
658 throw new OnapCommandHelpFailed(e);
662 help += "\n\nError:\nOn error, it prints <HTTP STATUS CODE>::<ERROR CODE>::<ERROR MESSAGE>\n";
667 * Helps to create OnapCredentials from default params.
671 * @return OnapCredentials
672 * @throws OnapCommandInvalidParameterValue
675 public static OnapCredentials fromParameters(List<OnapCommandParameter> params)
676 throws OnapCommandInvalidParameterValue {
677 Map<String, String> paramMap = new HashMap<>();
679 for (OnapCommandParameter param : params) {
680 paramMap.put(param.getName(), param.getValue().toString());
683 return new OnapCredentials(paramMap.get(Constants.DEAFULT_PARAMETER_USERNAME),
684 paramMap.get(Constants.DEAFULT_PARAMETER_PASS_WORD),
685 paramMap.get(Constants.DEAFULT_PARAMETER_HOST_URL));
689 * Create Dict from list of Parameters.
695 public static Map<String, OnapCommandParameter> getInputMap(List<OnapCommandParameter> inputs) {
696 Map<String, OnapCommandParameter> map = new HashMap<>();
697 for (OnapCommandParameter param : inputs) {
698 map.put(param.getName(), param);
704 * Discover the Onap commands.
708 public static List<Class<OnapCommand>> findOnapCommands() {
709 ServiceLoader<OnapCommand> loader = ServiceLoader.load(OnapCommand.class);
710 List<Class<OnapCommand>> clss = new ArrayList<>();
711 for (OnapCommand implClass : loader) {
712 clss.add((Class<OnapCommand>) implClass.getClass());
725 public static List<String> sort(Set<String> col) {
726 List<String> results = new ArrayList<>();
728 Collections.sort(results);
733 * Flatten the json list.
739 public static List<String> jsonFlatten(List<String> jsons) {
740 List<String> results = new ArrayList<>();
741 for (String json : jsons) {
743 results.add(JsonPath.parse(json).jsonString());
744 } catch (Exception e) { // NOSONAR
753 * Construct method name.
761 public static String formMethodNameFromAttributeName(String name, String prefix) {
762 if (name == null || name.isEmpty()) {
766 String methodName = prefix;
767 for (String tk : name.split("-")) {
768 methodName += Character.toString(tk.charAt(0)).toUpperCase();
769 methodName += tk.substring(1);
774 private static String replaceLineFromInputParameters(String line, Map<String, OnapCommandParameter> params)
775 throws OnapCommandException {
778 if (!line.contains("${")) {
783 while (currentIdx < line.length()) {
784 int idxS = line.indexOf("${", currentIdx);
786 result += line.substring(currentIdx);
789 int idxE = line.indexOf("}", idxS);
790 String paramName = line.substring(idxS + 2, idxE);
791 paramName = paramName.trim();
792 if (!params.containsKey(paramName)) {
793 throw new OnapCommandParameterNotFound(paramName);
796 String value = params.get(paramName).getValue().toString();
798 OnapCommandParameter param = params.get(paramName);
799 if (ParameterType.ARRAY.equals(param.getParameterType())
800 || ParameterType.MAP.equals(param.getParameterType())
801 || ParameterType.JSON.equals(param.getParameterType())
802 || ParameterType.YAML.equals(param.getParameterType())) {
803 // ignore the front and back double quotes in json body
804 result += line.substring(currentIdx, idxS - 1) + value;
805 currentIdx = idxE + 2;
807 result += line.substring(currentIdx, idxS) + value;
808 currentIdx = idxE + 1;
815 private static ArrayList<String> replaceLineFromOutputResults(String line, HttpResult resultHttp)
816 throws OnapCommandHttpHeaderNotFound, OnapCommandHttpInvalidResponseBody,
817 OnapCommandResultMapProcessingFailed, OnapCommandResultEmpty {
818 String headerProcessedLine = "";
820 ArrayList<String> result = new ArrayList<>();
821 if (!line.contains("$b{") && !line.contains("$h{")) {
827 * In case of empty response body [] or {}
829 if (resultHttp.getBody().length() <= 2) {
834 * Process headers macros : line: $h{abc}-$b{$.[*].xyz} , After processing line will be [abc's
835 * value]-$b{$.[*].xyz}
838 while (currentIdx < line.length()) {
839 int idxS = line.indexOf("$h{", currentIdx);
841 headerProcessedLine += line.substring(currentIdx);
844 int idxE = line.indexOf("}", idxS);
845 String headerName = line.substring(idxS + 3, idxE);
846 headerName = headerName.trim();
847 if (!resultHttp.getRespHeaders().containsKey(headerName)) {
848 throw new OnapCommandHttpHeaderNotFound(headerName);
850 String value = resultHttp.getRespHeaders().get(headerName);
852 headerProcessedLine += line.substring(currentIdx, idxS) + value;
853 currentIdx = idxE + 1;
856 // Process body jsonpath macros
857 List<Object> values = new ArrayList<>();
858 String bodyProcessedPattern = "";
860 int maxRows = 1; // in normal case, only one row will be there
861 while (currentIdx < headerProcessedLine.length()) {
862 int idxS = headerProcessedLine.indexOf("$b{", currentIdx);
864 bodyProcessedPattern += headerProcessedLine.substring(currentIdx);
867 int idxE = headerProcessedLine.indexOf("}", idxS);
868 String jsonPath = headerProcessedLine.substring(idxS + 3, idxE);
869 jsonPath = jsonPath.trim();
871 // JSONArray or String
872 Object value = JsonPath.read(resultHttp.getBody(), jsonPath);
873 if (value instanceof JSONArray) {
874 JSONArray arr = (JSONArray) value;
875 if (arr.size() > maxRows) {
876 maxRows = arr.size();
879 bodyProcessedPattern += headerProcessedLine.substring(currentIdx, idxS) + "%s";
881 currentIdx = idxE + 1;
882 } catch (Exception e) {
883 throw new OnapCommandHttpInvalidResponseBody(jsonPath, e);
887 if (bodyProcessedPattern.isEmpty()) {
888 result.add(headerProcessedLine);
891 for (int i = 0; i < maxRows; i++) {
893 String bodyProcessedLine = "";
894 int positionalIdx = 0; // %s positional idx
895 while (currentIdx < bodyProcessedPattern.length()) {
896 int idxS = bodyProcessedPattern.indexOf("%s", currentIdx);
898 bodyProcessedLine += bodyProcessedPattern.substring(currentIdx);
901 int idxE = idxS + 2; // %s
903 Object value = values.get(positionalIdx);
904 String valueS = String.valueOf(value);
905 if (value instanceof JSONArray) {
906 JSONArray arr = (JSONArray) value;
907 if (!arr.isEmpty()) {
908 valueS = arr.get(i).toString();
910 throw new OnapCommandResultEmpty();
914 bodyProcessedLine += bodyProcessedPattern.substring(currentIdx, idxS) + valueS;
917 } catch (OnapCommandResultEmpty e) {
919 } catch (Exception e) {
920 throw new OnapCommandResultMapProcessingFailed(line, e);
923 result.add(bodyProcessedLine);
931 * Set argument to param value.
938 * @throws OnapCommandParameterNotFound
940 * @throws OnapCommandInvalidParameterValue
943 public static HttpInput populateParameters(Map<String, OnapCommandParameter> params, HttpInput input)
944 throws OnapCommandException {
945 HttpInput inp = new HttpInput();
946 for (OnapCommandParameter param : params.values()) {
947 if (ParameterType.BINARY.equals(param.getParameterType())) {
948 inp.setBinaryData(true);
952 inp.setBody(replaceLineFromInputParameters(input.getBody(), params));
953 inp.setUri(replaceLineFromInputParameters(input.getUri(), params));
954 inp.setMethod(input.getMethod().toLowerCase());
955 for (String h : input.getReqHeaders().keySet()) {
956 String value = input.getReqHeaders().get(h);
957 inp.getReqHeaders().put(h, replaceLineFromInputParameters(value, params));
960 for (String h : input.getReqQueries().keySet()) {
961 String value = input.getReqQueries().get(h);
962 inp.getReqQueries().put(h, replaceLineFromInputParameters(value, params));
976 * @throws OnapCommandHttpHeaderNotFound
977 * header not found exception
978 * @throws OnapCommandHttpInvalidResponseBody
979 * invalid response body exception
980 * @throws OnapCommandResultMapProcessingFailed
981 * map processing failed exception
983 public static Map<String, ArrayList<String>> populateOutputs(Map<String, String> resultMap, HttpResult resultHttp)
984 throws OnapCommandException {
985 Map<String, ArrayList<String>> resultsProcessed = new HashMap<>();
987 for (Entry<String, String> entry : resultMap.entrySet()) {
988 String key = entry.getKey();
989 resultsProcessed.put(key, replaceLineFromOutputResults(resultMap.get(key), resultHttp));
992 return resultsProcessed;
996 * Find external schema files.
998 * @return list ExternalSchema
999 * @throws OnapCommandDiscoveryFailed
1001 * @throws OnapCommandInvalidSchema
1004 public static List<ExternalSchema> findAllExternalSchemas() throws OnapCommandException {
1005 List<ExternalSchema> extSchemas = new ArrayList<>();
1007 Resource[] res = getExternalResources(Constants.EXTERNAL_SCHEMA_PATH_PATERN);
1008 if (res != null && res.length > 0) {
1009 Map<String, ?> resourceMap;
1010 for (Resource resource : res) {
1011 resourceMap = getExternalSchemaMap(resource);
1012 if (resourceMap != null && resourceMap.size() > 0) {
1013 ExternalSchema schema = new ExternalSchema();
1014 schema.setSchemaName(resource.getFilename());
1015 schema.setCmdName((String) resourceMap.get(Constants.NAME));
1016 Object obj = resourceMap.get(Constants.ONAP_CMD_SCHEMA_VERSION);
1017 schema.setVersion(obj.toString());
1018 extSchemas.add(schema);
1022 } catch (IOException e) {
1023 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_SCHEMA_DIRECTORY, e);
1030 * Returns all resources available under certain directory in class-path.
1034 * @return resources found resources
1035 * @throws IOException
1038 public static Resource[] getExternalResources(String pattern) throws IOException {
1039 ClassLoader cl = OnapCommandUtils.class.getClassLoader();
1040 ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
1041 return resolver.getResources("classpath*:" + pattern);
1045 * Returns a resource available under certain directory in class-path.
1049 * @return found resource
1050 * @throws IOException
1053 public static Resource getExternalResource(String fileName, String pattern) throws IOException {
1054 Resource[] resources = getExternalResources(pattern);
1055 if (resources != null && resources.length > 0) {
1056 for (Resource res : resources) {
1057 if (res.getFilename().equals(fileName)) {
1072 * @throws OnapCommandInvalidSchema
1075 public static Map<String, ?> getExternalSchemaMap(Resource resource) throws OnapCommandInvalidSchema {
1076 Map<String, ?> values = null;
1078 values = (Map<String, ?>) new Yaml().load(resource.getInputStream());
1079 } catch (Exception e) {
1080 throw new OnapCommandInvalidSchema(resource.getFilename(), e);
1086 * Persist the external schema details.
1090 * @throws OnapCommandDiscoveryFailed
1093 public static void persist(List<ExternalSchema> schemas) throws OnapCommandDiscoveryFailed {
1094 if (schemas != null) {
1096 Resource[] resources = getExternalResources(Constants.EXTERNAL_DISCOVERY_DIRECTORY);
1097 if (resources != null && resources.length == 1) {
1098 String path = resources[0].getURI().getPath();
1099 File file = new File(path + File.separator + Constants.EXTERNAL_DISCOVERY_FILE);
1100 ObjectMapper mapper = new ObjectMapper();
1101 mapper.writerWithDefaultPrettyPrinter().writeValue(file, schemas);
1103 } catch (IOException e1) {
1104 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY,
1105 Constants.EXTERNAL_DISCOVERY_FILE, e1);
1111 * Check if json file discovered or not.
1114 * @throws OnapCommandDiscoveryFailed
1117 public static boolean isJsonFileDiscovered() throws OnapCommandDiscoveryFailed {
1118 Resource resource = null;
1120 resource = getExternalResource(Constants.EXTERNAL_DISCOVERY_FILE,
1121 Constants.EXTERNAL_DISCOVERY_DIRECTORY_PATTERN);
1122 if (resource != null) {
1125 } catch (IOException e) {
1126 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY,
1127 Constants.EXTERNAL_DISCOVERY_FILE, e);
1134 * Load the previous discovered json file.
1137 * @throws OnapCommandInvalidSchema
1139 * @throws OnapCommandDiscoveryFailed
1142 public static List<ExternalSchema> loadExternalSchemasFromJson() throws OnapCommandException {
1143 List<ExternalSchema> schemas = new ArrayList<>();
1144 if (!isJsonFileDiscovered()) {
1145 schemas = findAllExternalSchemas();
1146 if (!schemas.isEmpty()) {
1151 Resource resource = getExternalResource(Constants.EXTERNAL_DISCOVERY_FILE,
1152 Constants.EXTERNAL_DISCOVERY_DIRECTORY_PATTERN);
1153 if (resource != null) {
1154 File file = new File(resource.getURI().getPath());
1155 ObjectMapper mapper = new ObjectMapper();
1156 ExternalSchema[] list = mapper.readValue(file, ExternalSchema[].class);
1157 schemas.addAll(Arrays.asList(list));
1159 } catch (IOException e) {
1160 throw new OnapCommandDiscoveryFailed(Constants.EXTERNAL_DISCOVERY_DIRECTORY,
1161 Constants.EXTERNAL_DISCOVERY_FILE, e);
1169 * Fetch a particular schema details.
1173 * @return ExternalSchema obj
1174 * @throws OnapCommandInvalidSchema
1176 * @throws OnapCommandDiscoveryFailed
1179 public static ExternalSchema loadExternalSchemaFromJson(String cmd) throws OnapCommandException {
1180 List<ExternalSchema> list = loadExternalSchemasFromJson();
1181 ExternalSchema schemaStr = null;
1183 for (ExternalSchema schema : list) {
1184 if (cmd.equals(schema.getCmdName())) {