diff options
Diffstat (limited to 'cps-service/src')
3 files changed, 137 insertions, 121 deletions
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java index c776e5bb31..65dfa7f5c6 100755 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java @@ -252,8 +252,7 @@ public class CpsDataServiceImpl implements CpsDataService { return new DataNodeBuilder().withContainerNode(containerNode).build(); } - final ContainerNode containerNode = YangUtils - .parseData(contentType, nodeData, schemaContext, parentNodeXpath); + final ContainerNode containerNode = YangUtils.parseData(contentType, nodeData, schemaContext, parentNodeXpath); return new DataNodeBuilder() .withParentNodeXpath(parentNodeXpath) 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 0946ae3f64..3654042078 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 @@ -20,10 +20,10 @@ package org.onap.cps.utils; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -37,6 +37,8 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; 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; @@ -44,26 +46,25 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; +@NoArgsConstructor(access = AccessLevel.PRIVATE) 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})['\\\"]\\]"); + 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) { - + public static String prepareXmlContent(final String xmlContent, final SchemaContext schemaContext) + throws IOException, ParserConfigurationException, TransformerException, SAXException { return addRootNodeToXmlContent(xmlContent, schemaContext.getModules().iterator().next().getName(), - ROOT_NODE_NAMESPACE); - + YangUtils.DATA_ROOT_NODE_NAMESPACE); } /** @@ -71,15 +72,19 @@ public class XmlFileUtils { * * @param xmlContent XML content sent to store * @param parentSchemaNode Parent schema node + * @Param xpath Parent xpath + * * @return XML content wrapped by root node (if needed) */ - public static String prepareXmlContent(final String xmlContent, final DataSchemaNode parentSchemaNode, - final String xpath) { + public static String prepareXmlContent(final String xmlContent, + final DataSchemaNode parentSchemaNode, + final String xpath) + throws IOException, ParserConfigurationException, TransformerException, SAXException { 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>(); + final HashMap<String, String> rootNodePropertyMap = new HashMap<>(); rootNodePropertyMap.put(regexMatcher.group(1), regexMatcher.group(2)); return addRootNodeToXmlContent(xmlContent, parentSchemaNode.getQName().getLocalName(), namespace, rootNodePropertyMap); @@ -88,41 +93,30 @@ public class XmlFileUtils { 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, + private 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); + final Map<String, String> rootNodeProperty) + throws IOException, SAXException, ParserConfigurationException, TransformerException { + final DocumentBuilder documentBuilder = dbFactory.newDocumentBuilder(); + final StringBuilder xmlStringBuilder = new StringBuilder(); + xmlStringBuilder.append(xmlContent); + final Document document = documentBuilder.parse( + new ByteArrayInputStream(xmlStringBuilder.toString().getBytes(StandardCharsets.UTF_8))); + final Element root = document.getDocumentElement(); + if (!root.getTagName().equals(rootNodeTagName) + && !root.getTagName().equals(YangUtils.DATA_ROOT_NODE_TAG_NAME)) { + final Document documentWithRootNode = addDataRootNode(root, rootNodeTagName, namespace, rootNodeProperty); + documentWithRootNode.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(documentWithRootNode), new StreamResult(stringWriter)); + return stringWriter.toString(); } + return xmlContent; } /** @@ -132,9 +126,11 @@ public class XmlFileUtils { * @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>()); + public static String addRootNodeToXmlContent(final String xmlContent, + final String rootNodeTagName, + final String namespace) + throws IOException, ParserConfigurationException, TransformerException, SAXException { + return addRootNodeToXmlContent(xmlContent, rootNodeTagName, namespace, new HashMap<>()); } /** @@ -144,8 +140,10 @@ public class XmlFileUtils { * @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) { + static Document addDataRootNode(final Element node, + final String tagName, + final String namespace, + final Map<String, String> rootNodeProperty) { try { final DocumentBuilder docBuilder = dbFactory.newDocumentBuilder(); final Document document = docBuilder.newDocument(); diff --git a/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java b/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java index eb0c764cbc..c0dfe5205a 100644 --- a/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java +++ b/cps-service/src/main/java/org/onap/cps/utils/YangUtils.java @@ -38,9 +38,11 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; +import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.TransformerException; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -75,6 +77,9 @@ import org.xml.sax.SAXException; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class YangUtils { + public static final String DATA_ROOT_NODE_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0"; + public static final String DATA_ROOT_NODE_TAG_NAME = "data"; + /** * Parses data into Collection of NormalizedNode according to given schema context. * @@ -82,13 +87,13 @@ public class YangUtils { * @param schemaContext schema context describing associated data model * @return the NormalizedNode object */ - public static ContainerNode parseData(final ContentType contentType, final String nodeData, - final SchemaContext schemaContext) { + public static ContainerNode parseData(final ContentType contentType, + final String nodeData, + final SchemaContext schemaContext) { if (contentType == ContentType.JSON) { - return parseJsonData(nodeData, schemaContext, Optional.empty()); + return parseJsonDataWithOptionalParent(nodeData, schemaContext, Optional.empty()); } - return parseXmlData(XmlFileUtils.prepareXmlContent(nodeData, schemaContext), schemaContext, - Optional.empty()); + return parseXmlDataWithOptionalParent(nodeData, schemaContext, Optional.empty()); } /** @@ -98,19 +103,14 @@ public class YangUtils { * @param schemaContext schema context describing associated data model * @return the NormalizedNode object */ - public static ContainerNode parseData(final ContentType contentType, final String nodeData, - final SchemaContext schemaContext, final String parentNodeXpath) { - final DataSchemaNode parentSchemaNode = - (DataSchemaNode) getDataSchemaNodeAndIdentifiersByXpath(parentNodeXpath, schemaContext) - .get("dataSchemaNode"); - final Collection<QName> dataSchemaNodeIdentifiers = - (Collection<QName>) getDataSchemaNodeAndIdentifiersByXpath(parentNodeXpath, schemaContext) - .get("dataSchemaNodeIdentifiers"); + public static ContainerNode parseData(final ContentType contentType, + final String nodeData, + final SchemaContext schemaContext, + final String parentNodeXpath) { if (contentType == ContentType.JSON) { - return parseJsonData(nodeData, schemaContext, Optional.of(dataSchemaNodeIdentifiers)); + return parseJsonDataWithOptionalParent(nodeData, schemaContext, Optional.of(parentNodeXpath)); } - return parseXmlData(XmlFileUtils.prepareXmlContent(nodeData, parentSchemaNode, parentNodeXpath), schemaContext, - Optional.of(dataSchemaNodeIdentifiers)); + return parseXmlDataWithOptionalParent(nodeData, schemaContext, Optional.of(parentNodeXpath)); } /** @@ -121,7 +121,7 @@ public class YangUtils { * @return the Collection of NormalizedNode object */ public static ContainerNode parseJsonData(final String jsonData, final SchemaContext schemaContext) { - return parseJsonData(jsonData, schemaContext, Optional.empty()); + return parseJsonDataWithOptionalParent(jsonData, schemaContext, Optional.empty()); } /** @@ -132,40 +132,59 @@ public class YangUtils { * @param parentNodeXpath the xpath referencing the parent node current data fragment belong to * @return the NormalizedNode object */ - public static ContainerNode parseJsonData(final String jsonData, final SchemaContext schemaContext, - final String parentNodeXpath) { - final Collection<QName> dataSchemaNodeIdentifiers = - (Collection<QName>) getDataSchemaNodeAndIdentifiersByXpath(parentNodeXpath, schemaContext) - .get("dataSchemaNodeIdentifiers"); - return parseJsonData(jsonData, schemaContext, Optional.of(dataSchemaNodeIdentifiers)); + public static ContainerNode parseJsonData(final String jsonData, + final SchemaContext schemaContext, + final String parentNodeXpath) { + return parseJsonDataWithOptionalParent(jsonData, schemaContext, Optional.of(parentNodeXpath)); + } + + /** + * Create an xpath form a Yang Tools NodeIdentifier (i.e. PathArgument). + * + * @param nodeIdentifier the NodeIdentifier + * @return a xpath + */ + public static String buildXpath(final YangInstanceIdentifier.PathArgument nodeIdentifier) { + final StringBuilder xpathBuilder = new StringBuilder(); + xpathBuilder.append("/").append(nodeIdentifier.getNodeType().getLocalName()); + + if (nodeIdentifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) { + xpathBuilder.append(getKeyAttributesStatement( + (YangInstanceIdentifier.NodeIdentifierWithPredicates) nodeIdentifier)); + } + return xpathBuilder.toString(); } - private static ContainerNode parseJsonData(final String jsonData, final SchemaContext schemaContext, - final Optional<Collection<QName>> dataSchemaNodeIdentifiers) { + private static ContainerNode parseJsonDataWithOptionalParent(final String jsonData, + final SchemaContext schemaContext, + final Optional<String> parentNodeXpath) { final JSONCodecFactory jsonCodecFactory = JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02 .getShared((EffectiveModelContext) schemaContext); final DataContainerNodeBuilder<YangInstanceIdentifier.NodeIdentifier, ContainerNode> dataContainerNodeBuilder = Builders.containerBuilder() - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(schemaContext.getQName())); + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier( + QName.create(DATA_ROOT_NODE_NAMESPACE, DATA_ROOT_NODE_TAG_NAME) + )); final NormalizedNodeStreamWriter normalizedNodeStreamWriter = ImmutableNormalizedNodeStreamWriter .from(dataContainerNodeBuilder); final JsonReader jsonReader = new JsonReader(new StringReader(jsonData)); final JsonParserStream jsonParserStream; - if (dataSchemaNodeIdentifiers.isPresent()) { + if (parentNodeXpath.isPresent()) { + final Collection<QName> dataSchemaNodeIdentifiers + = getDataSchemaNodeIdentifiers(schemaContext, parentNodeXpath.get()); final EffectiveModelContext effectiveModelContext = ((EffectiveModelContext) schemaContext); final EffectiveStatementInference effectiveStatementInference = SchemaInferenceStack.of(effectiveModelContext, - SchemaNodeIdentifier.Absolute.of(dataSchemaNodeIdentifiers.get())).toInference(); + SchemaNodeIdentifier.Absolute.of(dataSchemaNodeIdentifiers)).toInference(); jsonParserStream = JsonParserStream.create(normalizedNodeStreamWriter, jsonCodecFactory, effectiveStatementInference); } else { jsonParserStream = JsonParserStream.create(normalizedNodeStreamWriter, jsonCodecFactory); } - try { + try (jsonParserStream) { jsonParserStream.parse(jsonReader); - jsonParserStream.close(); } catch (final IOException | JsonSyntaxException exception) { throw new DataValidationException( "Failed to parse json data: " + jsonData, exception.getMessage(), exception); @@ -177,58 +196,58 @@ public class YangUtils { return dataContainerNodeBuilder.build(); } - private static ContainerNode parseXmlData(final String xmlData, final SchemaContext schemaContext, - final Optional<Collection<QName>> dataSchemaNodeIdentifiers) { + private static ContainerNode parseXmlDataWithOptionalParent(final String xmlData, + final SchemaContext schemaContext, + final Optional<String> parentNodeXpath) { final XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.SUPPORT_DTD, false); final NormalizedNodeResult normalizedNodeResult = new NormalizedNodeResult(); final NormalizedNodeStreamWriter normalizedNodeStreamWriter = ImmutableNormalizedNodeStreamWriter .from(normalizedNodeResult); - final XmlParserStream xmlParser; - final EffectiveModelContext effectiveModelContext = ((EffectiveModelContext) schemaContext); - - if (dataSchemaNodeIdentifiers.isPresent()) { - final EffectiveStatementInference effectiveStatementInference = + final EffectiveModelContext effectiveModelContext = (EffectiveModelContext) schemaContext; + final XmlParserStream xmlParserStream; + final String preparedXmlContent; + try { + if (parentNodeXpath.isPresent()) { + final DataSchemaNode parentSchemaNode = + (DataSchemaNode) getDataSchemaNodeAndIdentifiersByXpath(parentNodeXpath.get(), schemaContext) + .get("dataSchemaNode"); + final Collection<QName> dataSchemaNodeIdentifiers = + getDataSchemaNodeIdentifiers(schemaContext, parentNodeXpath.get()); + final EffectiveStatementInference effectiveStatementInference = SchemaInferenceStack.of(effectiveModelContext, - SchemaNodeIdentifier.Absolute.of(dataSchemaNodeIdentifiers.get())).toInference(); - xmlParser = XmlParserStream.create(normalizedNodeStreamWriter, effectiveStatementInference); - } else { - xmlParser = XmlParserStream.create(normalizedNodeStreamWriter, effectiveModelContext); - } + SchemaNodeIdentifier.Absolute.of(dataSchemaNodeIdentifiers)).toInference(); + preparedXmlContent = XmlFileUtils.prepareXmlContent(xmlData, parentSchemaNode, parentNodeXpath.get()); + xmlParserStream = XmlParserStream.create(normalizedNodeStreamWriter, effectiveStatementInference); + } else { + preparedXmlContent = XmlFileUtils.prepareXmlContent(xmlData, schemaContext); + xmlParserStream = XmlParserStream.create(normalizedNodeStreamWriter, effectiveModelContext); + } - try { - final XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xmlData)); - xmlParser.parse(reader); - xmlParser.close(); - } catch (final XMLStreamException | URISyntaxException | IOException - | SAXException | NullPointerException exception) { + try (xmlParserStream; + StringReader stringReader = new StringReader(preparedXmlContent)) { + final XMLStreamReader xmlStreamReader = factory.createXMLStreamReader(stringReader); + xmlParserStream.parse(xmlStreamReader); + } + } catch (final XMLStreamException | URISyntaxException | IOException | SAXException | NullPointerException + | ParserConfigurationException | TransformerException exception) { throw new DataValidationException( - "Failed to parse xml data: " + xmlData, exception.getMessage(), exception); + "Failed to parse xml data: " + xmlData, exception.getMessage(), exception); } - final NormalizedNode normalizedNode = getFirstChildXmlRoot(normalizedNodeResult.getResult()); - return Builders.containerBuilder().withChild((DataContainerChild) normalizedNode) - .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(schemaContext.getQName())).build(); + final DataContainerChild dataContainerChild = + (DataContainerChild) getFirstChildXmlRoot(normalizedNodeResult.getResult()); + final YangInstanceIdentifier.NodeIdentifier nodeIdentifier = + new YangInstanceIdentifier.NodeIdentifier(dataContainerChild.getIdentifier().getNodeType()); + return Builders.containerBuilder().withChild(dataContainerChild).withNodeIdentifier(nodeIdentifier).build(); } - /** - * Create an xpath form a Yang Tools NodeIdentifier (i.e. PathArgument). - * - * @param nodeIdentifier the NodeIdentifier - * @return a xpath - */ - public static String buildXpath(final YangInstanceIdentifier.PathArgument nodeIdentifier) { - final StringBuilder xpathBuilder = new StringBuilder(); - xpathBuilder.append("/").append(nodeIdentifier.getNodeType().getLocalName()); - - if (nodeIdentifier instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates) { - xpathBuilder.append(getKeyAttributesStatement( - (YangInstanceIdentifier.NodeIdentifierWithPredicates) nodeIdentifier)); - } - return xpathBuilder.toString(); + private static Collection<QName> getDataSchemaNodeIdentifiers(final SchemaContext schemaContext, + final String parentNodeXpath) { + return (Collection<QName>) getDataSchemaNodeAndIdentifiersByXpath(parentNodeXpath, schemaContext) + .get("dataSchemaNodeIdentifiers"); } - private static String getKeyAttributesStatement( final YangInstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier) { final List<String> keyAttributes = nodeIdentifier.entrySet().stream().map( @@ -313,4 +332,4 @@ public class YangUtils { } return getFirstChildXmlRoot(child); } -}
\ No newline at end of file +} |