Eliminate use of SchemaNode.getPath() in sal-netconf-connector 05/100005/7
authorOleksandrZharov <Oleksandr.Zharov@pantheon.tech>
Tue, 8 Mar 2022 18:30:50 +0000 (19:30 +0100)
committerTomas Cere <tomas.cere@pantheon.tech>
Fri, 11 Mar 2022 17:10:50 +0000 (17:10 +0000)
Removed deprecated getPath method and replaced it with alternative
ways using qnames and yang instance identifier.

JIRA: NETCONF-817
Change-Id: Ia809e60f96f9a747d5d72e71f96cf421815ed751
Signed-off-by: OleksandrZharov <Oleksandr.Zharov@pantheon.tech>
Signed-off-by: Ivan Hrasko <ivan.hrasko@pantheon.tech>
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/schema/mapping/NetconfMessageTransformer.java
netconf/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/schema/mapping/NetconfMessageTransformerTest.java

index 1d9ad98eff084ffa9b850b850b473e46a1178dca..db675ded0ab3294f6058016be6aac7aaeef2b5ed 100644 (file)
@@ -26,7 +26,6 @@ import java.io.IOException;
 import java.net.URISyntaxException;
 import java.time.Instant;
 import java.util.AbstractMap;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -60,6 +59,9 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.common.XMLNamespace;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
@@ -86,6 +88,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
 import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -120,7 +123,7 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
         this.contextTree = DataSchemaContextTree.from(schemaContext);
 
         this.mappedRpcs = Maps.uniqueIndex(schemaContext.getOperations(), SchemaNode::getQName);
-        this.actions = Maps.uniqueIndex(getActions(schemaContext), action -> action.getPath().asAbsolute());
+        this.actions = getActions(schemaContext);
 
         // RFC6020 normal notifications
         this.mappedNotifications = Multimaps.index(schemaContext.getNotifications(),
@@ -130,26 +133,33 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
     }
 
     @VisibleForTesting
-    // FIXME: return Map<Absolute, ActionDefinition> by using only
-    static List<ActionDefinition> getActions(final SchemaContext schemaContext) {
-        final List<ActionDefinition> builder = new ArrayList<>();
-        findAction(schemaContext, builder);
-        return builder;
+    static ImmutableMap<Absolute, ActionDefinition> getActions(final SchemaContext schemaContext) {
+        final Map<Absolute, ActionDefinition> values = new HashMap<>();
+        final SchemaInferenceStack stack = SchemaInferenceStack.of((EffectiveModelContext) schemaContext);
+        findAction(schemaContext, values, stack);
+        return ImmutableMap.copyOf(values);
     }
 
-    private static void findAction(final DataSchemaNode dataSchemaNode, final List<ActionDefinition> builder) {
+    private static void findAction(final DataSchemaNode dataSchemaNode, final Map<Absolute, ActionDefinition> builder,
+                                   final SchemaInferenceStack stack) {
         if (dataSchemaNode instanceof ActionNodeContainer) {
             for (ActionDefinition actionDefinition : ((ActionNodeContainer) dataSchemaNode).getActions()) {
-                builder.add(actionDefinition);
+                stack.enterSchemaTree(actionDefinition.getQName());
+                builder.put(stack.toSchemaNodeIdentifier(), actionDefinition);
+                stack.exit();
             }
         }
         if (dataSchemaNode instanceof DataNodeContainer) {
             for (DataSchemaNode innerDataSchemaNode : ((DataNodeContainer) dataSchemaNode).getChildNodes()) {
-                findAction(innerDataSchemaNode, builder);
+                stack.enterSchemaTree(innerDataSchemaNode.getQName());
+                findAction(innerDataSchemaNode, builder, stack);
+                stack.exit();
             }
         } else if (dataSchemaNode instanceof ChoiceSchemaNode) {
             for (CaseSchemaNode caze : ((ChoiceSchemaNode) dataSchemaNode).getCases()) {
-                findAction(caze, builder);
+                stack.enterSchemaTree(caze.getQName());
+                findAction(caze, builder, stack);
+                stack.exit();
             }
         }
     }
@@ -187,12 +197,26 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
         final NotificationDefinition mostRecentNotification = getMostRecentNotification(notificationDefinitions);
 
         final ContainerNode content;
+        final SchemaInferenceStack stack;
+        final List<QName> qnames;
+        if (nestedNotificationInfo != null) {
+            qnames = nestedNotificationInfo.domDataTreeIdentifier.getRootIdentifier().getPathArguments().stream()
+                    .filter(arg -> !(arg instanceof NodeIdentifierWithPredicates))
+                    .filter(arg -> !(arg instanceof AugmentationIdentifier))
+                    .map(PathArgument::getNodeType)
+                    .map(qName -> QName.create(mostRecentNotification.getQName(), qName.getLocalName()))
+                    .collect(Collectors.toList());
+            stack = SchemaInferenceStack.of(mountContext.getEffectiveModelContext(), Absolute.of(qnames));
+        } else {
+            stack = SchemaInferenceStack.of(mountContext.getEffectiveModelContext(),
+                    Absolute.of(mostRecentNotification.getQName()));
+        }
+
         try {
             final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
             final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
             final XmlParserStream xmlParser = XmlParserStream.create(writer, mountContext,
-                    SchemaInferenceStack.ofInstantiatedPath(mountContext.getEffectiveModelContext(),
-                        mostRecentNotification.getPath()).toInference(), strictParsing);
+                    stack.toInference(), strictParsing);
             xmlParser.traverse(new DOMSource(element));
             content = (ContainerNode) resultHolder.getResult();
         } catch (XMLStreamException | URISyntaxException | IOException | SAXException
@@ -202,8 +226,7 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
 
         if (nestedNotificationInfo != null) {
             return new NetconfDeviceTreeNotification(content,
-                // FIXME: improve this to cache the path
-                mostRecentNotification.getPath().asAbsolute(),
+                stack.toSchemaNodeIdentifier(),
                 stripped.getKey(), nestedNotificationInfo.domDataTreeIdentifier);
         }
 
@@ -424,7 +447,8 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
                     "Unable to parse response of %s, the rpc is unknown", rpc);
 
             // In case no input for rpc is defined, we can simply construct the payload here
-            normalizedNode = parseResult(message, rpcDefinition);
+            final Absolute rpcPath = Absolute.of(rpcDefinition.getQName(), rpcDefinition.getOutput().getQName());
+            normalizedNode = parseResult(message, rpcDefinition, rpcPath);
         }
         return new DefaultDOMRpcResult(normalizedNode);
     }
@@ -433,8 +457,12 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
     public DOMActionResult toActionResult(final Absolute action, final NetconfMessage message) {
         final ActionDefinition actionDefinition = actions.get(action);
         Preconditions.checkArgument(actionDefinition != null, "Action does not exist: %s", action);
-        final ContainerNode normalizedNode = (ContainerNode) parseResult(message, actionDefinition);
 
+        final SchemaInferenceStack stack = SchemaInferenceStack.of(mountContext.getEffectiveModelContext(), action);
+        stack.enterSchemaTree(actionDefinition.getOutput().getQName());
+        final Absolute actionPath = stack.toSchemaNodeIdentifier();
+
+        final ContainerNode normalizedNode = (ContainerNode) parseResult(message, actionDefinition, actionPath);
         if (normalizedNode == null) {
             return new SimpleDOMActionResult(Collections.emptyList());
         } else {
@@ -442,7 +470,8 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
         }
     }
 
-    private NormalizedNode parseResult(final NetconfMessage message, final OperationDefinition operationDefinition) {
+    private NormalizedNode parseResult(final NetconfMessage message, final OperationDefinition operationDefinition,
+                                       final Absolute operationPath) {
         final Optional<XmlElement> okResponseElement = XmlElement.fromDomDocument(message.getDocument())
                 .getOnlyChildElementWithSameNamespaceOptionally("ok");
         if (operationDefinition.getOutput().getChildNodes().isEmpty()) {
@@ -455,14 +484,14 @@ public class NetconfMessageTransformer implements MessageTransformer<NetconfMess
                 return null;
             }
 
-            Element element = message.getDocument().getDocumentElement();
+            final Element element = message.getDocument().getDocumentElement();
+            final Inference inference = SchemaInferenceStack.of(mountContext.getEffectiveModelContext(),
+                    operationPath).toInference();
             try {
                 final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
                 final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
                 final XmlParserStream xmlParser = XmlParserStream.create(writer, mountContext,
-                        // FIXME: we should have a cached inference here
-                        SchemaInferenceStack.ofInstantiatedPath(mountContext.getEffectiveModelContext(),
-                            operationDefinition.getOutput().getPath()).toInference(), strictParsing);
+                        inference, strictParsing);
                 xmlParser.traverse(new DOMSource(element));
                 return resultHolder.getResult();
             } catch (XMLStreamException | URISyntaxException | IOException | SAXException e) {
index ad1d47f5fbe91bc8bd0e5fbddc1fa36cee43165c..7c8eb62c94f9e934be0ff24368989749a5ed2957 100644 (file)
@@ -556,11 +556,10 @@ public class NetconfMessageTransformerTest extends AbstractBaseSchemasTest {
         schemaPaths.add(CHECK_WITH_OUTPUT_INTERFACE_PATH);
         schemaPaths.add(CHECK_WITHOUT_OUTPUT_INTERFACE_PATH);
 
-        List<ActionDefinition> actions = NetconfMessageTransformer.getActions(ACTION_SCHEMA);
+        final Map<Absolute, ActionDefinition> actions = NetconfMessageTransformer.getActions(ACTION_SCHEMA);
         assertEquals(schemaPaths.size(), actions.size());
-        for (ActionDefinition actionDefinition : actions) {
-            Absolute path = actionDefinition.getPath().asAbsolute();
-            assertTrue(schemaPaths.remove(path));
+        for (final Absolute actionPath : actions.keySet()) {
+            assertTrue(schemaPaths.remove(actionPath));
         }
     }