identity ref issue fix in yang tools

Change-Id: If2d722fd98b714b879a82b7f66e586f31835ac4f
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangBase.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangBase.java
index a0194bb..55ec045 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangBase.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangBase.java
@@ -51,6 +51,9 @@
     // Referred identity parent information.
     private YangIdentity referredIdentity;
 
+    // Reference to parent
+    private YangIdentity parentIdentity;
+
     /**
      * Status of resolution. If completely resolved enum value is "RESOLVED",
      * if not enum value is "UNRESOLVED", in case reference of grouping/typedef/base/identityref
@@ -114,4 +117,22 @@
     public Object resolve() throws DataModelException {
         return null;
     }
+
+    /**
+     * Returns the parent identity node.
+     *
+     * @return the parent identity node
+     */
+    public YangIdentity getParentIdentity() {
+        return parentIdentity;
+    }
+
+    /**
+     * Sets the parent identity node.
+     *
+     * @param parentIdentity the parent identity node to set
+     */
+    public void setParentIdentity(YangIdentity parentIdentity) {
+        this.parentIdentity = parentIdentity;
+    }
 }
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangIdentity.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangIdentity.java
index 94732a9..316af01 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangIdentity.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/YangIdentity.java
@@ -20,6 +20,8 @@
 import org.onosproject.yang.compiler.datamodel.utils.YangConstructType;
 
 import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
 
 /*-
  * Reference RFC 6020.
@@ -65,14 +67,21 @@
     //YANG reference of the identity.
     private String reference;
 
+    /*
+     * Identity extend list to contain list of all the direct/indirect derived
+     * identities.
+     */
+    private List<YangIdentity> extendList;
+
     //Creates a identity type of node.
     public YangIdentity() {
         super(YangNodeType.IDENTITY_NODE, null);
+        extendList = new LinkedList<>();
     }
 
     @Override
     public void addToChildSchemaMap(YangSchemaNodeIdentifier schemaNodeIdentifier,
-            YangSchemaNodeContextInfo yangSchemaNodeContextInfo)
+                                    YangSchemaNodeContextInfo yangSchemaNodeContextInfo)
             throws DataModelException {
         // Do nothing.
     }
@@ -154,4 +163,31 @@
     public void setBaseNode(YangBase baseNode) {
         this.baseNode = baseNode;
     }
+
+    /**
+     * Returns the list of derived identities which extends the identity.
+     *
+     * @return the list of derived identities which extends the identity
+     */
+    public List<YangIdentity> getExtendList() {
+        return extendList;
+    }
+
+    /**
+     * Sets the list of derived identity.
+     *
+     * @param extendList the list of derived identities
+     */
+    public void setExtendList(List<YangIdentity> extendList) {
+        this.extendList = extendList;
+    }
+
+    /**
+     * Adds a derived identity.
+     *
+     * @param identity derived identity
+     */
+    public void addToExtendList(YangIdentity identity) {
+        extendList.add(identity);
+    }
 }
diff --git a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangResolutionInfoImpl.java b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangResolutionInfoImpl.java
index 2f7db3b..a4590ca 100644
--- a/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangResolutionInfoImpl.java
+++ b/compiler/base/linker/src/main/java/org/onosproject/yang/compiler/linker/impl/YangResolutionInfoImpl.java
@@ -835,6 +835,8 @@
             ((YangUses) entity).setRefGroup((YangGrouping) refNode);
         } else if (entity instanceof YangBase) {
             ((YangBase) entity).setReferredIdentity((YangIdentity) refNode);
+            addToIdentityExtendList(((YangIdentity) ((YangBase) entity).getParentIdentity()),
+                                    (YangIdentity) refNode);
         } else if (entity instanceof YangIdentityRef) {
             ((YangIdentityRef) entity).setReferredIdentity((YangIdentity) refNode);
         } else if (!(entity instanceof YangIfFeature) &&
@@ -847,6 +849,20 @@
         ((Resolvable) entity).setResolvableStatus(linkedStatus);
     }
 
+    private void addToIdentityExtendList(YangIdentity baseIdentity, YangIdentity
+            referredIdentity) {
+        YangIdentity referredId = referredIdentity;
+        while (referredId != null) {
+            referredId.addToExtendList(baseIdentity);
+            YangBase base = referredId.getBaseNode();
+            if (base == null) {
+                return;
+            } else {
+                referredId = base.getReferredIdentity();
+            }
+        }
+    }
+
     /**
      * Checks if type/grouping has further reference to typedef/ unresolved
      * uses. Add it to the partial resolve stack and return the status of
diff --git a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/BaseListener.java b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/BaseListener.java
index c05cd38..ac4975f 100644
--- a/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/BaseListener.java
+++ b/compiler/base/parser/src/main/java/org/onosproject/yang/compiler/parser/impl/listeners/BaseListener.java
@@ -90,6 +90,7 @@
         YangBase yangBase = new YangBase();
         yangBase.setBaseIdentifier(nodeIdentifier);
         ((YangIdentity) tmpData).setBaseNode(yangBase);
+        yangBase.setParentIdentity(((YangIdentity) tmpData));
 
         int errorLine = ctx.getStart().getLine();
         int errorPosition = ctx.getStart().getCharPositionInLine();
diff --git a/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/IdentityTranslatorTest.java b/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/IdentityTranslatorTest.java
index bb02522..2835a64 100644
--- a/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/IdentityTranslatorTest.java
+++ b/compiler/plugin/maven/src/test/java/org/onosproject/yang/compiler/plugin/maven/IdentityTranslatorTest.java
@@ -18,6 +18,10 @@
 
 import org.apache.maven.plugin.MojoExecutionException;
 import org.junit.Test;
+import org.onosproject.yang.compiler.datamodel.YangIdentity;
+import org.onosproject.yang.compiler.datamodel.YangModule;
+import org.onosproject.yang.compiler.datamodel.YangNode;
+import org.onosproject.yang.compiler.linker.impl.YangLinkerManager;
 import org.onosproject.yang.compiler.utils.io.YangPluginConfig;
 import org.onosproject.yang.compiler.utils.io.impl.YangFileScanner;
 import org.onosproject.yang.compiler.utils.io.impl.YangIoUtils;
@@ -26,12 +30,20 @@
 import java.io.File;
 import java.io.IOException;
 
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.onosproject.yang.compiler.datamodel.YangNodeType.MODULE_NODE;
+import static org.onosproject.yang.compiler.linker.impl.YangLinkerUtils.updateFilePriority;
+import static org.onosproject.yang.compiler.utils.io.YangPluginConfig.compileCode;
+import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.deleteDirectory;
+
 /**
  * Translator test case for identity.
  */
 public class IdentityTranslatorTest {
 
     private final YangUtilManager utilManager = new YangUtilManager();
+    private final YangLinkerManager yangLinkerManager = new YangLinkerManager();
     private static final String DIR = "target/identity/";
     private static final String COMP = System.getProperty("user.dir") + File
             .separator + DIR;
@@ -44,7 +56,7 @@
     @Test
     public void processTranslator() throws IOException,
             ParserException, MojoExecutionException {
-        YangIoUtils.deleteDirectory(DIR);
+        deleteDirectory(DIR);
         String searchDir = "src/test/resources/identityTranslator";
         utilManager.createYangFileInfoSet(YangFileScanner.getYangFiles(searchDir));
         utilManager.parseYangFileInfoSet();
@@ -54,7 +66,63 @@
         YangPluginConfig yangPluginConfig = new YangPluginConfig();
         yangPluginConfig.setCodeGenDir(DIR);
         utilManager.translateToJava(yangPluginConfig);
-        YangPluginConfig.compileCode(COMP);
-        YangIoUtils.deleteDirectory(DIR);
+        compileCode(COMP);
+        deleteDirectory(DIR);
+    }
+
+    /**
+     * Checks translation should not result in any exception.
+     *
+     * @throws MojoExecutionException
+     */
+    @Test
+    public void processMultipleLevelIdentity() throws IOException,
+            ParserException, MojoExecutionException {
+        deleteDirectory(DIR);
+        String searchDir = "src/test/resources/multipleIdentity";
+        utilManager.createYangFileInfoSet(YangFileScanner.getYangFiles(searchDir));
+        utilManager.parseYangFileInfoSet();
+        utilManager.createYangNodeSet();
+
+        YangNode selfNode = null;
+
+        // Create YANG node set
+        yangLinkerManager.createYangNodeSet(utilManager.getYangNodeSet());
+
+        // Add references to import list.
+        yangLinkerManager.addRefToYangFilesImportList(utilManager.getYangNodeSet());
+
+        updateFilePriority(utilManager.getYangNodeSet());
+
+        // Carry out inter-file linking.
+        yangLinkerManager.processInterFileLinking(utilManager.getYangNodeSet());
+
+        for (YangNode rootNode : utilManager.getYangNodeSet()) {
+            if (rootNode.getName().equals("test")) {
+                selfNode = rootNode;
+            }
+        }
+
+        // Check whether the data model tree returned is of type module.
+        assertThat(selfNode instanceof YangModule, is(true));
+
+        // Check whether the node type is set properly to module.
+        assertThat(selfNode.getNodeType(), is(MODULE_NODE));
+
+        // Check whether the module name is set correctly.
+        YangModule yangNode = (YangModule) selfNode;
+        assertThat(yangNode.getName(), is("test"));
+
+        YangIdentity id = ((YangIdentity) yangNode.getChild());
+        assertThat(id.getName(), is("identity3"));
+
+        assertThat(id.getExtendList().get(0).getName(), is("identity2"));
+        assertThat(id.getExtendList().get(1).getName(), is("identity1"));
+
+        YangPluginConfig yangPluginConfig = new YangPluginConfig();
+        yangPluginConfig.setCodeGenDir(DIR);
+        utilManager.translateToJava(yangPluginConfig);
+        compileCode(COMP);
+        deleteDirectory(DIR);
     }
 }
diff --git a/compiler/plugin/maven/src/test/resources/multipleIdentity/test.yang b/compiler/plugin/maven/src/test/resources/multipleIdentity/test.yang
new file mode 100644
index 0000000..05b4875
--- /dev/null
+++ b/compiler/plugin/maven/src/test/resources/multipleIdentity/test.yang
@@ -0,0 +1,21 @@
+module test {
+    namespace "identitytest";
+    prefix test ;
+
+    identity identity3;
+
+    identity identity2 {
+       base "identity3";
+    }
+
+    identity identity1 {
+       base "identity2";
+    }
+    container node {
+        leaf node-id{
+           type identityref {
+              base "identity1";
+           }
+        }
+    }
+}
\ No newline at end of file