[ONOS-4063 to 68] Intra YANG file Linking Implementation and Intra YANG file Linking Framework

Change-Id: I06e602c351ab54178bf90b8676af71a70e42371f
diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/TypeListener.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/TypeListener.java
index b000242..6f2f795 100644
--- a/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/TypeListener.java
+++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/parser/impl/listeners/TypeListener.java
@@ -16,10 +16,14 @@
 
 package org.onosproject.yangutils.parser.impl.listeners;
 
+import org.onosproject.yangutils.datamodel.ResolutionType;
 import org.onosproject.yangutils.datamodel.YangDataTypes;
-import org.onosproject.yangutils.datamodel.YangDerivedType;
+import org.onosproject.yangutils.datamodel.YangDerivedInfo;
 import org.onosproject.yangutils.datamodel.YangLeaf;
 import org.onosproject.yangutils.datamodel.YangLeafList;
+import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.datamodel.YangNodeIdentifier;
+import org.onosproject.yangutils.datamodel.YangResolutionInfo;
 import org.onosproject.yangutils.datamodel.YangType;
 import org.onosproject.yangutils.datamodel.YangTypeDef;
 import org.onosproject.yangutils.datamodel.YangUnion;
@@ -28,13 +32,18 @@
 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.utils.YangConstructType;
 
+import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.addResolutionInfo;
 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.UNHANDLED_PARSED_DATA;
+import static org.onosproject.yangutils.parser.impl.parserutils.ListenerUtil.getValidNodeIdentifier;
 import static org.onosproject.yangutils.parser.impl.parserutils.ListenerValidation.checkStackIsNotEmpty;
 import static org.onosproject.yangutils.utils.YangConstructType.TYPE_DATA;
 
@@ -77,12 +86,19 @@
         // Check for stack to be non empty.
         checkStackIsNotEmpty(listener, MISSING_HOLDER, TYPE_DATA, ctx.string().getText(), ENTRY);
 
-        YangDataTypes yangDataTypes = YangDataTypes.getType(ctx.string().getText());
-        YangType<?> type = new YangType();
+        // Validate node identifier.
+        YangNodeIdentifier nodeIdentifier = getValidNodeIdentifier(ctx.string().getText(), YangConstructType.TYPE_DATA,
+                ctx);
 
-        type.setDataTypeName(ctx.string().getText());
+        // Obtain the YANG data type.
+        YangDataTypes yangDataTypes = YangDataTypes.getType(ctx.string().getText());
+
+        // Create YANG type object and fill the values.
+        YangType<?> type = new YangType();
+        type.setNodeIdentifier(nodeIdentifier);
         type.setDataType(yangDataTypes);
 
+        // Push the type to the stack.
         listener.getParsedDataStack().push(type);
     }
 
@@ -99,24 +115,91 @@
         // Check for stack to be non empty.
         checkStackIsNotEmpty(listener, MISSING_CURRENT_HOLDER, TYPE_DATA, ctx.string().getText(), EXIT);
 
-        Parsable type = listener.getParsedDataStack().pop();
-        if (!(type instanceof YangType)) {
+        Parsable parsableType = listener.getParsedDataStack().pop();
+        if (!(parsableType instanceof YangType)) {
             throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
                     ctx.string().getText(), EXIT));
         }
 
+        YangType<?> type = (YangType<?>) parsableType;
+
         // Check for stack to be non empty.
         checkStackIsNotEmpty(listener, MISSING_HOLDER, TYPE_DATA, ctx.string().getText(), EXIT);
 
+        YangDataTypes yangDataTypes = YangDataTypes.getType(ctx.string().getText());
+
+        int errorLine = ctx.getStart().getLine();
+        int errorPosition = ctx.getStart().getCharPositionInLine();
+
         Parsable tmpData = listener.getParsedDataStack().peek();
         switch (tmpData.getYangConstructType()) {
             case LEAF_DATA:
                 YangLeaf leaf = (YangLeaf) tmpData;
                 leaf.setDataType((YangType<?>) type);
+
+                /*
+                 * If data type is derived, resolution information to be added
+                 * in resolution list.
+                 */
+                if (yangDataTypes == YangDataTypes.DERIVED) {
+                    // Parent YANG node of leaf to be added in resolution information.
+                    Parsable leafData = listener.getParsedDataStack().pop();
+                    Parsable parentNodeOfLeaf = listener.getParsedDataStack().peek();
+                    listener.getParsedDataStack().push(leafData);
+
+                    // Verify parent node of leaf
+                    if (!(parentNodeOfLeaf instanceof YangNode)) {
+                        throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
+                                ctx.string().getText(), EXIT));
+                    }
+
+                    // Get the prefix information
+                    String prefix = ((YangType<?>) type).getPrefix();
+
+                    // Create empty derived info and attach it to type extended info.
+                    YangDerivedInfo<?> yangDerivedInfo = new YangDerivedInfo<>();
+                    ((YangType<YangDerivedInfo>) type).setDataTypeExtendedInfo(yangDerivedInfo);
+
+                    // Add resolution information to the list
+                    YangResolutionInfo resolutionInfo = new YangResolutionInfo<YangType>(type,
+                            ResolutionType.TYPEDEF_RESOLUTION, (YangNode) parentNodeOfLeaf, prefix, errorLine,
+                            errorPosition);
+                    addToResolutionList(resolutionInfo, ctx);
+                }
                 break;
             case LEAF_LIST_DATA:
                 YangLeafList leafList = (YangLeafList) tmpData;
                 leafList.setDataType((YangType<?>) type);
+
+                /*
+                 * If data type is derived, resolution information to be added
+                 * in resolution list.
+                 */
+                if (yangDataTypes == YangDataTypes.DERIVED) {
+                    // Parent YANG node of leaf to be added in resolution information.
+                    Parsable leafListData = listener.getParsedDataStack().pop();
+                    Parsable parentNodeOfLeafList = listener.getParsedDataStack().peek();
+                    listener.getParsedDataStack().push(leafListData);
+
+                    // Verify parent node of leaf
+                    if (!(parentNodeOfLeafList instanceof YangNode)) {
+                        throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
+                                ctx.string().getText(), EXIT));
+                    }
+
+                    // Get the prefix information
+                    String prefix = ((YangType<?>) type).getPrefix();
+
+                    // Create empty derived info and attach it to type extended info.
+                    YangDerivedInfo<?> yangDerivedInfo = new YangDerivedInfo<>();
+                    ((YangType<YangDerivedInfo>) type).setDataTypeExtendedInfo(yangDerivedInfo);
+
+                    // Add resolution information to the list
+                    YangResolutionInfo resolutionInfo = new YangResolutionInfo<YangType>(type,
+                            ResolutionType.TYPEDEF_RESOLUTION, (YangNode) parentNodeOfLeafList, prefix, errorLine,
+                            errorPosition);
+                    addToResolutionList(resolutionInfo, ctx);
+                }
                 break;
             case UNION_DATA:
                 YangUnion unionNode = (YangUnion) tmpData;
@@ -130,34 +213,50 @@
                 }
                 break;
             case TYPEDEF_DATA:
-
                 /* Prepare the base type info and set in derived type */
                 YangTypeDef typeDef = (YangTypeDef) tmpData;
-                YangType<YangDerivedType> derivedType = typeDef.getDerivedType();
-                if (derivedType == null) {
-                    //TODO: set the error info correctly, to depict missing info
-                    throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
-                            ctx.string().getText(), ENTRY));
-                }
+                typeDef.setDataType((YangType<?>) type);
 
-                YangDerivedType derivedTypeInfo = new YangDerivedType();
-                if (((YangType<?>) type).getDataType() != YangDataTypes.DERIVED) {
-                    derivedTypeInfo.setEffectiveYangBuiltInType(((YangType<?>) type).getDataType());
-                } else {
-                    /*
-                     * It will be resolved in the validate data model at exit.
-                     * Nothing needs to be done.
-                     */
-                }
-                derivedTypeInfo.setBaseType((YangType<?>) type);
-                derivedType.setDataTypeExtendedInfo(derivedTypeInfo);
+                /*
+                 * If data type is derived, resolution information to be added
+                 * in resolution list.
+                 */
+                if (yangDataTypes == YangDataTypes.DERIVED) {
 
+                    // Get the prefix information
+                    String prefix = ((YangType<?>) type).getPrefix();
+
+                    // Create empty derived info and attach it to type extended info.
+                    YangDerivedInfo<?> yangDerivedInfo = new YangDerivedInfo<>();
+                    ((YangType<YangDerivedInfo>) type).setDataTypeExtendedInfo(yangDerivedInfo);
+
+                    // Add resolution information to the list
+                    YangResolutionInfo resolutionInfo = new YangResolutionInfo<YangType>(type,
+                            ResolutionType.TYPEDEF_RESOLUTION, (YangNode) typeDef, prefix, errorLine, errorPosition);
+                    addToResolutionList(resolutionInfo, ctx);
+                }
                 break;
-            //TODO: union, deviate replacement statement.case TYPEDEF_DATA: //TODO
+            //TODO: deviate replacement statement.case TYPEDEF_DATA: //TODO
 
             default:
                 throw new ParserException(constructListenerErrorMessage(INVALID_HOLDER, TYPE_DATA,
                         ctx.string().getText(), EXIT));
         }
     }
+
+    /**
+     * Add to resolution list.
+     *
+     * @param resolutionInfo resolution information.
+     * @param ctx context object of the grammar rule
+     */
+    private static void addToResolutionList(YangResolutionInfo<YangType> resolutionInfo,
+                                            GeneratedYangParser.TypeStatementContext ctx) {
+        try {
+            addResolutionInfo(resolutionInfo);
+        } catch (DataModelException e) {
+            throw new ParserException(constructExtendedListenerErrorMessage(UNHANDLED_PARSED_DATA,
+                    TYPE_DATA, ctx.string().getText(), EXIT, e.getMessage()));
+        }
+    }
 }