2 * Copyright 2017 Huawei Technologies Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.onap.cli.fw.schema;
20 import static org.onap.cli.fw.conf.OnapCommandConstants.ATTRIBUTES;
21 import static org.onap.cli.fw.conf.OnapCommandConstants.BOOLEAN_TRUE;
22 import static org.onap.cli.fw.conf.OnapCommandConstants.COMMAND_TYPE_VALUES;
23 import static org.onap.cli.fw.conf.OnapCommandConstants.DEFAULT_PARAMETER_FILE_NAME;
24 import static org.onap.cli.fw.conf.OnapCommandConstants.DEFAULT_VALUE;
25 import static org.onap.cli.fw.conf.OnapCommandConstants.DESCRIPTION;
26 import static org.onap.cli.fw.conf.OnapCommandConstants.DIRECTION;
27 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO;
28 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_AUTHOR;
29 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_IGNORE;
30 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_METADATA;
31 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_PARAMS_LIST;
32 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_PARAMS_MANDATORY_LIST;
33 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_PRODUCT;
34 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_SERVICE;
35 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_STATE;
36 import static org.onap.cli.fw.conf.OnapCommandConstants.INFO_TYPE;
37 import static org.onap.cli.fw.conf.OnapCommandConstants.INPUT_PARAMS_LIST;
38 import static org.onap.cli.fw.conf.OnapCommandConstants.INPUT_PARAMS_MANDATORY_LIST;
39 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_DEFAULT_ATTR;
40 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_DEFAULT_PARAM;
41 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_INCLUDE;
42 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_OPTIONAL;
43 import static org.onap.cli.fw.conf.OnapCommandConstants.IS_SECURED;
44 import static org.onap.cli.fw.conf.OnapCommandConstants.LONG_OPTION;
45 import static org.onap.cli.fw.conf.OnapCommandConstants.NAME;
46 import static org.onap.cli.fw.conf.OnapCommandConstants.OPEN_CLI_SCHEMA_VERSION;
47 import static org.onap.cli.fw.conf.OnapCommandConstants.PARAMETERS;
48 import static org.onap.cli.fw.conf.OnapCommandConstants.RESULTS;
49 import static org.onap.cli.fw.conf.OnapCommandConstants.RESULT_PARAMS_LIST;
50 import static org.onap.cli.fw.conf.OnapCommandConstants.RESULT_PARAMS_MANDATORY_LIST;
51 import static org.onap.cli.fw.conf.OnapCommandConstants.SCHEMA_FILE_NOT_EXIST;
52 import static org.onap.cli.fw.conf.OnapCommandConstants.SCHEMA_FILE_WRONG_EXTN;
53 import static org.onap.cli.fw.conf.OnapCommandConstants.SCHEMA_PATH_PATERN;
54 import static org.onap.cli.fw.conf.OnapCommandConstants.SCOPE;
55 import static org.onap.cli.fw.conf.OnapCommandConstants.SHORT_OPTION;
56 import static org.onap.cli.fw.conf.OnapCommandConstants.TOP_LEVEL_MANDATORY_LIST;
57 import static org.onap.cli.fw.conf.OnapCommandConstants.TOP_LEVEL_PARAMS_LIST;
58 import static org.onap.cli.fw.conf.OnapCommandConstants.TYPE;
61 import java.io.FileInputStream;
62 import java.io.FileNotFoundException;
63 import java.io.IOException;
64 import java.io.InputStream;
65 import java.util.ArrayList;
66 import java.util.Arrays;
67 import java.util.HashMap;
68 import java.util.HashSet;
69 import java.util.List;
73 import org.onap.cli.fw.cmd.OnapCommand;
74 import org.onap.cli.fw.cmd.OnapCommandType;
75 import org.onap.cli.fw.conf.OnapCommandConfig;
76 import org.onap.cli.fw.conf.OnapCommandConstants;
77 import org.onap.cli.fw.error.OnapCommandException;
78 import org.onap.cli.fw.error.OnapCommandInvalidSchema;
79 import org.onap.cli.fw.error.OnapCommandInvalidSchemaVersion;
80 import org.onap.cli.fw.error.OnapCommandParameterNameConflict;
81 import org.onap.cli.fw.error.OnapCommandParameterOptionConflict;
82 import org.onap.cli.fw.error.OnapCommandSchemaNotFound;
83 import org.onap.cli.fw.info.OnapCommandInfo;
84 import org.onap.cli.fw.info.OnapCommandState;
85 import org.onap.cli.fw.input.OnapCommandParameter;
86 import org.onap.cli.fw.input.OnapCommandParameterType;
87 import org.onap.cli.fw.output.OnapCommandPrintDirection;
88 import org.onap.cli.fw.output.OnapCommandResultAttribute;
89 import org.onap.cli.fw.output.OnapCommandResultAttributeScope;
90 import org.onap.cli.fw.utils.OnapCommandDiscoveryUtils;
91 import org.onap.cli.fw.utils.OnapCommandUtils;
92 import org.springframework.core.io.Resource;
94 public class OnapCommandSchemaLoader {
96 private OnapCommandSchemaLoader() {
97 // As per the java guidelines
101 * Validates schema version.
103 * @param schemaName schema name
104 * @param version schema version
106 * @throws OnapCommandInvalidSchemaVersion invalid schema version exception
107 * @throws OnapCommandInvalidSchema invalid schema
108 * @throws OnapCommandSchemaNotFound schema not found
110 public static Map<String, Object> validateSchemaVersion(String schemaName, String version) throws OnapCommandException {
111 Map<String, Object> values = null;
113 InputStream inputStream = OnapCommandUtils.class.getClassLoader().getResourceAsStream(schemaName);
115 Resource resource = OnapCommandDiscoveryUtils.findResource(schemaName, SCHEMA_PATH_PATERN);
117 if (resource != null) {
118 inputStream = resource.getInputStream();
121 if (inputStream == null) {
122 inputStream = loadSchemaFromFile(schemaName);
125 values = loadSchema(inputStream, schemaName);
126 String schemaVersion = "";
127 if (values.keySet().contains(OPEN_CLI_SCHEMA_VERSION)) {
128 Object obj = values.get(OPEN_CLI_SCHEMA_VERSION);
129 schemaVersion = obj.toString();
132 if (!version.equals(schemaVersion)) {
133 throw new OnapCommandInvalidSchemaVersion(schemaVersion);
136 } catch (IOException e) {
137 throw new OnapCommandSchemaNotFound(schemaName, e);
143 * Retrieve OnapCommand from schema.
145 * @param cmd OnapCommand
146 * @param schemaName schema name
147 * @param includeDefault include if default
148 * @param validateSchema flag to represent validation
149 * @throws OnapCommandException on error
151 public static List<String> loadSchema(OnapCommand cmd, String schemaName, boolean includeDefault,
152 boolean validateSchema) throws OnapCommandException {
154 List<String> errors = new ArrayList<>();
155 if (includeDefault) {
156 Map<String, ?> defaultParameterMap = validateSchemaVersion(DEFAULT_PARAMETER_FILE_NAME, cmd.getSchemaVersion());
157 //mrkanag default_parameter is supported only for parameters.
158 if (defaultParameterMap.containsKey(INFO)) {
159 defaultParameterMap.remove(OnapCommandConstants.INFO);
162 errors.addAll(parseSchema(cmd, defaultParameterMap, validateSchema));
165 Map<String, Object> commandYamlMap = validateSchemaVersion(schemaName, cmd.getSchemaVersion());
167 errors.addAll(parseSchema(cmd, commandYamlMap, validateSchema));
170 } catch (OnapCommandException e) {
172 } catch (Exception e) {
173 throw new OnapCommandInvalidSchema(schemaName, e);
177 public static List<String> parseSchema(OnapCommand cmd,
178 final Map<String, ?> values,
179 boolean validate) throws OnapCommandException {
181 List<String> exceptionList = new ArrayList<>();
182 List<String> shortOptions = new ArrayList<>();
183 List<String> longOptions = new ArrayList<>();
186 OnapCommandUtils.validateTags(exceptionList, (Map<String, Object>) values, OnapCommandConfig.getCommaSeparatedList(TOP_LEVEL_PARAMS_LIST),
187 OnapCommandConfig.getCommaSeparatedList(TOP_LEVEL_MANDATORY_LIST), "root level");
191 List<String> sections = Arrays.asList(NAME, DESCRIPTION, INFO, PARAMETERS, RESULTS);
193 for (String key : sections) {
197 Object val = values.get(key);
199 cmd.setName(val.toString());
204 Object description = values.get(key);
205 if (description != null) {
206 cmd.setDescription(description.toString());
211 Map<String, String> infoMap = (Map<String, String>) values.get(key);
213 if (infoMap != null) {
215 OnapCommandUtils.validateTags(exceptionList, (Map<String, Object>) values.get(key),
216 OnapCommandConfig.getCommaSeparatedList(INFO_PARAMS_LIST),
217 OnapCommandConfig.getCommaSeparatedList(INFO_PARAMS_MANDATORY_LIST), INFO);
219 HashMap<String, String> validationMap = new HashMap<>();
220 validationMap.put(INFO_TYPE, COMMAND_TYPE_VALUES);
222 for (Map.Entry<String,String> entry : validationMap.entrySet()) {
223 String secKey=entry.getKey();
224 if (infoMap.containsKey(secKey)) {
225 String value = infoMap.get(secKey);
227 exceptionList.add("Attribute '" + secKey + "' under '" + INFO + "' is empty");
229 if (!OnapCommandConfig.getCommaSeparatedList(validationMap.get(secKey)).contains(value)) {
230 exceptionList.add("Attribute '" + secKey + "' contains invalid value. Valide values are "
231 + OnapCommandConfig.getCommaSeparatedList(validationMap.get(key))); //
238 OnapCommandInfo info = new OnapCommandInfo();
240 for (Map.Entry<String, String> entry1 : infoMap.entrySet()) {
241 String key1 = entry1.getKey();
245 info.setProduct(infoMap.get(key1));
249 info.setService(infoMap.get(key1));
253 Object obj = infoMap.get(key1);
254 info.setCommandType(OnapCommandType.get(obj.toString()));
258 Object state = infoMap.get(key1);
259 info.setState(OnapCommandState.get(state.toString()));
263 Object mode = infoMap.get(key1);
264 info.setAuthor(mode.toString());
268 Object metadata = infoMap.get(key1);
269 info.setMetadata((Map<String,String>)metadata);
273 Object ignore = infoMap.get(key1);
274 info.setIgnore(ignore.toString().equalsIgnoreCase(OnapCommandConstants.BOOLEAN_TRUE));
276 default : // Do nothing
286 List<Map<String, String>> parameters = (List) values.get(key);
288 if (parameters != null) {
289 Set<String> names = new HashSet<>();
291 for (Map<String, String> parameter : parameters) {
292 OnapCommandParameter param = new OnapCommandParameter();
295 OnapCommandUtils.validateTags(exceptionList, parameter, OnapCommandConfig.getCommaSeparatedList(INPUT_PARAMS_LIST),
296 OnapCommandConfig.getCommaSeparatedList(INPUT_PARAMS_MANDATORY_LIST), PARAMETERS);
299 for (Map.Entry<String, String> entry1 : parameter.entrySet()) {
300 String key2 = entry1.getKey();
304 if (names.contains(parameter.get(key2))) {
305 OnapCommandUtils.throwOrCollect(new OnapCommandParameterNameConflict(parameter.get(key2)), exceptionList, validate);
307 names.add(parameter.get(key2));
310 param.setName(parameter.get(key2));
314 param.setDescription(parameter.get(key2));
318 if (shortOptions.contains(parameter.get(key2))) {
319 OnapCommandUtils.throwOrCollect(new OnapCommandParameterOptionConflict(
321 parameter.get(key2)), exceptionList, validate);
323 shortOptions.add(parameter.get(key2));
324 param.setShortOption(parameter.get(key2));
328 if (longOptions.contains(parameter.get(key2))) {
329 OnapCommandUtils.throwOrCollect(new OnapCommandParameterOptionConflict(
331 parameter.get(key2)), exceptionList, validate);
333 longOptions.add(parameter.get(key2));
334 param.setLongOption(parameter.get(key2));
338 Object obj = parameter.get(key2);
339 param.setRawDefaultValue(obj.toString());
344 param.setParameterType(OnapCommandParameterType.get(parameter.get(key2)));
345 } catch (OnapCommandException ex) {
346 OnapCommandUtils.throwOrCollect(ex, exceptionList, validate);
351 if (validate && !OnapCommandUtils.validateBoolean(String.valueOf(parameter.get(key2)))) {
352 exceptionList.add(OnapCommandUtils.invalidBooleanValueMessage(parameter.get(NAME),
353 IS_OPTIONAL, String.valueOf(parameter.get(key2))));
356 param.setOptional(BOOLEAN_TRUE.equalsIgnoreCase(String.valueOf(parameter.get(key2))));
360 if (validate && !OnapCommandUtils.validateBoolean(String.valueOf(parameter.get(key2)))) {
361 exceptionList.add(OnapCommandUtils.invalidBooleanValueMessage(parameter.get(NAME),
362 IS_SECURED, String.valueOf(parameter.get(key2))));
365 param.setSecured(BOOLEAN_TRUE.equalsIgnoreCase(String.valueOf(parameter.get(key2))));
369 if (validate && !OnapCommandUtils.validateBoolean(String.valueOf(parameter.get(key2)))) {
370 exceptionList.add(OnapCommandUtils.invalidBooleanValueMessage(parameter.get(NAME),
371 IS_INCLUDE, String.valueOf(parameter.get(key2))));
374 param.setInclude(BOOLEAN_TRUE.equalsIgnoreCase(String.valueOf(parameter.get(key2))));
377 case IS_DEFAULT_PARAM:
378 if (validate && !OnapCommandUtils.validateBoolean(String.valueOf(parameter.get(key2)))) {
379 exceptionList.add(OnapCommandUtils.invalidBooleanValueMessage(parameter.get(NAME),
380 IS_DEFAULT_PARAM, String.valueOf(parameter.get(key2))));
383 param.setDefaultParam(BOOLEAN_TRUE.equalsIgnoreCase(String.valueOf(parameter.get(key2))));
385 default : // Do nothing
389 cmd.getParameters().add(param);
395 Map<String, ?> valueMap = (Map<String, ?>) values.get(key);
396 if (valueMap != null) {
397 for (Map.Entry<String, ?> entry1 : valueMap.entrySet()) {
398 String key3 = entry1.getKey();
403 cmd.getResult().setPrintDirection(OnapCommandPrintDirection.get((String) valueMap.get(key3)));
404 } catch (OnapCommandException ex) {
405 OnapCommandUtils.throwOrCollect(ex, exceptionList, validate);
410 List<Map<String, String>> attrs = (ArrayList) valueMap.get(key3);
412 for (Map<String, String> map : attrs) {
413 OnapCommandResultAttribute attr = new OnapCommandResultAttribute();
415 OnapCommandUtils.validateTags(exceptionList, map, OnapCommandConfig.getCommaSeparatedList(RESULT_PARAMS_LIST),
416 OnapCommandConfig.getCommaSeparatedList(RESULT_PARAMS_MANDATORY_LIST), ATTRIBUTES);
419 Set<String> resultParamNames = new HashSet<>();
421 for (Map.Entry<String, String> entry4 : map.entrySet()) {
422 String key4 = entry4.getKey();
426 if (resultParamNames.contains(map.get(key4))) {
427 exceptionList.add("Attribute name='" + map.get(key4) + "' under '"
428 + ATTRIBUTES + ":' is already used, Take different one.");
431 attr.setName(map.get(key4));
432 resultParamNames.add(map.get(key4));
437 attr.setDescription(map.get(key4));
442 attr.setScope(OnapCommandResultAttributeScope.get(map.get(key4)));
443 } catch (OnapCommandException ex) {
444 OnapCommandUtils.throwOrCollect(ex, exceptionList, validate);
450 attr.setType(OnapCommandParameterType.get(map.get(key4)));
451 } catch (OnapCommandException ex) {
452 OnapCommandUtils.throwOrCollect(ex, exceptionList, validate);
457 Object obj = map.get(key4);
458 attr.setDefaultValue(obj.toString());
462 if (validate && !OnapCommandUtils.validateBoolean(String.valueOf(map.get(key4)))) {
463 exceptionList.add(OnapCommandUtils.invalidBooleanValueMessage(ATTRIBUTES,
464 IS_SECURED, String.valueOf(map.get(key4))));
466 attr.setSecured(BOOLEAN_TRUE.equals(String.valueOf(map.get(key4))));
469 case IS_DEFAULT_ATTR:
470 if (validate && !OnapCommandUtils.validateBoolean(String.valueOf(map.get(key4)))) {
471 exceptionList.add(OnapCommandUtils.invalidBooleanValueMessage(ATTRIBUTES,
472 IS_DEFAULT_ATTR, String.valueOf(map.get(key4))));
474 attr.setDefaultAttr(BOOLEAN_TRUE.equals(String.valueOf(map.get(key4))));
476 default : // Do nothing
480 cmd.getResult().getRecords().add(attr);
483 default : // Do nothing
488 default : // Do nothing
492 return exceptionList;
495 public static InputStream loadSchemaFromFile(String schemaLocation) throws OnapCommandInvalidSchema {
496 File schemaFile = new File(schemaLocation);
498 FileInputStream inputFileStream = new FileInputStream(schemaFile); // NOSONAR
499 if (!schemaFile.isFile()) {
500 throw new OnapCommandInvalidSchema(schemaFile.getName(), SCHEMA_FILE_NOT_EXIST);
503 if (!schemaFile.getName().endsWith(".yaml")) {
504 throw new OnapCommandInvalidSchema(schemaFile.getName(), SCHEMA_FILE_WRONG_EXTN);
506 return inputFileStream;
507 }catch (FileNotFoundException e) {
508 throw new OnapCommandInvalidSchema(schemaFile.getName(), e);
518 * @throws OnapCommandInvalidSchema
521 public static Map<String, Object> loadSchema(InputStream stream, String schemaName) throws OnapCommandInvalidSchema { //NOSONAR
522 return OnapCommandDiscoveryUtils.loadYaml(stream);