summaryrefslogtreecommitdiffstats
path: root/cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java')
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java165
1 files changed, 165 insertions, 0 deletions
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
new file mode 100644
index 000000000..0946ae3f6
--- /dev/null
+++ b/cps-service/src/main/java/org/onap/cps/utils/XmlFileUtils.java
@@ -0,0 +1,165 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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 java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+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.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+public class XmlFileUtils {
+
+ private static DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ private static final String DATA_ROOT_NODE_TAG_NAME = "data";
+ private static final String ROOT_NODE_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";
+ private static final Pattern XPATH_PROPERTY_REGEX = Pattern.compile(
+ "\\[@(\\S{1,100})=['\\\"](\\S{1,100})['\\\"]\\]");
+
+ /**
+ * Prepare XML content.
+ *
+ * @param xmlContent XML content sent to store
+ * @param schemaContext schema context
+ * @return XML content wrapped by root node (if needed)
+ */
+ public static String prepareXmlContent(final String xmlContent, final SchemaContext schemaContext) {
+
+ return addRootNodeToXmlContent(xmlContent, schemaContext.getModules().iterator().next().getName(),
+ ROOT_NODE_NAMESPACE);
+
+ }
+
+ /**
+ * Prepare XML content.
+ *
+ * @param xmlContent XML content sent to store
+ * @param parentSchemaNode Parent schema node
+ * @return XML content wrapped by root node (if needed)
+ */
+ public static String prepareXmlContent(final String xmlContent, final DataSchemaNode parentSchemaNode,
+ final String xpath) {
+ final String namespace = parentSchemaNode.getQName().getNamespace().toString();
+ final String parentXpathPart = xpath.substring(xpath.lastIndexOf('/') + 1);
+ final Matcher regexMatcher = XPATH_PROPERTY_REGEX.matcher(parentXpathPart);
+ if (regexMatcher.find()) {
+ final HashMap<String, String> rootNodePropertyMap = new HashMap<String, String>();
+ rootNodePropertyMap.put(regexMatcher.group(1), regexMatcher.group(2));
+ return addRootNodeToXmlContent(xmlContent, parentSchemaNode.getQName().getLocalName(), namespace,
+ rootNodePropertyMap);
+ }
+
+ return addRootNodeToXmlContent(xmlContent, parentSchemaNode.getQName().getLocalName(), namespace);
+ }
+
+ /**
+ * Add root node to XML content.
+ *
+ * @param xmlContent xml content to add root node
+ * @param rootNodeTagName root node tag name
+ * @param namespace root node namespace
+ * @param rootNodeProperty root node properites map
+ * @return An edited content with added root node (if needed)
+ */
+ public static String addRootNodeToXmlContent(final String xmlContent, final String rootNodeTagName,
+ final String namespace,
+ final HashMap<String, String> rootNodeProperty) {
+ try {
+ final DocumentBuilder documentBuilder = dbFactory.newDocumentBuilder();
+ final StringBuilder xmlStringBuilder = new StringBuilder();
+ xmlStringBuilder.append(xmlContent);
+ Document xmlDoc = documentBuilder.parse(
+ new ByteArrayInputStream(xmlStringBuilder.toString().getBytes("utf-8")));
+ final Element root = xmlDoc.getDocumentElement();
+ if (!root.getTagName().equals(rootNodeTagName) && !root.getTagName().equals(DATA_ROOT_NODE_TAG_NAME)) {
+ xmlDoc = addDataRootNode(root, rootNodeTagName, namespace, rootNodeProperty);
+ xmlDoc.setXmlStandalone(true);
+ final TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
+ final Transformer transformer = transformerFactory.newTransformer();
+ final StringWriter stringWriter = new StringWriter();
+ transformer.transform(new DOMSource(xmlDoc), new StreamResult(stringWriter));
+ return stringWriter.toString();
+ }
+ return xmlContent;
+ } catch (SAXException | IOException | ParserConfigurationException | TransformerException exception) {
+ throw new DataValidationException("Failed to parse XML data", "Invalid xml input " + exception.getMessage(),
+ exception);
+ }
+ }
+
+ /**
+ * Add root node to XML content.
+ *
+ * @param xmlContent XML content to add root node into
+ * @param rootNodeTagName Root node tag name
+ * @return XML content with root node tag added (if needed)
+ */
+ public static String addRootNodeToXmlContent(final String xmlContent, final String rootNodeTagName,
+ final String namespace) {
+ return addRootNodeToXmlContent(xmlContent, rootNodeTagName, namespace, new HashMap<String, String>());
+ }
+
+ /**
+ * Add root node into DOM element.
+ *
+ * @param node DOM element to add root node into
+ * @param tagName Root tag name to add
+ * @return DOM element with a root node
+ */
+ static Document addDataRootNode(final Element node, final String tagName, final String namespace,
+ final HashMap<String, String> rootNodeProperty) {
+ try {
+ final DocumentBuilder docBuilder = dbFactory.newDocumentBuilder();
+ final Document document = docBuilder.newDocument();
+ final Element rootElement = document.createElementNS(namespace, tagName);
+ for (final Map.Entry<String, String> entry : rootNodeProperty.entrySet()) {
+ final Element propertyElement = document.createElement(entry.getKey());
+ propertyElement.setTextContent(entry.getValue());
+ rootElement.appendChild(propertyElement);
+ }
+ rootElement.appendChild(document.adoptNode(node));
+ document.appendChild(rootElement);
+ return document;
+ } catch (final ParserConfigurationException exception) {
+ throw new DataValidationException("Can't parse XML", "XML can't be parsed", exception);
+ }
+ }
+}