/**
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.airavata.registry.api.service.handler;

import java.util.*;
import org.apache.airavata.common.utils.AiravataUtils;
import org.apache.airavata.common.utils.ServerSettings;
import org.apache.airavata.model.appcatalog.appdeployment.ApplicationDeploymentDescription;
import org.apache.airavata.model.appcatalog.appdeployment.ApplicationModule;
import org.apache.airavata.model.appcatalog.appinterface.ApplicationInterfaceDescription;
import org.apache.airavata.model.appcatalog.computeresource.*;
import org.apache.airavata.model.appcatalog.gatewaygroups.GatewayGroups;
import org.apache.airavata.model.appcatalog.gatewayprofile.ComputeResourcePreference;
import org.apache.airavata.model.appcatalog.gatewayprofile.GatewayResourceProfile;
import org.apache.airavata.model.appcatalog.gatewayprofile.StoragePreference;
import org.apache.airavata.model.appcatalog.groupresourceprofile.BatchQueueResourcePolicy;
import org.apache.airavata.model.appcatalog.groupresourceprofile.ComputeResourcePolicy;
import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupComputeResourcePreference;
import org.apache.airavata.model.appcatalog.groupresourceprofile.GroupResourceProfile;
import org.apache.airavata.model.appcatalog.parser.Parser;
import org.apache.airavata.model.appcatalog.parser.ParserInput;
import org.apache.airavata.model.appcatalog.parser.ParserOutput;
import org.apache.airavata.model.appcatalog.parser.ParsingTemplate;
import org.apache.airavata.model.appcatalog.storageresource.StorageResourceDescription;
import org.apache.airavata.model.appcatalog.userresourceprofile.UserComputeResourcePreference;
import org.apache.airavata.model.appcatalog.userresourceprofile.UserResourceProfile;
import org.apache.airavata.model.appcatalog.userresourceprofile.UserStoragePreference;
import org.apache.airavata.model.application.io.InputDataObjectType;
import org.apache.airavata.model.application.io.OutputDataObjectType;
import org.apache.airavata.model.commons.ErrorModel;
import org.apache.airavata.model.data.movement.*;
import org.apache.airavata.model.data.movement.DMType;
import org.apache.airavata.model.data.replica.DataProductModel;
import org.apache.airavata.model.data.replica.DataReplicaLocationModel;
import org.apache.airavata.model.error.*;
import org.apache.airavata.model.experiment.*;
import org.apache.airavata.model.job.JobModel;
import org.apache.airavata.model.process.ProcessModel;
import org.apache.airavata.model.process.ProcessWorkflow;
import org.apache.airavata.model.scheduling.ComputationalResourceSchedulingModel;
import org.apache.airavata.model.status.*;
import org.apache.airavata.model.task.TaskModel;
import org.apache.airavata.model.user.UserProfile;
import org.apache.airavata.model.workspace.Gateway;
import org.apache.airavata.model.workspace.GatewayUsageReportingCommand;
import org.apache.airavata.model.workspace.Notification;
import org.apache.airavata.model.workspace.Project;
import org.apache.airavata.registry.api.RegistryService;
import org.apache.airavata.registry.api.exception.RegistryServiceException;
import org.apache.airavata.registry.api.registry_apiConstants;
import org.apache.airavata.registry.core.entities.expcatalog.JobPK;
import org.apache.airavata.registry.core.repositories.appcatalog.*;
import org.apache.airavata.registry.core.repositories.expcatalog.*;
import org.apache.airavata.registry.core.repositories.replicacatalog.DataProductRepository;
import org.apache.airavata.registry.core.repositories.replicacatalog.DataReplicaLocationRepository;
import org.apache.airavata.registry.core.repositories.workflowcatalog.WorkflowRepository;
import org.apache.airavata.registry.core.utils.DBConstants;
import org.apache.airavata.registry.cpi.*;
import org.apache.airavata.registry.cpi.utils.Constants;
import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RegistryServerHandler implements RegistryService.Iface {
    private static final Logger logger = LoggerFactory.getLogger(RegistryServerHandler.class);

    private ApplicationDeploymentRepository applicationDeploymentRepository = new ApplicationDeploymentRepository();
    private ApplicationInterfaceRepository applicationInterfaceRepository = new ApplicationInterfaceRepository();
    private StorageResourceRepository storageResourceRepository = new StorageResourceRepository();
    private UserResourceProfileRepository userResourceProfileRepository = new UserResourceProfileRepository();
    private GatewayRepository gatewayRepository = new GatewayRepository();
    private ProjectRepository projectRepository = new ProjectRepository();
    private NotificationRepository notificationRepository = new NotificationRepository();
    private ExperimentSummaryRepository experimentSummaryRepository = new ExperimentSummaryRepository();
    private ExperimentRepository experimentRepository = new ExperimentRepository();
    private ExperimentOutputRepository experimentOutputRepository = new ExperimentOutputRepository();
    private ExperimentStatusRepository experimentStatusRepository = new ExperimentStatusRepository();
    private ExperimentErrorRepository experimentErrorRepository = new ExperimentErrorRepository();
    private ProcessRepository processRepository = new ProcessRepository();
    private ProcessOutputRepository processOutputRepository = new ProcessOutputRepository();
    private ProcessWorkflowRepository processWorkflowRepository = new ProcessWorkflowRepository();
    private ProcessStatusRepository processStatusRepository = new ProcessStatusRepository();
    private ProcessErrorRepository processErrorRepository = new ProcessErrorRepository();
    private TaskRepository taskRepository = new TaskRepository();
    private TaskStatusRepository taskStatusRepository = new TaskStatusRepository();
    private TaskErrorRepository taskErrorRepository = new TaskErrorRepository();
    private JobRepository jobRepository = new JobRepository();
    private JobStatusRepository jobStatusRepository = new JobStatusRepository();
    private QueueStatusRepository queueStatusRepository = new QueueStatusRepository();
    private DataProductRepository dataProductRepository = new DataProductRepository();
    private DataReplicaLocationRepository dataReplicaLocationRepository = new DataReplicaLocationRepository();
    private WorkflowRepository workflowRepository = new WorkflowRepository();
    private GatewayGroupsRepository gatewayGroupsRepository = new GatewayGroupsRepository();
    private ParserRepository parserRepository = new ParserRepository();
    private ParserInputRepository parserInputRepository = new ParserInputRepository();
    private ParserOutputRepository parserOutputRepository = new ParserOutputRepository();
    private ParsingTemplateRepository parsingTemplateRepository = new ParsingTemplateRepository();
    private UserRepository userRepository = new UserRepository();
    private ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
    private GatewayUsageReportingCommandRepository usageReportingCommandRepository =
            new GatewayUsageReportingCommandRepository();

    /**
     * Fetch Apache Registry API version
     */
    @Override
    public String getAPIVersion() throws TException {
        return registry_apiConstants.REGISTRY_API_VERSION;
    }

    /**
     * Verify if User Exists within Airavata.
     *
     * @param gatewayId
     * @param userName
     * @return true/false
     */
    @Override
    public boolean isUserExists(String gatewayId, String userName) throws RegistryServiceException, TException {
        try {
            return userRepository.isUserExists(gatewayId, userName);
        } catch (RegistryException e) {
            logger.error("Error while verifying user", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while verifying user. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get all users in the gateway
     *
     * @param gatewayId The gateway data model.
     * @return users
     * list of usernames of the users in the gateway
     */
    @Override
    public List<String> getAllUsersInGateway(String gatewayId) throws RegistryServiceException, TException {
        try {
            return userRepository.getAllUsernamesInGateway(gatewayId);
        } catch (RegistryException e) {
            logger.error("Error while retrieving users", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving users. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get Gateway details by providing gatewayId
     *
     * @param gatewayId The gateway Id of the Gateway.
     * @return gateway
     * Gateway obejct.
     */
    @Override
    public Gateway getGateway(String gatewayId) throws RegistryServiceException, TException {
        try {
            if (!gatewayRepository.isGatewayExist(gatewayId)) {
                logger.error("Gateway does not exist in the system. Please provide a valid gateway ID...");
                AiravataSystemException exception = new AiravataSystemException();
                exception.setMessage("Gateway does not exist in the system. Please provide a valid gateway ID...");
                throw exception;
            }
            Gateway gateway = gatewayRepository.getGateway(gatewayId);
            logger.debug("Airavata retrieved gateway with gateway id : " + gateway.getGatewayId());
            return gateway;
        } catch (RegistryException e) {
            logger.error("Error while getting the gateway", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while getting the gateway. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete a Gateway
     *
     * @param gatewayId The gateway Id of the Gateway to be deleted.
     * @return boolean
     * Boolean identifier for the success or failure of the deletion operation.
     */
    @Override
    public boolean deleteGateway(String gatewayId) throws RegistryServiceException, TException {
        try {
            if (!gatewayRepository.isGatewayExist(gatewayId)) {
                logger.error("Gateway does not exist in the system. Please provide a valid gateway ID...");
                AiravataSystemException exception = new AiravataSystemException();
                exception.setMessage("Gateway does not exist in the system. Please provide a valid gateway ID...");
                throw exception;
            }
            gatewayRepository.removeGateway(gatewayId);
            logger.debug("Airavata deleted gateway with gateway id : " + gatewayId);
            return true;
        } catch (RegistryException e) {
            logger.error("Error while deleting the gateway", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting the gateway. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get All the Gateways Connected to Airavata.
     */
    @Override
    public List<Gateway> getAllGateways() throws RegistryServiceException, TException {
        try {
            List<Gateway> gateways = gatewayRepository.getAllGateways();
            logger.debug("Airavata retrieved all available gateways...");
            return gateways;
        } catch (RegistryException e) {
            logger.error("Error while getting all the gateways", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while getting all the gateways. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Check for the Existance of a Gateway within Airavata
     *
     * @param gatewayId Provide the gatewayId of the gateway you want to check the existancy
     * @return gatewayId
     * return the gatewayId of the existing gateway.
     */
    @Override
    public boolean isGatewayExist(String gatewayId) throws RegistryServiceException, TException {
        try {
            return gatewayRepository.isGatewayExist(gatewayId);
        } catch (RegistryException e) {
            logger.error("Error while getting gateway", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while getting gateway. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean deleteNotification(String gatewayId, String notificationId)
            throws RegistryServiceException, TException {
        try {
            notificationRepository.deleteNotification(notificationId);
            return true;
        } catch (RegistryException e) {
            logger.error("Error while deleting notification", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting notification. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public Notification getNotification(String gatewayId, String notificationId)
            throws RegistryServiceException, TException {
        try {
            return notificationRepository.getNotification(notificationId);
        } catch (RegistryException e) {
            logger.error("Error while retrieving notification", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retreiving notification. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<Notification> getAllNotifications(String gatewayId) throws RegistryServiceException, TException {
        try {
            List<Notification> notifications = notificationRepository.getAllGatewayNotifications(gatewayId);
            return notifications;
        } catch (RegistryException e) {
            logger.error("Error while getting all notifications", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while getting all notifications. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get a Project by ID
     * This method is to obtain a project by providing a projectId.
     *
     * @param projectId projectId of the project you require.
     * @return project
     * project data model will be returned.
     */
    @Override
    public Project getProject(String projectId) throws RegistryServiceException, TException {
        try {
            if (!projectRepository.isProjectExist(projectId)) {
                logger.error("Project does not exist in the system. Please provide a valid project ID...");
                ProjectNotFoundException exception = new ProjectNotFoundException();
                exception.setMessage("Project does not exist in the system. Please provide a valid project ID...");
                throw exception;
            }
            logger.debug("Airavata retrieved project with project Id : " + projectId);

            Project project = projectRepository.getProject(projectId);
            return project;
        } catch (RegistryException e) {
            logger.error("Error while retrieving the project", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the project. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete a Project
     * This method is used to delete an existing Project.
     *
     * @param projectId projectId of the project you want to delete.
     * @return boolean
     * Boolean identifier for the success or failure of the deletion operation.
     * <p>
     * NOTE: This method is not used within gateways connected with Airavata.
     */
    @Override
    public boolean deleteProject(String projectId) throws RegistryServiceException, TException {
        try {
            if (!projectRepository.isProjectExist(projectId)) {
                logger.error("Project does not exist in the system. Please provide a valid project ID...");
                ProjectNotFoundException exception = new ProjectNotFoundException();
                exception.setMessage("Project does not exist in the system. Please provide a valid project ID...");
                throw exception;
            }

            projectRepository.removeProject(projectId);
            logger.debug("Airavata deleted project with project Id : " + projectId);
            return true;
        } catch (RegistryException e) {
            logger.error("Error while removing the project", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while removing the project. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get All User Projects
     * Get all Project for the user with pagination. Results will be ordered based on creation time DESC.
     *
     * @param gatewayId The identifier for the requested gateway.
     * @param userName  The identifier of the user.
     * @param limit     The amount results to be fetched.
     * @param offset    The starting point of the results to be fetched.
     */
    @Override
    public List<Project> getUserProjects(String gatewayId, String userName, int limit, int offset)
            throws RegistryServiceException, TException {
        if (!validateString(userName)) {
            logger.error("Username cannot be empty. Please provide a valid user..");
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Username cannot be empty. Please provide a valid user..");
            throw exception;
        }
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        List<Project> projects = new ArrayList<>();
        try {
            if (!userRepository.isUserExists(gatewayId, userName)) {
                logger.warn("User does not exist in the system. Please provide a valid user..");
                return projects;
            }
            Map<String, String> filters = new HashMap<>();
            filters.put(Constants.FieldConstants.ProjectConstants.OWNER, userName);
            filters.put(Constants.FieldConstants.ProjectConstants.GATEWAY_ID, gatewayId);
            projects = projectRepository.searchProjects(
                    filters,
                    limit,
                    offset,
                    Constants.FieldConstants.ProjectConstants.CREATION_TIME,
                    ResultOrderType.DESC);
            logger.debug("Airavata retrieved projects for user : " + userName + " and gateway id : " + gatewayId);
            return projects;
        } catch (RegistryException e) {
            logger.error("Error while retrieving projects", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving projects. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get Experiment Statistics
     * Get Experiment Statisitics for a given gateway for a specific time period. This feature is available only for admins of a particular gateway. Gateway admin access is managed by the user roles.
     *
     * @param gatewayId Unique identifier of the gateway making the request to fetch statistics.
     * @param fromTime  Starting date time.
     * @param toTime    Ending data time.
     */
    @Override
    public ExperimentStatistics getExperimentStatistics(
            String gatewayId,
            long fromTime,
            long toTime,
            String userName,
            String applicationName,
            String resourceHostName,
            List<String> accessibleExpIds,
            int limit,
            int offset)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
        }
        // FIXME: for now allowing to pass null accessibleExpIds (only admin users should call this method)
        // if (accessibleExpIds == null) {
        // logger.debug("accessibleExpIds is null, defaulting to an empty list");
        // accessibleExpIds = Collections.emptyList();
        // }
        try {
            Map<String, String> filters = new HashMap<>();
            filters.put(Constants.FieldConstants.ExperimentConstants.GATEWAY_ID, gatewayId);
            filters.put(Constants.FieldConstants.ExperimentConstants.FROM_DATE, fromTime + "");
            filters.put(Constants.FieldConstants.ExperimentConstants.TO_DATE, toTime + "");
            if (userName != null) {
                filters.put(Constants.FieldConstants.ExperimentConstants.USER_NAME, userName);
            }
            if (applicationName != null) {
                filters.put(Constants.FieldConstants.ExperimentConstants.EXECUTION_ID, applicationName);
            }
            if (resourceHostName != null) {
                filters.put(Constants.FieldConstants.ExperimentConstants.RESOURCE_HOST_ID, resourceHostName);
            }

            // Cap the max returned experiment summaries at 1000
            limit = Math.min(limit, 1000);

            ExperimentStatistics result = experimentSummaryRepository.getAccessibleExperimentStatistics(
                    accessibleExpIds, filters, limit, offset);
            logger.debug("Airavata retrieved experiments for gateway id : " + gatewayId + " between : "
                    + AiravataUtils.getTime(fromTime) + " and " + AiravataUtils.getTime(toTime));
            return result;
        } catch (Exception e) {
            logger.error("Error while retrieving experiments", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving experiments. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get All Experiments of the Project
     * Get Experiments within project with pagination. Results will be sorted based on creation time DESC.
     *
     * @param gatewayId Unique identifier of the gateway.
     * @param projectId Unique identifier of the project.
     * @param limit     Amount of results to be fetched.
     * @param offset    The starting point of the results to be fetched.
     */
    @Override
    public List<ExperimentModel> getExperimentsInProject(String gatewayId, String projectId, int limit, int offset)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
        }
        if (!validateString(projectId)) {
            logger.error("Project id cannot be empty. Please provide a valid project ID...");
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Project id cannot be empty. Please provide a valid project ID...");
            throw exception;
        }
        try {
            if (!projectRepository.isProjectExist(projectId)) {
                logger.error("Project does not exist in the system. Please provide a valid project ID...");
                ProjectNotFoundException exception = new ProjectNotFoundException();
                exception.setMessage("Project does not exist in the system. Please provide a valid project ID...");
                throw exception;
            }

            List<ExperimentModel> experiments = experimentRepository.getExperimentList(
                    gatewayId,
                    Constants.FieldConstants.ExperimentConstants.PROJECT_ID,
                    projectId,
                    limit,
                    offset,
                    Constants.FieldConstants.ExperimentConstants.CREATION_TIME,
                    ResultOrderType.DESC);
            logger.debug("Airavata retrieved experiments for project : " + projectId);
            return experiments;
        } catch (Exception e) {
            logger.error("Error while retrieving the experiments", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the experiments. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get All Experiments of the User
     * Get experiments by user with pagination. Results will be sorted based on creation time DESC.
     *
     * @param gatewayId Identifier of the requesting gateway.
     * @param userName  Username of the requested end user.
     * @param limit     Amount of results to be fetched.
     * @param offset    The starting point of the results to be fetched.
     */
    @Override
    public List<ExperimentModel> getUserExperiments(String gatewayId, String userName, int limit, int offset)
            throws RegistryServiceException, TException {
        if (!validateString(userName)) {
            logger.error("Username cannot be empty. Please provide a valid user..");
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Username cannot be empty. Please provide a valid user..");
            throw exception;
        }
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
        }
        List<ExperimentModel> experiments = new ArrayList<ExperimentModel>();
        try {
            if (!userRepository.isUserExists(gatewayId, userName)) {
                logger.warn("User does not exist in the system. Please provide a valid user..");
                return experiments;
            }
            experiments = experimentRepository.getExperimentList(
                    gatewayId,
                    Constants.FieldConstants.ExperimentConstants.USER_NAME,
                    userName,
                    limit,
                    offset,
                    Constants.FieldConstants.ExperimentConstants.CREATION_TIME,
                    ResultOrderType.DESC);
            logger.debug("Airavata retrieved experiments for user : " + userName);
            return experiments;
        } catch (Exception e) {
            logger.error("Error while retrieving the experiments", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the experiments. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete an Experiment
     * If the experiment is not already launched experiment can be deleted.
     *
     * @param experimentId@return boolean
     *                            Identifier for the success or failure of the deletion operation.
     */
    @Override
    public boolean deleteExperiment(String experimentId) throws RegistryServiceException, TException {
        try {
            if (!experimentRepository.isExperimentExist(experimentId)) {
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + experimentId + " does not exist in the system..");
            }
            ExperimentModel experimentModel = experimentRepository.getExperiment(experimentId);

            if (!(experimentModel.getExperimentStatus().get(0).getState() == ExperimentState.CREATED)) {
                logger.error("Error while deleting the experiment");
                throw new ExperimentCatalogException(
                        "Experiment is not in CREATED state. Hence cannot deleted. ID:" + experimentId);
            }
            experimentRepository.removeExperiment(experimentId);
            logger.debug("Airavata removed experiment with experiment id : " + experimentId);
            return true;
        } catch (Exception e) {
            logger.error("Error while deleting the experiment", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting the experiment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * *
     * * Get Experiment
     * * Fetch previously created experiment metadata.
     * *
     * * @param airavataExperimentId
     * *    The unique identifier of the requested experiment. This ID is returned during the create experiment step.
     * *
     * * @return ExperimentModel
     * *   This method will return the previously stored experiment metadata.
     * *
     * * @throws org.apache.airavata.model.error.InvalidRequestException
     * *    For any incorrect forming of the request itself.
     * *
     * * @throws org.apache.airavata.model.error.ExperimentNotFoundException
     * *    If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
     * *
     * * @throws org.apache.airavata.model.error.AiravataClientException
     * *    The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
     * *
     * *      UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
     * *         step, then Airavata Registry will not have a provenance area setup. The client has to follow
     * *         gateway registration steps and retry this request.
     * *
     * *      AUTHENTICATION_FAILURE - How Authentication will be implemented is yet to be determined.
     * *         For now this is a place holder.
     * *
     * *      INVALID_AUTHORIZATION - This will throw an authorization exception. When a more robust security hand-shake
     * *         is implemented, the authorization will be more substantial.
     * *
     * * @throws org.apache.airavata.model.error.AiravataSystemException
     * *    This exception will be thrown for any Airavata Server side issues and if the problem cannot be corrected by the client
     * *       rather an Airavata Administrator will be notified to take corrective action.
     * *
     * *
     *
     * @param airavataExperimentId
     */
    @Override
    public ExperimentModel getExperiment(String airavataExperimentId) throws RegistryServiceException, TException {
        ExperimentModel experimentModel = getExperimentInternal(airavataExperimentId);
        return experimentModel;
    }

    /**
     * Get Complete Experiment Details
     * Fetch the completed nested tree structue of previously created experiment metadata which includes processes ->
     * tasks -> jobs information.
     *
     * @param airavataExperimentId The identifier for the requested experiment. This is returned during the create experiment step.
     * @return ExperimentModel
     * This method will return the previously stored experiment metadata including application input parameters, computational resource scheduling
     * information, special input output handling and additional quality of service parameters.
     * @throws InvalidRequestException     For any incorrect forming of the request itself.
     * @throws ExperimentNotFoundException If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
     * @throws AiravataClientException     The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
     *                                     <p>
     *                                     UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
     *                                     step, then Airavata Registry will not have a provenance area setup. The client has to follow
     *                                     gateway registration steps and retry this request.
     *                                     <p>
     *                                     AUTHENTICATION_FAILURE - How Authentication will be implemented is yet to be determined.
     *                                     For now this is a place holder.
     *                                     <p>
     *                                     INVALID_AUTHORIZATION - This will throw an authorization exception. When a more robust security hand-shake
     *                                     is implemented, the authorization will be more substantial.
     * @throws AiravataSystemException     This exception will be thrown for any Airavata Server side issues and if the problem cannot be corrected by the client
     *                                     rather an Airavata Administrator will be notified to take corrective action.
     */
    @Override
    public ExperimentModel getDetailedExperimentTree(String airavataExperimentId)
            throws RegistryServiceException, TException {
        try {
            ExperimentModel experimentModel = getExperimentInternal(airavataExperimentId);
            List<ProcessModel> processList = processRepository.getProcessList(
                    Constants.FieldConstants.ExperimentConstants.EXPERIMENT_ID, experimentModel.getExperimentId());
            if (processList != null) {
                processList.stream().forEach(p -> {
                    // Process already has the task object
                    (p).getTasks().stream().forEach(t -> {
                        try {
                            List<JobModel> jobList = jobRepository.getJobList(
                                    Constants.FieldConstants.JobConstants.TASK_ID, ((TaskModel) t).getTaskId());
                            if (jobList != null) {
                                Collections.sort(jobList, new Comparator<JobModel>() {
                                    @Override
                                    public int compare(JobModel o1, JobModel o2) {
                                        return (int) (o1.getCreationTime() - o2.getCreationTime());
                                    }
                                });
                                t.setJobs(jobList);
                            }
                        } catch (RegistryException e) {
                            logger.error(e.getMessage(), e);
                        }
                    });
                });
                experimentModel.setProcesses(processList);
            }
            logger.debug("Airavata retrieved detailed experiment with experiment id : " + airavataExperimentId);
            return experimentModel;
        } catch (Exception e) {
            logger.error("Error while retrieving the experiment", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the experiment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get Experiment Status
     * <p>
     * Obtain the status of an experiment by providing the Experiment Id
     *
     * @param airavataExperimentId Experiment ID of the experimnet you require the status.
     * @return ExperimentStatus
     * ExperimentStatus model with the current status will be returned.
     */
    @Override
    public ExperimentStatus getExperimentStatus(String airavataExperimentId)
            throws RegistryServiceException, TException {
        ExperimentStatus experimentStatus = getExperimentStatusInternal(airavataExperimentId);
        logger.debug("Airavata retrieved experiment status for experiment id : " + airavataExperimentId);
        return experimentStatus;
    }

    /**
     * Get Experiment Outputs
     * This method to be used when need to obtain final outputs of a certain Experiment
     *
     * @param airavataExperimentId Experiment ID of the experimnet you need the outputs.
     * @return list
     * List of experiment outputs will be returned. They will be returned as a list of OutputDataObjectType for the experiment.
     */
    @Override
    public List<OutputDataObjectType> getExperimentOutputs(String airavataExperimentId)
            throws RegistryServiceException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                logger.error(
                        airavataExperimentId,
                        "Get experiment outputs failed, experiment {} doesn't exit.",
                        airavataExperimentId);
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }
            logger.debug("Airavata retrieved experiment outputs for experiment id : " + airavataExperimentId);
            return experimentOutputRepository.getExperimentOutputs(airavataExperimentId);
        } catch (Exception e) {
            logger.error(airavataExperimentId, "Error while retrieving the experiment outputs", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the experiment outputs. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get Intermediate Experiment Outputs
     * This method to be used when need to obtain intermediate outputs of a certain Experiment
     *
     * @param airavataExperimentId Experiment ID of the experimnet you need intermediate outputs.
     * @return list
     * List of intermediate experiment outputs will be returned. They will be returned as a list of OutputDataObjectType for the experiment.
     */
    @Override
    public List<OutputDataObjectType> getIntermediateOutputs(String airavataExperimentId)
            throws RegistryServiceException, TException {
        return null;
    }

    /**
     * Get Job Statuses for an Experiment
     * This method to be used when need to get the job status of an Experiment. An experiment may have one or many jobs; there for one or many job statuses may turnup
     *
     * @param airavataExperimentId@return JobStatus
     *                                    Job status (string) for all all the existing jobs for the experiment will be returned in the form of a map
     */
    @Override
    public Map<String, JobStatus> getJobStatuses(String airavataExperimentId)
            throws RegistryServiceException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                logger.error(
                        airavataExperimentId,
                        "Error while retrieving job details, experiment {} doesn't exist.",
                        airavataExperimentId);
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }
            List<ProcessModel> processModels = processRepository.getProcessList(
                    Constants.FieldConstants.ProcessConstants.EXPERIMENT_ID, airavataExperimentId);
            Map<String, JobStatus> jobStatus = new HashMap<String, JobStatus>();
            if (processModels != null && !processModels.isEmpty()) {
                for (ProcessModel processModel : processModels) {
                    List<TaskModel> tasks = processModel.getTasks();
                    if (tasks != null && !tasks.isEmpty()) {
                        for (TaskModel task : tasks) {
                            String taskId = task.getTaskId();
                            List<JobModel> jobs =
                                    jobRepository.getJobList(Constants.FieldConstants.JobConstants.TASK_ID, taskId);
                            if (jobs != null && !jobs.isEmpty()) {
                                for (JobModel jobModel : jobs) {
                                    String jobID = jobModel.getJobId();
                                    List<JobStatus> status = jobModel.getJobStatuses();
                                    if (status != null && status.size() > 0) {
                                        JobStatus latestStatus = status.get(status.size() - 1);
                                        jobStatus.put(jobID, latestStatus);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            logger.debug("Airavata retrieved job statuses for experiment with experiment id : " + airavataExperimentId);
            return jobStatus;
        } catch (Exception e) {
            logger.error(airavataExperimentId, "Error while retrieving the job statuses", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving the job statuses. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void addExperimentProcessOutputs(String outputType, List<OutputDataObjectType> outputs, String id)
            throws RegistryServiceException, TException {

        try {
            if (ExpCatChildDataType.PROCESS_OUTPUT.equals(ExpCatChildDataType.valueOf(outputType))) {
                processOutputRepository.addProcessOutputs(outputs, id);
            } else if (ExpCatChildDataType.EXPERIMENT_OUTPUT.equals(ExpCatChildDataType.valueOf(outputType))) {
                experimentOutputRepository.addExperimentOutputs(outputs, id);
            }
        } catch (Exception e) {
            logger.error(id, "Error while adding outputs", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding outputs. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void addErrors(String errorType, ErrorModel errorModel, String id)
            throws RegistryServiceException, TException {

        try {
            if (ExpCatChildDataType.EXPERIMENT_ERROR.equals(ExpCatChildDataType.valueOf(errorType))) {
                experimentErrorRepository.addExperimentError(errorModel, id);
            } else if (ExpCatChildDataType.TASK_ERROR.equals(ExpCatChildDataType.valueOf(errorType))) {
                taskErrorRepository.addTaskError(errorModel, id);
            } else if (ExpCatChildDataType.PROCESS_ERROR.equals(ExpCatChildDataType.valueOf(errorType))) {
                processErrorRepository.addProcessError(errorModel, id);
            }
        } catch (Exception e) {
            logger.error(id, "Error while adding error", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding error. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void addTaskStatus(TaskStatus taskStatus, String taskId) throws RegistryServiceException, TException {
        try {
            taskStatusRepository.addTaskStatus(taskStatus, taskId);
        } catch (Exception e) {
            logger.error(taskId, "Error while adding task status", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding task status. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void addProcessStatus(ProcessStatus processStatus, String processId)
            throws RegistryServiceException, TException {
        try {
            processStatusRepository.addProcessStatus(processStatus, processId);
        } catch (Exception e) {
            logger.error(processId, "Error while adding process status", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding process status. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void updateProcessStatus(ProcessStatus processStatus, String processId)
            throws RegistryServiceException, TException {
        try {
            processStatusRepository.updateProcessStatus(processStatus, processId);
        } catch (Exception e) {
            logger.error(processId, "Error while updating process status", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while updating process status. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void updateExperimentStatus(ExperimentStatus experimentStatus, String experimentId)
            throws RegistryServiceException, TException {
        try {
            experimentStatusRepository.updateExperimentStatus(experimentStatus, experimentId);
        } catch (Exception e) {
            logger.error(experimentId, "Error while updating experiment status", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while updating experiment status. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void addJobStatus(JobStatus jobStatus, String taskId, String jobId)
            throws RegistryServiceException, TException {
        try {
            JobPK jobPK = new JobPK();
            jobPK.setJobId(jobId);
            jobPK.setTaskId(taskId);
            jobStatusRepository.addJobStatus(jobStatus, jobPK);
        } catch (Exception e) {
            logger.error(jobId, "Error while adding job status", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding job status. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void addJob(JobModel jobModel, String processId) throws RegistryServiceException, TException {
        try {
            jobRepository.addJob(jobModel, processId);
        } catch (Exception e) {
            logger.error(processId, "Error while adding job ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding job. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void deleteJobs(String processId) throws RegistryServiceException, TException {
        try {
            List<JobModel> jobs = jobRepository.getJobList(Constants.FieldConstants.JobConstants.PROCESS_ID, processId);
            for (JobModel jobModel : jobs) {
                jobRepository.removeJob(jobModel);
            }
        } catch (Exception e) {
            logger.error(processId, "Error while deleting job ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while deleting job. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public String addProcess(ProcessModel processModel, String experimentId)
            throws RegistryServiceException, TException {
        try {
            return processRepository.addProcess(processModel, experimentId);
        } catch (Exception e) {
            logger.error(experimentId, "Error while adding process ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding process. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void updateProcess(ProcessModel processModel, String processId) throws RegistryServiceException, TException {
        try {
            processRepository.updateProcess(processModel, processId);
        } catch (Exception e) {
            logger.error(processId, "Error while updating process ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while updating process. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public String addTask(TaskModel taskModel, String processId) throws RegistryServiceException, TException {
        try {
            return taskRepository.addTask(taskModel, processId);
        } catch (Exception e) {
            logger.error(processId, "Error while adding task ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding task. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void deleteTasks(String processId) throws RegistryServiceException, TException {
        try {
            taskRepository.deleteTasks(processId);
        } catch (Exception e) {
            logger.error(processId, "Error while adding task ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding task. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public UserConfigurationDataModel getUserConfigurationData(String experimentId)
            throws RegistryServiceException, TException {
        try {
            return experimentRepository.getUserConfigurationData(experimentId);
        } catch (Exception e) {
            logger.error(experimentId, "Error while getting user configuration ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding task. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public ProcessModel getProcess(String processId) throws RegistryServiceException, TException {
        try {
            return processRepository.getProcess(processId);
        } catch (Exception e) {
            logger.error(processId, "Error while retrieving user configuration ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving user configuration. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<ProcessModel> getProcessList(String experimentId) throws RegistryServiceException, TException {
        try {
            List<ProcessModel> processModels = processRepository.getProcessList(
                    Constants.FieldConstants.ExperimentConstants.EXPERIMENT_ID, experimentId);
            return processModels;

        } catch (Exception e) {
            logger.error(experimentId, "Error while retrieving process list ", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving process list. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public ProcessStatus getProcessStatus(String processId) throws RegistryServiceException, TException {
        try {
            return processStatusRepository.getProcessStatus(processId);
        } catch (Exception e) {
            logger.error(processId, "Error while retrieving process status", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving process status. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<ProcessModel> getProcessListInState(ProcessState processState)
            throws RegistryServiceException, TException {
        try {

            List<ProcessModel> finalProcessList = new ArrayList<>();
            int offset = 0;
            int limit = 100;
            int count = 0;
            do {
                List<ProcessStatus> processStatusList =
                        processStatusRepository.getProcessStatusList(processState, offset, limit);
                offset += processStatusList.size();
                count = processStatusList.size();
                for (ProcessStatus processStatus : processStatusList) {
                    ProcessStatus latestStatus = processStatusRepository.getProcessStatus(processStatus.getProcessId());
                    if (latestStatus.getState().name().equals(processState.name())) {
                        finalProcessList.add(processRepository.getProcess(latestStatus.getProcessId()));
                    }
                }
            } while (count == limit);
            return finalProcessList;
        } catch (Exception e) {
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage(
                    "Error while retrieving process list with given status. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<ProcessStatus> getProcessStatusList(String processId) throws RegistryServiceException, TException {
        try {
            return processStatusRepository.getProcessStatusList(processId);
        } catch (Exception e) {
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage(
                    "Error while retrieving process status list  for given process Id. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * queryType can be PROCESS_ID or TASK_ID
     */
    @Override
    public boolean isJobExist(String queryType, String id) throws RegistryServiceException, TException {
        try {
            JobModel jobModel = fetchJobModel(queryType, id);
            return jobModel != null;
        } catch (Exception e) {
            logger.error(id, "Error while retrieving job", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving job. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * queryType can be PROCESS_ID or TASK_ID
     */
    @Override
    public JobModel getJob(String queryType, String id) throws RegistryServiceException, TException {
        try {
            JobModel jobModel = fetchJobModel(queryType, id);
            if (jobModel != null) return jobModel;
            throw new Exception("Job not found for queryType: " + queryType + ", id: " + id);
        } catch (Exception e) {
            logger.error(id, "Error while retrieving job", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving job. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<JobModel> getJobs(String queryType, String id) throws RegistryServiceException, TException {

        try {
            return fetchJobModels(queryType, id);
        } catch (Exception e) {
            logger.error(id, "Error while retrieving jobs for query " + queryType + " and id " + id, e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving jobs for query " + queryType + " and id " + id
                    + ". More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public int getJobCount(
            org.apache.airavata.model.status.JobStatus jobStatus, String gatewayId, double searchBackTimeInMinutes)
            throws RegistryServiceException, TException {

        List<JobStatus> jobStatusList = jobStatusRepository.getDistinctListofJobStatus(
                gatewayId, jobStatus.getJobState().name(), searchBackTimeInMinutes);
        return jobStatusList.size();
    }

    @Override
    public Map<String, Double> getAVGTimeDistribution(String gatewayId, double searchBackTimeInMinutes)
            throws RegistryServiceException, TException {
        return processRepository.getAVGTimeDistribution(gatewayId, searchBackTimeInMinutes);
    }

    private JobModel fetchJobModel(String queryType, String id) throws RegistryException {
        if (queryType.equals(Constants.FieldConstants.JobConstants.TASK_ID)) {
            List<JobModel> jobs = jobRepository.getJobList(Constants.FieldConstants.JobConstants.TASK_ID, id);
            if (jobs != null) {
                for (JobModel jobModel : jobs) {
                    if (jobModel.getJobId() != null || !jobModel.equals("")) {
                        return jobModel;
                    }
                }
            }
        } else if (queryType.equals(Constants.FieldConstants.JobConstants.PROCESS_ID)) {
            List<JobModel> jobs = jobRepository.getJobList(Constants.FieldConstants.JobConstants.PROCESS_ID, id);
            if (jobs != null) {
                for (JobModel jobModel : jobs) {
                    if (jobModel.getJobId() != null || !jobModel.equals("")) {
                        return jobModel;
                    }
                }
            }
        }
        return null;
    }

    private List<JobModel> fetchJobModels(String queryType, String id) throws RegistryException {
        List<JobModel> jobs = new ArrayList<>();
        switch (queryType) {
            case Constants.FieldConstants.JobConstants.TASK_ID:
                jobs = jobRepository.getJobList(Constants.FieldConstants.JobConstants.TASK_ID, id);
                break;
            case Constants.FieldConstants.JobConstants.PROCESS_ID:
                jobs = jobRepository.getJobList(Constants.FieldConstants.JobConstants.PROCESS_ID, id);
                break;
            case Constants.FieldConstants.JobConstants.JOB_ID:
                jobs = jobRepository.getJobList(Constants.FieldConstants.JobConstants.JOB_ID, id);
                break;
        }
        return jobs;
    }

    @Override
    public List<OutputDataObjectType> getProcessOutputs(String processId) throws RegistryServiceException, TException {
        try {
            return processOutputRepository.getProcessOutputs(processId);
        } catch (Exception e) {
            logger.error("Error while retrieving process outputs for process id " + processId, e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving process outputs. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<ProcessWorkflow> getProcessWorkflows(String processId) throws RegistryServiceException, TException {

        try {
            return processWorkflowRepository.getProcessWorkflows(processId);
        } catch (Exception e) {
            logger.error("Error while retrieving process workflows for process id " + processId, e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving process workflows for process id " + processId
                    + ". More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void addProcessWorkflow(ProcessWorkflow processWorkflow) throws RegistryServiceException, TException {
        try {
            processWorkflowRepository.addProcessWorkflow(processWorkflow, processWorkflow.getProcessId());
        } catch (Exception e) {
            logger.error("Error while adding process workflows for process id " + processWorkflow.getProcessId(), e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding process workflows for process id " + processWorkflow.getProcessId()
                    + ". More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<String> getProcessIds(String experimentId) throws RegistryServiceException, TException {
        try {
            return processRepository.getProcessIds(DBConstants.Process.EXPERIMENT_ID, experimentId);
        } catch (Exception e) {
            logger.error(experimentId, "Error while retrieving process ids", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving process ids. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Get Job Details for all the jobs within an Experiment.
     * This method to be used when need to get the job details for one or many jobs of an Experiment.
     *
     * @param airavataExperimentId@return list of JobDetails
     *                                    Job details.
     */
    @Override
    public List<JobModel> getJobDetails(String airavataExperimentId) throws RegistryServiceException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                logger.error(
                        airavataExperimentId,
                        "Error while retrieving job details, experiment {} doesn't exist.",
                        airavataExperimentId);
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }
            List<ProcessModel> processModels = processRepository.getProcessList(
                    Constants.FieldConstants.ProcessConstants.EXPERIMENT_ID, airavataExperimentId);
            List<JobModel> jobList = new ArrayList<>();
            if (processModels != null && !processModels.isEmpty()) {
                for (ProcessModel processModel : processModels) {
                    List<TaskModel> tasks = processModel.getTasks();
                    if (tasks != null && !tasks.isEmpty()) {
                        for (TaskModel taskModel : tasks) {
                            String taskId = taskModel.getTaskId();
                            List<JobModel> taskJobs =
                                    jobRepository.getJobList(Constants.FieldConstants.JobConstants.TASK_ID, taskId);
                            jobList.addAll(taskJobs);
                        }
                    }
                }
            }
            logger.debug("Airavata retrieved job models for experiment with experiment id : " + airavataExperimentId);
            return jobList;
        } catch (Exception e) {
            logger.error(airavataExperimentId, "Error while retrieving the job details", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the job details. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch a Application Module.
     *
     * @param appModuleId The unique identifier of the application module required
     * @return applicationModule
     * Returns an Application Module Object.
     */
    @Override
    public ApplicationModule getApplicationModule(String appModuleId) throws RegistryServiceException, TException {
        try {
            ApplicationModule module = applicationInterfaceRepository.getApplicationModule(appModuleId);
            logger.debug("Airavata retrieved application module with module id : " + appModuleId);
            return module;
        } catch (AppCatalogException e) {
            logger.error(appModuleId, "Error while retrieving application module...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the adding application module. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Application Module Descriptions.
     *
     * @param gatewayId ID of the gateway which need to list all available application deployment documentation.
     * @return list
     * Returns the list of all Application Module Objects.
     */
    @Override
    public List<ApplicationModule> getAllAppModules(String gatewayId) throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            List<ApplicationModule> moduleList = applicationInterfaceRepository.getAllApplicationModules(gatewayId);
            logger.debug("Airavata retrieved modules for gateway id : " + gatewayId);
            return moduleList;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving all application modules...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving all application modules. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Application Module Descriptions.
     *
     * @param gatewayId        ID of the gateway which need to list all available application deployment documentation.
     * @param accessibleAppIds App IDs that are accessible to the user
     * @return list
     * Returns the list of all Application Module Objects that are accessible to the user.
     */
    @Override
    public List<ApplicationModule> getAccessibleAppModules(
            String gatewayId, List<String> accessibleAppIds, List<String> accessibleComputeResourceIds)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            List<ApplicationModule> moduleList = applicationInterfaceRepository.getAccessibleApplicationModules(
                    gatewayId, accessibleAppIds, accessibleComputeResourceIds);
            logger.debug("Airavata retrieved modules for gateway id : " + gatewayId);
            return moduleList;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving all application modules...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving all application modules. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete an Application Module.
     *
     * @param appModuleId The identifier of the Application Module to be deleted.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteApplicationModule(String appModuleId) throws RegistryServiceException, TException {
        try {
            logger.debug("Airavata deleted application module with module id : " + appModuleId);
            return applicationInterfaceRepository.removeApplicationModule(appModuleId);
        } catch (AppCatalogException e) {
            logger.error(appModuleId, "Error while deleting application module...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting the application module. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch a Application Deployment.
     *
     * @param appDeploymentId The identifier for the requested application module
     * @return applicationDeployment
     * Returns a application Deployment Object.
     */
    @Override
    public ApplicationDeploymentDescription getApplicationDeployment(String appDeploymentId)
            throws RegistryServiceException, TException {
        try {
            ApplicationDeploymentDescription deployement =
                    applicationDeploymentRepository.getApplicationDeployement(appDeploymentId);
            logger.debug("Airavata registered application deployment for deployment id : " + appDeploymentId);
            return deployement;
        } catch (AppCatalogException e) {
            logger.error(appDeploymentId, "Error while retrieving application deployment...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application deployment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete an Application Deployment.
     *
     * @param appDeploymentId The unique identifier of application deployment to be deleted.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteApplicationDeployment(String appDeploymentId) throws RegistryServiceException, TException {
        try {
            applicationDeploymentRepository.removeAppDeployment(appDeploymentId);
            logger.debug("Airavata removed application deployment with deployment id : " + appDeploymentId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(appDeploymentId, "Error while deleting application deployment...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting application deployment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Application Deployment Descriptions.
     *
     * @param gatewayId ID of the gateway which need to list all available application deployment documentation.
     * @param gatewayId
     * @return list<applicationDeployment.
     * Returns the list of all application Deployment Objects.
     */
    @Override
    public List<ApplicationDeploymentDescription> getAllApplicationDeployments(String gatewayId)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            List<ApplicationDeploymentDescription> deployements =
                    applicationDeploymentRepository.getAllApplicationDeployements(gatewayId);
            logger.debug("Airavata retrieved application deployments for gateway id : " + gatewayId);
            return deployements;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving application deployments...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application deployments. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Application Deployment Descriptions.
     *
     * @param gatewayId                  ID of the gateway which need to list all available application deployment documentation.
     * @param accessibleAppDeploymentIds App IDs that are accessible to the user
     * @return list<applicationDeployment.
     * Returns the list of all application Deployment Objects that are accessible to the user.
     */
    @Override
    public List<ApplicationDeploymentDescription> getAccessibleApplicationDeployments(
            String gatewayId, List<String> accessibleAppDeploymentIds, List<String> accessibleComputeResourceIds)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            List<ApplicationDeploymentDescription> deployements =
                    applicationDeploymentRepository.getAccessibleApplicationDeployments(
                            gatewayId, accessibleAppDeploymentIds, accessibleComputeResourceIds);
            logger.debug("Airavata retrieved application deployments for gateway id : " + gatewayId);
            return deployements;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving application deployments...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application deployments. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all accessible Application Deployment Descriptions for the given Application Module.
     *
     * @param gatewayId                    ID of the gateway which need to list all available application deployment documentation.
     * @param appModuleId                  The given Application Module ID.
     * @param accessibleAppDeploymentIds   Application Deployment IDs which are accessible to the current user.
     * @param accessibleComputeResourceIds Compute Resource IDs which are accessible to the current user.
     * @return list<applicationDeployment>
     * Returns the list of all application Deployment Objects.
     */
    @Override
    public List<ApplicationDeploymentDescription> getAccessibleApplicationDeploymentsForAppModule(
            String gatewayId,
            String appModuleId,
            List<String> accessibleAppDeploymentIds,
            List<String> accessibleComputeResourceIds)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            List<ApplicationDeploymentDescription> deployments =
                    applicationDeploymentRepository.getAccessibleApplicationDeployments(
                            gatewayId, appModuleId, accessibleAppDeploymentIds, accessibleComputeResourceIds);
            return deployments;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving application deployments...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application deployments. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch a list of Deployed Compute Hosts.
     *
     * @param appModuleId The identifier for the requested application module
     * @return list<string>
     * Returns a list of Deployed Resources.
     */
    @Override
    public List<String> getAppModuleDeployedResources(String appModuleId) throws RegistryServiceException, TException {
        try {
            List<String> appDeployments = new ArrayList<>();
            Map<String, String> filters = new HashMap<>();
            filters.put(DBConstants.ApplicationDeployment.APPLICATION_MODULE_ID, appModuleId);
            List<ApplicationDeploymentDescription> applicationDeployments =
                    applicationDeploymentRepository.getApplicationDeployments(filters);
            for (ApplicationDeploymentDescription description : applicationDeployments) {
                appDeployments.add(description.getAppDeploymentId());
            }
            logger.debug("Airavata retrieved application deployments for module id : " + appModuleId);
            return appDeployments;
        } catch (AppCatalogException e) {
            logger.error(appModuleId, "Error while retrieving application deployments...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application deployment. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<ApplicationDeploymentDescription> getApplicationDeployments(String appModuleId)
            throws RegistryServiceException, TException {
        try {
            Map<String, String> filters = new HashMap<>();
            filters.put(DBConstants.ApplicationDeployment.APPLICATION_MODULE_ID, appModuleId);
            List<ApplicationDeploymentDescription> applicationDeployments =
                    applicationDeploymentRepository.getApplicationDeployments(filters);
            return applicationDeployments;
        } catch (AppCatalogException e) {
            logger.error(appModuleId, "Error while retrieving application deployments...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application deployment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch an Application Interface.
     *
     * @param appInterfaceId The identifier for the requested application interface.
     * @return applicationInterface
     * Returns an application Interface Object.
     */
    @Override
    public ApplicationInterfaceDescription getApplicationInterface(String appInterfaceId)
            throws RegistryServiceException, TException {
        try {
            ApplicationInterfaceDescription interfaceDescription =
                    applicationInterfaceRepository.getApplicationInterface(appInterfaceId);
            logger.debug("Airavata retrieved application interface with interface id : " + appInterfaceId);
            return interfaceDescription;
        } catch (AppCatalogException e) {
            logger.error(appInterfaceId, "Error while retrieving application interface...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application interface. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete an Application Interface.
     *
     * @param appInterfaceId The identifier for the requested application interface to be deleted.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteApplicationInterface(String appInterfaceId) throws RegistryServiceException, TException {
        try {
            boolean removeApplicationInterface =
                    applicationInterfaceRepository.removeApplicationInterface(appInterfaceId);
            logger.debug("Airavata removed application interface with interface id : " + appInterfaceId);
            return removeApplicationInterface;
        } catch (AppCatalogException e) {
            logger.error(appInterfaceId, "Error while deleting application interface...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting application interface. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch name and ID of  Application Interface documents.
     *
     * @param gatewayId
     * @return map<applicationId, applicationInterfaceNames>
     * Returns a list of application interfaces with corresponsing ID's
     */
    @Override
    public Map<String, String> getAllApplicationInterfaceNames(String gatewayId)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            List<ApplicationInterfaceDescription> allApplicationInterfaces =
                    applicationInterfaceRepository.getAllApplicationInterfaces(gatewayId);
            Map<String, String> allApplicationInterfacesMap = new HashMap<>();
            if (allApplicationInterfaces != null && !allApplicationInterfaces.isEmpty()) {
                for (ApplicationInterfaceDescription interfaceDescription : allApplicationInterfaces) {
                    allApplicationInterfacesMap.put(
                            interfaceDescription.getApplicationInterfaceId(),
                            interfaceDescription.getApplicationName());
                }
            }
            logger.debug("Airavata retrieved application interfaces for gateway id : " + gatewayId);
            return allApplicationInterfacesMap;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving application interfaces...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application interfaces. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Application Interface documents.
     *
     * @param gatewayId
     * @return map<applicationId, applicationInterfaceNames>
     * Returns a list of application interfaces documents (Application Interface ID, name, description, Inputs and Outputs objects).
     */
    @Override
    public List<ApplicationInterfaceDescription> getAllApplicationInterfaces(String gatewayId)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            List<ApplicationInterfaceDescription> interfaces =
                    applicationInterfaceRepository.getAllApplicationInterfaces(gatewayId);
            logger.debug("Airavata retrieved application interfaces for gateway id : " + gatewayId);
            return interfaces;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving application interfaces...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application interfaces. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch the list of Application Inputs.
     *
     * @param appInterfaceId The identifier of the application interface which need inputs to be fetched.
     * @return list<application_interface_model.InputDataObjectType>
     * Returns a list of application inputs.
     */
    @Override
    public List<InputDataObjectType> getApplicationInputs(String appInterfaceId)
            throws RegistryServiceException, TException {
        try {
            List<InputDataObjectType> applicationInputs =
                    applicationInterfaceRepository.getApplicationInputs(appInterfaceId);
            logger.debug("Airavata retrieved application inputs for application interface id : " + appInterfaceId);
            return applicationInputs;
        } catch (AppCatalogException e) {
            logger.error(appInterfaceId, "Error while retrieving application inputs...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving application inputs. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch list of Application Outputs.
     *
     * @param appInterfaceId The identifier of the application interface which need outputs to be fetched.
     * @return list<application_interface_model.OutputDataObjectType>
     * Returns a list of application outputs.
     */
    @Override
    public List<OutputDataObjectType> getApplicationOutputs(String appInterfaceId)
            throws RegistryServiceException, TException {
        List<OutputDataObjectType> list = getApplicationOutputsInternal(appInterfaceId);
        logger.debug("Airavata retrieved application outputs for app interface id : " + appInterfaceId);
        return list;
    }

    /**
     * Fetch a list of all deployed Compute Hosts for a given application interfaces.
     *
     * @param appInterfaceId The identifier for the requested application interface.
     * @return map<computeResourceId, computeResourceName>
     * A map of registered compute resource id's and their corresponding hostnames.
     * Deployments of each modules listed within the interfaces will be listed.
     */
    @Override
    public Map<String, String> getAvailableAppInterfaceComputeResources(String appInterfaceId)
            throws RegistryServiceException, TException {
        try {
            Map<String, String> allComputeResources =
                    new ComputeResourceRepository().getAvailableComputeResourceIdList();
            Map<String, String> availableComputeResources = new HashMap<String, String>();
            ApplicationInterfaceDescription applicationInterface =
                    applicationInterfaceRepository.getApplicationInterface(appInterfaceId);
            HashMap<String, String> filters = new HashMap<>();
            List<String> applicationModules = applicationInterface.getApplicationModules();
            if (applicationModules != null && !applicationModules.isEmpty()) {
                for (String moduleId : applicationModules) {
                    filters.put(DBConstants.ApplicationDeployment.APPLICATION_MODULE_ID, moduleId);
                    List<ApplicationDeploymentDescription> applicationDeployments =
                            applicationDeploymentRepository.getApplicationDeployments(filters);
                    for (ApplicationDeploymentDescription deploymentDescription : applicationDeployments) {
                        if (allComputeResources.get(deploymentDescription.getComputeHostId()) != null) {
                            availableComputeResources.put(
                                    deploymentDescription.getComputeHostId(),
                                    allComputeResources.get(deploymentDescription.getComputeHostId()));
                        }
                    }
                }
            }
            logger.debug(
                    "Airavata retrieved available compute resources for application interface id : " + appInterfaceId);
            return availableComputeResources;
        } catch (AppCatalogException e) {
            logger.error(appInterfaceId, "Error while saving compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while saving compute resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch the given Compute Resource.
     *
     * @param computeResourceId The identifier for the requested compute resource
     * @return computeResourceDescription
     * Compute Resource Object created from the datamodel..
     */
    @Override
    public ComputeResourceDescription getComputeResource(String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceDescription computeResource =
                    new ComputeResourceRepository().getComputeResource(computeResourceId);
            logger.debug("Airavata retrieved compute resource with compute resource Id : " + computeResourceId);
            return computeResource;
        } catch (AppCatalogException e) {
            logger.error(computeResourceId, "Error while retrieving compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving compute resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all registered Compute Resources.
     *
     * @return A map of registered compute resource id's and thier corresponding hostnames.
     * Compute Resource Object created from the datamodel..
     */
    @Override
    public Map<String, String> getAllComputeResourceNames() throws RegistryServiceException, TException {
        try {
            Map<String, String> computeResourceIdList = new ComputeResourceRepository().getAllComputeResourceIdList();
            logger.debug("Airavata retrieved all the available compute resources...");
            return computeResourceIdList;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving compute resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete a Compute Resource.
     *
     * @param computeResourceId The identifier for the requested compute resource to be deleted.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteComputeResource(String computeResourceId) throws RegistryServiceException, TException {
        try {
            new ComputeResourceRepository().removeComputeResource(computeResourceId);
            logger.debug("Airavata deleted compute resource with compute resource Id : " + computeResourceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(computeResourceId, "Error while deleting compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting compute resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch the given Storage Resource.
     *
     * @param storageResourceId The identifier for the requested storage resource
     * @return storageResourceDescription
     * Storage Resource Object created from the datamodel..
     */
    @Override
    public StorageResourceDescription getStorageResource(String storageResourceId)
            throws RegistryServiceException, TException {
        try {
            StorageResourceDescription storageResource =
                    storageResourceRepository.getStorageResource(storageResourceId);
            logger.debug("Airavata retrieved storage resource with storage resource Id : " + storageResourceId);
            return storageResource;
        } catch (AppCatalogException e) {
            logger.error(storageResourceId, "Error while retrieving storage resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving storage resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all registered Storage Resources.
     *
     * @return A map of registered compute resource id's and thier corresponding hostnames.
     * Compute Resource Object created from the datamodel..
     */
    @Override
    public Map<String, String> getAllStorageResourceNames() throws RegistryServiceException, TException {
        try {
            Map<String, String> resourceIdList = storageResourceRepository.getAllStorageResourceIdList();
            logger.debug("Airavata retrieved storage resources list...");
            return resourceIdList;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving storage resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving storage resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete a Storage Resource.
     *
     * @param storageResourceId The identifier of the requested compute resource to be deleted.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteStorageResource(String storageResourceId) throws RegistryServiceException, TException {
        try {
            storageResourceRepository.removeStorageResource(storageResourceId);
            logger.debug("Airavata deleted storage resource with storage resource Id : " + storageResourceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(storageResourceId, "Error while deleting storage resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting storage resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * This method returns localJobSubmission object
     *
     * @param jobSubmissionId@return LOCALSubmission instance
     */
    @Override
    public LOCALSubmission getLocalJobSubmission(String jobSubmissionId) throws RegistryServiceException, TException {
        try {
            LOCALSubmission localJobSubmission = new ComputeResourceRepository().getLocalJobSubmission(jobSubmissionId);
            logger.debug("Airavata retrieved local job submission for job submission interface id: " + jobSubmissionId);
            return localJobSubmission;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving local job submission interface to resource compute resource...";
            logger.error(jobSubmissionId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * This method returns SSHJobSubmission object
     *
     * @param jobSubmissionId@return SSHJobSubmission instance
     */
    @Override
    public SSHJobSubmission getSSHJobSubmission(String jobSubmissionId) throws RegistryServiceException, TException {
        try {
            SSHJobSubmission sshJobSubmission = new ComputeResourceRepository().getSSHJobSubmission(jobSubmissionId);
            logger.debug("Airavata retrieved SSH job submission for job submission interface id: " + jobSubmissionId);
            return sshJobSubmission;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving SSH job submission interface to resource compute resource...";
            logger.error(jobSubmissionId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * *
     * * This method returns UnicoreJobSubmission object
     * *
     * * @param jobSubmissionInterfaceId
     * *   The identifier of the JobSubmission Interface to be retrieved.
     * *  @return UnicoreJobSubmission instance
     * *
     * *
     *
     * @param jobSubmissionId
     */
    @Override
    public UnicoreJobSubmission getUnicoreJobSubmission(String jobSubmissionId)
            throws RegistryServiceException, TException {
        try {
            UnicoreJobSubmission unicoreJobSubmission =
                    new ComputeResourceRepository().getUNICOREJobSubmission(jobSubmissionId);
            logger.debug(
                    "Airavata retrieved UNICORE job submission for job submission interface id: " + jobSubmissionId);
            return unicoreJobSubmission;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving Unicore job submission interface to resource compute resource...";
            logger.error(jobSubmissionId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * *
     * * This method returns cloudJobSubmission object
     * * @param jobSubmissionInterfaceI
     * *   The identifier of the JobSubmission Interface to be retrieved.
     * *  @return CloudJobSubmission instance
     * *
     *
     * @param jobSubmissionId
     */
    @Override
    public CloudJobSubmission getCloudJobSubmission(String jobSubmissionId)
            throws RegistryServiceException, TException {
        try {
            CloudJobSubmission cloudJobSubmission =
                    new ComputeResourceRepository().getCloudJobSubmission(jobSubmissionId);
            logger.debug("Airavata retrieved cloud job submission for job submission interface id: " + jobSubmissionId);
            return cloudJobSubmission;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving Cloud job submission interface to resource compute resource...";
            logger.error(jobSubmissionId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * This method returns local datamovement object.
     *
     * @param dataMovementId The identifier of the datamovement Interface to be retrieved.
     * @return LOCALDataMovement instance
     */
    @Override
    public LOCALDataMovement getLocalDataMovement(String dataMovementId) throws RegistryServiceException, TException {
        try {
            LOCALDataMovement localDataMovement = new ComputeResourceRepository().getLocalDataMovement(dataMovementId);
            logger.debug("Airavata retrieved local data movement with data movement id: " + dataMovementId);
            return localDataMovement;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving local data movement interface to resource compute resource...";
            logger.error(dataMovementId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * This method returns SCP datamovement object
     *
     * @param dataMovementId The identifier of the datamovement Interface to be retrieved.
     * @return SCPDataMovement instance
     */
    @Override
    public SCPDataMovement getSCPDataMovement(String dataMovementId) throws RegistryServiceException, TException {
        try {
            SCPDataMovement scpDataMovement = new ComputeResourceRepository().getSCPDataMovement(dataMovementId);
            logger.debug("Airavata retrieved SCP data movement with data movement id: " + dataMovementId);
            return scpDataMovement;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving SCP data movement interface to resource compute resource...";
            logger.error(dataMovementId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * This method returns UNICORE datamovement object
     *
     * @param dataMovementId The identifier of the datamovement Interface to be retrieved.
     * @return UnicoreDataMovement instance
     */
    @Override
    public UnicoreDataMovement getUnicoreDataMovement(String dataMovementId)
            throws RegistryServiceException, TException {
        try {
            UnicoreDataMovement unicoreDataMovement =
                    new ComputeResourceRepository().getUNICOREDataMovement(dataMovementId);
            logger.debug("Airavata retrieved UNICORE data movement with data movement id: " + dataMovementId);
            return unicoreDataMovement;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving UNICORE data movement interface...";
            logger.error(dataMovementId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * This method returns GridFTP datamovement object
     *
     * @param dataMovementId The identifier of the datamovement Interface to be retrieved.
     * @return GridFTPDataMovement instance
     */
    @Override
    public GridFTPDataMovement getGridFTPDataMovement(String dataMovementId)
            throws RegistryServiceException, TException {
        try {
            GridFTPDataMovement gridFTPDataMovement =
                    new ComputeResourceRepository().getGridFTPDataMovement(dataMovementId);
            logger.debug("Airavata retrieved GRIDFTP data movement with data movement id: " + dataMovementId);
            return gridFTPDataMovement;
        } catch (AppCatalogException e) {
            String errorMsg = "Error while retrieving GridFTP data movement interface to resource compute resource...";
            logger.error(dataMovementId, errorMsg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(errorMsg + e.getMessage());
            throw exception;
        }
    }

    /**
     * Change the priority of a given job submisison interface
     *
     * @param jobSubmissionInterfaceId The identifier of the JobSubmission Interface to be changed
     * @param newPriorityOrder
     * @return status
     * Returns a success/failure of the change.
     */
    @Override
    public boolean changeJobSubmissionPriority(String jobSubmissionInterfaceId, int newPriorityOrder)
            throws RegistryServiceException, TException {
        return false;
    }

    /**
     * Change the priority of a given data movement interface
     *
     * @param dataMovementInterfaceId The identifier of the DataMovement Interface to be changed
     * @param newPriorityOrder
     * @return status
     * Returns a success/failure of the change.
     */
    @Override
    public boolean changeDataMovementPriority(String dataMovementInterfaceId, int newPriorityOrder)
            throws RegistryServiceException, TException {
        return false;
    }

    /**
     * Change the priorities of a given set of job submission interfaces
     *
     * @param jobSubmissionPriorityMap A Map of identifiers of the JobSubmission Interfaces and thier associated priorities to be set.
     * @return status
     * Returns a success/failure of the changes.
     */
    @Override
    public boolean changeJobSubmissionPriorities(Map<String, Integer> jobSubmissionPriorityMap)
            throws RegistryServiceException, TException {
        return false;
    }

    /**
     * Change the priorities of a given set of data movement interfaces
     *
     * @param dataMovementPriorityMap A Map of identifiers of the DataMovement Interfaces and thier associated priorities to be set.
     * @return status
     * Returns a success/failure of the changes.
     */
    @Override
    public boolean changeDataMovementPriorities(Map<String, Integer> dataMovementPriorityMap)
            throws RegistryServiceException, TException {
        return false;
    }

    /**
     * Delete a given job submisison interface
     *
     * @param computeResourceId
     * @param jobSubmissionInterfaceId The identifier of the JobSubmission Interface to be changed
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteJobSubmissionInterface(String computeResourceId, String jobSubmissionInterfaceId)
            throws RegistryServiceException, TException {
        try {
            new ComputeResourceRepository().removeJobSubmissionInterface(computeResourceId, jobSubmissionInterfaceId);
            logger.debug("Airavata deleted job submission interface with interface id : " + jobSubmissionInterfaceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(jobSubmissionInterfaceId, "Error while deleting job submission interface...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting job submission interface. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public ResourceJobManager getResourceJobManager(String resourceJobManagerId)
            throws RegistryServiceException, TException {
        try {
            return new ComputeResourceRepository().getResourceJobManager(resourceJobManagerId);
        } catch (AppCatalogException e) {
            logger.error(resourceJobManagerId, "Error while retrieving resource job manager...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving resource job manager. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean deleteResourceJobManager(String resourceJobManagerId) throws RegistryServiceException, TException {
        try {
            new ComputeResourceRepository().deleteResourceJobManager(resourceJobManagerId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(resourceJobManagerId, "Error while deleting resource job manager...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting resource job manager. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete a Compute Resource Queue
     *
     * @param computeResourceId The identifier of the compute resource which has the queue to be deleted
     * @param queueName         Name of the queue need to be deleted. Name is the uniqueue identifier for the queue within a compute resource
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteBatchQueue(String computeResourceId, String queueName)
            throws RegistryServiceException, TException {
        try {
            new ComputeResourceRepository().removeBatchQueue(computeResourceId, queueName);
            return true;
        } catch (AppCatalogException e) {
            logger.error(computeResourceId, "Error while deleting batch queue...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting batch queue. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch the given Gateway Resource Profile.
     *
     * @param gatewayID The identifier for the requested gateway resource.
     * @return gatewayResourceProfile
     * Gateway Resource Profile Object.
     */
    @Override
    public GatewayResourceProfile getGatewayResourceProfile(String gatewayID)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            GatewayResourceProfile gatewayResourceProfile = gwyResourceProfileRepository.getGatewayProfile(gatewayID);
            logger.debug("Airavata retrieved gateway profile with gateway id : " + gatewayID);
            return gatewayResourceProfile;
        } catch (Exception e) {
            logger.error(gatewayID, "Error while retrieving gateway resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving gateway resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete the given Gateway Resource Profile.
     *
     * @param gatewayID The identifier for the requested gateway resource to be deleted.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteGatewayResourceProfile(String gatewayID) throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            gwyResourceProfileRepository.delete(gatewayID);
            logger.debug("Airavata deleted gateway profile with gateway id : " + gatewayID);
            return true;
        } catch (Exception e) {
            logger.error(gatewayID, "Error while removing gateway resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while removing gateway resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch a Compute Resource Preference of a registered gateway profile.
     *
     * @param gatewayID         The identifier for the gateway profile to be requested
     * @param computeResourceId Preferences related to a particular compute resource
     * @return computeResourcePreference
     * Returns the ComputeResourcePreference object.
     */
    @Override
    public ComputeResourcePreference getGatewayComputeResourcePreference(String gatewayID, String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            if (!gwyResourceProfileRepository.isGatewayResourceProfileExists(gatewayID)) {
                logger.error(
                        gatewayID,
                        "Given gateway profile does not exist in the system. Please provide a valid gateway id...");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage(
                        "Given gateway profile does not exist in the system. Please provide a valid gateway id...");
                throw exception;
            }
            if (!computeResourceRepository.isComputeResourceExists(computeResourceId)) {
                logger.error(
                        computeResourceId,
                        "Given compute resource does not exist in the system. Please provide a valid compute resource id...");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage(
                        "Given compute resource does not exist in the system. Please provide a valid compute resource id...");
                throw exception;
            }
            ComputeResourcePreference computeResourcePreference =
                    gwyResourceProfileRepository.getComputeResourcePreference(gatewayID, computeResourceId);
            logger.debug("Airavata retrieved gateway compute resource preference with gateway id : " + gatewayID
                    + " and for compute resoruce id : " + computeResourceId);
            return computeResourcePreference;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while reading gateway compute resource preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while reading gateway compute resource preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch a Storage Resource Preference of a registered gateway profile.
     *
     * @param gatewayID The identifier of the gateway profile to request to fetch the particular storage resource preference.
     * @param storageId Identifier of the Stprage Preference required to be fetched.
     * @return StoragePreference
     * Returns the StoragePreference object.
     */
    @Override
    public StoragePreference getGatewayStoragePreference(String gatewayID, String storageId)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            if (!gwyResourceProfileRepository.isGatewayResourceProfileExists(gatewayID)) {
                logger.error(
                        gatewayID,
                        "Given gateway profile does not exist in the system. Please provide a valid gateway id...");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage(
                        "Given gateway profile does not exist in the system. Please provide a valid gateway id...");
                throw exception;
            }

            StoragePreference storagePreference =
                    gwyResourceProfileRepository.getStoragePreference(gatewayID, storageId);
            logger.debug("Airavata retrieved storage resource preference with gateway id : " + gatewayID
                    + " and for storage resource id : " + storageId);
            return storagePreference;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while reading gateway data storage preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading gateway data storage preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Compute Resource Preferences of a registered gateway profile.
     *
     * @param gatewayID The identifier for the gateway profile to be requested
     * @return computeResourcePreference
     * Returns the ComputeResourcePreference object.
     */
    @Override
    public List<ComputeResourcePreference> getAllGatewayComputeResourcePreferences(String gatewayID)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            return gwyResourceProfileRepository.getGatewayProfile(gatewayID).getComputeResourcePreferences();
        } catch (Exception e) {
            logger.error(gatewayID, "Error while reading gateway compute resource preferences...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while reading gateway compute resource preferences. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Storage Resource Preferences of a registered gateway profile.
     *
     * @param gatewayID The identifier for the gateway profile to be requested
     * @return StoragePreference
     * Returns the StoragePreference object.
     */
    @Override
    public List<StoragePreference> getAllGatewayStoragePreferences(String gatewayID)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            return gwyResourceProfileRepository.getGatewayProfile(gatewayID).getStoragePreferences();
        } catch (Exception e) {
            logger.error(gatewayID, "Error while reading gateway data storage preferences...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading gateway data storage preferences. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Gateway Profiles registered
     *
     * @return GatewayResourceProfile
     * Returns all the GatewayResourcePrifle list object.
     */
    @Override
    public List<GatewayResourceProfile> getAllGatewayResourceProfiles() throws RegistryServiceException, TException {
        try {
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            return gwyResourceProfileRepository.getAllGatewayProfiles();
        } catch (Exception e) {
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading retrieving all gateway profiles. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete the Compute Resource Preference of a registered gateway profile.
     *
     * @param gatewayID         The identifier for the gateway profile to be deleted.
     * @param computeResourceId Preferences related to a particular compute resource
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteGatewayComputeResourcePreference(String gatewayID, String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();

            return gwyResourceProfileRepository.removeComputeResourcePreferenceFromGateway(
                    gatewayID, computeResourceId);
        } catch (Exception e) {
            logger.error(gatewayID, "Error while reading gateway compute resource preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while updating gateway compute resource preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete the Storage Resource Preference of a registered gateway profile.
     *
     * @param gatewayID The identifier of the gateway profile to be deleted.
     * @param storageId ID of the storage preference you want to delete.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteGatewayStoragePreference(String gatewayID, String storageId)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }

            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            return gwyResourceProfileRepository.removeDataStoragePreferenceFromGateway(gatewayID, storageId);
        } catch (Exception e) {
            logger.error(gatewayID, "Error while reading gateway data storage preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating gateway data storage preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public DataProductModel getDataProduct(String productUri) throws RegistryServiceException, TException {
        try {
            DataProductModel dataProductModel = dataProductRepository.getDataProduct(productUri);
            return dataProductModel;
        } catch (RegistryException e) {
            String msg = "Error in retreiving the data product " + productUri + ".";
            logger.error(msg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(msg + " More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public DataProductModel getParentDataProduct(String productUri) throws RegistryServiceException, TException {
        try {
            DataProductModel dataProductModel = dataProductRepository.getParentDataProduct(productUri);
            return dataProductModel;
        } catch (RegistryException e) {
            String msg = "Error in retreiving the parent data product for " + productUri + ".";
            logger.error(msg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(msg + " More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<DataProductModel> getChildDataProducts(String productUri) throws RegistryServiceException, TException {
        try {
            List<DataProductModel> dataProductModels = dataProductRepository.getChildDataProducts(productUri);
            return dataProductModels;
        } catch (RegistryException e) {
            String msg = "Error in retreiving the child products for " + productUri + ".";
            logger.error(msg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(msg + " More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<DataProductModel> searchDataProductsByName(
            String gatewayId, String userId, String productName, int limit, int offset)
            throws RegistryServiceException, TException {
        try {
            List<DataProductModel> dataProductModels =
                    dataProductRepository.searchDataProductsByName(gatewayId, userId, productName, limit, offset);
            return dataProductModels;
        } catch (RegistryException e) {
            String msg = "Error in searching the data products for name " + productName + ".";
            logger.error(msg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(msg + " More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public String createGroupResourceProfile(GroupResourceProfile groupResourceProfile)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(groupResourceProfile.getGatewayId())) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            String groupResourceProfileId =
                    groupResourceProfileRepository.addGroupResourceProfile(groupResourceProfile);
            logger.debug("New Group Resource Profile Created: " + groupResourceProfileId);
            return groupResourceProfileId;
        } catch (Exception e) {
            logger.error("Error while creating group resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while creating group resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void updateGroupResourceProfile(GroupResourceProfile groupResourceProfile)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            if (!groupResourceProfileRepository.isGroupResourceProfileExists(
                    groupResourceProfile.getGroupResourceProfileId())) {
                logger.error(
                        "Cannot update. No group resource profile found with matching gatewayId and groupResourceProfileId");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage(
                        "Cannot update. No group resource profile found with matching gatewayId and groupResourceProfileId");
                throw exception;
            }
            String groupResourceProfileId =
                    groupResourceProfileRepository.updateGroupResourceProfile(groupResourceProfile);
            logger.debug(" Group Resource Profile updated: " + groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while updating group resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating group resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public GroupResourceProfile getGroupResourceProfile(String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            if (!groupResourceProfileRepository.isGroupResourceProfileExists(groupResourceProfileId)) {
                logger.error("No group resource profile found with matching gatewayId and groupResourceProfileId");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage(
                        "No group resource profile found with matching gatewayId and groupResourceProfileId");
                throw exception;
            }

            return groupResourceProfileRepository.getGroupResourceProfile(groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while retrieving group resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving group resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean isGroupResourceProfileExists(String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            return groupResourceProfileRepository.isGroupResourceProfileExists(groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while retrieving group resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving group resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean removeGroupResourceProfile(String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            if (!groupResourceProfileRepository.isGroupResourceProfileExists(groupResourceProfileId)) {
                logger.error(
                        "Cannot Remove. No group resource profile found with matching gatewayId and groupResourceProfileId");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage(
                        "Cannot Remove. No group resource profile found with matching gatewayId and groupResourceProfileId");
                throw exception;
            }
            return groupResourceProfileRepository.removeGroupResourceProfile(groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while removing group resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while removing group resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<GroupResourceProfile> getGroupResourceList(String gatewayId, List<String> accessibleGroupResProfileIds)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            return groupResourceProfileRepository.getAllGroupResourceProfiles(gatewayId, accessibleGroupResProfileIds);
        } catch (Exception e) {
            logger.error("Error while retrieving group resource list ", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving group resource list. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean removeGroupComputePrefs(String computeResourceId, String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            groupResourceProfileRepository.removeGroupComputeResourcePreference(
                    computeResourceId, groupResourceProfileId);
            logger.debug("Removed compute resource preferences with compute resource ID: " + computeResourceId);
            return true;
        } catch (Exception e) {
            logger.error("Error while removing group compute preference", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while removing group compute preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean removeGroupComputeResourcePolicy(String resourcePolicyId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            groupResourceProfileRepository.removeComputeResourcePolicy(resourcePolicyId);
            logger.debug("Removed compute resource policy with resource policy ID: " + resourcePolicyId);
            return true;
        } catch (Exception e) {
            logger.error("Error while removing group compute resource policy", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while removing group compute resource policy. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean removeGroupBatchQueueResourcePolicy(String resourcePolicyId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            groupResourceProfileRepository.removeBatchQueueResourcePolicy(resourcePolicyId);
            logger.debug("Removed batch resource policy with resource policy ID: " + resourcePolicyId);
            return true;
        } catch (Exception e) {
            logger.error("Error while removing group batch queue resource policy", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while removing group batch queue resource policy. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public GroupComputeResourcePreference getGroupComputeResourcePreference(
            String computeResourceId, String groupResourceProfileId) throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            GroupComputeResourcePreference groupComputeResourcePreference =
                    groupResourceProfileRepository.getGroupComputeResourcePreference(
                            computeResourceId, groupResourceProfileId);
            if (!(groupComputeResourcePreference != null)) {
                logger.error("GroupComputeResourcePreference not found");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage("GroupComputeResourcePreference not found ");
                throw exception;
            }
            return groupComputeResourcePreference;

        } catch (Exception e) {
            logger.error("Error while retrieving group compute resource preference", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while retrieving group compute resource preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean isGroupComputeResourcePreferenceExists(String computeResourceId, String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            return groupResourceProfileRepository.isGroupComputeResourcePreferenceExists(
                    computeResourceId, groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while retrieving group compute resource preference", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while retrieving group compute resource preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public ComputeResourcePolicy getGroupComputeResourcePolicy(String resourcePolicyId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            ComputeResourcePolicy computeResourcePolicy =
                    groupResourceProfileRepository.getComputeResourcePolicy(resourcePolicyId);
            if (!(computeResourcePolicy != null)) {
                logger.error("Group Compute Resource policy not found");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage("Group Compute Resource policy not found ");
                throw exception;
            }
            return computeResourcePolicy;
        } catch (Exception e) {
            logger.error("Error while retrieving group compute resource policy", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving group compute resource policy. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public BatchQueueResourcePolicy getBatchQueueResourcePolicy(String resourcePolicyId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            BatchQueueResourcePolicy batchQueueResourcePolicy =
                    groupResourceProfileRepository.getBatchQueueResourcePolicy(resourcePolicyId);
            if (!(batchQueueResourcePolicy != null)) {
                logger.error("Group Batch Queue Resource policy not found");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage("Group Batch Queue Resource policy not found ");
                throw exception;
            }
            return batchQueueResourcePolicy;
        } catch (Exception e) {
            logger.error("Error while retrieving Batch Queue resource policy", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving Batch Queue resource policy. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<GroupComputeResourcePreference> getGroupComputeResourcePrefList(String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            return groupResourceProfileRepository.getAllGroupComputeResourcePreferences(groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while retrieving retrieving Group Compute Resource Preference list", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while retrieving retrieving Group Compute Resource Preference list. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<BatchQueueResourcePolicy> getGroupBatchQueueResourcePolicyList(String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            return groupResourceProfileRepository.getAllGroupBatchQueueResourcePolicies(groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while retrieving retrieving Group Batch Queue Resource policy list", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while retrieving retrieving Group Batch Queue Resource policy list. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    @Override
    public List<ComputeResourcePolicy> getGroupComputeResourcePolicyList(String groupResourceProfileId)
            throws RegistryServiceException, TException {
        try {
            GroupResourceProfileRepository groupResourceProfileRepository = new GroupResourceProfileRepository();
            return groupResourceProfileRepository.getAllGroupComputeResourcePolicies(groupResourceProfileId);
        } catch (Exception e) {
            logger.error("Error while retrieving retrieving Group Compute Resource policy list", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving retrieving Group Compute Resource policy list. More info : "
                    + e.getMessage());
            throw exception;
        }
    }

    @Override
    public String registerReplicaLocation(DataReplicaLocationModel replicaLocationModel)
            throws RegistryServiceException, TException {
        try {
            String replicaId = dataReplicaLocationRepository.registerReplicaLocation(replicaLocationModel);
            return replicaId;
        } catch (RegistryException e) {
            String msg = "Error in retreiving the replica " + replicaLocationModel.getReplicaName() + ".";
            logger.error(msg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(msg + " More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * API Methods related to replica catalog
     *
     * @param dataProductModel
     */
    @Override
    public String registerDataProduct(DataProductModel dataProductModel) throws RegistryServiceException, TException {
        try {
            String productUrl = dataProductRepository.registerDataProduct(dataProductModel);
            return productUrl;
        } catch (RegistryException e) {
            String msg = "Error in registering the data resource" + dataProductModel.getProductName() + ".";
            logger.error(msg, e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(msg + " More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Storage Resource Preference of a registered gateway profile.
     *
     * @param gatewayID         The identifier of the gateway profile to be updated.
     * @param storageId         The Storage resource identifier of the one that you want to update
     * @param storagePreference The storagePreference object to be updated to the resource profile.
     * @return status
     * Returns a success/failure of the updation.
     */
    @Override
    public boolean updateGatewayStoragePreference(
            String gatewayID, String storageId, StoragePreference storagePreference)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            GatewayResourceProfile profile = gwyResourceProfileRepository.getGatewayProfile(gatewayID);
            List<StoragePreference> dataStoragePreferences = profile.getStoragePreferences();
            StoragePreference preferenceToRemove = null;
            for (StoragePreference preference : dataStoragePreferences) {
                if (preference.getStorageResourceId().equals(storageId)) {
                    preferenceToRemove = preference;
                    break;
                }
            }
            if (preferenceToRemove != null) {
                profile.getStoragePreferences().remove(preferenceToRemove);
            }
            profile.getStoragePreferences().add(storagePreference);
            gwyResourceProfileRepository.updateGatewayResourceProfile(profile);
            logger.debug("Airavata updated storage resource preference with gateway id : " + gatewayID
                    + " and for storage resource id : " + storageId);
            return true;
        } catch (Exception e) {
            logger.error(gatewayID, "Error while reading gateway data storage preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating gateway data storage preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Compute Resource Preference to a registered gateway profile.
     *
     * @param gatewayID                 The identifier for the gateway profile to be updated.
     * @param computeResourceId         Preferences related to a particular compute resource
     * @param computeResourcePreference The ComputeResourcePreference object to be updated to the resource profile.
     * @return status
     * Returns a success/failure of the updation.
     */
    @Override
    public boolean updateGatewayComputeResourcePreference(
            String gatewayID, String computeResourceId, ComputeResourcePreference computeResourcePreference)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            GatewayResourceProfile profile = gwyResourceProfileRepository.getGatewayProfile(gatewayID);
            List<ComputeResourcePreference> computeResourcePreferences = profile.getComputeResourcePreferences();
            ComputeResourcePreference preferenceToRemove = null;
            for (ComputeResourcePreference preference : computeResourcePreferences) {
                if (preference.getComputeResourceId().equals(computeResourceId)) {
                    preferenceToRemove = preference;
                    break;
                }
            }
            if (preferenceToRemove != null) {
                profile.getComputeResourcePreferences().remove(preferenceToRemove);
            }
            profile.getComputeResourcePreferences().add(computeResourcePreference);
            gwyResourceProfileRepository.updateGatewayResourceProfile(profile);
            logger.debug("Airavata updated compute resource preference with gateway id : " + gatewayID
                    + " and for compute resource id : " + computeResourceId);
            return true;
        } catch (Exception e) {
            logger.error(gatewayID, "Error while reading gateway compute resource preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while updating gateway compute resource preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a Storage Resource Preference to a registered gateway profile.
     *
     * @param gatewayID             The identifier of the gateway profile to be added.
     * @param storageResourceId     Preferences related to a particular compute resource
     * @param dataStoragePreference
     * @return status
     * Returns a success/failure of the addition. If a profile already exists, this operation will fail.
     * Instead an update should be used.
     */
    @Override
    public boolean addGatewayStoragePreference(
            String gatewayID, String storageResourceId, StoragePreference dataStoragePreference)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }

            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            if (!(gwyResourceProfileRepository.isExists(gatewayID))) {
                throw new RegistryServiceException("Gateway resource profile '" + gatewayID + "' does not exist!!!");
            }
            GatewayResourceProfile profile = gwyResourceProfileRepository.getGatewayProfile(gatewayID);

            dataStoragePreference.setStorageResourceId(storageResourceId);
            profile.addToStoragePreferences(dataStoragePreference);
            gwyResourceProfileRepository.updateGatewayResourceProfile(profile);
            logger.debug("Airavata added storage resource preference with gateway id : " + gatewayID
                    + " and for storage resource id : " + storageResourceId);
            return true;
        } catch (Exception e) {
            logger.error(gatewayID, "Error while registering gateway resource profile preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while registering gateway resource profile preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a Compute Resource Preference to a registered gateway profile.
     *
     * @param gatewayID                 The identifier for the gateway profile to be added.
     * @param computeResourceId         Preferences related to a particular compute resource
     * @param computeResourcePreference The ComputeResourcePreference object to be added to the resource profile.
     * @return status
     * Returns a success/failure of the addition. If a profile already exists, this operation will fail.
     * Instead an update should be used.
     */
    @Override
    public boolean addGatewayComputeResourcePreference(
            String gatewayID, String computeResourceId, ComputeResourcePreference computeResourcePreference)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            if (!(gwyResourceProfileRepository.isExists(gatewayID))) {
                throw new RegistryServiceException("Gateway resource profile '" + gatewayID + "' does not exist!!!");
            }
            GatewayResourceProfile profile = gwyResourceProfileRepository.getGatewayProfile(gatewayID);
            profile.addToComputeResourcePreferences(computeResourcePreference);
            gwyResourceProfileRepository.updateGatewayResourceProfile(profile);
            logger.debug("Airavata added gateway compute resource preference with gateway id : " + gatewayID
                    + " and for compute resource id : " + computeResourceId);
            return true;
        } catch (Exception e) {
            logger.error(gatewayID, "Error while registering gateway resource profile preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while registering gateway resource profile preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Gateway Resource Profile.
     *
     * @param gatewayID              The identifier for the requested gateway resource to be updated.
     * @param gatewayResourceProfile Gateway Resource Profile Object.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateGatewayResourceProfile(String gatewayID, GatewayResourceProfile gatewayResourceProfile)
            throws RegistryServiceException, TException {
        try {
            if (!isGatewayExistInternal(gatewayID)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            gwyResourceProfileRepository.updateGatewayResourceProfile(gatewayResourceProfile);
            logger.debug("Airavata updated gateway profile with gateway id : " + gatewayID);
            return true;
        } catch (Exception e) {
            logger.error(gatewayID, "Error while updating gateway resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating gateway resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Register a Gateway Resource Profile.
     *
     * @param gatewayResourceProfile Gateway Resource Profile Object.
     *                               The GatewayID should be obtained from Airavata gateway registration and passed to register a corresponding
     *                               resource profile.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public String registerGatewayResourceProfile(GatewayResourceProfile gatewayResourceProfile)
            throws RegistryServiceException, TException {
        try {
            if (!validateString(gatewayResourceProfile.getGatewayID())) {
                logger.error("Cannot create gateway profile with empty gateway id");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage("Cannot create gateway profile with empty gateway id");
                throw exception;
            }
            if (!isGatewayExistInternal(gatewayResourceProfile.getGatewayID())) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            GwyResourceProfileRepository gwyResourceProfileRepository = new GwyResourceProfileRepository();
            String resourceProfile = gwyResourceProfileRepository.addGatewayResourceProfile(gatewayResourceProfile);
            logger.debug(
                    "Airavata registered gateway profile with gateway id : " + gatewayResourceProfile.getGatewayID());
            return resourceProfile;
        } catch (Exception e) {
            logger.error("Error while registering gateway resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while registering gateway resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean updateResourceJobManager(String resourceJobManagerId, ResourceJobManager updatedResourceJobManager)
            throws RegistryServiceException, TException {
        try {
            new ComputeResourceRepository().updateResourceJobManager(resourceJobManagerId, updatedResourceJobManager);
            return true;
        } catch (AppCatalogException e) {
            logger.error(resourceJobManagerId, "Error while updating resource job manager...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating resource job manager. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public String registerResourceJobManager(ResourceJobManager resourceJobManager)
            throws RegistryServiceException, TException {
        try {
            return new ComputeResourceRepository().addResourceJobManager(resourceJobManager);
        } catch (AppCatalogException e) {
            logger.error(resourceJobManager.getResourceJobManagerId(), "Error while adding resource job manager...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding resource job manager. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete a given data movement interface
     *
     * @param dataMovementInterfaceId The identifier of the DataMovement Interface to be changed
     * @param dmType
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteDataMovementInterface(String resourceId, String dataMovementInterfaceId, DMType dmType)
            throws RegistryServiceException, TException {
        try {
            switch (dmType) {
                case COMPUTE_RESOURCE:
                    new ComputeResourceRepository().removeDataMovementInterface(resourceId, dataMovementInterfaceId);
                    logger.debug(
                            "Airavata deleted data movement interface with interface id : " + dataMovementInterfaceId);
                    return true;
                case STORAGE_RESOURCE:
                    storageResourceRepository.removeDataMovementInterface(resourceId, dataMovementInterfaceId);
                    logger.debug(
                            "Airavata deleted data movement interface with interface id : " + dataMovementInterfaceId);
                    return true;
                default:
                    logger.error(
                            "Unsupported data movement type specifies.. Please provide the correct data movement type... ");
                    return false;
            }
        } catch (AppCatalogException e) {
            logger.error(dataMovementInterfaceId, "Error while deleting data movement interface...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while deleting data movement interface. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update the given GridFTP data movement details to a compute resource
     * App catalog will return a dataMovementInterfaceId which will be added to the dataMovementInterfaces.
     *
     * @param dataMovementInterfaceId The identifier of the data movement Interface to be updated.
     * @param gridFTPDataMovement     The GridFTPDataMovement object to be updated.
     * @return boolean
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateGridFTPDataMovementDetails(
            String dataMovementInterfaceId, GridFTPDataMovement gridFTPDataMovement)
            throws RegistryServiceException, TException {
        throw new RegistryServiceException("updateGridFTPDataMovementDetails is not yet implemented");
    }

    /**
     * Add a GridFTP data movement details to a compute resource
     * App catalog will return a dataMovementInterfaceId which will be added to the dataMovementInterfaces.
     * <p>
     * productUri          The identifier of the compute resource to which dataMovement protocol to be added
     *
     * @param dmType
     * @param priorityOrder       Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param gridFTPDataMovement The GridFTPDataMovement object to be added to the resource.
     * @return status
     * Returns the unique data movement id.
     */
    @Override
    public String addGridFTPDataMovementDetails(
            String computeResourceId, DMType dmType, int priorityOrder, GridFTPDataMovement gridFTPDataMovement)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String addDataMovementInterface = addDataMovementInterface(
                    computeResourceRepository,
                    computeResourceId,
                    dmType,
                    computeResourceRepository.addGridFTPDataMovement(gridFTPDataMovement),
                    DataMovementProtocol.GridFTP,
                    priorityOrder);
            logger.debug("Airavata registered GridFTP data movement for resource Id: " + computeResourceId);
            return addDataMovementInterface;
        } catch (AppCatalogException e) {
            logger.error(
                    computeResourceId, "Error while adding data movement interface to resource compute resource...", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while adding data movement interface to resource compute resource. More info : "
                    + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a selected UNICORE data movement details
     * App catalog will return a dataMovementInterfaceId which will be added to the dataMovementInterfaces.
     *
     * @param dataMovementInterfaceId The identifier of the data movement Interface to be updated.
     * @param unicoreDataMovement
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateUnicoreDataMovementDetails(
            String dataMovementInterfaceId, UnicoreDataMovement unicoreDataMovement)
            throws RegistryServiceException, TException {
        throw new RegistryServiceException("updateUnicoreDataMovementDetails is not yet implemented");
    }

    /**
     * Add a UNICORE data movement details to a compute resource
     * App catalog will return a dataMovementInterfaceId which will be added to the dataMovementInterfaces.
     * <p>
     * productUri          The identifier of the compute resource to which data movement protocol to be added
     *
     * @param dmType
     * @param priorityOrder       Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param unicoreDataMovement
     * @return status
     * Returns the unique data movement id.
     */
    @Override
    public String addUnicoreDataMovementDetails(
            String resourceId, DMType dmType, int priorityOrder, UnicoreDataMovement unicoreDataMovement)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String movementInterface = addDataMovementInterface(
                    computeResourceRepository,
                    resourceId,
                    dmType,
                    computeResourceRepository.addUnicoreDataMovement(unicoreDataMovement),
                    DataMovementProtocol.UNICORE_STORAGE_SERVICE,
                    priorityOrder);
            logger.debug("Airavata registered UNICORE data movement for resource Id: " + resourceId);
            return movementInterface;
        } catch (AppCatalogException e) {
            logger.error(resourceId, "Error while adding data movement interface to resource compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding data movement interface to resource compute resource. More info : "
                    + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update the given scp data movement details
     * App catalog will return a dataMovementInterfaceId which will be added to the dataMovementInterfaces.
     *
     * @param dataMovementInterfaceId The identifier of the data movement Interface to be updated.
     * @param scpDataMovement         The SCPDataMovement object to be updated.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateSCPDataMovementDetails(String dataMovementInterfaceId, SCPDataMovement scpDataMovement)
            throws RegistryServiceException, TException {
        try {
            computeResourceRepository.updateScpDataMovement(scpDataMovement);
            logger.debug("Airavata updated SCP data movement with data movement id: " + dataMovementInterfaceId);
            return true;
        } catch (Exception e) {
            logger.error(
                    dataMovementInterfaceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a SCP data movement details to a compute resource
     * App catalog will return a dataMovementInterfaceId which will be added to the dataMovementInterfaces.
     * <p>
     * productUri      The identifier of the compute resource to which JobSubmission protocol to be added
     *
     * @param dmType
     * @param priorityOrder   Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param scpDataMovement The SCPDataMovement object to be added to the resource.
     * @return status
     * Returns the unique job submission id.
     */
    @Override
    public String addSCPDataMovementDetails(
            String resourceId, DMType dmType, int priorityOrder, SCPDataMovement scpDataMovement)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String movementInterface = addDataMovementInterface(
                    computeResourceRepository,
                    resourceId,
                    dmType,
                    computeResourceRepository.addScpDataMovement(scpDataMovement),
                    DataMovementProtocol.SCP,
                    priorityOrder);
            logger.debug("Airavata registered SCP data movement for resource Id: " + resourceId);
            return movementInterface;
        } catch (AppCatalogException e) {
            logger.error(resourceId, "Error while adding data movement interface to resource compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding data movement interface to resource compute resource. More info : "
                    + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update the given Local data movement details
     *
     * @param dataMovementInterfaceId The identifier of the data movement Interface to be updated.
     * @param localDataMovement       The LOCALDataMovement object to be updated.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateLocalDataMovementDetails(String dataMovementInterfaceId, LOCALDataMovement localDataMovement)
            throws RegistryServiceException, TException {
        try {
            computeResourceRepository.updateLocalDataMovement(localDataMovement);
            logger.debug("Airavata updated local data movement with data movement id: " + dataMovementInterfaceId);
            return true;
        } catch (Exception e) {
            logger.error(dataMovementInterfaceId, "Error while updating local data movement interface..", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating local data movement interface. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a Local data movement details to a compute resource
     * App catalog will return a dataMovementInterfaceId which will be added to the dataMovementInterfaces.
     * <p>
     * productUri        The identifier of the compute resource to which JobSubmission protocol to be added
     *
     * @param dataMoveType
     * @param priorityOrder     Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param localDataMovement The LOCALDataMovement object to be added to the resource.
     * @return status
     * Returns the unique job submission id.
     */
    @Override
    public String addLocalDataMovementDetails(
            String resourceId, DMType dataMoveType, int priorityOrder, LOCALDataMovement localDataMovement)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String movementInterface = addDataMovementInterface(
                    computeResourceRepository,
                    resourceId,
                    dataMoveType,
                    computeResourceRepository.addLocalDataMovement(localDataMovement),
                    DataMovementProtocol.LOCAL,
                    priorityOrder);
            logger.debug("Airavata registered local data movement for resource Id: " + resourceId);
            return movementInterface;
        } catch (AppCatalogException e) {
            logger.error(resourceId, "Error while adding data movement interface to resource resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding data movement interface to resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update the UNIOCRE Job Submission details
     *
     * @param jobSubmissionInterfaceId The identifier of the JobSubmission Interface to be updated.
     * @param unicoreJobSubmission
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateUnicoreJobSubmissionDetails(
            String jobSubmissionInterfaceId, UnicoreJobSubmission unicoreJobSubmission)
            throws RegistryServiceException, TException {
        throw new RegistryServiceException("updateUnicoreJobSubmissionDetails is not yet implemented");
    }

    /**
     * Update the cloud Job Submission details
     *
     * @param jobSubmissionInterfaceId The identifier of the JobSubmission Interface to be updated.
     * @param sshJobSubmission
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateCloudJobSubmissionDetails(String jobSubmissionInterfaceId, CloudJobSubmission sshJobSubmission)
            throws RegistryServiceException, TException {
        try {
            computeResourceRepository.updateCloudJobSubmission(sshJobSubmission);
            logger.debug("Airavata updated Cloud job submission for job submission interface id: "
                    + jobSubmissionInterfaceId);
            return true;
        } catch (Exception e) {
            logger.error(
                    jobSubmissionInterfaceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update the given SSH Job Submission details
     *
     * @param jobSubmissionInterfaceId The identifier of the JobSubmission Interface to be updated.
     * @param sshJobSubmission         The SSHJobSubmission object to be updated.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateSSHJobSubmissionDetails(String jobSubmissionInterfaceId, SSHJobSubmission sshJobSubmission)
            throws RegistryServiceException, TException {
        try {
            computeResourceRepository.updateSSHJobSubmission(sshJobSubmission);
            logger.debug(
                    "Airavata updated SSH job submission for job submission interface id: " + jobSubmissionInterfaceId);
            return true;
        } catch (Exception e) {
            logger.error(
                    jobSubmissionInterfaceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * *
     * * Add a Cloud Job Submission details to a compute resource
     * *  App catalog will return a jobSubmissionInterfaceId which will be added to the jobSubmissionInterfaces.
     * *
     * * @param computeResourceId
     * *   The identifier of the compute resource to which JobSubmission protocol to be added
     * *
     * * @param priorityOrder
     * *   Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * *
     * * @param sshJobSubmission
     * *   The SSHJobSubmission object to be added to the resource.
     * *
     * * @return status
     * *   Returns the unique job submission id.
     * *
     * *
     *
     * @param computeResourceId
     * @param priorityOrder
     * @param cloudSubmission
     */
    @Override
    public String addCloudJobSubmissionDetails(
            String computeResourceId, int priorityOrder, CloudJobSubmission cloudSubmission)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String submissionInterface = addJobSubmissionInterface(
                    computeResourceRepository,
                    computeResourceId,
                    computeResourceRepository.addCloudJobSubmission(cloudSubmission),
                    JobSubmissionProtocol.CLOUD,
                    priorityOrder);
            logger.debug("Airavata registered Cloud job submission for compute resource id: " + computeResourceId);
            return submissionInterface;
        } catch (AppCatalogException e) {
            logger.error(
                    computeResourceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a UNICORE Job Submission details to a compute resource
     * App catalog will return a jobSubmissionInterfaceId which will be added to the jobSubmissionInterfaces.
     *
     * @param computeResourceId    The identifier of the compute resource to which JobSubmission protocol to be added
     * @param priorityOrder        Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param unicoreJobSubmission The UnicoreJobSubmission object to be added to the resource.
     * @return status
     * Returns the unique job submission id.
     */
    @Override
    public String addUNICOREJobSubmissionDetails(
            String computeResourceId, int priorityOrder, UnicoreJobSubmission unicoreJobSubmission)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String submissionInterface = addJobSubmissionInterface(
                    computeResourceRepository,
                    computeResourceId,
                    computeResourceRepository.addUNICOREJobSubmission(unicoreJobSubmission),
                    JobSubmissionProtocol.UNICORE,
                    priorityOrder);
            logger.debug("Airavata registered UNICORE job submission for compute resource id: " + computeResourceId);
            return submissionInterface;
        } catch (AppCatalogException e) {
            logger.error("Error while adding job submission interface to resource compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a SSH_FORK Job Submission details to a compute resource
     * App catalog will return a jobSubmissionInterfaceId which will be added to the jobSubmissionInterfaces.
     *
     * @param computeResourceId The identifier of the compute resource to which JobSubmission protocol to be added
     * @param priorityOrder     Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param sshJobSubmission  The SSHJobSubmission object to be added to the resource.
     * @return status
     * Returns the unique job submission id.
     */
    @Override
    public String addSSHForkJobSubmissionDetails(
            String computeResourceId, int priorityOrder, SSHJobSubmission sshJobSubmission)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String submissionDetails = addJobSubmissionInterface(
                    computeResourceRepository,
                    computeResourceId,
                    computeResourceRepository.addSSHJobSubmission(sshJobSubmission),
                    JobSubmissionProtocol.SSH_FORK,
                    priorityOrder);
            logger.debug("Airavata registered Fork job submission for compute resource id: " + computeResourceId);
            return submissionDetails;
        } catch (AppCatalogException e) {
            logger.error(
                    computeResourceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a SSH Job Submission details to a compute resource
     * App catalog will return a jobSubmissionInterfaceId which will be added to the jobSubmissionInterfaces.
     *
     * @param computeResourceId The identifier of the compute resource to which JobSubmission protocol to be added
     * @param priorityOrder     Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param sshJobSubmission  The SSHJobSubmission object to be added to the resource.
     * @return status
     * Returns the unique job submission id.
     */
    @Override
    public String addSSHJobSubmissionDetails(
            String computeResourceId, int priorityOrder, SSHJobSubmission sshJobSubmission)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String submissionInterface = addJobSubmissionInterface(
                    computeResourceRepository,
                    computeResourceId,
                    computeResourceRepository.addSSHJobSubmission(sshJobSubmission),
                    JobSubmissionProtocol.SSH,
                    priorityOrder);
            logger.debug("Airavata registered SSH job submission for compute resource id: " + computeResourceId);
            return submissionInterface;
        } catch (AppCatalogException e) {
            logger.error(
                    computeResourceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update the given Local Job Submission details
     *
     * @param jobSubmissionInterfaceId The identifier of the JobSubmission Interface to be updated.
     * @param localSubmission          The LOCALSubmission object to be updated.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean updateLocalSubmissionDetails(String jobSubmissionInterfaceId, LOCALSubmission localSubmission)
            throws RegistryServiceException, TException {
        try {
            computeResourceRepository.updateLocalJobSubmission(localSubmission);
            logger.debug("Airavata updated local job submission for job submission interface id: "
                    + jobSubmissionInterfaceId);
            return true;
        } catch (Exception e) {
            logger.error(
                    jobSubmissionInterfaceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a Local Job Submission details to a compute resource
     * App catalog will return a jobSubmissionInterfaceId which will be added to the jobSubmissionInterfaces.
     *
     * @param computeResourceId The identifier of the compute resource to which JobSubmission protocol to be added
     * @param priorityOrder     Specify the priority of this job manager. If this is the only jobmanager, the priority can be zero.
     * @param localSubmission   The LOCALSubmission object to be added to the resource.
     * @return status
     * Returns the unique job submission id.
     */
    @Override
    public String addLocalSubmissionDetails(
            String computeResourceId, int priorityOrder, LOCALSubmission localSubmission)
            throws RegistryServiceException, TException {
        try {
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            String submissionInterface = addJobSubmissionInterface(
                    computeResourceRepository,
                    computeResourceId,
                    computeResourceRepository.addLocalJobSubmission(localSubmission),
                    JobSubmissionProtocol.LOCAL,
                    priorityOrder);
            logger.debug("Airavata added local job submission for compute resource id: " + computeResourceId);
            return submissionInterface;
        } catch (AppCatalogException e) {
            logger.error(
                    computeResourceId,
                    "Error while adding job submission interface to resource compute resource...",
                    e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while adding job submission interface to resource compute resource. More info : "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Storage Resource.
     *
     * @param storageResourceId          The identifier for the requested compute resource to be updated.
     * @param storageResourceDescription Storage Resource Object created from the datamodel.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateStorageResource(
            String storageResourceId, StorageResourceDescription storageResourceDescription)
            throws RegistryServiceException, TException {
        try {
            storageResourceRepository.updateStorageResource(storageResourceId, storageResourceDescription);
            logger.debug("Airavata updated storage resource with storage resource Id : " + storageResourceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(storageResourceId, "Error while updating storage resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updaing storage resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Register a Storage Resource.
     *
     * @param storageResourceDescription Storge Resource Object created from the datamodel.
     * @return storageResourceId
     * Returns a server-side generated airavata storage resource globally unique identifier.
     */
    @Override
    public String registerStorageResource(StorageResourceDescription storageResourceDescription)
            throws RegistryServiceException, TException {
        try {
            String storageResource = storageResourceRepository.addStorageResource(storageResourceDescription);
            logger.debug("Airavata registered storage resource with storage resource Id : " + storageResource);
            return storageResource;
        } catch (AppCatalogException e) {
            logger.error("Error while saving storage resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while saving storage resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Compute Resource.
     *
     * @param computeResourceId          The identifier for the requested compute resource to be updated.
     * @param computeResourceDescription Compute Resource Object created from the datamodel.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateComputeResource(
            String computeResourceId, ComputeResourceDescription computeResourceDescription)
            throws RegistryServiceException, TException {
        try {
            new ComputeResourceRepository().updateComputeResource(computeResourceId, computeResourceDescription);
            logger.debug("Airavata updated compute resource with compute resource Id : " + computeResourceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(computeResourceId, "Error while updating compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updaing compute resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Register a Compute Resource.
     *
     * @param computeResourceDescription Compute Resource Object created from the datamodel.
     * @return computeResourceId
     * Returns a server-side generated airavata compute resource globally unique identifier.
     */
    @Override
    public String registerComputeResource(ComputeResourceDescription computeResourceDescription)
            throws RegistryServiceException, TException {
        try {
            String computeResource = new ComputeResourceRepository().addComputeResource(computeResourceDescription);
            logger.debug("Airavata registered compute resource with compute resource Id : " + computeResource);
            return computeResource;
        } catch (AppCatalogException e) {
            logger.error("Error while saving compute resource...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while saving compute resource. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Application Interface.
     *
     * @param appInterfaceId       The identifier of the requested application deployment to be updated.
     * @param applicationInterface
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateApplicationInterface(
            String appInterfaceId, ApplicationInterfaceDescription applicationInterface)
            throws RegistryServiceException, TException {
        try {
            applicationInterfaceRepository.updateApplicationInterface(appInterfaceId, applicationInterface);
            logger.debug("Airavata updated application interface with interface id : " + appInterfaceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(appInterfaceId, "Error while updating application interface...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating application interface. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Register a Application Interface.
     *
     * @param gatewayId
     * @param applicationInterface Application Module Object created from the datamodel.
     * @return appInterfaceId
     * Returns a server-side generated airavata application interface globally unique identifier.
     */
    @Override
    public String registerApplicationInterface(String gatewayId, ApplicationInterfaceDescription applicationInterface)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            String interfaceId =
                    applicationInterfaceRepository.addApplicationInterface(applicationInterface, gatewayId);
            logger.debug("Airavata registered application interface for gateway id : " + gatewayId);
            return interfaceId;
        } catch (AppCatalogException e) {
            logger.error("Error while adding application interface...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding application interface. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update an Application Deployment.
     *
     * @param appDeploymentId       The identifier of the requested application deployment to be updated.
     * @param applicationDeployment
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateApplicationDeployment(
            String appDeploymentId, ApplicationDeploymentDescription applicationDeployment)
            throws RegistryServiceException, TException {
        try {
            applicationDeploymentRepository.updateApplicationDeployment(appDeploymentId, applicationDeployment);
            logger.debug("Airavata updated application deployment for deployment id : " + appDeploymentId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(appDeploymentId, "Error while updating application deployment...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating application deployment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Register an Application Deployment.
     *
     * @param gatewayId             ID of the gateway which is registering the new Application Deployment.
     * @param applicationDeployment Application Module Object created from the datamodel.
     * @return appDeploymentId
     * Returns a server-side generated airavata appDeployment globally unique identifier.
     */
    @Override
    public String registerApplicationDeployment(
            String gatewayId, ApplicationDeploymentDescription applicationDeployment)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            String deployment =
                    applicationDeploymentRepository.addApplicationDeployment(applicationDeployment, gatewayId);
            logger.debug("Airavata registered application deployment for gateway id : " + gatewayId);
            return deployment;
        } catch (AppCatalogException e) {
            logger.error("Error while adding application deployment...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding application deployment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Application Module.
     *
     * @param appModuleId       The identifier for the requested application module to be updated.
     * @param applicationModule Application Module Object created from the datamodel.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateApplicationModule(String appModuleId, ApplicationModule applicationModule)
            throws RegistryServiceException, TException {
        try {
            applicationInterfaceRepository.updateApplicationModule(appModuleId, applicationModule);
            logger.debug("Airavata updated application module with module id: " + appModuleId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(appModuleId, "Error while updating application module...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating application module. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Register a Application Module.
     *
     * @param gatewayId
     * @param applicationModule Application Module Object created from the datamodel.
     * @return appModuleId
     * Returns the server-side generated airavata appModule globally unique identifier.
     * @gatewayId ID of the gateway which is registering the new Application Module.
     */
    @Override
    public String registerApplicationModule(String gatewayId, ApplicationModule applicationModule)
            throws RegistryServiceException, TException {
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
        }
        try {
            String module = applicationInterfaceRepository.addApplicationModule(applicationModule, gatewayId);
            logger.debug("Airavata registered application module for gateway id : " + gatewayId);
            return module;
        } catch (AppCatalogException e) {
            logger.error("Error while adding application module...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding application module. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void updateResourceScheduleing(
            String airavataExperimentId, ComputationalResourceSchedulingModel resourceScheduling)
            throws RegistryServiceException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                logger.debug(
                        airavataExperimentId,
                        "Update resource scheduling failed, experiment {} doesn't exist.",
                        airavataExperimentId);
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }
            ExperimentStatus experimentStatus = getExperimentStatusInternal(airavataExperimentId);
            if (experimentStatus != null) {
                ExperimentState experimentState = experimentStatus.getState();
                switch (experimentState) {
                    case CREATED:
                    case VALIDATED:
                    case CANCELED:
                    case FAILED:
                        processRepository.addProcessResourceSchedule(resourceScheduling, airavataExperimentId);
                        logger.debug(
                                airavataExperimentId,
                                "Successfully updated resource scheduling for the experiment {}.",
                                airavataExperimentId);
                        break;
                    default:
                        logger.error(
                                airavataExperimentId,
                                "Error while updating scheduling info. Update experiment is only valid for experiments "
                                        + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                                        + "experiment is in one of above statuses... ");
                        AiravataSystemException exception = new AiravataSystemException();
                        exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                        exception.setMessage(
                                "Error while updating experiment. Update experiment is only valid for experiments "
                                        + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                                        + "experiment is in one of above statuses... ");
                        throw exception;
                }
            }
        } catch (Exception e) {
            logger.error(airavataExperimentId, "Error while updating scheduling info", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while updating scheduling info. " + "Update experiment is only valid for experiments "
                            + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                            + "experiment is in one of above statuses...  "
                            + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void updateExperimentConfiguration(String airavataExperimentId, UserConfigurationDataModel userConfiguration)
            throws RegistryServiceException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                logger.error(
                        airavataExperimentId,
                        "Update experiment configuration failed, experiment {} doesn't exist.",
                        airavataExperimentId);
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }
            ExperimentStatus experimentStatus = getExperimentStatusInternal(airavataExperimentId);
            if (experimentStatus != null) {
                ExperimentState experimentState = experimentStatus.getState();
                switch (experimentState) {
                    case CREATED:
                    case VALIDATED:
                    case CANCELED:
                    case FAILED:
                        experimentRepository.addUserConfigurationData(userConfiguration, airavataExperimentId);
                        logger.debug(
                                airavataExperimentId,
                                "Successfully updated experiment configuration for experiment {}.",
                                airavataExperimentId);
                        break;
                    default:
                        logger.error(
                                airavataExperimentId,
                                "Error while updating experiment {}. Update experiment is only valid for experiments "
                                        + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                                        + "experiment is in one of above statuses... ",
                                airavataExperimentId);
                        AiravataSystemException exception = new AiravataSystemException();
                        exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                        exception.setMessage(
                                "Error while updating experiment. Update experiment is only valid for experiments "
                                        + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                                        + "experiment is in one of above statuses... ");
                        throw exception;
                }
            }
        } catch (Exception e) {
            logger.error(airavataExperimentId, "Error while updating user configuration", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while updating user configuration. " + "Update experiment is only valid for experiments "
                            + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                            + "experiment is in one of above statuses...  "
                            + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Previously Created Experiment
     * Configure the CREATED experiment with required inputs, scheduling and other quality of service parameters. This method only updates the experiment object within the registry.
     * The experiment has to be launched to make it actionable by the server.
     *
     * @param airavataExperimentId The identifier for the requested experiment. This is returned during the create experiment step.
     * @param experiment
     * @return This method call does not have a return value.
     * @throws InvalidRequestException     For any incorrect forming of the request itself.
     * @throws ExperimentNotFoundException If the specified experiment is not previously created, then an Experiment Not Found Exception is thrown.
     * @throws AiravataClientException     The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
     *                                     <p>
     *                                     UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
     *                                     step, then Airavata Registry will not have a provenance area setup. The client has to follow
     *                                     gateway registration steps and retry this request.
     *                                     <p>
     *                                     AUTHENTICATION_FAILURE - How Authentication will be implemented is yet to be determined.
     *                                     For now this is a place holder.
     *                                     <p>
     *                                     INVALID_AUTHORIZATION - This will throw an authorization exception. When a more robust security hand-shake
     *                                     is implemented, the authorization will be more substantial.
     * @throws AiravataSystemException     This exception will be thrown for any Airavata Server side issues and if the problem cannot be corrected by the client
     *                                     rather an Airavata Administrator will be notified to take corrective action.
     */
    @Override
    public void updateExperiment(String airavataExperimentId, ExperimentModel experiment)
            throws RegistryServiceException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                logger.error(
                        airavataExperimentId,
                        "Update request failed, Experiment {} doesn't exist.",
                        airavataExperimentId);
                throw new RegistryServiceException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }

            ExperimentStatus experimentStatus = getExperimentStatusInternal(airavataExperimentId);
            if (experimentStatus != null) {
                ExperimentState experimentState = experimentStatus.getState();
                switch (experimentState) {
                    case CREATED:
                    case SCHEDULED:
                    case VALIDATED:
                        if (experiment.getUserConfigurationData() != null
                                && experiment.getUserConfigurationData().getComputationalResourceScheduling() != null
                                && experiment
                                                .getUserConfigurationData()
                                                .getComputationalResourceScheduling()
                                                .getResourceHostId()
                                        != null) {
                            String compResourceId = experiment
                                    .getUserConfigurationData()
                                    .getComputationalResourceScheduling()
                                    .getResourceHostId();
                            ComputeResourceDescription computeResourceDescription =
                                    new ComputeResourceRepository().getComputeResource(compResourceId);
                            if (!computeResourceDescription.isEnabled()) {
                                logger.error("Compute Resource is not enabled by the Admin!");
                                AiravataSystemException exception = new AiravataSystemException();
                                exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                                exception.setMessage("Compute Resource is not enabled by the Admin!");
                                throw exception;
                            }
                        }
                        experimentRepository.updateExperiment(experiment, airavataExperimentId);
                        logger.debug(
                                airavataExperimentId,
                                "Successfully updated experiment {} ",
                                experiment.getExperimentName());
                        break;
                    default:
                        logger.error(
                                airavataExperimentId,
                                "Error while updating experiment. Update experiment is only valid for experiments "
                                        + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                                        + "experiment is in one of above statuses... ");
                        AiravataSystemException exception = new AiravataSystemException();
                        exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                        exception.setMessage(
                                "Error while updating experiment. Update experiment is only valid for experiments "
                                        + "with status CREATED, VALIDATED, CANCELLED, FAILED and UNKNOWN. Make sure the given "
                                        + "experiment is in one of above statuses... ");
                        throw exception;
                }
            }
        } catch (RegistryException e) {
            logger.error(airavataExperimentId, "Error while updating experiment", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating experiment. More info : " + e.getMessage());
            throw exception;
        } catch (AppCatalogException e) {
            logger.error(airavataExperimentId, "Error while updating experiment", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating experiment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * *
     * * Create New Experiment
     * * Create an experiment for the specified user belonging to the gateway. The gateway identity is not explicitly passed
     * *   but inferred from the sshKeyAuthentication header. This experiment is just a persistent place holder. The client
     * *   has to subsequently configure and launch the created experiment. No action is taken on Airavata Server except
     * *   registering the experiment in a persistent store.
     * *
     * * @param gatewayId
     * *    The unique ID of the gateway where the experiment is been created.
     * *
     * * @param ExperimentModel
     * *    The create experiment will require the basic experiment metadata like the name and description, intended user,
     * *      the gateway identifer and if the experiment should be shared public by defualt. During the creation of an experiment
     * *      the ExperimentMetadata is a required field.
     * *
     * * @return
     * *   The server-side generated.airavata.registry.core.experiment.globally unique identifier.
     * *
     * * @throws org.apache.airavata.model.error.InvalidRequestException
     * *    For any incorrect forming of the request itself.
     * *
     * * @throws org.apache.airavata.model.error.AiravataClientException
     * *    The following list of exceptions are thrown which Airavata Client can take corrective actions to resolve:
     * *
     * *      UNKNOWN_GATEWAY_ID - If a Gateway is not registered with Airavata as a one time administrative
     * *         step, then Airavata Registry will not have a provenance area setup. The client has to follow
     * *         gateway registration steps and retry this request.
     * *
     * *      AUTHENTICATION_FAILURE - How Authentication will be implemented is yet to be determined.
     * *         For now this is a place holder.
     * *
     * *      INVALID_AUTHORIZATION - This will throw an authorization exception. When a more robust security hand-shake
     * *         is implemented, the authorization will be more substantial.
     * *
     * * @throws org.apache.airavata.model.error.AiravataSystemException
     * *    This exception will be thrown for any Airavata Server side issues and if the problem cannot be corrected by the client
     * *       rather an Airavata Administrator will be notified to take corrective action.
     * *
     * *
     *
     * @param gatewayId
     * @param experiment
     */
    @Override
    public String createExperiment(String gatewayId, ExperimentModel experiment)
            throws RegistryServiceException, TException {
        try {
            if (!validateString(experiment.getExperimentName())) {
                logger.error("Cannot create experiments with empty experiment name");
                AiravataSystemException exception = new AiravataSystemException();
                exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                exception.setMessage("Cannot create experiments with empty experiment name");
                throw exception;
            }
            logger.info("Creating experiment with name " + experiment.getExperimentName());
            if (!isGatewayExistInternal(gatewayId)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }

            if (experiment.getUserConfigurationData() != null
                    && experiment.getUserConfigurationData().getComputationalResourceScheduling() != null
                    && experiment
                                    .getUserConfigurationData()
                                    .getComputationalResourceScheduling()
                                    .getResourceHostId()
                            != null) {

                String compResourceId = experiment
                        .getUserConfigurationData()
                        .getComputationalResourceScheduling()
                        .getResourceHostId();
                ComputeResourceDescription computeResourceDescription =
                        new ComputeResourceRepository().getComputeResource(compResourceId);
                if (!computeResourceDescription.isEnabled()) {
                    logger.error("Compute Resource is not enabled by the Admin!");
                    AiravataSystemException exception = new AiravataSystemException();
                    exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                    exception.setMessage("Compute Resource is not enabled by the Admin!");
                    throw exception;
                }
            } else if (!experiment
                    .getUserConfigurationData()
                    .getAutoScheduledCompResourceSchedulingList()
                    .isEmpty()) {
                for (ComputationalResourceSchedulingModel computationalResourceScheduling :
                        experiment.getUserConfigurationData().getAutoScheduledCompResourceSchedulingList()) {
                    ComputeResourceDescription computeResourceDescription = new ComputeResourceRepository()
                            .getComputeResource(computationalResourceScheduling.getResourceHostId());
                    if (!computeResourceDescription.isEnabled()) {
                        logger.error("Compute Resource  with id" + computationalResourceScheduling.getResourceHostId()
                                + "" + " is not enabled by the Admin!");
                        AiravataSystemException exception = new AiravataSystemException();
                        exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                        exception.setMessage(
                                "Compute Resource  with id" + computationalResourceScheduling.getResourceHostId() + ""
                                        + " is not enabled by the Admin!");
                        throw exception;
                    }
                }
            }

            experiment.setGatewayId(gatewayId);
            String experimentId = experimentRepository.addExperiment(experiment);
            if (experiment.getExperimentType() == ExperimentType.WORKFLOW) {
                workflowRepository.registerWorkflow(experiment.getWorkflow(), experimentId);
            }
            logger.debug(
                    experimentId, "Created new experiment with experiment name {}", experiment.getExperimentName());
            return experimentId;
        } catch (Exception e) {
            logger.error("Error while creating the experiment with experiment name {}", experiment.getExperimentName());
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while creating the experiment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Search Experiments.
     * Search Experiments by using multiple filter criteria with pagination. Results will be sorted based on creation time DESC.
     *
     * @param gatewayId Identifier of the requested gateway.
     * @param userName  Username of the user requesting the search function.
     * @param filters   Map of multiple filter criteria. Currenlt search filters includes Experiment Name, Description, Application, etc....
     * @param limit     Amount of results to be fetched.
     * @param offset    The starting point of the results to be fetched.
     * @return ExperimentSummaryModel
     * List of experiments for the given search filter. Here only the Experiment summary will be returned.
     */
    @Override
    public List<ExperimentSummaryModel> searchExperiments(
            String gatewayId,
            String userName,
            List<String> accessibleExpIds,
            Map<ExperimentSearchFields, String> filters,
            int limit,
            int offset)
            throws RegistryServiceException, TException {
        if (!validateString(userName)) {
            logger.error("Username cannot be empty. Please provide a valid user..");
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Username cannot be empty. Please provide a valid user..");
            throw exception;
        }
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
        }
        try {
            if (!userRepository.isUserExists(gatewayId, userName)) {
                logger.error("User does not exist in the system. Please provide a valid user..");
                AiravataSystemException exception = new AiravataSystemException();
                exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                exception.setMessage("User does not exist in the system. Please provide a valid user..");
                throw exception;
            }
            List<ExperimentSummaryModel> summaries = new ArrayList<ExperimentSummaryModel>();
            Map<String, String> regFilters = new HashMap();
            regFilters.put(Constants.FieldConstants.ExperimentConstants.GATEWAY_ID, gatewayId);
            for (Map.Entry<ExperimentSearchFields, String> entry : filters.entrySet()) {
                if (entry.getKey().equals(ExperimentSearchFields.EXPERIMENT_NAME)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.EXPERIMENT_NAME, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.EXPERIMENT_DESC)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.DESCRIPTION, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.APPLICATION_ID)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.EXECUTION_ID, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.STATUS)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.EXPERIMENT_STATUS, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.FROM_DATE)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.FROM_DATE, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.TO_DATE)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.TO_DATE, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.PROJECT_ID)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.PROJECT_ID, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.USER_NAME)) {
                    regFilters.put(Constants.FieldConstants.ExperimentConstants.USER_NAME, entry.getValue());
                } else if (entry.getKey().equals(ExperimentSearchFields.JOB_ID)) {
                    regFilters.put(Constants.FieldConstants.JobConstants.JOB_ID, entry.getValue());
                }
            }

            if (accessibleExpIds.size() == 0 && !ServerSettings.isEnableSharing()) {
                if (!regFilters.containsKey(DBConstants.Experiment.USER_NAME)) {
                    regFilters.put(DBConstants.Experiment.USER_NAME, userName);
                }
            }
            summaries = experimentSummaryRepository.searchAllAccessibleExperiments(
                    accessibleExpIds,
                    regFilters,
                    limit,
                    offset,
                    Constants.FieldConstants.ExperimentConstants.CREATION_TIME,
                    ResultOrderType.DESC);
            logger.debug("Airavata retrieved experiments for user : " + userName + " and gateway id : " + gatewayId);
            return summaries;
        } catch (Exception e) {
            logger.error("Error while retrieving experiments", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving experiments. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Search User Projects
     * Search and get all Projects for user by project description or/and project name  with pagination.
     * Results will be ordered based on creation time DESC.
     *
     * @param gatewayId The unique identifier of the gateway making the request.
     * @param userName  The identifier of the user.
     * @param filters   Map of multiple filter criteria. Currenlt search filters includes Project Name and Project Description
     * @param limit     The amount results to be fetched.
     * @param offset    The starting point of the results to be fetched.
     */
    @Override
    public List<Project> searchProjects(
            String gatewayId,
            String userName,
            List<String> accessibleProjIds,
            Map<ProjectSearchFields, String> filters,
            int limit,
            int offset)
            throws RegistryServiceException, TException {
        if (!validateString(userName)) {
            logger.error("Username cannot be empty. Please provide a valid user..");
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Username cannot be empty. Please provide a valid user..");
            throw exception;
        }
        if (!isGatewayExistInternal(gatewayId)) {
            logger.error("Gateway does not exist.Please provide a valid gateway id...");
            throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
        }
        try {
            if (!userRepository.isUserExists(gatewayId, userName)) {
                logger.error("User does not exist in the system. Please provide a valid user..");
                AiravataSystemException exception = new AiravataSystemException();
                exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
                exception.setMessage("User does not exist in the system. Please provide a valid user..");
                throw exception;
            }
            List<Project> projects = new ArrayList<>();
            Map<String, String> regFilters = new HashMap<>();
            regFilters.put(Constants.FieldConstants.ProjectConstants.GATEWAY_ID, gatewayId);
            for (Map.Entry<ProjectSearchFields, String> entry : filters.entrySet()) {
                if (entry.getKey().equals(ProjectSearchFields.PROJECT_NAME)) {
                    regFilters.put(Constants.FieldConstants.ProjectConstants.PROJECT_NAME, entry.getValue());
                } else if (entry.getKey().equals(ProjectSearchFields.PROJECT_DESCRIPTION)) {
                    regFilters.put(Constants.FieldConstants.ProjectConstants.DESCRIPTION, entry.getValue());
                }
            }

            if (accessibleProjIds.size() == 0 && !ServerSettings.isEnableSharing()) {
                if (!regFilters.containsKey(DBConstants.Project.OWNER)) {
                    regFilters.put(DBConstants.Project.OWNER, userName);
                }
            }

            projects = projectRepository.searchAllAccessibleProjects(
                    accessibleProjIds,
                    regFilters,
                    limit,
                    offset,
                    Constants.FieldConstants.ProjectConstants.CREATION_TIME,
                    ResultOrderType.DESC);
            logger.debug("Airavata retrieved projects for user : " + userName + " and gateway id : " + gatewayId);
            return projects;
        } catch (Exception e) {
            logger.error("Error while retrieving projects", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving projects. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update an Existing Project
     *
     * @param projectId      The projectId of the project needed an update.
     * @param updatedProject
     * @return void
     * Currently this does not return any value.
     */
    @Override
    public void updateProject(String projectId, Project updatedProject) throws RegistryServiceException, TException {
        if (!validateString(projectId) || !validateString(projectId)) {
            logger.error("Project id cannot be empty...");
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Project id cannot be empty...");
            throw exception;
        }
        try {
            if (!projectRepository.isProjectExist(projectId)) {
                logger.error("Project does not exist in the system. Please provide a valid project ID...");
                ProjectNotFoundException exception = new ProjectNotFoundException();
                exception.setMessage("Project does not exist in the system. Please provide a valid project ID...");
                throw exception;
            }

            projectRepository.updateProject(updatedProject, projectId);
            logger.debug("Airavata updated project with project Id : " + projectId);
        } catch (RegistryException e) {
            logger.error("Error while updating the project", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating the project. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Creates a Project with basic metadata.
     * A Project is a container of experiments.
     *
     * @param gatewayId The identifier for the requested gateway.
     * @param project
     */
    @Override
    public String createProject(String gatewayId, Project project) throws RegistryServiceException, TException {
        try {
            if (!validateString(project.getName()) || !validateString(project.getOwner())) {
                logger.error("Project name and owner cannot be empty...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }
            if (!validateString(gatewayId)) {
                logger.error("Gateway ID cannot be empty...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }
            if (!isGatewayExistInternal(gatewayId)) {
                logger.error("Gateway does not exist.Please provide a valid gateway id...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }
            String projectId = projectRepository.addProject(project, gatewayId);
            return projectId;
        } catch (Exception e) {
            logger.error("Error while creating the project", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while creating the project. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean updateNotification(Notification notification) throws RegistryServiceException, TException {
        try {
            notificationRepository.updateNotification(notification);
            return true;
        } catch (RegistryException e) {
            logger.error("Error while updating notification", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while getting gateway. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * * API methods to retrieve notifications
     * *
     *
     * @param notification
     */
    @Override
    public String createNotification(Notification notification) throws RegistryServiceException, TException {
        try {
            return notificationRepository.createNotification(notification);
        } catch (RegistryException e) {
            logger.error("Error while creating notification", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while creating notification. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update previously registered Gateway metadata.
     *
     * @param gatewayId      The gateway Id of the Gateway which require an update.
     * @param updatedGateway
     * @return gateway
     * Modified gateway obejct.
     * @throws AiravataClientException
     */
    @Override
    public boolean updateGateway(String gatewayId, Gateway updatedGateway) throws RegistryServiceException, TException {
        try {
            if (!gatewayRepository.isGatewayExist(gatewayId)) {
                logger.error("Gateway does not exist in the system. Please provide a valid gateway ID...");
                AiravataSystemException exception = new AiravataSystemException();
                exception.setMessage("Gateway does not exist in the system. Please provide a valid gateway ID...");
                throw exception;
            }
            gatewayRepository.updateGateway(gatewayId, updatedGateway);

            // check if gatewayprofile exists and check if the identity server password token equals the admin password
            // token, if not update
            GatewayResourceProfile existingGwyResourceProfile =
                    new GwyResourceProfileRepository().getGatewayProfile(gatewayId);
            if (existingGwyResourceProfile.getIdentityServerPwdCredToken() == null
                    || !existingGwyResourceProfile
                            .getIdentityServerPwdCredToken()
                            .equals(updatedGateway.getIdentityServerPasswordToken())) {
                existingGwyResourceProfile.setIdentityServerPwdCredToken(
                        updatedGateway.getIdentityServerPasswordToken());
                new GwyResourceProfileRepository().updateGatewayResourceProfile(gatewayId, existingGwyResourceProfile);
            }
            logger.debug("Airavata update gateway with gateway id : " + gatewayId);
            return true;
        } catch (RegistryException e) {
            logger.error("Error while updating the gateway", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating the gateway. More info : " + e.getMessage());
            throw exception;
        } catch (AppCatalogException e) {
            logger.error("Error while updating gateway profile", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating gateway profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Register a Gateway with Airavata.
     *
     * @param gateway The gateway data model.
     * @return gatewayId
     * Th unique identifier of the  newly registered gateway.
     */
    @Override
    public String addGateway(Gateway gateway) throws RegistryServiceException, DuplicateEntryException, TException {
        try {
            if (!validateString(gateway.getGatewayId())) {
                logger.error("Gateway id cannot be empty...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }
            // check if gateway exists
            if (isGatewayExist(gateway.getGatewayId())) {
                throw new DuplicateEntryException(
                        "Gateway with gatewayId: " + gateway.getGatewayId() + ", already exists in ExperimentCatalog.");
            }
            // check if gatewayresourceprofile exists
            if (new GwyResourceProfileRepository().isGatewayResourceProfileExists(gateway.getGatewayId())) {
                throw new DuplicateEntryException("GatewayResourceProfile with gatewayId: " + gateway.getGatewayId()
                        + ", already exists in AppCatalog.");
            }

            // add gateway in experiment catalog
            String gatewayId = gatewayRepository.addGateway(gateway);

            // add gatewayresourceprofile in appCatalog
            GatewayResourceProfile gatewayResourceProfile = new GatewayResourceProfile();
            gatewayResourceProfile.setGatewayID(gatewayId);
            gatewayResourceProfile.setIdentityServerTenant(gatewayId);
            gatewayResourceProfile.setIdentityServerPwdCredToken(gateway.getIdentityServerPasswordToken());
            new GwyResourceProfileRepository().addGatewayResourceProfile(gatewayResourceProfile);
            logger.debug("Airavata added gateway with gateway id : " + gateway.getGatewayId());
            return gatewayId;
        } catch (RegistryException e) {
            logger.error("Error while adding gateway", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding gateway. More info : " + e.getMessage());
            throw exception;
        } catch (AppCatalogException e) {
            logger.error("Error while adding gateway profile", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while adding gateway profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    private boolean validateString(String name) {
        boolean valid = true;
        if (name == null || name.equals("") || name.trim().length() == 0) {
            valid = false;
        }
        return valid;
    }

    /*Following method wraps the logic of isGatewayExist method and this is to be called by any other method of the API as needed.*/
    private boolean isGatewayExistInternal(String gatewayId)
            throws InvalidRequestException, AiravataClientException, AiravataSystemException, AuthorizationException,
                    TException {
        try {
            return gatewayRepository.isGatewayExist(gatewayId);
        } catch (RegistryException e) {
            logger.error("Error while getting gateway", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while getting gateway. More info : " + e.getMessage());
            throw exception;
        }
    }

    /*This private method wraps the logic of getExperiment method as this method is called internally in the API.*/
    private ExperimentModel getExperimentInternal(String airavataExperimentId)
            throws InvalidRequestException, ExperimentNotFoundException, AiravataClientException,
                    AiravataSystemException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }
            return experimentRepository.getExperiment(airavataExperimentId);
        } catch (RegistryException e) {
            logger.error("Error while retrieving the experiment", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving the experiment. More info : " + e.getMessage());
            throw exception;
        }
    }

    /*Private method wraps the logic of getExperimentStatus method since this method is called internally.*/
    private ExperimentStatus getExperimentStatusInternal(String airavataExperimentId)
            throws InvalidRequestException, ExperimentNotFoundException, AiravataClientException,
                    AiravataSystemException, TException {
        try {
            if (!experimentRepository.isExperimentExist(airavataExperimentId)) {
                logger.error(
                        airavataExperimentId,
                        "Error while retrieving experiment status, experiment {} doesn't exist.",
                        airavataExperimentId);
                throw new ExperimentNotFoundException(
                        "Requested experiment id " + airavataExperimentId + " does not exist in the system..");
            }
            return experimentStatusRepository.getExperimentStatus(airavataExperimentId);
        } catch (Exception e) {
            logger.error(airavataExperimentId, "Error while retrieving the experiment status", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving the experiment status. More info : " + e.getMessage());
            throw exception;
        }
    }

    /*This private method wraps the logic of getApplicationOutputs method as this method is called internally in the API.*/
    private List<OutputDataObjectType> getApplicationOutputsInternal(String appInterfaceId)
            throws InvalidRequestException, AiravataClientException, AiravataSystemException, TException {
        try {
            List<OutputDataObjectType> applicationOutputs =
                    applicationInterfaceRepository.getApplicationOutputs(appInterfaceId);
            logger.debug("Airavata retrieved application outputs for application interface id : " + appInterfaceId);
            return applicationOutputs;
        } catch (AppCatalogException e) {
            logger.error(appInterfaceId, "Error while retrieving application outputs...", e);
            AiravataSystemException exception = new AiravataSystemException();
            exception.setAiravataErrorType(AiravataErrorType.INTERNAL_ERROR);
            exception.setMessage("Error while retrieving application outputs. More info : " + e.getMessage());
            throw exception;
        }
    }

    private String addJobSubmissionInterface(
            ComputeResourceRepository computeResourceRepository,
            String computeResourceId,
            String jobSubmissionInterfaceId,
            JobSubmissionProtocol protocolType,
            int priorityOrder)
            throws AppCatalogException {
        JobSubmissionInterface jobSubmissionInterface = new JobSubmissionInterface();
        jobSubmissionInterface.setJobSubmissionInterfaceId(jobSubmissionInterfaceId);
        jobSubmissionInterface.setPriorityOrder(priorityOrder);
        jobSubmissionInterface.setJobSubmissionProtocol(protocolType);
        return computeResourceRepository.addJobSubmissionProtocol(computeResourceId, jobSubmissionInterface);
    }

    private String addDataMovementInterface(
            ComputeResource computeResource,
            String computeResourceId,
            DMType dmType,
            String dataMovementInterfaceId,
            DataMovementProtocol protocolType,
            int priorityOrder)
            throws AppCatalogException {
        DataMovementInterface dataMovementInterface = new DataMovementInterface();
        dataMovementInterface.setDataMovementInterfaceId(dataMovementInterfaceId);
        dataMovementInterface.setPriorityOrder(priorityOrder);
        dataMovementInterface.setDataMovementProtocol(protocolType);
        if (dmType.equals(DMType.COMPUTE_RESOURCE)) {
            return computeResource.addDataMovementProtocol(computeResourceId, dmType, dataMovementInterface);
        } else if (dmType.equals(DMType.STORAGE_RESOURCE)) {
            dataMovementInterface.setStorageResourceId(computeResourceId);
            return storageResourceRepository.addDataMovementInterface(dataMovementInterface);
        }
        return null;
    }

    /**
     * Register a User Resource Profile.
     *
     * @param userResourceProfile User Resource Profile Object.
     *                            The GatewayID should be obtained from Airavata user profile data model and passed to register a corresponding
     *                            resource profile.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public String registerUserResourceProfile(UserResourceProfile userResourceProfile)
            throws RegistryServiceException, TException {
        try {
            if (!validateString(userResourceProfile.getUserId())) {
                logger.error("Cannot create user resource profile with empty user id");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage("Cannot create user resource profile with empty gateway id");
                throw exception;
            }
            if (!validateString(userResourceProfile.getGatewayID())) {
                logger.error("Cannot create user resource profile with empty gateway id");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage("Cannot create user resource profile with empty gateway id");
                throw exception;
            }

            if (!userRepository.isUserExists(userResourceProfile.getGatewayID(), userResourceProfile.getUserId())) {
                logger.error("User does not exist.Please provide a valid user ID...");
                throw new RegistryServiceException("User does not exist.Please provide a valid user ID...");
            }
            String resourceProfile = userResourceProfileRepository.addUserResourceProfile(userResourceProfile);
            logger.debug("Airavata registered user resource profile with gateway id : "
                    + userResourceProfile.getGatewayID() + "and user id : " + userResourceProfile.getUserId());
            return resourceProfile;
        } catch (AppCatalogException e) {
            logger.error("Error while registering user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while registering user resource profile. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error("Error while registering user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while registering user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public boolean isUserResourceProfileExists(String userId, String gatewayId)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayId, userId)) {
                logger.error("user does not exist.Please provide a valid gateway id...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }
            return userResourceProfileRepository.isUserResourceProfileExists(userId, gatewayId);
        } catch (AppCatalogException e) {
            logger.error("Error while checking existence of user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while checking existence of user resource profile. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error("Error while checking existence of user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while checking existence of user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch the given Gateway Resource Profile.
     *
     * @param userId The identifier for the requested user resource.
     * @return UserResourceProfile object
     */
    @Override
    public UserResourceProfile getUserResourceProfile(String userId, String gatewayId)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayId, userId)) {
                logger.error("user does not exist.Please provide a valid gateway id...");
                throw new AiravataSystemException(AiravataErrorType.INTERNAL_ERROR);
            }
            UserResourceProfile userResourceProfile =
                    userResourceProfileRepository.getUserResourceProfile(userId, gatewayId);
            logger.debug("Airavata retrieved User resource profile with user id : " + userId);
            return userResourceProfile;
        } catch (AppCatalogException e) {
            logger.error("Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error("Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a User Resource Profile.
     *
     * @param gatewayID           The identifier for the requested gateway resource to be updated.
     * @param userResourceProfile Gateway Resource Profile Object.
     * @return status
     * Returns a success/failure of the update.
     */
    @Override
    public boolean updateUserResourceProfile(String userId, String gatewayID, UserResourceProfile userResourceProfile)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("User does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            userResourceProfileRepository.updateUserResourceProfile(userId, gatewayID, userResourceProfile);
            logger.debug("Airavata updated gateway profile with gateway id : " + userId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while updating gateway resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating gateway resource profile. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete the given User Resource Profile.
     *
     * @param userId    identifier for user profile
     * @param gatewayID The identifier for the requested gateway resource to be deleted.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteUserResourceProfile(String userId, String gatewayID)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            userResourceProfileRepository.removeUserResourceProfile(userId, gatewayID);
            logger.debug("Airavata deleted User profile with gateway id : " + gatewayID + " and user id : " + userId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while removing User resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while removing User resource profile. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public String addUser(UserProfile userProfile)
            throws RegistryServiceException, DuplicateEntryException, TException {
        try {
            logger.info("Adding User in Registry: " + userProfile);
            if (isUserExists(userProfile.getGatewayId(), userProfile.getUserId())) {
                throw new DuplicateEntryException("User already exists, with userId: " + userProfile.getUserId()
                        + ", and gatewayId: " + userProfile.getGatewayId());
            }
            UserProfile savedUser = userRepository.addUser(userProfile);
            return savedUser.getUserId();
        } catch (RegistryException ex) {
            logger.error("Error while adding user in registry: " + ex, ex);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage("Error while adding user in registry: " + ex.getMessage());
            throw rse;
        }
    }

    /**
     * Add a User Compute Resource Preference to a registered gateway profile.
     *
     * @param userId
     * @param gatewayID                     The identifier for the gateway profile to be added.
     * @param computeResourceId             Preferences related to a particular compute resource
     * @param userComputeResourcePreference The UserComputeResourcePreference object to be added to the resource profile.
     * @return status
     * Returns a success/failure of the addition. If a profile already exists, this operation will fail.
     * Instead an update should be used.
     */
    @Override
    public boolean addUserComputeResourcePreference(
            String userId,
            String gatewayID,
            String computeResourceId,
            UserComputeResourcePreference userComputeResourcePreference)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            if (!userResourceProfileRepository.isUserResourceProfileExists(userId, gatewayID)) {
                throw new RegistryServiceException("User resource profile with user id'" + userId + " &  gateway Id"
                        + gatewayID + "' does not exist!!!");
            }
            UserResourceProfile profile = userResourceProfileRepository.getUserResourceProfile(userId, gatewayID);
            //            gatewayProfile.removeGatewayResourceProfile(gatewayID);
            profile.addToUserComputeResourcePreferences(userComputeResourcePreference);
            userResourceProfileRepository.updateUserResourceProfile(userId, gatewayID, profile);
            logger.debug("Airavata added User compute resource preference with gateway id : " + gatewayID
                    + " and for compute resource id : " + computeResourceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while registering User resource profile preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while registering user resource profile preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Is a User Compute Resource Preference exists.
     *
     * @param userId
     * @param gatewayID         The identifier for the gateway profile to be added.
     * @param computeResourceId Preferences related to a particular compute resource
     * @return status
     * Returns a success/failure of the addition. If a resource already exists, this operation will fail.
     */
    @Override
    public boolean isUserComputeResourcePreferenceExists(String userId, String gatewayID, String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            if (userRepository.isUserExists(gatewayID, userId)
                    && userResourceProfileRepository.isUserResourceProfileExists(userId, gatewayID)) {
                return userResourceProfileRepository.isUserComputeResourcePreferenceExists(
                        userId, gatewayID, computeResourceId);
            }
            return false;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while fetching compute resource preference", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while fetching compute resource preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while fetching compute resource preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while fetching compute resource preference. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Add a Storage Resource Preference to a registered gateway profile.
     *
     * @param gatewayID             The identifier of the gateway profile to be added.
     * @param storageResourceId     Preferences related to a particular compute resource
     * @param dataStoragePreference
     * @return status
     * Returns a success/failure of the addition. If a profile already exists, this operation will fail.
     * Instead an update should be used.
     */
    @Override
    public boolean addUserStoragePreference(
            String userId, String gatewayID, String storageResourceId, UserStoragePreference dataStoragePreference)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            if (!userResourceProfileRepository.isUserResourceProfileExists(userId, gatewayID)) {
                throw new RegistryServiceException("User resource profile with user id'" + userId + " &  gateway Id"
                        + gatewayID + "' does not exist!!!");
            }
            UserResourceProfile profile = userResourceProfileRepository.getUserResourceProfile(userId, gatewayID);
            //            gatewayProfile.removeGatewayResourceProfile(gatewayID);
            dataStoragePreference.setStorageResourceId(storageResourceId);
            profile.addToUserStoragePreferences(dataStoragePreference);
            userResourceProfileRepository.updateUserResourceProfile(userId, gatewayID, profile);
            logger.debug("Airavata added storage resource preference with gateway id : " + gatewayID
                    + " and for storage resource id : " + storageResourceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while registering user resource profile preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while registering user resource profile preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch a Compute Resource Preference of a registered gateway profile.
     *
     * @param userId
     * @param gatewayID             The identifier for the gateway profile to be requested
     * @param userComputeResourceId Preferences related to a particular compute resource
     * @return computeResourcePreference
     * Returns the ComputeResourcePreference object.
     */
    @Override
    public UserComputeResourcePreference getUserComputeResourcePreference(
            String userId, String gatewayID, String userComputeResourceId) throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            if (!userResourceProfileRepository.isUserResourceProfileExists(userId, gatewayID)) {
                throw new RegistryServiceException("User resource profile with user id'" + userId + " &  gateway Id"
                        + gatewayID + "' does not exist!!!");
            }
            ComputeResourceRepository computeResourceRepository = new ComputeResourceRepository();
            if (!computeResourceRepository.isComputeResourceExists(userComputeResourceId)) {
                logger.error(
                        userComputeResourceId,
                        "Given compute resource does not exist in the system. Please provide a valid compute resource id...");
                RegistryServiceException exception = new RegistryServiceException();
                exception.setMessage(
                        "Given compute resource does not exist in the system. Please provide a valid compute resource id...");
                throw exception;
            }
            UserComputeResourcePreference userComputeResourcePreference =
                    userResourceProfileRepository.getUserComputeResourcePreference(
                            userId, gatewayID, userComputeResourceId);
            logger.debug("Airavata retrieved user compute resource preference with gateway id : " + gatewayID
                    + " and for compute resoruce id : " + userComputeResourceId);
            return userComputeResourcePreference;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while reading user compute resource preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading user compute resource preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch a Storage Resource Preference of a registered gateway profile.
     *
     * @param userId    identifier for user data model
     * @param gatewayID The identifier of the gateway profile to request to fetch the particular storage resource preference.
     * @param storageId Identifier of the Storage Preference required to be fetched.
     * @return StoragePreference
     * Returns the StoragePreference object.
     */
    @Override
    public UserStoragePreference getUserStoragePreference(String userId, String gatewayID, String storageId)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            if (!userResourceProfileRepository.isUserResourceProfileExists(userId, gatewayID)) {
                throw new RegistryServiceException("User resource profile with user id'" + userId + " &  gateway Id"
                        + gatewayID + "' does not exist!!!");
            }

            UserStoragePreference storagePreference =
                    userResourceProfileRepository.getUserStoragePreference(userId, gatewayID, storageId);
            logger.debug("Airavata retrieved user storage resource preference with gateway id : " + gatewayID
                    + " and for storage resource id : " + storageId);
            return storagePreference;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while reading gateway data storage preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading gateway data storage preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all User Resource Profiles registered
     *
     * @return UserResourceProfile
     * Returns all the UserResourceProfile list object.
     */
    @Override
    public List<UserResourceProfile> getAllUserResourceProfiles() throws RegistryServiceException, TException {
        try {
            return userResourceProfileRepository.getAllUserResourceProfiles();
        } catch (AppCatalogException e) {
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading retrieving all gateway profiles. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Compute Resource Preference to a registered user resource profile.
     *
     * @param userId                        identifier for user data model
     * @param gatewayID                     The identifier for the gateway profile to be updated.
     * @param computeResourceId             Preferences related to a particular compute resource
     * @param userComputeResourcePreference The ComputeResourcePreference object to be updated to the resource profile.
     * @return status
     * Returns a success/failure of the updation.
     */
    @Override
    public boolean updateUserComputeResourcePreference(
            String userId,
            String gatewayID,
            String computeResourceId,
            UserComputeResourcePreference userComputeResourcePreference)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            UserResourceProfile profile = userResourceProfileRepository.getUserResourceProfile(userId, gatewayID);
            List<UserComputeResourcePreference> userComputeResourcePreferences =
                    profile.getUserComputeResourcePreferences();
            UserComputeResourcePreference preferenceToRemove = null;
            for (UserComputeResourcePreference preference : userComputeResourcePreferences) {
                if (preference.getComputeResourceId().equals(computeResourceId)) {
                    preferenceToRemove = preference;
                    break;
                }
            }
            if (preferenceToRemove != null) {
                profile.getUserComputeResourcePreferences().remove(preferenceToRemove);
            }
            profile.getUserComputeResourcePreferences().add(userComputeResourcePreference);
            userResourceProfileRepository.updateUserResourceProfile(userId, gatewayID, profile);
            logger.debug("Airavata updated compute resource preference with gateway id : " + gatewayID
                    + " and for compute resource id : " + computeResourceId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(userId, "Error while reading user compute resource preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while updating user compute resource preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Update a Storage Resource Preference of a registered user resource profile.
     *
     * @param userId                identifier for user data model
     * @param gatewayID             The identifier of the gateway profile to be updated.
     * @param storageId             The Storage resource identifier of the one that you want to update
     * @param userStoragePreference The storagePreference object to be updated to the resource profile.
     * @return status
     * Returns a success/failure of the updation.
     */
    @Override
    public boolean updateUserStoragePreference(
            String userId, String gatewayID, String storageId, UserStoragePreference userStoragePreference)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            UserResourceProfile profile = userResourceProfileRepository.getUserResourceProfile(userId, gatewayID);
            List<UserStoragePreference> dataStoragePreferences = profile.getUserStoragePreferences();
            UserStoragePreference preferenceToRemove = null;
            for (UserStoragePreference preference : dataStoragePreferences) {
                if (preference.getStorageResourceId().equals(storageId)) {
                    preferenceToRemove = preference;
                    break;
                }
            }
            if (preferenceToRemove != null) {
                profile.getUserStoragePreferences().remove(preferenceToRemove);
            }
            profile.getUserStoragePreferences().add(userStoragePreference);
            userResourceProfileRepository.updateUserResourceProfile(userId, gatewayID, profile);
            logger.debug("Airavata updated user storage resource preference with gateway id : " + gatewayID
                    + " and for storage resource id : " + storageId);
            return true;
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while reading user data storage preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating user data storage preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete the Compute Resource Preference of a registered gateway profile.
     *
     * @param userId            The identifier for user data model
     * @param gatewayID         The identifier for the gateway profile to be deleted.
     * @param computeResourceId Preferences related to a particular compute resource
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteUserComputeResourcePreference(String userId, String gatewayID, String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            return userResourceProfileRepository.removeUserComputeResourcePreferenceFromGateway(
                    userId, gatewayID, computeResourceId);
        } catch (AppCatalogException e) {
            logger.error(userId, "Error while reading user compute resource preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage(
                    "Error while updating user compute resource preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Delete the Storage Resource Preference of a registered gateway profile.
     *
     * @param userId    The identifier for user data model
     * @param gatewayID The identifier of the gateway profile to be deleted.
     * @param storageId ID of the storage preference you want to delete.
     * @return status
     * Returns a success/failure of the deletion.
     */
    @Override
    public boolean deleteUserStoragePreference(String userId, String gatewayID, String storageId)
            throws RegistryServiceException, TException {
        try {
            if (!userRepository.isUserExists(gatewayID, userId)) {
                logger.error("user does not exist.Please provide a valid user id...");
                throw new RegistryServiceException("user does not exist.Please provide a valid user id...");
            }
            return userResourceProfileRepository.removeUserDataStoragePreferenceFromGateway(
                    userId, gatewayID, storageId);
        } catch (AppCatalogException e) {
            logger.error(gatewayID, "Error while reading user data storage preference...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while updating user data storage preference. More info : " + e.getMessage());
            throw exception;
        } catch (RegistryException e) {
            logger.error(userId, "Error while retrieving user resource profile...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while retrieving user resource profile. More info : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * * Get queue statuses of all compute resources
     * *
     */
    @Override
    public List<QueueStatusModel> getLatestQueueStatuses() throws RegistryServiceException, TException {
        try {
            List<QueueStatusModel> queueStatusModels = queueStatusRepository.getLatestQueueStatuses();
            return queueStatusModels;
        } catch (RegistryException e) {
            logger.error("Error while reading queue status models....", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading queue status models.... : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void registerQueueStatuses(List<QueueStatusModel> queueStatuses)
            throws RegistryServiceException, TException {
        try {
            queueStatusRepository.createQueueStatuses(queueStatuses);
        } catch (RegistryException e) {
            logger.error("Error while storing queue status models....", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while storing queue status models.... : " + e.getMessage());
            throw exception;
        }
    }

    @Override
    public QueueStatusModel getQueueStatus(String hostName, String queueName)
            throws RegistryServiceException, TException {
        try {
            Optional<QueueStatusModel> optionalQueueStatusModel =
                    queueStatusRepository.getQueueStatus(hostName, queueName);
            logger.info("Executed and present " + optionalQueueStatusModel.isPresent());
            if (optionalQueueStatusModel.isPresent()) {
                return optionalQueueStatusModel.get();
            } else {
                QueueStatusModel queueStatusModel = new QueueStatusModel();
                queueStatusModel.setHostName(hostName);
                queueStatusModel.setQueueName(queueName);
                queueStatusModel.setQueueUp(false);
                queueStatusModel.setRunningJobs(0);
                queueStatusModel.setQueuedJobs(0);
                queueStatusModel.setTime(0);
                return queueStatusModel;
            }
        } catch (RegistryException e) {
            logger.error("Error while storing queue status models....", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while storing queue status models.... : " + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all User Compute Resource Preferences of a registered User Resource Profile.
     *
     * @param userId
     * @param gatewayID The identifier for the gateway profile to be requested
     * @return computeResourcePreference
     * Returns the ComputeResourcePreference object.
     */
    @Override
    public List<UserComputeResourcePreference> getAllUserComputeResourcePreferences(String userId, String gatewayID)
            throws RegistryServiceException, TException {
        try {
            if (!isUserExists(gatewayID, userId)) {
                logger.error("User Resource Profile does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException(
                        "User Resource Profile does not exist.Please provide a valid gateway id...");
            }
            return userResourceProfileRepository
                    .getUserResourceProfile(userId, gatewayID)
                    .getUserComputeResourcePreferences();
        } catch (AppCatalogException e) {
            logger.error(userId, "Error while reading User Resource Profile compute resource preferences...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading User Resource Profile compute resource preferences. More info : "
                    + e.getMessage());
            throw exception;
        }
    }

    /**
     * Fetch all Storage Resource Preferences of a registered User Resource Profile.
     *
     * @param userId
     * @param gatewayID The identifier for the gateway profile to be requested
     * @return StoragePreference
     * Returns the StoragePreference object.
     */
    @Override
    public List<UserStoragePreference> getAllUserStoragePreferences(String userId, String gatewayID)
            throws RegistryServiceException, TException {
        try {
            if (!isUserExists(gatewayID, userId)) {
                logger.error("User does not exist.Please provide a valid gateway id...");
                throw new RegistryServiceException("Gateway does not exist.Please provide a valid gateway id...");
            }
            return userResourceProfileRepository
                    .getUserResourceProfile(userId, gatewayID)
                    .getUserStoragePreferences();
        } catch (AppCatalogException e) {
            logger.error(userId, "Error while reading user resource Profile data storage preferences...", e);
            RegistryServiceException exception = new RegistryServiceException();
            exception.setMessage("Error while reading user resource Profile data storage preferences. More info : "
                    + e.getMessage());
            throw exception;
        }
    }

    @Override
    public void createGatewayGroups(GatewayGroups gatewayGroups)
            throws RegistryServiceException, DuplicateEntryException, TException {
        try {
            if (gatewayGroupsRepository.isExists(gatewayGroups.getGatewayId())) {
                logger.error("GatewayGroups already exists for " + gatewayGroups.getGatewayId());
                throw new DuplicateEntryException(
                        "GatewayGroups for gatewayId: " + gatewayGroups.getGatewayId() + " already exists.");
            }
            gatewayGroupsRepository.create(gatewayGroups);
        } catch (DuplicateEntryException e) {
            throw e; // re-throw
        } catch (Exception e) {

            final String message =
                    "Error while creating a GatewayGroups entry for gateway " + gatewayGroups.getGatewayId() + ".";
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public void updateGatewayGroups(GatewayGroups gatewayGroups) throws RegistryServiceException, TException {
        try {
            if (!gatewayGroupsRepository.isExists(gatewayGroups.getGatewayId())) {
                final String message = "No GatewayGroups entry exists for " + gatewayGroups.getGatewayId();
                logger.error(message);
                throw new RegistryServiceException(message);
            }
            gatewayGroupsRepository.update(gatewayGroups);
        } catch (RegistryServiceException e) {
            throw e; // re-throw
        } catch (Exception e) {

            final String message =
                    "Error while updating the GatewayGroups entry for gateway " + gatewayGroups.getGatewayId() + ".";
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public boolean isGatewayGroupsExists(String gatewayId) throws RegistryServiceException, TException {
        try {
            return gatewayGroupsRepository.isExists(gatewayId);
        } catch (Exception e) {
            final String message = "Error checking existence of the GatewayGroups entry for gateway " + gatewayId + ".";
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public GatewayGroups getGatewayGroups(String gatewayId) throws RegistryServiceException, TException {
        try {
            if (!gatewayGroupsRepository.isExists(gatewayId)) {
                final String message = "No GatewayGroups entry exists for " + gatewayId;
                logger.error(message);
                throw new RegistryServiceException(message);
            }
            return gatewayGroupsRepository.get(gatewayId);
        } catch (RegistryServiceException e) {
            throw e; // re-throw
        } catch (Exception e) {

            final String message = "Error while retrieving the GatewayGroups entry for gateway " + gatewayId + ".";
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public Parser getParser(String parserId, String gatewayId) throws RegistryServiceException, TException {

        try {
            if (!parserRepository.isExists(parserId)) {
                final String message = "No Parser Info entry exists for " + parserId;
                logger.error(message);
                throw new RegistryServiceException(message);
            }
            return parserRepository.get(parserId);

        } catch (RegistryServiceException e) {
            throw e; // re-throw

        } catch (Exception e) {
            final String message = "Error while retrieving parser with id " + parserId + ".";
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public String saveParser(Parser parser) throws RegistryServiceException, TException {

        try {
            Parser created = parserRepository.saveParser(parser);
            return created.getId();

        } catch (Exception e) {
            final String message = "Error while saving parser with id " + parser.getId();
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public List<Parser> listAllParsers(String gatewayId) throws RegistryServiceException, TException {

        try {
            return parserRepository.getAllParsers(gatewayId);

        } catch (Exception e) {
            final String message = "Error while listing parsers for gateway " + gatewayId;
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public void removeParser(String parserId, String gatewayId) throws RegistryServiceException, TException {

        try {
            boolean exists = parserRepository.isExists(parserId);

            if (exists && !gatewayId.equals(parserRepository.get(parserId).getGatewayId())) {
                parserRepository.delete(parserId);
            } else {
                throw new RegistryServiceException("Parser " + parserId + " does not exist");
            }
        } catch (RegistryServiceException e) {
            throw e; // re-throw

        } catch (Exception e) {
            final String message = "Error while removing parser with id " + parserId + ".";
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public ParserInput getParserInput(String parserInputId, String gatewayId)
            throws RegistryServiceException, TException {
        try {
            ParserInput parserInput = parserInputRepository.getParserInput(parserInputId);
            // TODO check the gateway

            return parserInput;
        } catch (Exception e) {
            logger.error("Failed to fetch parser input " + parserInputId + " for gateway " + gatewayId, e);
            throw new RegistryServiceException("Failed to fetch parser input " + parserInputId + " for gateway "
                    + gatewayId + " More info: " + e.getMessage());
        }
    }

    @Override
    public ParserOutput getParserOutput(String parserOutputId, String gatewayId)
            throws RegistryServiceException, TException {
        try {
            ParserOutput parserOutput = parserOutputRepository.getParserOutput(parserOutputId);
            // TODO check the gateway

            return parserOutput;
        } catch (Exception e) {
            logger.error("Failed to fetch parser output " + parserOutputId + " for gateway " + gatewayId, e);
            throw new RegistryServiceException("Failed to fetch parser output " + parserOutputId + " for gateway "
                    + gatewayId + " More info: " + e.getMessage());
        }
    }

    @Override
    public ParsingTemplate getParsingTemplate(String templateId, String gatewayId)
            throws RegistryServiceException, TException {

        try {
            if (!parsingTemplateRepository.isExists(templateId)) {
                final String message = "No Parsing Template entry exists for " + templateId;
                logger.error(message);
                throw new RegistryServiceException(message);
            }
            return parsingTemplateRepository.get(templateId);

        } catch (RegistryServiceException e) {
            throw e; // re-throw

        } catch (Exception e) {
            final String message = "Error while retrieving Parsing Template for id " + templateId + ".";
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public List<ParsingTemplate> getParsingTemplatesForExperiment(String experimentId, String gatewayId)
            throws RegistryServiceException, TException {

        try {
            List<ProcessModel> processes = getExperiment(experimentId).getProcesses();
            if (processes.size() > 0) {
                return parsingTemplateRepository.getParsingTemplatesForApplication(
                        processes.get(processes.size() - 1).getApplicationInterfaceId());
            }
            return Collections.emptyList();

        } catch (Exception e) {
            final String message = "Error while retrieving parsing templates for experiment id " + experimentId;
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public String saveParsingTemplate(ParsingTemplate parsingTemplate) throws RegistryServiceException, TException {

        try {
            ParsingTemplate saved = parsingTemplateRepository.create(parsingTemplate);
            return saved.getId();

        } catch (Exception e) {
            final String message = "Error while saving parsing template with id " + parsingTemplate.getId();
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public List<ParsingTemplate> listAllParsingTemplates(String gatewayId) throws RegistryServiceException, TException {

        try {
            return parsingTemplateRepository.getAllParsingTemplates(gatewayId);

        } catch (Exception e) {
            final String message = "Error while listing parsing templates for gateway " + gatewayId;
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public void removeParsingTemplate(String templateId, String gatewayId) throws RegistryServiceException, TException {

        try {
            boolean exists = parsingTemplateRepository.isExists(templateId);

            if (exists
                    && !gatewayId.equals(
                            parsingTemplateRepository.get(templateId).getGatewayId())) {
                parsingTemplateRepository.delete(templateId);
            } else {
                throw new RegistryServiceException("Parsing tempolate " + templateId + " does not exist");
            }
        } catch (RegistryServiceException e) {
            throw e; // re-throw

        } catch (Exception e) {

            final String message = "Error while removing parsing template with id " + templateId;
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + " More info: " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public boolean isGatewayUsageReportingAvailable(String gatewayId, String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            return usageReportingCommandRepository.isGatewayUsageReportingCommandExists(gatewayId, computeResourceId);
        } catch (Exception e) {
            String message = "Failed to check the availability to find the reporting information for the gateway "
                    + gatewayId + " and compute resource " + computeResourceId;
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + ". More info " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public GatewayUsageReportingCommand getGatewayReportingCommand(String gatewayId, String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            if (usageReportingCommandRepository.isGatewayUsageReportingCommandExists(gatewayId, computeResourceId)) {
                return usageReportingCommandRepository.getGatewayUsageReportingCommand(gatewayId, computeResourceId);
            } else {
                String message = "No usage reporting information for the gateway " + gatewayId
                        + " and compute resource " + computeResourceId;
                logger.error(message);
                throw new RegistryServiceException(message);
            }
        } catch (RegistryServiceException e) {
            throw e; // re-throw

        } catch (Exception e) {
            String message = "Failed to check the availability to find the reporting information for the gateway "
                    + gatewayId + " and compute resource " + computeResourceId;
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + ". More info " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public void addGatewayUsageReportingCommand(GatewayUsageReportingCommand command)
            throws RegistryServiceException, TException {
        try {
            usageReportingCommandRepository.addGatewayUsageReportingCommand(command);
        } catch (Exception e) {
            String message = "Failed to add the reporting information for the gateway " + command.getGatewayId()
                    + " and compute resource " + command.getComputeResourceId();
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + ". More info " + e.getMessage());
            throw rse;
        }
    }

    @Override
    public void removeGatewayUsageReportingCommand(String gatewayId, String computeResourceId)
            throws RegistryServiceException, TException {
        try {
            usageReportingCommandRepository.removeGatewayUsageReportingCommand(gatewayId, computeResourceId);
        } catch (Exception e) {
            String message = "Failed to add the reporting information for the gateway " + gatewayId
                    + " and compute resource " + computeResourceId;
            logger.error(message, e);
            RegistryServiceException rse = new RegistryServiceException();
            rse.setMessage(message + ". More info " + e.getMessage());
            throw rse;
        }
    }
}
