[ONOS-5112] Path referred multiple times is not handled.
Change-Id: I2e9a3a9571515e687bd18471a4aac62f3ce7f462
diff --git a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangXpathLinker.java b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangXpathLinker.java
index 5369a67..89d2dbe 100644
--- a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangXpathLinker.java
+++ b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangXpathLinker.java
@@ -118,6 +118,15 @@
}
/**
+ * Adds target nodes paths.
+ *
+ * @param absPaths target nodes paths
+ */
+ private void addAbsPaths(YangAtomicPath absPaths) {
+ getAbsPaths().add(absPaths);
+ }
+
+ /**
* Returns current prefix.
*
* @return current prefix
@@ -201,9 +210,11 @@
if (atomicPaths.size() == 1) {
targetNode = getTargetNodewhenSizeIsOne(atomicPaths);
} else {
- atomicPaths.remove(atomicPaths.size() - 1);
-
- setAbsPaths(atomicPaths);
+ for (YangAtomicPath atomicPath : atomicPaths) {
+ if (atomicPath != leafRefPath) {
+ addAbsPaths(atomicPath);
+ }
+ }
targetNode = parseData(root);
}
if (targetNode == null) {
diff --git a/plugin/src/test/java/org/onosproject/yangutils/plugin/manager/InterFileLeafrefLinkingTest.java b/plugin/src/test/java/org/onosproject/yangutils/plugin/manager/InterFileLeafrefLinkingTest.java
index dd1029e..cfa59cb 100644
--- a/plugin/src/test/java/org/onosproject/yangutils/plugin/manager/InterFileLeafrefLinkingTest.java
+++ b/plugin/src/test/java/org/onosproject/yangutils/plugin/manager/InterFileLeafrefLinkingTest.java
@@ -19,17 +19,19 @@
import java.io.IOException;
import java.util.Iterator;
import java.util.ListIterator;
-
import org.apache.maven.plugin.MojoExecutionException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.onosproject.yangutils.datamodel.YangContainer;
import org.onosproject.yangutils.datamodel.YangLeaf;
+import org.onosproject.yangutils.datamodel.YangLeafList;
import org.onosproject.yangutils.datamodel.YangLeafRef;
import org.onosproject.yangutils.datamodel.YangList;
import org.onosproject.yangutils.datamodel.YangModule;
import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.datamodel.YangNodeType;
+import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
import org.onosproject.yangutils.linker.impl.YangLinkerManager;
import org.onosproject.yangutils.parser.exceptions.ParserException;
@@ -350,4 +352,86 @@
assertThat(leafref1.getEffectiveDataType().getDataType(),
is(YangDataTypes.DERIVED));
}
+
+ /**
+ * Checks self resolution when leafref under typedef been referred multiple times.
+ */
+ @Test
+ public void processLeafrefWhenUsedMultipleTimes()
+ throws IOException, ParserException {
+ String searchDir = "src/test/resources/leafreflinker/interfile/typedefreferredmultipletimes";
+ utilManager.createYangFileInfoSet(YangFileScanner.getYangFiles(searchDir));
+ utilManager.parseYangFileInfoSet();
+ utilManager.createYangNodeSet();
+ YangNode selfNode = null;
+
+ // Create YANG node set
+ yangLinkerManager.createYangNodeSet(utilManager.getYangNodeSet());
+
+ // Add references to import list.
+ yangLinkerManager.addRefToYangFilesImportList(utilManager.getYangNodeSet());
+
+ updateFilePriority(utilManager.getYangNodeSet());
+
+ // Carry out inter-file linking.
+ yangLinkerManager.processInterFileLinking(utilManager.getYangNodeSet());
+
+ Iterator<YangNode> yangNodeIterator = utilManager.getYangNodeSet().iterator();
+
+ YangNode rootNode = yangNodeIterator.next();
+
+ if (rootNode.getName().equals("ietf-interfaces")) {
+ selfNode = rootNode;
+ }
+
+ // Check whether the data model tree returned is of type module.
+ assertThat((selfNode instanceof YangModule), is(true));
+
+ // Check whether the node type is set properly to module.
+ assertThat(selfNode.getNodeType(), is(YangNodeType.MODULE_NODE));
+
+ // Check whether the module name is set correctly.
+ YangModule yangNode = (YangModule) selfNode;
+ assertThat(yangNode.getName(), is("ietf-interfaces"));
+
+ YangContainer container = (YangContainer) yangNode.getChild().getNextSibling();
+
+ YangList list = (YangList) container.getChild();
+
+ ListIterator<YangLeafList> leafIterator;
+ YangLeafList leafInfo;
+
+ leafIterator = list.getListOfLeafList().listIterator();
+ leafInfo = leafIterator.next();
+
+ // Check whether the information in the leaf is correct.
+ assertThat(leafInfo.getName(), is("higher-layer-if"));
+ assertThat(leafInfo.getDataType().getDataTypeName(), is("leafref"));
+ assertThat(leafInfo.getDataType().getDataType(), is(YangDataTypes.LEAFREF));
+ YangLeafRef leafref = (YangLeafRef) (leafInfo.getDataType().getDataTypeExtendedInfo());
+
+ // Check whether leafref type got resolved.
+ assertThat(leafref.getResolvableStatus(),
+ is(ResolvableStatus.RESOLVED));
+
+ // Check the effective type for the leaf.
+ assertThat(leafref.getEffectiveDataType().getDataType(),
+ is(YangDataTypes.STRING));
+
+ leafInfo = leafIterator.next();
+
+ // Check whether the information in the leaf is correct.
+ assertThat(leafInfo.getName(), is("lower-layer-if"));
+ assertThat(leafInfo.getDataType().getDataTypeName(), is("leafref"));
+ assertThat(leafInfo.getDataType().getDataType(), is(YangDataTypes.LEAFREF));
+ YangLeafRef leafref1 = (YangLeafRef) (leafInfo.getDataType().getDataTypeExtendedInfo());
+
+ // Check whether leafref type got resolved.
+ assertThat(leafref1.getResolvableStatus(),
+ is(ResolvableStatus.RESOLVED));
+
+ // Check the effective type for the leaf.
+ assertThat(leafref1.getEffectiveDataType().getDataType(),
+ is(YangDataTypes.STRING));
+ }
}
diff --git a/plugin/src/test/resources/leafreflinker/interfile/typedefreferredmultipletimes/ietf-interfaces.yang b/plugin/src/test/resources/leafreflinker/interfile/typedefreferredmultipletimes/ietf-interfaces.yang
new file mode 100644
index 0000000..31bcb98
--- /dev/null
+++ b/plugin/src/test/resources/leafreflinker/interfile/typedefreferredmultipletimes/ietf-interfaces.yang
@@ -0,0 +1,55 @@
+module ietf-interfaces {
+ namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+ prefix if;
+ typedef interface-state-ref {
+ type leafref {
+ path "/if:interfaces-state/if:interface/if:name";
+ }
+ description
+ "This type is used by data models that need to reference
+ the operationally present interfaces";
+ }
+ /*
+ * Operational state data nodes
+ */
+ container interfaces-state {
+ config false;
+ description
+ "Data nodes for the operational state of interfaces.";
+ list interface {
+ key "name";
+ description
+ "The list of interfaces on the device.
+ System-controlled interfaces created by the system are
+ always present in this list, whether they are configured or
+ not.";
+ leaf name {
+ type string;
+ description
+ "The name of the interface.
+ A server implementation MAY map this leaf to the ifName
+ MIB object. Such an implementation needs to use some
+ mechanism to handle the differences in size and characters
+ allowed between this leaf and ifName. The definition of
+ such a mechanism is outside the scope of this document.";
+ reference "RFC 2863: The Interfaces Group MIB - ifName";
+ }
+ leaf-list higher-layer-if {
+ type interface-state-ref;
+ description
+ "A list of references to interfaces layered on top of this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+ leaf-list lower-layer-if {
+ type interface-state-ref;
+ description
+ "A list of references to interfaces layered underneath this
+ interface.";
+ reference
+ "RFC 2863: The Interfaces Group MIB - ifStackTable";
+ }
+ }
+ }
+}