YANG construct collision detection framework added

Change-Id: I1458f9e3192641f3f90c444798c31a64536ffa5d
diff --git a/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java b/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java
index 2319b8e..7692025 100644
--- a/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java
+++ b/src/main/java/org/onosproject/yangutils/parser/impl/listeners/ListListener.java
@@ -16,31 +16,38 @@
 
 package org.onosproject.yangutils.parser.impl.listeners;
 
-import org.onosproject.yangutils.datamodel.YangList;
 import org.onosproject.yangutils.datamodel.YangContainer;
+import org.onosproject.yangutils.datamodel.YangList;
 import org.onosproject.yangutils.datamodel.YangModule;
 import org.onosproject.yangutils.datamodel.YangNode;
 import org.onosproject.yangutils.datamodel.YangNodeType;
 import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
 import org.onosproject.yangutils.parser.Parsable;
-import org.onosproject.yangutils.parser.ParsableDataType;
 import org.onosproject.yangutils.parser.antlrgencode.GeneratedYangParser;
 import org.onosproject.yangutils.parser.exceptions.ParserException;
 import org.onosproject.yangutils.parser.impl.TreeWalkListener;
-import org.onosproject.yangutils.parser.impl.YangUtilsParserManager;
-import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation;
-
-import static org.onosproject.yangutils.parser.ParsableDataType.LIST_DATA;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerCollisionDetector.detectCollidingChildUtil;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.ENTRY;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorLocation.EXIT;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructExtendedListenerErrorMessage;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorMessageConstruction.constructListenerErrorMessage;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_CURRENT_HOLDER;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.MISSING_HOLDER;
-import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_HOLDER;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.UNHANDLED_PARSED_DATA;
-import static org.onosproject.yangutils.parser.impl.parserutils.ListenerErrorType.INVALID_CARDINALITY;
+import org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.validateCardinality;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.validateCardinalityNonNull;
+import static org.onosproject.yangutils.utils.YangConstructType.CONFIG_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.DATA_DEF_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.DESCRIPTION_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.KEY_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.LIST_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.MAX_ELEMENT_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.MIN_ELEMENT_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.REFERENCE_DATA;
+import static org.onosproject.yangutils.utils.YangConstructType.STATUS_DATA;
 
 /*
  * Reference: RFC6020 and YANG ANTLR Grammar
@@ -74,13 +81,11 @@
  */
 
 /**
- * Implements listener based call back function corresponding to the "list"
- * rule defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
+ * Implements listener based call back function corresponding to the "list" rule
+ * defined in ANTLR grammar file for corresponding ABNF rule in RFC 6020.
  */
 public final class ListListener {
 
-    private static ParsableDataType yangConstruct;
-
     /**
      * Creates a new list listener.
      */
@@ -88,30 +93,35 @@
     }
 
     /**
-     * It is called when parser receives an input matching the grammar
-     * rule (list), performs validation and updates the data model
-     * tree.
+     * It is called when parser receives an input matching the grammar rule
+     * (list), performs validation and updates the data model tree.
      *
-     * @param listener listener's object.
-     * @param ctx context object of the grammar rule.
+     * @param listener listener's object
+     * @param ctx context object of the grammar rule
      */
     public static void processListEntry(TreeWalkListener listener,
-                                             GeneratedYangParser.ListStatementContext ctx) {
+            GeneratedYangParser.ListStatementContext ctx) {
 
         YangNode curNode;
 
         checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.IDENTIFIER().getText(), ENTRY);
 
-        boolean result = validateSubStatementsCardinality(ctx);
-        if (!result) {
-            throw new ParserException(constructListenerErrorMessage(INVALID_CARDINALITY, yangConstruct, "", ENTRY));
-        }
+        // Validate sub statement cardinality.
+        validateSubStatementsCardinality(ctx);
+
+        // Check for identifier collision
+        int line = ctx.IDENTIFIER().getSymbol().getLine();
+        int charPositionInLine = ctx.IDENTIFIER().getSymbol().getCharPositionInLine();
+        String identifierName = ctx.IDENTIFIER().getText();
+        detectCollidingChildUtil(listener, line, charPositionInLine, identifierName, LIST_DATA);
 
         YangList yangList = new YangList(YangNodeType.LIST_NODE);
         yangList.setName(ctx.IDENTIFIER().getText());
 
-        /* If "config" is not specified, the default is the same as the parent
-           schema node's "config" value. */
+        /*
+         * If "config" is not specified, the default is the same as the parent
+         * schema node's "config" value.
+         */
         if (ctx.configStatement().isEmpty()) {
             boolean parentConfig = ListenerValidation.getParentNodeConfig(listener);
             yangList.setConfig(parentConfig);
@@ -130,7 +140,7 @@
             listener.getParsedDataStack().push(yangList);
         } else {
             throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, LIST_DATA,
-                            ctx.IDENTIFIER().getText(), ENTRY));
+                    ctx.IDENTIFIER().getText(), ENTRY));
         }
     }
 
@@ -138,11 +148,11 @@
      * It is called when parser exits from grammar rule (list), it performs
      * validation and updates the data model tree.
      *
-     * @param listener listener's object.
-     * @param ctx context object of the grammar rule.
+     * @param listener listener's object
+     * @param ctx context object of the grammar rule
      */
     public static void processListExit(TreeWalkListener listener,
-                                            GeneratedYangParser.ListStatementContext ctx) {
+            GeneratedYangParser.ListStatementContext ctx) {
 
         checkStackIsNotEmpty(listener, MISSING_HOLDER, LIST_DATA, ctx.IDENTIFIER().getText(), EXIT);
 
@@ -157,65 +167,25 @@
             listener.getParsedDataStack().pop();
         } else {
             throw new ParserException(constructListenerErrorMessage(MISSING_CURRENT_HOLDER, LIST_DATA,
-                            ctx.IDENTIFIER().getText(), EXIT));
+                    ctx.IDENTIFIER().getText(), EXIT));
         }
     }
 
     /**
      * Validates the cardinality of list sub-statements as per grammar.
      *
-     * @param ctx context object of the grammar rule.
-     * @return true/false validation success or failure.
+     * @param ctx context object of the grammar rule
      */
-    private static boolean validateSubStatementsCardinality(GeneratedYangParser.ListStatementContext ctx) {
+    private static void validateSubStatementsCardinality(GeneratedYangParser.ListStatementContext ctx) {
 
-        if ((!ctx.keyStatement().isEmpty())
-                && (ctx.keyStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
-            yangConstruct = ParsableDataType.KEY_DATA;
-            return false;
-        }
-
-        if ((!ctx.configStatement().isEmpty())
-                && (ctx.configStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
-            yangConstruct = ParsableDataType.CONFIG_DATA;
-            return false;
-        }
-
-        if ((!ctx.maxElementsStatement().isEmpty())
-                && (ctx.maxElementsStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
-            yangConstruct = ParsableDataType.MAX_ELEMENT_DATA;
-            return false;
-        }
-
-        if ((!ctx.minElementsStatement().isEmpty())
-                && (ctx.minElementsStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
-            yangConstruct = ParsableDataType.MIN_ELEMENT_DATA;
-            return false;
-        }
-
-        if ((!ctx.descriptionStatement().isEmpty())
-                && (ctx.descriptionStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
-            yangConstruct = ParsableDataType.DESCRIPTION_DATA;
-            return false;
-        }
-
-        if ((!ctx.referenceStatement().isEmpty())
-                && (ctx.referenceStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
-            yangConstruct = ParsableDataType.REFERENCE_DATA;
-            return false;
-        }
-
-        if ((!ctx.statusStatement().isEmpty())
-                && (ctx.statusStatement().size() != YangUtilsParserManager.SUB_STATEMENT_CARDINALITY)) {
-            yangConstruct = ParsableDataType.STATUS_DATA;
-            return false;
-        }
-
-        if (ctx.dataDefStatement().isEmpty()) {
-            yangConstruct = ParsableDataType.LIST_DATA;
-            return false;
-        }
-
-        return true;
+        validateCardinality(ctx.keyStatement(), KEY_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        validateCardinality(ctx.configStatement(), CONFIG_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        validateCardinality(ctx.maxElementsStatement(), MAX_ELEMENT_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        validateCardinality(ctx.minElementsStatement(), MIN_ELEMENT_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        validateCardinality(ctx.descriptionStatement(), DESCRIPTION_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        validateCardinality(ctx.referenceStatement(), REFERENCE_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        validateCardinality(ctx.statusStatement(), STATUS_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        validateCardinalityNonNull(ctx.dataDefStatement(), DATA_DEF_DATA, LIST_DATA, ctx.IDENTIFIER().getText());
+        //TODO when, typedef, grouping, unique
     }
-}
\ No newline at end of file
+}