[ONOS-4650][ONOS-4726][ONOS-4727] [ONOS-4728]Implement must parser + when parser + feature + if-feature + revision defect fix
Change-Id: I0a3aee6c1c6b72ef7da7f7f565fd0f149fe3fd42
diff --git a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangEntityToResolveInfoImpl.java b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangEntityToResolveInfoImpl.java
index 6b6be58..17285f6 100644
--- a/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangEntityToResolveInfoImpl.java
+++ b/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangEntityToResolveInfoImpl.java
@@ -18,6 +18,7 @@
import java.io.Serializable;
import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
+import org.onosproject.yangutils.datamodel.YangIfFeature;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangType;
import org.onosproject.yangutils.datamodel.YangUses;
@@ -76,6 +77,8 @@
prefix = ((YangType<?>) entityToBeResolved).getPrefix();
} else if (entityToBeResolved instanceof YangUses) {
prefix = ((YangUses) entityToBeResolved).getPrefix();
+ } else if (entityToBeResolved instanceof YangIfFeature) {
+ prefix = ((YangIfFeature) entityToBeResolved).getPrefix();
} else {
throw new LinkerException("Linker Exception: Entity to resolved is other than type/uses");
}
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 96e1bcc..dc321bd 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
@@ -156,6 +156,8 @@
throws LinkerException {
for (YangNode yangNode : yangNodeSet) {
try {
+ ((YangReferenceResolver) yangNode)
+ .resolveInterFileLinking(ResolvableType.YANG_IF_FEATURE);
((YangReferenceResolver) yangNode).resolveInterFileLinking(ResolvableType.YANG_USES);
((YangReferenceResolver) yangNode)
.resolveInterFileLinking(ResolvableType.YANG_DERIVED_DATA_TYPE);
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 2a710dc..0b5a464 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
@@ -17,15 +17,22 @@
package org.onosproject.yangutils.linker.impl;
import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
import java.util.Stack;
import org.onosproject.yangutils.datamodel.Resolvable;
import org.onosproject.yangutils.datamodel.YangDataTypes;
import org.onosproject.yangutils.datamodel.YangDerivedInfo;
+import org.onosproject.yangutils.datamodel.YangEntityToResolveInfo;
+import org.onosproject.yangutils.datamodel.YangFeature;
+import org.onosproject.yangutils.datamodel.YangFeatureHolder;
import org.onosproject.yangutils.datamodel.YangGrouping;
+import org.onosproject.yangutils.datamodel.YangIfFeature;
import org.onosproject.yangutils.datamodel.YangImport;
import org.onosproject.yangutils.datamodel.YangInclude;
import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
import org.onosproject.yangutils.datamodel.YangReferenceResolver;
import org.onosproject.yangutils.datamodel.YangResolutionInfo;
import org.onosproject.yangutils.datamodel.YangType;
@@ -39,9 +46,11 @@
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.INTRA_FILE_RESOLVED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.LINKED;
import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.RESOLVED;
+import static org.onosproject.yangutils.datamodel.utils.ResolvableStatus.UNDEFINED;
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.utils.UtilConstants.FEATURE_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.TYPEDEF_LINKER_ERROR;
@@ -64,7 +73,7 @@
/**
* Error line number.
*/
- private transient int lineNumber;
+ private transient int lineNumber;
/**
* Error character position in number.
@@ -115,7 +124,7 @@
setCurReferenceResolver(dataModelRootNode);
- // Current node to resolve, it can be a YANG type or YANG uses.
+ // Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature.
T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
// Check if linking is already done
@@ -128,7 +137,8 @@
return;
}
} else {
- throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
+ throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
+ "type/uses/if-feature");
}
// Push the initial entity to resolve in stack.
@@ -154,57 +164,60 @@
Resolvable resolvable = (Resolvable) entityToResolve;
switch (resolvable.getResolvableStatus()) {
- case RESOLVED: {
- /*
- * If the entity is already resolved in the stack, then pop
- * it and continue with the remaining stack elements to
- * resolve
- */
- getPartialResolvedStack().pop();
- break;
- }
-
- case LINKED: {
- /*
- * If the top of the stack is already linked then resolve
- * the references and pop the entity and continue with
- * remaining stack elements to resolve.
- */
- resolveTopOfStack(INTRA_FILE);
- getPartialResolvedStack().pop();
- break;
- }
-
- case INTRA_FILE_RESOLVED: {
- /*
- * Pop the top of the stack.
- */
- getPartialResolvedStack().pop();
- break;
- }
-
- case UNRESOLVED: {
- linkTopOfStackReferenceUpdateStack();
-
- if (resolvable.getResolvableStatus() == UNRESOLVED) {
- // If current entity is still not resolved, then
- // linking/resolution has failed.
- String errorInfo;
- if (resolvable instanceof YangType) {
- errorInfo = TYPEDEF_LINKER_ERROR;
- } else {
- errorInfo = GROUPING_LINKER_ERROR;
- }
- DataModelException dataModelException = new DataModelException(errorInfo);
- dataModelException.setLine(getLineNumber());
- dataModelException.setCharPosition(getCharPosition());
- throw dataModelException;
+ case RESOLVED: {
+ /*
+ * If the entity is already resolved in the stack, then pop
+ * it and continue with the remaining stack elements to
+ * resolve
+ */
+ getPartialResolvedStack().pop();
+ break;
}
- break;
- }
- default: {
- throw new DataModelException("Data Model Exception: Unsupported, linker state");
- }
+
+ case LINKED: {
+ /*
+ * If the top of the stack is already linked then resolve
+ * the references and pop the entity and continue with
+ * remaining stack elements to resolve.
+ */
+ resolveTopOfStack(INTRA_FILE);
+ getPartialResolvedStack().pop();
+ break;
+ }
+
+ case INTRA_FILE_RESOLVED: {
+ /*
+ * Pop the top of the stack.
+ */
+ getPartialResolvedStack().pop();
+ break;
+ }
+
+ case UNRESOLVED: {
+ linkTopOfStackReferenceUpdateStack();
+
+ if (resolvable.getResolvableStatus() == UNRESOLVED) {
+ // If current entity is still not resolved, then
+ // linking/resolution has failed.
+ String errorInfo;
+ if (resolvable instanceof YangType) {
+ errorInfo = TYPEDEF_LINKER_ERROR;
+ } else if (resolvable instanceof YangUses) {
+ errorInfo = GROUPING_LINKER_ERROR;
+ } else {
+ errorInfo = FEATURE_LINKER_ERROR;
+ }
+ DataModelException dataModelException =
+ new DataModelException(errorInfo);
+ dataModelException.setLine(getLineNumber());
+ dataModelException.setCharPosition(getCharPosition());
+ throw dataModelException;
+ }
+ break;
+ }
+ default: {
+ throw new DataModelException("Data Model Exception: Unsupported, linker state");
+ }
}
@@ -222,8 +235,9 @@
private void resolveTopOfStack(YangLinkingPhase linkingPhase)
throws DataModelException {
((Resolvable) getCurrentEntityToResolveFromStack()).resolve();
- if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != INTRA_FILE_RESOLVED) {
- // Sets the resolution status in inside the type/uses.
+ if (((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != INTRA_FILE_RESOLVED
+ && ((Resolvable) getCurrentEntityToResolveFromStack()).getResolvableStatus() != UNDEFINED) {
+ // Sets the resolution status in inside the type/uses/if-feature.
((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(RESOLVED);
}
}
@@ -253,21 +267,27 @@
YangNode potentialAncestorWithReferredNode = getPartialResolvedStack().peek()
.getHolderOfEntityToResolve();
- /**
- * Traverse up in the ancestor tree to check if the referred node is
- * defined
- */
- while (potentialAncestorWithReferredNode != null) {
+ if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ resolveSelfFileLinkingForIfFeature(potentialAncestorWithReferredNode);
+ return;
+ } else {
/**
- * Check for the referred node defined in a ancestor scope
+ * Traverse up in the ancestor tree to check if the referred node is
+ * defined
*/
- YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
- if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
- return;
- }
+ while (potentialAncestorWithReferredNode != null) {
- potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
+ /**
+ * Check for the referred node defined in a ancestor scope
+ */
+ YangNode potentialReferredNode = potentialAncestorWithReferredNode.getChild();
+ if (isReferredNodeInSiblingListProcessed(potentialReferredNode)) {
+ return;
+ }
+
+ potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
+ }
}
/*
@@ -280,6 +300,56 @@
}
/**
+ * Resolves self file linking for if-feature.
+ *
+ * @param potentialAncestorWithReferredNode if-feature holder node
+ * @throws DataModelException DataModelException a violation of data model
+ * rules
+ */
+ private void resolveSelfFileLinkingForIfFeature(YangNode potentialAncestorWithReferredNode)
+ throws DataModelException {
+
+ YangFeatureHolder featureHolder = getFeatureHolder(potentialAncestorWithReferredNode);
+ YangNode potentialReferredNode = (YangNode) featureHolder;
+ if (isReferredNode(potentialReferredNode)) {
+
+ // Adds reference link of entity to the node under resolution.
+ addReferredEntityLink(potentialReferredNode, LINKED);
+
+ /**
+ * resolve the reference and update the partial resolution stack
+ * with any further recursive references
+ */
+ addUnresolvedRecursiveReferenceToStack(potentialReferredNode);
+ return;
+ }
+
+ /*
+ * In case prefix is not present it's a candidate for inter-file
+ * resolution via include list.
+ */
+ if (getRefPrefix() == null) {
+ ((Resolvable) getCurrentEntityToResolveFromStack()).setResolvableStatus(INTRA_FILE_RESOLVED);
+ }
+ }
+
+
+ /**
+ * Returns feature holder(module/sub-module node) .
+ *
+ * @param potentialAncestorWithReferredNode if-feature holder node
+ */
+ private YangFeatureHolder getFeatureHolder(YangNode potentialAncestorWithReferredNode) {
+ while (potentialAncestorWithReferredNode != null) {
+ if (potentialAncestorWithReferredNode instanceof YangFeatureHolder) {
+ return (YangFeatureHolder) potentialAncestorWithReferredNode;
+ }
+ potentialAncestorWithReferredNode = potentialAncestorWithReferredNode.getParent();
+ }
+ return null;
+ }
+
+ /**
* Checks if the reference in self file or in external file.
*
* @return true if self file reference, false otherwise
@@ -352,6 +422,14 @@
*/
return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
}
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ if (potentialReferredNode instanceof YangFeatureHolder) {
+ /*
+ * Check if name of node name matches with the entity being
+ * resolved
+ */
+ return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
+ }
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
}
@@ -381,12 +459,31 @@
((YangUses) getCurrentEntityToResolveFromStack()).getName())) {
return true;
}
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ return isFeatureDefinedInNode(node);
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
}
return false;
}
+ private boolean isFeatureDefinedInNode(YangNode node) throws DataModelException {
+ YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
+ List<YangFeature> featureList = ((YangFeatureHolder) node).getFeatureList();
+ if (featureList != null && !featureList.isEmpty()) {
+ Iterator<YangFeature> iterator = featureList.iterator();
+ while (iterator.hasNext()) {
+ YangFeature feature = iterator.next();
+ if (ifFeature.getName().equals(feature.getName())) {
+ ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
+ ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeatureHolder(node);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
/**
* Adds reference of grouping/typedef in uses/type.
*
@@ -403,6 +500,8 @@
} else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
((YangUses) getCurrentEntityToResolveFromStack())
.setRefGroup((YangGrouping) referredNode);
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ // do nothing , referred node is already set
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
}
@@ -440,6 +539,8 @@
* return true, else return false.
*/
addUnResolvedUsesToStack(referredNode);
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ addUnResolvedIfFeatureToStack(referredNode);
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
}
@@ -469,6 +570,26 @@
}
/**
+ * Returns if there is any unresolved if-feature in feature.
+ *
+ * @param node module/submodule node
+ */
+ private void addUnResolvedIfFeatureToStack(YangNode node) {
+ YangFeature refFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeature();
+ List<YangIfFeature> ifFeatureList = refFeature.getIfFeatureList();
+ if (ifFeatureList != null && !ifFeatureList.isEmpty()) {
+ Iterator<YangIfFeature> ifFeatureIterator = ifFeatureList.iterator();
+ while (ifFeatureIterator.hasNext()) {
+ YangIfFeature ifFeature = ifFeatureIterator.next();
+ YangEntityToResolveInfo<YangIfFeature> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
+ unResolvedEntityInfo.setEntityToResolve(ifFeature);
+ unResolvedEntityInfo.setHolderOfEntityToResolve(node);
+ addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
+ }
+ }
+ }
+
+ /**
* Returns stack of YANG type with partially resolved YANG construct
* hierarchy.
*
@@ -600,6 +721,8 @@
refPrefix = ((YangType<?>) getCurrentEntityToResolveFromStack()).getPrefix();
} else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
refPrefix = ((YangUses) getCurrentEntityToResolveFromStack()).getPrefix();
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ refPrefix = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getPrefix();
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
}
@@ -623,41 +746,50 @@
Resolvable resolvable = (Resolvable) entityToResolve;
switch (resolvable.getResolvableStatus()) {
- case RESOLVED: {
- /*
- * If the entity is already resolved in the stack, then pop
- * it and continue with the remaining stack elements to
- * resolve
- */
- getPartialResolvedStack().pop();
- break;
- }
+ case RESOLVED: {
+ /*
+ * If the entity is already resolved in the stack, then pop
+ * it and continue with the remaining stack elements to
+ * resolve
+ */
+ getPartialResolvedStack().pop();
+ break;
+ }
- case INTER_FILE_LINKED: {
- /*
- * If the top of the stack is already linked then resolve
- * the references and pop the entity and continue with
- * remaining stack elements to resolve
- */
- resolveTopOfStack(INTER_FILE);
- getPartialResolvedStack().pop();
- break;
- }
+ case INTER_FILE_LINKED: {
+ /*
+ * If the top of the stack is already linked then resolve
+ * the references and pop the entity and continue with
+ * remaining stack elements to resolve
+ */
+ resolveTopOfStack(INTER_FILE);
+ getPartialResolvedStack().pop();
+ break;
+ }
- case INTRA_FILE_RESOLVED: {
- /*
- * If the top of the stack is intra file resolved then check
- * if top of stack is linked, if not link it using
- * import/include list and push the linked referred entity
- * to the stack, otherwise only push it to the stack.
- */
- linkInterFileTopOfStackRefUpdateStack();
- break;
- }
+ case INTRA_FILE_RESOLVED: {
+ /*
+ * If the top of the stack is intra file resolved then check
+ * if top of stack is linked, if not link it using
+ * import/include list and push the linked referred entity
+ * to the stack, otherwise only push it to the stack.
+ */
+ linkInterFileTopOfStackRefUpdateStack();
+ break;
+ }
- default: {
- throw new DataModelException("Data Model Exception: Unsupported, linker state");
- }
+ case UNDEFINED: {
+ /*
+ * In case of if-feature resolution, if referred "feature" is not
+ * defined then the resolvable status will be undefined.
+ */
+ getPartialResolvedStack().pop();
+ break;
+ }
+
+ default: {
+ throw new DataModelException("Data Model Exception: Unsupported, linker state");
+ }
}
@@ -701,6 +833,11 @@
return;
}
}
+
+ if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ ((YangIfFeature) getCurrentEntityToResolveFromStack()).setResolvableStatus(UNDEFINED);
+ return;
+ }
// Exception when referred typedef/grouping is not found.
DataModelException dataModelException = new DataModelException("YANG file error: Referred " +
"typedef/grouping for a given type/uses can't be found.");
@@ -735,6 +872,8 @@
linkedNode = findRefTypedef(yangInclude.getIncludedNode());
} else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
linkedNode = findRefGrouping(yangInclude.getIncludedNode());
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ linkedNode = findRefFeature(yangInclude.getIncludedNode());
}
if (linkedNode != null) {
// Add the link to external entity.
@@ -776,6 +915,8 @@
linkedNode = findRefTypedef(yangImport.getImportedNode());
} else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
linkedNode = findRefGrouping(yangImport.getImportedNode());
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ linkedNode = findRefFeature(yangImport.getImportedNode());
}
if (linkedNode != null) {
// Add the link to external entity.
@@ -816,6 +957,8 @@
return (T) derivedInfo.getReferredTypeDef();
} else if (getCurrentEntityToResolveFromStack() instanceof YangUses) {
return (T) ((YangUses) getCurrentEntityToResolveFromStack()).getRefGroup();
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
+ return (T) ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeatureHolder();
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
}
@@ -842,6 +985,29 @@
}
/**
+ * Finds the referred feature node at the root level of imported/included node.
+ *
+ * @param refNode module/sub-module node
+ * @return referred feature
+ */
+ private YangNode findRefFeature(YangNode refNode) {
+ YangNodeIdentifier ifFeature = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getName();
+ List<YangFeature> featureList = ((YangFeatureHolder) refNode).getFeatureList();
+
+ if (featureList != null && !featureList.isEmpty()) {
+ Iterator<YangFeature> iterator = featureList.iterator();
+ while (iterator.hasNext()) {
+ YangFeature feature = iterator.next();
+ if (ifFeature.getName().equals(feature.getName())) {
+ ((YangIfFeature) getCurrentEntityToResolveFromStack()).setReferredFeature(feature);
+ return refNode;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
* Finds the referred typedef node at the root level of imported/included node.
*
* @param refNode module/sub-module node