[ONOS-4753] Identity/identityref implementation and UT

Change-Id: I40148fa228465555be3bdf410cc294ffc0f34c18
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/GeneratedJavaFileType.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/GeneratedJavaFileType.java
index d4666c0c..1a2b9b8 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/GeneratedJavaFileType.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/GeneratedJavaFileType.java
@@ -89,6 +89,11 @@
     public static final int GENERATE_EVENT_SUBJECT_CLASS = 1024;
 
     /**
+     * Identity listener class.
+     */
+    public static final int GENERATE_IDENTITY_CLASS = 2048;
+
+    /**
      * Creates an instance of generate java file type.
      */
     private GeneratedJavaFileType() {
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/YangDataModelFactory.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/YangDataModelFactory.java
index 4d68fe2..9ba4068 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/YangDataModelFactory.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/YangDataModelFactory.java
@@ -20,6 +20,7 @@
 import org.onosproject.yangutils.datamodel.YangChoice;
 import org.onosproject.yangutils.datamodel.YangContainer;
 import org.onosproject.yangutils.datamodel.YangGrouping;
+import org.onosproject.yangutils.datamodel.YangIdentity;
 import org.onosproject.yangutils.datamodel.YangInput;
 import org.onosproject.yangutils.datamodel.YangLeaf;
 import org.onosproject.yangutils.datamodel.YangLeafList;
@@ -41,6 +42,7 @@
 import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaContainer;
 import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaEnumeration;
 import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaGrouping;
+import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaIdentity;
 import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaInput;
 import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaLeaf;
 import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaLeafList;
@@ -163,6 +165,24 @@
      * generated
      * @return the corresponding inherited node based on the target language
      */
+    public static YangIdentity getYangIdentityNode(GeneratedLanguage targetLanguage) {
+        switch (targetLanguage) {
+            case JAVA_GENERATION: {
+                return new YangJavaIdentity();
+            }
+            default: {
+                throw new TranslatorException("Only YANG to Java is supported.");
+            }
+        }
+    }
+
+    /**
+     * Returns based on the target language generate the inherited data model node.
+     *
+     * @param targetLanguage target language in which YANG mapping needs to be
+     * generated
+     * @return the corresponding inherited node based on the target language
+     */
     public static YangGrouping getYangGroupingNode(GeneratedLanguage targetLanguage) {
         switch (targetLanguage) {
             case JAVA_GENERATION: {
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/javamodel/AttributesJavaDataType.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/javamodel/AttributesJavaDataType.java
index 6df66af..52595c7 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/javamodel/AttributesJavaDataType.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/javamodel/AttributesJavaDataType.java
@@ -20,7 +20,9 @@
 
 import org.onosproject.yangutils.datamodel.YangDerivedInfo;
 import org.onosproject.yangutils.datamodel.YangEnumeration;
+import org.onosproject.yangutils.datamodel.YangIdentity;
 import org.onosproject.yangutils.datamodel.YangLeafRef;
+import org.onosproject.yangutils.datamodel.YangIdentityRef;
 import org.onosproject.yangutils.datamodel.YangNode;
 import org.onosproject.yangutils.datamodel.YangType;
 import org.onosproject.yangutils.datamodel.YangTypeDef;
@@ -161,8 +163,10 @@
                     YangType<?> referredType = getReferredTypeFromLeafref(yangType);
                     return getJavaImportClass(referredType, isListAttr, pluginConfig);
                 case IDENTITYREF:
-                    //TODO:IDENTITYREF
-                    break;
+                    YangIdentityRef identityRef = (YangIdentityRef) yangType.getDataTypeExtendedInfo();
+                    YangIdentity identity = identityRef.getReferredIdentity();
+                    return getCapitalCase(getCamelCase(((YangJavaIdentity) identity).
+                                                        getName(), pluginConfig));
                 case EMPTY:
                     return BOOLEAN_WRAPPER;
                 case UNION:
@@ -196,8 +200,9 @@
                     YangType<?> referredType = getReferredTypeFromLeafref(yangType);
                     return getJavaImportClass(referredType, isListAttr, pluginConfig);
                 case IDENTITYREF:
-                    //TODO:IDENTITYREF
-                    break;
+                    YangIdentityRef identityRef = (YangIdentityRef) yangType.getDataTypeExtendedInfo();
+                    YangIdentity identity = identityRef.getReferredIdentity();
+                    return getCapitalCase(getCamelCase(((YangJavaIdentity) identity).getName(), pluginConfig));
                 case EMPTY:
                     return BOOLEAN_DATA_TYPE;
                 case UNION:
@@ -212,7 +217,6 @@
                     return null;
             }
         }
-        return null;
     }
 
     /**
@@ -253,8 +257,7 @@
                     YangType<?> referredType = getReferredTypeFromLeafref(yangType);
                     return getJavaImportPackage(referredType, isListAttr, conflictResolver);
                 case IDENTITYREF:
-                    //TODO:IDENTITYREF
-                    break;
+                    return getIdentityRefPackage(yangType, conflictResolver);
                 case UNION:
                     return getUnionPackage(yangType, conflictResolver);
                 case INSTANCE_IDENTIFIER:
@@ -280,8 +283,7 @@
                     YangType<?> referredType = getReferredTypeFromLeafref(yangType);
                     return getJavaImportPackage(referredType, isListAttr, conflictResolver);
                 case IDENTITYREF:
-                    //TODO:IDENTITYREF
-                    break;
+                    return getIdentityRefPackage(yangType, conflictResolver);
                 case EMPTY:
                     return JAVA_LANG;
                 case UNION:
@@ -294,7 +296,6 @@
                     return null;
             }
         }
-        return null;
     }
 
     /**
@@ -361,6 +362,25 @@
     }
 
     /**
+     * Returns YANG identity's java package.
+     *
+     * @param type             YANG type
+     * @param conflictResolver object of YANG to java naming conflict util
+     * @return YANG identity's java package
+     */
+    private static String getIdentityRefPackage(YangType<?> type, YangToJavaNamingConflictUtil conflictResolver) {
+
+        if (!(type.getDataTypeExtendedInfo() instanceof YangIdentityRef)) {
+            throw new TranslatorException("type should have been identityref.");
+        }
+        YangIdentityRef identityRef = (YangIdentityRef) type.getDataTypeExtendedInfo();
+        YangJavaIdentity identity = (YangJavaIdentity) (identityRef.getReferredIdentity());
+        if (identity.getJavaFileInfo().getPackage() == null) {
+            return getPackageFromParent(identity.getParent(), conflictResolver);
+        }
+        return identity.getJavaFileInfo().getPackage();
+    }
+    /**
      * Returns package from parent node.
      *
      * @param parent           parent YANG node
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/javamodel/YangJavaIdentity.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/javamodel/YangJavaIdentity.java
new file mode 100644
index 0000000..ec0e637
--- /dev/null
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/javamodel/YangJavaIdentity.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2016-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.yangutils.translator.tojava.javamodel;
+
+import org.onosproject.yangutils.datamodel.YangIdentity;
+import org.onosproject.yangutils.translator.exception.TranslatorException;
+import org.onosproject.yangutils.translator.tojava.JavaCodeGenerator;
+import org.onosproject.yangutils.translator.tojava.JavaCodeGeneratorInfo;
+import org.onosproject.yangutils.translator.tojava.JavaFileInfo;
+import org.onosproject.yangutils.translator.tojava.JavaImportData;
+import org.onosproject.yangutils.translator.tojava.JavaQualifiedTypeInfo;
+import org.onosproject.yangutils.translator.tojava.TempJavaCodeFragmentFiles;
+import org.onosproject.yangutils.utils.io.impl.YangPluginConfig;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_INTERFACE_WITH_BUILDER;
+import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_IDENTITY_CLASS;
+import static org.onosproject.yangutils.translator.tojava.javamodel.YangJavaModelUtils.updatePackageInfo;
+import static org.onosproject.yangutils.translator.tojava.utils.JavaFileGeneratorUtils.getFileObject;
+import static org.onosproject.yangutils.translator.tojava.utils.JavaFileGeneratorUtils.initiateJavaFileGeneration;
+import static org.onosproject.yangutils.translator.tojava.utils.JavaIdentifierSyntax.createPackage;
+import static org.onosproject.yangutils.translator.tojava.utils.TempJavaCodeFragmentFilesUtils.closeFile;
+import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
+
+/**
+ * Represents input information extended to support java code generation.
+ */
+public class YangJavaIdentity extends YangIdentity
+        implements JavaCodeGeneratorInfo, JavaCodeGenerator {
+
+    //File type extension for java classes.
+    private static final String JAVA_FILE_EXTENSION = ".java";
+
+
+    //Contains the information of the java file being generated.
+    private JavaFileInfo javaFileInfo;
+
+    //Contains the information of the importd.
+    private transient JavaImportData importData;
+
+    /**
+     * File handle to maintain temporary java code fragments as per the code
+     * snippet types.
+     */
+    private TempJavaCodeFragmentFiles tempFileHandle;
+
+    /**
+     * Creates YANG java container object.
+     */
+    public YangJavaIdentity() {
+        setJavaFileInfo(new JavaFileInfo());
+        getJavaFileInfo().setGeneratedFileTypes(GENERATE_INTERFACE_WITH_BUILDER);
+        importData = new JavaImportData();
+    }
+
+    /**
+     * Returns the generated java file information.
+     *
+     * @return generated java file information
+     */
+    @Override
+    public JavaFileInfo getJavaFileInfo() {
+        if (javaFileInfo == null) {
+            throw new TranslatorException("Missing java info in java datamodel node");
+        }
+        return javaFileInfo;
+    }
+
+    /**
+     * Sets the java file info object.
+     *
+     * @param javaInfo java file info object
+     */
+    @Override
+    public void setJavaFileInfo(JavaFileInfo javaInfo) {
+        javaFileInfo = javaInfo;
+    }
+
+    /**
+     * Returns the temporary file handle.
+     *
+     * @return temporary file handle
+     */
+    @Override
+    public TempJavaCodeFragmentFiles getTempJavaCodeFragmentFiles() {
+        return tempFileHandle;
+    }
+
+    /**
+     * Sets temporary file handle.
+     *
+     * @param fileHandle temporary file handle
+     */
+    @Override
+    public void setTempJavaCodeFragmentFiles(TempJavaCodeFragmentFiles fileHandle) {
+        tempFileHandle = fileHandle;
+    }
+
+    /**
+     * Prepare the information for java code generation corresponding to YANG
+     * container info.
+     *
+     * @param yangPlugin YANG plugin config
+     * @throws TranslatorException translator operation fail
+     */
+    @Override
+    public void generateCodeEntry(YangPluginConfig yangPlugin) throws TranslatorException {
+        try {
+            updatePackageInfo(this, yangPlugin);
+            JavaQualifiedTypeInfo basePkgInfo = new JavaQualifiedTypeInfo();
+            String className = getCapitalCase(getJavaFileInfo().getJavaName());
+            String path = getJavaFileInfo().getPackageFilePath();
+            createPackage(this);
+            List<String> imports = null;
+            boolean isQualified = false;
+
+            if (getBaseNode() != null && getBaseNode().getReferredIdentity() != null) {
+                if (!(getBaseNode().getReferredIdentity() instanceof YangJavaIdentity)) {
+                    throw new TranslatorException("Failed to prepare generate code entry for base node");
+                }
+                YangJavaIdentity baseIdentity = (YangJavaIdentity) getBaseNode().getReferredIdentity();
+                String baseClassName = getCapitalCase(baseIdentity.getJavaFileInfo().getJavaName());
+                String basePkg =  baseIdentity.getJavaFileInfo().getPackage();
+                basePkgInfo.setClassInfo(baseClassName);
+                basePkgInfo.setPkgInfo(basePkg);
+                isQualified = importData.addImportInfo(basePkgInfo, className, getJavaFileInfo().getPackage());
+                if (!isQualified) {
+                    imports = importData.getImports();
+                }
+            }
+
+            File file = getFileObject(path, className, JAVA_FILE_EXTENSION, getJavaFileInfo());
+
+            initiateJavaFileGeneration(file, GENERATE_IDENTITY_CLASS, imports, this, className);
+            closeFile(file, false);
+        } catch (IOException e) {
+            throw new TranslatorException(
+                    "Failed to prepare generate code entry for identity node " + this.getName());
+        }
+    }
+
+    /**
+     * Create a java file using the YANG container info.
+     *
+     * @throws TranslatorException translator operation fail
+     */
+    @Override
+    public void generateCodeExit() throws TranslatorException {
+        /* Do nothing, file is already generated in entry*/
+    }
+}
+
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/ClassDefinitionGenerator.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/ClassDefinitionGenerator.java
index 69f6d3e..ab8134f 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/ClassDefinitionGenerator.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/ClassDefinitionGenerator.java
@@ -16,10 +16,13 @@
 
 package org.onosproject.yangutils.translator.tojava.utils;
 
+import org.onosproject.yangutils.datamodel.YangIdentity;
 import org.onosproject.yangutils.datamodel.YangNode;
 import org.onosproject.yangutils.datamodel.YangNotification;
+import org.onosproject.yangutils.translator.exception.TranslatorException;
 import org.onosproject.yangutils.translator.tojava.JavaQualifiedTypeInfo;
 import org.onosproject.yangutils.translator.tojava.TempJavaCodeFragmentFilesContainer;
+import org.onosproject.yangutils.translator.tojava.javamodel.YangJavaIdentity;
 
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.BUILDER_CLASS_MASK;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.BUILDER_INTERFACE_MASK;
@@ -27,6 +30,7 @@
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_EVENT_CLASS;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_EVENT_LISTENER_INTERFACE;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_EVENT_SUBJECT_CLASS;
+import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_IDENTITY_CLASS;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_SERVICE_AND_MANAGER;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_TYPEDEF_CLASS;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_UNION_CLASS;
@@ -57,6 +61,8 @@
 import static org.onosproject.yangutils.utils.UtilConstants.SERVICE;
 import static org.onosproject.yangutils.utils.UtilConstants.SPACE;
 import static org.onosproject.yangutils.utils.UtilConstants.SUBJECT;
+import static org.onosproject.yangutils.utils.UtilConstants.ABSTRACT;
+import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
 import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.trimAtLast;
 
 /**
@@ -128,6 +134,8 @@
                 return getEventListenerDefinition(yangName);
             case GENERATE_EVENT_SUBJECT_CLASS:
                 return getClassDefinition(yangName);
+            case GENERATE_IDENTITY_CLASS:
+                return getIdentityClassDefinition(yangName, curNode);
             default:
                 return null;
         }
@@ -214,6 +222,32 @@
     }
 
     /**
+     * Returns implementation file identity class definition.
+     *
+     * @param yangName file name
+     * @return identity class definition
+     */
+    private static String getIdentityClassDefinition(String yangName, YangNode curNode) {
+        if (!(curNode instanceof YangJavaIdentity)) {
+            throw new TranslatorException("Expected java identity instance node");
+        }
+        YangJavaIdentity identity = (YangJavaIdentity) curNode;
+        if (identity.getBaseNode() != null) {
+            YangIdentity baseIdentity = identity.getBaseNode().getReferredIdentity();
+            if (!(baseIdentity instanceof YangJavaIdentity)) {
+                throw new TranslatorException("Expected java identity instance node");
+            }
+
+            YangJavaIdentity baseJavaIdentity = (YangJavaIdentity) baseIdentity;
+            return PUBLIC + SPACE + ABSTRACT + SPACE + CLASS + SPACE + yangName + SPACE + EXTEND + SPACE
+                    + getCapitalCase(baseJavaIdentity.getJavaFileInfo().getJavaName()) + SPACE +
+                    OPEN_CURLY_BRACKET + NEW_LINE;
+        }
+
+        return PUBLIC + SPACE + ABSTRACT + SPACE + CLASS + SPACE + yangName + SPACE + OPEN_CURLY_BRACKET + NEW_LINE;
+    }
+
+    /**
      * Returns type file class definition.
      *
      * @param yangName file name
diff --git a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/JavaFileGeneratorUtils.java b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/JavaFileGeneratorUtils.java
index fc24ff9..4a2b6f5 100644
--- a/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/JavaFileGeneratorUtils.java
+++ b/utils/yangutils/plugin/src/main/java/org/onosproject/yangutils/translator/tojava/utils/JavaFileGeneratorUtils.java
@@ -42,6 +42,7 @@
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_SERVICE_AND_MANAGER;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_TYPEDEF_CLASS;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_UNION_CLASS;
+import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.GENERATE_IDENTITY_CLASS;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.IMPL_CLASS_MASK;
 import static org.onosproject.yangutils.translator.tojava.GeneratedJavaFileType.INTERFACE_MASK;
 import static org.onosproject.yangutils.translator.tojava.GeneratedTempFileType.ATTRIBUTES_MASK;
@@ -68,6 +69,7 @@
 import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getJavaPackageFromPackagePath;
 import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getSmallCase;
 import static org.onosproject.yangutils.utils.UtilConstants.CLOSE_PARENTHESIS;
+import static org.onosproject.yangutils.utils.UtilConstants.CLOSE_CURLY_BRACKET;
 import static org.onosproject.yangutils.utils.UtilConstants.COMPONENT_ANNOTATION;
 import static org.onosproject.yangutils.utils.UtilConstants.EQUAL;
 import static org.onosproject.yangutils.utils.UtilConstants.FOUR_SPACE_INDENTATION;
@@ -294,6 +296,7 @@
             }
 
             file.createNewFile();
+
             appendContents(file, genType, imports, curNode, className);
         } catch (IOException e) {
             throw new IOException("Failed to create " + file.getName() + " class file.");
@@ -348,6 +351,11 @@
                 appendHeaderContents(file, pkgString, importsList);
                 write(file, genType, EVENT_SUBJECT_CLASS, curNode, className);
                 break;
+            case GENERATE_IDENTITY_CLASS:
+                appendHeaderContents(file, pkgString, importsList);
+                write(file, genType, EVENT_SUBJECT_CLASS, curNode, className);
+                insertDataIntoJavaFile(file, CLOSE_CURLY_BRACKET);
+                break;
             default:
                 break;
         }