[ONOS-5517] Identity-ref resolution of typedef and grouping.

Change-Id: I2e1a775bfa61efa9203efa32dad8992a67331918
diff --git a/generator/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java b/generator/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
index 3400cfe..7c97805 100644
--- a/generator/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
+++ b/generator/src/main/java/org/onosproject/yangutils/linker/impl/YangResolutionInfoImpl.java
@@ -18,7 +18,6 @@
 
 import org.onosproject.yangutils.datamodel.DefaultLocationInfo;
 import org.onosproject.yangutils.datamodel.Resolvable;
-import org.onosproject.yangutils.datamodel.ResolvableType;
 import org.onosproject.yangutils.datamodel.RpcNotificationContainer;
 import org.onosproject.yangutils.datamodel.TraversalType;
 import org.onosproject.yangutils.datamodel.YangAtomicPath;
@@ -61,7 +60,6 @@
 import java.util.List;
 import java.util.Stack;
 
-import static org.onosproject.yangutils.datamodel.ResolvableType.YANG_IDENTITYREF;
 import static org.onosproject.yangutils.datamodel.ResolvableType.YANG_LEAFREF;
 import static org.onosproject.yangutils.datamodel.TraversalType.CHILD;
 import static org.onosproject.yangutils.datamodel.TraversalType.PARENT;
@@ -91,7 +89,6 @@
 import static org.onosproject.yangutils.utils.UtilConstants.FAILED_TO_FIND_ANNOTATION;
 import static org.onosproject.yangutils.utils.UtilConstants.FAILED_TO_FIND_LEAD_INFO_HOLDER;
 import static org.onosproject.yangutils.utils.UtilConstants.FAILED_TO_LINK;
-import static org.onosproject.yangutils.utils.UtilConstants.IDENTITYREF;
 import static org.onosproject.yangutils.utils.UtilConstants.INVALID_ENTITY;
 import static org.onosproject.yangutils.utils.UtilConstants.INVALID_LINKER_STATE;
 import static org.onosproject.yangutils.utils.UtilConstants.INVALID_RESOLVED_ENTITY;
@@ -253,96 +250,89 @@
     }
 
     /**
-     * Adds the leafref/identityref type to the type, which has derived type referring to
-     * typedef with leafref/identityref type.
+     * Adds leaf-ref to the resolution list, with different context if
+     * leaf-ref is defined under derived type. Leaf-ref must be resolved from
+     * where the typedef is referenced.
      */
     private void addDerivedRefTypeToRefTypeResolutionList()
             throws DataModelException {
 
         YangNode refNode = entityToResolveInfo.getHolderOfEntityToResolve();
-        YangType yangType = getValidateResolvableType();
+        YangDerivedInfo info = getValidResolvableType();
 
-        if (yangType == null) {
+        if (info == null) {
             return;
         }
 
-        YangDerivedInfo derivedInfo = (YangDerivedInfo) yangType
+        YangType<T> type =
+                (YangType<T>) entityToResolveInfo.getEntityToResolve();
+
+        T extType = (T) info.getReferredTypeDef().getTypeDefBaseType()
                 .getDataTypeExtendedInfo();
 
-        YangDataTypes dataType = derivedInfo.getEffectiveBuiltInType();
-        // If the derived types referred type is not leafref/identityref return
-        if (dataType != YangDataTypes.LEAFREF &&
-                dataType != YangDataTypes.IDENTITYREF) {
-            return;
+        while (extType instanceof YangDerivedInfo) {
+            info = (YangDerivedInfo) extType;
+            extType = (T) info.getReferredTypeDef().getTypeDefBaseType()
+                    .getDataTypeExtendedInfo();
         }
-
-        T extendedInfo = (T) derivedInfo.getReferredTypeDef()
-                .getTypeDefBaseType().getDataTypeExtendedInfo();
-
-        while (extendedInfo instanceof YangDerivedInfo) {
-            YangDerivedInfo derivedInfoFromTypedef = (YangDerivedInfo) extendedInfo;
-            extendedInfo = (T) derivedInfoFromTypedef.getReferredTypeDef()
-                    .getTypeDefBaseType().getDataTypeExtendedInfo();
-        }
-
         /*
-         * 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.
+         * Backup the leaf-ref info from derived type and deletes the derived
+         * type info. Copies the backed up leaf-ref data to the actual type in
+         * replacement of derived type. Adds to the resolution list in this
+         * context.
          */
-        if (dataType == YangDataTypes.LEAFREF) {
-            YangLeafRef leafRefInTypeDef = (YangLeafRef) extendedInfo;
-            addRefTypeInfo(YangDataTypes.LEAFREF, LEAFREF, extendedInfo,
-                           yangType, refNode, YANG_LEAFREF);
-            leafRefInTypeDef.setParentNode(refNode);
-        } else {
-            addRefTypeInfo(YangDataTypes.IDENTITYREF, IDENTITYREF, extendedInfo,
-                           yangType, refNode, YANG_IDENTITYREF);
-        }
+        addRefTypeInfo(extType, type, refNode);
     }
 
-    //Validates entity to resolve for YANG type and returns type
-    private YangType getValidateResolvableType() {
+    /**
+     * Returns the derived info if the holder is typedef, the entity is type
+     * and the effective type is leaf-ref; null otherwise.
+     *
+     * @return derived info
+     */
+    private YangDerivedInfo<?> getValidResolvableType() {
+
         YangNode refNode = entityToResolveInfo.getHolderOfEntityToResolve();
         T entity = entityToResolveInfo.getEntityToResolve();
-        // If holder is typedef return.
-        if (!(refNode instanceof YangTypeDef) && entity instanceof YangType) {
-            YangType yangType = (YangType) entity;
 
-            // If type is not resolved return.
-            if (yangType.getResolvableStatus() == RESOLVED) {
-                return (YangType) entity;
+        if (!(refNode instanceof YangTypeDef) && entity instanceof YangType) {
+            YangType<?> type = (YangType) entity;
+            YangDerivedInfo<?> info =
+                    (YangDerivedInfo) type.getDataTypeExtendedInfo();
+            YangDataTypes dataType = info.getEffectiveBuiltInType();
+            if ((type.getResolvableStatus() == RESOLVED) &&
+                    (dataType == YangDataTypes.LEAFREF)) {
+                return info;
             }
         }
         return null;
     }
 
     /**
-     * Adds referred type(leafref/identityref) info to resolution list.
+     * Adds resolvable type (leaf-ref) info to resolution list.
      *
-     * @param type     data type
-     * @param typeName type name
-     * @param info     extended info
-     * @param yangType YANG type
-     * @param refNode  referred node
-     * @param resType  resolution type
-     * @throws DataModelException when fails to do data model operations
+     * @param extType resolvable type
+     * @param type    YANG type
+     * @param holder  holder node
+     * @throws DataModelException if there is a data model error
      */
-    private void addRefTypeInfo(YangDataTypes type, String typeName, T info,
-                                YangType yangType, YangNode refNode,
-                                ResolvableType resType) throws DataModelException {
-        yangType.resetYangType();
-        yangType.setResolvableStatus(RESOLVED);
-        yangType.setDataType(type);
-        yangType.setDataTypeName(typeName);
-        yangType.setDataTypeExtendedInfo(info);
-        ((Resolvable) info).setResolvableStatus(UNRESOLVED);
-        YangResolutionInfoImpl resolutionInfoImpl
-                = new YangResolutionInfoImpl<>(info, refNode,
-                                               getLineNumber(), getCharPosition());
-        curRefResolver.addToResolutionList(resolutionInfoImpl, resType);
-        curRefResolver.resolveSelfFileLinking(resType);
+    private void addRefTypeInfo(T extType, YangType<T> type, YangNode holder)
+            throws DataModelException {
+
+        type.resetYangType();
+        type.setResolvableStatus(RESOLVED);
+        type.setDataType(YangDataTypes.LEAFREF);
+        type.setDataTypeName(LEAFREF);
+        type.setDataTypeExtendedInfo(extType);
+
+        YangLeafRef leafRef = (YangLeafRef) extType;
+        (leafRef).setResolvableStatus(UNRESOLVED);
+        leafRef.setParentNode(holder);
+
+        YangResolutionInfoImpl info = new YangResolutionInfoImpl<>(
+                leafRef, holder, getLineNumber(), getCharPosition());
+        curRefResolver.addToResolutionList(info, YANG_LEAFREF);
+        curRefResolver.resolveSelfFileLinking(YANG_LEAFREF);
     }
 
     /**
diff --git a/generator/src/main/java/org/onosproject/yangutils/translator/tojava/utils/StringGenerator.java b/generator/src/main/java/org/onosproject/yangutils/translator/tojava/utils/StringGenerator.java
index dfe2826..2ab8bc3 100644
--- a/generator/src/main/java/org/onosproject/yangutils/translator/tojava/utils/StringGenerator.java
+++ b/generator/src/main/java/org/onosproject/yangutils/translator/tojava/utils/StringGenerator.java
@@ -27,9 +27,23 @@
 import org.onosproject.yangutils.utils.io.YangPluginConfig;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.BOOLEAN;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.DECIMAL64;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.EMPTY;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT16;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT32;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT64;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.INT8;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.UINT16;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.UINT32;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.UINT64;
+import static org.onosproject.yangutils.datamodel.utils.builtindatatype.YangDataTypes.UINT8;
 import static org.onosproject.yangutils.translator.tojava.utils.BracketType.OPEN_CLOSE_BRACKET;
 import static org.onosproject.yangutils.translator.tojava.utils.BracketType.OPEN_CLOSE_BRACKET_WITH_VALUE;
 import static org.onosproject.yangutils.translator.tojava.utils.BracketType.OPEN_CLOSE_BRACKET_WITH_VALUE_AND_RETURN_TYPE;
@@ -148,6 +162,12 @@
  */
 public final class StringGenerator {
 
+    private static final Set<YangDataTypes> PRIMITIVE_TYPES =
+            new HashSet<>(Arrays.asList(INT8, INT16, INT32, INT64, UINT8,
+                                        UINT16, UINT32, UINT64, DECIMAL64,
+                                        BOOLEAN, EMPTY));
+
+    // No instantiation.
     private StringGenerator() {
     }
 
@@ -746,48 +766,59 @@
      */
     static String getParseFromStringMethod(String targetDataType,
                                            YangType<?> yangType) {
-        YangDataTypes type = yangType.getDataType();
 
+        YangDataTypes type = yangType.getDataType();
         switch (type) {
             case INT8:
                 return BYTE_WRAPPER + PERIOD + PARSE_BYTE;
+
             case INT16:
                 return SHORT_WRAPPER + PERIOD + PARSE_SHORT;
+
             case INT32:
                 return INTEGER_WRAPPER + PERIOD + PARSE_INT;
+
             case INT64:
                 return LONG_WRAPPER + PERIOD + PARSE_LONG;
+
             case UINT8:
                 return SHORT_WRAPPER + PERIOD + PARSE_SHORT;
+
             case UINT16:
                 return INTEGER_WRAPPER + PERIOD + PARSE_INT;
+
             case UINT32:
                 return LONG_WRAPPER + PERIOD + PARSE_LONG;
+
             case UINT64:
                 return NEW + SPACE + BIG_INTEGER;
+
             case DECIMAL64:
                 return NEW + SPACE + BIG_DECIMAL;
+
+            case INSTANCE_IDENTIFIER:
             case STRING:
             case IDENTITYREF:
                 return EMPTY_STRING;
+
             case EMPTY:
             case BOOLEAN:
                 return BOOLEAN_WRAPPER + PERIOD + PARSE_BOOLEAN;
+
             case ENUMERATION:
                 return targetDataType + PERIOD + OF;
+
             case DERIVED:
             case UNION:
                 return targetDataType + PERIOD + FROM_STRING_METHOD_NAME;
+
             default:
-                throw new TranslatorException("given data type is not " +
-                                                      "supported. " +
-                                                      yangType.getDataTypeName() +
-                                                      " in " +
-                                                      yangType.getLineNumber() +
-                                                      " at " +
-                                                      yangType.getCharPosition() +
-                                                      " in " +
-                                                      yangType.getFileName());
+                throw new TranslatorException(
+                        "Given data type is not supported. " +
+                                yangType.getDataTypeName() + " in " +
+                                yangType.getLineNumber() + " at " +
+                                yangType.getCharPosition() + " in " +
+                                yangType.getFileName());
         }
     }
 
@@ -873,6 +904,16 @@
     }
 
     /**
+     * Returns true, if the data type is primitive; false otherwise.
+     *
+     * @param dataType data type
+     * @return true if the data type is primitive; false otherwise
+     */
+    public static boolean isPrimitiveDataType(YangDataTypes dataType) {
+        return PRIMITIVE_TYPES.contains(dataType);
+    }
+
+    /**
      * Returns list string.
      *
      * @return list string