[ONOS-4753] Identity/identityref implementation and UT
Change-Id: I40148fa228465555be3bdf410cc294ffc0f34c18
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
index b70d44c..eb42233 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
@@ -24,12 +24,15 @@
import org.onosproject.yangutils.datamodel.Resolvable;
import org.onosproject.yangutils.datamodel.ResolvableType;
import org.onosproject.yangutils.datamodel.YangAtomicPath;
+import org.onosproject.yangutils.datamodel.YangBase;
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.YangIdentity;
+import org.onosproject.yangutils.datamodel.YangIdentityRef;
import org.onosproject.yangutils.datamodel.YangImport;
import org.onosproject.yangutils.datamodel.YangInclude;
import org.onosproject.yangutils.datamodel.YangInput;
@@ -69,9 +72,12 @@
import static org.onosproject.yangutils.utils.UtilConstants.GROUPING_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.INPUT;
import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF;
+import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF;
import static org.onosproject.yangutils.utils.UtilConstants.LEAFREF_LINKER_ERROR;
import static org.onosproject.yangutils.utils.UtilConstants.OUTPUT;
import static org.onosproject.yangutils.utils.UtilConstants.TYPEDEF_LINKER_ERROR;
+import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF_LINKER_ERROR;
+import static org.onosproject.yangutils.utils.UtilConstants.BASE_LINKER_ERROR;
/**
* Represents implementation of resolution object which will be resolved by
@@ -143,7 +149,10 @@
setCurReferenceResolver(dataModelRootNode);
- // Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature or YANG leafref.
+ /**
+ * Current node to resolve, it can be a YANG type, YANG uses or YANG if-feature or
+ * YANG leafref or YANG base or YANG identityref.
+ */
T entityToResolve = getEntityToResolveInfo().getEntityToResolve();
// Check if linking is already done
@@ -157,7 +166,7 @@
}
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than " +
- "type/uses/if-feature/leafref");
+ "type/uses/if-feature/leafref/base/identityref");
}
// Push the initial entity to resolve in stack.
@@ -178,7 +187,10 @@
while (getPartialResolvedStack().size() != 0) {
- // Current node to resolve, it can be a YANG type or YANG uses.
+ /**
+ * Current node to resolve, it can be a YANG type or YANG uses or
+ * YANG if-feature or YANG leafref or YANG base or YANG identityref.
+ */
T entityToResolve = getCurrentEntityToResolveFromStack();
// Check if linking is already done
if (entityToResolve instanceof Resolvable) {
@@ -227,6 +239,10 @@
errorInfo = GROUPING_LINKER_ERROR;
} else if (resolvable instanceof YangIfFeature) {
errorInfo = FEATURE_LINKER_ERROR;
+ } else if (resolvable instanceof YangBase) {
+ errorInfo = BASE_LINKER_ERROR;
+ } else if (resolvable instanceof YangIdentityRef) {
+ errorInfo = IDENTITYREF_LINKER_ERROR;
} else {
errorInfo = LEAFREF_LINKER_ERROR;
}
@@ -246,14 +262,16 @@
} else {
throw new DataModelException(
- "Data Model Exception: Entity to resolved is other than type/uses/if-feature/leafref");
+ "Data Model Exception: Entity to resolved is other than type/uses/if-feature" +
+ "/leafref/base/identityref");
}
}
}
/**
- * Adds the leafref type to the type, which has derived type referring to typedef with leafref type.
+ * Adds the leafref/identityref type to the type, which has derived type referring to
+ * typedef with leafref/identityref type.
*/
private void addDerivedRefTypeToRefTypeResolutionList() throws DataModelException {
@@ -279,9 +297,10 @@
YangDerivedInfo derivedInfo = (YangDerivedInfo) yangType.getDataTypeExtendedInfo();
/*
- * If the derived types referred type is not leaf ref return
+ * If the derived types referred type is not leafref/identityref return
*/
- if (derivedInfo.getEffectiveBuiltInType() != YangDataTypes.LEAFREF) {
+ if ((derivedInfo.getEffectiveBuiltInType() != YangDataTypes.LEAFREF) &&
+ (derivedInfo.getEffectiveBuiltInType() != YangDataTypes.IDENTITYREF)) {
return;
}
@@ -292,28 +311,49 @@
extendedInfo = (T) derivedInfoFromTypedef.getReferredTypeDef().getTypeDefBaseType()
.getDataTypeExtendedInfo();
}
+
/*
- * Backup the derived types leaf ref info, delete all the info in
- * current type, but for resolution status as resolved. Copy the backed
- * up leaf ref to types extended info, create a leaf ref resolution info
- * using the current resolution info and add to leaf ref resolution
- * list.
+ * Backup the derived types leafref/identityref info, delete all the info in current type,
+ * but for resolution status as resolved. Copy the backed up leafref/identityref to types extended info,
+ * create a leafref/identityref resolution info using the current resolution info and
+ * add to leafref/identityref resolution list.
*/
- YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
- yangType.resetYangType();
+ if (derivedInfo.getEffectiveBuiltInType() == YangDataTypes.LEAFREF) {
+ YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
+ yangType.resetYangType();
- yangType.setResolvableStatus(RESOLVED);
- yangType.setDataType(YangDataTypes.LEAFREF);
- yangType.setDataTypeName(LEAFREF);
- yangType.setDataTypeExtendedInfo(leafRefInTypeDef);
- leafRefInTypeDef.setResolvableStatus(UNRESOLVED);
+ yangType.setResolvableStatus(RESOLVED);
+ yangType.setDataType(YangDataTypes.LEAFREF);
+ yangType.setDataTypeName(LEAFREF);
+ yangType.setDataTypeExtendedInfo(leafRefInTypeDef);
+ leafRefInTypeDef.setResolvableStatus(UNRESOLVED);
- // Add resolution information to the list.
- YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(leafRefInTypeDef,
- potentialAncestorWithReferredNode, getLineNumber(), getCharPosition());
- getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
- ResolvableType.YANG_LEAFREF);
- getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_LEAFREF);
+ // Add resolution information to the list.
+ YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(leafRefInTypeDef,
+ potentialAncestorWithReferredNode,
+ getLineNumber(), getCharPosition());
+ getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
+ ResolvableType.YANG_LEAFREF);
+ getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_LEAFREF);
+
+ } else if (derivedInfo.getEffectiveBuiltInType() == YangDataTypes.IDENTITYREF) {
+
+ YangIdentityRef identityRefInTypeDef = (YangIdentityRef) extendedInfo;
+ yangType.resetYangType();
+
+ yangType.setResolvableStatus(RESOLVED);
+ yangType.setDataType(YangDataTypes.IDENTITYREF);
+ yangType.setDataTypeName(IDENTITYREF);
+ yangType.setDataTypeExtendedInfo(identityRefInTypeDef);
+ identityRefInTypeDef.setResolvableStatus(UNRESOLVED);
+
+ // Add resolution information to the list.
+ YangResolutionInfoImpl resolutionInfoImpl = new YangResolutionInfoImpl<>(identityRefInTypeDef,
+ potentialAncestorWithReferredNode, getLineNumber(), getCharPosition());
+ getCurReferenceResolver().addToResolutionList(resolutionInfoImpl,
+ ResolvableType.YANG_IDENTITYREF);
+ getCurReferenceResolver().resolveSelfFileLinking(ResolvableType.YANG_IDENTITYREF);
+ }
}
/**
@@ -360,6 +400,10 @@
} else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
resolveSelfFileLinkingForLeafref(potentialAncestorWithReferredNode);
return;
+ } else if ((getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) ||
+ (getCurrentEntityToResolveFromStack() instanceof YangBase)) {
+ resolveSelfFileLinkingForBaseAndIdentityref();
+ return;
} else {
/**
@@ -453,6 +497,47 @@
}
/**
+ * Resolves self file linking for base/identityref.
+ *
+ * @throws DataModelException a violation of data model rules
+ */
+ private void resolveSelfFileLinkingForBaseAndIdentityref()
+ throws DataModelException {
+
+ boolean referredIdentityFound = false;
+ String nodeName = null;
+
+ if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ nodeName = ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getName();
+ }
+
+ if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ nodeName = ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName();
+ }
+
+ if (getCurReferenceResolver() instanceof YangModule) {
+ YangModule rootNode = (YangModule) getCurReferenceResolver();
+ // Sends list of nodes for finding the target identity.
+ referredIdentityFound = isIdentityReferenceFound(nodeName, rootNode);
+ } else if (getCurReferenceResolver() instanceof YangSubModule) {
+ YangSubModule rootNode = (YangSubModule) getCurReferenceResolver();
+ // Sends list of nodes for finding the target identity.
+ referredIdentityFound = isIdentityReferenceFound(nodeName, rootNode);
+ }
+
+ if (referredIdentityFound) {
+ 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 the root parent with respect to the ancestor count from leafref.
*
* @param ancestorCount count of node where parent node can be reached
@@ -561,6 +646,41 @@
}
/**
+ * Returns the status of the referred identity found for base/identityref.
+ *
+ * @param nodeName the name of the base nodeidentifier/identityref nodeidentifier
+ * @param ancestorWithTheReferredNode the parent node of base/identityref
+ * @return status of referred base/identityref
+ * @throws DataModelException a violation of data model rules
+ */
+ private boolean isIdentityReferenceFound(String nodeName, YangNode ancestorWithTheReferredNode)
+ throws DataModelException {
+
+ // When child is not present return.
+ if (ancestorWithTheReferredNode.getChild() == null) {
+ return false;
+ }
+
+ ancestorWithTheReferredNode = ancestorWithTheReferredNode.getChild();
+
+ // Checks all the siblings under the node and returns the matched node.
+ YangNode nodeFound = isReferredNodeInSiblingProcessedForIdentity(ancestorWithTheReferredNode, nodeName);
+
+ if (nodeFound != null) {
+ // Adds reference link of entity to the node under resolution.
+ addReferredEntityLink(nodeFound, LINKED);
+
+ /**
+ * resolve the reference and update the partial resolution stack with any further recursive references
+ */
+ addUnresolvedRecursiveReferenceToStack(nodeFound);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
* Fills the referred leaf or leaf-list inside the path predicates.
*
* @param ancestorWithTheReferredNode the actual node where YANG list will be present
@@ -856,6 +976,28 @@
}
/**
+ * Checks for the referred parent node for the base/identity.
+ *
+ * @param potentialReferredNode potential referred node
+ * @return the reffered parent node of base/identity.
+ * @throws DataModelException data model errors
+ */
+ private YangNode isReferredNodeInSiblingProcessedForIdentity(YangNode potentialReferredNode,
+ String referredNodeName) throws DataModelException {
+
+ while (potentialReferredNode != null) {
+ if (potentialReferredNode instanceof YangIdentity) {
+ // Check if the potential referred node is the actual referred node
+ if (isReferredNodeForIdentity(potentialReferredNode, referredNodeName)) {
+ return potentialReferredNode;
+ }
+ }
+ potentialReferredNode = potentialReferredNode.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
* Checks if the current reference node name and the name in the path are equal.
*
* @param currentReferredNode the node where the reference is pointed
@@ -878,6 +1020,28 @@
}
/**
+ * Checks if the current reference node name and the name in the base/identityref base are equal.
+ *
+ * @param currentReferredNode the node where the reference is pointed
+ * @param nameOfIdentityRefBase name of the base in the base/identityref base
+ * @return status of the match between the name
+ * @throws DataModelException a violation of data model rules
+ */
+ private boolean isReferredNodeForIdentity(YangNode currentReferredNode, String nameOfIdentityRefBase)
+ throws DataModelException {
+
+ if ((getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) ||
+ (getCurrentEntityToResolveFromStack() instanceof YangBase)) {
+ /*
+ * Check if name of node name matches with the current reference node.
+ */
+ return currentReferredNode.getName().contentEquals(nameOfIdentityRefBase);
+ } else {
+ throw new DataModelException("Data Model Exception: Entity to resolved is other than identityref");
+ }
+ }
+
+ /**
* Checks for the referred node defined in a ancestor scope.
*
* @param potentialReferredNode potential referred node
@@ -946,8 +1110,18 @@
*/
return isNodeNameSameAsResolutionInfoName(potentialReferredNode);
}
+ } else if ((getCurrentEntityToResolveFromStack() instanceof YangBase) ||
+ (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef)) {
+ if (potentialReferredNode instanceof YangIdentity) {
+ /*
+ * 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");
+ throw new DataModelException("Data Model Exception: Entity to resolved is other than type/" +
+ "uses/base/identityref");
}
return false;
}
@@ -977,6 +1151,16 @@
}
} else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
return isFeatureDefinedInNode(node);
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ if (node.getName().contentEquals(
+ ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName())) {
+ return true;
+ }
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ if (node.getName().contentEquals(
+ ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getName())) {
+ return true;
+ }
} else {
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
}
@@ -1020,8 +1204,13 @@
// do nothing , referred node is already set
} else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
// do nothing , referred node is already set
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ ((YangBase) getCurrentEntityToResolveFromStack()).setReferredIdentity((YangIdentity) referredNode);
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ ((YangIdentityRef) getCurrentEntityToResolveFromStack()).setReferredIdentity((YangIdentity) referredNode);
} 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/base/identityref");
}
// Sets the resolution status in inside the type/uses.
@@ -1062,6 +1251,15 @@
} else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
// do nothing , referred node is already set
throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses");
+ } else if ((getCurrentEntityToResolveFromStack() instanceof YangBase) ||
+ (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef)) {
+ /*
+ * Search if the identity has any un resolved base, if so return true, else return false.
+ */
+ addUnResolvedBaseToStack(referredNode);
+ } else {
+ throw new DataModelException("Data Model Exception: Entity to resolved is other than type/uses/" +
+ "base/identityref");
}
}
@@ -1109,6 +1307,26 @@
}
/**
+ * Returns if there is any unresolved base in identity.
+ *
+ * @param node module/submodule node
+ */
+ private void addUnResolvedBaseToStack(YangNode node) {
+
+ YangIdentity curNode = (YangIdentity) node;
+ if (curNode.getBaseNode() != null) {
+ if (curNode.getBaseNode().getResolvableStatus() != RESOLVED) {
+ YangEntityToResolveInfoImpl<YangBase> unResolvedEntityInfo = new YangEntityToResolveInfoImpl<>();
+ unResolvedEntityInfo.setEntityToResolve(curNode.getBaseNode());
+ unResolvedEntityInfo.setHolderOfEntityToResolve(node);
+ addInPartialResolvedStack((YangEntityToResolveInfoImpl<T>) unResolvedEntityInfo);
+
+ }
+ }
+ }
+
+
+ /**
* Returns stack of YANG type with partially resolved YANG construct
* hierarchy.
*
@@ -1247,8 +1465,13 @@
refPrefix = ((YangIfFeature) getCurrentEntityToResolveFromStack()).getPrefix();
} else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
refPrefix = refPrefixForLeafRef();
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ refPrefix = ((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getPrefix();
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ refPrefix = ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getPrefix();
} 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/base/identityref");
}
return refPrefix;
}
@@ -1392,6 +1615,10 @@
errorInfo = GROUPING_LINKER_ERROR;
} else if (getCurrentEntityToResolveFromStack() instanceof YangIfFeature) {
errorInfo = FEATURE_LINKER_ERROR;
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ errorInfo = BASE_LINKER_ERROR;
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ errorInfo = IDENTITYREF_LINKER_ERROR;
} else {
errorInfo = LEAFREF_LINKER_ERROR;
}
@@ -1449,7 +1676,12 @@
setCurReferenceResolver((YangReferenceResolver) yangInclude.getIncludedNode());
return referredNode;
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ linkedNode = findRefIdentity(yangInclude.getIncludedNode());
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ linkedNode = findRefIdentityRef(yangInclude.getIncludedNode());
}
+
if (linkedNode != null) {
// Add the link to external entity.
addReferredEntityLink(linkedNode, INTER_FILE_LINKED);
@@ -1502,6 +1734,10 @@
setCurReferenceResolver((YangReferenceResolver) yangImport.getImportedNode());
return referredNode;
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ linkedNode = findRefIdentity(yangImport.getImportedNode());
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ linkedNode = findRefIdentityRef(yangImport.getImportedNode());
}
if (linkedNode != null) {
// Add the link to external entity.
@@ -1584,8 +1820,13 @@
return (T) ((YangIfFeature) getCurrentEntityToResolveFromStack()).getReferredFeatureHolder();
} else if (getCurrentEntityToResolveFromStack() instanceof YangLeafRef) {
return (T) ((YangLeafRef) getCurrentEntityToResolveFromStack()).getReferredLeafOrLeafList();
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangBase) {
+ return (T) ((YangBase) getCurrentEntityToResolveFromStack()).getReferredIdentity();
+ } else if (getCurrentEntityToResolveFromStack() instanceof YangIdentityRef) {
+ return (T) ((YangIdentityRef) getCurrentEntityToResolveFromStack()).getReferredIdentity();
} 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/base/identityref");
}
}
@@ -1651,4 +1892,45 @@
}
return null;
}
+
+ /**
+ * Finds the referred identity node at the root level of imported/included node.
+ *
+ * @param refNode module/sub-module node
+ * @return referred identity
+ */
+ private YangNode findRefIdentity(YangNode refNode) {
+ YangNode tmpNode = refNode.getChild();
+ while (tmpNode != null) {
+ if (tmpNode instanceof YangIdentity) {
+ if (tmpNode.getName()
+ .equals(((YangBase) getCurrentEntityToResolveFromStack()).getBaseIdentifier().getName())) {
+ return tmpNode;
+ }
+ }
+ tmpNode = tmpNode.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
+ * Finds the referred identity node at the root level of imported/included node.
+ *
+ * @param refNode module/sub-module node
+ * @return referred identity
+ */
+ private YangNode findRefIdentityRef(YangNode refNode) {
+ YangNode tmpNode = refNode.getChild();
+ while (tmpNode != null) {
+ if (tmpNode instanceof YangIdentity) {
+ if (tmpNode.getName()
+ .equals(((YangIdentityRef) getCurrentEntityToResolveFromStack())
+ .getBaseIdentity().getName())) {
+ return tmpNode;
+ }
+ }
+ tmpNode = tmpNode.getNextSibling();
+ }
+ return null;
+ }
}