aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--checkstyle/src/main/resources/apache-license-2.regexp.txt15
-rw-r--r--checkstyle/src/main/resources/cps-checkstyle/check-license.xml38
-rw-r--r--checkstyle/src/main/resources/cps-checkstyle/cps-java-style.xml342
-rw-r--r--checkstyle/src/main/resources/cps-java-style.xml35
-rw-r--r--cps-ncmp-rest/pom.xml2
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DeprecationHelper.java17
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java22
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java59
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy16
-rw-r--r--cps-parent/pom.xml210
-rw-r--r--cps-rest/docs/openapi/components.yml4
-rw-r--r--cps-rest/docs/openapi/cpsDataV2.yml9
-rwxr-xr-xcps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java28
-rwxr-xr-xcps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy21
-rw-r--r--cps-service/pom.xml5
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java4
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/ContentType.java10
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java87
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/utils/ContentTypeSpec.groovy37
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/utils/XmlFileUtilsSpec.groovy57
-rw-r--r--docs/api/swagger/cps/openapi.yaml52
-rw-r--r--pom.xml7
23 files changed, 886 insertions, 193 deletions
diff --git a/checkstyle/src/main/resources/apache-license-2.regexp.txt b/checkstyle/src/main/resources/apache-license-2.regexp.txt
new file mode 100644
index 0000000000..80f7be3fd8
--- /dev/null
+++ b/checkstyle/src/main/resources/apache-license-2.regexp.txt
@@ -0,0 +1,15 @@
+^/[*]+$
+^ \* Copyright .*$
+^ \*( )?$
+^ \* 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.
+^ [*]+/$ \ No newline at end of file
diff --git a/checkstyle/src/main/resources/cps-checkstyle/check-license.xml b/checkstyle/src/main/resources/cps-checkstyle/check-license.xml
new file mode 100644
index 0000000000..a19dbe98e8
--- /dev/null
+++ b/checkstyle/src/main/resources/cps-checkstyle/check-license.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<!--
+# ============LICENSE_START=======================================================
+# Copyright (C) 2024 Nordix Foundation
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+-->
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+<!-- Checks the license headers expected by ONAP. -->
+<module name="Checker">
+ <property name="charset" value="UTF-8"/>
+ <property name="severity" value="error"/>
+ <module name="RegexpSingleline">
+ <property name="format" value="under the Apache License, Version 2\.0"/>
+ <property name="minimum" value="1"/>
+ <property name="maximum" value="10"/>
+ </module>
+ <module name="RegexpSingleline">
+ <property name="format" value="http://www.apache\.org/licenses/LICENSE-2\.0"/>
+ <property name="minimum" value="1"/>
+ <property name="maximum" value="10"/>
+ </module>
+</module> \ No newline at end of file
diff --git a/checkstyle/src/main/resources/cps-checkstyle/cps-java-style.xml b/checkstyle/src/main/resources/cps-checkstyle/cps-java-style.xml
new file mode 100644
index 0000000000..6e1664a4a3
--- /dev/null
+++ b/checkstyle/src/main/resources/cps-checkstyle/cps-java-style.xml
@@ -0,0 +1,342 @@
+<?xml version="1.0"?>
+<!--
+ Copyright (C) 2024 Nordix Foundation.
+
+ 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.
+-->
+<!DOCTYPE module PUBLIC
+ "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
+ "https://checkstyle.org/dtds/configuration_1_3.dtd">
+
+<!--
+ Checkstyle configuration that checks the Google coding conventions from Google Java Style
+ that can be found at https://google.github.io/styleguide/javaguide.html
+
+ Checkstyle is very configurable. Be sure to read the documentation at
+ http://checkstyle.org (or in your downloaded distribution).
+
+ To completely disable a check, just comment it out or delete it from the file.
+ To suppress certain violations please review suppression filters.
+
+ Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
+ -->
+
+<!--
+To update the checkstyle version in ONAP see:
+https://lf-onap.atlassian.net/wiki/spaces/DW/pages/16429749/How+to+update+ONAP+checkstyle+when+Checkstyle+steps+their+version
+ -->
+
+<module name="Checker">
+ <property name="charset" value="UTF-8" />
+
+ <property name="severity" value="warning" />
+
+ <property name="fileExtensions" value="java, properties, xml" />
+ <!-- Excludes all 'module-info.java' files -->
+ <!-- See https://checkstyle.org/config_filefilters.html -->
+ <module name="BeforeExecutionExclusionFileFilter">
+ <property name="fileNamePattern" value="module\-info\.java$" />
+ </module>
+ <!-- https://checkstyle.org/config_filters.html#SuppressionFilter -->
+ <module name="SuppressionFilter">
+ <property name="file" value="${org.checkstyle.google.suppressionfilter.config}"
+ default="checkstyle-suppressions.xml" />
+ <property name="optional" value="true" />
+ </module>
+ <module name="SuppressWarningsFilter"/>
+
+ <!-- Checks for whitespace -->
+ <!-- See http://checkstyle.org/config_whitespace.html -->
+ <module name="FileTabCharacter">
+ <property name="eachLine" value="true" />
+ </module>
+
+ <module name="LineLength">
+ <property name="fileExtensions" value="java" />
+ <property name="max" value="120" />
+ <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://" />
+ </module>
+
+ <module name="TreeWalker">
+ <module name="OuterTypeFilename" />
+ <module name="IllegalTokenText">
+ <property name="tokens" value="STRING_LITERAL, CHAR_LITERAL" />
+ <property name="format"
+ value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)" />
+ <property name="message"
+ value="Consider using special escape sequence instead of octal value or Unicode escaped value." />
+ </module>
+ <module name="AvoidEscapedUnicodeCharacters">
+ <property name="allowEscapesForControlCharacters" value="true" />
+ <property name="allowByTailComment" value="true" />
+ <property name="allowNonPrintableEscapes" value="true" />
+ </module>
+ <module name="AvoidStarImport" />
+ <module name="OneTopLevelClass" />
+ <module name="NoLineWrap">
+ <property name="tokens" value="PACKAGE_DEF, IMPORT, STATIC_IMPORT" />
+ </module>
+ <module name="EmptyBlock">
+ <property name="option" value="TEXT" />
+ <property name="tokens"
+ value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH" />
+ </module>
+ <module name="NeedBraces">
+ <property name="tokens" value="LITERAL_DO, LITERAL_ELSE, LITERAL_FOR, LITERAL_IF, LITERAL_WHILE" />
+ </module>
+ <module name="LeftCurly">
+ <property name="tokens"
+ value="ANNOTATION_DEF, CLASS_DEF, CTOR_DEF, ENUM_CONSTANT_DEF, ENUM_DEF,
+ INTERFACE_DEF, LAMBDA, LITERAL_CASE, LITERAL_CATCH, LITERAL_DEFAULT,
+ LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF,
+ LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE, METHOD_DEF,
+ OBJBLOCK, STATIC_INIT" />
+ </module>
+ <module name="RightCurly">
+ <property name="id" value="RightCurlySame" />
+ <property name="tokens"
+ value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE,
+ LITERAL_DO" />
+ </module>
+ <module name="RightCurly">
+ <property name="id" value="RightCurlyAlone" />
+ <property name="option" value="alone" />
+ <property name="tokens"
+ value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT,
+ INSTANCE_INIT, ANNOTATION_DEF, ENUM_DEF" />
+ </module>
+ <module name="SuppressionXpathSingleFilter">
+ <!-- suppression is required till https://github.com/checkstyle/checkstyle/issues/7541 -->
+ <property name="id" value="RightCurlyAlone" />
+ <property name="query"
+ value="//RCURLY[parent::SLIST[count(./*)=1]
+ or preceding-sibling::*[last()][self::LCURLY]]" />
+ </module>
+ <module name="WhitespaceAfter">
+ <property name="tokens"
+ value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE,
+ LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE" />
+ </module>
+ <module name="WhitespaceAround">
+ <property name="allowEmptyConstructors" value="true" />
+ <property name="allowEmptyLambdas" value="true" />
+ <property name="allowEmptyMethods" value="true" />
+ <property name="allowEmptyTypes" value="true" />
+ <property name="allowEmptyLoops" value="true" />
+ <property name="tokens"
+ value="ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR,
+ BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, DO_WHILE, EQUAL, GE, GT, LAMBDA, LAND,
+ LCURLY, LE, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY,
+ LITERAL_FOR, LITERAL_IF, LITERAL_RETURN, LITERAL_SWITCH, LITERAL_SYNCHRONIZED,
+ LITERAL_TRY, LITERAL_WHILE, LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN,
+ NOT_EQUAL, PLUS, PLUS_ASSIGN, QUESTION, RCURLY, SL, SLIST, SL_ASSIGN, SR,
+ SR_ASSIGN, STAR, STAR_ASSIGN, LITERAL_ASSERT, TYPE_EXTENSION_AND" />
+ <message key="ws.notFollowed"
+ value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)" />
+ <message key="ws.notPreceded" value="WhitespaceAround: ''{0}'' is not preceded with whitespace." />
+ </module>
+ <module name="OneStatementPerLine" />
+ <module name="MultipleVariableDeclarations" />
+ <module name="ArrayTypeStyle" />
+ <module name="MissingSwitchDefault" />
+ <module name="FallThrough" />
+ <module name="UpperEll" />
+ <module name="ModifierOrder" />
+ <module name="EmptyLineSeparator">
+ <property name="tokens"
+ value="PACKAGE_DEF, IMPORT, STATIC_IMPORT, CLASS_DEF, INTERFACE_DEF, ENUM_DEF,
+ STATIC_INIT, INSTANCE_INIT, METHOD_DEF, CTOR_DEF, VARIABLE_DEF" />
+ <property name="allowNoEmptyLineBetweenFields" value="true" />
+ </module>
+ <module name="SeparatorWrap">
+ <property name="id" value="SeparatorWrapDot" />
+ <property name="tokens" value="DOT" />
+ <property name="option" value="nl" />
+ </module>
+ <module name="SeparatorWrap">
+ <property name="id" value="SeparatorWrapComma" />
+ <property name="tokens" value="COMMA" />
+ <property name="option" value="EOL" />
+ </module>
+ <module name="SeparatorWrap">
+ <!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
+ <property name="id" value="SeparatorWrapEllipsis" />
+ <property name="tokens" value="ELLIPSIS" />
+ <property name="option" value="EOL" />
+ </module>
+ <module name="SeparatorWrap">
+ <!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
+ <property name="id" value="SeparatorWrapArrayDeclarator" />
+ <property name="tokens" value="ARRAY_DECLARATOR" />
+ <property name="option" value="EOL" />
+ </module>
+ <module name="SeparatorWrap">
+ <property name="id" value="SeparatorWrapMethodRef" />
+ <property name="tokens" value="METHOD_REF" />
+ <property name="option" value="nl" />
+ </module>
+ <module name="PackageName">
+ <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$" />
+ <message key="name.invalidPattern" value="Package name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="TypeName">
+ <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF" />
+ <message key="name.invalidPattern" value="Type name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="MemberName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$" />
+ <message key="name.invalidPattern" value="Member name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="ParameterName">
+ <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$" />
+ <message key="name.invalidPattern" value="Parameter name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="LambdaParameterName">
+ <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$" />
+ <message key="name.invalidPattern" value="Lambda parameter name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="CatchParameterName">
+ <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$" />
+ <message key="name.invalidPattern" value="Catch parameter name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="LocalVariableName">
+ <property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$" />
+ <message key="name.invalidPattern" value="Local variable name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="ClassTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
+ <message key="name.invalidPattern" value="Class type name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="MethodTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
+ <message key="name.invalidPattern" value="Method type name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="InterfaceTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
+ <message key="name.invalidPattern" value="Interface type name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="NoFinalizer" />
+ <module name="GenericWhitespace">
+ <message key="ws.followed" value="GenericWhitespace ''{0}'' is followed by whitespace." />
+ <message key="ws.preceded" value="GenericWhitespace ''{0}'' is preceded with whitespace." />
+ <message key="ws.illegalFollow" value="GenericWhitespace ''{0}'' should followed by whitespace." />
+ <message key="ws.notPreceded" value="GenericWhitespace ''{0}'' is not preceded with whitespace." />
+ </module>
+ <module name="Indentation">
+ <property name="basicOffset" value="4" />
+ <property name="braceAdjustment" value="0" />
+ <property name="caseIndent" value="4" />
+ <property name="throwsIndent" value="4" />
+ <property name="lineWrappingIndentation" value="4" />
+ <property name="arrayInitIndent" value="4" />
+ </module>
+ <module name="AbbreviationAsWordInName">
+ <property name="ignoreFinal" value="false" />
+ <property name="allowedAbbreviationLength" value="1" />
+ <property name="tokens"
+ value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, ANNOTATION_DEF, ANNOTATION_FIELD_DEF,
+ PARAMETER_DEF, VARIABLE_DEF, METHOD_DEF" />
+ </module>
+ <module name="OverloadMethodsDeclarationOrder" />
+ <module name="VariableDeclarationUsageDistance" />
+ <module name="CustomImportOrder">
+ <property name="sortImportsInGroupAlphabetically" value="true" />
+ <property name="separateLineBetweenGroups" value="true" />
+ <property name="customImportOrderRules" value="STATIC###THIRD_PARTY_PACKAGE" />
+ <property name="tokens" value="IMPORT, STATIC_IMPORT, PACKAGE_DEF" />
+ </module>
+ <module name="MethodParamPad">
+ <property name="tokens"
+ value="CTOR_DEF, LITERAL_NEW, METHOD_CALL, METHOD_DEF,
+ SUPER_CTOR_CALL, ENUM_CONSTANT_DEF" />
+ </module>
+ <module name="NoWhitespaceBefore">
+ <property name="tokens"
+ value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS,
+ LABELED_STAT, METHOD_REF" />
+ <property name="allowLineBreaks" value="true" />
+ </module>
+ <module name="ParenPad">
+ <property name="tokens"
+ value="ANNOTATION, ANNOTATION_FIELD_DEF, CTOR_CALL, CTOR_DEF, DOT, ENUM_CONSTANT_DEF,
+ EXPR, LITERAL_CATCH, LITERAL_DO, LITERAL_FOR, LITERAL_IF, LITERAL_NEW,
+ LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_WHILE, METHOD_CALL,
+ METHOD_DEF, QUESTION, RESOURCE_SPECIFICATION, SUPER_CTOR_CALL, LAMBDA" />
+ </module>
+ <module name="OperatorWrap">
+ <property name="option" value="NL" />
+ <property name="tokens"
+ value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR,
+ LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF " />
+ </module>
+ <module name="AnnotationLocation">
+ <property name="id" value="AnnotationLocationMostCases" />
+ <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF" />
+ </module>
+ <module name="AnnotationLocation">
+ <property name="id" value="AnnotationLocationVariables" />
+ <property name="tokens" value="VARIABLE_DEF" />
+ <property name="allowSamelineMultipleAnnotations" value="true" />
+ </module>
+ <module name="NonEmptyAtclauseDescription" />
+ <module name="InvalidJavadocPosition" />
+ <module name="JavadocTagContinuationIndentation" />
+ <module name="SummaryJavadoc">
+ <property name="forbiddenSummaryFragments"
+ value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )" />
+ </module>
+ <module name="JavadocParagraph" />
+ <module name="AtclauseOrder">
+ <property name="tagOrder" value="@param, @return, @throws, @deprecated" />
+ <property name="target"
+ value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF" />
+ </module>
+ <module name="JavadocMethod">
+ <property name="allowMissingParamTags" value="true" />
+ <property name="allowMissingReturnTag" value="true" />
+ <property name="allowedAnnotations" value="Override, Test" />
+ <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF" />
+ </module>
+ <module name="MissingJavadocMethod">
+ <property name="minLineCount" value="2" />
+ <property name="allowedAnnotations" value="Override, Test" />
+ <property name="tokens" value="METHOD_DEF, CTOR_DEF, ANNOTATION_FIELD_DEF" />
+ <property name="ignoreMethodNamesRegex" value="^(test|before|after)[a-zA-Z0-9_]*$" />
+ </module>
+ <module name="MethodName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$" />
+ <message key="name.invalidPattern" value="Method name ''{0}'' must match pattern ''{1}''." />
+ </module>
+ <module name="SingleLineJavadoc">
+ <property name="ignoreInlineTags" value="false" />
+ </module>
+ <module name="EmptyCatchBlock">
+ <property name="exceptionVariableName" value="expected" />
+ </module>
+ <module name="CommentsIndentation">
+ <property name="tokens" value="SINGLE_LINE_COMMENT, BLOCK_COMMENT_BEGIN" />
+ </module>
+ <!-- https://checkstyle.org/config_filters.html#SuppressionXpathFilter -->
+ <module name="SuppressionXpathFilter">
+ <property name="file" value="${org.checkstyle.google.suppressionxpathfilter.config}"
+ default="checkstyle-xpath-suppressions.xml" />
+ <property name="optional" value="true" />
+ </module>
+ <module name="SuppressWarningsHolder"/>
+ <module name="FinalLocalVariable">
+ <property name="tokens" value="VARIABLE_DEF,PARAMETER_DEF"/>
+ <property name="validateEnhancedForLoopVariable" value="true"/>
+ </module>
+ <module name="UnusedImports"/>
+ </module>
+</module> \ No newline at end of file
diff --git a/checkstyle/src/main/resources/cps-java-style.xml b/checkstyle/src/main/resources/cps-java-style.xml
deleted file mode 100644
index d10484c31e..0000000000
--- a/checkstyle/src/main/resources/cps-java-style.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0"?>
-<!--
-============LICENSE_START=======================================================
- Copyright (C) 2020 Pantheon.tech
- ================================================================================
- 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.
-
- SPDX-License-Identifier: Apache-2.0
- ============LICENSE_END=========================================================
--->
-<!DOCTYPE module PUBLIC
- "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
- "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-<module name="Checker">
- <property name="charset" value="UTF-8"/>
- <property name="severity" value="warning"/>
- <property name="fileExtensions" value="java, properties, xml"/>
-
- <module name="TreeWalker">
- <module name="FinalLocalVariable">
- <property name="tokens" value="VARIABLE_DEF,PARAMETER_DEF"/>
- <property name="validateEnhancedForLoopVariable" value="true"/>
- </module>
- <module name="UnusedImports"/>
- </module>
-</module>
diff --git a/cps-ncmp-rest/pom.xml b/cps-ncmp-rest/pom.xml
index c78fe55a59..681d1e52b4 100644
--- a/cps-ncmp-rest/pom.xml
+++ b/cps-ncmp-rest/pom.xml
@@ -35,6 +35,7 @@
<properties>
<minimum-coverage>0.99</minimum-coverage>
+ <maven-resources-plugin.version>3.2.0</maven-resources-plugin.version>
</properties>
<dependencies>
@@ -211,6 +212,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
+ <version>${maven-resources-plugin.version}</version>
<executions>
<execution>
<id>copy-resources</id>
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DeprecationHelper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DeprecationHelper.java
index 7492c1fcac..f5804d73ad 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DeprecationHelper.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/util/DeprecationHelper.java
@@ -36,13 +36,19 @@ public class DeprecationHelper {
private final JsonObjectMapper jsonObjectMapper;
/**
- * Convert the old condition properties to the new schema.
- * !!! remove it after the old condition removed !!!
- * it only works for module names
+ * Converts the old condition properties from {@link CmHandleQueryParameters}
+ * to the new schema defined in {@link CmHandleQueryApiParameters}.
*
- * @deprecated this method will be removed in Release 12 (No Name know yet)
+ * <p>This method transforms the old module name-based condition properties to the new format.
+ * It should only be used for backward compatibility until the old conditions
+ * are removed in future releases.
*
- * @param cmHandleQueryParameters the original input parameter
+ * <p><b>Important:</b> This method will be removed in next release(release name not finalized yet).</p>
+ *
+ * @param cmHandleQueryParameters the original query parameters containing old condition properties
+ * @return an instance of {@link CmHandleQueryApiParameters} with the transformed condition properties
+ * @deprecated This method is deprecated and will be removed in Release 12.
+ * Use the new condition handling approach instead.
*/
@Deprecated
public CmHandleQueryApiParameters mapOldConditionProperties(
@@ -69,7 +75,6 @@ public class DeprecationHelper {
}
);
}
-
return cmHandleQueryApiParameters;
}
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java
index 70d08dccdc..e13d3c2328 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminer.java
@@ -32,6 +32,7 @@ import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation;
import org.onap.cps.ncmp.api.datajobs.models.ProducerKey;
import org.onap.cps.ncmp.api.datajobs.models.WriteOperation;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.ncmp.impl.models.RequiredDmiService;
import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher;
import org.onap.cps.ncmp.impl.utils.YangDataConverter;
import org.onap.cps.spi.model.DataNode;
@@ -69,9 +70,11 @@ public class WriteRequestExaminer {
final DataNode dataNode = alternateIdMatcher
.getCmHandleDataNodeByLongestMatchingAlternateId(writeOperation.path(), PATH_SEPARATOR);
- final DmiWriteOperation dmiWriteOperation = createDmiWriteOperation(writeOperation, dataNode);
+ final YangModelCmHandle yangModelCmHandle = YangDataConverter.toYangModelCmHandle(dataNode);
+
+ final DmiWriteOperation dmiWriteOperation = createDmiWriteOperation(writeOperation, yangModelCmHandle);
- final ProducerKey producerKey = createProducerKey(dataNode);
+ final ProducerKey producerKey = createProducerKey(yangModelCmHandle);
final List<DmiWriteOperation> dmiWriteOperations;
if (dmiWriteOperationsPerProducerKey.containsKey(producerKey)) {
dmiWriteOperations = dmiWriteOperationsPerProducerKey.get(producerKey);
@@ -82,24 +85,23 @@ public class WriteRequestExaminer {
dmiWriteOperations.add(dmiWriteOperation);
}
- private ProducerKey createProducerKey(final DataNode dataNode) {
- return new ProducerKey((String) dataNode.getLeaves().get("dmi-service-name"),
- (String) dataNode.getLeaves().get("data-producer-identifier"));
+ private ProducerKey createProducerKey(final YangModelCmHandle yangModelCmHandle) {
+ return new ProducerKey(yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA),
+ yangModelCmHandle.getDataProducerIdentifier());
}
private DmiWriteOperation createDmiWriteOperation(final WriteOperation writeOperation,
- final DataNode dataNode) {
+ final YangModelCmHandle yangModelCmHandle) {
return new DmiWriteOperation(
writeOperation.path(),
writeOperation.op(),
- (String) dataNode.getLeaves().get("module-set-tag"),
+ yangModelCmHandle.getModuleSetTag(),
writeOperation.value(),
writeOperation.operationId(),
- getPrivatePropertiesFromDataNode(dataNode));
+ getPrivatePropertiesFromDataNode(yangModelCmHandle));
}
- private Map<String, String> getPrivatePropertiesFromDataNode(final DataNode dataNode) {
- final YangModelCmHandle yangModelCmHandle = YangDataConverter.toYangModelCmHandle(dataNode);
+ private Map<String, String> getPrivatePropertiesFromDataNode(final YangModelCmHandle yangModelCmHandle) {
final Map<String, String> cmHandleDmiProperties = new LinkedHashMap<>();
yangModelCmHandle.getDmiProperties()
.forEach(dmiProperty -> cmHandleDmiProperties.put(dmiProperty.getName(), dmiProperty.getValue()));
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
index 80cdea8b7b..31fcbad08b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncTasks.java
@@ -58,36 +58,16 @@ public class ModuleSyncTasks {
*/
public CompletableFuture<Void> performModuleSync(final Collection<DataNode> cmHandlesAsDataNodes,
final AtomicInteger batchCounter) {
+ final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle =
+ new HashMap<>(cmHandlesAsDataNodes.size());
try {
- final Map<YangModelCmHandle, CmHandleState> cmHandelStatePerCmHandle
- = new HashMap<>(cmHandlesAsDataNodes.size());
- for (final DataNode cmHandleAsDataNode : cmHandlesAsDataNodes) {
- final String cmHandleId = String.valueOf(cmHandleAsDataNode.getLeaves().get("id"));
+ cmHandlesAsDataNodes.forEach(cmHandleAsDataNode -> {
final YangModelCmHandle yangModelCmHandle = YangDataConverter.toYangModelCmHandle(cmHandleAsDataNode);
- final CompositeState compositeState = inventoryPersistence.getCmHandleState(cmHandleId);
- final boolean inUpgrade = ModuleOperationsUtils.inUpgradeOrUpgradeFailed(compositeState);
- try {
- if (inUpgrade) {
- moduleSyncService.syncAndUpgradeSchemaSet(yangModelCmHandle);
- } else {
- moduleSyncService.deleteSchemaSetIfExists(cmHandleId);
- moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle);
- }
- yangModelCmHandle.getCompositeState().setLockReason(null);
- cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.READY);
- } catch (final Exception e) {
- log.warn("Processing of {} module failed due to reason {}.", cmHandleId, e.getMessage());
- final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED
- : LockReasonCategory.MODULE_SYNC_FAILED;
- moduleOperationsUtils.updateLockReasonWithAttempts(compositeState,
- lockReasonCategory, e.getMessage());
- setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason());
- cmHandelStatePerCmHandle.put(yangModelCmHandle, CmHandleState.LOCKED);
- }
- }
- lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandelStatePerCmHandle);
+ cmHandleStatePerCmHandle.put(yangModelCmHandle, processCmHandle(yangModelCmHandle));
+ });
} finally {
batchCounter.getAndDecrement();
+ lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
log.info("Processing module sync batch finished. {} batch(es) active.", batchCounter.get());
}
return CompletableFuture.completedFuture(null);
@@ -107,13 +87,36 @@ public class ModuleSyncTasks {
final CompositeState compositeState = yangModelCmHandle.getCompositeState();
final String resetCmHandleId = yangModelCmHandle.getId();
log.debug("Resetting CM handle {} state to ADVISED for retry by the module-sync watchdog. Lock reason: {}",
- yangModelCmHandle.getId(), compositeState.getLockReason().getLockReasonCategory().name());
+ yangModelCmHandle.getId(), compositeState.getLockReason().getLockReasonCategory().name());
cmHandleStatePerCmHandle.put(yangModelCmHandle, CmHandleState.ADVISED);
removeResetCmHandleFromModuleSyncMap(resetCmHandleId);
}
lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle);
}
+ private CmHandleState processCmHandle(final YangModelCmHandle yangModelCmHandle) {
+ final CompositeState compositeState = inventoryPersistence.getCmHandleState(yangModelCmHandle.getId());
+ final boolean inUpgrade = ModuleOperationsUtils.inUpgradeOrUpgradeFailed(compositeState);
+ try {
+ if (inUpgrade) {
+ moduleSyncService.syncAndUpgradeSchemaSet(yangModelCmHandle);
+ } else {
+ moduleSyncService.deleteSchemaSetIfExists(yangModelCmHandle.getId());
+ moduleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle);
+ }
+ yangModelCmHandle.getCompositeState().setLockReason(null);
+ return CmHandleState.READY;
+ } catch (final Exception e) {
+ log.warn("Processing of {} module failed due to reason {}.", yangModelCmHandle.getId(), e.getMessage());
+ final LockReasonCategory lockReasonCategory = inUpgrade ? LockReasonCategory.MODULE_UPGRADE_FAILED
+ : LockReasonCategory.MODULE_SYNC_FAILED;
+ moduleOperationsUtils.updateLockReasonWithAttempts(compositeState,
+ lockReasonCategory, e.getMessage());
+ setCmHandleStateLocked(yangModelCmHandle, compositeState.getLockReason());
+ return CmHandleState.LOCKED;
+ }
+ }
+
private void setCmHandleStateLocked(final YangModelCmHandle advisedCmHandle,
final CompositeState.LockReason lockReason) {
advisedCmHandle.getCompositeState().setLockReason(lockReason);
@@ -124,4 +127,4 @@ public class ModuleSyncTasks {
log.info("{} removed from in progress map", resetCmHandleId);
}
}
-}
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java
index 8ae942eb7b..eefabd1079 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java
@@ -57,7 +57,7 @@ public class WebClientConfiguration {
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, serviceConfig.getConnectionTimeoutInSeconds() * 1000)
.doOnConnected(connection -> connection.addHandlerLast(new ReadTimeoutHandler(
serviceConfig.getReadTimeoutInSeconds(), TimeUnit.SECONDS)).addHandlerLast(
- new WriteTimeoutHandler(serviceConfig.getWriteTimeoutInSeconds(), TimeUnit.SECONDS)))
+ new WriteTimeoutHandler(serviceConfig.getWriteTimeoutInSeconds(), TimeUnit.SECONDS)))
.resolver(DefaultAddressResolverGroup.INSTANCE)
.compress(true);
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy
index 84eb78b751..47b57669ca 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/WriteRequestExaminerSpec.groovy
@@ -3,6 +3,8 @@ package org.onap.cps.ncmp.impl.datajobs
import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest
import org.onap.cps.ncmp.api.datajobs.models.WriteOperation
+import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher
import org.onap.cps.spi.model.DataNode
import spock.lang.Specification
@@ -60,4 +62,18 @@ class WriteRequestExaminerSpec extends Specification {
then: 'we get the operation ids in the expected order.'
assert dmiWriteOperations.operationId == ['1', '2', '3']
}
+
+ def 'Validate the creation of a ProducerKey with correct dmiservicename.'() {
+ given: 'yangModelCmHandles with service name: "#dmiServiceName" and data service name: "#dataServiceName"'
+ def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dataServiceName, '', new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1'), '', '', 'dpi1')
+ when: 'the ProducerKey is created'
+ def result = objectUnderTest.createProducerKey(yangModelCmHandle).toString()
+ then: 'we get the ProducerKey with the correct service name'
+ assert result == expectedProducerKey
+ where: 'the following services are registered'
+ dmiServiceName | dataServiceName || expectedProducerKey
+ 'dmi-service-name' | '' || 'dmi-service-name#dpi1'
+ '' | 'dmi-data-service-name' || 'dmi-data-service-name#dpi1'
+ 'dmi-service-name' | 'dmi-data-service-name' || 'dmi-service-name#dpi1'
+ }
}
diff --git a/cps-parent/pom.xml b/cps-parent/pom.xml
index a83278d6cd..6776008acf 100644
--- a/cps-parent/pom.xml
+++ b/cps-parent/pom.xml
@@ -22,33 +22,76 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <groupId>org.onap.oparent</groupId>
- <artifactId>oparent</artifactId>
- <version>3.2.0</version>
- <relativePath/>
- </parent>
- <modelVersion>4.0.0</modelVersion>
+ <!-- Project Metadata -->
+ <modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>cps-parent</artifactId>
<version>3.5.5-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
+ <!-- Set UTF-8 encoding for consistent builds across platforms -->
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+ <!-- Application Configuration -->
<app>org.onap.cps.Application</app>
+
+ <!-- Parent Directory Configuration -->
+ <parent.directory>${project.basedir}/..</parent.directory>
+
+ <!-- Global properties for version management -->
+ <bug.pattern.version>1.5.0</bug.pattern.version>
+ <dependency.check.version>9.2.0</dependency.check.version>
+ <git.commit.id.version>9.0.0</git.commit.id.version>
+ <gmavenplus.plugin.version>4.0.1</gmavenplus.plugin.version>
+ <jacoco.version>0.8.11</jacoco.version>
<java.version>17</java.version>
- <minimum-coverage>1.00</minimum-coverage>
+ <jsonschema2pojo.maven.plugin.version>1.2.1</jsonschema2pojo.maven.plugin.version>
+ <maven.checkstyle.plugin.version>3.3.1</maven.checkstyle.plugin.version>
+ <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
+ <maven.compiler.release>17</maven.compiler.release>
+ <maven.site.plugin.version>4.0.0-M13</maven.site.plugin.version>
+ <maven.surefire.plugin.version>3.2.5</maven.surefire.plugin.version>
<postgres.version>42.5.1</postgres.version>
+ <slf4j.simple.version>2.0.6</slf4j.simple.version>
+ <sonar.version>4.0.0.4121</sonar.version>
+ <spotbugs.plugin.version>4.8.6.4</spotbugs.plugin.version>
+ <spotbugs.version>4.8.6</spotbugs.version>
+ <spring.boot.maven.plugin.version>3.2.4</spring.boot.maven.plugin.version>
+ <swagger.codegen.version>1.2.1</swagger.codegen.version>
+ <!-- Reporting paths and coverage -->
+ <jacoco.execFile>${project.build.directory}/code-coverage/jacoco-ut.exec</jacoco.execFile>
+ <jacoco.outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</jacoco.outputDirectory>
<jacoco.reportDirectory.aggregate>${project.reporting.outputDirectory}/jacoco-aggregate</jacoco.reportDirectory.aggregate>
+ <minimum-coverage>1.00</minimum-coverage>
<sonar.coverage.jacoco.xmlReportPaths>
../jacoco-report/target/site/jacoco-aggregate/jacoco.xml
</sonar.coverage.jacoco.xmlReportPaths>
- <parent.directory>${project.basedir}/..</parent.directory>
- <maven.compiler.release>17</maven.compiler.release>
</properties>
+ <!-- Dependency Management, Profiles, Build, and Plugins -->
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.cps</groupId>
+ <artifactId>cps-dependencies</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.cps</groupId>
+ <artifactId>cps-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
<profiles>
<profile>
<id>Windows</id>
@@ -72,27 +115,27 @@
<script.executor>python3</script.executor>
</properties>
</profile>
+ <profile>
+ <id>dependency-vulnerability-check</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.owasp</groupId>
+ <artifactId>dependency-check-maven</artifactId>
+ <version>${dependency.check.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>aggregate</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
</profiles>
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>org.onap.cps</groupId>
- <artifactId>cps-dependencies</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- <dependency>
- <groupId>org.onap.cps</groupId>
- <artifactId>cps-bom</artifactId>
- <version>${project.version}</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
-
<build>
<resources>
<resource>
@@ -118,7 +161,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
- <version>3.2.4</version>
+ <version>${spring.boot.maven.plugin.version}</version>
<executions>
<execution>
<goals>
@@ -130,7 +173,7 @@
<plugin>
<groupId>io.github.git-commit-id</groupId>
<artifactId>git-commit-id-maven-plugin</artifactId>
- <version>9.0.0</version>
+ <version>${git.commit.id.version}</version>
<executions>
<execution>
<id>get-git-info</id>
@@ -141,11 +184,6 @@
</execution>
</executions>
</plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>3.0.0-M5</version>
- </plugin>
<!-- Swagger code generation. -->
<plugin>
<groupId>io.swagger.codegen.v3</groupId>
@@ -167,12 +205,12 @@
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
- <version>4.8.6.4</version>
+ <version>${spotbugs.plugin.version}</version>
<dependencies>
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
- <version>4.8.6</version>
+ <version>${spotbugs.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -183,7 +221,7 @@
<!-- The SpotBugs Maven plugin uses SLF4J 1.8 beta 2 -->
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
- <version>2.0.6</version>
+ <version>${slf4j.simple.version}</version>
</dependency>
</dependencies>
<configuration>
@@ -191,7 +229,7 @@
<plugin>
<groupId>jp.skypencil.findbugs.slf4j</groupId>
<artifactId>bug-pattern</artifactId>
- <version>1.5.0</version>
+ <version>${bug.pattern.version}</version>
</plugin>
</plugins>
<!--
@@ -228,7 +266,7 @@
<plugin>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-maven-plugin</artifactId>
- <version>1.2.1</version>
+ <version>${jsonschema2pojo.maven.plugin.version}</version>
<configuration>
<targetVersion>${java.version}</targetVersion>
</configuration>
@@ -246,11 +284,15 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.11.0</version>
+ <version>${maven.compiler.plugin.version}</version>
+ <configuration>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${maven.checkstyle.plugin.version}</version>
<executions>
<execution>
<id>onap-license</id>
@@ -259,7 +301,7 @@
</goals>
<phase>process-sources</phase>
<configuration>
- <configLocation>onap-checkstyle/check-license.xml</configLocation>
+ <configLocation>cps-checkstyle/check-license.xml</configLocation>
<includeResources>false</includeResources>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<includeTestResources>false</includeTestResources>
@@ -272,39 +314,20 @@
</configuration>
</execution>
<execution>
- <id>onap-java-style</id>
- <goals>
- <goal>check</goal>
- </goals>
- <phase>process-sources</phase>
- <configuration>
- <configLocation>onap-checkstyle/onap-java-style.xml</configLocation>
- <sourceDirectories>
- <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
- </sourceDirectories>
- <includeResources>true</includeResources>
- <includeTestSourceDirectory>true</includeTestSourceDirectory>
- <includeTestResources>true</includeTestResources>
- <consoleOutput>false</consoleOutput>
- <violationSeverity>warning</violationSeverity>
- <failOnViolation>true</failOnViolation>
- </configuration>
- </execution>
- <execution>
<id>cps-java-style</id>
<goals>
<goal>check</goal>
</goals>
<phase>process-sources</phase>
<configuration>
- <configLocation>cps-java-style.xml</configLocation>
+ <configLocation>cps-checkstyle/cps-java-style.xml</configLocation>
<sourceDirectories>
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
</sourceDirectories>
<includeResources>true</includeResources>
<includeTestSourceDirectory>true</includeTestSourceDirectory>
<includeTestResources>true</includeTestResources>
- <consoleOutput>true</consoleOutput>
+ <consoleOutput>false</consoleOutput>
<violationSeverity>warning</violationSeverity>
<failOnViolation>true</failOnViolation>
</configuration>
@@ -312,11 +335,6 @@
</executions>
<dependencies>
<dependency>
- <groupId>org.onap.oparent</groupId>
- <artifactId>checkstyle</artifactId>
- <version>3.2.0</version>
- </dependency>
- <dependency>
<groupId>${project.groupId}</groupId>
<artifactId>checkstyle</artifactId>
<version>${project.version}</version>
@@ -329,7 +347,7 @@
To learn more about this plugin, visit https://github.com/groovy/GMavenPlus/wiki -->
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
- <version>1.9.0</version>
+ <version>${gmavenplus.plugin.version}</version>
<executions>
<execution>
<goals>
@@ -343,6 +361,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
+ <version>${maven.surefire.plugin.version}</version>
<configuration>
<!--suppress UnresolvedMavenProperty -->
<argLine>${surefireArgLine}</argLine>
@@ -371,17 +390,18 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
- <version>0.8.10</version>
+ <version>${jacoco.version}</version>
<configuration>
- <!--All exclusions below are referring to generated code-->
+ <!-- Exclude all generated classes or specific patterns if necessary -->
<excludes>
- <exclude>org/onap/cps/event/model/*</exclude>
+ <exclude>org/onap/cps/events/model/*</exclude>
<exclude>org/onap/cps/rest/model/*</exclude>
<exclude>org/onap/cps/cpspath/parser/antlr4/*</exclude>
<exclude>org/onap/cps/ncmp/rest/model/*</exclude>
<exclude>org/onap/cps/**/*MapperImpl.class</exclude>
<exclude>org/onap/cps/ncmp/rest/stub/*</exclude>
<exclude>org/onap/cps/policyexecutor/stub/model/*</exclude>
+ <exclude>**/pom.xml</exclude>
</excludes>
</configuration>
<executions>
@@ -390,14 +410,19 @@
<goals>
<goal>prepare-agent</goal>
</goals>
+ <configuration>
+ <destFile>${jacoco.execFile}</destFile>
+ <propertyName>surefireArgLine</propertyName>
+ </configuration>
</execution>
<execution>
<id>coverage-check</id>
+ <phase>test</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
- <dataFile>${project.build.directory}/code-coverage/jacoco-ut.exec</dataFile>
+ <dataFile>${jacoco.execFile}</dataFile>
<rules>
<rule>
<element>BUNDLE</element>
@@ -412,17 +437,42 @@
</rules>
</configuration>
</execution>
+ <execution>
+ <id>post-unit-test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <!-- Sets the path to the file which contains the execution data. -->
+ <dataFile>${jacoco.execFile}</dataFile>
+ <!-- Sets the output directory for the code coverage report. -->
+ <outputDirectory>${jacoco.outputDirectory}</outputDirectory>
+ </configuration>
+ </execution>
</executions>
</plugin>
- <plugin>
- <groupId>com.github.spotbugs</groupId>
- <artifactId>spotbugs-maven-plugin</artifactId>
- </plugin>
+
+ <!-- Sonar Plugin for Code Quality -->
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
- <version>3.9.1.2184</version>
+ <version>${sonar.version}</version>
+ </plugin>
+
+ <!-- Maven Site Plugin for Site Generation -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>${maven.site.plugin.version}</version>
+ <executions>
+ <execution>
+ <id>default-site</id>
+ <phase>site</phase>
+ <goals><goal>site</goal></goals>
+ </execution>
+ </executions>
</plugin>
</plugins>
</build>
-</project>
+</project> \ No newline at end of file
diff --git a/cps-rest/docs/openapi/components.yml b/cps-rest/docs/openapi/components.yml
index 40f0e170ff..728295fd31 100644
--- a/cps-rest/docs/openapi/components.yml
+++ b/cps-rest/docs/openapi/components.yml
@@ -293,7 +293,9 @@ components:
description: Content type in header
schema:
type: string
- example: 'application/json'
+ enum:
+ - application/json
+ - application/xml
required: true
descendantsInQuery:
name: descendants
diff --git a/cps-rest/docs/openapi/cpsDataV2.yml b/cps-rest/docs/openapi/cpsDataV2.yml
index d5a8ef3891..999c5b2c19 100644
--- a/cps-rest/docs/openapi/cpsDataV2.yml
+++ b/cps-rest/docs/openapi/cpsDataV2.yml
@@ -28,6 +28,7 @@ nodeByDataspaceAndAnchor:
- $ref: 'components.yml#/components/parameters/anchorNameInPath'
- $ref: 'components.yml#/components/parameters/xpathInQuery'
- $ref: 'components.yml#/components/parameters/descendantsInQuery'
+ - $ref: 'components.yml#/components/parameters/contentTypeInHeader'
responses:
'200':
description: OK
@@ -38,6 +39,14 @@ nodeByDataspaceAndAnchor:
examples:
dataSample:
$ref: 'components.yml#/components/examples/dataSample'
+ application/xml:
+ schema:
+ type: object
+ xml:
+ name: stores
+ examples:
+ dataSample:
+ $ref: 'components.yml#/components/examples/dataSampleXml'
'400':
$ref: 'components.yml#/components/responses/BadRequest'
'403':
diff --git a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
index 7390afcf98..6d22581845 100755
--- a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
+++ b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java
@@ -48,8 +48,8 @@ import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.DataMapUtils;
import org.onap.cps.utils.JsonObjectMapper;
import org.onap.cps.utils.PrefixResolver;
+import org.onap.cps.utils.XmlFileUtils;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -75,7 +75,7 @@ public class DataRestController implements CpsDataApi {
final String contentTypeInHeader,
final String nodeData, final String parentNodeXpath,
final Boolean dryRunEnabled, final String observedTimestamp) {
- final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
+ final ContentType contentType = ContentType.fromString(contentTypeInHeader);
if (Boolean.TRUE.equals(dryRunEnabled)) {
cpsDataService.validateData(dataspaceName, anchorName, parentNodeXpath, nodeData, contentType);
return ResponseEntity.ok().build();
@@ -105,7 +105,7 @@ public class DataRestController implements CpsDataApi {
final String anchorName, final String parentNodeXpath,
final String contentTypeInHeader, final String nodeData,
final String observedTimestamp) {
- final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
+ final ContentType contentType = ContentType.fromString(contentTypeInHeader);
cpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath,
nodeData, toOffsetDateTime(observedTimestamp), contentType);
return new ResponseEntity<>(HttpStatus.CREATED);
@@ -129,8 +129,9 @@ public class DataRestController implements CpsDataApi {
@Timed(value = "cps.data.controller.datanode.get.v2",
description = "Time taken to get data node")
public ResponseEntity<Object> getNodeByDataspaceAndAnchorV2(final String dataspaceName, final String anchorName,
- final String xpath,
+ final String contentTypeInHeader, final String xpath,
final String fetchDescendantsOptionAsString) {
+ final ContentType contentType = ContentType.fromString(contentTypeInHeader);
final FetchDescendantsOption fetchDescendantsOption =
FetchDescendantsOption.getFetchDescendantsOption(fetchDescendantsOptionAsString);
final Collection<DataNode> dataNodes = cpsDataService.getDataNodes(dataspaceName, anchorName, xpath,
@@ -142,7 +143,7 @@ public class DataRestController implements CpsDataApi {
final Map<String, Object> dataMap = DataMapUtils.toDataMapWithIdentifier(dataNode, prefix);
dataMaps.add(dataMap);
}
- return new ResponseEntity<>(jsonObjectMapper.asJsonString(dataMaps), HttpStatus.OK);
+ return buildResponseEntity(dataMaps, contentType);
}
@Override
@@ -150,7 +151,7 @@ public class DataRestController implements CpsDataApi {
final String anchorName, final String contentTypeInHeader,
final String nodeData, final String parentNodeXpath,
final String observedTimestamp) {
- final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
+ final ContentType contentType = ContentType.fromString(contentTypeInHeader);
cpsDataService.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath,
nodeData, toOffsetDateTime(observedTimestamp), contentType);
return new ResponseEntity<>(HttpStatus.OK);
@@ -161,7 +162,7 @@ public class DataRestController implements CpsDataApi {
final String anchorName, final String contentTypeInHeader,
final String nodeData, final String parentNodeXpath,
final String observedTimestamp) {
- final ContentType contentType = getContentTypeFromHeader(contentTypeInHeader);
+ final ContentType contentType = ContentType.fromString(contentTypeInHeader);
cpsDataService.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath,
nodeData, toOffsetDateTime(observedTimestamp), contentType);
return new ResponseEntity<>(HttpStatus.OK);
@@ -219,12 +220,19 @@ public class DataRestController implements CpsDataApi {
final List<DeltaReport> deltaBetweenAnchors =
cpsDataService.getDeltaByDataspaceAndAnchors(dataspaceName, sourceAnchorName,
- targetAnchorName, xpath, fetchDescendantsOption);
+ targetAnchorName, xpath, fetchDescendantsOption);
return new ResponseEntity<>(jsonObjectMapper.asJsonString(deltaBetweenAnchors), HttpStatus.OK);
}
- private static ContentType getContentTypeFromHeader(final String contentTypeInHeader) {
- return contentTypeInHeader.contains(MediaType.APPLICATION_XML_VALUE) ? ContentType.XML : ContentType.JSON;
+ ResponseEntity<Object> buildResponseEntity(final List<Map<String, Object>> dataMaps,
+ final ContentType contentType) {
+ final String responseData;
+ if (contentType == ContentType.XML) {
+ responseData = XmlFileUtils.convertDataMapsToXml(dataMaps);
+ } else {
+ responseData = jsonObjectMapper.asJsonString(dataMaps);
+ }
+ return new ResponseEntity<>(responseData, HttpStatus.OK);
}
private static boolean isRootXpath(final String xpath) {
diff --git a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy
index 705c2fee91..27738b07c6 100755
--- a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy
+++ b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy
@@ -314,7 +314,9 @@ class DataRestControllerSpec extends Specification {
mockCpsDataService.getDataNodes(dataspaceName, anchorName, xpath, OMIT_DESCENDANTS) >> [dataNodeWithLeavesNoChildren, dataNodeWithLeavesNoChildren2]
when: 'V2 of get request is performed through REST API'
def response =
- mvc.perform(get(endpoint).param('xpath', xpath))
+ mvc.perform(get(endpoint)
+ .contentType(MediaType.APPLICATION_JSON)
+ .param('xpath', xpath))
.andReturn().response
then: 'a success response is returned'
response.status == HttpStatus.OK.value()
@@ -326,6 +328,21 @@ class DataRestControllerSpec extends Specification {
assert numberOfDataTrees == 2
}
+ def 'Get all the data trees as XML with root node xPath using V2'() {
+ given: 'the service returns all data node leaves'
+ def xpath = '/'
+ def endpoint = "$dataNodeBaseEndpointV2/anchors/$anchorName/node"
+ mockCpsDataService.getDataNodes(dataspaceName, anchorName, xpath, OMIT_DESCENDANTS) >> [dataNodeWithLeavesNoChildren]
+ when: 'V2 of get request is performed through REST API with XML content type'
+ def response =
+ mvc.perform(get(endpoint).contentType(MediaType.APPLICATION_XML).param('xpath', xpath))
+ .andReturn().response
+ then: 'a success response is returned'
+ response.status == HttpStatus.OK.value()
+ and: 'the response contains the datanode in XML format'
+ response.getContentAsString() == '<parent-1><leaf>value</leaf><leafList>leaveListElement1</leafList><leafList>leaveListElement2</leafList></parent-1>'
+ }
+
def 'Get data node with #scenario using V2.'() {
given: 'the service returns data nodes with #scenario'
def xpath = 'some xPath'
@@ -335,6 +352,7 @@ class DataRestControllerSpec extends Specification {
def response =
mvc.perform(
get(endpoint)
+ .contentType(MediaType.APPLICATION_JSON)
.param('xpath', xpath)
.param('descendants', includeDescendantsOption))
.andReturn().response
@@ -361,6 +379,7 @@ class DataRestControllerSpec extends Specification {
def response =
mvc.perform(
get(endpoint)
+ .contentType(MediaType.APPLICATION_JSON)
.param('xpath', xpath)
.param('descendants', '2'))
.andReturn().response
diff --git a/cps-service/pom.xml b/cps-service/pom.xml
index c7a3666a07..fdd6272660 100644
--- a/cps-service/pom.xml
+++ b/cps-service/pom.xml
@@ -5,6 +5,7 @@
Modifications Copyright (C) 2021 Bell Canada.
Modifications Copyright (C) 2021 Pantheon.tech
Modifications Copyright (C) 2022 Deutsche Telekom AG
+ Modifications Copyright (C) 2024 TechMahindra Ltd.
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -192,5 +193,9 @@
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
index 931209c998..bbfe496d85 100644
--- a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
+++ b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java
@@ -178,8 +178,8 @@ public interface CpsModuleService {
* an attribute key-value pair used in the WHERE clause for parent fragments.
* @param childAttributes a map of attributes to filter child fragments. Each entry in this map represents
* an attribute key-value pair used in the WHERE clause for child fragments.
- * @return a collection of {@link ModuleReference} objects that match the given criteria. Each
- * {@code ModuleReference} contains information about a module's name and revision.
+ * @return a collection of {@link ModuleReference} objects that match the given criteria.
+ * Each {@code ModuleReference} contains information about a module's name and revision.
* @implNote The method assumes that both `parentAttributes` and `childAttributes` maps contain at least
* one entry. The first entry from `parentAttributes` is used to filter parent fragments,
* and the first entry from `childAttributes` is used to filter child fragments.
diff --git a/cps-service/src/main/java/org/onap/cps/utils/ContentType.java b/cps-service/src/main/java/org/onap/cps/utils/ContentType.java
index f888504843..eb8e592d9b 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/ContentType.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/ContentType.java
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Deutsche Telekom AG
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +21,14 @@
package org.onap.cps.utils;
+import org.springframework.http.MediaType;
+
public enum ContentType {
JSON,
- XML
+ XML;
+
+ public static ContentType fromString(final String contentTypeAsString) {
+ return contentTypeAsString.contains(MediaType.APPLICATION_XML_VALUE) ? XML : JSON;
+ }
+
}
diff --git a/cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java b/cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java
index 7a6d0bb3d5..94b97bd88f 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java
@@ -2,6 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Deutsche Telekom AG
* Modifications Copyright (C) 2023-2024 Nordix Foundation.
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,11 +22,13 @@
package org.onap.cps.utils;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -33,6 +36,7 @@ import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
@@ -40,10 +44,14 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import org.onap.cps.spi.exceptions.DataValidationException;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
+import org.w3c.dom.Node;
import org.xml.sax.SAXException;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@@ -156,6 +164,85 @@ public class XmlFileUtils {
return document;
}
+ /**
+ * Convert a list of data maps to XML format.
+ *
+ * @param dataMaps List of data maps to convert
+ * @return XML string representation of the data maps
+ */
+ @SuppressFBWarnings(value = "DCN_NULLPOINTER_EXCEPTION")
+ public static String convertDataMapsToXml(final List<Map<String, Object>> dataMaps) {
+ try {
+ final DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder();
+ final Document document = documentBuilder.newDocument();
+ final DocumentFragment documentFragment = document.createDocumentFragment();
+ for (final Map<String, Object> dataMap : dataMaps) {
+ createXmlElements(document, documentFragment, dataMap);
+ }
+ return transformFragmentToString(documentFragment);
+ } catch (final DOMException | NullPointerException | ParserConfigurationException | TransformerException
+ exception) {
+ throw new DataValidationException(
+ "Data Validation Failed", "Failed to parse xml data: " + exception.getMessage(), exception);
+ }
+ }
+
+ private static void createXmlElements(final Document document, final Node parentNode,
+ final Map<String, Object> dataMap) {
+ for (final Map.Entry<String, Object> mapEntry : dataMap.entrySet()) {
+ if (mapEntry.getValue() instanceof List) {
+ appendList(document, parentNode, mapEntry);
+ } else if (mapEntry.getValue() instanceof Map) {
+ appendMap(document, parentNode, mapEntry);
+ } else {
+ appendObject(document, parentNode, mapEntry);
+ }
+ }
+ }
+
+ private static void appendList(final Document document, final Node parentNode,
+ final Map.Entry<String, Object> mapEntry) {
+ final List<Object> list = (List<Object>) mapEntry.getValue();
+ if (list.isEmpty()) {
+ final Element listElement = document.createElement(mapEntry.getKey());
+ parentNode.appendChild(listElement);
+ } else {
+ for (final Object element : list) {
+ final Element listElement = document.createElement(mapEntry.getKey());
+ if (element instanceof Map) {
+ createXmlElements(document, listElement, (Map<String, Object>) element);
+ } else {
+ listElement.appendChild(document.createTextNode(element.toString()));
+ }
+ parentNode.appendChild(listElement);
+ }
+ }
+ }
+
+ private static void appendMap(final Document document, final Node parentNode,
+ final Map.Entry<String, Object> mapEntry) {
+ final Element childElement = document.createElement(mapEntry.getKey());
+ createXmlElements(document, childElement, (Map<String, Object>) mapEntry.getValue());
+ parentNode.appendChild(childElement);
+ }
+
+ private static void appendObject(final Document document, final Node parentNode,
+ final Map.Entry<String, Object> mapEntry) {
+ final Element element = document.createElement(mapEntry.getKey());
+ element.appendChild(document.createTextNode(mapEntry.getValue().toString()));
+ parentNode.appendChild(element);
+ }
+
+ private static String transformFragmentToString(final DocumentFragment documentFragment)
+ throws TransformerException {
+ final Transformer transformer = getTransformerFactory().newTransformer();
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ final StringWriter writer = new StringWriter();
+ final StreamResult result = new StreamResult(writer);
+ transformer.transform(new DOMSource(documentFragment), result);
+ return writer.toString();
+ }
+
private static DocumentBuilderFactory getDocumentBuilderFactory() {
if (isNewDocumentBuilderFactoryInstance) {
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/ContentTypeSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/ContentTypeSpec.groovy
new file mode 100644
index 0000000000..cada33ef06
--- /dev/null
+++ b/cps-service/src/test/groovy/org/onap/cps/utils/ContentTypeSpec.groovy
@@ -0,0 +1,37 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2024 TechMahindra Ltd
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.utils;
+
+import spock.lang.Specification;
+import org.springframework.http.MediaType
+
+
+class ContentTypeSpec extends Specification {
+
+ def 'Should return correct ContentType based on given input.'() {
+ given: 'contentType fromString method converts the input string as expectedContentType'
+ ContentType.fromString(contentTypeString) == expectedContentType
+ where:
+ contentTypeString || expectedContentType
+ MediaType.APPLICATION_XML_VALUE || ContentType.XML
+ MediaType.APPLICATION_JSON_VALUE || ContentType.JSON
+ }
+
+}
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/XmlFileUtilsSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/XmlFileUtilsSpec.groovy
index dc6027de25..3b21145293 100644
--- a/cps-service/src/test/groovy/org/onap/cps/utils/XmlFileUtilsSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/utils/XmlFileUtilsSpec.groovy
@@ -2,6 +2,7 @@
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Deutsche Telekom AG
* Modifications Copyright (c) 2023-2024 Nordix Foundation
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,10 +22,14 @@
package org.onap.cps.utils
import org.onap.cps.TestUtils
+import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
+import org.w3c.dom.DOMException
import org.xml.sax.SAXParseException
import spock.lang.Specification
+import static org.onap.cps.utils.XmlFileUtils.convertDataMapsToXml
+
class XmlFileUtilsSpec extends Specification {
def 'Parse a valid xml content #scenario'(){
@@ -68,4 +73,56 @@ class XmlFileUtilsSpec extends Specification {
'without root data node' | '<?xml version="1.0" encoding="UTF-8"?><nest xmlns="org:onap:cps:test:test-tree"><name>Small</name><birds>Sparrow</birds></nest>' | '/test-tree/branch[@name=\'Branch\']' || '<?xml version="1.0" encoding="UTF-8"?><branch xmlns="org:onap:cps:test:test-tree"><name>Branch</name><nest><name>Small</name><birds>Sparrow</birds></nest></branch>'
}
+ def 'Convert data maps to XML #scenario'() {
+ when: 'data maps are converted to XML'
+ def result = convertDataMapsToXml(dataMaps)
+ then: 'the result contains the expected XML'
+ assert result == expectedXmlOutput
+ where:
+ scenario | dataMaps || expectedXmlOutput
+ 'single XML branch' | [['branch': ['name': 'Left', 'nest': ['name': 'Small', 'birds': ['Sparrow', 'Owl']]]]] || '<branch><name>Left</name><nest><name>Small</name><birds>Sparrow</birds><birds>Owl</birds></nest></branch>'
+ 'nested XML branch' | [['test-tree': [branch: [name: 'Left', nest: [name: 'Small', birds: 'Sparrow']]]]] || '<test-tree><branch><name>Left</name><nest><name>Small</name><birds>Sparrow</birds></nest></branch></test-tree>'
+ 'list of branch within a test tree' | [['test-tree': [branch: [[name: 'Left', nest: [name: 'Small', birds: 'Sparrow']], [name: 'Right', nest: [name: 'Big', birds: 'Owl']]]]]] || '<test-tree><branch><name>Left</name><nest><name>Small</name><birds>Sparrow</birds></nest></branch><branch><name>Right</name><nest><name>Big</name><birds>Owl</birds></nest></branch></test-tree>'
+ 'list of birds under a nest' | [['nest': ['name': 'Small', 'birds': ['Sparrow']]]] || '<nest><name>Small</name><birds>Sparrow</birds></nest>'
+ 'XML Content map with null key/value' | [['test-tree': [branch: [name: 'Left', nest: []]]]] || '<test-tree><branch><name>Left</name><nest/></branch></test-tree>'
+ 'XML Content list is empty' | [['nest': ['name': 'Small', 'birds': []]]] || '<nest><name>Small</name><birds/></nest>'
+ 'XML with mixed content in list' | [['branch': ['name': 'Left', 'nest': ['name': 'Small', 'birds': ['', 'Sparrow']]]]] || '<branch><name>Left</name><nest><name>Small</name><birds/><birds>Sparrow</birds></nest></branch>'
+ }
+
+ def 'Convert data maps to XML with null or empty maps and lists'() {
+ when: 'data maps with empty content are converted to XML'
+ def result = convertDataMapsToXml(dataMaps)
+ then: 'the result contains the expected XML or handles nulls correctly'
+ assert result == expectedXmlOutput
+ where:
+ scenario | dataMaps || expectedXmlOutput
+ 'null entry in map' | [['branch': []]] || '<branch/>'
+ 'list with null object' | [['branch': [name: 'Left', nest: [name: 'Small', birds: []]]]] || '<branch><name>Left</name><nest><name>Small</name><birds/></nest></branch>'
+ 'list containing null list' | [['test-tree': [branch: '']]] || '<test-tree><branch/></test-tree>'
+ 'nested map with null values' | [['test-tree': [branch: [name: 'Left', nest: '']]]] || '<test-tree><branch><name>Left</name><nest/></branch></test-tree>'
+ }
+
+ def 'Converting data maps to xml with no data'() {
+ given: 'A list of maps where entry is null'
+ def dataMapWithNull = [null]
+ when: 'convert the dataMaps to XML'
+ convertDataMapsToXml(dataMapWithNull)
+ then: 'a validation exception is thrown'
+ def exception = thrown(DataValidationException)
+ and:'the cause is a null pointer exception'
+ assert exception.cause instanceof NullPointerException
+ }
+
+ def 'Converting data maps to xml with document syntax error'() {
+ given: 'A list of maps with an invalid entry'
+ def dataMap = [['invalid<tag>': 'value']]
+ when: 'convert the dataMaps to XML'
+ convertDataMapsToXml(dataMap)
+ then: 'a validation exception is thrown'
+ def exception = thrown(DataValidationException)
+ and:'the cause is a document object model exception'
+ assert exception.cause instanceof DOMException
+
+ }
+
}
diff --git a/docs/api/swagger/cps/openapi.yaml b/docs/api/swagger/cps/openapi.yaml
index 3069b18d1e..3f889c1e6c 100644
--- a/docs/api/swagger/cps/openapi.yaml
+++ b/docs/api/swagger/cps/openapi.yaml
@@ -1162,6 +1162,15 @@ paths:
default: none
example: "3"
type: string
+ - description: Content type in header
+ in: header
+ name: Content-Type
+ required: true
+ schema:
+ enum:
+ - application/json
+ - application/xml
+ type: string
responses:
"200":
content:
@@ -1172,6 +1181,15 @@ paths:
value: null
schema:
type: object
+ application/xml:
+ examples:
+ dataSample:
+ $ref: '#/components/examples/dataSampleXml'
+ value: null
+ schema:
+ type: object
+ xml:
+ name: stores
description: OK
"400":
content:
@@ -1347,7 +1365,9 @@ paths:
name: Content-Type
required: true
schema:
- example: application/json
+ enum:
+ - application/json
+ - application/xml
type: string
requestBody:
content:
@@ -1472,7 +1492,9 @@ paths:
name: Content-Type
required: true
schema:
- example: application/json
+ enum:
+ - application/json
+ - application/xml
type: string
requestBody:
content:
@@ -1597,7 +1619,9 @@ paths:
name: Content-Type
required: true
schema:
- example: application/json
+ enum:
+ - application/json
+ - application/xml
type: string
requestBody:
content:
@@ -1788,7 +1812,9 @@ paths:
name: Content-Type
required: true
schema:
- example: application/json
+ enum:
+ - application/json
+ - application/xml
type: string
requestBody:
content:
@@ -2543,6 +2569,16 @@ components:
default: none
example: "3"
type: string
+ contentTypeInHeader:
+ description: Content type in header
+ in: header
+ name: Content-Type
+ required: true
+ schema:
+ enum:
+ - application/json
+ - application/xml
+ type: string
observedTimestampInQuery:
description: observed-timestamp
in: query
@@ -2551,14 +2587,6 @@ components:
schema:
example: 2021-03-21T00:10:34.030-0100
type: string
- contentTypeInHeader:
- description: Content type in header
- in: header
- name: Content-Type
- required: true
- schema:
- example: application/json
- type: string
dryRunInQuery:
description: "Boolean flag to validate data, without persisting it. Default\
\ value is set to false."
diff --git a/pom.xml b/pom.xml
index 6c34a19ed1..27a9a216ae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,13 +23,8 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.oparent</groupId>
- <artifactId>oparent</artifactId>
- <version>3.2.0</version>
- </parent>
+ <modelVersion>4.0.0</modelVersion>
<groupId>org.onap.cps</groupId>
<artifactId>cps-aggregator</artifactId>
<version>3.5.5-SNAPSHOT</version>