[ONOS-4799],[ONOS-4351] Augment inter file linker and Generated Code refactored.
Change-Id: Id1f3ac9c90a632373f51cc75d499c3110216be17
diff --git a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangLinkerManager.java b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangLinkerManager.java
index 3847d3d..f63d8df 100644
--- a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangLinkerManager.java
+++ b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangLinkerManager.java
@@ -161,6 +161,8 @@
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_USES);
((YangReferenceResolver) yangNode)
+ .resolveInterFileLinking(ResolvableType.YANG_AUGMENT);
+ ((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_DERIVED_DATA_TYPE);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_LEAFREF);
diff --git a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangLinkerUtils.java b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangLinkerUtils.java
new file mode 100644
index 0000000..38a8188
--- /dev/null
+++ b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangLinkerUtils.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yangutils.linker.impl;
+
+import java.util.List;
+
+import org.onosproject.yangutils.datamodel.YangAugment;
+import org.onosproject.yangutils.datamodel.YangAugmentableNode;
+import org.onosproject.yangutils.datamodel.YangAugmentedInfo;
+import org.onosproject.yangutils.datamodel.YangLeaf;
+import org.onosproject.yangutils.datamodel.YangLeafList;
+import org.onosproject.yangutils.datamodel.YangLeavesHolder;
+import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.linker.exceptions.LinkerException;
+
+/**
+ * Represent utilities for YANG linker.
+ */
+public final class YangLinkerUtils {
+
+ private YangLinkerUtils() {
+ }
+
+ /**
+ * Detects collision between target nodes leaf/leaf-list or child node with
+ * augmented leaf/leaf-list or child node.
+ *
+ * @param targetNode target node
+ * @param augment augment node
+ */
+ private static void detectCollision(YangNode targetNode, YangAugment augment) {
+ YangNode targetNodesChild = targetNode.getChild();
+ YangNode augmentsChild = augment.getChild();
+ YangLeavesHolder augmentsLeavesHolder = augment;
+ YangLeavesHolder targetNodesLeavesHolder = (YangLeavesHolder) targetNode;
+
+ YangNode parent = targetNode;
+ if (targetNode instanceof YangAugment) {
+ parent = targetNode.getParent();
+ } else {
+ while (parent.getParent() != null) {
+ parent = parent.getParent();
+ }
+ }
+ if (augmentsLeavesHolder.getListOfLeaf() != null && augmentsLeavesHolder.getListOfLeaf().size() != 0
+ && targetNodesLeavesHolder.getListOfLeaf() != null) {
+ for (YangLeaf leaf : augmentsLeavesHolder.getListOfLeaf()) {
+ for (YangLeaf targetLeaf : targetNodesLeavesHolder.getListOfLeaf()) {
+ if (targetLeaf.getName().equals(leaf.getName())) {
+ throw new LinkerException("target node " + targetNode.getName()
+ + " contains augmented leaf " + leaf.getName() + " in module "
+ + parent.getName());
+ }
+ }
+ }
+ } else if (augmentsLeavesHolder.getListOfLeafList() != null
+ && augmentsLeavesHolder.getListOfLeafList().size() != 0
+ && targetNodesLeavesHolder.getListOfLeafList() != null) {
+ for (YangLeafList leafList : augmentsLeavesHolder.getListOfLeafList()) {
+ for (YangLeafList targetLeafList : targetNodesLeavesHolder.getListOfLeafList()) {
+ if (targetLeafList.getName().equals(leafList.getName())) {
+ throw new LinkerException("target node " + targetNode.getName()
+ + " contains augmented leaf-list" + leafList.getName() + " in module "
+ + parent.getName());
+ }
+ }
+ }
+ } else {
+ while (augmentsChild != null) {
+ while (targetNodesChild != null) {
+ if (targetNodesChild.getName().equals(augmentsChild.getName())) {
+ throw new LinkerException("target node " + targetNode.getName()
+ + " contains augmented child node" + augmentsChild.getName() + " in module "
+ + parent.getName());
+ }
+ targetNodesChild = targetNodesChild.getNextSibling();
+ }
+ augmentsChild = augmentsChild.getNextSibling();
+ }
+ }
+ }
+
+ /**
+ * Detects collision between target nodes and its all leaf/leaf-list or child node with
+ * augmented leaf/leaf-list or child node.
+ *
+ * @param targetNode target node
+ * @param augment augment node
+ */
+ public static void detectCollisionForAugmentedNode(YangNode targetNode, YangAugment augment) {
+ // Detect collision for target node and augment node.
+ detectCollision(targetNode, augment);
+ List<YangAugmentedInfo> yangAugmentedInfo = ((YangAugmentableNode) targetNode).getAugmentedInfoList();
+ // Detect collision for target augment node and current augment node.
+ for (YangAugmentedInfo info : yangAugmentedInfo) {
+ detectCollision((YangAugment) info, augment);
+ }
+ }
+}
diff --git a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
index eb42233..bcc5a5f 100644
--- a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
+++ b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
@@ -24,6 +24,8 @@
import org.onosproject.yangutils.datamodel.Resolvable;
import org.onosproject.yangutils.datamodel.ResolvableType;
import org.onosproject.yangutils.datamodel.YangAtomicPath;
+import org.onosproject.yangutils.datamodel.YangAugment;
+import org.onosproject.yangutils.datamodel.YangAugmentableNode;
import org.onosproject.yangutils.datamodel.YangBase;
import org.onosproject.yangutils.datamodel.YangDerivedInfo;
import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
@@ -55,10 +57,12 @@
import org.onosproject.yangutils.datamodel.YangType;
import org.onosproject.yangutils.datamodel.YangTypeDef;
import org.onosproject.yangutils.datamodel.YangUses;
+import org.onosproject.yangutils.datamodel.YangXPathResolver;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yangutils.datamodel.utils.ResolvableStatus;
import org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes;
import org.onosproject.yangutils.linker.YangLinkingPhase;
+import org.onosproject.yangutils.linker.exceptions.LinkerException;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTER_FILE_LINKED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
@@ -68,6 +72,7 @@
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNRESOLVED;
import static org.onosproject.yangutils.linker.YangLinkingPhase.INTER_FILE;
import static org.onosproject.yangutils.linker.YangLinkingPhase.INTRA_FILE;
+import static org.onosproject.yangutils.linker.impl.YangLinkerUtils.detectCollisionForAugmentedNode;
import static org.onosproject.yangutils.utils.UtilConstants.FEATURE_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.INPUT;
@@ -1438,14 +1443,73 @@
throw new DataModelException("Data Model Exception: Entity to resolved is not Resolvable");
}
- // Push the initial entity to resolve in stack.
- addInPartialResolvedStack(getEntityToResolveInfo());
+ if (entityToResolve instanceof YangXPathResolver) {
+ //Process x-path linking.
+ processXPathLinking(getEntityToResolveInfo(), dataModelRootNode);
- // Inter file linking and resolution.
- linkInterFileAndResolve();
+ } else {
- // Resolve the derived types having leafref.
- addDerivedRefTypeToRefTypeResolutionList();
+ // Push the initial entity to resolve in stack.
+ addInPartialResolvedStack(getEntityToResolveInfo());
+
+ // Inter file linking and resolution.
+ linkInterFileAndResolve();
+
+ addDerivedRefTypeToRefTypeResolutionList();
+ }
+ }
+
+ /**
+ * Process x-path linking for augment and leaf-ref.
+ *
+ * @param entityToResolveInfo entity to resolve
+ * @param root root node
+ */
+ private void processXPathLinking(YangEntityToResolveInfoImpl<T> entityToResolveInfo,
+ YangReferenceResolver root) {
+ YangXpathLinker<T> xPathLinker = new YangXpathLinker<T>();
+ T entityToResolve = entityToResolveInfo.getEntityToResolve();
+ if (entityToResolve instanceof YangAugment) {
+ YangNode targetNode = null;
+ YangAugment augment = (YangAugment) entityToResolve;
+ targetNode = xPathLinker.processAugmentXpathLinking(augment.getTargetNode(),
+ (YangNode) root);
+ if (targetNode != null) {
+ if (targetNode instanceof YangAugmentableNode) {
+ detectCollisionForAugmentedNode(targetNode, augment);
+ ((YangAugmentableNode) targetNode).addAugmentation(augment);
+ augment.setAugmentedNode(targetNode);
+ Resolvable resolvable = (Resolvable) entityToResolve;
+ resolvable.setResolvableStatus(RESOLVED);
+ } else {
+ throw new LinkerException("Invalid target node type " + targetNode.getNodeType() + " for "
+ + augment.getName());
+ }
+ } else {
+ throw new LinkerException("Failed to link " + augment.getName());
+ }
+ } else if (entityToResolve instanceof YangLeafRef) {
+ YangLeafRef leafRef = (YangLeafRef) entityToResolve;
+ Object target = xPathLinker.processLeafRefXpathLinking(leafRef.getAtomicPath(),
+ (YangNode) root);
+ if (target != null) {
+ YangLeaf leaf = null;
+ YangLeafList leafList = null;
+ leafRef.setReferredLeafOrLeafList(target);
+ if (target instanceof YangLeaf) {
+ leaf = (YangLeaf) target;
+ leafRef.setEffectiveDataType(leaf.getDataType());
+ } else {
+ leafList = (YangLeafList) target;
+ leafRef.setEffectiveDataType(leafList.getDataType());
+ }
+ leafRef.setResolvableStatus(RESOLVED);
+ //TODO: add logic for leaf-ref for path predicates.
+ } else {
+ throw new LinkerException("YANG file error: Unable to find base leaf/leaf-list for given leafref "
+ + leafRef.getPath());
+ }
+ }
}
/**
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
new file mode 100644
index 0000000..681a52c
--- /dev/null
+++ b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangXpathLinker.java
@@ -0,0 +1,711 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.yangutils.linker.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+import org.onosproject.yangutils.datamodel.YangAtomicPath;
+import org.onosproject.yangutils.datamodel.YangAugment;
+import org.onosproject.yangutils.datamodel.YangImport;
+import org.onosproject.yangutils.datamodel.YangInclude;
+import org.onosproject.yangutils.datamodel.YangLeaf;
+import org.onosproject.yangutils.datamodel.YangLeafList;
+import org.onosproject.yangutils.datamodel.YangLeavesHolder;
+import org.onosproject.yangutils.datamodel.YangModule;
+import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
+import org.onosproject.yangutils.datamodel.YangSubModule;
+import org.onosproject.yangutils.datamodel.YangUses;
+import org.onosproject.yangutils.linker.exceptions.LinkerException;
+
+/**
+ * Represents x-path linking.
+ *
+ * @param <T> x-path linking can be done for target node or for target leaf/leaf-list
+ */
+public class YangXpathLinker<T> {
+
+ /**
+ * Enum for prefix resolver type when augment has come in path.
+ */
+ private static enum PrefixResolverType {
+
+ /**
+ * When prefix changes from inter file to intra file.
+ */
+ INTER_TO_INTRA,
+
+ /**
+ * When prefix changes from intra file to inter file.
+ */
+ INTRA_TO_INTER,
+
+ /**
+ * When prefix changes from one inter file to other inter file.
+ */
+ INTER_TO_INTER,
+
+ /**
+ * When no prefix change occurres.
+ */
+ NO_PREFIX_CHANGE_FOR_INTRA,
+
+ /**
+ * When no prefix change occurres.
+ */
+ NO_PREFIX_CHANGE_FOR_INTER
+ }
+
+ private List<YangAtomicPath> absPaths;
+ private YangNode rootNode;
+ private PrefixResolverType type;
+ private String curPrefix;
+ private Map<YangAtomicPath, YangNode> resolvedNodes;
+
+ /**
+ * Creates an instance of x-path linker.
+ */
+ public YangXpathLinker() {
+ absPaths = new ArrayList<>();
+ setResolvedNodes(new HashMap<>());
+ }
+
+ /**
+ * Returns list of target nodes paths.
+ *
+ * @return target nodes paths
+ */
+ private List<YangAtomicPath> getAbsPaths() {
+ return absPaths;
+ }
+
+ /**
+ * Sets target nodes paths.
+ *
+ * @param absPaths target nodes paths
+ */
+ private void setAbsPaths(List<YangAtomicPath> absPaths) {
+ this.absPaths = absPaths;
+ }
+
+ /**
+ * Returns current prefix.
+ *
+ * @return current prefix
+ */
+ private String getCurPrefix() {
+ return curPrefix;
+ }
+
+ /**
+ * Sets current prefix.
+ *
+ * @param curPrefix current prefix
+ */
+ private void setCurPrefix(String curPrefix) {
+ this.curPrefix = curPrefix;
+ }
+
+ /**
+ * Return root node.
+ *
+ * @return root Node
+ */
+ private YangNode getRootNode() {
+ return rootNode;
+ }
+
+ /**
+ * Sets root node.
+ *
+ * @param rootNode root node
+ */
+ private void setRootNode(YangNode rootNode) {
+ this.rootNode = rootNode;
+ }
+
+ /**
+ * Returns prefix resolver type.
+ *
+ * @return prefix resolver type
+ */
+ private PrefixResolverType getPrefixResolverType() {
+ return type;
+ }
+
+ /**
+ * Sets prefix resolver type.
+ *
+ * @param type prefix resolver type
+ */
+ private void setPrefixResolverType(PrefixResolverType type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns resolved nodes.
+ *
+ * @return resolved nodes
+ */
+ public Map<YangAtomicPath, YangNode> getResolvedNodes() {
+ return resolvedNodes;
+ }
+
+ /**
+ * Sets resolved nodes.
+ *
+ * @param resolvedNodes resolved nodes
+ */
+ private void setResolvedNodes(Map<YangAtomicPath, YangNode> resolvedNodes) {
+ this.resolvedNodes = resolvedNodes;
+ }
+
+ /**
+ * Adds node to resolved nodes.
+ *
+ * @param path absolute path
+ * @param node resolved node
+ */
+ private void addToResolvedNodes(YangAtomicPath path, YangNode node) {
+ getResolvedNodes().put(path, node);
+ }
+
+ /**
+ * Returns list of augment nodes.
+ *
+ * @param node root node
+ * @return list of augment nodes
+ */
+ public List<YangAugment> getListOfYangAugment(YangNode node) {
+ node = node.getChild();
+ List<YangAugment> augments = new ArrayList<>();
+ while (node != null) {
+ if (node instanceof YangAugment) {
+ augments.add((YangAugment) node);
+ }
+ node = node.getNextSibling();
+ }
+ return augments;
+ }
+
+ /**
+ * Process absolute node path for target leaf.
+ *
+ * @param absPaths absolute path node list
+ * @param root root node
+ * @return linked target node
+ */
+ public T processLeafRefXpathLinking(List<YangAtomicPath> absPaths, YangNode root) {
+
+ YangNode targetNode = null;
+ setRootNode(root);
+ YangAtomicPath leafRefPath = absPaths.get(absPaths.size() - 1);
+
+ // When leaf-ref path contains only one absolute path.
+ if (absPaths.size() == 1) {
+ targetNode = getTargetNodewhenSizeIsOne(absPaths);
+ } else {
+ absPaths.remove(absPaths.size() - 1);
+
+ setAbsPaths(absPaths);
+ targetNode = parseData(root);
+ }
+ if (targetNode == null) {
+ targetNode = parsePath(getIncludedNode(root));
+ }
+
+ if (targetNode != null) {
+ YangLeaf targetLeaf = searchReferredLeaf(targetNode, leafRefPath.getNodeIdentifier().getName());
+ if (targetLeaf == null) {
+ YangLeafList targetLeafList = searchReferredLeafList(targetNode,
+ leafRefPath.getNodeIdentifier().getName());
+ if (targetLeafList != null) {
+ return (T) targetLeafList;
+ } else {
+ throw new LinkerException(
+ "YANG file error: Unable to find base leaf/leaf-list for given leafref "
+ + leafRefPath.getNodeIdentifier().getName());
+ }
+ }
+ return (T) targetLeaf;
+ }
+ return null;
+ }
+
+ /**
+ * Returns target node when leaf-ref has only one absolute path in list.
+ *
+ * @param absPaths absolute paths
+ * @return target node
+ */
+ private YangNode getTargetNodewhenSizeIsOne(List<YangAtomicPath> absPaths) {
+ if (absPaths.get(0).getNodeIdentifier().getPrefix() != null
+ && !absPaths.get(0).getNodeIdentifier().getPrefix().equals(getRootsPrefix(getRootNode()))) {
+ return getImportedNode(getRootNode(), absPaths.get(0).getNodeIdentifier());
+ }
+ return getRootNode();
+
+ }
+
+ /**
+ * Process absolute node path linking for augment.
+ *
+ * @param absPaths absolute path node list
+ * @param root root node
+ * @return linked target node
+ */
+ public YangNode processAugmentXpathLinking(List<YangAtomicPath> absPaths, YangNode root) {
+
+ setAbsPaths(absPaths);
+ setRootNode(root);
+
+ YangNode targetNode = parseData(root);
+
+ if (targetNode == null) {
+ targetNode = parsePath(getIncludedNode(root));
+ }
+ return targetNode;
+
+ }
+
+ /**
+ * Searches for the referred leaf in target node.
+ *
+ * @param targetNode target node
+ * @param leafName leaf name
+ * @return target leaf
+ */
+ private YangLeaf searchReferredLeaf(YangNode targetNode, String leafName) {
+ if (!(targetNode instanceof YangLeavesHolder)) {
+ throw new LinkerException("Refered node " + targetNode.getName() +
+ "should be of type leaves holder ");
+ }
+ YangLeavesHolder holder = (YangLeavesHolder) targetNode;
+ List<YangLeaf> leaves = holder.getListOfLeaf();
+ for (YangLeaf leaf : leaves) {
+ if (leaf.getName().equals(leafName)) {
+ return leaf;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Searches for the referred leaf-list in target node.
+ *
+ * @param targetNode target node
+ * @param leafListName leaf-list name
+ * @return target leaf-list
+ */
+ private YangLeafList searchReferredLeafList(YangNode targetNode, String leafListName) {
+ if (!(targetNode instanceof YangLeavesHolder)) {
+ throw new LinkerException("Refered node " + targetNode.getName() +
+ "should be of type leaves holder ");
+ }
+ YangLeavesHolder holder = (YangLeavesHolder) targetNode;
+ List<YangLeafList> leavesList = holder.getListOfLeafList();
+ for (YangLeafList leafList : leavesList) {
+ if (leafList.getName().equals(leafListName)) {
+ return leafList;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Process linking using for node identifier for inter/intra file.
+ *
+ * @param root root node
+ * @return linked target node
+ */
+ private YangNode parseData(YangNode root) {
+ String rootPrefix = getRootsPrefix(root);
+ Iterator<YangAtomicPath> pathIterator = getAbsPaths().iterator();
+ YangAtomicPath path = pathIterator.next();
+ if (path.getNodeIdentifier().getPrefix() != null
+ && !path.getNodeIdentifier().getPrefix().equals(rootPrefix)) {
+ return parsePath(getImportedNode(root, path.getNodeIdentifier()));
+ } else {
+ return parsePath(root);
+ }
+ }
+
+ /**
+ * Process linking of target node in root node.
+ *
+ * @param root root node
+ * @return linked target node
+ */
+ private YangNode parsePath(YangNode root) {
+
+ YangNode tempNode = root;
+ Stack<YangNode> linkerStack = new Stack<>();
+ Iterator<YangAtomicPath> pathIterator = getAbsPaths().iterator();
+ YangAtomicPath tempPath = pathIterator.next();
+ setCurPrefix(tempPath.getNodeIdentifier().getPrefix());
+ int index = 0;
+ YangNode tempAugment = null;
+ do {
+
+ if (tempNode instanceof YangUses) {
+ tempNode = handleUsesNode(tempNode, tempPath.getNodeIdentifier());
+ if (pathIterator.hasNext()) {
+ tempPath = pathIterator.next();
+ index++;
+ } else {
+ addToResolvedNodes(tempPath, tempNode);
+ return tempNode;
+ }
+ }
+
+ if (tempPath.getNodeIdentifier().getPrefix() == null) {
+ tempAugment = resolveIntraFileAugment(tempPath, root);
+ } else {
+ tempAugment = resolveInterFileAugment(tempPath, root);
+ }
+
+ if (tempAugment != null) {
+ linkerStack.push(tempNode);
+ tempNode = tempAugment;
+ }
+
+ tempNode = searchTargetNode(tempNode, tempPath.getNodeIdentifier());
+ if (tempNode == null && linkerStack.size() != 0) {
+ tempNode = linkerStack.peek();
+ linkerStack.pop();
+ tempNode = searchTargetNode(tempNode, tempPath.getNodeIdentifier());
+ }
+
+ if (tempNode != null) {
+ addToResolvedNodes(tempPath, tempNode);
+ }
+
+ if (index == getAbsPaths().size() - 1) {
+ break;
+ }
+ tempPath = pathIterator.next();
+ index++;
+ } while (validate(tempNode, index));
+ return tempNode;
+ }
+
+ /**
+ * Resolves intra file augment linking.
+ *
+ * @param tempPath temporary absolute path
+ * @param root root node
+ * @return linked target node
+ */
+ private YangNode resolveIntraFileAugment(YangAtomicPath tempPath, YangNode root) {
+ YangNode tempAugment = null;
+ setPrefixResolverType(PrefixResolverType.NO_PREFIX_CHANGE_FOR_INTRA);
+ if (getCurPrefix() != tempPath.getNodeIdentifier().getPrefix()) {
+ setPrefixResolverType(PrefixResolverType.INTRA_TO_INTER);
+ root = getIncludedNode(getRootNode());
+ }
+
+ setCurPrefix(tempPath.getNodeIdentifier().getPrefix());
+ tempAugment = getAugment(tempPath.getNodeIdentifier(), root, getAbsPaths());
+ if (tempAugment == null) {
+ tempAugment = getAugment(tempPath.getNodeIdentifier(), getRootNode(), getAbsPaths());
+ }
+ return tempAugment;
+ }
+
+ /**
+ * Resolves inter file augment linking.
+ *
+ * @param tempPath temporary absolute path
+ * @param root root node
+ * @return linked target node
+ */
+ private YangNode resolveInterFileAugment(YangAtomicPath tempPath, YangNode root) {
+
+ YangNode tempAugment = null;
+ if (tempPath.getNodeIdentifier().getPrefix().equals(getCurPrefix())) {
+ setPrefixResolverType(PrefixResolverType.NO_PREFIX_CHANGE_FOR_INTER);
+ } else {
+ setCurPrefix(tempPath.getNodeIdentifier().getPrefix());
+ setPrefixResolverType(PrefixResolverType.INTER_TO_INTER);
+ if (getCurPrefix() == null) {
+ setPrefixResolverType(PrefixResolverType.INTER_TO_INTRA);
+ }
+ root = getImportedNode(getRootNode(), tempPath.getNodeIdentifier());
+ }
+ tempAugment = getAugment(tempPath.getNodeIdentifier(), root, getAbsPaths());
+ if (tempAugment == null && getPrefixResolverType().equals(PrefixResolverType.INTER_TO_INTER)) {
+ return resolveInterToInterFileAugment(root);
+ }
+ return tempAugment;
+ }
+
+ /**
+ * Resolves augment when prefix changed from inter file to inter file.
+ * it may be possible that the prefix used in imported module is different the
+ * given list of node identifiers.
+ *
+ * @param root root node
+ * @return target node
+ */
+ private YangNode resolveInterToInterFileAugment(YangNode root) {
+ List<YangAugment> augments = getListOfYangAugment(root);
+ int index;
+ List<YangAtomicPath> absPaths = new ArrayList<>();
+ for (YangAugment augment : augments) {
+ index = 0;
+
+ for (YangAtomicPath path : augment.getTargetNode()) {
+
+ if (!searchForAugmentInImportedNode(path.getNodeIdentifier(), index)) {
+ absPaths.clear();
+ break;
+ }
+ absPaths.add(path);
+ index++;
+ }
+ if (!absPaths.isEmpty() && absPaths.size() == getAbsPaths().size() - 1) {
+ return augment;
+ } else {
+ absPaths.clear();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Searches for the augment node in imported module when prefix has changed from
+ * inter file to inter file.
+ * @param nodeId node id
+ * @param index index
+ * @return true if found
+ */
+ private boolean searchForAugmentInImportedNode(YangNodeIdentifier nodeId, int index) {
+ YangNodeIdentifier tempNodeId = getAbsPaths().get(index).getNodeIdentifier();
+ return nodeId.getName().equals(tempNodeId.getName());
+ }
+
+ /**
+ * Returns augment node.
+ *
+ * @param tempNodeId temporary absolute path id
+ * @param root root node
+ * @return linked target node
+ */
+ private YangNode getAugment(YangNodeIdentifier tempNodeId, YangNode root, List<YangAtomicPath> absPaths) {
+ String augmentName = getAugmentNodeIdentifier(tempNodeId, absPaths);
+ if (augmentName != null) {
+ return searchAugmentNode(root, augmentName);
+ }
+ return null;
+ }
+
+ /**
+ * Process linking using import list.
+ *
+ * @param root root node
+ * @param nodeId node identifier
+ * @return linked target node
+ */
+ private YangNode getImportedNode(YangNode root, YangNodeIdentifier nodeId) {
+
+ List<YangImport> importList = new ArrayList<>();
+
+ if (root instanceof YangModule) {
+ importList = ((YangModule) root).getImportList();
+ } else {
+ importList = ((YangSubModule) root).getImportList();
+ }
+
+ for (YangImport imported : importList) {
+ if (imported.getPrefixId().equals(nodeId.getPrefix())) {
+ return imported.getImportedNode();
+ }
+ }
+
+ return root;
+ }
+
+ /**
+ * Process linking using include list.
+ *
+ * @param root root node
+ * @return linked target node
+ */
+ private YangNode getIncludedNode(YangNode root) {
+
+ List<YangInclude> includeList = new ArrayList<>();
+
+ if (root instanceof YangModule) {
+ includeList = ((YangModule) root).getIncludeList();
+ } else {
+ includeList = ((YangSubModule) root).getIncludeList();
+ }
+
+ for (YangInclude included : includeList) {
+ return included.getIncludedNode();
+ }
+
+ return root;
+ }
+
+ /**
+ * Returns augments node id.
+ *
+ * @param nodeId node identifier
+ * @return augment node id
+ */
+ private String getAugmentNodeIdentifier(YangNodeIdentifier nodeId, List<YangAtomicPath> absPaths) {
+
+ Iterator<YangAtomicPath> nodeIdIterator = absPaths.iterator();
+ YangAtomicPath tempNodeId = null;
+ StringBuilder builder = new StringBuilder();
+ while (nodeIdIterator.hasNext()) {
+ tempNodeId = nodeIdIterator.next();
+ if (!tempNodeId.getNodeIdentifier().equals(nodeId)) {
+ if (tempNodeId.getNodeIdentifier().getPrefix() != null
+ && (getPrefixResolverType().equals(PrefixResolverType.INTER_TO_INTER)
+ || getPrefixResolverType().equals(PrefixResolverType.INTRA_TO_INTER))) {
+ builder.append("/" + tempNodeId.getNodeIdentifier().getPrefix());
+ builder.append(":" + tempNodeId.getNodeIdentifier().getName());
+ } else {
+ builder.append("/" + tempNodeId.getNodeIdentifier().getName());
+ }
+ } else {
+ return builder.toString();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Searches augment node in root node.
+ *
+ * @param node root node
+ * @param tempNodeId node identifier
+ * @return target augment node
+ */
+ private YangNode searchAugmentNode(YangNode node, String tempNodeId) {
+ node = node.getChild();
+ while (node != null) {
+ if (node instanceof YangAugment) {
+ if (((YangAugment) node).getName().equals(tempNodeId)) {
+ return node;
+ }
+ }
+ node = node.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
+ * Validates for target node if target node found or not.
+ *
+ * @param tempNode temporary node
+ * @param index current index of list
+ * @return false if target node found
+ */
+ private boolean validate(YangNode tempNode, int index) {
+
+ int size = getAbsPaths().size();
+ if (tempNode != null && index != size) {
+ return true;
+ } else if (tempNode != null && index == size) {
+ return false;
+ // this is your target node.
+ } else if (tempNode == null && index != size) {
+ return false;
+ // this could be in submodule as well.
+ }
+ return false;
+ }
+
+ /**
+ * Searches target node in root node.
+ *
+ * @param node root node
+ * @param curNodeId YANG node identifier
+ * @return linked target node
+ */
+ private YangNode searchTargetNode(YangNode node, YangNodeIdentifier curNodeId) {
+
+ if (node != null) {
+ node = node.getChild();
+ }
+
+ while (node != null) {
+ if (node.getName().equals(curNodeId.getName())) {
+ return node;
+ }
+ node = node.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
+ * Handles linking when uses node is present.
+ *
+ * @param node uses node
+ * @param curNodeId current node id
+ * @return linked node
+ */
+ private YangNode handleUsesNode(YangNode node, YangNodeIdentifier curNodeId) {
+ YangNode tempNode = null;
+ tempNode = searchInUsesNode((YangUses) node, curNodeId);
+ if (tempNode != null) {
+ return tempNode;
+ }
+ return null;
+ }
+
+ /**
+ * Searches target node in uses resolved list.
+ *
+ * @param uses uses node
+ * @param curNodeId current node id
+ * @return linked target node
+ */
+ private YangNode searchInUsesNode(YangUses uses, YangNodeIdentifier curNodeId) {
+
+ List<YangNode> resolvedNodes = uses.getUsesResolvedNodeList();
+ for (YangNode node : resolvedNodes) {
+ if (node.getName().equals(curNodeId.getName())) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns root prefix.
+ *
+ * @param root root node
+ * @return root prefix
+ */
+ private String getRootsPrefix(YangNode root) {
+ if (root instanceof YangModule) {
+ return ((YangModule) root).getPrefix();
+ } else {
+ return ((YangSubModule) root).getPrefix();
+ }
+ }
+
+}