/*
 * 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.yms.app.ysr;

import org.onosproject.yangutils.datamodel.RpcNotificationContainer;
import org.onosproject.yangutils.datamodel.YangInclude;
import org.onosproject.yangutils.datamodel.YangModule;
import org.onosproject.yangutils.datamodel.YangNode;
import org.onosproject.yangutils.datamodel.YangSchemaNode;
import org.onosproject.yangutils.datamodel.YangSubModule;
import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
import org.onosproject.yms.ysr.YangModuleIdentifier;
import org.onosproject.yms.ysr.YangModuleInformation;
import org.onosproject.yms.ysr.YangModuleLibrary;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;

import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.parseJarFile;
import static org.onosproject.yangutils.utils.UtilConstants.DEFAULT;
import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
import static org.onosproject.yangutils.utils.UtilConstants.EVENT_STRING;
import static org.onosproject.yangutils.utils.UtilConstants.OP_PARAM;
import static org.onosproject.yangutils.utils.UtilConstants.PERIOD;
import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
import static org.osgi.framework.FrameworkUtil.getBundle;


/**
 * Representation of default YANG schema registry. Yang schema registry
 * provides interface to an application to register its YANG schema
 * with YMS. It provides YANG schema nodes to YDT, YNB and YSB.
 */
public class DefaultYangSchemaRegistry
        implements YangSchemaRegistry {

    private static final String SYSTEM = File.separator + "system" +
            File.separator;
    private static final String MAVEN = "mvn:";
    private static final String HYPHEN = "-";
    private static final String DELIMITER = ".";
    private static final String SERVICE = "Service";
    private static final String JAR = ".jar";
    private static final String USER_DIRECTORY = "user.dir";
    private static final String SLASH = File.separator;
    private static final String AT = "@";
    private static final String DATE_FORMAT = "yyyy-mm-dd";
    private static final Logger log =
            LoggerFactory.getLogger(DefaultYangSchemaRegistry.class);
    private final ConcurrentMap<String, YsrAppContext> appObjectStore;
    private final ConcurrentMap<String, YsrAppContext> yangSchemaStore;
    private final ConcurrentMap<String, YsrAppContext>
            yangSchemaStoreForRootInterface;
    private final ConcurrentMap<String, YsrAppContext>
            yangSchemaStoreForRootOpParam;
    private final ConcurrentMap<String, YsrAppContext>
            yangRootSchemaStoreForNotification;
    private final ConcurrentMap<String, Class<?>> registerClassStore;
    private final ConcurrentMap<YangModuleIdentifier, String> yangFileStore;
    private final YangModuleLibrary library;
    private YsrAppContext ysrAppContext;
    private YsrAppContext ysrContextForSchemaStore;
    private YsrAppContext ysrContextForAppStore;
    private ClassLoader classLoader;

    /**
     * Creates an instance of default YANG schema registry.
     *
     * @param moduleId module set id of YSR module library
     */
    public DefaultYangSchemaRegistry(String moduleId) {
        appObjectStore = new ConcurrentHashMap<>();
        yangSchemaStore = new ConcurrentHashMap<>();
        yangSchemaStoreForRootInterface = new ConcurrentHashMap<>();
        yangSchemaStoreForRootOpParam = new ConcurrentHashMap<>();
        yangRootSchemaStoreForNotification = new ConcurrentHashMap<>();
        registerClassStore = new ConcurrentHashMap<>();
        yangFileStore = new ConcurrentHashMap<>();
        library = new DefaultYangModuleLibrary(moduleId);
    }


    @Override
    public void registerApplication(Object appObject, Class<?> serviceClass) {

        BundleContext bundleContext = getBundle(serviceClass)
                .getBundleContext();
        String jarPath = getJarPathFromBundleLocation(
                bundleContext.getBundle().getLocation(),
                bundleContext.getProperty(USER_DIRECTORY));
        processRegistration(serviceClass, appObject, jarPath);
    }

    /**
     * Process application registration.
     *
     * @param serviceClass service class
     * @param appObject    application object
     * @param jarPath      jar path
     */
    void processRegistration(Class<?> serviceClass, Object appObject,
                             String jarPath) {

        // set class loader for service class.
        setClassLoader(serviceClass.getClassLoader());

        //Check if service should be registered?
        if (appObject != null) {
            verifyApplicationRegistration(appObject, serviceClass);
        }
        //Add app class to registered service store.
        if (!registerClassStore.containsKey(serviceClass.getName())) {
            updateServiceClass(serviceClass);
        }

        // process storing operations.
        if (!verifyIfApplicationAlreadyRegistered(serviceClass)) {
            List<YangNode> curNodes =
                    processJarParsingOperations(jarPath);

            if (curNodes != null) {
                for (YangNode schemaNode : curNodes) {
                    //Process application context for registrations.
                    processApplicationContext(schemaNode);
                    //Update YANG file store.
                    updateYangFileStore(schemaNode, jarPath);
                    //Process module library operation for current node list.
                    processModuleLibrary(schemaNode);
                }
                //Set jar path for app context.
                ysrAppContext.jarPath(jarPath);
                ysrContextForSchemaStore.jarPath(jarPath);
                ysrContextForAppStore.jarPath(jarPath);
            }
        }

        //Verifies if object is updated for app store.
        updateApplicationObject(appObject, serviceClass);
    }

    /**
     * Verifies if service class should be registered or not.
     *
     * @param appObject application object
     * @param appClass  application class
     */
    private void verifyApplicationRegistration(Object appObject,
                                               Class<?> appClass) {
        Class<?> managerClass = appObject.getClass();
        Class<?>[] services = managerClass.getInterfaces();
        List<Class<?>> classes = new ArrayList<>();
        Collections.addAll(classes, services);
        if (!classes.contains(appClass)) {
            throw new RuntimeException("service class " + appClass.getName() +
                                               "is not being implemented by " +
                                               managerClass.getName());
        }
    }

    /**
     * Verifies if application is already registered with YMS.
     *
     * @param appClass application class
     * @return true if application already registered
     */
    private boolean verifyIfApplicationAlreadyRegistered(Class<?> appClass) {
        String simpleName = appClass.getSimpleName();
        String appName = appClass.getName();
        if (!appObjectStore.containsKey(appName)) {
            if (simpleName.contains(OP_PARAM)) {
                return yangSchemaStoreForRootOpParam
                        .containsKey(appName);
            } else {
                return yangSchemaStoreForRootInterface
                        .containsKey(appName);
            }
        }
        return true;
    }

    /**
     * Verifies if service is being implemented by some new object.
     *
     * @param appObject application's object
     * @param appClass  application's class
     */
    private void updateApplicationObject(Object appObject, Class<?> appClass) {
        YsrAppContext appContext =
                appObjectStore.get(appClass.getName());
        if (appContext != null) {
            YangSchemaNode schemaNode = appContext.curNode();
            String name = getInterfaceClassName(schemaNode);
            if (appContext.appObject() == null) {
                //update in application store.
                appContext.appObject(appObject);
                //Update app object for schema store for root interface.
                appContext = yangSchemaStoreForRootInterface.get(name);
                if (appContext != null) {
                    appContext.appObject(appObject);
                }
                // Update app object for schema store for root op param
                appContext = yangSchemaStoreForRootOpParam.get(name + OP_PARAM);
                if (appContext != null) {
                    appContext.appObject(appObject);
                }
            }
        }
    }

    @Override
    public void unRegisterApplication(Object managerObject,
                                      Class<?> serviceClass) {
        YangSchemaNode curNode = null;
        String serviceName = serviceClass.getName();

        //Check if service should be unregistered?
        if (managerObject != null) {
            verifyApplicationRegistration(managerObject, serviceClass);
        }
        //Remove registered class from store.
        registerClassStore.remove(serviceName);

        //check if service is in app store.
        if (appObjectStore.containsKey(serviceName)) {
            curNode = retrieveNodeForUnregister(serviceName, appObjectStore,
                                                managerObject);
        } else if (yangSchemaStoreForRootInterface.containsKey(serviceName)) {
            //check if service is in interface store.
            curNode = retrieveNodeForUnregister(serviceName,
                                                yangSchemaStoreForRootInterface,
                                                managerObject);
        } else if (yangSchemaStoreForRootOpParam.containsKey(serviceName)) {
            //check if service is in op param store.
            curNode = retrieveNodeForUnregister(serviceName,
                                                yangSchemaStoreForRootOpParam,
                                                managerObject);
        }
        if (curNode != null) {
            String javaName = getInterfaceClassName(curNode);
            removeFromYangSchemaStore(curNode);
            removeFromYangNotificationStore(curNode);
            removeFromAppSchemaStore(serviceName);
            removeFromYangSchemaNodeForRootInterface(javaName);
            removeFromYangSchemaNodeForRootOpParam(javaName);
            removeYangFileInfoFromStore(curNode);
            log.info(" service {} is unregistered.",
                     serviceClass.getSimpleName());
        } else {
            throw new RuntimeException(serviceClass.getSimpleName() +
                                               " service was not registered.");
        }
    }

    @Override
    public Object getRegisteredApplication(YangSchemaNode schemaNode) {
        if (schemaNode != null) {
            String name = getInterfaceClassName(schemaNode);
            if (yangSchemaStoreForRootInterface.containsKey(name)) {
                return yangSchemaStoreForRootInterface.get(name)
                        .appObject();
            }
            log.error("{} not found.", name);
        }
        return null;
    }

    @Override
    public YangSchemaNode getYangSchemaNodeUsingSchemaName(String schemaName) {
        return getSchemaNodeUsingSchemaNameWithRev(schemaName);
    }

    @Override
    public YangSchemaNode getYangSchemaNodeUsingAppName(String appName) {
        YsrAppContext appContext = appObjectStore.get(appName);
        if (appContext != null) {
            return appContext.curNode();
        }
        log.error("{} not found.", appName);
        return null;
    }

    @Override
    public YangSchemaNode
    getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName(String name) {
        YsrAppContext appContext = yangSchemaStoreForRootInterface.get(name);
        if (appContext != null) {
            return appContext.curNode();
        }
        log.error("{} not found.", name);
        return null;
    }

    @Override
    public YangSchemaNode getYangSchemaNodeUsingGeneratedRootNodeOpPramFileName(
            String name) {
        YsrAppContext appContext = yangSchemaStoreForRootOpParam.get(name);
        if (appContext != null) {
            return appContext.curNode();
        }
        log.error("{} not found.", name);
        return null;
    }

    @Override
    public YangSchemaNode getRootYangSchemaNodeForNotification(String name) {
        YsrAppContext appContext = yangRootSchemaStoreForNotification.get(name);
        if (appContext != null) {
            return appContext.curNode();
        }
        log.error("{} not found.", name);
        return null;
    }

    @Override
    public Class<?> getRegisteredClass(YangSchemaNode schemaNode,
                                       String appName) {
        String interfaceName = getInterfaceClassName(schemaNode);
        String serviceName = getServiceName(schemaNode);
        String defaultClass;
        if (schemaNode instanceof RpcNotificationContainer) {
            defaultClass = getOpParamClassName(schemaNode);
        } else {
            defaultClass = getDefaultClassName(schemaNode);
        }
        //If application class is registered.
        if (registerClassStore.containsKey(appName)) {
            return registerClassStore.get(appName);
        } else if (registerClassStore.containsKey(interfaceName)) {
            //If interface class is registered.
            return registerClassStore.get(interfaceName);
        } else if (registerClassStore.containsKey(serviceName)) {
            //If service class is registered.
            return registerClassStore.get(serviceName);
        } else if (registerClassStore.containsKey(defaultClass)) {
            //If default class is registered.
            return registerClassStore.get(defaultClass);
        }
        return null;
    }

    /**
     * Returns YANG file path for module identifier.
     *
     * @param moduleIdentifier module identifier
     * @return YANG file path for module identifier
     */
    public String getYangFile(YangModuleIdentifier moduleIdentifier) {
        if (yangFileStore.containsKey(moduleIdentifier)) {
            return yangFileStore.get(moduleIdentifier);
        }
        log.error("YANG files for corresponding module identifier {} not " +
                          "found", moduleIdentifier);
        return null;
    }

    /**
     * Updates service class store.
     *
     * @param serviceClass service class
     */
    void updateServiceClass(Class<?> serviceClass) {
        registerClassStore.put(serviceClass.getName(), serviceClass);
    }

    /**
     * Updates application object store.
     *
     * @param appName application name
     */
    private void updateAppObjectStore(String appName) {
        if (verifyClassExistence(appName)) {
            appObjectStore.put(appName, ysrContextForAppStore);
        }
    }

    /**
     * Updates YANG schema object store.
     *
     * @param schemaNode application's schema node
     */
    private void updateYangSchemaStore(YangSchemaNode schemaNode) {
        addSchemaNodeUsingSchemaNameWithRev(schemaNode);
    }

    /**
     * Updates YANG schema notification object store.
     *
     * @param name application's notification name
     */
    private void updateYangNotificationStore(String name) {
        if (verifyClassExistence(name)) {
            yangRootSchemaStoreForNotification.put(name, ysrAppContext);
        }
    }

    /**
     * Updates YANG schema object store for root interface file name.
     *
     * @param name name of generated interface file for root
     *             node
     */
    private void updateYangSchemaForRootInterfaceFileNameStore(String name) {
        if (verifyClassExistence(name)) {
            yangSchemaStoreForRootInterface.put(name, ysrAppContext);
        }
    }

    /**
     * Updates YANG schema object store  for root op param file name.
     *
     * @param name name of generated op param file for root node
     */
    private void updateYangSchemaForRootOpParamFileNameStore(String name) {
        if (verifyClassExistence(name)) {
            yangSchemaStoreForRootOpParam.put(name, ysrAppContext);
        }
    }

    /**
     * Updates yang file store for YANG node.
     *
     * @param node    YANG node
     * @param jarPath jar file path
     */
    private void updateYangFileStore(YangNode node, String jarPath) {
       //FIXME: fix when yang tools support for file name.
       //yangFileStore.put(getModuleIdentifier(node),
       //                   getYangFilePath(jarPath, node.getFileName()));
    }

    /**
     * Returns yang file path.
     *
     * @param jarPath          jar path
     * @param metaDataFileName name of yang file from metadata
     * @return yang file path
     */
    private String getYangFilePath(String jarPath, String metaDataFileName) {
       String[] metaData = metaDataFileName.split(SLASH);
       return jarPath + SLASH + metaData[metaData.length - 1];
    }

    /**
     * Process jar file for fetching YANG nodes.
     *
     * @param path jar file path
     * @return YANG schema nodes
     */
    private List<YangNode> processJarParsingOperations(String path) {
        //Deserialize data model and get the YANG node set.
        try {
            return parseJarFile(path + JAR, path);
        } catch (IOException e) {
            log.error(" failed to parse the jar file in path {} : {} ", path,
                      e.getMessage());
        }
        return null;
    }

    /**
     * Process an application an updates the maps for YANG schema registry.
     *
     * @param appNode application YANG schema nodes
     */
    void processApplicationContext(YangSchemaNode appNode) {

        String appName = getInterfaceClassName(appNode);

        //Create a new instance of ysr app context for each node.
        ysrAppContext = new YsrAppContext();
        ysrContextForSchemaStore = new YsrAppContext();
        ysrContextForAppStore = new YsrAppContext();

        //add cur node to app context.
        ysrAppContext.curNode(appNode);
        ysrContextForAppStore.curNode(appNode);

        //Updates maps wih schema nodes.
        updateAppObjectStore(getServiceName(appNode));

        // Updates schema store.
        updateYangSchemaStore(appNode);
        // update interface store.
        updateYangSchemaForRootInterfaceFileNameStore(appName);
        //update op param store.
        updateYangSchemaForRootOpParamFileNameStore(getOpParamClassName(appNode));
        //Checks if notification is present then update notification store map.
        String eventSubject = null;
        try {
            if (appNode.isNotificationPresent()) {
                eventSubject = getEventClassName(appNode);
            }
        } catch (DataModelException e) {
            log.error("failed to search notification from schema map : {}",
                      e.getLocalizedMessage());
        }
        if (eventSubject != null) {
            updateYangNotificationStore(eventSubject);
        }
        log.info("successfully registered this application {}{}", appName,
                 SERVICE);
    }

    /**
     * Returns jar path from bundle mvnLocationPath.
     *
     * @param mvnLocationPath mvnLocationPath of bundle
     * @return path of jar
     */
    private String getJarPathFromBundleLocation(String mvnLocationPath,
                                                String currentDirectory) {
        String path = currentDirectory + SYSTEM;
        String[] strArray = mvnLocationPath.split(MAVEN);
        String[] split = strArray[1].split(File.separator);
        String[] groupId = split[0].split(Pattern.quote(DELIMITER));

        return path + groupId[0] + SLASH + groupId[1] + SLASH + split[1] +
                SLASH + split[2] + SLASH + split[1] + HYPHEN + split[2];
    }

    /**
     * Returns de-serializes YANG data-model nodes.
     *
     * @param serializedFileInfo serialized File Info
     * @return de-serializes YANG data-model nodes
     */
    Set<YangSchemaNode> deSerializeDataModel(String serializedFileInfo) {

        Set<YangSchemaNode> nodes = new HashSet<>();
        Object readValue;
        try {
            FileInputStream fileInputStream =
                    new FileInputStream(serializedFileInfo);
            ObjectInputStream objectInputStream =
                    new ObjectInputStream(fileInputStream);
            readValue = objectInputStream.readObject();
            if (readValue instanceof Set<?>) {
                for (Object obj : (Set<?>) readValue) {
                    if (obj instanceof YangSchemaNode) {
                        nodes.add((YangSchemaNode) obj);
                    } else {
                        throw new RuntimeException(
                                "deserialize object is not an instance of " +
                                        "YANG schema node" + obj);
                    }
                }
            } else {
                throw new RuntimeException(
                        "deserialize object is not an instance of set of" +
                                "YANG schema node" + readValue);
            }
            objectInputStream.close();
            fileInputStream.close();
        } catch (IOException | ClassNotFoundException e) {
            log.error(" {} not found.: {}", serializedFileInfo,
                      e.getLocalizedMessage());
        }

        return nodes;
    }

    /**
     * Returns ysr app context.
     *
     * @return ysr app context
     */
    YsrAppContext ysrAppContext() {
        return ysrAppContext;
    }

    /**
     * Returns schema node based on the revision.
     *
     * @param name name of the schema node
     * @return schema node based on the revision
     */
    private YangSchemaNode getSchemaNodeUsingSchemaNameWithRev(String name) {
        YsrAppContext appContext;
        YangSchemaNode schemaNode;
        if (name.contains(AT)) {
            String[] revArray = name.split(AT);
            appContext = yangSchemaStore.get(revArray[0]);
            schemaNode = appContext.getSchemaNodeForRevisionStore(name);
            if (schemaNode != null) {
                return schemaNode;
            }
            return appContext.curNode();
        }
        if (yangSchemaStore.containsKey(name)) {
            appContext = yangSchemaStore.get(name);
            if (appContext != null) {
                Iterator<YangSchemaNode> iterator = appContext
                        .getYangSchemaNodeForRevisionStore().values()
                        .iterator();
                if (iterator.hasNext()) {
                    return appContext.getYangSchemaNodeForRevisionStore()
                            .values().iterator().next();
                } else {
                    return null;
                }
            }
        }
        log.error("{} not found.", name);
        return null;
    }

    /**
     * Adds schema node when different revision of node has received.
     *
     * @param schemaNode schema node
     */
    private void addSchemaNodeUsingSchemaNameWithRev(
            YangSchemaNode schemaNode) {

        String date = getDateInStringFormat(schemaNode);
        String name = schemaNode.getName();
        if (!date.equals(EMPTY_STRING)) {
            name = name + AT + date;
        }
        //check if already present.
        if (!yangSchemaStore.containsKey(schemaNode.getName())) {
            ysrContextForSchemaStore.curNode(schemaNode);
            //if revision is not present no need to add in revision store.
            ysrContextForSchemaStore
                    .addSchemaNodeWithRevisionStore(name, schemaNode);
            yangSchemaStore.put(schemaNode.getName(),
                                ysrContextForSchemaStore);
        } else {
            YsrAppContext appContext =
                    yangSchemaStore.get(schemaNode.getName());
            appContext.addSchemaNodeWithRevisionStore(name, schemaNode);
            appContext.curNode(schemaNode);
        }
    }

    /**
     * Returns date in string format.
     *
     * @param schemaNode schema node
     * @return date in string format
     */
    String getDateInStringFormat(YangSchemaNode schemaNode) {
        if (schemaNode != null) {
            if (((YangNode) schemaNode).getRevision() != null) {
                return new SimpleDateFormat(DATE_FORMAT)
                        .format(((YangNode) schemaNode).getRevision()
                                        .getRevDate());
            }
        }
        return EMPTY_STRING;
    }

    /**
     * Removes schema node from schema map.
     *
     * @param removableNode schema node which needs to be removed
     */
    private void removeSchemaNode(YangSchemaNode removableNode) {

        String name = removableNode.getName();
        String date = getDateInStringFormat(removableNode);

        if (!date.isEmpty()) {
            name = removableNode.getName() + AT +
                    getDateInStringFormat(removableNode);
        }
        YsrAppContext appContext = yangSchemaStore
                .get(removableNode.getName());
        if (appContext != null &&
                !appContext.getYangSchemaNodeForRevisionStore().isEmpty() &&
                appContext.getYangSchemaNodeForRevisionStore().size() != 1) {
            appContext.removeSchemaNodeForRevisionStore(name);
        } else {
            yangSchemaStore.remove(removableNode.getName());
        }
    }

    /**
     * Verifies if the manager object is already registered with notification
     * handler.
     *
     * @param serviceClass service class
     * @return true if the manager object is already registered with
     * notification handler
     */
    public boolean verifyNotificationObject(Class<?> serviceClass) {
        YangSchemaNode schemaNode = null;
        String serviceName = serviceClass.getName();
        if (appObjectStore.containsKey(serviceName)) {
            schemaNode = getYangSchemaNodeUsingAppName(serviceName);
        } else if (yangSchemaStoreForRootInterface.containsKey(serviceName)) {
            schemaNode =
                    getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName(
                            serviceName);
        } else if (yangSchemaStoreForRootOpParam.containsKey(serviceName)) {
            schemaNode = getYangSchemaNodeUsingGeneratedRootNodeOpPramFileName(
                    serviceName);
        }

        if (schemaNode != null) {
            String name = getEventClassName(schemaNode);

            YsrAppContext appContext =
                    yangRootSchemaStoreForNotification.get(name);
            if (appContext != null && !appContext.isNotificationRegistered()) {
                appContext.setNotificationRegistered(true);
                return true;
            }
        }
        return false;
    }

    /**
     * Returns schema node's generated interface class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated interface class name
     */
    private String getInterfaceClassName(YangSchemaNode schemaNode) {
        return schemaNode.getJavaPackage() + PERIOD +
                getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType());
    }

    /**
     * Returns schema node's generated op param class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated op param class name
     */
    private String getOpParamClassName(YangSchemaNode schemaNode) {
        return getInterfaceClassName(schemaNode) + OP_PARAM;
    }

    /**
     * Returns schema node's generated op param class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated op param class name
     */
    private String getDefaultClassName(YangSchemaNode schemaNode) {
        return schemaNode.getJavaPackage() + PERIOD + getCapitalCase(DEFAULT) +
                getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType());
    }

    /**
     * Returns schema node's generated event class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated event class name
     */
    private String getEventClassName(YangSchemaNode schemaNode) {
        return getInterfaceClassName(schemaNode).toLowerCase() + PERIOD +
                getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType()) +
                EVENT_STRING;
    }

    /**
     * Returns schema node's generated service class name.
     *
     * @param schemaNode schema node
     * @return schema node's generated service class name
     */
    private String getServiceName(YangSchemaNode schemaNode) {
        return getInterfaceClassName(schemaNode) + SERVICE;
    }

    /**
     * Returns YSR application context for schema map.
     *
     * @return YSR application context for schema map
     */
    YsrAppContext ysrContextForSchemaStore() {
        return ysrContextForSchemaStore;
    }

    /**
     * Sets YSR application context for schema map.
     *
     * @param context YSR application context for
     *                schema map
     */
    void ysrContextForSchemaStore(YsrAppContext context) {
        ysrContextForSchemaStore = context;
    }

    /**
     * Returns YSR app context for application store.
     *
     * @return YSR app context for application store
     */
    YsrAppContext ysrContextForAppStore() {
        return ysrContextForAppStore;
    }

    /**
     * Retrieves schema node from the store and deletes jar file path.
     *
     * @param appName   application name
     * @param store     YSR stores
     * @param appObject applications object
     * @return schema node from the store
     */
    private YangSchemaNode retrieveNodeForUnregister(
            String appName,
            ConcurrentMap<String, YsrAppContext> store, Object appObject) {

        YsrAppContext curContext = store.get(appName);
        boolean isValidObject;
        if (curContext != null) {
            isValidObject = verifyAppObject(appObject, curContext.appObject());
            if (isValidObject) {
                YangSchemaNode curNode = curContext.curNode();
                //Delete all the generated ysr information in application's
                // package.
                removeYsrGeneratedTemporaryResources(curContext.jarPath(),
                                                     appName);
                return curNode;
            }
        }
        return null;
    }

    /**
     * Verifies the application object which needs to be unregistered.
     *
     * @param appObject current received application object
     * @param context   stored application object
     * @return true if objects are equal
     */
    private boolean verifyAppObject(Object appObject, Object context) {
        if (appObject != null && context != null) {
            return appObject.equals(context);
        }
        return appObject == null && context == null;
    }

    /**
     * Removes YSR generated temporary resources.
     *
     * @param rscPath resource path
     * @param appName application name
     */
    private void removeYsrGeneratedTemporaryResources(String rscPath,
                                                      String appName) {
        if (rscPath != null) {
            File jarPath = new File(rscPath);
            if (jarPath.exists()) {
                try {
                    deleteDirectory(jarPath);
                } catch (IOException e) {
                    log.error("failed to delete ysr resources for {} : {}",
                              appName, e.getLocalizedMessage());
                }
            }
        }
    }

    /**
     * Removes from YANG schema store.
     *
     * @param curNode schema node
     */
    private void removeFromYangSchemaStore(YangSchemaNode curNode) {
        removeSchemaNode(curNode);
    }

    /**
     * Removes from YANG schema  notification store.
     *
     * @param curNode schema node
     */
    private void removeFromYangNotificationStore(YangSchemaNode curNode) {
        yangRootSchemaStoreForNotification
                .remove(getEventClassName(curNode));
    }

    /**
     * Removes from app store.
     *
     * @param appName application name
     */
    private void removeFromAppSchemaStore(String appName) {
        appObjectStore.remove(appName);
    }

    /**
     * Removes from interface store.
     *
     * @param appName application name
     */
    private void removeFromYangSchemaNodeForRootInterface(String appName) {
        yangSchemaStoreForRootInterface.remove(appName);
    }

    /**
     * Removes from op param store.
     *
     * @param appName application name
     */
    private void removeFromYangSchemaNodeForRootOpParam(String appName) {
        yangSchemaStoreForRootOpParam.remove(appName + OP_PARAM);
    }

    /**
     * Removes YANG file information from file store.
     *
     * @param schemaNode schema node
     */
    private void removeYangFileInfoFromStore(YangSchemaNode schemaNode) {
        yangFileStore.remove(getModuleIdentifier(schemaNode));
    }

    /**
     * Verifies if class with given name exists.
     *
     * @param appName application name
     * @return true if class exists
     */
    boolean verifyClassExistence(String appName) {
        try {
            classLoader.loadClass(appName);
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    /**
     * Clears database for YSR.
     */
    public void flushYsrData() {
        appObjectStore.clear();
        yangSchemaStore.clear();
        yangRootSchemaStoreForNotification.clear();
        yangSchemaStoreForRootOpParam.clear();
        yangSchemaStoreForRootInterface.clear();
        registerClassStore.clear();
        yangFileStore.clear();
    }

    /**
     * Sets class loader of registered class.
     *
     * @param classLoader class loader of registered class
     */
    void setClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    /**
     * Process module library for a registered service.
     *
     * @param node YANG schema nodes
     */
    private void processModuleLibrary(YangNode node) {
        YangModuleInformation moduleInformation =
                new DefaultYangModuleInformation(getModuleIdentifier(node),
                                                 node.getNameSpace());
        addSubModuleIdentifier(node, (
                DefaultYangModuleInformation) moduleInformation);
        //TODO: add feature list to module information.
        ((DefaultYangModuleLibrary) library)
                .addModuleInformation(moduleInformation);
    }

    /**
     * Adds sub module identifier.
     *
     * @param node        schema node
     * @param information module information
     */
    private void addSubModuleIdentifier(
            YangSchemaNode node, DefaultYangModuleInformation information) {
        List<YangInclude> includeList = new ArrayList<>();
        if (node instanceof YangModule) {
            includeList = ((YangModule) node).getIncludeList();
        } else if (node instanceof YangSubModule) {
            includeList = ((YangSubModule) node).getIncludeList();
        }
        for (YangInclude include : includeList) {
            information.addSubModuleIdentifiers(getModuleIdentifier(
                    include.getIncludedNode()));
        }
    }

    /**
     * Returns module identifier for schema node.
     *
     * @param schemaNode schema node
     * @return module identifier for schema node
     */
    private YangModuleIdentifier getModuleIdentifier(
            YangSchemaNode schemaNode) {
        return new DefaultYangModuleIdentifier(
                schemaNode.getName(), getDateInStringFormat(schemaNode));
    }

    /**
     * Returns module library.
     *
     * @return module library
     */
    public YangModuleLibrary getLibrary() {
        return library;
    }
}
