aboutsummaryrefslogtreecommitdiffstats
path: root/cps-service/src
diff options
context:
space:
mode:
authorToineSiebelink <toine.siebelink@est.tech>2020-11-10 16:32:50 +0000
committerRuslan Kashapov <ruslan.kashapov@pantheon.tech>2020-12-01 13:24:01 +0200
commit46a7718bc0f0d2951ed18795c85f6961f839df25 (patch)
treef1d521a52247897e22718fa71b7c61bdfce3d1f1 /cps-service/src
parente731118eca0540792a140803f18c298fb3be132d (diff)
Xpath builder on data fragmentation
Issue-ID: CPS-72 Change-Id: Iab5be2bf0dd7d5540b8880bbf5ab2c6ed9342a9e Signed-off-by: Ruslan Kashapov <ruslan.kashapov@pantheon.tech>
Diffstat (limited to 'cps-service/src')
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/Fragment.java22
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/YangUtils.java40
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/utils/YangUtilsSpec.groovy4
3 files changed, 54 insertions, 12 deletions
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/Fragment.java b/cps-service/src/main/java/org/onap/cps/api/impl/Fragment.java
index 252b09e5c..90c92f905 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/Fragment.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/Fragment.java
@@ -39,7 +39,7 @@ import org.opendaylight.yangtools.yang.model.api.Module;
public class Fragment {
@Getter
- private String xpath;
+ private final String xpath;
@Getter
private final Map<String, Object> attributes = new HashMap<>();
@@ -62,9 +62,10 @@ public class Fragment {
*
* @param module the Yang module that encompasses this fragment
* @param qnames the list of qualified names that points the schema node for this fragment
+ * @param xpath the xpath of root fragment
*/
- public static Fragment createRootFragment(final Module module, final QName... qnames) {
- return new Fragment(null, module, qnames);
+ public static Fragment createRootFragment(final Module module, final QName[] qnames, final String xpath) {
+ return new Fragment(null, module, qnames, xpath);
}
/**
@@ -72,24 +73,27 @@ public class Fragment {
*
* @param parentFragment the parent (can be null for 'root' objects)
* @param module the Yang module that encompasses this fragment
- * @param qnames the list of qualified names that points the schema node for this fragment
+ * @param qnames array of qualified names that points the schema node for this fragment
+ * @param xpath the xpath for this fragment
*/
- private Fragment(final Fragment parentFragment, final Module module, final QName... qnames) {
+ private Fragment(final Fragment parentFragment, final Module module, final QName[] qnames, String xpath) {
this.parentFragment = parentFragment;
this.module = module;
this.qnames = qnames;
+ this.xpath = xpath;
}
/**
* Create a Child Fragment where the current Fragment is the parent.
*
- * @param qnameChild The Qualified name for the child (relative to the parent)
+ * @param childQname The Qualified name for the child (relative to the parent)
+ * @param childXPath The child xpath (relative to the parrent)
* @return the child fragment
*/
- public Fragment createChildFragment(final QName qnameChild) {
+ public Fragment createChildFragment(final QName childQname, final String childXPath) {
final QName[] qnamesForChild = Arrays.copyOf(qnames, qnames.length + 1);
- qnamesForChild[qnamesForChild.length - 1] = qnameChild;
- final Fragment childFragment = new Fragment(this, module, qnamesForChild);
+ qnamesForChild[qnamesForChild.length - 1] = childQname;
+ final Fragment childFragment = new Fragment(this, module, qnamesForChild, getXpath() + childXPath);
childFragments.add(childFragment);
return childFragment;
}
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 0f05d7d92..071ff6ad3 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
@@ -24,12 +24,16 @@ import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import java.util.ServiceLoader;
import java.util.logging.Logger;
+import java.util.stream.Collectors;
import org.onap.cps.api.impl.Fragment;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
@@ -116,8 +120,9 @@ public class YangUtils {
public static Fragment fragmentNormalizedNode(
final NormalizedNode<? extends YangInstanceIdentifier.PathArgument, ?> tree,
final Module module) {
- final QName nodeType = tree.getNodeType();
- final Fragment rootFragment = Fragment.createRootFragment(module, nodeType);
+ final QName[] nodeTypes = {tree.getNodeType()};
+ final String xpath = buildXpathId(tree.getIdentifier());
+ final Fragment rootFragment = Fragment.createRootFragment(module, nodeTypes, xpath);
fragmentNormalizedNode(rootFragment, tree);
return rootFragment;
}
@@ -167,8 +172,37 @@ public class YangUtils {
private static void createNodeForEachListElement(final Fragment currentFragment, final MapNode mapNode) {
final Collection<MapEntryNode> mapEntryNodes = mapNode.getValue();
for (final MapEntryNode mapEntryNode : mapEntryNodes) {
- final Fragment listElementFragment = currentFragment.createChildFragment(mapNode.getNodeType());
+ final String xpathId = buildXpathId(mapEntryNode.getIdentifier());
+ final Fragment listElementFragment =
+ currentFragment.createChildFragment(mapNode.getNodeType(), xpathId);
fragmentNormalizedNode(listElementFragment, mapEntryNode);
}
}
+
+ private static String buildXpathId(final YangInstanceIdentifier.PathArgument nodeIdentifier) {
+ final StringBuilder xpathIdBuilder = new StringBuilder();
+ xpathIdBuilder.append("/").append(nodeIdentifier.getNodeType().getLocalName());
+
+ if (nodeIdentifier instanceof NodeIdentifierWithPredicates) {
+ xpathIdBuilder.append(getKeyAttributesStatement((NodeIdentifierWithPredicates) nodeIdentifier));
+ }
+ return xpathIdBuilder.toString();
+ }
+
+ private static String getKeyAttributesStatement(final NodeIdentifierWithPredicates nodeIdentifier) {
+ final List<String> keyAttributes = nodeIdentifier.entrySet().stream().map(
+ entry -> {
+ final String name = entry.getKey().getLocalName();
+ final String value = String.valueOf(entry.getValue()).replace("'", "\\'");
+ return String.format("@%s='%s'", name, value);
+ }
+ ).collect(Collectors.toList());
+
+ if (keyAttributes.isEmpty()) {
+ return "";
+ } else {
+ Collections.sort(keyAttributes);
+ return "[" + String.join(" and ", keyAttributes) + "]";
+ }
+ }
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/YangUtilsSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/YangUtilsSpec.groovy
index 6a463ad6f..801e43079 100644
--- a/cps-service/src/test/groovy/org/onap/cps/utils/YangUtilsSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/utils/YangUtilsSpec.groovy
@@ -96,6 +96,10 @@ class YangUtilsSpec extends Specification{
result.childFragments.size() == 2
and: 'each child (category) has the root fragment (result) as parent and in turn as 1 child (a list of books)'
result.childFragments.each { it.parentFragment == result && it.childFragments.size() == 1 }
+ and: 'the fragments have the correct xpaths'
+ assert result.xpath == '/bookstore'
+ assert result.childFragments.collect { it.xpath }
+ .containsAll(["/bookstore/categories[@code='01']", "/bookstore/categories[@code='02']"])
}
}