/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023-2025 TechMahindra Ltd.
+ * Copyright (C) 2023-2025 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.impl;
+import static org.onap.cps.cpspath.parser.CpsPathUtil.ROOT_NODE_XPATH;
import static org.onap.cps.utils.ContentType.JSON;
import io.micrometer.core.annotation.Timed;
import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsDeltaService;
import org.onap.cps.api.DataNodeFactory;
+import org.onap.cps.api.exceptions.DataValidationException;
import org.onap.cps.api.model.Anchor;
import org.onap.cps.api.model.DataNode;
import org.onap.cps.api.model.DeltaReport;
import org.onap.cps.api.parameters.FetchDescendantsOption;
+import org.onap.cps.cpspath.parser.CpsPathUtil;
+import org.onap.cps.cpspath.parser.PathParsingException;
import org.onap.cps.utils.CpsValidator;
import org.onap.cps.utils.DataMapper;
import org.onap.cps.utils.JsonObjectMapper;
final FetchDescendantsOption fetchDescendantsOption,
final boolean groupDataNodes) {
+ final String xpathForDeltaReport = validateXpath(xpath);
final Collection<DataNode> sourceDataNodes = cpsDataService.getDataNodesForMultipleXpaths(dataspaceName,
- sourceAnchorName, Collections.singletonList(xpath), fetchDescendantsOption);
+ sourceAnchorName, Collections.singletonList(xpathForDeltaReport), fetchDescendantsOption);
final Collection<DataNode> targetDataNodes = cpsDataService.getDataNodesForMultipleXpaths(dataspaceName,
- targetAnchorName, Collections.singletonList(xpath), fetchDescendantsOption);
+ targetAnchorName, Collections.singletonList(xpathForDeltaReport), fetchDescendantsOption);
return getDeltaReports(sourceDataNodes, targetDataNodes, groupDataNodes);
}
}
}
+ private String validateXpath(final String xpath) {
+ try {
+ return ROOT_NODE_XPATH.equals(xpath) ? ROOT_NODE_XPATH : CpsPathUtil.getNormalizedXpath(xpath);
+ } catch (final PathParsingException pathParsingException) {
+ throw new DataValidationException("Invalid xpath: " + xpath, pathParsingException.getMessage(),
+ pathParsingException);
+ }
+ }
+
}
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023-2025 TechMahindra Ltd.
+ * Copyright (C) 2023-2025 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.
'updated with grouping enabled' | sourceDataNode | targetDataNode | GROUPING_ENABLED || 'replace' | ['parent':['parent-leaf': 'parent-leaf-as-source-data']] | ['parent':['parent-leaf': 'parent-leaf-as-target-data']]
}
+ def 'Get delta between 2 anchors with invalid xpath'() {
+ given: 'an invalid xpath'
+ def invalidXpath = '/test[invalid'
+ when: 'attempt to get delta between 2 anchors with invalid xpath'
+ objectUnderTest.getDeltaByDataspaceAndAnchors(dataspaceName, ANCHOR_NAME_1, ANCHOR_NAME_2, invalidXpath, INCLUDE_ALL_DESCENDANTS, GROUPING_DISABLED)
+ then: 'DataValidationException is thrown'
+ def exception = thrown(DataValidationException)
+ assert exception.message == 'Invalid xpath: /test[invalid'
+ }
+
def 'Delta Report between parent nodes with children where data node is #scenario without grouping of data nodes'() {
given: 'root node xpath and expected source and target data'
def xpath = '/'