YANG Translator optimization

Change-Id: Ie6a6b9d371a4fc5fd973cf56d6f3c7b44a3146ba
diff --git a/utils/yangutils/src/main/java/org/onosproject/yangutils/translator/tojava/JavaQualifiedTypeInfo.java b/utils/yangutils/src/main/java/org/onosproject/yangutils/translator/tojava/JavaQualifiedTypeInfo.java
new file mode 100644
index 0000000..ba4b99b
--- /dev/null
+++ b/utils/yangutils/src/main/java/org/onosproject/yangutils/translator/tojava/JavaQualifiedTypeInfo.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2016 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;
+
+import java.util.Objects;
+
+import org.onosproject.yangutils.datamodel.YangNode;
+import org.onosproject.yangutils.datamodel.YangType;
+import org.onosproject.yangutils.translator.tojava.utils.AttributesJavaDataType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Maintains the information about individual imports in the generated file.
+ */
+public class JavaQualifiedTypeInfo implements Comparable<JavaQualifiedTypeInfo> {
+
+    /**
+     * Package location where the imported class/interface is defined.
+     */
+    private String pkgInfo;
+
+    /**
+     * Class/interface being referenced.
+     */
+    private String classInfo;
+
+    /**
+     * Default constructor.
+     */
+    public JavaQualifiedTypeInfo() {
+    }
+
+    /**
+     * Get the imported package info.
+     *
+     * @return the imported package info
+     */
+    public String getPkgInfo() {
+
+        return pkgInfo;
+    }
+
+    /**
+     * Set the imported package info.
+     *
+     * @param pkgInfo the imported package info
+     */
+    public void setPkgInfo(String pkgInfo) {
+
+        this.pkgInfo = pkgInfo;
+    }
+
+    /**
+     * Get the imported class/interface info.
+     *
+     * @return the imported class/interface info
+     */
+    public String getClassInfo() {
+
+        return classInfo;
+    }
+
+    /**
+     * Set the imported class/interface info.
+     *
+     * @param classInfo the imported class/interface info
+     */
+    public void setClassInfo(String classInfo) {
+
+        this.classInfo = classInfo;
+    }
+
+    /**
+     * Get the import info for an attribute, which needs to be used for code
+     * generation for import or for qualified access.
+     *
+     * @param curNode current data model node for which the java file is being
+     *            generated.
+     * @param attrType type of attribute being added, it will be null, when the
+     *            child class is added as an attribute
+     * @param attributeName name of the attribute being added, it will used in
+     *            import info for child class.
+     * @param isListAttr is the added attribute going to be used as a list
+     * @return return the import info for this attribute
+     */
+    public static JavaQualifiedTypeInfo getQualifiedTypeInfoOfLeafAttribute(YangNode curNode,
+            YangType<?> attrType, String attributeName,
+            boolean isListAttr) {
+
+        JavaQualifiedTypeInfo importInfo = new JavaQualifiedTypeInfo();
+
+        if (attrType == null) {
+            throw new RuntimeException("missing data type of leaf " + attributeName);
+        }
+
+        /*
+         * Current leaves holder is adding a leaf info as a attribute to the
+         * current class.
+         */
+        String className = AttributesJavaDataType.getJavaImportClass(attrType, isListAttr);
+        if (className != null) {
+            /*
+             * Corresponding to the attribute type a class needs to be imported,
+             * since it can be a derived type or a usage of wrapper classes.
+             */
+            importInfo.setClassInfo(className);
+            String classPkg = AttributesJavaDataType.getJavaImportPackage(attrType, isListAttr, className);
+            if (classPkg == null) {
+                throw new RuntimeException("import package cannot be null when the class is used");
+            }
+            importInfo.setPkgInfo(classPkg);
+        } else {
+            /*
+             * The attribute does not need a class to be imported, for example
+             * built in java types.
+             */
+            String dataTypeName = AttributesJavaDataType.getJavaDataType(attrType);
+            if (dataTypeName == null) {
+                throw new RuntimeException("not supported data type");
+            }
+            importInfo.setClassInfo(dataTypeName);
+        }
+        return importInfo;
+    }
+
+    /**
+     * Get the import info for an attribute, which needs to be used for code
+     * generation for import or for qualified access.
+     *
+     * @param curNode current data model node for which the java file is being
+     *            generated.
+     * @param attributeName name of the attribute being added, it will used in
+     *            import info for child class.
+     * @param isListAttr is the added attribute going to be used as a list
+     * @return return the import info for this attribute
+     */
+    public static JavaQualifiedTypeInfo getQualifiedTypeInfoOfCurNode(YangNode curNode,
+            String attributeName, boolean isListAttr) {
+
+        JavaQualifiedTypeInfo importInfo = new JavaQualifiedTypeInfo();
+
+        if (!(curNode instanceof HasJavaFileInfo)) {
+            throw new RuntimeException("missing java file information to get the package details "
+                    + "of attribute corresponding to child node");
+        }
+        /*
+         * The scenario when we need to add the child class as an attribute in
+         * the current class. The child class is in the package of the current
+         * classes package with current classes name.
+         */
+        importInfo.setClassInfo(attributeName);
+        importInfo.setPkgInfo((((HasJavaFileInfo) curNode).getJavaFileInfo().getPackage() + "."
+                + ((HasJavaFileInfo) curNode).getJavaFileInfo().getJavaName()).toLowerCase());
+
+        return importInfo;
+    }
+
+    /**
+     * Get if the attribute needs to be accessed in a qualified manner or not,
+     * if it needs to be imported, then the same needs to be done.
+     *
+     * @param curNode current cache of the data model node for which java file
+     *            is bing generated
+     * @param importInfo import info for the current attribute being added
+     * @return status of the qualified access to the attribute
+     */
+    public static boolean getIsQualifiedAccessOrAddToImportList(YangNode curNode,
+            JavaQualifiedTypeInfo importInfo) {
+
+        boolean isImportPkgEqualCurNodePkg;
+        if (!(curNode instanceof HasJavaFileInfo)) {
+            throw new RuntimeException("missing java file info for getting the qualified access");
+        }
+        if (importInfo.getClassInfo().contentEquals(
+                ((HasJavaFileInfo) curNode).getJavaFileInfo().getJavaName())) {
+            /*
+             * if the current class name is same as the attribute class name,
+             * then the attribute must be accessed in a qualified manner.
+             */
+            return true;
+        } else if (importInfo.getPkgInfo() != null) {
+            /*
+             * If the attribute type is having the package info, it is contender
+             * for import list and also need to check if it needs to be a
+             * qualified access.
+             */
+            isImportPkgEqualCurNodePkg = isImportPkgEqualCurNodePkg(curNode, importInfo);
+            if (!isImportPkgEqualCurNodePkg) {
+                /*
+                 * If the package of the attribute added is not same as the
+                 * current class package, then it must either be imported for
+                 * access or it must be a qualified access.
+                 */
+                if (!(curNode instanceof HasJavaImportData)) {
+                    /*
+                     * If the current data model node is not supposed to import
+                     * data, then this is a usage issue and needs to be fixed.
+                     */
+                    throw new RuntimeException("Current node needs to support Imports");
+                }
+
+                boolean isImportAdded = ((HasJavaImportData) curNode).getJavaImportData()
+                        .addImportInfo(curNode, importInfo);
+                if (!isImportAdded) {
+                    /*
+                     * If the attribute type info is not imported, then it must
+                     * be a qualified access.
+                     */
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check if the import info is same as the package of the current generated
+     * java file.
+     *
+     * @param curNode Java identifier of the current data model node
+     * @param importInfo import info for an attribute
+     * @return true if the import info is same as the current nodes package
+     *         false otherwise
+     */
+    public static boolean isImportPkgEqualCurNodePkg(
+            YangNode curNode, JavaQualifiedTypeInfo importInfo) {
+
+        if (!(curNode instanceof HasJavaFileInfo)) {
+            throw new RuntimeException("missing java file info for the data model node");
+        }
+        return ((HasJavaFileInfo) curNode).getJavaFileInfo().getPackage()
+                .contentEquals(importInfo.getPkgInfo()
+                        + "." + importInfo.getClassInfo());
+    }
+
+    @Override
+    public int hashCode() {
+
+        return Objects.hash(pkgInfo, classInfo);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof JavaQualifiedTypeInfo) {
+            JavaQualifiedTypeInfo other = (JavaQualifiedTypeInfo) obj;
+            return Objects.equals(pkgInfo, other.pkgInfo) &&
+                    Objects.equals(classInfo, other.classInfo);
+        }
+        return false;
+    }
+
+    /**
+     * check if the import info matches.
+     *
+     * @param importInfo matched import
+     * @return if equal or not
+     */
+    public boolean exactMatch(JavaQualifiedTypeInfo importInfo) {
+
+        return equals(importInfo)
+                && Objects.equals(pkgInfo, importInfo.getPkgInfo())
+                && Objects.equals(classInfo, importInfo.getClassInfo());
+    }
+
+    @Override
+    public String toString() {
+
+        return MoreObjects.toStringHelper(getClass())
+                .add("pkgInfo", pkgInfo)
+                .add("classInfo", classInfo).toString();
+    }
+
+    /**
+     * Check that there is no 2 objects with the same class name.
+     *
+     * @param other compared import info.
+     */
+    @Override
+    public int compareTo(JavaQualifiedTypeInfo other) {
+
+        return getClassInfo().compareTo(other.getClassInfo());
+    }
+
+}