[ONOS-5695] notification defect fix

Change-Id: I5f2a7e857975244061e969dd248878b3f2ecda44
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/ych/DefaultYangCodecHandler.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/ych/DefaultYangCodecHandler.java
index 8847c41..3e990be 100644
--- a/apps/yms/app/src/main/java/org/onosproject/yms/app/ych/DefaultYangCodecHandler.java
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/ych/DefaultYangCodecHandler.java
@@ -16,6 +16,10 @@
 
 package org.onosproject.yms.app.ych;
 
+import org.onosproject.yangutils.datamodel.YangSchemaNode;
+import org.onosproject.yangutils.datamodel.YangSchemaNodeContextInfo;
+import org.onosproject.yangutils.datamodel.YangSchemaNodeIdentifier;
+import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
 import org.onosproject.yms.app.ych.defaultcodecs.YangCodecRegistry;
 import org.onosproject.yms.app.ydt.YdtExtendedBuilder;
 import org.onosproject.yms.app.ydt.YdtExtendedContext;
@@ -37,6 +41,8 @@
 import java.util.List;
 import java.util.Map;
 
+import static org.onosproject.yms.app.yob.YobUtils.createAndSetInEventInstance;
+import static org.onosproject.yms.app.yob.YobUtils.createAndSetInEventSubjectInstance;
 
 /**
  * Represents implementation of YANG SBI broker interfaces.
@@ -48,6 +54,10 @@
             "sub-module object list cannot be null.";
     private static final String E_DATA_TREE_CODEC = "data tree codec handler" +
             " is null.";
+    private static final String E_DATA_MODEL_CHILD = "Unable to find the " +
+            "child node";
+    private static final String E_NOTIFICATION_NODE = "Notification node " +
+            "should be the first child of module in YDT";
 
     /**
      * Schema registry for driver.
@@ -214,6 +224,14 @@
                                                        schemaRegistry,
                                                        opType);
 
+        YdtExtendedContext rootNode = ((YdtExtendedContext) ydtBuilder
+                .getRootNode());
+
+        if (opType == YmsOperationType.NOTIFICATION) {
+            return getNotificationObject(((YdtExtendedContext) rootNode
+                    .getFirstChild()));
+        }
+
         // Get the module object by using YANG data tree
         if (ydtBuilder != null) {
             return getObjectList(ydtBuilder.getRootNode());
@@ -222,6 +240,39 @@
         return null;
     }
 
+    //returns notification event object
+    private Object getNotificationObject(YdtExtendedContext rootNode) {
+        YangSchemaNode module = rootNode.getYangSchemaNode();
+        YangSchemaNode childSchema = ((YdtExtendedContext) rootNode
+                .getFirstChild()).getYangSchemaNode();
+
+        YangSchemaNodeIdentifier id = new YangSchemaNodeIdentifier();
+        id.setNameSpace(childSchema.getNameSpace());
+        id.setName(childSchema.getName());
+
+        YangSchemaNodeContextInfo contextInfo;
+        try {
+            contextInfo = module.getChildSchema(id);
+        } catch (DataModelException e) {
+            throw new YchException(E_DATA_MODEL_CHILD);
+        }
+
+        if (contextInfo == null) {
+            throw new YchException(E_NOTIFICATION_NODE);
+        }
+
+        DefaultYobBuilder builder = new DefaultYobBuilder();
+        Object object = builder.getYangObject(((YdtExtendedContext) rootNode
+                                                      .getFirstChild()),
+                                              schemaRegistry);
+
+        Object eventSubObj = createAndSetInEventSubjectInstance(object,
+                                                                rootNode,
+                                                                schemaRegistry);
+        return createAndSetInEventInstance(eventSubObj, rootNode,
+                                           schemaRegistry);
+    }
+
     @Override
     public void registerOverriddenCodec(YangDataTreeCodec overrideCodec,
                                         YangProtocolEncodingFormat dataFormat) {
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YdtSingleInstanceLeafNode.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YdtSingleInstanceLeafNode.java
index 44de72e..be80ec2 100644
--- a/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YdtSingleInstanceLeafNode.java
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/ydt/YdtSingleInstanceLeafNode.java
@@ -27,7 +27,7 @@
  * Represents YDT single instance leaf node which is an atomic element
  * and doesn't have any child.
  */
-class YdtSingleInstanceLeafNode extends YdtNode {
+public class YdtSingleInstanceLeafNode extends YdtNode {
 
     /*
      * Value of the leaf.
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobConstants.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobConstants.java
index cf2638e..7c38e6c 100644
--- a/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobConstants.java
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobConstants.java
@@ -40,6 +40,9 @@
     static final String JAVA_LANG = "java.lang";
     static final String LEAF_IDENTIFIER = "LeafIdentifier";
     static final String SELECT_LEAF = "selectLeaf";
+    static final String EVENT_SUBJECT = "EventSubject";
+    static final String EVENT = "Event";
+    static final String TYPE = "Type";
 
     //Error strings
     static final String E_NO_HANDLE_FOR_YDT = "No handler for YDT node";
diff --git a/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobUtils.java b/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobUtils.java
index c4cbfc5..54bb37f 100644
--- a/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobUtils.java
+++ b/apps/yms/app/src/main/java/org/onosproject/yms/app/yob/YobUtils.java
@@ -35,6 +35,7 @@
 import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.math.BigDecimal;
@@ -42,26 +43,37 @@
 import java.util.Base64;
 
 import static org.onosproject.yangutils.datamodel.YangSchemaNodeType.YANG_AUGMENT_NODE;
+import static org.onosproject.yangutils.translator.tojava.utils.JavaIdentifierSyntax.getEnumJavaAttribute;
 import static org.onosproject.yms.app.ydt.AppType.YOB;
 import static org.onosproject.yms.app.yob.YobConstants.DEFAULT;
+import static org.onosproject.yms.app.yob.YobConstants.EVENT;
+import static org.onosproject.yms.app.yob.YobConstants.EVENT_SUBJECT;
 import static org.onosproject.yms.app.yob.YobConstants.E_DATA_TYPE_NOT_SUPPORT;
+import static org.onosproject.yms.app.yob.YobConstants.E_FAIL_TO_CREATE_OBJ;
+import static org.onosproject.yms.app.yob.YobConstants.E_FAIL_TO_GET_FIELD;
+import static org.onosproject.yms.app.yob.YobConstants.E_FAIL_TO_GET_METHOD;
+import static org.onosproject.yms.app.yob.YobConstants.E_FAIL_TO_INVOKE_METHOD;
 import static org.onosproject.yms.app.yob.YobConstants.E_FAIL_TO_LOAD_CLASS;
 import static org.onosproject.yms.app.yob.YobConstants.E_FAIL_TO_LOAD_CONSTRUCTOR;
 import static org.onosproject.yms.app.yob.YobConstants.E_INVALID_DATA_TREE;
 import static org.onosproject.yms.app.yob.YobConstants.E_INVALID_EMPTY_DATA;
 import static org.onosproject.yms.app.yob.YobConstants.FROM_STRING;
 import static org.onosproject.yms.app.yob.YobConstants.LEAF_IDENTIFIER;
+import static org.onosproject.yms.app.yob.YobConstants.L_FAIL_TO_GET_FIELD;
+import static org.onosproject.yms.app.yob.YobConstants.L_FAIL_TO_GET_METHOD;
+import static org.onosproject.yms.app.yob.YobConstants.L_FAIL_TO_INVOKE_METHOD;
 import static org.onosproject.yms.app.yob.YobConstants.L_FAIL_TO_LOAD_CLASS;
 import static org.onosproject.yms.app.yob.YobConstants.OF;
 import static org.onosproject.yms.app.yob.YobConstants.OP_PARAM;
 import static org.onosproject.yms.app.yob.YobConstants.PERIOD;
 import static org.onosproject.yms.app.yob.YobConstants.SELECT_LEAF;
+import static org.onosproject.yms.app.yob.YobConstants.TYPE;
 import static org.onosproject.yms.app.yob.YobConstants.VALUE_OF;
 
 /**
  * Utils to support object creation.
  */
-final class YobUtils {
+public final class YobUtils {
 
     private static final Logger log = LoggerFactory.getLogger(YobUtils.class);
 
@@ -631,4 +643,142 @@
 
         parentSetterMethod.invoke(parentBuilderObject, childValue);
     }
+
+    /**
+     * Creates and sets default notification object in event subject object.
+     *
+     * @param defaultObj default notification object
+     * @param curNode    application context
+     * @param registry   YANG schema registry
+     * @return notification event subject object
+     */
+    public static Object createAndSetInEventSubjectInstance(Object defaultObj,
+                                                            YdtExtendedContext curNode,
+                                                            YangSchemaRegistry registry) {
+        YangSchemaNode childSchema = ((YdtExtendedContext) curNode
+                .getFirstChild()).getYangSchemaNode();
+        String packageName = childSchema.getJavaPackage();
+        String className = getCapitalCase(curNode.getYangSchemaNode()
+                                                  .getJavaClassNameOrBuiltInType());
+        String qualName = packageName + PERIOD + className + EVENT_SUBJECT;
+
+        ClassLoader classLoader = YobUtils.getClassLoader(registry, qualName,
+                                                          curNode, curNode);
+
+        Object eventSubObj;
+        Class<?> eventSubjectClass = null;
+        try {
+            eventSubjectClass = classLoader.loadClass(qualName);
+            eventSubObj = eventSubjectClass.newInstance();
+        } catch (ClassNotFoundException e) {
+            log.error(E_FAIL_TO_LOAD_CLASS, className);
+            throw new YobException(E_FAIL_TO_LOAD_CLASS +
+                                           eventSubjectClass.getName());
+        } catch (InstantiationException e) {
+            log.error(E_FAIL_TO_CREATE_OBJ, className);
+            throw new YobException(E_FAIL_TO_CREATE_OBJ +
+                                           eventSubjectClass.getName());
+        } catch (IllegalAccessException e) {
+            log.error(L_FAIL_TO_INVOKE_METHOD, className);
+            throw new YobException(E_FAIL_TO_INVOKE_METHOD +
+                                           eventSubjectClass.getName());
+        }
+
+        setInEventSubject(((YdtExtendedContext) curNode.getFirstChild()),
+                          eventSubObj, defaultObj);
+        return eventSubObj;
+    }
+
+    /**
+     * Sets the default notification object in event subject class.
+     *
+     * @param ydtNode     application context
+     * @param eventSubObj notification event subject instance
+     * @param defaultObj  default notification instance
+     */
+    public static void setInEventSubject(YdtExtendedContext ydtNode,
+                                         Object eventSubObj,
+                                         Object defaultObj) {
+
+        Class<?> eventSubjectClass = eventSubObj.getClass();
+        String className = eventSubjectClass.getName();
+        String setter = ydtNode.getYangSchemaNode().getJavaAttributeName();
+
+        try {
+            Class<?> type = null;
+            Field fieldName = eventSubjectClass.getDeclaredField(setter);
+            if (fieldName != null) {
+                type = fieldName.getType();
+            }
+
+            Method method;
+            method = eventSubjectClass.getDeclaredMethod(setter, type);
+            method.invoke(eventSubObj, defaultObj);
+        } catch (NoSuchFieldException e) {
+            log.error(L_FAIL_TO_GET_FIELD, className);
+            throw new YobException(E_FAIL_TO_GET_FIELD + className);
+        } catch (NoSuchMethodException e) {
+            log.error(L_FAIL_TO_GET_METHOD, className);
+            throw new YobException(E_FAIL_TO_GET_METHOD + className);
+        } catch (InvocationTargetException | IllegalAccessException e) {
+            log.error(L_FAIL_TO_INVOKE_METHOD, className);
+            throw new YobException(E_FAIL_TO_INVOKE_METHOD + className);
+        }
+    }
+
+    /**
+     * Creates an object of notification event class and sets event subject
+     * in event class.
+     *
+     * @param eventSubObj instance of event subject class
+     * @param curNode     current YDT node
+     * @param registry    YANG schema registry
+     * @return notification event object
+     */
+    public static Object createAndSetInEventInstance(Object eventSubObj,
+                                                     YdtExtendedContext curNode,
+                                                     YangSchemaRegistry registry) {
+        YangSchemaNode childSchema = ((YdtExtendedContext) curNode
+                .getFirstChild()).getYangSchemaNode();
+        String packageName = childSchema.getJavaPackage();
+        String className = getCapitalCase(curNode.getYangSchemaNode()
+                                                  .getJavaClassNameOrBuiltInType());
+        String qualName = packageName + PERIOD + className + EVENT;
+
+        try {
+            ClassLoader classLoader = YobUtils.getClassLoader(registry, qualName,
+                                                              curNode, curNode);
+            Class<?> eventClass = classLoader.loadClass(qualName);
+            Class<?>[] innerClasses = eventClass.getClasses();
+            Object typeObj = null;
+            for (Class<?> innerEnumClass : innerClasses) {
+                if (innerEnumClass.getSimpleName().equals(TYPE)) {
+                    Method valueOfMethod = innerEnumClass
+                            .getDeclaredMethod(VALUE_OF, String.class);
+                    String eventType = getEnumJavaAttribute(childSchema.getName())
+                            .toUpperCase();
+                    typeObj = valueOfMethod.invoke(null, eventType);
+                    break;
+                }
+            }
+
+            Constructor constructor = eventClass
+                    .getDeclaredConstructor(typeObj.getClass(),
+                                            eventSubObj.getClass());
+            constructor.setAccessible(true);
+            return constructor.newInstance(typeObj, eventSubObj);
+        } catch (ClassNotFoundException e) {
+            log.error(L_FAIL_TO_INVOKE_METHOD, className);
+            throw new YobException(E_FAIL_TO_INVOKE_METHOD + className);
+        } catch (InstantiationException e) {
+            log.error(E_FAIL_TO_CREATE_OBJ, className);
+            throw new YobException(E_FAIL_TO_CREATE_OBJ + className);
+        } catch (NoSuchMethodException e) {
+            log.error(L_FAIL_TO_GET_METHOD, className);
+            throw new YobException(E_FAIL_TO_GET_METHOD + className);
+        } catch (InvocationTargetException | IllegalAccessException e) {
+            log.error(L_FAIL_TO_INVOKE_METHOD, className);
+            throw new YobException(E_FAIL_TO_INVOKE_METHOD + className);
+        }
+    }
 }