summaryrefslogtreecommitdiffstats
path: root/dictionaryvalidation/src
diff options
context:
space:
mode:
Diffstat (limited to 'dictionaryvalidation/src')
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/Main.java48
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/OutputFilePathGenerator.java41
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseModel.java51
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseStorage.java30
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToJsonConverter.java28
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToResponseModelConverter.java31
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ValidateDictionaryYamlCommand.java92
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Cli.java85
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Command.java29
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandException.java27
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandResponse.java48
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Console.java41
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidate.java120
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidateResponse.java57
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlContentValidator.java83
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java82
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java40
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java36
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java42
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java33
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java56
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java52
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java42
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java34
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java111
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java45
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java37
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java59
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java78
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java50
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java66
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java84
-rw-r--r--dictionaryvalidation/src/main/java/org/onap/validation/yaml/util/Args.java36
-rw-r--r--dictionaryvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand15
-rw-r--r--dictionaryvalidation/src/main/resources/log4j2.properties56
-rw-r--r--dictionaryvalidation/src/main/resources/open-cli-schema/dictionary-validate.yaml63
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/functional/DictionaryValidateRuleFunctionalTest.java178
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/functional/util/OnapCliWrapper.java42
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/functional/util/ValidationUtility.java49
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/cli/MainCITest.java144
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/OutputFilePathGeneratorTest.java43
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ToJsonConverterTest.java70
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ValidateYamlCommandTest.java96
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/cli/core/CliTest.java101
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlContentValidatorTest.java164
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java148
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java104
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java115
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java130
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java85
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java100
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java115
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java147
-rw-r--r--dictionaryvalidation/src/test/java/org/onap/validation/yaml/util/ArgsTest.java39
-rw-r--r--dictionaryvalidation/src/test/resources/Not_Yaml_File.txt1
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Custom_Invalid_Dictionary.yaml56
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Custom_Valid_Dictionary.yaml58
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml86
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml228
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml239
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml149
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml39
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml39
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml149
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml39
-rw-r--r--dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml23
66 files changed, 4904 insertions, 0 deletions
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/Main.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/Main.java
new file mode 100644
index 0000000..ddeecbf
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/Main.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli;
+
+import org.onap.validation.cli.command.validate.ResponseStorage;
+import org.onap.validation.cli.command.validate.ToJsonConverter;
+import org.onap.validation.cli.command.validate.ValidateDictionaryYamlCommand;
+import org.onap.validation.cli.core.Cli;
+import org.onap.validation.cli.core.Console;
+import org.onap.validation.yaml.util.Args;
+
+import java.util.List;
+
+public class Main {
+
+ public static void main(String[] args) {
+ final Console console = new Console();
+ final ResponseStorage storage = new ResponseStorage();
+
+ System.exit(
+ run(args, console, storage)
+ );
+ }
+
+ static int run(String[] args, Console console, ResponseStorage responseStorage) {
+
+ Cli<String> cli = new Cli<>(console, responseStorage);
+
+ return cli.run(
+ new Args(List.of(args)),
+ new ValidateDictionaryYamlCommand(new ToJsonConverter())
+ );
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/OutputFilePathGenerator.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/OutputFilePathGenerator.java
new file mode 100644
index 0000000..2ed7285
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/OutputFilePathGenerator.java
@@ -0,0 +1,41 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import java.nio.file.Path;
+
+public class OutputFilePathGenerator {
+
+ public static final int FILE_NAME_ABBREVIATION_INDEX = 0;
+ public static final String BY_PERIOD_REGEX = "\\.";
+ public static final String POST_FIX = "-validation-results.json";
+
+ public Path responsePathFor(Path filePath) {
+ final Path parent = filePath.getParent();
+ final String fileNameAbbreviation = getFileNameAbbreviation(filePath);
+ return Path.of(parent.toString(), createFileName(fileNameAbbreviation));
+ }
+
+ private String createFileName(String fileNameAbbreviation) {
+ return fileNameAbbreviation + POST_FIX;
+ }
+
+ private String getFileNameAbbreviation(Path filePath) {
+ final Path fileName = filePath.getFileName();
+ return fileName.toString().split(BY_PERIOD_REGEX)[FILE_NAME_ABBREVIATION_INDEX];
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseModel.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseModel.java
new file mode 100644
index 0000000..033031d
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseModel.java
@@ -0,0 +1,51 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ResponseModel {
+
+ private final String file;
+ private final ResponseStatus status;
+ private final List<YamlDocumentValidationError> errors;
+
+ public ResponseModel(String file, ResponseStatus status, List<YamlDocumentValidationError> errors) {
+ this.file = file;
+ this.status = status;
+ this.errors = errors;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public List<YamlDocumentValidationError> getErrors() {
+ return Collections.unmodifiableList(errors);
+ }
+
+ public ResponseStatus getStatus() {
+ return status;
+ }
+
+ public enum ResponseStatus {
+ PASS, FAILED
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseStorage.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseStorage.java
new file mode 100644
index 0000000..3daed16
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ResponseStorage.java
@@ -0,0 +1,30 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Path;
+
+public class ResponseStorage{
+
+ public <T> void store(Path filePath, T response) throws IOException {
+ try (PrintWriter out = new PrintWriter(filePath.toFile())) {
+ out.println(response);
+ }
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToJsonConverter.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToJsonConverter.java
new file mode 100644
index 0000000..168daf8
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToJsonConverter.java
@@ -0,0 +1,28 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+
+public class ToJsonConverter {
+ public String convert(ResponseModel responseModel) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ return gson.toJson(responseModel);
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToResponseModelConverter.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToResponseModelConverter.java
new file mode 100644
index 0000000..674068f
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ToResponseModelConverter.java
@@ -0,0 +1,31 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+public final class ToResponseModelConverter {
+
+ private ToResponseModelConverter() {
+ }
+
+ public static ResponseModel toModel(String json) {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ return gson.fromJson(json, ResponseModel.class);
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ValidateDictionaryYamlCommand.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ValidateDictionaryYamlCommand.java
new file mode 100644
index 0000000..68b0b7a
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/command/validate/ValidateDictionaryYamlCommand.java
@@ -0,0 +1,92 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import org.onap.validation.cli.core.Command;
+import org.onap.validation.cli.core.CommandException;
+import org.onap.validation.cli.core.CommandResponse;
+import org.onap.validation.yaml.YamlContentValidator;
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.util.Args;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+public class ValidateDictionaryYamlCommand implements Command<String> {
+
+ public static final int PATH_TO_FILE_INDEX = 0;
+ private final YamlContentValidator yamlContentValidator = new YamlContentValidator();
+
+ private final ToJsonConverter toJsonConverter;
+ private final OutputFilePathGenerator filePathGenerator = new OutputFilePathGenerator();
+
+ public ValidateDictionaryYamlCommand(ToJsonConverter toJsonConverter) {
+ this.toJsonConverter = toJsonConverter;
+ }
+
+ @Override
+ public CommandResponse<String> execute(Args args) throws CommandException {
+ final String pathToFile = resolvePathToFile(args);
+
+ try {
+ return validate(pathToFile);
+ } catch (YamlProcessingException e) {
+ throw new CommandException("Provided yaml file has invalid structure!", e);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "Validate Dictionary yaml";
+ }
+
+ @Override
+ public Path getOutputFilePath(Args args) throws CommandException {
+ final String pathToFile = resolvePathToFile(args);
+ return this.filePathGenerator.responsePathFor(Path.of(pathToFile));
+ }
+
+ private CommandResponse<String> validate(String pathToFile) throws YamlProcessingException {
+ final List<YamlDocumentValidationError> errors = yamlContentValidator.validate(pathToFile);
+ return new CommandResponse<>(
+ toJsonConverter.convert(new ResponseModel(pathToFile, resolveResponseStatus(errors), errors))
+ ,resolveCommandStatus(errors)
+ );
+ }
+
+ private ResponseModel.ResponseStatus resolveResponseStatus(List<YamlDocumentValidationError> errors) {
+ return errors.isEmpty() ? ResponseModel.ResponseStatus.PASS : ResponseModel.ResponseStatus.FAILED;
+ }
+
+ private CommandResponse.CommandStatus resolveCommandStatus(List<YamlDocumentValidationError> errors) {
+ return errors.isEmpty() ? CommandResponse.CommandStatus.PASS : CommandResponse.CommandStatus.FAILED;
+ }
+
+ private String resolvePathToFile(Args args) throws CommandException {
+ try {
+ final String pathToFile = args.getArg(PATH_TO_FILE_INDEX);
+ if (!Files.exists(Path.of(pathToFile))) {
+ throw new CommandException(String.format("File '%s' does not exist!", pathToFile));
+ }
+ return pathToFile;
+ } catch (IllegalArgumentException ex) {
+ throw new CommandException("Command argument is missing: provide a path to file", ex);
+ }
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Cli.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Cli.java
new file mode 100644
index 0000000..bf2abad
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Cli.java
@@ -0,0 +1,85 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.core;
+
+import org.onap.validation.cli.command.validate.ResponseStorage;
+import org.onap.validation.cli.core.CommandResponse.CommandStatus;
+import org.onap.validation.yaml.util.Args;
+
+import java.nio.file.Path;
+
+public class Cli<T> {
+
+ public static final int INTERNAL_ERROR_STATUS_CODE = 2;
+ public static final int FAILED_STATUS_CODE = 1;
+ public static final int PASS_STATUS_CODE = 0;
+
+ public static final String APPLICATION_INTERNAL_ERROR_MSG = "\n# Application fails with internal error.";
+ public static final String APPLICATION_EXIT_SUCCESSFULLY_MSG = "\n# Application exits successfully.";
+
+ private final Console console;
+ private final ResponseStorage responseStorage;
+
+ public Cli(Console console, ResponseStorage responseStorage) {
+ this.console = console;
+ this.responseStorage = responseStorage;
+ }
+
+ public int run(Args args, Command<T> command) {
+ try {
+ final CommandResponse<T> commandResponse = processCommand(args, command);
+
+ logResultInfo(commandResponse.getResult());
+ storeResult(args, command, commandResponse.getResult());
+
+ this.console.info(APPLICATION_EXIT_SUCCESSFULLY_MSG);
+
+ return resolveCliStatusCodeFor(commandResponse);
+ } catch (Exception e) {
+ logException(e);
+ return INTERNAL_ERROR_STATUS_CODE;
+ }
+ }
+
+ private int resolveCliStatusCodeFor(CommandResponse<T> commandResponse) {
+ return commandResponse.getCommandStatus() == CommandStatus.PASS ? PASS_STATUS_CODE : FAILED_STATUS_CODE;
+ }
+
+ private void logException(Exception e) {
+ this.console.error("# Command error: ");
+ this.console.error(e);
+ this.console.error(APPLICATION_INTERNAL_ERROR_MSG);
+ }
+
+ private void storeResult(Args args, Command<T> command, T result) throws CommandException, java.io.IOException {
+ final Path pathToFileWithResponse = command.getOutputFilePath(args);
+ this.responseStorage.store(pathToFileWithResponse, result);
+ this.console.info(String.format("%n# Result was stored in a file: '%s'", pathToFileWithResponse));
+ }
+
+ private void logResultInfo(T result) {
+ this.console.info("\n# Operation result:\n");
+ this.console.info(result.toString());
+ }
+
+ private CommandResponse<T> processCommand(Args args, Command<T> command) throws CommandException {
+ this.console.info(String.format("# Executing a '%s' operation ...", command.getName()));
+ final CommandResponse<T> commandResponse = command.execute(args);
+ this.console.info("# ... Done.");
+ return commandResponse;
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Command.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Command.java
new file mode 100644
index 0000000..1da724f
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Command.java
@@ -0,0 +1,29 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.core;
+
+import org.onap.validation.yaml.util.Args;
+
+import java.nio.file.Path;
+
+public interface Command<T> {
+ CommandResponse<T> execute(Args args) throws CommandException;
+
+ String getName();
+
+ Path getOutputFilePath(Args args) throws CommandException;
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandException.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandException.java
new file mode 100644
index 0000000..2c72ff8
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandException.java
@@ -0,0 +1,27 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.core;
+
+public class CommandException extends Exception {
+ public CommandException(String msg) {
+ super(msg);
+ }
+
+ public CommandException(String msg, Exception ex) {
+ super(msg, ex);
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandResponse.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandResponse.java
new file mode 100644
index 0000000..73db4ab
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/CommandResponse.java
@@ -0,0 +1,48 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.core;
+
+public class CommandResponse<T> {
+
+ private final T result;
+ private final CommandStatus commandStatus;
+
+ public CommandResponse(T result, CommandStatus commandStatus) {
+ this.result = result;
+ this.commandStatus = commandStatus;
+ }
+
+ public T getResult() {
+ return result;
+ }
+
+ public CommandStatus getCommandStatus() {
+ return commandStatus;
+ }
+
+ public enum CommandStatus {
+ PASS, FAILED
+ }
+
+ @Override
+ public String toString() {
+ return "CommandResponse{" +
+ "result=" + result +
+ ", commandStatus=" + commandStatus +
+ '}';
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Console.java b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Console.java
new file mode 100644
index 0000000..4c20437
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/cli/core/Console.java
@@ -0,0 +1,41 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.core;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Console {
+
+ public static final Logger logger = LoggerFactory.getLogger(Console.class);
+
+ public void info(String msg) {
+ System.out.println(msg);
+ logger.info(msg);
+ }
+
+ public void error(Exception ex) {
+ System.err.println(ex.getMessage() + ", more information in log file.");
+ logger.error("Internal error", ex);
+ }
+
+ public void error(String msg) {
+ System.err.println(msg);
+ logger.error(msg);
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidate.java b/dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidate.java
new file mode 100644
index 0000000..c3b96b4
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidate.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2019 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.validation.rule;
+
+import com.google.gson.Gson;
+import org.onap.cli.fw.cmd.OnapCommand;
+import org.onap.cli.fw.error.OnapCommandException;
+import org.onap.cli.fw.output.OnapCommandResultType;
+import org.onap.cli.fw.schema.OnapCommandSchema;
+import org.onap.validation.cli.command.validate.ResponseModel;
+import org.onap.validation.cli.command.validate.ResponseModel.ResponseStatus;
+import org.onap.validation.cli.command.validate.ToJsonConverter;
+import org.onap.validation.cli.command.validate.ToResponseModelConverter;
+import org.onap.validation.cli.command.validate.ValidateDictionaryYamlCommand;
+import org.onap.validation.cli.core.CommandException;
+import org.onap.validation.cli.core.CommandResponse;
+import org.onap.validation.yaml.util.Args;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Validates CSAR
+ */
+@OnapCommandSchema(schema = "dictionary-validate.yaml")
+public class DictionaryValidate extends OnapCommand {
+
+ private static final String VALIDATION_PASS = "PASS";
+ private static final String VALIDATION_FAILED = "FAILED";
+ public static final String PARAM_IN_YAML = "yaml";
+ public static final String PARAM_OUT_FILE = "file";
+ public static final String PARAM_OUT_DATE = "date";
+ public static final String PARAM_OUT_CRITERIA = "criteria";
+ public static final String PARAM_OUT_ERRORS = "errors";
+ private final Gson gson = new Gson();
+
+ private static final Logger logger = LoggerFactory.getLogger(DictionaryValidate.class);
+
+ @Override
+ protected void run() throws OnapCommandException {
+
+ final Date timestamp = new Date();
+ final String yamlPath = (String) getParametersMap().get(PARAM_IN_YAML).getValue();
+
+ try {
+ final ResponseModel responseModel = executeValidation(yamlPath);
+ handleResponse(responseModel, timestamp);
+ } catch (CommandException e) {
+ handleError(timestamp, yamlPath, e);
+ }
+ }
+
+ private void handleResponse(ResponseModel responseModel, Date timestamp) {
+ setOclipResponse(responseModel.getFile(),
+ timestamp,
+ getCriteria(responseModel),
+ transformToJson(responseModel.getErrors())
+ );
+ }
+
+ private void handleError(Date validationTimestamp, String path, CommandException e) {
+ setOclipResponse(path,
+ validationTimestamp,
+ VALIDATION_FAILED,
+ transformToJson(e.getMessage())
+ );
+ logger.error("Internal application error", e);
+ }
+
+ private String getCriteria(ResponseModel responseModel) {
+ return responseModel.getStatus().equals(ResponseStatus.PASS) ? VALIDATION_PASS : VALIDATION_FAILED;
+ }
+
+ private <T> String transformToJson(T data) {
+ return gson.toJson(data);
+ }
+
+ private void setOclipResponse(String pathToFile, Date timestamp, String criteria, String errors) {
+ final DictionaryValidateResponse dictionaryValidateResponse = new DictionaryValidateResponse(
+ pathToFile,
+ timestamp.toString(),
+ criteria,
+ errors
+ );
+ setOclipResponse(dictionaryValidateResponse);
+ }
+
+ private void setOclipResponse(DictionaryValidateResponse dictionaryValidateResponse) {
+ this.getResult().getRecordsMap().get(PARAM_OUT_FILE).getValues().add(dictionaryValidateResponse.getFile());
+ this.getResult().getRecordsMap().get(PARAM_OUT_DATE).getValues().add(dictionaryValidateResponse.getDate());
+ this.getResult().getRecordsMap().get(PARAM_OUT_CRITERIA).getValues().add(dictionaryValidateResponse.getCriteria());
+ this.getResult().getRecordsMap().get(PARAM_OUT_ERRORS).getValues().add(dictionaryValidateResponse.getErrors());
+ this.getResult().setOutput(transformToJson(dictionaryValidateResponse));
+ this.getResult().setType(OnapCommandResultType.TEXT);
+ }
+
+ private ResponseModel executeValidation(String path) throws CommandException {
+ final ValidateDictionaryYamlCommand validation = new ValidateDictionaryYamlCommand(new ToJsonConverter());
+ final CommandResponse<String> commandResponse = validation.execute(new Args(List.of(path)));
+ final String result = commandResponse.getResult();
+
+ return ToResponseModelConverter.toModel(result);
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidateResponse.java b/dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidateResponse.java
new file mode 100644
index 0000000..684cf7b
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/rule/DictionaryValidateResponse.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.validation.rule;
+
+public class DictionaryValidateResponse {
+
+ public static final String PLATFORM_VTP_1_0 = "Dictionary Test Platform (VTP) 1.0";
+ public static final String ONAP_DISCUSS_LISTS_ONAP_ORG = "ONAP VTP Team onap-discuss@lists.onap.org";
+ private final String file;
+ private final String date;
+ private final String criteria;
+ private final String errors;
+
+ public DictionaryValidateResponse(String file, String date, String criteria, String errors) {
+ this.file = file;
+ this.date = date;
+ this.criteria = criteria;
+ this.errors = errors;
+ }
+
+ public String getFile() {
+ return file;
+ }
+
+ public String getDate() {
+ return date;
+ }
+
+ public String getContact() {
+ return ONAP_DISCUSS_LISTS_ONAP_ORG;
+ }
+
+ public String getPlatform() {
+ return PLATFORM_VTP_1_0;
+ }
+
+ public String getCriteria() {
+ return criteria;
+ }
+
+ public String getErrors() {
+ return errors;
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlContentValidator.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlContentValidator.java
new file mode 100644
index 0000000..4501113
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlContentValidator.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.onap.validation.yaml.schema.YamlSchema;
+import org.onap.validation.yaml.schema.YamlSchemaFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class YamlContentValidator {
+
+ private static final int FIRST_DOCUMENT_INDEX = 1;
+ private static final YamlLoader YAML_LOADER = new YamlLoader(new YamlDocumentFactory());
+
+ public List<YamlDocumentValidationError> validate(String pathToFile)
+ throws YamlProcessingException {
+ List<YamlDocument> documents = YAML_LOADER.loadMultiDocumentYamlFile(pathToFile);
+ return getYamlDocumentValidationErrors(documents);
+ }
+
+ public List<YamlDocumentValidationError> validate(byte[] yamlWithSchema)
+ throws YamlProcessingException {
+ List<YamlDocument> documents = YAML_LOADER.loadMultiDocumentYaml(yamlWithSchema);
+ return getYamlDocumentValidationErrors(documents);
+ }
+
+ private List<YamlDocumentValidationError> getYamlDocumentValidationErrors(List<YamlDocument> documents) throws YamlProcessingException {
+ if (documents.isEmpty()) {
+ throw new YamlProcessingException("Dictionary YAML file is empty");
+ } else {
+ return validateDocuments(documents);
+ }
+ }
+
+ private List<YamlDocumentValidationError> validateDocuments(List<YamlDocument> documents)
+ throws YamlProcessingException {
+
+ List<YamlDocumentValidationError> yamlFileValidationErrors = new ArrayList<>();
+ YamlSchema schema = extractSchema(documents);
+ YamlValidator validator = new YamlValidator(schema);
+
+ for (int index = FIRST_DOCUMENT_INDEX; index < documents.size(); index++) {
+ List<SchemaValidationError> validationErrors = validator.validate(documents.get(index));
+ yamlFileValidationErrors.addAll(transformErrors(index, validationErrors));
+ }
+
+ return yamlFileValidationErrors;
+ }
+
+ private List<YamlDocumentValidationError> transformErrors(int index, List<SchemaValidationError> validationErrors) {
+ return validationErrors
+ .stream()
+ .map(error -> new YamlDocumentValidationError(index, error.getPath(), error.getMessage()))
+ .collect(Collectors.toList());
+ }
+
+ private YamlSchema extractSchema(List<YamlDocument> documents) throws YamlProcessingException {
+ return new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java
new file mode 100644
index 0000000..c23da0a
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlLoader.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.yaml.snakeyaml.Yaml;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+class YamlLoader {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(YamlLoader.class);
+ private final YamlDocumentFactory documentFactory;
+
+ YamlLoader(YamlDocumentFactory documentFactory) {
+ this.documentFactory = documentFactory;
+ }
+
+ List<YamlDocument> loadMultiDocumentYaml(byte[] yamlWithSchema)
+ throws YamlDocumentFactory.YamlDocumentParsingException {
+ List<YamlDocument> documents = new ArrayList<>();
+ try (InputStream yamlStream = new ByteArrayInputStream(yamlWithSchema)) {
+ documents.addAll(loadMultiDocumentYaml(yamlStream));
+ } catch (IOException e) {
+ LOGGER.error("Failed to load multi document YAML", e);
+ }
+ return documents;
+ }
+
+ List<YamlDocument> loadMultiDocumentYamlFile(URL path)
+ throws YamlDocumentFactory.YamlDocumentParsingException {
+ List<YamlDocument> documents = new ArrayList<>();
+ try (InputStream yamlStream = path.openStream()) {
+ documents.addAll(loadMultiDocumentYaml(yamlStream));
+ } catch (IOException e) {
+ LOGGER.error("Failed to load multi document YAML file", e);
+ }
+ return documents;
+ }
+
+ List<YamlDocument> loadMultiDocumentYamlFile(String path)
+ throws YamlProcessingException {
+ try {
+ return loadMultiDocumentYamlFile(new URL("file://" + path));
+ } catch (MalformedURLException e) {
+ throw new YamlProcessingException("Fail to read file under given path.", e);
+ }
+ }
+
+ private List<YamlDocument> loadMultiDocumentYaml(InputStream yamlStream) throws YamlDocumentFactory.YamlDocumentParsingException {
+ List<YamlDocument> documents = new ArrayList<>();
+ for (Object yamlDocument : new Yaml().loadAll(yamlStream)) {
+ documents.add(documentFactory.createYamlDocument(yamlDocument));
+ }
+ return documents;
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java
new file mode 100644
index 0000000..30ba646
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/YamlValidator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.process.YamlValidationProcess;
+import org.onap.validation.yaml.schema.YamlSchema;
+
+import java.util.List;
+
+public class YamlValidator {
+
+ private final YamlSchema schema;
+
+ YamlValidator(YamlSchema schema) {
+ this.schema = schema;
+ }
+
+ public List<SchemaValidationError> validate(YamlDocument document) throws YamlProcessingException {
+ return new YamlValidationProcess(schema,document).validate();
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java
new file mode 100644
index 0000000..6ffe6d4
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/SchemaValidationError.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.error;
+
+public class SchemaValidationError {
+ private final String path;
+ private final String message;
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public SchemaValidationError(String path, String message) {
+ this.path = path;
+ this.message = message;
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java
new file mode 100644
index 0000000..f04708f
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/error/YamlDocumentValidationError.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.error;
+
+public class YamlDocumentValidationError {
+ private final int yamlDocumentNumber;
+ private final String path;
+ private final String message;
+
+ public YamlDocumentValidationError(int yamlDocumentNumber, String path, String message) {
+ this.yamlDocumentNumber = yamlDocumentNumber;
+ this.path = path;
+ this.message = message;
+ }
+
+ public int getYamlDocumentNumber() {
+ return yamlDocumentNumber;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java
new file mode 100644
index 0000000..99c2437
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/exception/YamlProcessingException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.exception;
+
+public class YamlProcessingException extends Exception {
+
+ public YamlProcessingException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+
+ public YamlProcessingException(String message) {
+ super(message);
+ }
+
+ public YamlProcessingException(Throwable throwable) {
+ super(throwable);
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java
new file mode 100644
index 0000000..557b6fd
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocument.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import java.util.Map;
+
+public class YamlDocument {
+
+ private final Map<String, Object> yaml;
+
+ YamlDocument(Map<String, Object> yaml) {
+ this.yaml = yaml;
+ }
+
+ public Map<String, Object> getYaml() {
+ return yaml;
+ }
+
+ public boolean containsKey(String key) {
+ return yaml.containsKey(key);
+ }
+
+ public String getValue(String key) {
+ return yaml.get(key).toString();
+ }
+
+ public YamlParametersList getListOfValues(String key) {
+ return new YamlParameterListFactory().createYamlParameterList(
+ yaml.get(key)
+ );
+ }
+
+ public YamlDocument getSubStructure(String name)
+ throws YamlDocumentFactory.YamlDocumentParsingException {
+ return new YamlDocumentFactory().createYamlDocument(
+ yaml.get(name)
+ );
+ }
+}
+
+
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java
new file mode 100644
index 0000000..b56422c
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlDocumentFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class YamlDocumentFactory {
+
+ public YamlDocument createYamlDocument(Object yaml) throws YamlDocumentParsingException {
+ try {
+ Map<String, Object> parsedYaml = transformMap((Map) yaml);
+ return new YamlDocument(parsedYaml);
+ } catch (ClassCastException e) {
+ throw new YamlDocumentParsingException(
+ String.format("Fail to parse given objects: %s as yaml document.", yaml), e
+ );
+ }
+ }
+
+ private Map<String, Object> transformMap(Map<Object, Object> yaml) {
+ Map<String, Object> parsedYaml = new HashMap<>();
+ for (Map.Entry<Object, Object> entry: yaml.entrySet()) {
+ parsedYaml.put(entry.getKey().toString(), entry.getValue());
+ }
+ return parsedYaml;
+ }
+
+ public static class YamlDocumentParsingException extends YamlProcessingException {
+ YamlDocumentParsingException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java
new file mode 100644
index 0000000..5f41c5c
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParameterListFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class YamlParameterListFactory {
+
+ public YamlParametersList createEmptyYamlParameterList() {
+ return new YamlParametersList(Collections.emptyList());
+ }
+
+ public YamlParametersList createYamlParameterList(Object yaml) {
+ List<String> parametersList = new ArrayList<>();
+ if( yaml instanceof List) {
+ for (Object element : (List) yaml) {
+ parametersList.add(element.toString());
+ }
+ } else {
+ parametersList.add(yaml.toString());
+ }
+ return new YamlParametersList(parametersList);
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java
new file mode 100644
index 0000000..2b93c74
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/model/YamlParametersList.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import java.util.List;
+
+public class YamlParametersList {
+
+ private final List<String> parameters;
+
+ YamlParametersList(List<String> parameters) {
+ this.parameters = parameters;
+ }
+
+ public List<String> getParameters() {
+ return parameters;
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java
new file mode 100644
index 0000000..ebd37ce
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationProcess.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.process;
+
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.YamlSchema;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+public class YamlValidationProcess {
+
+ private final Queue<YamlValidationStep> validationSteps;
+ private final List<SchemaValidationError> errors;
+ private final YamlSchema schema;
+ private final YamlDocument document;
+
+ public YamlValidationProcess(YamlSchema schema, YamlDocument document) {
+ this.schema = schema;
+ this.document = document;
+ errors = new ArrayList<>();
+ validationSteps = new LinkedList<>();
+ }
+
+ public List<SchemaValidationError> validate() throws YamlProcessingException {
+ validationSteps.add(new YamlValidationStep(schema.getRootNodes(), document));
+ while (!validationSteps.isEmpty()) {
+ YamlValidationStep nextValidationNode = validationSteps.poll();
+ validateStep(nextValidationNode);
+ }
+ return errors;
+ }
+
+ private void validateStep(YamlValidationStep validationNode)
+ throws YamlProcessingException {
+ for (YamlSchemaNode schemaNode : validationNode.getSchemaNodes()) {
+ validateNode(validationNode.getDocument(), schemaNode);
+ }
+ }
+
+ private void validateNode(YamlDocument document, YamlSchemaNode schemaNode)
+ throws YamlProcessingException {
+
+ if (document.containsKey(schemaNode.getName())) {
+ if (schemaNode.isContainingSubStructure()) {
+ addNextLevelNodeToValidationNodesQueue(document, schemaNode);
+ } else if (!isValueOfNodeInAcceptedValuesList(document, schemaNode)) {
+ addIncorrectValueError(document, schemaNode);
+ }
+ } else if (schemaNode.isRequired()) {
+ addRequiredKeyNotFoundError(schemaNode);
+ }
+ }
+
+ private boolean isValueOfNodeInAcceptedValuesList(YamlDocument document, YamlSchemaNode node) {
+ return node.getAcceptedValues().isEmpty() ||
+ node.getAcceptedValues().containsAll(
+ document.getListOfValues(node.getName()).getParameters()
+ );
+ }
+
+ private void addNextLevelNodeToValidationNodesQueue(YamlDocument document, YamlSchemaNode node)
+ throws YamlProcessingException {
+ validationSteps.add(
+ new YamlValidationStep(
+ node.getNextNodes(),
+ document.getSubStructure(node.getName())
+ )
+ );
+ }
+
+ private void addRequiredKeyNotFoundError(YamlSchemaNode node) {
+ errors.add(
+ new SchemaValidationError(
+ node.getPath(),
+ String.format("Key not found: %s", node.getName())
+ )
+ );
+ }
+
+ private void addIncorrectValueError(YamlDocument document, YamlSchemaNode node) {
+ errors.add(
+ new SchemaValidationError(
+ node.getPath() + node.getName(),
+ String.format(
+ "Value(s) is/are not in array of accepted values.%n value(s): %s%n accepted value(s): %s",
+ document.getValue(node.getName()), node.getAcceptedValues())
+ )
+ );
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java
new file mode 100644
index 0000000..eb5ab8e
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/process/YamlValidationStep.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.process;
+
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+class YamlValidationStep {
+
+ private final List<YamlSchemaNode> schemaNodes;
+ private final YamlDocument document;
+
+ YamlValidationStep(List<YamlSchemaNode> nodes, YamlDocument yaml) {
+ this.schemaNodes = new ArrayList<>(nodes);
+ this.document = yaml;
+ }
+
+ List<YamlSchemaNode> getSchemaNodes() {
+ return Collections.unmodifiableList(schemaNodes);
+ }
+
+ YamlDocument getDocument() {
+ return document;
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java
new file mode 100644
index 0000000..69bb6cd
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchema.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema;
+
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class YamlSchema {
+
+ private final List<YamlSchemaNode> rootNodes;
+
+ public List<YamlSchemaNode> getRootNodes() {
+ return Collections.unmodifiableList(rootNodes);
+ }
+
+ YamlSchema(List<YamlSchemaNode> rootNodes) {
+ this.rootNodes = new ArrayList<>(rootNodes);
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java
new file mode 100644
index 0000000..df7d673
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/YamlSchemaFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.onap.validation.yaml.schema;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+import org.onap.validation.yaml.schema.node.YamlSchemaNodeFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class YamlSchemaFactory {
+
+
+ private static final String ROOT_PATH = "/";
+
+ public YamlSchema createTreeStructuredYamlSchema(YamlDocument schema)
+ throws YamlProcessingException {
+
+ return new YamlSchema(getRootNodes(schema));
+ }
+
+ private List<YamlSchemaNode> getRootNodes(YamlDocument yamlDocument)
+ throws YamlProcessingException {
+
+ List<YamlSchemaNode> nextNodes = new ArrayList<>();
+ for(String nodeName: yamlDocument.getYaml().keySet()) {
+ nextNodes.add(
+ new YamlSchemaNodeFactory().createNode(
+ nodeName,
+ ROOT_PATH,
+ new YamlDocumentFactory().createYamlDocument(
+ yamlDocument.getYaml().get(nodeName)
+ )
+ )
+ );
+ }
+ return nextNodes;
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java
new file mode 100644
index 0000000..a3e9636
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaBranchNode.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class YamlSchemaBranchNode extends YamlSchemaNode {
+
+ private final YamlDocument nextNodesInLazyForm;
+ private List<YamlSchemaNode> nextNodes = Collections.emptyList();
+
+ YamlSchemaBranchNode(String name, String path, boolean required, String comment,
+ YamlDocument nextNodesInLazyForm) {
+ super(name, path, required, comment);
+ this.nextNodesInLazyForm = nextNodesInLazyForm;
+ }
+
+ @Override
+ public boolean isContainingSubStructure() {
+ return true;
+ }
+
+ @Override
+ public List<String> getAcceptedValues() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public synchronized List<YamlSchemaNode> getNextNodes() throws YamlSchemaProcessingException {
+ try {
+ return nextNodes.isEmpty() ? this.loadNextNodes() : nextNodes;
+ } catch (YamlSchemaLazyLoadingException lazyLoadingException) {
+ throw new YamlSchemaProcessingException(lazyLoadingException);
+ }
+ }
+
+ private List<YamlSchemaNode> loadNextNodes() {
+ try {
+ List<YamlSchemaNode> loadedNextNodes = new ArrayList<>();
+ for (String key : nextNodesInLazyForm.getYaml().keySet()) {
+ YamlDocument substructure = new YamlDocumentFactory()
+ .createYamlDocument(nextNodesInLazyForm.getYaml().get(key));
+ loadedNextNodes.add(new YamlSchemaNodeFactory().createNode(key, getPath() + getName() + "/", substructure));
+ }
+ nextNodes = loadedNextNodes;
+ return loadedNextNodes;
+ } catch (YamlProcessingException e) {
+ throw new YamlSchemaLazyLoadingException("Lazy loading failed, due to yaml parsing exception.",e);
+ }
+ }
+
+ static class YamlSchemaLazyLoadingException extends RuntimeException {
+ YamlSchemaLazyLoadingException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java
new file mode 100644
index 0000000..c98f41e
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaLeafNode.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.model.YamlParametersList;
+
+import java.util.Collections;
+import java.util.List;
+
+public class YamlSchemaLeafNode extends YamlSchemaNode {
+
+ private final YamlParametersList acceptedValues;
+
+ YamlSchemaLeafNode(String name, String path, boolean required, String comment,
+ YamlParametersList acceptedValues) {
+ super(name, path, required, comment);
+ this.acceptedValues = acceptedValues;
+ }
+
+ @Override
+ public List<String> getAcceptedValues() {
+ return acceptedValues.getParameters();
+ }
+
+ @Override
+ public List<YamlSchemaNode> getNextNodes() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isContainingSubStructure() {
+ return false;
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java
new file mode 100644
index 0000000..28913a2
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNode.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+
+import java.util.List;
+
+public abstract class YamlSchemaNode {
+
+ private final String path;
+ private final String name;
+ private final boolean required;
+ private final String comment;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public abstract List<String> getAcceptedValues();
+
+ public abstract List<YamlSchemaNode> getNextNodes() throws YamlSchemaProcessingException;
+
+ public abstract boolean isContainingSubStructure();
+
+ public String getComment() {
+ return comment;
+ }
+
+ YamlSchemaNode(String name, String path, boolean required, String comment) {
+ this.name = name;
+ this.path = path;
+ this.required = required;
+ this.comment = comment;
+ }
+
+ static class YamlSchemaProcessingException extends YamlProcessingException {
+ YamlSchemaProcessingException(Throwable throwable) {
+ super(throwable);
+ }
+ }
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java
new file mode 100644
index 0000000..79a8f14
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactory.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.onap.validation.yaml.model.YamlParameterListFactory;
+import org.onap.validation.yaml.model.YamlParametersList;
+
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+
+public class YamlSchemaNodeFactory {
+
+ public static final String EMPTY_COMMENT = "no comment available";
+ static final String STRUCTURE_KEY = "structure";
+ static final String COMMENT_KEY = "comment";
+ static final String VALUE_KET = "value";
+ static final String PRESENCE_KEY = "presence";
+ static final String PRESENCE_REQUIRED_KEY = "required";
+
+ public YamlSchemaNode createNode(String nodeName, String path, YamlDocument yamlDocument)
+ throws YamlProcessingException {
+
+ YamlSchemaNode yamlSchemaNode;
+ if(isYamlContainingKey(yamlDocument, STRUCTURE_KEY)) {
+ yamlSchemaNode = new YamlSchemaBranchNode(
+ nodeName, path, getIsPresenceRequired(yamlDocument), getComment(yamlDocument),
+ getNextNodes(yamlDocument)
+ );
+ } else {
+ yamlSchemaNode = new YamlSchemaLeafNode(
+ nodeName, path, getIsPresenceRequired(yamlDocument), getComment(yamlDocument),
+ getAcceptedValues(yamlDocument)
+ );
+ }
+ return yamlSchemaNode;
+ }
+
+ private YamlDocument getNextNodes(YamlDocument yamlDocument)
+ throws YamlDocumentParsingException {
+ return new YamlDocumentFactory().createYamlDocument(yamlDocument.getYaml().get(STRUCTURE_KEY));
+ }
+
+ private String getComment(YamlDocument yamlDocument) {
+
+ return isYamlContainingKey(yamlDocument, COMMENT_KEY)
+ ? yamlDocument.getYaml().get(COMMENT_KEY).toString()
+ : EMPTY_COMMENT;
+ }
+
+ private YamlParametersList getAcceptedValues(YamlDocument yamlDocument) {
+
+ return isYamlContainingKey(yamlDocument, VALUE_KET)
+ ? new YamlParameterListFactory().createYamlParameterList(yamlDocument.getYaml().get(VALUE_KET))
+ : new YamlParameterListFactory().createEmptyYamlParameterList();
+ }
+
+ private boolean getIsPresenceRequired(YamlDocument yamlDocument) {
+
+ return isYamlContainingKey(yamlDocument, PRESENCE_KEY)
+ && yamlDocument.getYaml().get(PRESENCE_KEY).equals(PRESENCE_REQUIRED_KEY);
+ }
+
+ private boolean isYamlContainingKey(YamlDocument yamlDocument, String structureKey) {
+ return yamlDocument.getYaml().containsKey(structureKey);
+ }
+
+}
diff --git a/dictionaryvalidation/src/main/java/org/onap/validation/yaml/util/Args.java b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/util/Args.java
new file mode 100644
index 0000000..9ae44c8
--- /dev/null
+++ b/dictionaryvalidation/src/main/java/org/onap/validation/yaml/util/Args.java
@@ -0,0 +1,36 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.yaml.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Args {
+
+ private final List<String> data;
+
+ public Args(List<String> data) {
+ this.data = new ArrayList<>(data);
+ }
+
+ public String getArg(int index) {
+ if (this.data.size() <= index) {
+ throw new IllegalArgumentException(String.format("Argument with index %d is not available!", index));
+ }
+ return this.data.get(index);
+ }
+}
diff --git a/dictionaryvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand b/dictionaryvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand
new file mode 100644
index 0000000..9d1b8a2
--- /dev/null
+++ b/dictionaryvalidation/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand
@@ -0,0 +1,15 @@
+# Copyright 2020 Nokia
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+org.onap.validation.rule.DictionaryValidate
diff --git a/dictionaryvalidation/src/main/resources/log4j2.properties b/dictionaryvalidation/src/main/resources/log4j2.properties
new file mode 100644
index 0000000..8ef4de1
--- /dev/null
+++ b/dictionaryvalidation/src/main/resources/log4j2.properties
@@ -0,0 +1,56 @@
+# Copyright Nokia 2020
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# By default, log4j2 will look for a configuration file named log4j2.xml on the classpath.
+# reference: https://logging.apache.org/log4j/2.x/faq.html#troubleshooting
+
+
+status = error
+dest = err
+name = PropertiesConfig
+
+property.filename = ./dictionary-validate.log
+
+filter.threshold.type = ThresholdFilter
+filter.threshold.level = debug
+
+appender.console.type = Console
+appender.console.name = STDOUT
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %m%n
+appender.console.filter.threshold.type = ThresholdFilter
+appender.console.filter.threshold.level = error
+
+appender.rolling.type = RollingFile
+appender.rolling.name = RollingFile
+appender.rolling.fileName = ${filename}
+appender.rolling.filePattern = ./dictionary-validate.%d{yyyy-MM-dd-HH:mm:ss}.log
+appender.rolling.layout.type = PatternLayout
+appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n
+appender.rolling.policies.type = Policies
+appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
+appender.rolling.policies.time.interval = 2
+appender.rolling.policies.time.modulate = true
+appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
+appender.rolling.policies.size.size=5MB
+appender.rolling.strategy.type = DefaultRolloverStrategy
+appender.rolling.strategy.max = 5
+
+logger.rolling.name = org.onap.validation
+logger.rolling.level = debug
+logger.rolling.additivity = false
+logger.rolling.appenderRef.rolling.ref = RollingFile
+
+rootLogger.level = info
+rootLogger.appenderRef.stdout.ref = STDOUT
diff --git a/dictionaryvalidation/src/main/resources/open-cli-schema/dictionary-validate.yaml b/dictionaryvalidation/src/main/resources/open-cli-schema/dictionary-validate.yaml
new file mode 100644
index 0000000..1f5801d
--- /dev/null
+++ b/dictionaryvalidation/src/main/resources/open-cli-schema/dictionary-validate.yaml
@@ -0,0 +1,63 @@
+# Copyright 2020 Nokia
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+open_cli_schema_version: 1.0
+
+name: dictionary-validate
+
+description: Validate Dictionary Yaml file
+
+info:
+ product: onap-honolulu
+ version: 1.0
+ service: vnf-compliance
+ author: ONAP VTP Team onap-discuss@lists.onap.org
+
+parameters:
+ - name: yaml
+ description: Yaml file path
+ long_option: yaml
+ short_option: b
+ type: binary
+ is_optional: false
+
+results:
+ direction: portrait
+ attributes:
+ - name: file
+ description: Dictionary Yaml file
+ scope: short
+ type: string
+ - name: date
+ description: Validation date
+ scope: short
+ type: string
+ - name: platform
+ description: Platform used to test the reqs
+ scope: short
+ type: string
+ default_value: Dictionary Test Platform (VTP) 1.0
+ - name: contact
+ description: Owner for this test case
+ scope: short
+ type: string
+ default_value: ONAP VTP Team onap-discuss@lists.onap.org
+ - name: criteria
+ description: Overall test reqs passed? PASS or FAILED
+ scope: short
+ type: string
+ - name: errors
+ description: All test cases errors
+ scope: short
+ type: json
diff --git a/dictionaryvalidation/src/test/java/org/onap/functional/DictionaryValidateRuleFunctionalTest.java b/dictionaryvalidation/src/test/java/org/onap/functional/DictionaryValidateRuleFunctionalTest.java
new file mode 100644
index 0000000..2d2c542
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/functional/DictionaryValidateRuleFunctionalTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2020 Nokia
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.functional;
+
+import org.junit.Test;
+import org.onap.functional.util.OnapCliWrapper;
+import org.onap.validation.rule.DictionaryValidate;
+import org.onap.validation.rule.DictionaryValidateResponse;
+
+import java.net.URISyntaxException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.onap.functional.util.ValidationUtility.OPERATION_STATUS_FAILED;
+import static org.onap.functional.util.ValidationUtility.OPERATION_STATUS_PASS;
+import static org.onap.functional.util.ValidationUtility.getCliCommandValidationResult;
+import static org.onap.functional.util.ValidationUtility.verifyThatOperationFinishedWithError;
+import static org.onap.functional.util.ValidationUtility.verifyThatOperationFinishedWithoutAnyError;
+
+
+public class DictionaryValidateRuleFunctionalTest {
+
+
+ private static final String YAML_SCHEMA_SIMPLE_VALID_SCHEMA_YAML = "yaml_schema/Simple_Valid_Schema.yaml";
+ private static final String YAML_CUSTOM_SCHEMA_SIMPLE_VALID_SCHEMA_YAML = "yaml_schema/Custom_Valid_Dictionary.yaml";
+ private static final String YAML_CUSTOM_SCHEMA_SIMPLE_INVALID_SCHEMA_YAML = "yaml_schema/Custom_Invalid_Dictionary.yaml";
+ private static final String NO_ERRORS = "[]";
+ private static final String YAML_SCHEMA_PM_DICTIONARY_YAML = "yaml_schema/PM_Dictionary.yaml";
+ private static final String PATH_TO_NON_EXITING_FILE_YAML = "path/to/nonExitingFile.yaml";
+ private static final String NOT_YAML_FILE_TXT = "Not_Yaml_File.txt";
+
+ @Test
+ public void shouldSuccessfullyValidatePMDictionaryYamlFile() throws URISyntaxException {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo(YAML_SCHEMA_SIMPLE_VALID_SCHEMA_YAML));
+
+ // when
+ cli.handle();
+
+ // then
+ final DictionaryValidateResponse result = getCliCommandValidationResult(cli, DictionaryValidateResponse.class);
+
+ assertThat(result.getFile()).contains(YAML_SCHEMA_SIMPLE_VALID_SCHEMA_YAML);
+ assertThat(result.getPlatform()).contains(DictionaryValidateResponse.PLATFORM_VTP_1_0);
+ assertThat(result.getContact()).contains(DictionaryValidateResponse.ONAP_DISCUSS_LISTS_ONAP_ORG);
+ assertThat(result.getCriteria()).isEqualTo(OPERATION_STATUS_PASS);
+ assertThat(result.getErrors()).isEqualTo(NO_ERRORS);
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ @Test
+ public void shouldSuccessfullyValidateCustomDictionaryYamlFile() throws URISyntaxException {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo(YAML_CUSTOM_SCHEMA_SIMPLE_VALID_SCHEMA_YAML));
+
+ // when
+ cli.handle();
+
+ // then
+ final DictionaryValidateResponse result = getCliCommandValidationResult(cli, DictionaryValidateResponse.class);
+
+ assertThat(result.getFile()).contains(YAML_CUSTOM_SCHEMA_SIMPLE_VALID_SCHEMA_YAML);
+ assertThat(result.getPlatform()).contains(DictionaryValidateResponse.PLATFORM_VTP_1_0);
+ assertThat(result.getContact()).contains(DictionaryValidateResponse.ONAP_DISCUSS_LISTS_ONAP_ORG);
+ assertThat(result.getCriteria()).isEqualTo(OPERATION_STATUS_PASS);
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ @Test
+ public void shouldFailWhileValidatingCustomDictionaryYamlFileWithEerror() throws URISyntaxException {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo(YAML_CUSTOM_SCHEMA_SIMPLE_INVALID_SCHEMA_YAML));
+
+ // when
+ cli.handle();
+
+ // then
+ final DictionaryValidateResponse result = getCliCommandValidationResult(cli, DictionaryValidateResponse.class);
+
+ assertThat(result.getFile()).contains(YAML_CUSTOM_SCHEMA_SIMPLE_INVALID_SCHEMA_YAML);
+ assertThat(result.getPlatform()).contains(DictionaryValidateResponse.PLATFORM_VTP_1_0);
+ assertThat(result.getContact()).contains(DictionaryValidateResponse.ONAP_DISCUSS_LISTS_ONAP_ORG);
+ assertThat(result.getCriteria()).isEqualTo(OPERATION_STATUS_FAILED);
+ final String errors = result.getErrors();
+ assertThat(errors).contains(
+ "Value(s) is/are not in array of accepted values.",
+ "accepted value(s): [X, Y, Z]",
+ "accepted value(s): [3, 30, 33]",
+ "Key not found: field2"
+ );
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ @Test
+ public void shouldFailsWhenPMDictionaryYamlFileHasSomeErrors() throws URISyntaxException {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo(YAML_SCHEMA_PM_DICTIONARY_YAML));
+
+ // when
+ cli.handle();
+
+ // then
+ final DictionaryValidateResponse result = getCliCommandValidationResult(cli, DictionaryValidateResponse.class);
+
+ assertThat(result.getFile()).contains(YAML_SCHEMA_PM_DICTIONARY_YAML);
+ assertThat(result.getPlatform()).contains(DictionaryValidateResponse.PLATFORM_VTP_1_0);
+ assertThat(result.getContact()).contains(DictionaryValidateResponse.ONAP_DISCUSS_LISTS_ONAP_ORG);
+ assertThat(result.getCriteria()).isEqualTo(OPERATION_STATUS_FAILED);
+ final String errors = result.getErrors();
+ assertThat(errors).contains(
+ "Value(s) is/are not in array of accepted values.",
+ "accepted value(s): [float, uint32, uint64]",
+ "Key not found: measChangeType",
+ "accepted value(s): [X, Y, Z]"
+ );
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+ @Test
+ public void shouldReportAnErrorWhenYamlFileDoesNotExist() {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(new String[]{PATH_TO_NON_EXITING_FILE_YAML});
+
+ // when
+ cli.handle();
+
+ verifyThatOperationFinishedWithError(cli);
+ }
+
+
+ @Test
+ public void shouldReportThatValidationFailedWithInternalError() throws URISyntaxException {
+ // given
+ OnapCliWrapper cli = new OnapCliWrapper(createPnfValidationRequestInfo(NOT_YAML_FILE_TXT));
+
+ // when
+ cli.handle();
+
+ // then
+ final DictionaryValidateResponse result = getCliCommandValidationResult(cli, DictionaryValidateResponse.class);
+
+ assertThat(result.getFile()).contains(NOT_YAML_FILE_TXT);
+ assertThat(result.getPlatform()).contains(DictionaryValidateResponse.PLATFORM_VTP_1_0);
+ assertThat(result.getContact()).contains(DictionaryValidateResponse.ONAP_DISCUSS_LISTS_ONAP_ORG);
+ assertThat(result.getCriteria()).isEqualTo(OPERATION_STATUS_FAILED);
+ assertThat(result.getErrors()).contains("Provided yaml file has invalid structure!");
+ verifyThatOperationFinishedWithoutAnyError(cli);
+ }
+
+
+ private String[] createPnfValidationRequestInfo(String yamlPath) throws URISyntaxException {
+ return new String[]{
+ "--product", "onap-honolulu",
+ "dictionary-validate",
+ "--format", "json",
+ "--yaml", absoluteFilePath(yamlPath)
+ };
+ }
+
+
+ public static String absoluteFilePath(String relativeFilePath) throws URISyntaxException {
+ return DictionaryValidate.class.getClassLoader().getResource(relativeFilePath)
+ .toURI().getPath();
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/functional/util/OnapCliWrapper.java b/dictionaryvalidation/src/test/java/org/onap/functional/util/OnapCliWrapper.java
new file mode 100644
index 0000000..347a7bb
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/functional/util/OnapCliWrapper.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2020 Nokia
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.functional.util;
+
+
+import org.onap.cli.fw.cmd.OnapCommand;
+import org.onap.cli.fw.error.OnapCommandException;
+import org.onap.cli.fw.output.OnapCommandResult;
+import org.onap.cli.main.OnapCli;
+
+public class OnapCliWrapper extends OnapCli {
+
+ private OnapCommandResult commandResult;
+
+ public OnapCliWrapper(String[] args) {
+ super(args);
+ }
+
+ @Override
+ public void handleTracking(OnapCommand cmd) throws OnapCommandException {
+ super.handleTracking(cmd);
+ this.commandResult = cmd.getResult();
+ }
+
+ public OnapCommandResult getCommandResult() {
+ return this.commandResult;
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/functional/util/ValidationUtility.java b/dictionaryvalidation/src/test/java/org/onap/functional/util/ValidationUtility.java
new file mode 100644
index 0000000..3a497f4
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/functional/util/ValidationUtility.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020 Nokia
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onap.functional.util;
+
+import com.google.gson.Gson;
+import org.onap.cli.fw.output.OnapCommandResult;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+public final class ValidationUtility {
+
+ private static final int NO_ERROR_CODE = 0;
+ public static final int ERROR_CODE = 1;
+
+ private ValidationUtility(){}
+
+ public static final String OPERATION_STATUS_PASS = "PASS";
+ public static final String OPERATION_STATUS_FAILED = "FAILED";
+
+ public static <T> T getCliCommandValidationResult(OnapCliWrapper cli, Class<T> clazz) {
+ final OnapCommandResult onapCommandResult = cli.getCommandResult();
+ final String json = onapCommandResult.getOutput().toString();
+ return new Gson().fromJson(json, clazz);
+ }
+
+ public static void verifyThatOperationFinishedWithoutAnyError(OnapCliWrapper cli) {
+ assertThat(cli.getExitCode()).isEqualTo(NO_ERROR_CODE);
+ }
+
+ public static void verifyThatOperationFinishedWithError(OnapCliWrapper cli) {
+ assertThat(cli.getExitCode()).isEqualTo(ERROR_CODE);
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/cli/MainCITest.java b/dictionaryvalidation/src/test/java/org/onap/validation/cli/MainCITest.java
new file mode 100644
index 0000000..307d388
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/cli/MainCITest.java
@@ -0,0 +1,144 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli;
+
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.validation.cli.command.validate.OutputFilePathGenerator;
+import org.onap.validation.cli.command.validate.ResponseModel;
+import org.onap.validation.cli.command.validate.ResponseStorage;
+import org.onap.validation.cli.core.Cli;
+import org.onap.validation.cli.core.CommandException;
+import org.onap.validation.cli.core.Console;
+import org.onap.validation.cli.command.validate.ToResponseModelConverter;
+import org.onap.validation.yaml.YamlLoadingUtils;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+@ExtendWith(MockitoExtension.class)
+class MainCITest {
+
+ public static final int JSON_RESPONSE_INDEX = 3;
+ public static final int OPERATION_INFO_MSG_INDEX = 5;
+ public static final int NO_ERROR = 0;
+ @Mock
+ private Console console;
+ @Mock
+ private ResponseStorage responseStorage;
+ private final OutputFilePathGenerator filePathGenerator = new OutputFilePathGenerator();
+
+ @Test
+ void shouldReportThatPathToFileWasNotProvided() {
+ // when
+ final int statusCode = Main.run(new String[0], console, responseStorage);
+
+ // then
+ assertThat(statusCode).isEqualTo(Cli.INTERNAL_ERROR_STATUS_CODE);
+ final ArgumentCaptor<CommandException> exceptionCaptor = ArgumentCaptor.forClass(CommandException.class);
+ verify(console).error(exceptionCaptor.capture());
+ verify(console).error(Cli.APPLICATION_INTERNAL_ERROR_MSG);
+ assertThat(exceptionCaptor.getValue().getMessage()).isEqualTo("Command argument is missing: provide a path to file");
+
+ }
+
+ @Test
+ void shouldReportThatFileDoseNotExist() throws IOException {
+ // when
+ final String pathToYaml = "/path/to/nonExisting.yaml";
+ final int statusCode = Main.run(new String[]{pathToYaml}, console, new ResponseStorage());
+
+ // then
+ assertThat(statusCode).isEqualTo(Cli.INTERNAL_ERROR_STATUS_CODE);
+ final ArgumentCaptor<CommandException> exceptionCaptor = ArgumentCaptor.forClass(CommandException.class);
+ verify(console).error(exceptionCaptor.capture());
+ verify(console).error(Cli.APPLICATION_INTERNAL_ERROR_MSG);
+ assertThat(exceptionCaptor.getValue().getMessage()).isEqualTo("File '/path/to/nonExisting.yaml' does not exist!");
+ verify(responseStorage, never()).store(eq(Path.of(pathToYaml)), anyString());
+ }
+
+ @Test
+ void shouldReportThatFileIsBroken() throws IOException {
+ // when
+ final String pathToFile = YamlLoadingUtils.getUrlForGivenPath("Not_Yaml_File.txt").getPath();
+ final int statusCode = Main.run(new String[]{pathToFile}, console, new ResponseStorage());
+
+ // then
+ assertThat(statusCode).isEqualTo(Cli.INTERNAL_ERROR_STATUS_CODE);
+ final ArgumentCaptor<CommandException> exceptionCaptor = ArgumentCaptor.forClass(CommandException.class);
+ verify(console).error(exceptionCaptor.capture());
+ verify(console).error(Cli.APPLICATION_INTERNAL_ERROR_MSG);
+ assertThat(exceptionCaptor.getValue().getMessage()).isEqualTo("Provided yaml file has invalid structure!");
+ verify(responseStorage, never()).store(eq(Path.of(pathToFile)), anyString());
+ }
+
+ @Test
+ void shouldValidateProperYamlFile() throws IOException {
+ // when
+ final String path = YamlLoadingUtils.getUrlForGivenPath(YamlLoadingUtils.PATH_TO_SIMPLE_VALID_SCHEMA).getPath();
+ final int statusCode = Main.run(new String[]{path}, console, responseStorage);
+
+ // then
+ assertThat(statusCode).isEqualTo(Cli.PASS_STATUS_CODE);
+ assertThatResponseWasLoggedAtConsole(
+ path,
+ ResponseModel.ResponseStatus.PASS,
+ NO_ERROR
+ );
+ }
+
+ @Test
+ void shouldValidateYamlWithErrors() throws IOException {
+ // when
+ final String path = YamlLoadingUtils.getUrlForGivenPath(YamlLoadingUtils.PATH_TO_YAML_WITH_WRONG_VALUES).getPath();
+ final int statusCode = Main.run(new String[]{path}, console, responseStorage);
+
+ // then
+ assertThat(statusCode).isEqualTo(Cli.FAILED_STATUS_CODE);
+ assertThatResponseWasLoggedAtConsole(
+ path,
+ ResponseModel.ResponseStatus.FAILED,
+ 4
+ );
+ }
+
+ private void assertThatResponseWasLoggedAtConsole(String pathToFile, ResponseModel.ResponseStatus responseStatus, int expectedErrors) throws IOException {
+ ArgumentCaptor<String> consoleInfoCaptor = ArgumentCaptor.forClass(String.class);
+ verify(console, times(6)).info(consoleInfoCaptor.capture());
+ final List<String> allValues = consoleInfoCaptor.getAllValues();
+ final String json = allValues.get(JSON_RESPONSE_INDEX);
+ final ResponseModel responseModel = ToResponseModelConverter.toModel(json);
+ assertThat(responseModel.getFile()).isEqualTo(pathToFile);
+ assertThat(responseModel.getStatus()).isEqualTo(responseStatus);
+ assertThat(responseModel.getErrors()).hasSize(expectedErrors);
+ assertThat(consoleInfoCaptor.getAllValues().get(OPERATION_INFO_MSG_INDEX)).isEqualTo(Cli.APPLICATION_EXIT_SUCCESSFULLY_MSG);
+ verify(responseStorage).store(eq(filePathGenerator.responsePathFor(Path.of(pathToFile))), eq(json));
+ }
+
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/OutputFilePathGeneratorTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/OutputFilePathGeneratorTest.java
new file mode 100644
index 0000000..b4d68b4
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/OutputFilePathGeneratorTest.java
@@ -0,0 +1,43 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import org.junit.jupiter.api.Test;
+
+import java.nio.file.Path;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+class OutputFilePathGeneratorTest {
+
+ private final OutputFilePathGenerator filePathGenerator = new OutputFilePathGenerator();
+
+ @Test
+ void shouldReturnPathToFileWithResponse() {
+ // given
+ final Path pathToYaml = Path.of("/some/path/PMDictionary.yaml");
+ final Path expected = Path.of("/some/path/PMDictionary-validation-results.json");
+
+ // when
+ final Path actual = filePathGenerator.responsePathFor(pathToYaml);
+
+ // then
+ assertThat(actual).isEqualTo(expected);
+ }
+
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ToJsonConverterTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ToJsonConverterTest.java
new file mode 100644
index 0000000..06a15bb
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ToJsonConverterTest.java
@@ -0,0 +1,70 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import org.junit.jupiter.api.Test;
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.onap.validation.cli.command.validate.ToResponseModelConverter.toModel;
+
+
+class ToJsonConverterTest {
+
+ private static final String PATH_TO_TEST_YAML = "/path/to/test.yaml";
+ private final ToJsonConverter toJsonConverter = new ToJsonConverter();
+
+ @Test
+ void shouldConvertEmptyArray() {
+ // given
+ final ResponseModel responseModel = new ResponseModel(PATH_TO_TEST_YAML,
+ ResponseModel.ResponseStatus.PASS,
+ List.of());
+
+ // when
+ String json = toJsonConverter.convert(responseModel);
+
+ // then
+ ResponseModel actual = toModel(json);
+ assertThat(actual.getFile()).isEqualTo(PATH_TO_TEST_YAML);
+ assertThat(actual.getStatus()).isEqualTo(ResponseModel.ResponseStatus.PASS);
+ assertThat(actual.getErrors()).isEmpty();
+ }
+
+
+ @Test
+ void shouldConvertListOfErrors() {
+ // given
+ final ResponseModel responseModel = new ResponseModel(PATH_TO_TEST_YAML,
+ ResponseModel.ResponseStatus.FAILED,
+ List.of(
+ new YamlDocumentValidationError(1, PATH_TO_TEST_YAML, "error1"),
+ new YamlDocumentValidationError(2, PATH_TO_TEST_YAML, "error2")));
+
+ // when
+ String json = toJsonConverter.convert(responseModel);
+
+ // then
+
+ ResponseModel actual = toModel(json);
+ assertThat(actual.getFile()).isEqualTo(PATH_TO_TEST_YAML);
+ assertThat(actual.getStatus()).isEqualTo(ResponseModel.ResponseStatus.FAILED);
+ assertThat(actual.getErrors()).hasSize(2);
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ValidateYamlCommandTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ValidateYamlCommandTest.java
new file mode 100644
index 0000000..9d651ad
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/cli/command/validate/ValidateYamlCommandTest.java
@@ -0,0 +1,96 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.command.validate;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.validation.cli.core.CommandException;
+import org.onap.validation.cli.core.CommandResponse;
+import org.onap.validation.yaml.YamlLoadingUtils;
+import org.onap.validation.yaml.util.Args;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.onap.validation.cli.command.validate.ToResponseModelConverter.toModel;
+
+@ExtendWith(MockitoExtension.class)
+class ValidateYamlCommandTest {
+
+ private final ToJsonConverter toJsonConverter = new ToJsonConverter();
+ private ValidateDictionaryYamlCommand validateYamlCommand;
+
+ @BeforeEach
+ void setUp() {
+ this.validateYamlCommand = new ValidateDictionaryYamlCommand(toJsonConverter);
+ }
+
+ @Test
+ void shouldReportAnErrorWhenFileDoesNotExist() {
+ // given
+ Args args = new Args(List.of("/invalid/filePath/toValidate.yaml"));
+
+ // when
+ assertThatThrownBy(() -> validateYamlCommand.execute(args)).hasMessage("File '/invalid/filePath/toValidate.yaml' does not exist!");
+ }
+
+ @Test
+ void shouldReportAnErrorWhenPathToFileWasNotPass() {
+ // given
+ Args args = new Args(List.of());
+
+ // when
+ assertThatThrownBy(() -> validateYamlCommand.execute(args)).hasMessage("Command argument is missing: provide a path to file");
+ }
+
+ @Test
+ void shouldValidateFileWithoutAnyError() throws CommandException {
+ // given
+ final String path = YamlLoadingUtils.getUrlForGivenPath(YamlLoadingUtils.PATH_TO_SIMPLE_VALID_SCHEMA).getPath();
+ Args args = new Args(List.of(path));
+
+ // when
+ final CommandResponse<String> commandResponse = validateYamlCommand.execute(args);
+
+ // then
+ assertThat(commandResponse.getCommandStatus()).isEqualTo(CommandResponse.CommandStatus.PASS);
+ ResponseModel actual = toModel(commandResponse.getResult());
+ assertThat(actual.getFile()).isEqualTo(path);
+ assertThat(actual.getStatus()).isEqualTo(ResponseModel.ResponseStatus.PASS);
+ assertThat(actual.getErrors()).isEmpty();
+ }
+
+ @Test
+ void shouldReportThatFileHasSomeErrors() throws CommandException {
+ // given
+ final String path = YamlLoadingUtils.getUrlForGivenPath(YamlLoadingUtils.PATH_TO_YAML_WITH_WRONG_VALUES).getPath();
+ Args args = new Args(List.of(path));
+
+ // when
+ final CommandResponse<String> commandResponse = validateYamlCommand.execute(args);
+
+ // then
+ assertThat(commandResponse.getCommandStatus()).isEqualTo(CommandResponse.CommandStatus.FAILED);
+ ResponseModel actual = toModel(commandResponse.getResult());
+ assertThat(actual.getFile()).isEqualTo(path);
+ assertThat(actual.getStatus()).isEqualTo(ResponseModel.ResponseStatus.FAILED);
+ assertThat(actual.getErrors()).hasSize(4);
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/cli/core/CliTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/cli/core/CliTest.java
new file mode 100644
index 0000000..c8ad629
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/cli/core/CliTest.java
@@ -0,0 +1,101 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.cli.core;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.onap.validation.cli.command.validate.ResponseStorage;
+import org.onap.validation.yaml.util.Args;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+@ExtendWith(MockitoExtension.class)
+class CliTest {
+ @Mock
+ private Console console;
+
+ @Mock
+ private ResponseStorage responseStorage;
+
+ @Mock
+ private Command<String> validationCommand;
+
+ private Cli<String> cli;
+
+ @BeforeEach
+ void setUp() {
+ cli = new Cli<>(console, responseStorage);
+ }
+
+ @Test
+ void shouldExecuteCommandWithoutAnyError() throws CommandException {
+
+ // given
+ Args args = new Args(List.of());
+ when(validationCommand.execute(args)).thenReturn(
+ new CommandResponse<>("{ 'errors': [] }", CommandResponse.CommandStatus.PASS)
+ );
+
+ // when
+ final int exitCode = cli.run(args, validationCommand);
+
+ // then
+ assertThat(exitCode).isEqualTo(Cli.PASS_STATUS_CODE);
+ verify(console).info("{ 'errors': [] }");
+ }
+
+ @Test
+ void shouldHandleErrorReportedByCommand() throws CommandException {
+
+ // given
+ Args args = new Args(List.of());
+ final CommandException commandException = new CommandException("It should be reported");
+ Mockito.doThrow(commandException).when(validationCommand).execute(args);
+
+ // when
+ final int exitCode = cli.run(args, validationCommand);
+
+ // then
+ assertThat(exitCode).isEqualTo(Cli.INTERNAL_ERROR_STATUS_CODE);
+ verify(console).error(commandException);
+ }
+
+ @Test
+ void shouldHandleRuntimeException() throws CommandException {
+
+ // given
+ Args args = new Args(List.of());
+ final RuntimeException commandException = new RuntimeException();
+ Mockito.doThrow(commandException).when(validationCommand).execute(args);
+
+ // when
+ final int exitCode = cli.run(args, validationCommand);
+
+ // then
+ assertThat(exitCode).isEqualTo(Cli.INTERNAL_ERROR_STATUS_CODE);
+ verify(console).error(commandException);
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlContentValidatorTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlContentValidatorTest.java
new file mode 100644
index 0000000..ff4e55b
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlContentValidatorTest.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.yaml;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.onap.validation.yaml.error.YamlDocumentValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.yaml.snakeyaml.parser.ParserException;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.onap.validation.yaml.YamlLoadingUtils.PATH_TO_MULTI_DOCUMENT_INVALID_YAML;
+import static org.onap.validation.yaml.YamlLoadingUtils.PATH_TO_VALID_JSON_STYLE_YAML;
+import static org.onap.validation.yaml.YamlLoadingUtils.PATH_TO_YAML_WITH_WRONG_VALUES;
+import static org.onap.validation.yaml.YamlLoadingUtils.readFile;
+
+class YamlContentValidatorTest {
+
+ final YamlContentValidator yamlContentValidator = new YamlContentValidator();
+
+ @Nested
+ class FromStringPathValidator {
+ @Test
+ void shouldReturnCorrectErrorsWhenGivenPathToValidPmDictionaryFile() throws YamlProcessingException {
+ // given
+ String path = getFullPathForGivenResources(PATH_TO_YAML_WITH_WRONG_VALUES);
+
+ // when
+ List<YamlDocumentValidationError> validationErrors = new YamlContentValidator().validate(path);
+
+ // then
+ assertValidationReturnedExpectedErrors(validationErrors);
+ }
+
+ @Test
+ void shouldReturnCorrectErrorsWhenGivenPathToValidJsonStylePmDictionaryFile() throws YamlProcessingException {
+ // given
+ String path = getFullPathForGivenResources(PATH_TO_VALID_JSON_STYLE_YAML);
+
+ // when
+ List<YamlDocumentValidationError> validationErrors = new YamlContentValidator().validate(path);
+
+ // then
+ assertValidationReturnedExpectedErrors(validationErrors);
+ }
+
+ @Test
+ void shouldThrowErrorWhenGivenPathToInvalidPmDictionaryFile() {
+ // given
+ String path = getFullPathForGivenResources(PATH_TO_MULTI_DOCUMENT_INVALID_YAML);
+
+ //when then
+ assertThatThrownBy(() -> yamlContentValidator.validate(path))
+ .isInstanceOf(ParserException.class)
+ .hasMessageContaining("expected the node content, but found '<document end>'");
+ }
+
+ @Test
+ void shouldThrowErrorWhenGivenInvalidPath() {
+ // given
+ String path = "invalid/path/to/pm_dictionary";
+
+ //when then
+ assertThatThrownBy(() -> yamlContentValidator.validate(path))
+ .isInstanceOf(YamlProcessingException.class)
+ .hasMessageContaining("Dictionary YAML file is empty");
+ }
+ }
+
+ @Nested
+ class FromByteArrayValidator {
+ @Test
+ void shouldReturnCorrectErrorsWhenGivenPmDictionaryFileWithErrors() throws YamlProcessingException, IOException {
+ // given
+ byte[] yaml = readFile(PATH_TO_YAML_WITH_WRONG_VALUES);
+
+ // when
+ List<YamlDocumentValidationError> validationErrors = new YamlContentValidator().validate(yaml);
+
+ // then
+ assertValidationReturnedExpectedErrors(validationErrors);
+ }
+
+ @Test
+ void shouldReturnCorrectErrorsWhenGivenValidJsonStylePmDictionary() throws YamlProcessingException, IOException {
+ // given
+ byte[] yaml = readFile(PATH_TO_VALID_JSON_STYLE_YAML);
+
+ // when
+ List<YamlDocumentValidationError> validationErrors = new YamlContentValidator().validate(yaml);
+
+ // then
+ assertValidationReturnedExpectedErrors(validationErrors);
+ }
+
+ @Test
+ void shouldThrowErrorWhenGivenInvalidPmDictionary() throws IOException {
+ // given
+ byte[] yaml = readFile(PATH_TO_MULTI_DOCUMENT_INVALID_YAML);
+
+ //when then
+ assertThatThrownBy(() -> new YamlContentValidator().validate(yaml))
+ .isInstanceOf(ParserException.class)
+ .hasMessageContaining("expected the node content, but found '<document end>'");
+ }
+
+ @Test
+ void shouldThrowErrorWhenGivenEmptyPmDictionary() {
+ //when then
+ assertThatThrownBy(() -> new YamlContentValidator().validate(new byte[0]))
+ .isInstanceOf(YamlProcessingException.class)
+ .hasMessageContaining("Dictionary YAML file is empty");
+ }
+ }
+
+ private void assertValidationReturnedExpectedErrors(List<YamlDocumentValidationError> validationErrors) {
+ assertThat(validationErrors)
+ .isNotNull()
+ .hasSize(4)
+ .usingRecursiveFieldByFieldElementComparator()
+ .containsAll(
+ List.of(
+ new YamlDocumentValidationError(1,
+ "/pmMetaData/pmFields/measResultType",
+ "Value(s) is/are not in array of accepted values.\n" +
+ " value(s): integer\n" +
+ " accepted value(s): [float, uint32, uint64]"),
+ new YamlDocumentValidationError(1,
+ "/pmMetaData/pmFields/",
+ "Key not found: measChangeType"),
+ new YamlDocumentValidationError(2,
+ "/pmMetaData/pmFields/",
+ "Key not found: measChangeType"),
+ new YamlDocumentValidationError(3,
+ "/pmMetaData/pmFields/measAdditionalFields/vendorField1",
+ "Value(s) is/are not in array of accepted values.\n" +
+ " value(s): [Z, A]\n" +
+ " accepted value(s): [X, Y, Z]")
+ )
+ );
+ }
+
+ private String getFullPathForGivenResources(String pathToValidYaml) {
+ return this.getClass().getClassLoader().getResource(pathToValidYaml).getPath();
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java
new file mode 100644
index 0000000..3e1f601
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoaderTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.yaml;
+
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+import org.yaml.snakeyaml.parser.ParserException;
+import org.yaml.snakeyaml.scanner.ScannerException;
+
+import java.io.IOException;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class YamlLoaderTest {
+ private static final int EXPECTED_NUMBER_OF_DOCUMENTS = 5;
+ private static final String LETTER_S_WITH_ASCII_CODE = "s(115)";
+
+ @Nested
+ class FromUrlLoader {
+ @Test
+ void shouldLoadAllDocumentsFromYamlFile() throws YamlDocumentFactory.YamlDocumentParsingException {
+ // when
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ void shouldLoadAllDocumentsFromJsonStyleYamlFile() throws YamlDocumentFactory.YamlDocumentParsingException {
+ // when
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidJsonStyleMultiDocumentYamlFile();
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenLoadingDocumentsFromInvalidYamlFile() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadMultiDocumentInvalidYamlFile)
+ .isInstanceOf(ParserException.class)
+ .hasMessageContaining("expected the node content, but found '<document end>'");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenLoadingInvalidYamlFileWithIncorrectKeyMapping() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadInvalidYamlFileWithIncorrectKeyMapping)
+ .isInstanceOf(ScannerException.class)
+ .hasMessageContaining("mapping values are not allowed here");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenLoadingInvalidYamlFileWithUnknownEscapeCharacter() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadInvalidYamlFileWithUnknownEscapeCharacter)
+ .isInstanceOf(ScannerException.class)
+ .hasMessageContaining("found unknown escape character " + LETTER_S_WITH_ASCII_CODE);
+ }
+ }
+
+ @Nested
+ class FromStringPathLoader {
+ @Test
+ void shouldLoadAllDocumentsFromYamlFileUsingPathInString() throws YamlProcessingException {
+ // when
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFileUsingStringPath();
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenLoadingDocumentsFromInvalidYamlFileUsingPathInString() {
+ // when then
+ assertThatThrownBy(YamlLoadingUtils::tryToLoadMultiDocumentInvalidYamlFileUsingStringPath)
+ .isInstanceOf(ParserException.class)
+ .hasMessageContaining("expected the node content, but found '<document end>'");
+ }
+ }
+
+ @Nested
+ class FromByteArrayLoader {
+ private final YamlLoader YAML_LOADER = new YamlLoader(new YamlDocumentFactory());
+
+ @Test
+ void shouldLoadAllDocumentsFromYamlFile() throws YamlDocumentFactory.YamlDocumentParsingException, IOException {
+ // when
+ List<YamlDocument> documents = YAML_LOADER.loadMultiDocumentYaml(YamlLoadingUtils.readFile(YamlLoadingUtils.PATH_TO_YAML_WITH_WRONG_VALUES));
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ void shouldLoadAllDocumentsFromJsonStyleYamlFile() throws YamlDocumentFactory.YamlDocumentParsingException, IOException {
+ // when
+ List<YamlDocument> documents = YAML_LOADER.loadMultiDocumentYaml(YamlLoadingUtils.readFile(YamlLoadingUtils.PATH_TO_VALID_JSON_STYLE_YAML));
+
+ // then
+ assertThat(documents).hasSize(EXPECTED_NUMBER_OF_DOCUMENTS);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenLoadingDocumentsFromInvalidYamlFile() {
+ // when then
+ assertThatThrownBy(() -> YAML_LOADER.loadMultiDocumentYaml(YamlLoadingUtils.readFile(YamlLoadingUtils.PATH_TO_MULTI_DOCUMENT_INVALID_YAML)))
+ .isInstanceOf(ParserException.class)
+ .hasMessageContaining("expected the node content, but found '<document end>'");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenLoadingInvalidYamlFileWithIncorrectKeyMapping() {
+ // when then
+ assertThatThrownBy(() -> YAML_LOADER.loadMultiDocumentYaml(YamlLoadingUtils.readFile(YamlLoadingUtils.PATH_TO_INVALID_YAML_WITH_INCORRECT_KEY_MAPPING)))
+ .isInstanceOf(ScannerException.class)
+ .hasMessageContaining("mapping values are not allowed here");
+ }
+
+ @Test
+ void shouldThrowExceptionWhenLoadingInvalidYamlFileWithUnknownEscapeCharacter() {
+ // when then
+ assertThatThrownBy(() -> YAML_LOADER.loadMultiDocumentYaml(YamlLoadingUtils.readFile(YamlLoadingUtils.PATH_TO_INVALID_YAML_WITH_UNKNOWN_ESCAPE_CHARACTER)))
+ .isInstanceOf(ScannerException.class)
+ .hasMessageContaining("found unknown escape character " + LETTER_S_WITH_ASCII_CODE);
+ }
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java
new file mode 100644
index 0000000..dc1ce3b
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlLoadingUtils.java
@@ -0,0 +1,104 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.yaml;
+
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+
+public final class YamlLoadingUtils {
+
+ public static final YamlLoader YAML_LOADER = new YamlLoader(new YamlDocumentFactory());
+
+ private YamlLoadingUtils() {
+ }
+
+ public static final int VALID_YAML_DOCUMENT_INDEX = 4;
+ public static final int YAML_DOCUMENT_WITH_WRONG_VALUE_IN_ARRAY_INDEX = 3;
+ public static final int YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX = 2;
+ public static final int YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX = 1;
+ public static final String PATH_TO_YAML_WITH_WRONG_VALUES = "yaml_schema/PM_Dictionary.yaml";
+ public static final String PATH_TO_VALID_JSON_STYLE_YAML = "yaml_schema/PM_Dictionary_JSON_Style.yaml";
+ public static final String PATH_TO_SIMPLE_VALID_SCHEMA = "yaml_schema/Simple_Valid_Schema.yaml";
+ public static final String PATH_TO_SIMPLE_VALID_SCHEMA_MULTI_ROOT = "yaml_schema/Simple_Valid_Schema_Multi_Root.yaml";
+ public static final String PATH_TO_SIMPLE_INVALID_SCHEMA = "yaml_schema/Simple_Invalid_Schema_Construction.yaml";
+ public static final String PATH_TO_SIMPLE_INVALID_SCHEMA_FOR_LAZY_LOADING = "yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml";
+ public static final String PATH_TO_MULTI_DOCUMENT_INVALID_YAML = "yaml_schema/Multi_Document_Invalid.yaml";
+ public static final String PATH_TO_INVALID_YAML_WITH_INCORRECT_KEY_MAPPING = "yaml_schema/Simple_Invalid_Mapping_Value.yaml";
+ public static final String PATH_TO_INVALID_YAML_WITH_UNKNOWN_ESCAPE_CHARACTER = "yaml_schema/Simple_Unknown_Escape_Character.yaml";
+
+ public static List<YamlDocument> loadValidMultiDocumentYamlFile() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_YAML_WITH_WRONG_VALUES));
+ }
+
+ public static List<YamlDocument> loadValidJsonStyleMultiDocumentYamlFile() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_VALID_JSON_STYLE_YAML));
+ }
+
+ public static List<YamlDocument> loadValidMultiDocumentYamlFileUsingStringPath() throws YamlProcessingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_YAML_WITH_WRONG_VALUES).getPath());
+ }
+
+ public static YamlDocument loadSimpleValidYamlSchemaFile() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_VALID_SCHEMA)).get(0);
+ }
+
+ public static YamlDocument loadSimpleInvalidYamlSchemaFile() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_INVALID_SCHEMA)).get(0);
+ }
+
+ public static YamlDocument loadSimpleInvalidYamlSchemaForLazyLoadingFile() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_INVALID_SCHEMA_FOR_LAZY_LOADING)).get(0);
+ }
+
+ public static YamlDocument loadSimpleValidYamlSchemaWithMultiRootFile() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_SIMPLE_VALID_SCHEMA_MULTI_ROOT)).get(0);
+ }
+
+ public static List<YamlDocument> tryToLoadMultiDocumentInvalidYamlFile() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_MULTI_DOCUMENT_INVALID_YAML));
+ }
+
+ public static List<YamlDocument> tryToLoadMultiDocumentInvalidYamlFileUsingStringPath() throws YamlProcessingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_MULTI_DOCUMENT_INVALID_YAML).getPath());
+ }
+
+ public static List<YamlDocument> tryToLoadInvalidYamlFileWithIncorrectKeyMapping() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_INVALID_YAML_WITH_INCORRECT_KEY_MAPPING));
+ }
+
+ public static List<YamlDocument> tryToLoadInvalidYamlFileWithUnknownEscapeCharacter() throws YamlDocumentParsingException {
+ return YAML_LOADER.loadMultiDocumentYamlFile(getUrlForGivenPath(PATH_TO_INVALID_YAML_WITH_UNKNOWN_ESCAPE_CHARACTER));
+ }
+
+ public static byte[] readFile(String path) throws IOException {
+ String file = getUrlForGivenPath(path).getFile();
+ return Files.readAllBytes(Path.of(file));
+ }
+
+ public static URL getUrlForGivenPath(String path) {
+ return YamlLoadingUtils.class.getClassLoader().getResource(path);
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java
new file mode 100644
index 0000000..3d993f8
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/YamlValidatorTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml;
+
+import org.junit.jupiter.api.Test;
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.YamlSchemaFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.onap.validation.yaml.YamlLoadingUtils.VALID_YAML_DOCUMENT_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_WRONG_VALUE_IN_ARRAY_INDEX;
+
+class YamlValidatorTest {
+
+ @Test
+ void shouldCreateValidatorUsingSchemaLoadedFromYamlFileAndValidatedJsonStyleDocumentsFromThatFile()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidJsonStyleMultiDocumentYamlFile();
+ YamlValidator validator = new YamlValidator(new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0)));
+ Map<Integer, List<SchemaValidationError>> validationErrors = new HashMap<>();
+
+ // when
+ for (int documentIndex = 1; documentIndex < documents.size(); documentIndex++) {
+ validationErrors.put(documentIndex, validator.validate(documents.get(documentIndex)));
+ }
+
+ // then
+ assertValidatorReturnedCorrectErrors(validationErrors);
+ }
+
+ @Test
+ void shouldCreateValidatorUsingSchemaLoadedFromYamlFileAndValidatedDocumentsFromThatFile()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlValidator validator = new YamlValidator(new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0)));
+ Map<Integer, List<SchemaValidationError>> validationErrors = new HashMap<>();
+
+ // when
+ for (int documentIndex = 1; documentIndex < documents.size(); documentIndex++) {
+ validationErrors.put(documentIndex, validator.validate(documents.get(documentIndex)));
+ }
+
+ // then
+ assertValidatorReturnedCorrectErrors(validationErrors);
+ }
+
+ private void assertValidatorReturnedCorrectErrors(Map<Integer, List<SchemaValidationError>> validationErrors) {
+
+ SchemaValidationError expectedValidationValueError =
+ new SchemaValidationError(
+ "/pmMetaData/pmFields/measResultType",
+ "Value(s) is/are not in array of accepted values.\n"
+ + " value(s): integer\n"
+ + " accepted value(s): [float, uint32, uint64]"
+ );
+ SchemaValidationError expectedValidationKeyError =
+ new SchemaValidationError(
+ "/pmMetaData/pmFields/",
+ "Key not found: measChangeType"
+ );
+ SchemaValidationError expectedValidationValuesInArrayError =
+ new SchemaValidationError(
+ "/pmMetaData/pmFields/measAdditionalFields/vendorField1",
+ "Value(s) is/are not in array of accepted values.\n"
+ + " value(s): [Z, A]\n"
+ + " accepted value(s): [X, Y, Z]"
+ );
+
+ assertThat(validationErrors)
+ .hasSize(4)
+ .containsKeys(1, 2, 3);
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX))
+ .hasSize(2)
+ .usingFieldByFieldElementComparator()
+ .containsAll(List.of(
+ expectedValidationValueError,
+ expectedValidationKeyError
+ ));
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX))
+ .hasSize(1)
+ .usingFieldByFieldElementComparator()
+ .contains(expectedValidationKeyError);
+ assertThat(validationErrors.get(YAML_DOCUMENT_WITH_WRONG_VALUE_IN_ARRAY_INDEX))
+ .hasSize(1)
+ .usingFieldByFieldElementComparator()
+ .contains(expectedValidationValuesInArrayError);
+ assertThat(validationErrors.get(VALID_YAML_DOCUMENT_INDEX)).isEmpty();
+ }
+
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java
new file mode 100644
index 0000000..d7d1153
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlDocumentFactoryTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.ThrowableAssert.catchThrowable;
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+
+class YamlDocumentFactoryTest {
+
+ @Test
+ void shouldTurnMapOfUnknownKeyTypeToMapWithStringKeysAndBeAbleToReturnStringifyValues()
+ throws YamlDocumentParsingException {
+ // given
+ List<String> testList = List.of("element1", "element11");
+ Map<Object, Object> testEmptyMap = Collections.emptyMap();
+ Map<Object, Object> inputMap = Map.of(
+ "test", testList,
+ 345, "element2",
+ "test2", "element3",
+ 2.67, testEmptyMap);
+
+ // when
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // then
+ assertYamlDocument(document, inputMap);
+ }
+
+ @Test
+ void shouldTurnMapOfUnknownKeyTypeToMapWithStringKeysAndBeAbleToExtractSubStructure()
+ throws YamlDocumentParsingException {
+ // given
+ Map<Object, Object> subStructureMap = Map.of(
+ "subTest1", "subElement1",
+ "subTest2", "subElement2");
+ Map<Object, Object> inputMap = Map.of(
+ "test", "element1",
+ "structure", subStructureMap);
+
+ // when
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // then
+ assertYamlDocument(document, inputMap);
+ }
+
+ @Test
+ void shouldTurnMapOfUnknownKeyTypeToMapWithStringKeysAndBeAbleToExtractParametersList()
+ throws YamlDocumentParsingException {
+ // given
+ List<String> parametersList = List.of("parameter1", "parameter2");
+ Map<Object, Object> inputMap = Map.of(
+ "test", "element1",
+ "parameters", parametersList);
+
+ // when
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // then
+ assertYamlDocument(document, inputMap);
+ }
+
+ @Test
+ void shouldThrowExceptionIfGetSubStructureIsCalledOnList()
+ throws YamlDocumentParsingException {
+ // given
+ List<String> testList = List.of("element1", "element2");
+ Map<Object, Object> inputMap = Collections.singletonMap("test", testList);
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // when
+ Throwable ex = catchThrowable(() -> document.getSubStructure("test"));
+
+ // then
+ assertYamlDocumentParsingException(ex, testList);
+ }
+
+ @Test
+ void shouldThrowExceptionIfGetSubStructureIsCalledOnString()
+ throws YamlDocumentParsingException {
+ // given
+ Map<Object, Object> inputMap = Collections.singletonMap("test", "testElement");
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(inputMap);
+
+ // when
+ Throwable ex = catchThrowable(() -> document.getSubStructure("test"));
+
+ // then
+ assertYamlDocumentParsingException(ex, "testElement");
+ }
+
+ private void assertYamlDocument(YamlDocument document, Map<Object, Object> inputMap) {
+ assertThat(document).isNotNull();
+ assertThat(document.getYaml()).containsExactlyEntriesOf(mapKeyToString(inputMap));
+ }
+
+ private Map<String, Object> mapKeyToString(Map<Object, Object> inputMap) {
+ return inputMap.entrySet().stream()
+ .collect(Collectors.toMap(w -> w.getKey().toString(), Map.Entry::getValue));
+ }
+
+ private void assertYamlDocumentParsingException(Throwable ex, Object unparsed) {
+ assertThat(ex)
+ .isInstanceOf(YamlDocumentParsingException.class)
+ .hasMessageContaining(String.format("Fail to parse given objects: %s as yaml document.", unparsed));
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java
new file mode 100644
index 0000000..ab6f882
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/model/YamlParameterListFactoryTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.model;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class YamlParameterListFactoryTest {
+
+ @Test
+ void shouldCreateEmptyParametersList() {
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createEmptyYamlParameterList();
+
+ // then
+ assertThat(parametersList).isNotNull();
+ assertThat(parametersList.getParameters()).isEmpty();
+ }
+
+ @Test
+ void shouldCreateParametersListContainingStringsFromListContainingSimpleTypes() {
+ // given
+ List<Object> testList = List.of("test1", 3, 23.45, 'a', "test2");
+
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createYamlParameterList(testList);
+
+ // then
+ assertYamlParametersList(parametersList, testList);
+ }
+
+ @Test
+ void shouldCreateParametersListContainingStringsFromListContainingVariousTypes() {
+ // given
+ List<Object> testList = List.of("test1", 3, List.of(2, 3, 4), "test2");
+
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createYamlParameterList(testList);
+
+ // then
+ assertYamlParametersList(parametersList, testList);
+ }
+
+ @Test
+ void shouldCreateListWithOneStringWhenGivenObjectIsNotList() {
+ // given
+ Object testObject = "test";
+
+ // when
+ YamlParametersList parametersList = new YamlParameterListFactory().createYamlParameterList(testObject);
+
+ // then
+ assertYamlParametersList(parametersList, Collections.singletonList(testObject));
+ }
+
+ private void assertYamlParametersList(YamlParametersList parametersList, List<Object> testList) {
+ assertThat(parametersList).isNotNull();
+ assertThat(parametersList.getParameters())
+ .containsExactly(mapToStrings(testList));
+ }
+
+ private String[] mapToStrings(List<Object> elements) {
+ return elements.stream().map(Object::toString).toArray(String[]::new);
+ }
+
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java
new file mode 100644
index 0000000..5c9d8e5
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/process/YamlValidationProcessTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.process;
+
+import org.junit.jupiter.api.Test;
+import org.onap.validation.yaml.YamlLoadingUtils;
+import org.onap.validation.yaml.error.SchemaValidationError;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.YamlSchema;
+import org.onap.validation.yaml.schema.YamlSchemaFactory;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+import static org.onap.validation.yaml.YamlLoadingUtils.VALID_YAML_DOCUMENT_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX;
+import static org.onap.validation.yaml.YamlLoadingUtils.YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX;
+
+class YamlValidationProcessTest {
+
+ @Test
+ void shouldReturnNoErrorWhenProcessingValidPmDictionaryYaml()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ YamlDocument document = documents.get(VALID_YAML_DOCUMENT_INDEX);
+
+ // when
+ List<SchemaValidationError> errors = new YamlValidationProcess(schema, document).validate();
+
+ // then
+ assertThat(errors).isEmpty();
+ }
+
+ @Test
+ void shouldReturnOneErrorWhenProcessingPmDictionaryYamlWithMissingField()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ YamlDocument document = documents.get(YAML_DOCUMENT_WITH_MISSING_FIELD_INDEX);
+
+ // when
+ List<SchemaValidationError> errors = new YamlValidationProcess(schema, document).validate();
+
+ // then
+ assertThat(errors).hasSize(1);
+ }
+
+ @Test
+ void shouldReturnTwoErrorsWhenProcessingPmDictionaryYamlWithMissingFieldAndIncorrectValue()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents.get(0));
+ YamlDocument document = documents.get(YAML_DOCUMENT_WITH_MISSING_FIELD_AND_WRONG_VALUE_INDEX);
+
+ // when
+ List<SchemaValidationError> errors = new YamlValidationProcess(schema, document).validate();
+
+ // then
+ assertThat(errors).hasSize(2);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenProcessingPmDictionaryIsNotValidYaml()
+ throws YamlProcessingException {
+ // given
+ List<YamlDocument> documents = YamlLoadingUtils.loadValidMultiDocumentYamlFile();
+ YamlDocument schemaInYaml = YamlLoadingUtils.loadSimpleInvalidYamlSchemaForLazyLoadingFile();
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(schemaInYaml);
+ YamlDocument document = documents.get(VALID_YAML_DOCUMENT_INDEX);
+
+ // when
+ Throwable ex = catchThrowable(() -> new YamlValidationProcess(schema, document).validate());
+
+ // then
+ assertThat(ex)
+ .isInstanceOf(YamlProcessingException.class)
+ .hasMessageContaining("Lazy loading failed, due to yaml parsing exception.");
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java
new file mode 100644
index 0000000..efc304c
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/YamlSchemaFactoryTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.onap.validation.yaml.YamlLoadingUtils;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.schema.node.YamlSchemaNode;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.onap.validation.yaml.model.YamlDocumentFactory.YamlDocumentParsingException;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactory.EMPTY_COMMENT;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactoryTest.assertThatBranchNodeIsValid;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactoryTest.assertThatLeafNodeIsValid;
+
+
+class YamlSchemaFactoryTest {
+
+ @Test
+ void shouldCreateYamlSchemaFromYamlDocumentWithMultipleRoots()
+ throws YamlProcessingException {
+ // given
+ YamlDocument documents = YamlLoadingUtils.loadSimpleValidYamlSchemaWithMultiRootFile();
+
+ // when
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents);
+
+ // then
+ assertThat(schema).isNotNull();
+ assertThat(schema.getRootNodes())
+ .extracting(YamlSchemaNode::getName)
+ .containsExactly("root1", "root2", "root3");
+ }
+
+
+ @Test
+ void shouldCreateYamlSchemaFromYamlDocument()
+ throws YamlProcessingException {
+ // given
+ YamlDocument documents = YamlLoadingUtils.loadSimpleValidYamlSchemaFile();
+
+ // when
+ YamlSchema schema = new YamlSchemaFactory().createTreeStructuredYamlSchema(documents);
+
+ // then
+ assertThat(schema).isNotNull();
+ assertThat(schema.getRootNodes()).hasSize(1);
+ YamlSchemaNode pmMetaData = schema.getRootNodes().get(0);
+ assertThatBranchNodeIsValid(pmMetaData, "pmMetaData", "/", true, EMPTY_COMMENT,
+ 2);
+
+ YamlSchemaNode pmHeader = pmMetaData.getNextNodes().get(1);
+ assertThatBranchNodeIsValid(pmHeader, "pmHeader", "/pmMetaData/", true, EMPTY_COMMENT,
+ 1);
+
+ YamlSchemaNode nfType = pmHeader.getNextNodes().get(0);
+ assertThatLeafNodeIsValid(nfType, "nfType", "/pmMetaData/pmHeader/", true, "nfType comment");
+
+ YamlSchemaNode pmFields = pmMetaData.getNextNodes().get(0);
+ assertThatBranchNodeIsValid(pmFields, "pmFields", "/pmMetaData/", true, EMPTY_COMMENT,
+ 2);
+
+ YamlSchemaNode measChangeType = pmFields.getNextNodes().get(1);
+ assertThatLeafNodeIsValid(measChangeType, "measChangeType", "/pmMetaData/pmFields/",
+ true, "measChangeType comment",
+ "added", "modified", "deleted");
+
+ YamlSchemaNode measAdditionalFields = pmFields.getNextNodes().get(0);
+ assertThatBranchNodeIsValid(measAdditionalFields, "measAdditionalFields", "/pmMetaData/pmFields/",
+ true, "measAdditionalFields comment",
+ 2);
+
+ YamlSchemaNode vendorField1 = measAdditionalFields.getNextNodes().get(0);
+ assertThatLeafNodeIsValid(vendorField1, "vendorField1", "/pmMetaData/pmFields/measAdditionalFields/",
+ true, "vendorField1 comment",
+ "X", "Y", "Z");
+ YamlSchemaNode vendorField2 = measAdditionalFields.getNextNodes().get(1);
+ assertThatLeafNodeIsValid(vendorField2, "vendorField2", "/pmMetaData/pmFields/measAdditionalFields/",
+ false, "vendorField2 comment",
+ "A", "B");
+ }
+
+ @Test
+ void shouldThrowYamlParsingExceptionWhenLoadedSchemaIsInvalid()
+ throws YamlDocumentParsingException {
+ // given
+ YamlDocument documents = YamlLoadingUtils.loadSimpleInvalidYamlSchemaFile();
+
+ //when then
+ assertThatThrownBy(() -> new YamlSchemaFactory().createTreeStructuredYamlSchema(documents))
+ .isInstanceOf(YamlDocumentParsingException.class)
+ .hasMessageContaining(String.format(
+ "Fail to parse given objects: %s as yaml document",
+ documents.getSubStructure("pmMetaData").getYaml().get("structure"))
+ );
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java
new file mode 100644
index 0000000..646b8a2
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/schema/node/YamlSchemaNodeFactoryTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.onap.validation.yaml.schema.node;
+
+import org.junit.jupiter.api.Test;
+import org.onap.validation.yaml.YamlLoadingUtils;
+import org.onap.validation.yaml.exception.YamlProcessingException;
+import org.onap.validation.yaml.model.YamlDocument;
+import org.onap.validation.yaml.model.YamlDocumentFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+import static org.onap.validation.yaml.schema.node.YamlSchemaNodeFactory.EMPTY_COMMENT;
+
+public class YamlSchemaNodeFactoryTest {
+
+ private static final String ROOT_PATH = "/";
+
+ @Test
+ void shouldThrowExceptionDuringLazyLoadingWhenLoadedSchemaHaveInvalidSubStructure()
+ throws YamlProcessingException {
+ // given
+ String nodeName = "pmMetaData";
+ YamlDocument document = YamlLoadingUtils.loadSimpleInvalidYamlSchemaForLazyLoadingFile();
+ YamlSchemaNode node = new YamlSchemaNodeFactory()
+ .createNode(nodeName, ROOT_PATH, document.getSubStructure(nodeName));
+
+ // when
+ Throwable ex = catchThrowable(node::getNextNodes);
+
+ // then
+ assertThat(ex)
+ .isInstanceOf(YamlSchemaNode.YamlSchemaProcessingException.class)
+ .hasMessageContaining("Lazy loading failed, due to yaml parsing exception.");
+ }
+
+ @Test
+ void shouldCreateLeafNodeIfGivenYamlDocumentHaveNoSubStructure()
+ throws YamlProcessingException {
+ // given
+ String nodeName = "leaf_test";
+ String comment = "test leaf node";
+ List<String> acceptedValues = List.of("val1", "val2");
+ Map<Object, Object> nodeInYamlFormat = Map.of(
+ YamlSchemaNodeFactory.PRESENCE_KEY, YamlSchemaNodeFactory.PRESENCE_REQUIRED_KEY,
+ YamlSchemaNodeFactory.COMMENT_KEY, comment,
+ YamlSchemaNodeFactory.VALUE_KET, acceptedValues);
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(nodeInYamlFormat);
+
+ // when
+ YamlSchemaNode yamlSchemaNode = new YamlSchemaNodeFactory().createNode(nodeName, ROOT_PATH, document);
+
+ // then
+ assertThatLeafNodeIsValid(
+ yamlSchemaNode, nodeName, ROOT_PATH, true, comment,
+ acceptedValues.toArray(new String[0])
+ );
+ }
+
+ @Test
+ void shouldCreateBranchNodeIfGivenYamlDocumentHaveSubStructure()
+ throws YamlProcessingException {
+ // given
+ String nodeName = "branch_test";
+ String comment = "test branch node";
+
+ String subNode1Name = "branch_test_node1";
+ String subNode2Name = "branch_test_node2";
+
+ Map<Object, Object> subStructure = Map.of(
+ subNode1Name, new HashMap<>(),
+ subNode2Name, new HashMap<>());
+
+ Map<Object, Object> nodeInYamlFormat = Map.of(
+ YamlSchemaNodeFactory.PRESENCE_KEY, YamlSchemaNodeFactory.PRESENCE_REQUIRED_KEY,
+ YamlSchemaNodeFactory.COMMENT_KEY, comment,
+ YamlSchemaNodeFactory.STRUCTURE_KEY, subStructure);
+ YamlDocument document = new YamlDocumentFactory().createYamlDocument(nodeInYamlFormat);
+
+ // when
+ YamlSchemaNode yamlSchemaNode = new YamlSchemaNodeFactory().createNode(nodeName, ROOT_PATH, document);
+
+ // then
+ assertThatBranchNodeIsValid(yamlSchemaNode, nodeName, ROOT_PATH, true, comment, 2);
+ List<YamlSchemaNode> subNodes = yamlSchemaNode.getNextNodes();
+ assertThat(subNodes).hasSize(2);
+ assertThatLeafNodeIsValid(
+ subNodes.get(1), subNode1Name, ROOT_PATH + nodeName + "/", false, EMPTY_COMMENT);
+ assertThatLeafNodeIsValid(
+ subNodes.get(0), subNode2Name, ROOT_PATH + nodeName + "/", false, EMPTY_COMMENT);
+ }
+
+ public static void assertThatBranchNodeIsValid(
+ YamlSchemaNode yamlSchemaNode, String name, String path, boolean isRequired, String comment,
+ int numberOfSubNodes
+ ) throws YamlSchemaNode.YamlSchemaProcessingException {
+ assertThatNodeIsValid(yamlSchemaNode, name, path, isRequired, comment);
+
+ assertThat(yamlSchemaNode.getClass()).isEqualTo(YamlSchemaBranchNode.class);
+ assertThat(yamlSchemaNode.isContainingSubStructure()).isTrue();
+ assertThat(yamlSchemaNode.getNextNodes()).hasSize(numberOfSubNodes);
+ assertThat(yamlSchemaNode.getAcceptedValues()).isEmpty();
+ }
+
+ public static void assertThatLeafNodeIsValid(
+ YamlSchemaNode yamlSchemaNode, String name, String path, boolean isRequired, String comment,
+ String... acceptedValues
+ ) throws YamlSchemaNode.YamlSchemaProcessingException {
+ assertThatNodeIsValid(yamlSchemaNode, name, path, isRequired, comment);
+
+ assertThat(yamlSchemaNode.getClass()).isEqualTo(YamlSchemaLeafNode.class);
+ assertThat(yamlSchemaNode.isContainingSubStructure()).isFalse();
+ assertThat(yamlSchemaNode.getAcceptedValues()).containsExactly(acceptedValues);
+ assertThat(yamlSchemaNode.getNextNodes()).isEmpty();
+ }
+
+ private static void assertThatNodeIsValid(YamlSchemaNode yamlSchemaNode, String name, String path, boolean isRequired, String comment) {
+ assertThat(yamlSchemaNode).isNotNull();
+ assertThat(yamlSchemaNode.getName()).isEqualTo(name);
+ assertThat(yamlSchemaNode.getPath()).isEqualTo(path);
+ if (comment.isEmpty()) {
+ assertThat(yamlSchemaNode.getComment()).isNotEmpty();
+ } else {
+ assertThat(yamlSchemaNode.getComment()).isEqualTo(comment);
+ }
+ assertThat(yamlSchemaNode.isRequired()).isEqualTo(isRequired);
+ }
+}
diff --git a/dictionaryvalidation/src/test/java/org/onap/validation/yaml/util/ArgsTest.java b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/util/ArgsTest.java
new file mode 100644
index 0000000..0090683
--- /dev/null
+++ b/dictionaryvalidation/src/test/java/org/onap/validation/yaml/util/ArgsTest.java
@@ -0,0 +1,39 @@
+/*
+ *Copyright 2020 Nokia
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.onap.validation.yaml.util;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+class ArgsTest {
+
+ @Test
+ void shouldThrowAnExceptionWhenArgIsNotAvailable() {
+ Args args = new Args(List.of());
+ Assertions.assertThatThrownBy(() -> args.getArg(0)).hasMessage("Argument with index 0 is not available!");
+ }
+
+ @Test
+ void shouldReturnArgumentForGivenIndex() {
+ Args args = new Args(List.of("one","two", "three"));
+ Assertions.assertThat(args.getArg(0)).isEqualTo("one");
+ Assertions.assertThat(args.getArg(1)).isEqualTo("two");
+ Assertions.assertThat(args.getArg(2)).isEqualTo("three");
+ }
+}
diff --git a/dictionaryvalidation/src/test/resources/Not_Yaml_File.txt b/dictionaryvalidation/src/test/resources/Not_Yaml_File.txt
new file mode 100644
index 0000000..be6ee44
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/Not_Yaml_File.txt
@@ -0,0 +1 @@
+Not a Yaml file!
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Custom_Invalid_Dictionary.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Custom_Invalid_Dictionary.yaml
new file mode 100644
index 0000000..d5d12d6
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Custom_Invalid_Dictionary.yaml
@@ -0,0 +1,56 @@
+---
+rootElement: { presence: required, structure: {
+ field1: {
+ presence: required,
+ comment: "field 1 description",
+ structure: {
+ field11:{
+ presence: required,
+ comment: "field 11 description"
+ },
+ field12: {
+ presence: required,
+ comment: "field 12 description"
+ },
+ field13: {
+ presence: optional,
+ value: [ X, Y, Z ],
+ comment: "field 13 description"
+ }
+ }
+ },
+ field2: {
+ presence: required,
+ comment: "field 2 description"
+ },
+ field3: {
+ presence: required,
+ value: [ 3, 30, 33 ],
+ comment: "field 2 description"
+ }
+}}
+...
+---
+rootElement:
+ field1:
+ field11: test11
+ field12: test12
+ field13: A
+ field2: test2
+ field3: 3
+...
+---
+rootElement:
+ field1:
+ field11: test11
+ field12: test12
+ field2: test2
+ field3: 300
+...
+---
+rootElement:
+ field1:
+ field11: test11
+ field12: test12
+ field3: 3
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Custom_Valid_Dictionary.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Custom_Valid_Dictionary.yaml
new file mode 100644
index 0000000..4193b0d
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Custom_Valid_Dictionary.yaml
@@ -0,0 +1,58 @@
+---
+rootElement1: { presence: required, structure: {
+ field11: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "field 11 description"
+ },
+ field12: {
+ presence: required,
+ comment: "field 12 description"
+ }
+}}
+rootElement2: { presence: required, structure: {
+ field21: {
+ presence: required,
+ value: [22, 222, 2222],
+ comment: "field 21 description"
+ },
+ field22: {
+ presence: optional,
+ value: [ A,B,C ],
+ comment: "field 22 description"
+ }
+}}
+rootElement3: { presence: optional, structure: {
+ field3: {
+ presence: required,
+ comment: "field 3 description"
+ }
+}}
+...
+---
+rootElement1:
+ field11: X
+ field12: test
+rootElement2:
+ field21: 22
+ field22: B
+...
+---
+rootElement1:
+ field11: X
+ field12: test12
+rootElement2:
+ field21: 22
+rootElement3:
+ field3: test3
+...
+---
+rootElement1:
+ field11: Y
+ field12: testing12
+rootElement2:
+ field21: 222
+ field22: A
+rootElement3:
+ field3: testing3
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml
new file mode 100644
index 0000000..aab34fa
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Multi_Document_Invalid.yaml
@@ -0,0 +1,86 @@
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 1,
+
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange.",
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change attempts.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: integer,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChAttempt,
+ measAdditionalFields: {
+ vendorField1: X,
+ vendorField2: B
+ }
+ }
+}
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 2,
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when the TDCoverall timer has elapsed before gNB receives the X2AP: SgNB Modification Confirm message.",
+ measDescription: "This measurement the number of intra gNB intra frequency PSCell change failures due to TDCoverall timer expiry.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailTdcExp,
+ measAdditionalFields: {
+ vendorField1: Y
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2206,
+ iMeasType: 1,
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message.",
+ measCollectionMethod: CC,
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G19_1906_002,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measChangeType: added,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef,
+ measAdditionalFields: {
+ vendorField1: Z,
+ vendorField2: A
+ }
+ }
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml
new file mode 100644
index 0000000..12a4af9
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary.yaml
@@ -0,0 +1,228 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 1
+ measCollectionMethod: CC
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange."
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change attempts."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: integer
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChAttempt
+ measAdditionalFields:
+ vendorField1: X
+ vendorField2: B
+...
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 2
+ measCollectionMethod: CC
+ measCondition: "This measurement is updated when the TDCoverall timer has elapsed before gNB receives the X2AP: SgNB Modification Confirm message."
+ measDescription: "This measurement the number of intra gNB intra frequency PSCell change failures due to TDCoverall timer expiry."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: float
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChFailTdcExp
+ measAdditionalFields:
+ vendorField1:
+ - Y
+ - X
+...
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2206
+ iMeasType: 1
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message."
+ measCollectionMethod: CC
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G19_1906_002
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: float
+ measChangeType: added
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef
+ measAdditionalFields:
+ vendorField1:
+ - Z
+ - A
+ vendorField2: A
+...
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2206
+ iMeasType: 1
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message."
+ measCollectionMethod: CC
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal."
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G19_1906_002
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: float
+ measChangeType: added
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef
+ measAdditionalFields:
+ vendorField1:
+ - X
+ - Y
+ vendorField2: A
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml
new file mode 100644
index 0000000..f4cbddf
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/PM_Dictionary_JSON_Style.yaml
@@ -0,0 +1,239 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 1,
+
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange.",
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change attempts.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: integer,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChAttempt,
+ measAdditionalFields: {
+ vendorField1: X,
+ vendorField2: B
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2204,
+ iMeasType: 2,
+ measCollectionMethod: CC,
+ measCondition: "This measurement is updated when the TDCoverall timer has elapsed before gNB receives the X2AP: SgNB Modification Confirm message.",
+ measDescription: "This measurement the number of intra gNB intra frequency PSCell change failures due to TDCoverall timer expiry.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G18A_1807_003,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailTdcExp,
+ measAdditionalFields: {
+ vendorField1: [Y,Z]
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2206,
+ iMeasType: 1,
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message.",
+ measCollectionMethod: CC,
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G19_1906_002,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measChangeType: added,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef,
+ measAdditionalFields: {
+ vendorField1: [Z,A],
+ vendorField2: A
+ }
+ }
+}
+...
+---
+pmMetaData: {
+ pmHeader: {
+ nfType: gnb-Nokia,
+ pmDefSchemaVsn: 2.0,
+ pmDefVsn: 5G19_1906_002
+ },
+ pmFields: {
+ iMeasInfoId: 2206,
+ iMeasType: 1,
+ measCondition: "This measurement is updated when MeNB replies to X2AP: SgNB Modification Required message with the X2AP: SgNB Modification Refuse message.",
+ measCollectionMethod: CC,
+ measDescription: "This counter indicates the number of intra gNB intra frequency PSCell change failures due to MeNB refusal.",
+ measFamily: NINFC,
+ measInfoId: "NR Intra Frequency PSCell Change",
+ measLastChange: 5G19_1906_002,
+ measObjClass: NGCELL,
+ measResultRange: 0-4096,
+ measResultType: float,
+ measChangeType: added,
+ measResultUnits: number,
+ measType: VS.NINFC.IntraFrPscelChFailMenbRef,
+ measAdditionalFields: {
+ vendorField1: [X,Y],
+ vendorField2: A
+ }
+ }
+}
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml
new file mode 100644
index 0000000..25c72cd
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Mapping_Value.yaml
@@ -0,0 +1,149 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 1
+ measCollectionMethod: CC
+ measCondition: This measurement is updated when X2AP: SgNB Modification Required message is sent to MeNB
+ with the SCG Change Indication set as PSCellChange.
+ measDescription: This counter indicates the number of intra gNB intra frequency PSCell change attempts.
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: integer
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChAttempt
+ measAdditionalFields:
+ vendorField1: X
+ vendorField2: B
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml
new file mode 100644
index 0000000..c5e7b7c
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_Construction.yaml
@@ -0,0 +1,39 @@
+---
+pmMetaData: { presence: required, structure: [
+ -pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "nfType comment"
+ }
+ }
+ },
+ -pmFields: {
+ presence: required,
+ structure: {
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "measChangeType comment"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "measAdditionalFields comment",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendorField1 comment"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendorField2 comment"
+ }
+ }
+ }
+ }
+ }
+]}
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml
new file mode 100644
index 0000000..7f9f946
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Invalid_Schema_LazyLoading.yaml
@@ -0,0 +1,39 @@
+---
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "nfType comment"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: [
+ -measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "measChangeType comment"
+ },
+ -measAdditionalFields: {
+ presence: required,
+ comment: "measAdditionalFields comment",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendorField1 comment"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendorField2 comment"
+ }
+ }
+ }
+ ]
+ }
+}}
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml
new file mode 100644
index 0000000..2cac9e6
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Unknown_Escape_Character.yaml
@@ -0,0 +1,149 @@
+---
+# PM Dictionary schema specifying and describing the meta information
+# used to define perf3gpp measurements in the PM Dictionary
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "NF type; should match the nfName-vendor string used in
+ the fileReady or perf3gpp eventName"
+ },
+ pmDefSchemaVsn: {
+ presence: required,
+ value: 2.0,
+ comment: "PM Dictionary Schema Version from the VES Event
+ Registration specification"
+ },
+ pmDefVsn: {
+ presence: required,
+ comment: "vendor-defined PM Dictionary version"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ iMeasInfoId: {
+ presence: required,
+ comment: "vendor-defined integer measurement group identifier"
+ },
+ iMeasType: {
+ presence: required,
+ comment: "vendor-defined integer identifier for the measType;
+ must be combined with measInfoId to identify a
+ specific measurement."
+ },
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "indicates the type of change that occurred during
+ measLastChange"
+ },
+ measCollectionMethod: {
+ presence: required,
+ value: [CC, SI, DER, Gauge, Average],
+ comment: "the measurement collection method; CC, SI, DER and
+ Gauge are as defined in 3GPP; average contains the
+ average value of the measurement during the
+ granularity period"
+ },
+ measCondition: {
+ presence: required,
+ comment: "description of the condition causing the measurement"
+ },
+ measDescription: {
+ presence: required,
+ comment: "description of the measurement information
+ and purpose"
+ },
+ measFamily: {
+ presence: required,
+ comment: "abbreviation for a family of measurements, in
+ 3GPP format, or vendor defined"
+ },
+ measInfoId: {
+ presence: required,
+ comment: "name for a group of related measurements in
+ 3GPP format or vendor defined"
+ },
+ measLastChange: {
+ presence: required,
+ comment: "version of the PM Dictionary the last time this
+ measurement was added, modified or deleted"
+ },
+ measObjClass: {
+ presence: required,
+ value: [NGBTS, NGCELL, IPNO, IPSEC, ETHIF],
+ comment: "measurement object class"
+ },
+ measResultRange: {
+ presence: optional,
+ comment: "range of the measurement result; only necessary when
+ the range is smaller than the full range of the
+ data type"
+ },
+ measResultType: {
+ presence: required,
+ value: [float, uint32, uint64],
+ comment: "data type of the measurement result"
+ },
+ measResultUnits: {
+ presence: required,
+ value: [seconds, minutes, nanoseconds, microseconds, dB,
+ number, kilobytes, bytes, ethernetFrames,
+ packets, users],
+ comment: "units of measure for the measurement result"
+ },
+ measType: {
+ presence: required,
+ comment: "measurement name in 3GPP or vendor-specific format;
+ vendor specific names are preceded with VS"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "vendor-specific PM Dictionary fields",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendor field 1 description"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendor field 2 description."
+ }
+ }
+ }
+ }
+ }
+}}
+...
+# PM Dictionary perf3gpp measurements for the gnb-Nokia NF (bracket style yaml)
+---
+pmMetaData:
+ pmHeader:
+ nfType: gnb-Nokia
+ pmDefSchemaVsn: 2.0
+ pmDefVsn: 5G19_1906_002
+ pmFields:
+ iMeasInfoId: 2204
+ iMeasType: 1
+ measCollectionMethod: CC
+ measCondition: "This measurement is updated when X2AP: SgNB Modification Required message is \sent\ to MeNB
+ with the SCG Change Indication set as PSCellChange."
+ measDescription: This counter indicates the number of intra gNB intra frequency PSCell change attempts.
+ measFamily: NINFC
+ measInfoId: "NR Intra Frequency PSCell Change"
+ measLastChange: 5G18A_1807_003
+ measObjClass: NGCELL
+ measResultRange: 0-4096
+ measResultType: integer
+ measResultUnits: number
+ measType: VS.NINFC.IntraFrPscelChAttempt
+ measAdditionalFields:
+ vendorField1: X
+ vendorField2: B
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml
new file mode 100644
index 0000000..a125b13
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema.yaml
@@ -0,0 +1,39 @@
+---
+pmMetaData: { presence: required, structure: {
+ pmHeader: {
+ presence: required,
+ structure: {
+ nfType: {
+ presence: required,
+ comment: "nfType comment"
+ }
+ }
+ },
+ pmFields: {
+ presence: required,
+ structure: {
+ measChangeType: {
+ presence: required,
+ value: [added, modified, deleted],
+ comment: "measChangeType comment"
+ },
+ measAdditionalFields: {
+ presence: required,
+ comment: "measAdditionalFields comment",
+ structure: {
+ vendorField1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "vendorField1 comment"
+ },
+ vendorField2: {
+ presence: optional,
+ value: [A, B],
+ comment: "vendorField2 comment"
+ }
+ }
+ }
+ }
+ }
+}}
+...
diff --git a/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml
new file mode 100644
index 0000000..d73ca4f
--- /dev/null
+++ b/dictionaryvalidation/src/test/resources/yaml_schema/Simple_Valid_Schema_Multi_Root.yaml
@@ -0,0 +1,23 @@
+---
+root1: { presence: required, structure: {
+ field1: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "field 1 description"
+ }
+}}
+root2: { presence: required, structure: {
+ field2: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "field 1 description"
+ }
+}}
+root3: { presence: required, structure: {
+ field3: {
+ presence: required,
+ value: [X, Y, Z],
+ comment: "field 1 description"
+ }
+}}
+...