[ONOS-6032] target linking in yang tools

Change-Id: Ic24a7c4e395bc4452f3dc82ecc48a2115ec7909a
diff --git a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
index 1d2ebe0..1b4f6a3 100644
--- a/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
+++ b/compiler/base/datamodel/src/main/java/org/onosproject/yang/compiler/datamodel/utils/DataModelUtils.java
@@ -404,7 +404,8 @@
             objectInputStream.close();
             fileInputStream.close();
         } catch (IOException | ClassNotFoundException e) {
-            throw new IOException(serializedFileInfo + " not found.");
+            throw new IOException(serializedFileInfo + " failed to fetch " +
+                                          "nodes due to " + e.getLocalizedMessage());
         }
         return nodes;
     }
diff --git a/compiler/base/tool/src/main/java/org/onosproject/yang/compiler/tool/impl/YangCompilerManager.java b/compiler/base/tool/src/main/java/org/onosproject/yang/compiler/tool/impl/YangCompilerManager.java
index a0f7b98..b5b4120 100644
--- a/compiler/base/tool/src/main/java/org/onosproject/yang/compiler/tool/impl/YangCompilerManager.java
+++ b/compiler/base/tool/src/main/java/org/onosproject/yang/compiler/tool/impl/YangCompilerManager.java
@@ -210,6 +210,9 @@
                 // Carry out the parsing for all the YANG files.
                 parseYangFileInfoSet();
 
+                // Serialize data model.
+                processSerialization(config.resourceGenDir());
+
                 // Resolve dependencies using linker.
                 resolveDependenciesUsingLinker();
 
@@ -219,9 +222,6 @@
                 //add to generated java code map
                 processGeneratedCode(config.getCodeGenDir());
 
-                // Serialize data model.
-                processSerialization(config.resourceGenDir());
-
                 //add YANG files to JAR
                 processCopyYangFile(config.resourceGenDir());
             } catch (IOException | ParserException e) {
diff --git a/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/JavaCodeGeneratorUtil.java b/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/JavaCodeGeneratorUtil.java
index e8f3da0..73b7b78 100644
--- a/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/JavaCodeGeneratorUtil.java
+++ b/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/JavaCodeGeneratorUtil.java
@@ -16,13 +16,16 @@
 
 package org.onosproject.yang.compiler.translator.tojava;
 
+import org.onosproject.yang.compiler.datamodel.RpcNotificationContainer;
 import org.onosproject.yang.compiler.datamodel.SchemaDataNode;
 import org.onosproject.yang.compiler.datamodel.TraversalType;
 import org.onosproject.yang.compiler.datamodel.YangInput;
 import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
 import org.onosproject.yang.compiler.datamodel.YangNode;
 import org.onosproject.yang.compiler.datamodel.YangNodeType;
+import org.onosproject.yang.compiler.datamodel.YangNotification;
 import org.onosproject.yang.compiler.datamodel.YangOutput;
+import org.onosproject.yang.compiler.datamodel.YangUses;
 import org.onosproject.yang.compiler.translator.exception.InvalidNodeForTranslatorException;
 import org.onosproject.yang.compiler.translator.exception.TranslatorException;
 import org.onosproject.yang.compiler.utils.io.YangPluginConfig;
@@ -33,6 +36,8 @@
 import static org.onosproject.yang.compiler.datamodel.TraversalType.PARENT;
 import static org.onosproject.yang.compiler.datamodel.TraversalType.ROOT;
 import static org.onosproject.yang.compiler.datamodel.TraversalType.SIBLING;
+import static org.onosproject.yang.compiler.translator.tojava.YangJavaModelUtils.updateJavaInfo;
+import static org.onosproject.yang.compiler.translator.tojava.utils.JavaIdentifierSyntax.getEnumJavaAttribute;
 import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.searchAndDeleteTempDir;
 
 /**
@@ -47,16 +52,17 @@
     }
 
     /**
-     * Generates Java code files corresponding to the YANG schema.
+     * Translated YANG info to java info.
      *
-     * @param rootNode   root node of the data model tree
-     * @param yangPlugin YANG plugin config
+     * @param rootNode   root node
+     * @param yangPlugin YANG plugin configurations
+     * @param codeGen    true if code generation is required
      * @throws TranslatorException when fails to generate java code file the current node
      * @throws IOException         when fails to do IO operations
      */
-    public static void generateJavaCode(YangNode rootNode, YangPluginConfig yangPlugin)
+    public static void translate(YangNode rootNode, YangPluginConfig yangPlugin,
+                                 boolean codeGen)
             throws TranslatorException, IOException {
-
         YangNode codeGenNode = rootNode;
         TraversalType curTraversal = ROOT;
 
@@ -70,7 +76,35 @@
                                                           codeGenNode.getFileName());
                 }
                 try {
-                    generateCodeEntry(codeGenNode, yangPlugin, rootNode);
+                    if (codeGen) {
+                        generateCodeEntry(codeGenNode, yangPlugin, rootNode);
+                    } else {
+                        //for uses java info is not required so need to skip
+                        // it and go to its sibling or parent node.
+                        if (!(codeGenNode instanceof YangUses)) {
+                            //this will update java file info for the target
+                            // node.
+                            updateJavaInfo(codeGenNode, yangPlugin);
+                            if (codeGenNode instanceof YangNotification) {
+                                //to know in generated code what was the enum
+                                // name generated for current notification
+                                String enumName = getEnumJavaAttribute(codeGenNode.getName()
+                                                                               .toUpperCase());
+                                ((RpcNotificationContainer) codeGenNode.getParent())
+                                        .addToNotificationEnumMap(enumName, codeGenNode);
+                            }
+                        } else {
+                            //handle uses ,its java info is not required.
+                            if (codeGenNode.getNextSibling() != null) {
+                                curTraversal = SIBLING;
+                                codeGenNode = codeGenNode.getNextSibling();
+                            } else {
+                                curTraversal = PARENT;
+                                codeGenNode = codeGenNode.getParent();
+                            }
+                            continue;
+                        }
+                    }
                     codeGenNode.setNameSpaceAndAddToParentSchemaMap();
                     if (codeGenNode instanceof YangLeavesHolder ||
                             codeGenNode instanceof SchemaDataNode) {
@@ -96,7 +130,9 @@
                 codeGenNode = codeGenNode.getChild();
             } else if (codeGenNode.getNextSibling() != null) {
                 try {
-                    generateCodeExit(codeGenNode, yangPlugin, rootNode);
+                    if (codeGen) {
+                        generateCodeExit(codeGenNode, yangPlugin, rootNode);
+                    }
                 } catch (Exception e) {
                     e.printStackTrace();
                     close(codeGenNode, yangPlugin, rootNode);
@@ -106,7 +142,9 @@
                 codeGenNode = codeGenNode.getNextSibling();
             } else {
                 try {
-                    generateCodeExit(codeGenNode, yangPlugin, rootNode);
+                    if (codeGen) {
+                        generateCodeExit(codeGenNode, yangPlugin, rootNode);
+                    }
                 } catch (Exception e) {
                     e.printStackTrace();
                     close(codeGenNode, yangPlugin, rootNode);
@@ -119,6 +157,19 @@
     }
 
     /**
+     * Generates Java code files corresponding to the YANG schema.
+     *
+     * @param rootNode   root node of the data model tree
+     * @param yangPlugin YANG plugin config
+     * @throws TranslatorException when fails to generate java code file the current node
+     * @throws IOException         when fails to do IO operations
+     */
+    public static void generateJavaCode(YangNode rootNode, YangPluginConfig yangPlugin)
+            throws TranslatorException, IOException {
+        translate(rootNode, yangPlugin, true);
+    }
+
+    /**
      * Generates the current nodes code snippet.
      *
      * @param codeGenNode current data model node for which the code needs to be generated
diff --git a/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/YangJavaModelUtils.java b/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/YangJavaModelUtils.java
index e321595..3f2b102 100644
--- a/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/YangJavaModelUtils.java
+++ b/compiler/base/translator/src/main/java/org/onosproject/yang/compiler/translator/tojava/YangJavaModelUtils.java
@@ -26,16 +26,21 @@
 import org.onosproject.yang.compiler.datamodel.YangEnum;
 import org.onosproject.yang.compiler.datamodel.YangEnumeration;
 import org.onosproject.yang.compiler.datamodel.YangGrouping;
+import org.onosproject.yang.compiler.datamodel.YangLeaf;
+import org.onosproject.yang.compiler.datamodel.YangLeafList;
 import org.onosproject.yang.compiler.datamodel.YangLeavesHolder;
+import org.onosproject.yang.compiler.datamodel.YangModule;
 import org.onosproject.yang.compiler.datamodel.YangNode;
 import org.onosproject.yang.compiler.datamodel.YangNodeIdentifier;
 import org.onosproject.yang.compiler.datamodel.YangRpc;
 import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.compiler.datamodel.YangSubModule;
 import org.onosproject.yang.compiler.datamodel.YangTranslatorOperatorNode;
 import org.onosproject.yang.compiler.datamodel.YangType;
 import org.onosproject.yang.compiler.datamodel.YangTypeHolder;
 import org.onosproject.yang.compiler.datamodel.exceptions.DataModelException;
 import org.onosproject.yang.compiler.translator.exception.TranslatorException;
+import org.onosproject.yang.compiler.translator.tojava.javamodel.JavaLeafInfoContainer;
 import org.onosproject.yang.compiler.translator.tojava.javamodel.YangJavaAugmentTranslator;
 import org.onosproject.yang.compiler.translator.tojava.javamodel.YangJavaEnumerationTranslator;
 import org.onosproject.yang.compiler.translator.tojava.javamodel.YangJavaInputTranslator;
@@ -55,6 +60,7 @@
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.isRpcChildNodePresent;
 import static org.onosproject.yang.compiler.translator.tojava.GeneratedJavaFileType.GENERATE_ENUM_CLASS;
 import static org.onosproject.yang.compiler.translator.tojava.GeneratedJavaFileType.GENERATE_SERVICE_AND_MANAGER;
+import static org.onosproject.yang.compiler.translator.tojava.JavaQualifiedTypeInfoTranslator.updateLeavesJavaQualifiedInfo;
 import static org.onosproject.yang.compiler.translator.tojava.TempJavaFragmentFiles.addCurNodeInfoInParentTempFile;
 import static org.onosproject.yang.compiler.translator.tojava.utils.JavaFileGenerator.generateInterfaceFile;
 import static org.onosproject.yang.compiler.translator.tojava.utils.JavaIdentifierSyntax.getRootPackage;
@@ -787,4 +793,57 @@
                                                  false));
         insertDataIntoJavaFile(interFace, CLOSE_CURLY_BRACKET);
     }
+
+    /**
+     * Updates java file info for nodes in target linking.
+     *
+     * @param node   node
+     * @param config plugin config
+     */
+    static void updateJavaInfo(YangNode node, YangPluginConfig config) {
+        if (node instanceof YangModule) {
+            //handle module
+            YangModule module = (YangModule) node;
+            String modulePkg = getRootPackage(module.getVersion(),
+                                              module.getModuleNamespace(),
+                                              module.getRevision(),
+                                              null);
+            updatePackageInfo((JavaCodeGeneratorInfo) node, config, modulePkg);
+        } else if (node instanceof YangSubModule) {
+            //handle submodule
+            YangJavaSubModuleTranslator subModule = (YangJavaSubModuleTranslator) node;
+            String subModulePkg = getRootPackage(
+                    subModule.getVersion(), subModule.getNameSpaceFromModule(),
+                    subModule.getRevision(),
+                    null);
+            updatePackageInfo((JavaCodeGeneratorInfo) node, config, subModulePkg);
+        } else {
+            //handle other nodes and also handle grouping
+            if (node.getReferredSchema() != null) {
+                //in case of grouping in normal case we generate java file
+                // info for node even before cloning so when we clone the
+                // actual java file info will be cloned but in this case we
+                // will clone first so in the cloned node , we have to update
+                // the actual java file info for correct operations. because
+                // code will be generated only for actual node.
+                YangNode n = (YangNode) getRefSchema((JavaCodeGeneratorInfo) node);
+                if (n != null) {
+                    updatePackageInfo((JavaCodeGeneratorInfo) n, config);
+                    ((JavaCodeGeneratorInfo) node).setJavaFileInfo(
+                            ((JavaCodeGeneratorInfo) n).getJavaFileInfo());
+                }
+            } else {
+                updatePackageInfo((JavaCodeGeneratorInfo) node, config);
+            }
+        }
+        if (node instanceof YangLeavesHolder) {
+            YangLeavesHolder holder = (YangLeavesHolder) node;
+            for (YangLeaf leaf : holder.getListOfLeaf()) {
+                updateLeavesJavaQualifiedInfo((JavaLeafInfoContainer) leaf);
+            }
+            for (YangLeafList leaf : holder.getListOfLeafList()) {
+                updateLeavesJavaQualifiedInfo((JavaLeafInfoContainer) leaf);
+            }
+        }
+    }
 }
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java b/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java
index 4139fc4..deecbbc 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/RuntimeHelper.java
@@ -16,15 +16,23 @@
 
 package org.onosproject.yang.runtime.helperutils;
 
+import org.onosproject.yang.compiler.datamodel.YangDeviationHolder;
 import org.onosproject.yang.compiler.datamodel.YangNode;
 import org.onosproject.yang.compiler.datamodel.YangSchemaNode;
+import org.onosproject.yang.compiler.linker.YangLinker;
+import org.onosproject.yang.compiler.linker.impl.YangLinkerManager;
+import org.onosproject.yang.compiler.utils.io.YangPluginConfig;
 import org.onosproject.yang.model.YangModel;
 import org.onosproject.yang.model.YangModule;
+import org.slf4j.Logger;
 
+import java.io.IOException;
 import java.util.HashSet;
 import java.util.Set;
 
+import static org.onosproject.yang.compiler.translator.tojava.JavaCodeGeneratorUtil.translate;
 import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.getYangModel;
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * Represents utility for runtime. These utilities can be used by application
@@ -33,11 +41,11 @@
  */
 public final class RuntimeHelper {
 
-    public static final String OP_PARAM = "OpParam";
     public static final String PERIOD = ".";
-    public static final String SERVICE = "Service";
+    private static final String SERVICE = "Service";
     public static final String DEFAULT_CAPS = "Default";
     public static final String UNDER_SCORE = "_";
+    private static final Logger log = getLogger(RuntimeHelper.class);
 
     // Forbid construction.
     private RuntimeHelper() {
@@ -65,9 +73,32 @@
             YangModuleExtendedInfo ex = (YangModuleExtendedInfo) info;
             nodes.add(ex.getSchema());
         }
-        return nodes;
+        //Target linking.
+        return addLinkerAndJavaInfo(nodes);
     }
 
+    /**
+     * Adds linker and translator info for each data model tree.
+     *
+     * @param nodes YANG node
+     */
+    public static Set<YangNode> addLinkerAndJavaInfo(Set<YangNode> nodes) {
+        YangLinker yangLinker = new YangLinkerManager();
+        //Do the linking.
+        yangLinker.resolveDependencies(nodes);
+
+        //add the java info.
+        for (YangNode node : nodes) {
+            if (!((YangDeviationHolder) node).isModuleForDeviation()) {
+                try {
+                    translate(node, new YangPluginConfig(), false);
+                } catch (IOException e) {
+                    log.error("failed to target link node {},", node.getName());
+                }
+            }
+        }
+        return nodes;
+    }
 
     /**
      * Returns schema node's generated interface class name.
@@ -81,16 +112,6 @@
     }
 
     /**
-     * Returns schema node's generated op param class name.
-     *
-     * @param schemaNode schema node
-     * @return schema node's generated op param class name
-     */
-    public static String getOpParamClassName(YangSchemaNode schemaNode) {
-        return getInterfaceClassName(schemaNode) + OP_PARAM;
-    }
-
-    /**
      * Returns schema node's generated service class name.
      *
      * @param schemaNode schema node
diff --git a/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/YangApacheUtils.java b/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/YangApacheUtils.java
index 439334a..8cf6fc9 100644
--- a/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/YangApacheUtils.java
+++ b/runtime/src/main/java/org/onosproject/yang/runtime/helperutils/YangApacheUtils.java
@@ -138,15 +138,26 @@
      */
     private static String getJarPathFromBundleLocation(String mvnLocationPath,
                                                        String currentDirectory) {
-        String path = currentDirectory + SYSTEM;
+        StringBuilder builder = new StringBuilder();
+        builder.append(currentDirectory).append(SYSTEM);
+        StringBuilder ver = new StringBuilder();
         if (mvnLocationPath.contains(MAVEN)) {
             String[] strArray = mvnLocationPath.split(MAVEN);
             if (strArray[1].contains(File.separator)) {
                 String[] split = strArray[1].split(File.separator);
                 if (split[0].contains(PERIOD)) {
                     String[] groupId = split[0].split(Pattern.quote(PERIOD));
-                    return path + groupId[0] + SLASH + groupId[1] + SLASH + split[1] +
-                            SLASH + split[2] + SLASH + split[1] + HYPHEN + split[2];
+
+                    for (String s : groupId) {
+                        builder.append(s).append(SLASH);
+                    }
+                    for (int i = 1; i < split.length; i++) {
+                        builder.append(split[i]).append(SLASH);
+                        ver.append(split[i]).append(HYPHEN);
+                    }
+                    builder.append(ver);
+                    builder.deleteCharAt(builder.length() - 1);
+                    return builder.toString();
                 }
             }
         }
diff --git a/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java b/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java
index 1d62cb7..e1fdc5e 100644
--- a/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java
+++ b/runtime/src/test/java/org/onosproject/yang/runtime/impl/TestYangSchemaNodeProvider.java
@@ -36,6 +36,7 @@
 import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.processYangModel;
 import static org.onosproject.yang.compiler.utils.UtilConstants.TEMP;
 import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.deleteDirectory;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.addLinkerAndJavaInfo;
 import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getInterfaceClassName;
 
 /**
@@ -67,6 +68,7 @@
         try {
             //Need to deserialize generated meta data file for unit tests.
             Set<YangNode> appNode = deSerializeDataModel(META_PATH);
+            addLinkerAndJavaInfo(appNode);
             nodes.addAll(appNode);
             reg.registerModel(prepareParam(nodes));
             deleteDirectory(TEMP_FOLDER_PATH);
diff --git a/serializers/json/src/test/java/org/onosproject/yang/serializers/json/MockYangSchemaNodeProvider.java b/serializers/json/src/test/java/org/onosproject/yang/serializers/json/MockYangSchemaNodeProvider.java
index c45d18a..d9832ca 100644
--- a/serializers/json/src/test/java/org/onosproject/yang/serializers/json/MockYangSchemaNodeProvider.java
+++ b/serializers/json/src/test/java/org/onosproject/yang/serializers/json/MockYangSchemaNodeProvider.java
@@ -34,6 +34,7 @@
 import java.util.Set;
 
 import static org.onosproject.yang.compiler.datamodel.utils.DataModelUtils.deSerializeDataModel;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.addLinkerAndJavaInfo;
 import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.processModuleId;
 import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.processYangModel;
 import static org.onosproject.yang.compiler.utils.UtilConstants.TEMP;
@@ -69,6 +70,7 @@
         try {
             //Need to deserialize generated meta data file for unit tests.
             Set<YangNode> appNode = deSerializeDataModel(META_PATH);
+            addLinkerAndJavaInfo(appNode);
             nodes.addAll(appNode);
             reg.registerModel(prepareParam(nodes));
             deleteDirectory(TEMP_FOLDER_PATH);
diff --git a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
index af897d5..9a899b7 100644
--- a/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
+++ b/serializers/xml/src/test/java/org/onosproject/yang/serializers/xml/MockYangSchemaNodeProvider.java
@@ -38,6 +38,7 @@
 import static org.onosproject.yang.runtime.helperutils.YangApacheUtils.processYangModel;
 import static org.onosproject.yang.compiler.utils.UtilConstants.TEMP;
 import static org.onosproject.yang.compiler.utils.io.impl.YangIoUtils.deleteDirectory;
+import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.addLinkerAndJavaInfo;
 import static org.onosproject.yang.runtime.helperutils.RuntimeHelper.getInterfaceClassName;
 
 /**
@@ -69,6 +70,7 @@
         try {
             //Need to deserialize generated meta data file for unit tests.
             Set<YangNode> appNode = deSerializeDataModel(META_PATH);
+            addLinkerAndJavaInfo(appNode);
             nodes.addAll(appNode);
             reg.registerModel(prepareParam(nodes));
             deleteDirectory(TEMP_FOLDER_PATH);