handling of unique
Change-Id: Iadd216f2c8ada19a3b3c11a670497d1a493b8237
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java
index 87603fd..de6f35c 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateAdd.java
@@ -76,9 +76,9 @@
private List<YangMust> mustConstraintList;
/**
- * List of unique leaf names.
+ * List of unique atomic path list.
*/
- private List<String> uniqueList;
+ private List<List<YangAtomicPath>> pathList;
/**
* Default value in string, needs to be converted to the target object,
@@ -107,11 +107,17 @@
private YangMinElement minElements;
/**
+ * List of unique leaves.
+ */
+ private List<YangLeaf> uniqueLeaves;
+
+ /**
* Creates a YANG deviate add object.
*/
public YangDeviateAdd() {
mustConstraintList = new LinkedList<>();
- uniqueList = new LinkedList<>();
+ pathList = new LinkedList<>();
+ uniqueLeaves = new LinkedList<>();
}
@Override
@@ -255,37 +261,52 @@
}
/**
- * Returns the list of unique field names.
+ * Adds unique path in data holder.
*
- * @return the list of unique field names
+ * @param path unique path
*/
@Override
- public List<String> getUniqueList() {
- return uniqueList;
+ public void addUnique(List<YangAtomicPath> path) {
+ pathList.add(path);
}
/**
- * Sets the list of unique field names.
+ * Sets the list of unique path.
*
- * @param uniqueList the list of unique field names
+ * @param pathList unique path list
*/
@Override
- public void setUniqueList(List<String> uniqueList) {
- this.uniqueList = uniqueList;
+ public void setPathList(List<List<YangAtomicPath>> pathList) {
+ this.pathList = pathList;
}
/**
- * Adds a unique field name.
+ * Returns the list of unique path from data holder.
*
- * @param unique unique field name
- * @throws DataModelException a violation of data model rules
+ * @return unique path list
*/
@Override
- public void addUnique(String unique) throws DataModelException {
- if (uniqueList.contains(unique)) {
- throw new DataModelException("A leaf identifier must not appear more than once in the\n" +
- " unique");
- }
- uniqueList.add(unique);
+ public List<List<YangAtomicPath>> getPathList() {
+ return pathList;
+ }
+
+ /**
+ * Returns the list of unique leaves.
+ *
+ * @return unique leaves
+ */
+ @Override
+ public List<YangLeaf> getUniqueLeaves() {
+ return uniqueLeaves;
+ }
+
+ /**
+ * Adds unique leaf to the unique leaves.
+ *
+ * @param uniqueLeaf YANG leaf
+ */
+ @Override
+ public void addUniqueLeaf(YangLeaf uniqueLeaf) {
+ uniqueLeaves.add(uniqueLeaf);
}
}
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java
index d93cd93..47a3d8a 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangDeviateDelete.java
@@ -75,9 +75,9 @@
private List<YangMust> mustConstraintList;
/**
- * List of unique leaf names.
+ * List of unique atomic path list.
*/
- private List<String> uniqueList;
+ private List<List<YangAtomicPath>> pathList;
/**
* Default value in string, needs to be converted to the target object,
@@ -86,11 +86,17 @@
private String defaultValueInString;
/**
+ * List of unique leaves.
+ */
+ private List<YangLeaf> uniqueLeaves;
+
+ /**
* Creates a YANG deviate delete object.
*/
public YangDeviateDelete() {
mustConstraintList = new LinkedList<>();
- uniqueList = new LinkedList<>();
+ pathList = new LinkedList<>();
+ uniqueLeaves = new LinkedList<>();
}
@Override
@@ -144,39 +150,31 @@
}
/**
+ * Adds a unique path to the list.
+ *
+ * @param path unique path
+ */
+ @Override
+ public void addUnique(List<YangAtomicPath> path) {
+ pathList.add(path);
+ }
+
+ /**
+ * Sets the list of unique path list.
+ *
+ * @param pathList the list of unique path list
+ */
+ public void setPathList(List<List<YangAtomicPath>> pathList) {
+ this.pathList = pathList;
+ }
+
+ /**
* Returns the list of unique field names.
*
* @return the list of unique field names
*/
- @Override
- public List<String> getUniqueList() {
- return uniqueList;
- }
-
- /**
- * Sets the list of unique field names.
- *
- * @param uniqueList the list of unique field names
- */
- @Override
- public void setUniqueList(List<String> uniqueList) {
- this.uniqueList = uniqueList;
- }
-
- /**
- * Adds a unique field name.
- *
- * @param unique unique field name
- * @throws DataModelException a violation of data model rules
- */
- @Override
- public void addUnique(String unique)
- throws DataModelException {
- if (uniqueList.contains(unique)) {
- throw new DataModelException("A leaf identifier must not appear more than once in the\n" +
- " unique");
- }
- uniqueList.add(unique);
+ public List<List<YangAtomicPath>> getPathList() {
+ return pathList;
}
/**
@@ -198,4 +196,24 @@
public void setDefaultValueInString(String defaultValueInString) {
this.defaultValueInString = defaultValueInString;
}
+
+ /**
+ * Returns the list of unique leaves.
+ *
+ * @return the list of unique leves
+ */
+ @Override
+ public List<YangLeaf> getUniqueLeaves() {
+ return uniqueLeaves;
+ }
+
+ /**
+ * Adds a unique lead to unique leaves.
+ *
+ * @param uniqueLeaf YANG leaf
+ */
+ @Override
+ public void addUniqueLeaf(YangLeaf uniqueLeaf) {
+ uniqueLeaves.add(uniqueLeaf);
+ }
}
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java
index f7e63cb..1365b7e 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangList.java
@@ -148,9 +148,12 @@
* default values, MUST be unique within all list entry instances in
* which all referenced leafs exist.
* <p>
- * List of unique leaf/leaf-list names
*/
- private List<String> uniqueList;
+
+ /**
+ * List of unique atomic path list.
+ */
+ private List<List<YangAtomicPath>> pathList;
/**
* List of leaves.
@@ -242,6 +245,11 @@
private boolean defaultDenyAll;
/**
+ * List of unique leaves.
+ */
+ private List<YangLeaf> uniqueLeaves;
+
+ /**
* Creates a YANG list object.
*/
public YangList() {
@@ -250,7 +258,8 @@
listOfLeafList = new LinkedList<>();
mustConstraintList = new LinkedList<>();
ifFeatureList = new LinkedList<>();
- uniqueList = new LinkedList<>();
+ pathList = new LinkedList<>();
+ uniqueLeaves = new LinkedList<>();
keyList = new LinkedHashSet<>();
}
@@ -354,26 +363,6 @@
}
/**
- * Returns the list of unique field names.
- *
- * @return the list of unique field names
- */
- @Override
- public List<String> getUniqueList() {
- return uniqueList;
- }
-
- /**
- * Sets the list of unique field names.
- *
- * @param uniqueList the list of unique field names
- */
- @Override
- public void setUniqueList(List<String> uniqueList) {
- this.uniqueList = uniqueList;
- }
-
- /**
* Returns the set of key field names.
*
* @return the set of key field names
@@ -421,26 +410,31 @@
}
/**
- * Adds a unique field name.
+ * Adds a unique path to the list.
*
- * @param unique unique field name.
- * @throws DataModelException a violation of data model rules
+ * @param path unique path
*/
@Override
- public void addUnique(String unique)
- throws DataModelException {
- if (getUniqueList() == null) {
- setUniqueList(new LinkedList<>());
- }
- if (getUniqueList().contains(unique)) {
- throw new DataModelException("A leaf identifier must not appear more than once in the\n" +
- " unique" +
- getName() + " in " +
- getLineNumber() + " at " +
- getCharPosition() +
- " in " + getFileName() + "\"");
- }
- getUniqueList().add(unique);
+ public void addUnique(List<YangAtomicPath> path) {
+ pathList.add(path);
+ }
+
+ /**
+ * Sets the list of unique path list.
+ *
+ * @param pathList the list of unique path list
+ */
+ public void setPathList(List<List<YangAtomicPath>> pathList) {
+ this.pathList = pathList;
+ }
+
+ /**
+ * Returns the list of unique field names.
+ *
+ * @return the list of unique field names
+ */
+ public List<List<YangAtomicPath>> getPathList() {
+ return pathList;
}
/**
@@ -464,6 +458,26 @@
}
/**
+ * Returns a list of unique leaves.
+ *
+ * @return the list of unique leaves
+ */
+ @Override
+ public List<YangLeaf> getUniqueLeaves() {
+ return uniqueLeaves;
+ }
+
+ /**
+ * Adds a unique leaf to unique leaves.
+ *
+ * @param uniqueLeaf YANG leaf
+ */
+ @Override
+ public void addUniqueLeaf(YangLeaf uniqueLeaf) {
+ uniqueLeaves.add(uniqueLeaf);
+ }
+
+ /**
* Adds a leaf.
*
* @param leaf the leaf to be added
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java
index 4509e59..9bf8b2d 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangModule.java
@@ -39,6 +39,7 @@
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.detectCollidingChildUtil;
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.linkInterFileReferences;
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.resolveLinkingForResolutionList;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.validateUniqueInList;
import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.MODULE_DATA;
/*-
@@ -271,6 +272,11 @@
private final List<YangAugment> augments;
/**
+ * List of unique identifiers List.
+ */
+ private List<YangUniqueHolder> uniqueHolderList;
+
+ /**
* YANG defined namespace.
*/
private String namespace;
@@ -310,6 +316,7 @@
listOfFeature = new LinkedList<>();
notificationEnumMap = new HashMap<>();
augments = new LinkedList<>();
+ uniqueHolderList = new LinkedList<>();
}
@Override
@@ -423,6 +430,16 @@
}
/**
+ * Adds a unique holder to a unique holder list.
+ *
+ * @param uniqueHolder
+ */
+ @Override
+ public void addToUniqueHolderList(YangUniqueHolder uniqueHolder) {
+ uniqueHolderList.add(uniqueHolder);
+ }
+
+ /**
* Returns the list of leaves in module.
*
* @return the list of leaves
@@ -657,6 +674,17 @@
}
/**
+ * Validates each yang unique holder in the unique holder list.
+ *
+ * @throws DataModelException a violation of data model rules
+ */
+ public void resolveUniqueLinking() throws DataModelException {
+ for (YangUniqueHolder holder : uniqueHolderList) {
+ validateUniqueInList(holder);
+ }
+ }
+
+ /**
* Returns the type of the parsed data.
*
* @return returns MODULE_DATA
@@ -865,6 +893,15 @@
return unmodifiableList(augments);
}
+ /**
+ * Returns a list of uniqueholders.
+ *
+ * @return unique holder list
+ */
+ public List<YangUniqueHolder> getUniqueHolderList() {
+ return uniqueHolderList;
+ }
+
@Override
public String getModuleNamespace() {
return namespace;
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java
index d47387e..0e1eee5 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangReferenceResolver.java
@@ -45,6 +45,13 @@
ResolvableType type);
/**
+ * Adds a unique holder to unique holder list.
+ *
+ * @param uniqueHolder yanguniqueholder
+ */
+ void addToUniqueHolderList(YangUniqueHolder uniqueHolder);
+
+ /**
* Creates resolution list.
*
* @param resolutionList resolution list
@@ -82,6 +89,13 @@
List<YangInclude> getIncludeList();
/**
+ * Returns list of unique holders.
+ *
+ * @return unique holder list
+ */
+ List<YangUniqueHolder> getUniqueHolderList();
+
+ /**
* Adds to the include list.
*
* @param yangInclude include to be added
@@ -128,6 +142,13 @@
throws DataModelException;
/**
+ * Resolves unique linking.
+ *
+ * @throws DataModelException a violation in data model rule
+ */
+ void resolveUniqueLinking() throws DataModelException;
+
+ /**
* Adds references to include.
*
* @param yangNodeSet YANG node info set
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java
index e960fbd..4911ed4 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangSubModule.java
@@ -40,6 +40,7 @@
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.detectCollidingChildUtil;
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.linkInterFileReferences;
import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.resolveLinkingForResolutionList;
+import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.validateUniqueInList;
import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.SUB_MODULE_DATA;
/*
@@ -270,6 +271,11 @@
private final List<YangAugment> augments;
/**
+ * List of unique identifiers List.
+ */
+ private List<YangUniqueHolder> uniqueHolderList;
+
+ /**
* YANG defined namespace.
*/
private String namespace;
@@ -313,6 +319,7 @@
listOfFeature = new LinkedList<>();
notificationEnumMap = new HashMap<>();
augments = new LinkedList<>();
+ uniqueHolderList = new LinkedList<>();
}
@Override
@@ -870,6 +877,25 @@
return unmodifiableList(augments);
}
+ /**
+ * Returns a list of unique holders.
+ *
+ * @return uniqueHolderList
+ */
+ public List<YangUniqueHolder> getUniqueHolderList() {
+ return uniqueHolderList;
+ }
+
+ /**
+ * Add a unique holder to unique holder list.
+ *
+ * @param uniqueHolder yanguniqueholder
+ */
+ @Override
+ public void addToUniqueHolderList(YangUniqueHolder uniqueHolder) {
+ uniqueHolderList.add(uniqueHolder);
+ }
+
@Override
public String getModuleNamespace() {
return namespace;
@@ -905,6 +931,18 @@
}
/**
+ * Resolve unique linking.
+ *
+ * @throws DataModelException a violation in data model rule
+ */
+ @Override
+ public void resolveUniqueLinking() throws DataModelException {
+ for (YangUniqueHolder holder : uniqueHolderList) {
+ validateUniqueInList(holder);
+ }
+ }
+
+ /**
* Returns true if rpc is present.
*
* @param rpcPresent true if rpc is present
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java
index 40fc343..0907856 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangUniqueHolder.java
@@ -16,8 +16,6 @@
package org.onosproject.yang.compiler.datamodel;
-import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
-
import java.util.List;
/**
@@ -27,24 +25,37 @@
public interface YangUniqueHolder {
/**
- * Adds unique in data holder like list.
+ * Adds unique path in data holder like list.
*
- * @param unique the unique to be added
- * @throws DataModelException if any violation of data model rules
+ * @param path unique path
*/
- void addUnique(String unique) throws DataModelException;
+ void addUnique(List<YangAtomicPath> path);
/**
- * Sets the list of unique.
+ * Sets the list of unique path.
*
- * @param uniqueList the list of unique to set
+ * @param pathList unique path list
*/
- void setUniqueList(List<String> uniqueList);
+ void setPathList(List<List<YangAtomicPath>> pathList);
/**
- * Returns the list of unique from data holder like list.
+ * Returns the list of unique path from data holder like list.
*
- * @return the list of unique
+ * @return unique path list
*/
- List<String> getUniqueList();
+ List<List<YangAtomicPath>> getPathList();
+
+ /**
+ * Returns the list of YANG leaves, unique was referring to.
+ *
+ * @return YANG leaves list
+ */
+ List<YangLeaf> getUniqueLeaves();
+
+ /**
+ * Adds the YANG leaf, unique is referring to.
+ *
+ * @param uniqueLeaf YANG leaf
+ */
+ void addUniqueLeaf(YangLeaf uniqueLeaf);
}
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
index 929b587..6b74df1 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
@@ -48,6 +48,7 @@
import org.onosproject.yang.compiler.datamodel.YangMust;
import org.onosproject.yang.compiler.datamodel.YangMustHolder;
import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
import org.onosproject.yang.compiler.datamodel.YangNotification;
import org.onosproject.yang.compiler.datamodel.YangOutput;
import org.onosproject.yang.compiler.datamodel.YangReferenceResolver;
@@ -75,9 +76,11 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
@@ -119,6 +122,12 @@
private static final String E_DATATYPE = "Data type not supported.";
public static final String E_ID = "Schema id should not be null.";
private static final String DATE_FORMAT = "yyyy-MM-dd";
+ private static final String E_INVALID_REF = "YANG file error: A leaf " +
+ "reference, in unique, does not refer to a leaf under the list";
+ private static final String E_UNIQUE = "YANG file error: Same leaf " +
+ "cannot be mentioned more than one time in the unique statement";
+ private static final String E_TARGET_NODE = "YANG file error: The target" +
+ " node in unique reference path is invalid";
/**
* Creates a new data model tree utility.
@@ -1088,8 +1097,8 @@
// delete unique statement
if (targetNode instanceof YangUniqueHolder
- && !deviateDelete.getUniqueList().isEmpty()) {
- deviateDelete.setUniqueList(new LinkedList<>());
+ && !deviateDelete.getPathList().isEmpty()) {
+ deviateDelete.setPathList(new LinkedList<>());
}
// delete units statement
@@ -1125,9 +1134,9 @@
// update unique statement
if (targetNode instanceof YangUniqueHolder
- && !deviateAdd.getUniqueList().isEmpty()) {
- Iterator<String> uniqueList = deviateAdd.getUniqueList()
- .listIterator();
+ && !deviateAdd.getPathList().isEmpty()) {
+ ListIterator<List<YangAtomicPath>> uniqueList = deviateAdd
+ .getPathList().listIterator();
while (uniqueList.hasNext()) {
((YangUniqueHolder) targetNode).addUnique(uniqueList.next());
}
@@ -1390,6 +1399,105 @@
}
/**
+ * Validates the path in unique and gets the referred leaf.
+ *
+ * @param holder holder of unique
+ * @throws DataModelException a violation of data model rules
+ */
+ public static void validateUniqueInList(YangUniqueHolder holder)
+ throws DataModelException {
+ YangLeaf leaf;
+ List<List<YangAtomicPath>> uniques = holder.getPathList();
+ if (uniques != null && !uniques.isEmpty()) {
+ for (List<YangAtomicPath> path : uniques) {
+ List<YangAtomicPath> newPath = new LinkedList<>(path);
+ YangAtomicPath pLeaf = newPath.get(newPath.size() - 1);
+ if (newPath.size() == 1) {
+ leaf = getLeaf((YangNode) holder, pLeaf);
+ } else {
+ newPath.remove(newPath.size() - 1);
+ YangNode leafHolder = getRefNode(newPath, (YangNode) holder);
+ leaf = getLeaf(leafHolder, pLeaf);
+ }
+ if (leaf == null) {
+ throw new DataModelException(E_INVALID_REF);
+ }
+ holder.addUniqueLeaf(leaf);
+ }
+ List<YangLeaf> leaves = holder.getUniqueLeaves();
+ Map<YangLeaf, Integer> map = new HashMap<YangLeaf, Integer>();
+ for (YangLeaf lf : leaves) {
+ if (map.containsKey(lf)) {
+ throw new DataModelException(E_UNIQUE);
+ }
+ map.put(lf, 0);
+ }
+ }
+ }
+
+ /**
+ * Returns the leaf from leaves holder.
+ *
+ * @param holder root node from where it starts searching
+ * @param pLeaf yang atomic path
+ * @return yang leaf from leaves holder
+ */
+ private static YangLeaf getLeaf(YangNode holder, YangAtomicPath pLeaf) {
+ YangLeavesHolder leavesHolder = (YangLeavesHolder) holder;
+ List<YangLeaf> leaves = leavesHolder.getListOfLeaf();
+ if (leaves != null && !leaves.isEmpty()) {
+ for (YangLeaf leaf : leaves) {
+ if (pLeaf.getNodeIdentifier().getName()
+ .equals(leaf.getName())) {
+ return leaf;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the last node under the unique path.
+ *
+ * @param path atomic path list
+ * @param holder root node
+ * @return last node in the list
+ * @throws DataModelException a violation of data model rules
+ */
+ private static YangNode getRefNode(List<YangAtomicPath> path, YangNode holder)
+ throws DataModelException {
+ Iterator<YangAtomicPath> nodes = path.listIterator();
+ YangNode potRefNode = null;
+ while (nodes.hasNext()) {
+ potRefNode = holder.getChild();
+ YangAtomicPath node = nodes.next();
+ potRefNode = getNode(node.getNodeIdentifier(), potRefNode);
+ if (potRefNode == null) {
+ throw new DataModelException(E_TARGET_NODE);
+ }
+ }
+ return potRefNode;
+ }
+
+ /**
+ * Returns referred node.
+ *
+ * @param nodeId node identifier
+ * @param potRefNode potential referred node
+ * @return potential referred node
+ */
+ private static YangNode getNode(YangNodeIdentifier nodeId,
+ YangNode potRefNode) {
+ while (potRefNode != null) {
+ if (potRefNode.getName().equals(nodeId.getName())) {
+ return potRefNode;
+ }
+ potRefNode = potRefNode.getNextSibling();
+ }
+ return null;
+ }
+
+ /**
* Returns date in string format.
*
* @param schemaNode schema node
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java
index 2761480..32beed1 100644
--- a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangLinkerManager.java
@@ -93,6 +93,8 @@
// Carry out inter-file linking.
processInterFileLinking(yangNodeSet);
+
+ processUniqueLinking(yangNodeSet);
}
/**
@@ -208,4 +210,40 @@
}
}
}
+
+ /**
+ * Processes unique linking, which takes place after all linking.
+ *
+ * @param nodeSet set of YANG files info
+ * @throws LinkerException a violation in linker execution
+ */
+ public void processUniqueLinking(Set<YangNode> nodeSet)
+ throws LinkerException {
+ List<YangNode> list = new LinkedList<>();
+ list.addAll(nodeSet);
+ sort(list);
+ for (YangNode yangNode : list) {
+ try {
+ YangReferenceResolver resolver =
+ ((YangReferenceResolver) yangNode);
+ resolver.resolveUniqueLinking();
+ } catch (DataModelException e) {
+ String errorInfo = "Error in file: " + yangNode.getName() +
+ " in " + yangNode.getFileName() + " at " +
+ "line: " + e.getLineNumber() + " at position: " +
+ e.getCharPositionInLine() + NEW_LINE +
+ e.getLocalizedMessage();
+ throw new LinkerException(errorInfo);
+ // TODO add file path in exception message in util manager.
+ } catch (LinkerException e) {
+ String errorInfo = "Error in file: " + yangNode.getName() +
+ " in " + yangNode.getFileName() + " at " +
+ "line: " + e.getLineNumber() + " at position: " +
+ e.getCharPositionInLine() + NEW_LINE +
+ e.getLocalizedMessage();
+ throw new LinkerException(errorInfo);
+ // TODO add file path in exception message in util manager.
+ }
+ }
+ }
}
diff --git a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java
index b7758db..633567e 100644
--- a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java
+++ b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/ListListener.java
@@ -52,8 +52,8 @@
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
+import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.addUniqueHolderToRoot;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.getValidIdentifier;
-import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.validateUniqueInList;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.getParentNodeConfig;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.validateCardinalityMaxOne;
@@ -163,33 +163,38 @@
}
/**
- * It is called when parser exits from grammar rule (list), it performs
- * validation and updates the data model tree.
+ * Processes parser exits from grammar rule (list), performing validation
+ * and update on the date model tree.
*
* @param listener listener's object
- * @param ctx context object of the grammar rule
+ * @param ctx context object
*/
public static void processListExit(TreeWalkListener listener,
ListStatementContext ctx) {
- checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.identifier().getText(), EXIT);
+ checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA,
+ ctx.identifier().getText(), EXIT);
if (listener.getParsedDataStack().peek() instanceof YangList) {
YangList yangList = (YangList) listener.getParsedDataStack().peek();
try {
yangList.validateDataOnExit();
- validateUniqueInList(yangList, ctx);
+ addUniqueHolderToRoot(yangList);
} catch (DataModelException e) {
- ParserException parserException = new ParserException(constructExtendedListenerErrorMessage(
- UNHANDLED_PARSED_DATA, LIST_DATA, ctx.identifier().getText(), EXIT, e.getMessage()));
- parserException.setLine(ctx.getStart().getLine());
- parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
- throw parserException;
+ ParserException exc = new ParserException(
+ constructExtendedListenerErrorMessage(
+ UNHANDLED_PARSED_DATA, LIST_DATA,
+ ctx.identifier().getText(), EXIT,
+ e.getMessage()));
+ exc.setLine(ctx.getStart().getLine());
+ exc.setCharPosition(ctx.getStart().getCharPositionInLine());
+ throw exc;
}
listener.getParsedDataStack().pop();
} else {
- throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, LIST_DATA,
- ctx.identifier().getText(), EXIT));
+ throw new ParserException(constructListenerErrorMessage(
+ MISSING_CURRENT_HOLDER, LIST_DATA,
+ ctx.identifier().getText(), EXIT));
}
}
diff --git a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java
index c97d272..7a89c71 100644
--- a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java
+++ b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListener.java
@@ -16,22 +16,25 @@
package org.onosproject.yang.compiler.parser.impl.listeners;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangDeviateAdd;
+import org.onosproject.yang.compiler.datamodel.YangDeviateDelete;
import org.onosproject.yang.compiler.datamodel.YangUniqueHolder;
-import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
import org.onosproject.yang.compiler.datamodel.utils.Parsable;
-import org.onosproject.yang.compiler.parser.antlrgencode.GeneratedYangParser;
+import org.onosproject.yang.compiler.parser.antlrgencode.GeneratedYangParser.UniqueStatementContext;
import org.onosproject.yang.compiler.parser.exceptions.ParserException;
import org.onosproject.yang.compiler.parser.impl.TreeWalkListener;
+import java.util.List;
+
import static org.onosproject.yang.compiler.datamodel.utils.YangConstructType.UNIQUE_DATA;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
-import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
-import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.SPACE;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.removeQuotesAndHandleConcat;
+import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerUtil.validateUniqueInList;
import static org.onosproject.yang.compiler.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
/*
@@ -46,65 +49,50 @@
*/
/**
- * Represesnts listener based call back function corresponding to the "unique" rule
- * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
+ * Represents listener based call back function corresponding to the "unique"
+ * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
*/
public final class UniqueListener {
/**
- * Creates a new unique listener.
+ * Creates unique listener.
*/
private UniqueListener() {
}
/**
- * It is called when parser receives an input matching the grammar rule
+ * Processes when parser receives an input matching the grammar rule
* (unique), perform validations and updates the data model tree.
*
* @param listener listener's object
- * @param ctx context object of the grammar rule
+ * @param ctx context object
*/
public static void processUniqueEntry(TreeWalkListener listener,
- GeneratedYangParser.UniqueStatementContext ctx) {
+ UniqueStatementContext ctx) {
// Check for stack to be non empty.
- checkStackIsNotEmpty(listener, MISSING_HOLDER, UNIQUE_DATA, ctx.unique()
- .getText(), ENTRY);
+ checkStackIsNotEmpty(listener, MISSING_HOLDER, UNIQUE_DATA,
+ ctx.unique().getText(), ENTRY);
Parsable tmpData = listener.getParsedDataStack().peek();
- if (listener.getParsedDataStack().peek() instanceof YangUniqueHolder) {
- YangUniqueHolder uniqueHolder = (YangUniqueHolder) tmpData;
- String tmpUniqueValue = removeQuotesAndHandleConcat(
- ctx.unique().getText());
+ if (!(tmpData instanceof YangUniqueHolder)) {
+ throw new ParserException(constructListenerErrorMessage(
+ INVALID_HOLDER, UNIQUE_DATA, ctx.unique().getText(),
+ ENTRY));
+ }
- if (tmpUniqueValue.contains(SPACE)) {
- String[] uniqueValues = tmpUniqueValue.split(SPACE);
- for (String uniqueValue : uniqueValues) {
- try {
- uniqueHolder.addUnique(uniqueValue);
- } catch (DataModelException e) {
- throw new ParserException(
- constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
- UNIQUE_DATA,
- ctx.unique().getText(),
- ENTRY, e.getMessage()));
- }
- }
- } else {
- try {
- uniqueHolder.addUnique(tmpUniqueValue);
- } catch (DataModelException e) {
- throw new ParserException(
- constructExtendedListenerErrorMessage(
- UNHANDLED_PARSED_DATA, UNIQUE_DATA,
- ctx.unique().getText(), ENTRY, e.getMessage()));
- }
- }
- } else {
- throw new ParserException(
- constructListenerErrorMessage(INVALID_HOLDER, UNIQUE_DATA,
- ctx.unique().getText(),
- ENTRY));
+ YangUniqueHolder holder = (YangUniqueHolder) tmpData;
+ if (holder instanceof YangDeviateAdd ||
+ holder instanceof YangDeviateDelete) {
+ return;
+ }
+ String tmpVal = removeQuotesAndHandleConcat(ctx.unique().getText());
+
+ String[] values = tmpVal.split(SPACE);
+ for (String val : values) {
+ List<YangAtomicPath> atomicPath = validateUniqueInList(
+ holder, val, ctx);
+ holder.addUnique(atomicPath);
}
}
}
\ No newline at end of file
diff --git a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java
index 1e367a4..f566545 100644
--- a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java
+++ b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/parserutils/ListenerUtil.java
@@ -19,10 +19,7 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
import org.onosproject.yang.compiler.datamodel.YangImport;
-import org.onosproject.yang.compiler.datamodel.YangLeaf;
import org.onosproject.yang.compiler.datamodel.YangLeafRef;
-import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
-import org.onosproject.yang.compiler.datamodel.YangList;
import org.onosproject.yang.compiler.datamodel.YangModule;
import org.onosproject.yang.compiler.datamodel.YangNode;
import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
@@ -31,6 +28,7 @@
import org.onosproject.yang.compiler.datamodel.YangReferenceResolver;
import org.onosproject.yang.compiler.datamodel.YangRelativePath;
import org.onosproject.yang.compiler.datamodel.YangSubModule;
+import org.onosproject.yang.compiler.datamodel.YangUniqueHolder;
import org.onosproject.yang.compiler.datamodel.utils.YangConstructType;
import org.onosproject.yang.compiler.parser.exceptions.ParserException;
import org.slf4j.Logger;
@@ -40,7 +38,6 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -99,6 +96,8 @@
public static final String LINE_NUMBER = "line number ";
public static final String CHARACTER_POSITION = "character position ";
public static final String FILE = "file ";
+ private static final String E_LEAF_REF = "YANG file error : A leaf " +
+ "reference, in unique, must refer to a leaf in the list";
// No instantiation.
private ListenerUtil() {
@@ -435,135 +434,56 @@
/**
* Validates the unique syntax from the reference path.
*
- * @param uniquePath path of unique
- * @param prefixOfFile current file's prefix
- * @param ctx yang construct's context to get the line number and character position
+ * @param val path of unique
+ * @param prefix current file's prefix
+ * @param ctx yang construct's context to get the line number and character position
* @return list of absolute path
*/
- private static List<YangAtomicPath> validateUniqueValues(String uniquePath, String prefixOfFile,
+ private static List<YangAtomicPath> validateUniqueValues(String val,
+ String prefix,
ParserRuleContext ctx) {
- List<YangAtomicPath> atomicPath = new LinkedList<>();
- String[] pathInUnique = uniquePath.split(SLASH_FOR_STRING);
- for (String uniqueValue : pathInUnique) {
- YangAtomicPath yangAtomicPathPath = new YangAtomicPath();
- YangNodeIdentifier nodeIdentifier = getValidNodeIdentifier(uniqueValue, UNIQUE_DATA, ctx);
- yangAtomicPathPath.setNodeIdentifier(nodeIdentifier);
- atomicPath.add(yangAtomicPathPath);
- if (nodeIdentifier.getPrefix() != null && nodeIdentifier.getPrefix() != prefixOfFile) {
- ParserException parserException =
- new ParserException("YANG file error : A leaf reference, in unique," +
- " must refer to a leaf in the list");
- parserException.setLine(ctx.getStart().getLine());
- parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
- throw parserException;
+ List<YangAtomicPath> pathList = new LinkedList<>();
+ String[] path = val.split(SLASH_FOR_STRING);
+ for (String uniVal : path) {
+ YangAtomicPath atomicPath = new YangAtomicPath();
+ YangNodeIdentifier nodeId = getValidNodeIdentifier(
+ uniVal, UNIQUE_DATA, ctx);
+ atomicPath.setNodeIdentifier(nodeId);
+ pathList.add(atomicPath);
+ if (nodeId.getPrefix() != null &&
+ !nodeId.getPrefix().equals(prefix)) {
+ ParserException exc = new ParserException(E_LEAF_REF);
+ exc.setLine(ctx.getStart().getLine());
+ exc.setCharPosition(ctx.getStart().getCharPositionInLine());
+ throw exc;
}
}
- return atomicPath;
+ return pathList;
}
- /**
- * Validates unique field from the list.
- *
- * @param yangList instance of YANG list
- * @param ctx yang construct's context to get the line number and character position
- */
- public static void validateUniqueInList(YangList yangList, ParserRuleContext ctx) {
- YangLeaf leaf;
- // Returns the prefix for the file where unique is present.
- String prefixOfTheFile = getRootPrefix(yangList);
- List<String> uniques = yangList.getUniqueList();
+ public static void addUniqueHolderToRoot(YangUniqueHolder holder) {
+ List<List<YangAtomicPath>> uniques = holder.getPathList();
if (uniques != null && !uniques.isEmpty()) {
- Iterator<String> uniqueList = uniques.listIterator();
- while (uniqueList.hasNext()) {
- String pathInUnique = uniqueList.next();
- List<YangAtomicPath> atomicPathInUnique = validateUniqueValues(pathInUnique, prefixOfTheFile, ctx);
- YangAtomicPath leafInPath = atomicPathInUnique.get(atomicPathInUnique.size() - 1);
- if (atomicPathInUnique.size() == 1) {
- leaf = getReferenceLeafFromUnique(yangList, leafInPath);
- } else {
- atomicPathInUnique.remove(atomicPathInUnique.size() - 1);
- YangNode holderOfLeaf = getNodeUnderListFromPath(atomicPathInUnique, yangList, ctx);
- leaf = getReferenceLeafFromUnique(holderOfLeaf, leafInPath);
- }
- if (leaf == null) {
- ParserException parserException =
- new ParserException("YANG file error : A leaf reference, in unique," +
- " must refer to a leaf under the list");
- parserException.setLine(ctx.getStart().getLine());
- parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
- throw parserException;
- }
- }
+ YangReferenceResolver root = (YangReferenceResolver) getRootNode(
+ (YangNode) holder);
+ root.addToUniqueHolderList(holder);
}
}
/**
- * Returns the last node under the unique path.
+ * Validates unique from the list.
*
- * @param uniquePath atomic path list
- * @param node root node from where it starts searching
- * @param ctx yang construct's context to get the line number and character position
- * @return last node in the list
+ * @param holder unique holder
+ * @param val path of unique
+ * @param ctx yang construct's context
+ * @return list of yang atomic path
*/
- private static YangNode getNodeUnderListFromPath(List<YangAtomicPath> uniquePath, YangNode node,
- ParserRuleContext ctx) {
- Iterator<YangAtomicPath> nodesInReference = uniquePath.listIterator();
- YangNode potentialReferredNode = node.getChild();
- while (nodesInReference.hasNext()) {
- YangAtomicPath nodeInUnique = nodesInReference.next();
- YangNode referredNode = getReferredNodeFromTheUniqueNodes(nodeInUnique.getNodeIdentifier(),
- potentialReferredNode);
- if (referredNode == null) {
- ParserException parserException =
- new ParserException("YANG file error : The target node in unique " +
- "reference path is invalid");
- parserException.setLine(ctx.getStart().getLine());
- parserException.setCharPosition(ctx.getStart().getCharPositionInLine());
- throw parserException;
- } else {
- potentialReferredNode = referredNode.getChild();
- }
- }
- return potentialReferredNode;
- }
-
- /**
- * Returns the node that matches with the name of the node in path.
- *
- * @param nodeInUnique node name in path
- * @param potentialReferredNode node under which it has to match
- * @return referred node
- */
- private static YangNode getReferredNodeFromTheUniqueNodes(YangNodeIdentifier nodeInUnique, YangNode
- potentialReferredNode) {
- while (potentialReferredNode != null) {
- // Check if the potential referred node is the actual referred node
- if (potentialReferredNode.getName().equals(nodeInUnique.getName())) {
- return potentialReferredNode;
- }
- potentialReferredNode = potentialReferredNode.getNextSibling();
- }
- return null;
- }
-
- /**
- * Returns the leaf which unique refers.
- *
- * @param nodeForLeaf last node where leaf is referred
- * @param leafInUnique leaf in unique path
- * @return YANG leaf
- */
- private static YangLeaf getReferenceLeafFromUnique(YangNode nodeForLeaf, YangAtomicPath leafInUnique) {
- YangLeavesHolder leavesHolder = (YangLeavesHolder) nodeForLeaf;
- List<YangLeaf> leaves = leavesHolder.getListOfLeaf();
- if (leaves != null && !leaves.isEmpty()) {
- for (YangLeaf leaf : leaves) {
- if (leafInUnique.getNodeIdentifier().getName().equals(leaf.getName())) {
- return leaf;
- }
- }
- }
- return null;
+ public static List<YangAtomicPath> validateUniqueInList(YangUniqueHolder holder,
+ String val,
+ ParserRuleContext ctx) {
+ YangNode node = (YangNode) holder;
+ String rootPre = getRootPrefix(node);
+ return validateUniqueValues(val, rootPre, ctx);
}
/**
@@ -572,7 +492,7 @@
* @param curNode YANG node
* @return prefix of the root node
*/
- public static String getRootPrefix(YangNode curNode) {
+ private static String getRootPrefix(YangNode curNode) {
String prefix;
YangNode node = getRootNode(curNode);
diff --git a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java
index cca24d1..8b8e5ba 100644
--- a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java
+++ b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/DeviationListenerTest.java
@@ -115,7 +115,6 @@
assertThat(deviateAdd.getUnits(), is("\"units\""));
assertThat(deviateAdd.getListOfMust().get(0).getConstraint(),
is("/base:system"));
- assertThat(deviateAdd.getUniqueList().get(0), is("id"));
assertThat(deviateAdd.getDefaultValueInString(), is("admin"));
assertThat(deviateAdd.isConfig(), is(true));
assertThat(deviateAdd.isMandatory(), is(true));
@@ -152,7 +151,6 @@
assertThat(deviateDelete.getUnits(), is("\"units\""));
assertThat(deviateDelete.getListOfMust().get(0).getConstraint(),
is("daytime or time"));
- assertThat(deviateDelete.getUniqueList().get(0), is("id"));
assertThat(deviateDelete.getDefaultValueInString(), is("defaultValue"));
assertThat(deviation.getResolvableStatus(), is(UNRESOLVED));
}
diff --git a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java
index ababd08..7eeef04 100644
--- a/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java
+++ b/compiler/base/parser/src/test/java/org/onosproject/yang/compiler/parser/impl/listeners/UniqueListenerTest.java
@@ -19,6 +19,8 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
import org.onosproject.yang.compiler.datamodel.YangList;
import org.onosproject.yang.compiler.datamodel.YangModule;
import org.onosproject.yang.compiler.datamodel.YangNode;
@@ -27,7 +29,8 @@
import org.onosproject.yang.compiler.parser.impl.YangUtilsParserManager;
import java.io.IOException;
-import java.util.ListIterator;
+import java.util.Iterator;
+import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
@@ -62,7 +65,10 @@
// Check whether the list is child of module
YangList yangList = (YangList) yangNode.getChild();
assertThat(yangList.getName(), is("valid"));
- assertThat(yangList.getUniqueList().listIterator().next(), is("invalid-interval"));
+ List<YangLeaf> leaves = yangList.getListOfLeaf();
+ YangLeaf leaf = leaves.iterator().next();
+
+ List<List<YangAtomicPath>> uniLeaves = yangList.getPathList();
}
/**
@@ -85,12 +91,85 @@
// Check whether the list is child of module
YangList yangList = (YangList) yangNode.getChild();
assertThat(yangList.getName(), is("valid"));
- ListIterator<String> listIterator;
- String list;
- listIterator = yangList.getUniqueList().listIterator();
- list = listIterator.next();
- assertThat(list, is("ospf"));
- list = listIterator.next();
- assertThat(list, is("isis"));
+
+ Iterator<List<YangAtomicPath>> pathListIt;
+ Iterator<YangAtomicPath> pathIt;
+ List<YangAtomicPath> path;
+ YangAtomicPath atPath;
+
+ pathListIt = yangList.getPathList().iterator();
+ path = pathListIt.next();
+ assertThat(path.size(), is(1));
+ pathIt = path.iterator();
+ atPath = pathIt.next();
+ assertThat(atPath.getNodeIdentifier().getName(), is("ospf"));
+ path = pathListIt.next();
+ assertThat(path.size(), is(1));
+ pathIt = path.iterator();
+ atPath = pathIt.next();
+ assertThat(atPath.getNodeIdentifier().getName(), is("isis"));
+ }
+
+
+ /**
+ * Check single unique along its atomic path.
+ */
+ @Test
+ public void processParsingUniqueValues() throws IOException,
+ ParserException {
+ YangNode node = manager.getDataModel(
+ "src/test/resources/UniqueError.yang");
+ assertThat((node instanceof YangModule), is(true));
+
+ //Check whether the node type is set properly to module.
+ assertThat(node.getNodeType(), is(YangNodeType.MODULE_NODE));
+
+ //Check whether the module name is set correctly.
+ YangModule yangNode = (YangModule) node;
+ assertThat(yangNode.getName(), is("TestUnique"));
+
+ //Check whether the list is child of module.
+ YangList yangList = (YangList) yangNode.getChild();
+ assertThat(yangList.getName(), is("resources"));
+
+ Iterator<List<YangAtomicPath>> pathListIt;
+ Iterator<YangAtomicPath> pathIt;
+ List<YangAtomicPath> path;
+ YangAtomicPath atPath;
+
+ pathListIt = yangList.getPathList().iterator();
+ path = pathListIt.next();
+ assertThat(path.size(), is(3));
+ pathIt = path.iterator();
+ atPath = pathIt.next();
+ assertThat(atPath.getNodeIdentifier().getName(), is("animal"));
+ atPath = pathIt.next();
+ assertThat(atPath.getNodeIdentifier().getName(), is("mammal"));
+ atPath = pathIt.next();
+ assertThat(atPath.getNodeIdentifier().getName(), is("abc"));
+ }
+
+ /**
+ * Check unique for its descendent.
+ */
+ @Test
+ public void processParsingUniqueDescendent() throws IOException,
+ ParserException {
+ thrown.expect(ParserException.class);
+ thrown.expectMessage("YANG file error : unique name is" +
+ " not valid.");
+ YangNode node = manager.getDataModel(
+ "src/test/resources/UniqueDescendent.yang");
+ }
+
+ /**
+ * Check the error for wrong holder of unique.
+ */
+ @Test
+ public void processWrongHolderOfUnique() throws IOException,
+ ParserException {
+ thrown.expect(ParserException.class);
+ YangNode node = manager.getDataModel(
+ "src/test/resources/WrongHolderOfUnique.yang");
}
}
\ No newline at end of file
diff --git a/compiler/base/parser/src/test/resources/UniqueDescendent.yang b/compiler/base/parser/src/test/resources/UniqueDescendent.yang
new file mode 100644
index 0000000..20409cb
--- /dev/null
+++ b/compiler/base/parser/src/test/resources/UniqueDescendent.yang
@@ -0,0 +1,12 @@
+module TestDescendent {
+ yang-version 1;
+ namespace http://huawei.com;
+ prefix Ant;
+ list networks {
+ key "abc";
+ unique "/abc";
+ leaf abc {
+ type "String";
+ }
+ }
+}
\ No newline at end of file
diff --git a/compiler/base/parser/src/test/resources/UniqueError.yang b/compiler/base/parser/src/test/resources/UniqueError.yang
new file mode 100644
index 0000000..cd15de1
--- /dev/null
+++ b/compiler/base/parser/src/test/resources/UniqueError.yang
@@ -0,0 +1,20 @@
+module TestUnique {
+ yang-version 1;
+ namespace http://huawei.com;
+ prefix Anim;
+ list resources {
+ key "count";
+ leaf count {
+ type int;
+ }
+ unique "animal/mammal/abc";
+ container animal {
+ list mammal {
+ key "abc";
+ leaf abc {
+ type "String";
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/compiler/base/parser/src/test/resources/WrongHolderOfUnique.yang b/compiler/base/parser/src/test/resources/WrongHolderOfUnique.yang
new file mode 100644
index 0000000..b259cc1
--- /dev/null
+++ b/compiler/base/parser/src/test/resources/WrongHolderOfUnique.yang
@@ -0,0 +1,11 @@
+module TestHolder {
+ yang-version 1;
+ namespace http://huawei.com;
+ prefix Hold;
+ container birds {
+ unique "abc"
+ leaf abc {
+ type "String";
+ }
+ }
+}
\ No newline at end of file
diff --git a/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/UniqueLinkingTest.java b/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/UniqueLinkingTest.java
new file mode 100644
index 0000000..0133b61
--- /dev/null
+++ b/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/UniqueLinkingTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017-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.yang.compiler.plugin.maven;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.onosproject.yang.compiler.datamodel.YangAtomicPath;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangList;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.linker.impl.YangLinkerManager;
+import org.onosproject.yang.compiler.parser.exceptions.ParserException;
+import org.onosproject.yang.compiler.tool.YangCompilerManager;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.updateFilePriority;
+import static org.onosproject.yang.compiler.utils.io.impl.YangFileScanner.getYangFiles;
+
+/**
+ * Test cases for testing the unique statement validation after linking.
+ */
+public class UniqueLinkingTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+
+ private final YangCompilerManager utilMgr = new YangCompilerManager();
+ private final YangLinkerManager linkerMgr = new YangLinkerManager();
+
+ /**
+ * Checks grouping linking of unique.
+ */
+ @Test
+ public void processGroupingLinkingForUnique()
+ throws IOException, ParserException, MojoExecutionException {
+
+ String searchDir = "src/test/resources/groupingforunique";
+
+ Set<Path> paths = new HashSet<>();
+ for (String file : getYangFiles(searchDir)) {
+ paths.add(Paths.get(file));
+ }
+
+ utilMgr.createYangFileInfoSet(paths);
+ utilMgr.parseYangFileInfoSet();
+ utilMgr.createYangNodeSet();
+ Set<YangNode> yangSet = utilMgr.getYangNodeSet();
+
+ YangNode refNode = null;
+ YangNode selfNode = null;
+
+ linkerMgr.createYangNodeSet(yangSet);
+ linkerMgr.addRefToYangFilesImportList(yangSet);
+ updateFilePriority(yangSet);
+ linkerMgr.processInterFileLinking(yangSet);
+ linkerMgr.processUniqueLinking(yangSet);
+
+ Iterator<YangNode> yangNodeIterator = utilMgr.getYangNodeSet().iterator();
+ YangNode rootNode = yangNodeIterator.next();
+
+ List<YangLeaf> leaves;
+ Iterator<YangLeaf> it;
+ YangNode list = rootNode.getChild();
+ assertThat(list instanceof YangList, is(true));
+ leaves = ((YangList) list).getUniqueLeaves();
+ assertThat(leaves.size(), is(1));
+ it = leaves.iterator();
+ YangLeaf groupingLeaf = it.next();
+ assertThat(groupingLeaf.getName(), is("groupingleaf"));
+
+ Iterator<List<YangAtomicPath>> pathListIt;
+ Iterator<YangAtomicPath> pathIt;
+ List<YangAtomicPath> path;
+ YangAtomicPath atPath;
+
+ pathListIt = ((YangList) list).getPathList().iterator();
+ path = pathListIt.next();
+ assertThat(path.size(), is(1));
+ pathIt = path.iterator();
+ atPath = pathIt.next();
+ assertThat(atPath.getNodeIdentifier().getName(), is("groupingleaf"));
+ }
+}
diff --git a/compiler/plugin/maven/src/test/resources/groupingforunique/ietf-network.yang b/compiler/plugin/maven/src/test/resources/groupingforunique/ietf-network.yang
new file mode 100644
index 0000000..0ecdbfa
--- /dev/null
+++ b/compiler/plugin/maven/src/test/resources/groupingforunique/ietf-network.yang
@@ -0,0 +1,19 @@
+module ietf-network {
+ yang-version 1;
+ namespace http://huawei.com;
+ prefix net;
+ list networks {
+ key "val";
+ unique "groupingleaf";
+ leaf val {
+ type string;
+ }
+ uses forgrouping;
+ }
+
+ grouping forgrouping {
+ leaf groupingleaf {
+ type string;
+ }
+ }
+}