Here to bring Support for XML content on Get delta between two anchors within a given dataspace
- Add deltaReportSampleXml Example in component.yaml
- Add ContentTypeInheader in cpsDataV2.yml to support application/xml in Delta
- Add contentTypeInHeader parameter to accept xml in DataRestController.java
- Implemented Logic to convert deltaReport to XML in XmlFileUtils.java
- written testcase for above changes made
Issue-ID: CPS-2452
Change-Id: Iff7fab66ddcc03703255123c6d5c2eade0e7cb4a
Signed-off-by: GM001016278 <gourav.malviya@techmahindra.com>
# ============LICENSE_START=======================================================
# Copyright (c) 2021-2022 Bell Canada.
# Modifications Copyright (C) 2021-2023 Nordix Foundation
-# Modifications Copyright (C) 2022-2025 Deutsche Telekom AG
+# Modifications Copyright (C) 2025-2026 Deutsche Telekom AG
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
dataspace:
- name: my-dataspace
- name: bookstore-dataspace
+ deltaReportSampleXml:
+ value:
+ <deltaReports>
+ <deltaReport>
+ <action>replace</action>
+ <xpath>/bookstore/categories[@code='1']</xpath>
+ <source-data>
+ <name>SciFi</name>
+ </source-data>
+ <target-data>
+ <name>Comic</name>
+ </target-data>
+ </deltaReport>
+ <deltaReport>
+ <action>remove</action>
+ <xpath>/bookstore/categories[@code='2']</xpath>
+ <source-data>
+ <code>2</code>
+ <name>kids</name>
+ </source-data>
+ </deltaReport>
+ <deltaReport>
+ <action>create</action>
+ <xpath>/bookstore/categories[@code='3']</xpath>
+ <target-data>
+ <code>3</code>
+ <name>Fiction</name>
+ </target-data>
+ </deltaReport>
+ </deltaReports>
parameters:
dataspaceNameInQuery:
name: dataspace-name
# ============LICENSE_START=======================================================
-# Copyright (c) 2025 Deutsche Telekom AG
+# Copyright (c) 2025-2026 Deutsche Telekom AG
# ================================================================================
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
- $ref: 'components.yml#/components/parameters/xpathInQuery'
- $ref: 'components.yml#/components/parameters/descendantsInQuery'
- $ref: 'components.yml#/components/parameters/groupDataNodesInQuery'
+ - $ref: 'components.yml#/components/parameters/contentTypeInHeader'
responses:
'200':
description: OK
examples:
dataSample:
$ref: 'components.yml#/components/examples/deltaReportSample'
+ application/xml:
+ schema:
+ type: object
+ examples:
+ dataSample:
+ $ref: 'components.yml#/components/examples/deltaReportSampleXml'
'400':
$ref: 'components.yml#/components/responses/BadRequest'
'403':
* Copyright (C) 2020-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2021-2025 Nordix Foundation
- * Modifications Copyright (C) 2022-2025 Deutsche Telekom AG
+ * Modifications Copyright (C) 2025-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
package org.onap.cps.rest.controller;
+import static org.onap.cps.utils.XmlUtils.convertDataMapsToXml;
+
import io.micrometer.core.annotation.Timed;
import jakarta.validation.ValidationException;
import java.time.OffsetDateTime;
import org.onap.cps.rest.api.CpsDataApi;
import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.JsonObjectMapper;
-import org.onap.cps.utils.XmlFileUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
private ResponseEntity<Object> buildResponseEntity(final Object dataMaps, final ContentType contentType) {
final String responseData;
if (ContentType.XML.equals(contentType)) {
- responseData = XmlFileUtils.convertDataMapsToXml(dataMaps);
+ responseData = convertDataMapsToXml(dataMaps);
} else {
responseData = jsonObjectMapper.asJsonString(dataMaps);
}
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2025 Deutsche Telekom AG
+ * Copyright (C) 2025-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
package org.onap.cps.rest.controller;
import static org.onap.cps.rest.utils.MultipartFileUtil.extractYangResourcesMap;
+import static org.onap.cps.utils.ContentType.XML;
import io.micrometer.core.annotation.Timed;
import java.util.Collection;
import org.onap.cps.api.parameters.FetchDescendantsOption;
import org.onap.cps.rest.api.CpsDeltaApi;
import org.onap.cps.rest.utils.MultipartFileUtil;
+import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.JsonObjectMapper;
+import org.onap.cps.utils.XmlObjectMapper;
+import org.onap.cps.utils.deltareport.DeltaReportWrapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
@RequiredArgsConstructor
public class DeltaRestController implements CpsDeltaApi {
+ private static final String XML_ROOT_NAME = "deltaReports";
+
private final CpsDeltaService cpsDeltaService;
private final JsonObjectMapper jsonObjectMapper;
+ private final XmlObjectMapper xmlObjectMapper;
@Timed(value = "cps.delta.controller.get.delta",
description = "Time taken to get delta between anchors")
final String targetAnchorName,
final String xpath,
final String descendants,
- final Boolean groupDataNodes) {
+ final Boolean groupDataNodes,
+ final String contentTypeInHeader) {
final FetchDescendantsOption fetchDescendantsOption =
FetchDescendantsOption.getFetchDescendantsOption(descendants);
- final List<DeltaReport> deltaBetweenAnchors =
+ final List<DeltaReport> deltaReports =
cpsDeltaService.getDeltaByDataspaceAndAnchors(dataspaceName, sourceAnchorName,
targetAnchorName, xpath, fetchDescendantsOption, groupDataNodes);
- return new ResponseEntity<>(jsonObjectMapper.asJsonString(deltaBetweenAnchors), HttpStatus.OK);
+ return buildDeltaResponseEntity(deltaReports, ContentType.fromString(contentTypeInHeader));
+
}
@Timed(value = "cps.delta.controller.get.delta",
return ResponseEntity.status(HttpStatus.CREATED).build();
}
+ private ResponseEntity<Object> buildDeltaResponseEntity(final List<DeltaReport> deltaReports,
+ final ContentType contentType) {
+ if (XML.equals(contentType)) {
+ final DeltaReportWrapper<DeltaReport> deltaReportWrapper = new DeltaReportWrapper<>(deltaReports);
+ final String xmlDeltaReport = xmlObjectMapper.asXmlString(deltaReportWrapper, XML_ROOT_NAME);
+ return new ResponseEntity<>(xmlDeltaReport, HttpStatus.OK);
+ } else {
+ return new ResponseEntity<>(jsonObjectMapper.asJsonString(deltaReports), HttpStatus.OK);
+ }
+ }
}
* ============LICENSE_START=======================================================
* Copyright (C) 2021-2025 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada.
- * Modifications Copyright (C) 2022-2024 Deutsche Telekom AG
+ * Modifications Copyright (C) 2025-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
package org.onap.cps.rest.controller;
+import static org.onap.cps.utils.XmlUtils.convertDataMapsToXml;
+
import io.micrometer.core.annotation.Timed;
import java.util.List;
import java.util.Map;
import org.onap.cps.rest.api.CpsQueryApi;
import org.onap.cps.utils.ContentType;
import org.onap.cps.utils.JsonObjectMapper;
-import org.onap.cps.utils.XmlFileUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
final ContentType contentType) {
final String responseData;
if (ContentType.XML.equals(contentType)) {
- responseData = XmlFileUtils.convertDataMapsToXml(dataNodesAsMaps);
+ responseData = convertDataMapsToXml(dataNodesAsMaps);
} else {
responseData = jsonObjectMapper.asJsonString(dataNodesAsMaps);
}
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2025 Deutsche Telekom AG
+ * Copyright (C) 2025-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import org.onap.cps.api.CpsDeltaService
import org.onap.cps.impl.DeltaReportBuilder
import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.utils.XmlObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.web.multipart.MultipartFile
import spock.lang.Shared
import spock.lang.Specification
-
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path
@SpringBean
JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ @SpringBean
+ XmlObjectMapper xmlObjectMapper = new XmlObjectMapper()
+
@Autowired
MockMvc mvc
Files.deleteIfExists(targetDataAsJsonFile)
}
- def 'Get delta between two anchors'() {
- given: 'the service returns a list containing delta reports'
- def deltaReports = new DeltaReportBuilder().actionReplace().withXpath('some xpath').withSourceData('some key': 'some value').withTargetData('some key': 'some value').build()
+ def 'Get delta between two anchors with content type #scenario'() {
+ given: 'a xpath and delta report'
def xpath = 'some xpath'
+ def deltaReports = new DeltaReportBuilder().actionReplace().withXpath(xpath).withSourceData('some_key': 'some value').withTargetData('some_key': 'some value').build()
+ and: 'service returns a list containing delta reports'
mockCpsDeltaService.getDeltaByDataspaceAndAnchors(dataspaceName, anchorName, 'targetAnchor', xpath, OMIT_DESCENDANTS, NO_GROUPING) >> [deltaReports]
when: 'get delta request is performed using REST API'
- def response =
- mvc.perform(get(dataNodeBaseEndpointV2)
- .param('target-anchor-name', 'targetAnchor')
- .param('xpath', xpath))
- .andReturn().response
+ def response = mvc.perform(get(dataNodeBaseEndpointV2)
+ .contentType(contentType)
+ .accept(contentType)
+ .param('target-anchor-name', 'targetAnchor')
+ .param('xpath', xpath))
+ .andReturn().response
then: 'expected response code is returned'
assert response.status == HttpStatus.OK.value()
and: 'the response contains expected value'
- assert response.contentAsString.contains('[{\"action\":\"replace\",\"xpath\":\"some xpath\",\"sourceData\":{\"some key\":\"some value\"},\"targetData\":{\"some key\":\"some value\"}}]')
+ assert response.contentAsString.contains(expectedResponse)
+ where:
+ scenario | contentType || expectedResponse
+ 'JSON' | MediaType.APPLICATION_JSON || '[{"action":"replace","xpath":"some xpath","sourceData":{"some_key":"some value"},"targetData":{"some_key":"some value"}}]'
+ 'XML' | MediaType.APPLICATION_XML || '<deltaReports><deltaReport><action>replace</action><xpath>some xpath</xpath><sourceData><some_key>some value</some_key></sourceData><targetData><some_key>some value</some_key></targetData></deltaReport></deltaReports>'
}
def 'Get delta between anchor and JSON payload with yangResourceFile'() {
then: 'expected response code is returned'
assert response.status == HttpStatus.CREATED.value()
}
-}
+}
\ No newline at end of file
* Copyright (C) 2020 Pantheon.tech
* Modifications Copyright (C) 2021-2025 Nordix Foundation
* Modifications Copyright (C) 2021 Bell Canada.
- * Modifications Copyright (C) 2022-2025 Deutsche Telekom AG
+ * Modifications Copyright (C) 2025-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import org.onap.cps.rest.controller.CpsRestInputMapper
import org.onap.cps.utils.JsonObjectMapper
import org.onap.cps.utils.PrefixResolver
+import org.onap.cps.utils.XmlObjectMapper
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
@SpringBean
CpsDeltaService cpsDeltaService = Stub()
+ @SpringBean
+ XmlObjectMapper xmlObjectMapper = new XmlObjectMapper()
+
@Autowired
MockMvc mvc
Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
Modifications Copyright (C) 2021 Bell Canada.
Modifications Copyright (C) 2021 Pantheon.tech
- Modifications Copyright (C) 2022-2024 Deutsche Telekom AG
+ Modifications Copyright (C) 2025-2026 Deutsche Telekom AG
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-annotations</artifactId>
</dependency>
+ <!-- For parsing JSON object -->
<dependency>
- <!-- For parsing JSON object -->
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
+ <!-- For parsing XML object -->
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-xml</artifactId>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025-2026 Deutsche Telekom AG.
+ * ================================================================================
+ * 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 com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import lombok.NoArgsConstructor;
+import org.onap.cps.api.exceptions.DataValidationException;
+import org.springframework.stereotype.Component;
+
+@NoArgsConstructor
+@Component
+public class XmlObjectMapper {
+
+ private final XmlMapper xmlMapper = new XmlMapper();
+
+ /**
+ * Serializing generic java object to XML using Jackson.
+ *
+ * @param object any java object value
+ * @param rootName the name of the XML root name
+ * @return the generated XML as a string.
+ */
+
+ public String asXmlString(final Object object, final String rootName) {
+ try {
+ return xmlMapper.writer().withRootName(rootName).writeValueAsString(object);
+ } catch (final Exception exception) {
+ throw new DataValidationException("Data Validation Failed",
+ "Failed to build XML: " + exception.getMessage(),
+ exception
+ );
+ }
+ }
+}
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Deutsche Telekom AG
* Modifications Copyright (C) 2023-2025 OpenInfra Foundation Europe.
- * Modifications Copyright (C) 2022-2025 Deutsche Telekom AG
+ * Modifications Copyright (C) 2025-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import org.xml.sax.SAXException;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class XmlFileUtils {
+public class XmlUtils {
private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
private static boolean isNewDocumentBuilderFactoryInstance = true;
} else {
throw new IllegalArgumentException("Unsupported data type for XML conversion");
}
- return transformFragmentToString(documentFragment);
+ return transformNodeToString(documentFragment);
} catch (final DOMException | NullPointerException | ParserConfigurationException | TransformerException
exception) {
throw new DataValidationException(
}
parentNode.appendChild(element);
}
+ /**
+ * Converts the given XML Node into a String.
+ *
+ * @param node the XML node to convert
+ * @return string representation of the XML node
+ * @throws TransformerException if transformation fails
+ */
- private static String transformFragmentToString(final DocumentFragment documentFragment)
+ private static String transformNodeToString(final Node node)
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();
+ final StringWriter stringWriter = new StringWriter();
+ final StreamResult streamResult = new StreamResult(stringWriter);
+ transformer.transform(new DOMSource(node), streamResult);
+ return stringWriter.toString();
}
+ /**
+ * Provides a configured instance of DocumentBuilderFactory.
+ * This method initializes the factory with secure processing settings
+ * to prevent XML External Entity (XXE) attacks.
+ * @return a configured DocumentBuilderFactory instance
+ */
- @SuppressWarnings("SameReturnValue")
private static DocumentBuilderFactory getDocumentBuilderFactory() {
if (isNewDocumentBuilderFactoryInstance) {
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
documentBuilderFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
isNewDocumentBuilderFactoryInstance = false;
}
-
return documentBuilderFactory;
}
+ /**
+ * Provides a configured instance of TransformerFactory.
+ * This method initializes the factory with secure settings to prevent
+ * unwanted stylesheet or DTD access.
+ * @return a configured TransformerFactory instance
+ */
@SuppressWarnings("SameReturnValue")
private static TransformerFactory getTransformerFactory() {
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
isNewTransformerFactoryInstance = false;
}
-
return transformerFactory;
}
}
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Modifications Copyright (C) 2025-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
final String preparedXmlContent;
try {
if (parentNodeXpath.isEmpty()) {
- preparedXmlContent = XmlFileUtils.prepareXmlContent(xmlData, schemaContext);
+ preparedXmlContent = XmlUtils.prepareXmlContent(xmlData, schemaContext);
xmlParserStream = XmlParserStream.create(normalizedNodeStreamWriter, effectiveModelContext);
} else {
final DataSchemaNode parentSchemaNode =
final EffectiveStatementInference effectiveStatementInference =
SchemaInferenceStack.of(effectiveModelContext,
SchemaNodeIdentifier.Absolute.of(dataSchemaNodeIdentifiers)).toInference();
- preparedXmlContent = XmlFileUtils.prepareXmlContent(xmlData, parentSchemaNode, parentNodeXpath);
+ preparedXmlContent = XmlUtils.prepareXmlContent(xmlData, parentSchemaNode, parentNodeXpath);
xmlParserStream = XmlParserStream.create(normalizedNodeStreamWriter, effectiveStatementInference);
}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025-2026 Deutsche Telekom AG.
+ * ================================================================================
+ * 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.deltareport;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class DeltaReportWrapper<T> {
+ @JacksonXmlElementWrapper(useWrapping = false)
+ @JacksonXmlProperty(localName = "deltaReport")
+ private List<T> deltaReports;
+}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025-2026 Deutsche Telekom AG.
+ * ================================================================================
+ * 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 com.fasterxml.jackson.dataformat.xml.XmlMapper
+import org.onap.cps.api.exceptions.DataValidationException
+import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectWriter
+import spock.lang.Specification
+
+class XmlObjectMapperSpec extends Specification {
+
+ def objectUnderTest = new XmlObjectMapper()
+
+ def 'Map a structured object to Xml'() {
+ given: 'an object model'
+ def object = [bookstore: [['bookstore-name': 'Chapters',categories: [code: '1', name: 'SciFi']]]]
+ def expectedResult = '<stores><bookstore><bookstore-name>Chapters</bookstore-name><categories><code>1</code><name>SciFi</name></categories></bookstore></stores>'
+ when: 'the object is mapped to string'
+ def result = objectUnderTest.asXmlString(object, "stores")
+ then: 'the result is a valid xml string'
+ assert result == expectedResult
+ }
+
+ def 'Map a structured object with exception during mapping.'() {
+ given: 'some object'
+ def object = new Object();
+ and: 'the XmlMapper chain throws an exception'
+ def spiedXmlMapper = Spy(XmlMapper)
+ def writer = Mock(ObjectWriter)
+ spiedXmlMapper.writer() >> writer
+ writer.withRootName('stores') >> writer
+ writer.writeValueAsString(_) >> { throw new Exception() }
+ when: 'attempt to build XML'
+ objectUnderTest.asXmlString(object, 'stores')
+ then: 'the exception has correct message'
+ def thrownException = thrown(DataValidationException)
+ thrownException.message == 'Data Validation Failed'
+ }
+}
+
* ============LICENSE_START=======================================================
* Copyright (C) 2022 Deutsche Telekom AG
* Modifications Copyright (c) 2023-2024 Nordix Foundation
- * Modifications Copyright (C) 2024-2025 Deutsche Telekom AG
+ * Modifications Copyright (C) 2024-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import org.w3c.dom.DOMException
import org.xml.sax.SAXParseException
import spock.lang.Specification
+import static XmlUtils.convertDataMapsToXml
-import static org.onap.cps.utils.XmlFileUtils.convertDataMapsToXml
-class XmlFileUtilsSpec extends Specification {
+class XmlUtilsSpec extends Specification {
def 'Parse a valid xml content #scenario'() {
given: 'YANG model schema context'
def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('bookstore.yang')
def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).schemaContext()
when: 'the xml data is parsed'
- def parsedXmlContent = XmlFileUtils.prepareXmlContent(xmlData, schemaContext)
+ def parsedXmlContent = XmlUtils.prepareXmlContent(xmlData, schemaContext)
then: 'the result xml is wrapped by root node defined in YANG schema'
assert parsedXmlContent == expectedOutput
where:
def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('bookstore.yang')
def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).schemaContext()
when: 'attempt to parse invalid xml'
- XmlFileUtils.prepareXmlContent('invalid-xml', schemaContext)
+ XmlUtils.prepareXmlContent('invalid-xml', schemaContext)
then: 'a Sax Parser exception is thrown'
thrown(SAXParseException)
}
and: 'Parent schema node by xPath'
def parentSchemaNode = YangParserHelper.getDataSchemaNodeAndIdentifiersByXpath(xPath, schemaContext).get('dataSchemaNode')
when: 'the XML data is parsed'
- def parsedXmlContent = XmlFileUtils.prepareXmlContent(xmlData, parentSchemaNode, xPath)
+ def parsedXmlContent = XmlUtils.prepareXmlContent(xmlData, parentSchemaNode, xPath)
then: 'the result XML is wrapped by xPath defined parent root node'
assert parsedXmlContent == expectedOutput
where:
}
-}
+}
\ No newline at end of file
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2023-2025 OpenInfra Foundation Europe. All rights reserved.
- * Modifications Copyright (C) 2024-2025 Deutsche Telekom AG
+ * Modifications Copyright (C) 2024-2026 Deutsche Telekom AG
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
import org.onap.cps.ri.utils.SessionManager
import org.onap.cps.spi.CpsModulePersistenceService
import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.utils.XmlObjectMapper
+import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
@Autowired
MeterRegistry meterRegistry
+ @SpringBean
+ XmlObjectMapper xmlObjectMapper = new XmlObjectMapper()
+
@Value('${ncmp.policy-executor.server.port:8080}')
private String policyServerPort;