org.wso2.carbon.appmgt.impl.APIConsumerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.appmgt.impl.APIConsumerImpl.java

Source

/*
*  Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. 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.wso2.carbon.appmgt.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.appmgt.api.APIConsumer;
import org.wso2.carbon.appmgt.api.AppManagementException;
import org.wso2.carbon.appmgt.api.model.*;
import org.wso2.carbon.appmgt.api.model.Tag;
import org.wso2.carbon.appmgt.impl.dto.SubscriptionWorkflowDTO;
import org.wso2.carbon.appmgt.impl.dto.TierPermissionDTO;
import org.wso2.carbon.appmgt.impl.service.ServiceReferenceHolder;
import org.wso2.carbon.appmgt.impl.utils.APINameComparator;
import org.wso2.carbon.appmgt.impl.utils.AppManagerUtil;
import org.wso2.carbon.appmgt.impl.utils.APIVersionComparator;
import org.wso2.carbon.appmgt.impl.workflow.*;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.governance.api.exception.GovernanceException;
import org.wso2.carbon.governance.api.generic.GenericArtifactManager;
import org.wso2.carbon.governance.api.generic.dataobjects.GenericArtifact;
import org.wso2.carbon.registry.core.*;
import org.wso2.carbon.registry.core.Collection;
import org.wso2.carbon.registry.core.config.RegistryContext;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.pagination.PaginationContext;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.registry.core.utils.RegistryUtils;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class provides the core WebApp store functionality. It is implemented in a very
 * self-contained and 'pure' manner, without taking requirements like security into account,
 * which are subject to frequent change. Due to this 'pure' nature and the significance of
 * the class to the overall WebApp management functionality, the visibility of the class has
 * been reduced to package level. This means we can still use it for internal purposes and
 * possibly even extend it, but it's totally off the limits of the users. Users wishing to
 * programmatically access this functionality should use one of the extensions of this
 * class which is visible to them. These extensions may add additional features like
 * security to this class.
 */
class APIConsumerImpl extends AbstractAPIManager implements APIConsumer {

    private static final Log log = LogFactory.getLog(APIConsumerImpl.class);

    /* Map to Store APIs against Tag */
    private Map<String, Set<WebApp>> taggedAPIs;
    private boolean isTenantModeStoreView;
    private String requestedTenant;
    private boolean isTagCacheEnabled;
    private Set<Tag> tagSet;
    private long tagCacheValidityTime;
    private long lastUpdatedTime;
    private Object tagCacheMutex = new Object();

    public APIConsumerImpl() throws AppManagementException {
        super();
        readTagCacheConfigs();
    }

    public APIConsumerImpl(String username) throws AppManagementException {
        super(username);
        readTagCacheConfigs();
    }

    private void readTagCacheConfigs() {
        AppManagerConfiguration config = ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService()
                .getAPIManagerConfiguration();
        String enableTagCache = config.getFirstProperty(AppMConstants.API_STORE_TAG_CACHE_DURATION);
        if (enableTagCache == null) {
            isTagCacheEnabled = false;
            tagCacheValidityTime = 0;
        } else {
            isTagCacheEnabled = true;
            tagCacheValidityTime = Long.parseLong(enableTagCache);
        }
    }

    public Subscriber getSubscriber(String subscriberId) throws AppManagementException {
        Subscriber subscriber = null;
        try {
            subscriber = appMDAO.getSubscriber(subscriberId);
        } catch (AppManagementException e) {
            handleException("Failed to get Subscriber", e);
        }
        return subscriber;
    }

    /**
     * Retrieve business owner by given id.
     *
     * @param businessOwnerId Id of business owner
     * @return {@link BusinessOwner} object
     * @throws AppManagementException on error while trying to get business owner
     */
    @Override
    public BusinessOwner getBusinessOwner(int businessOwnerId) throws AppManagementException {
        return appMDAO.getBusinessOwner(businessOwnerId, tenantId);
    }

    /**
     * Retrieve business owner for a given business owner id.
     *
     * @param businessOwnerId Business owner id
     * @param appTenantId     Tenant id of the application
     * @return {@link BusinessOwner} object
     * @throws AppManagementException on error while trying to get business owner
     */
    @Override
    public BusinessOwner getBusinessOwnerForAppStore(int businessOwnerId, int appTenantId)
            throws AppManagementException {
        return appMDAO.getBusinessOwner(businessOwnerId, appTenantId);
    }

    /**
     * Search business owner.
     *
     * @param searchPrefix Search prefix
     * @param tenantId  Tenant Id of the application
     * @return List of business owner ids
     * @throws AppManagementException on error while trying to search business owner
     */
    @Override
    public List<String> getBusinessOwnerIdsBySearchPrefix(String searchPrefix, int tenantId)
            throws AppManagementException {
        return appMDAO.getBusinessOwnerIdsBySearchPrefix(searchPrefix, tenantId);
    }

    /**
     * Returns the set of APIs with the given tag from the taggedAPIs Map
     *
     * @param tag
     * @return
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    public Set<WebApp> getAPIsWithTag(String tag) throws AppManagementException {
        if (taggedAPIs != null) {
            return taggedAPIs.get(tag);
        }
        this.getAllTags(this.tenantDomain);
        if (taggedAPIs != null) {
            return taggedAPIs.get(tag);
        }
        return null;
    }

    /**
     * Returns the set of APIs with the given tag from the taggedAPIs Map
     *
     * @param tag
     * @return
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    public Map<String, Object> getPaginatedAPIsWithTag(String tag, int start, int end)
            throws AppManagementException {
        List<WebApp> apiSet = new ArrayList<WebApp>();
        Set<WebApp> resultSet = new TreeSet<WebApp>(new APIVersionComparator());
        Map<String, Object> results = new HashMap<String, Object>();
        Set<WebApp> taggedAPISet = this.getAPIsWithTag(tag);
        if (taggedAPISet != null) {
            if (taggedAPISet.size() < end) {
                end = taggedAPISet.size();
            }

            apiSet.addAll(taggedAPISet);
            for (int i = start; i < end; i++) {
                resultSet.add(apiSet.get(i));
            }

            results.put("apis", resultSet);
            results.put("length", taggedAPISet.size());
        } else {
            results.put("apis", null);
            results.put("length", 0);

        }
        return results;
    }

    /**
     * Returns the set of apps with the given tag, retrieved from registry.
     *
     * @param registry Current registry; tenant/SuperTenant.
     * @param tag
     * @param attributeMap
     * @return
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    private Set<WebApp> getAppsWithTag(Registry registry, String tag, String assetType,
            Map<String, String> attributeMap) throws AppManagementException {
        Set<WebApp> apiSet = new TreeSet<WebApp>(new APINameComparator());
        boolean isTenantFlowStarted = false;
        try {
            if (tenantDomain != null && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                isTenantFlowStarted = true;
                PrivilegedCarbonContext.startTenantFlow();
                PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
            }
            String resourceByTagQueryPath = RegistryConstants.QUERIES_COLLECTION_PATH + "/resource-by-tag-appm";
            Map<String, String> params = new HashMap<String, String>();
            params.put("1", tag);
            if (AppMConstants.WEBAPP_ASSET_TYPE.equals(assetType)
                    || AppMConstants.SITE_ASSET_TYPE.equals(assetType)) {
                params.put("2", AppMConstants.MediaType.WEB_APP);
            } else if (AppMConstants.MOBILE_ASSET_TYPE.equals(assetType)) {
                params.put("2", AppMConstants.MediaType.MOBILE_APP);
            } else {
                handleException("Could not retrieved app for tag.App type :" + assetType + " does not exist");
            }

            params.put(RegistryConstants.RESULT_TYPE_PROPERTY_NAME, RegistryConstants.RESOURCE_UUID_RESULT_TYPE);
            Collection collection = registry.executeQuery(resourceByTagQueryPath, params);

            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry, assetType);

            for (String row : collection.getChildren()) {
                boolean isTagRetrievable = false;
                String uuid = row.substring(row.indexOf(";") + 1, row.length());
                GenericArtifact genericArtifact = artifactManager.getGenericArtifact(uuid);
                if (attributeMap == null || attributeMap.isEmpty()) {
                    isTagRetrievable = true;
                } else {
                    //genericArtifact can be null when user doesn't have permission to artifact.
                    if (genericArtifact != null) {
                        String artifactTreatAsASiteValue = genericArtifact
                                .getAttribute(AppMConstants.APP_OVERVIEW_TREAT_AS_A_SITE).toLowerCase();
                        String attributeMapTreatAsASiteValue = attributeMap
                                .get(AppMConstants.APP_OVERVIEW_TREAT_AS_A_SITE).toString().toLowerCase();
                        if (attributeMapTreatAsASiteValue.equals(artifactTreatAsASiteValue)) {
                            isTagRetrievable = true;
                        }
                    }
                }

                if (genericArtifact != null
                        && genericArtifact.getLifecycleState().equals(AppMConstants.APP_LC_PUBLISHED)
                        && isTagRetrievable) {
                    apiSet.add(AppManagerUtil.getAPI(genericArtifact));
                }
            }

        } catch (RegistryException e) {
            handleException("Failed to get WebApp for tag " + tag, e);
        } finally {
            if (isTenantFlowStarted) {
                PrivilegedCarbonContext.endTenantFlow();
            }
        }
        return apiSet;
    }

    /**
     * The method to get APIs to Store view      *
     *
     * @return Set<WebApp>  Set of APIs
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    public Set<WebApp> getAllPublishedAPIs(String tenantDomain) throws AppManagementException {
        SortedSet<WebApp> apiSortedSet = new TreeSet<WebApp>(new APINameComparator());
        SortedSet<WebApp> apiVersionsSortedSet = new TreeSet<WebApp>(new APIVersionComparator());
        try {
            Registry userRegistry;
            boolean isTenantMode = (tenantDomain != null);
            if ((isTenantMode && this.tenantDomain == null)
                    || (isTenantMode && isTenantDomainNotMatching(tenantDomain))) {//Tenant store anonymous mode
                int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(tenantDomain);
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantId);
            } else {
                userRegistry = registry;
            }
            this.isTenantModeStoreView = isTenantMode;
            this.requestedTenant = tenantDomain;
            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(userRegistry,
                    AppMConstants.API_KEY);
            if (artifactManager != null) {
                GenericArtifact[] genericArtifacts = artifactManager.getAllGenericArtifacts();
                if (genericArtifacts == null || genericArtifacts.length == 0) {
                    return apiSortedSet;
                }

                Map<String, WebApp> latestPublishedAPIs = new HashMap<String, WebApp>();
                List<WebApp> multiVersionedAPIs = new ArrayList<WebApp>();
                Comparator<WebApp> versionComparator = new APIVersionComparator();
                Boolean displayMultipleVersions = isAllowDisplayMultipleVersions();
                Boolean displayAPIsWithMultipleStatus = isAllowDisplayAPIsWithMultipleStatus();
                for (GenericArtifact artifact : genericArtifacts) {
                    // adding the WebApp provider can mark the latest WebApp .
                    String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                    WebApp api = null;
                    //Check the app-manager.xml config file entry <DisplayAllAPIs> value is false
                    if (!displayAPIsWithMultipleStatus) {
                        // then we are only interested in published APIs here...
                        if (status.equals(AppMConstants.PUBLISHED)) {
                            api = AppManagerUtil.getAPI(artifact);
                        }
                    } else { // else we are interested in both deprecated/published APIs here...
                        if (status.equals(AppMConstants.PUBLISHED) || status.equals(AppMConstants.DEPRECATED)) {
                            api = AppManagerUtil.getAPI(artifact);

                        }

                    }
                    if (api != null) {
                        String key;
                        //Check the configuration to allow showing multiple versions of an WebApp true/false
                        if (!displayMultipleVersions) { //If allow only showing the latest version of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName();
                            WebApp existingAPI = latestPublishedAPIs.get(key);
                            if (existingAPI != null) {
                                // If we have already seen an WebApp with the same name, make sure
                                // this one has a higher version number
                                if (versionComparator.compare(api, existingAPI) > 0) {
                                    latestPublishedAPIs.put(key, api);
                                }
                            } else {
                                // We haven't seen this WebApp before
                                latestPublishedAPIs.put(key, api);
                            }
                        } else { //If allow showing multiple versions of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName() + ":"
                                    + api.getId().getVersion();
                            multiVersionedAPIs.add(api);
                        }
                    }
                }
                if (!displayMultipleVersions) {
                    for (WebApp api : latestPublishedAPIs.values()) {
                        apiSortedSet.add(api);
                    }
                    return apiSortedSet;
                } else {
                    for (WebApp api : multiVersionedAPIs) {
                        apiVersionsSortedSet.add(api);
                    }
                    return apiVersionsSortedSet;
                }
            }

        } catch (RegistryException e) {
            handleException("Failed to get all published APIs", e);
        } catch (UserStoreException e) {
            handleException("Failed to get all published APIs", e);
        }
        return apiSortedSet;

    }

    /**
     * The method to get APIs to Store view      *
     *
     * @return Set<WebApp>  Set of APIs
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    public Map<String, Object> getAllPaginatedPublishedAPIs(String tenantDomain, int start, int end)
            throws AppManagementException {

        Boolean displayAPIsWithMultipleStatus = isAllowDisplayAPIsWithMultipleStatus();
        Map<String, List<String>> listMap = new HashMap<String, List<String>>();
        //Check the app-manager.xml config file entry <DisplayAllAPIs> value is false
        if (!displayAPIsWithMultipleStatus) {
            //Create the search attribute map
            listMap.put(AppMConstants.API_OVERVIEW_STATUS, new ArrayList<String>() {
                {
                    add(AppMConstants.PUBLISHED);
                }
            });
        } else {
            return getAllPaginatedAPIs(tenantDomain, start, end);
        }

        Map<String, Object> result = new HashMap<String, Object>();
        SortedSet<WebApp> apiSortedSet = new TreeSet<WebApp>(new APINameComparator());
        SortedSet<WebApp> apiVersionsSortedSet = new TreeSet<WebApp>(new APIVersionComparator());
        int totalLength = 0;
        try {
            Registry userRegistry;
            boolean isTenantMode = (tenantDomain != null);
            if ((isTenantMode && this.tenantDomain == null)
                    || (isTenantMode && isTenantDomainNotMatching(tenantDomain))) {//Tenant store anonymous mode
                int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(tenantDomain);
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantId);
            } else {
                userRegistry = registry;
            }
            this.isTenantModeStoreView = isTenantMode;
            this.requestedTenant = tenantDomain;
            PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(this.username);

            Map<String, WebApp> latestPublishedAPIs = new HashMap<String, WebApp>();
            List<WebApp> multiVersionedAPIs = new ArrayList<WebApp>();
            Comparator<WebApp> versionComparator = new APIVersionComparator();
            Boolean displayMultipleVersions = isAllowDisplayMultipleVersions();

            PaginationContext.init(start, end, "ASC", AppMConstants.API_OVERVIEW_NAME, Integer.MAX_VALUE);

            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(userRegistry,
                    AppMConstants.API_KEY);
            if (artifactManager != null) {
                GenericArtifact[] genericArtifacts = artifactManager.findGenericArtifacts(listMap);
                totalLength = PaginationContext.getInstance().getLength();
                if (genericArtifacts == null || genericArtifacts.length == 0) {
                    result.put("apis", apiSortedSet);
                    result.put("totalLength", totalLength);
                    return result;
                }

                for (GenericArtifact artifact : genericArtifacts) {
                    // adding the WebApp provider can mark the latest WebApp .
                    String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                    WebApp api = AppManagerUtil.getAPI(artifact);

                    if (api != null) {
                        String key;
                        //Check the configuration to allow showing multiple versions of an WebApp true/false
                        if (!displayMultipleVersions) { //If allow only showing the latest version of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName();
                            WebApp existingAPI = latestPublishedAPIs.get(key);
                            if (existingAPI != null) {
                                // If we have already seen an WebApp with the same name, make sure
                                // this one has a higher version number
                                if (versionComparator.compare(api, existingAPI) > 0) {
                                    latestPublishedAPIs.put(key, api);
                                }
                            } else {
                                // We haven't seen this WebApp before
                                latestPublishedAPIs.put(key, api);
                            }
                        } else { //If allow showing multiple versions of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName() + ":"
                                    + api.getId().getVersion();
                            multiVersionedAPIs.add(api);
                        }
                    }
                }
                if (!displayMultipleVersions) {
                    for (WebApp api : latestPublishedAPIs.values()) {
                        apiSortedSet.add(api);
                    }
                    result.put("apis", apiSortedSet);
                    result.put("totalLength", totalLength);
                    return result;

                } else {
                    for (WebApp api : multiVersionedAPIs) {
                        apiVersionsSortedSet.add(api);
                    }
                    result.put("apis", apiVersionsSortedSet);
                    result.put("totalLength", totalLength);
                    return result;

                }
            }

        } catch (RegistryException e) {
            handleException("Failed to get all published APIs", e);
        } catch (UserStoreException e) {
            handleException("Failed to get all published APIs", e);
        } finally {
            PaginationContext.destroy();
        }
        result.put("apis", apiSortedSet);
        result.put("totalLength", totalLength);
        return result;

    }

    /**
     * The method to get All PUBLISHED and DEPRECATED APIs, to Store view      
     *
     * @return Set<WebApp>  Set of APIs
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    public Map<String, Object> getAllPaginatedAPIs(String tenantDomain, int start, int end)
            throws AppManagementException {
        Map<String, Object> result = new HashMap<String, Object>();
        SortedSet<WebApp> apiSortedSet = new TreeSet<WebApp>(new APINameComparator());
        SortedSet<WebApp> apiVersionsSortedSet = new TreeSet<WebApp>(new APIVersionComparator());
        int totalLength = 0;
        try {
            Registry userRegistry;
            boolean isTenantMode = (tenantDomain != null);
            if ((isTenantMode && this.tenantDomain == null)
                    || (isTenantMode && isTenantDomainNotMatching(tenantDomain))) {//Tenant store anonymous mode
                int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(tenantDomain);
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantId);
            } else {
                userRegistry = registry;
            }
            this.isTenantModeStoreView = isTenantMode;
            this.requestedTenant = tenantDomain;
            PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(this.username);

            Map<String, WebApp> latestPublishedAPIs = new HashMap<String, WebApp>();
            List<WebApp> multiVersionedAPIs = new ArrayList<WebApp>();
            Comparator<WebApp> versionComparator = new APIVersionComparator();
            Boolean displayMultipleVersions = isAllowDisplayMultipleVersions();

            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(userRegistry,
                    AppMConstants.API_KEY);

            PaginationContext.init(start, end, "ASC", AppMConstants.API_OVERVIEW_NAME, Integer.MAX_VALUE);

            boolean noPublishedAPIs = false;
            if (artifactManager != null) {

                //Create the search attribute map for PUBLISHED APIs
                Map<String, List<String>> listMap = new HashMap<String, List<String>>();
                listMap.put(AppMConstants.API_OVERVIEW_STATUS, new ArrayList<String>() {
                    {
                        add(AppMConstants.PUBLISHED);
                    }
                });

                GenericArtifact[] genericArtifacts = artifactManager.findGenericArtifacts(listMap);
                totalLength = PaginationContext.getInstance().getLength();
                if (genericArtifacts == null || genericArtifacts.length == 0) {
                    noPublishedAPIs = true;
                }
                int publishedAPICount = 0;
                for (GenericArtifact artifact : genericArtifacts) {
                    // adding the WebApp provider can mark the latest WebApp .
                    String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                    WebApp api = AppManagerUtil.getAPI(artifact);

                    if (api != null) {
                        String key;
                        //Check the configuration to allow showing multiple versions of an WebApp true/false
                        if (!displayMultipleVersions) { //If allow only showing the latest version of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName();
                            WebApp existingAPI = latestPublishedAPIs.get(key);
                            if (existingAPI != null) {
                                // If we have already seen an WebApp with the same name, make sure
                                // this one has a higher version number
                                if (versionComparator.compare(api, existingAPI) > 0) {
                                    latestPublishedAPIs.put(key, api);
                                }
                            } else {
                                // We haven't seen this WebApp before
                                latestPublishedAPIs.put(key, api);
                            }
                        } else { //If allow showing multiple versions of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName() + ":"
                                    + api.getId().getVersion();
                            multiVersionedAPIs.add(api);
                        }
                    }
                }
                if (!displayMultipleVersions) {
                    publishedAPICount = latestPublishedAPIs.size();
                } else {
                    publishedAPICount = multiVersionedAPIs.size();
                }
                if ((start + end) > publishedAPICount) {
                    if (publishedAPICount > 0) {
                        /*Starting to retrieve DEPRECATED APIs*/
                        start = 0;
                        /* publishedAPICount is always less than end*/
                        end = end - publishedAPICount;
                    } else {
                        start = start - totalLength;
                    }
                    PaginationContext.init(start, end, "ASC", AppMConstants.API_OVERVIEW_NAME, Integer.MAX_VALUE);
                    //Create the search attribute map for DEPRECATED APIs
                    Map<String, List<String>> listMapForDeprecatedAPIs = new HashMap<String, List<String>>();
                    listMapForDeprecatedAPIs.put(AppMConstants.API_OVERVIEW_STATUS, new ArrayList<String>() {
                        {
                            add(AppMConstants.DEPRECATED);
                        }
                    });

                    GenericArtifact[] genericArtifactsForDeprecatedAPIs = artifactManager
                            .findGenericArtifacts(listMapForDeprecatedAPIs);
                    totalLength = totalLength + PaginationContext.getInstance().getLength();
                    if ((genericArtifactsForDeprecatedAPIs == null || genericArtifactsForDeprecatedAPIs.length == 0)
                            && noPublishedAPIs) {
                        result.put("apis", apiSortedSet);
                        result.put("totalLength", totalLength);
                        return result;
                    }

                    for (GenericArtifact artifact : genericArtifactsForDeprecatedAPIs) {
                        // adding the WebApp provider can mark the latest WebApp .
                        String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                        WebApp api = AppManagerUtil.getAPI(artifact);

                        if (api != null) {
                            String key;
                            //Check the configuration to allow showing multiple versions of an WebApp true/false
                            if (!displayMultipleVersions) { //If allow only showing the latest version of an WebApp
                                key = api.getId().getProviderName() + ":" + api.getId().getApiName();
                                WebApp existingAPI = latestPublishedAPIs.get(key);
                                if (existingAPI != null) {
                                    // If we have already seen an WebApp with the same name, make sure
                                    // this one has a higher version number
                                    if (versionComparator.compare(api, existingAPI) > 0) {
                                        latestPublishedAPIs.put(key, api);
                                    }
                                } else {
                                    // We haven't seen this WebApp before
                                    latestPublishedAPIs.put(key, api);
                                }
                            } else { //If allow showing multiple versions of an WebApp
                                key = api.getId().getProviderName() + ":" + api.getId().getApiName() + ":"
                                        + api.getId().getVersion();
                                multiVersionedAPIs.add(api);
                            }
                        }
                    }
                }

                if (!displayMultipleVersions) {
                    for (WebApp api : latestPublishedAPIs.values()) {
                        apiSortedSet.add(api);
                    }
                    result.put("apis", apiSortedSet);
                    result.put("totalLength", totalLength);
                    return result;

                } else {
                    for (WebApp api : multiVersionedAPIs) {
                        apiVersionsSortedSet.add(api);
                    }
                    result.put("apis", apiVersionsSortedSet);
                    result.put("totalLength", totalLength);
                    return result;

                }
            }

        } catch (RegistryException e) {
            handleException("Failed to get all published APIs", e);
        } catch (UserStoreException e) {
            handleException("Failed to get all published APIs", e);
        } finally {
            PaginationContext.destroy();
        }
        result.put("apis", apiSortedSet);
        result.put("totalLength", totalLength);
        return result;

    }

    private <T> T[] concatArrays(T[] first, T[] second) {
        T[] result = Arrays.copyOf(first, first.length + second.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }

    public Set<WebApp> getTopRatedAPIs(int limit) throws AppManagementException {
        int returnLimit = 0;
        SortedSet<WebApp> apiSortedSet = new TreeSet<WebApp>(new APINameComparator());
        try {
            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry,
                    AppMConstants.API_KEY);
            GenericArtifact[] genericArtifacts = artifactManager.getAllGenericArtifacts();
            if (genericArtifacts == null || genericArtifacts.length == 0) {
                return apiSortedSet;
            }
            for (GenericArtifact genericArtifact : genericArtifacts) {
                String status = genericArtifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);
                if (status.equals(AppMConstants.PUBLISHED)) {
                    String artifactPath = genericArtifact.getPath();

                    float rating = registry.getAverageRating(artifactPath);
                    if (rating > AppMConstants.TOP_TATE_MARGIN && (returnLimit < limit)) {
                        returnLimit++;
                        apiSortedSet.add(AppManagerUtil.getAPI(genericArtifact, registry));
                    }
                }
            }
        } catch (RegistryException e) {
            handleException("Failed to get top rated WebApp", e);
        }
        return apiSortedSet;
    }

    public float getAverageRating(String uuid, String assetType) throws AppManagementException {
        float rating = 0;
        try {
            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry, assetType);
            GenericArtifact genericArtifact = artifactManager.getGenericArtifact(uuid);
            rating = registry.getAverageRating(genericArtifact.getPath());
        } catch (RegistryException e) {
            handleException("Failed to retrieve rating", e);
        }
        return rating;
    }

    /**
     * Get the recently added APIs set
     *
     * @param limit no limit. Return everything else, limit the return list to specified value.
     * @return Set<WebApp>
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    public Set<WebApp> getRecentlyAddedAPIs(int limit, String tenantDomain) throws AppManagementException {
        SortedSet<WebApp> recentlyAddedAPIs = new TreeSet<WebApp>(new APINameComparator());
        SortedSet<WebApp> recentlyAddedAPIsWithMultipleVersions = new TreeSet<WebApp>(new APIVersionComparator());
        Registry userRegistry = null;
        String latestAPIQueryPath = null;
        try {
            boolean isTenantMode = (tenantDomain != null);
            if ((isTenantMode && this.tenantDomain == null)
                    || (isTenantMode && isTenantDomainNotMatching(tenantDomain))) {//Tenant based store anonymous mode
                int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(tenantDomain);
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantId);
            } else {
                userRegistry = registry;
            }

            latestAPIQueryPath = RegistryConstants.QUERIES_COLLECTION_PATH + "/latest-apis";
            Map<String, String> params = new HashMap<String, String>();
            params.put(RegistryConstants.RESULT_TYPE_PROPERTY_NAME, RegistryConstants.RESOURCES_RESULT_TYPE);
            if (userRegistry != null) {
                Collection collection = userRegistry.executeQuery(latestAPIQueryPath, params);
                int resultSetSize = Math.min(limit, collection.getChildCount());
                String[] recentlyAddedAPIPaths = new String[resultSetSize];
                for (int i = 0; i < resultSetSize; i++) {
                    recentlyAddedAPIPaths[i] = collection.getChildren()[i];
                }
                Set<WebApp> apisSet = getAPIs(userRegistry, limit, recentlyAddedAPIPaths);
                if (!isAllowDisplayMultipleVersions()) {

                    recentlyAddedAPIs.addAll(apisSet);
                    return recentlyAddedAPIs;
                } else {
                    recentlyAddedAPIsWithMultipleVersions.addAll(apisSet);
                    return recentlyAddedAPIsWithMultipleVersions;
                }
            }
            return recentlyAddedAPIs;

        } catch (RegistryException e) {
            try {
                //Before a tenant login to the store or publisher at least one time, 
                //a registry exception is thrown when the tenant store is accessed the store in anonymous mode.
                //This fix checks whether query resource available in the registry. If not
                // give a warn. 
                if (!userRegistry.resourceExists(latestAPIQueryPath)) {
                    log.warn("Failed to retrieve recently added WebApp query resource at " + latestAPIQueryPath);
                    return recentlyAddedAPIs;
                }
            } catch (RegistryException e1) {
                //ignore
            }
            handleException("Failed to get recently added APIs", e);
            return null;
        } catch (org.wso2.carbon.user.api.UserStoreException e) {
            handleException("Failed to get recently added APIs", e);
            return null;
        }

    }

    public Set<Tag> getAllTags(String requestedTenantDomain) throws AppManagementException {
        return getAllTags(requestedTenantDomain, null, null);
    }

    /**
     * @param requestedTenantDomain
     * @param assetType Currently we don't use asset type. Asset type could be webapp, mobileapp or any other asset type.
     * @param attributeMap Attribute map for the give assetType.
     * @return matching tag set which qualified the conditions of assetTye and attributeMap.
     * @throws AppManagementException
     */
    public Set<Tag> getAllTags(String requestedTenantDomain, String assetType, Map<String, String> attributeMap)
            throws AppManagementException {

        this.isTenantModeStoreView = (requestedTenantDomain != null);

        if (requestedTenantDomain != null) {
            this.requestedTenant = requestedTenantDomain;
        }

        /* We keep track of the lastUpdatedTime of the TagCache to determine its freshness.
         */
        long lastUpdatedTimeAtStart = lastUpdatedTime;
        long currentTimeAtStart = System.currentTimeMillis();
        if (isTagCacheEnabled && ((currentTimeAtStart - lastUpdatedTimeAtStart) < tagCacheValidityTime)) {
            if (tagSet != null) {
                return tagSet;
            }
        }

        Map<String, Set<WebApp>> tempTaggedAPIs = new HashMap<String, Set<WebApp>>();
        TreeSet<Tag> tempTagSet = new TreeSet<Tag>(new Comparator<Tag>() {
            @Override
            public int compare(Tag o1, Tag o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        Registry userRegistry = null;
        String tagsQueryPath = null;
        try {
            tagsQueryPath = RegistryConstants.QUERIES_COLLECTION_PATH + "/tag-summary-appmgt";
            Map<String, String> params = new HashMap<String, String>();
            params.put(RegistryConstants.RESULT_TYPE_PROPERTY_NAME, RegistryConstants.TAG_SUMMARY_RESULT_TYPE);

            if (AppMConstants.WEBAPP_ASSET_TYPE.equals(assetType)
                    || AppMConstants.SITE_ASSET_TYPE.equals(assetType)) {
                params.put("1", AppMConstants.MediaType.WEB_APP);
                params.put("2", AppMConstants.WEB_APP_LIFECYCLE_STATUS);
                params.put("3", AppMConstants.APP_LC_PUBLISHED);
            } else if (AppMConstants.MOBILE_ASSET_TYPE.equals(assetType)) {
                params.put("1", AppMConstants.MediaType.MOBILE_APP);
                params.put("2", AppMConstants.MOBILE_APP_LIFECYCLE_STATUS);
                params.put("3", AppMConstants.APP_LC_PUBLISHED);
            } else {
                handleException("Could not retrieved tags.App type :" + assetType + " does not exist");
            }

            if ((this.isTenantModeStoreView && this.tenantDomain == null)
                    || (this.isTenantModeStoreView && isTenantDomainNotMatching(requestedTenantDomain))) {//Tenant based store anonymous mode
                int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(this.requestedTenant);
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantId);
            } else {
                userRegistry = registry;
            }
            Collection collection = userRegistry.executeQuery(tagsQueryPath, params);
            for (String fullTag : collection.getChildren()) {
                //remove hardcoded path value
                String tagName = fullTag.substring(fullTag.indexOf(";") + 1, fullTag.indexOf(":"));

                Set<WebApp> apisWithTag = getAppsWithTag(userRegistry, tagName, assetType, attributeMap);
                /* Add the APIs against the tag name */
                if (apisWithTag.size() != 0) {
                    if (tempTaggedAPIs.containsKey(tagName)) {
                        for (WebApp api : apisWithTag) {
                            tempTaggedAPIs.get(tagName).add(api);
                        }
                    } else {
                        tempTaggedAPIs.put(tagName, apisWithTag);
                    }
                }
            }

            if (tempTaggedAPIs != null) {
                Iterator<Map.Entry<String, Set<WebApp>>> entryIterator = tempTaggedAPIs.entrySet().iterator();
                while (entryIterator.hasNext()) {
                    Map.Entry<String, Set<WebApp>> entry = entryIterator.next();
                    tempTagSet.add(new Tag(entry.getKey(), entry.getValue().size()));
                }
            }
            synchronized (tagCacheMutex) {
                lastUpdatedTime = System.currentTimeMillis();
                this.taggedAPIs = tempTaggedAPIs;
                this.tagSet = tempTagSet;
            }

        } catch (RegistryException e) {
            try {
                //Before a tenant login to the store or publisher at least one time, 
                //a registry exception is thrown when the tenant store is accessed in anonymous mode.
                //This fix checks whether query resource available in the registry. If not
                // give a warn. 
                if (!userRegistry.resourceExists(tagsQueryPath)) {
                    log.warn("Failed to retrieve tags query resource at " + tagsQueryPath);
                    return tagSet;
                }
            } catch (RegistryException e1) {
                //ignore
            }
            handleException("Failed to get all the tags", e);
        } catch (UserStoreException e) {
            handleException("Failed to get all the tags", e);
        }
        return tagSet;
    }

    public Set<WebApp> getPublishedAPIsByProvider(String providerId, int limit) throws AppManagementException {
        SortedSet<WebApp> apiSortedSet = new TreeSet<WebApp>(new APINameComparator());
        SortedSet<WebApp> apiVersionsSortedSet = new TreeSet<WebApp>(new APIVersionComparator());
        try {
            Map<String, WebApp> latestPublishedAPIs = new HashMap<String, WebApp>();
            List<WebApp> multiVersionedAPIs = new ArrayList<WebApp>();
            Comparator<WebApp> versionComparator = new APIVersionComparator();
            Boolean displayMultipleVersions = isAllowDisplayMultipleVersions();
            Boolean displayAPIsWithMultipleStatus = isAllowDisplayAPIsWithMultipleStatus();
            String providerPath = AppMConstants.API_ROOT_LOCATION + RegistryConstants.PATH_SEPARATOR + providerId;
            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry,
                    AppMConstants.API_KEY);
            Association[] associations = registry.getAssociations(providerPath, AppMConstants.PROVIDER_ASSOCIATION);
            if (associations.length < limit || limit == -1) {
                limit = associations.length;
            }
            for (int i = 0; i < limit; i++) {
                Association association = associations[i];
                String apiPath = association.getDestinationPath();
                Resource resource = registry.get(apiPath);
                String apiArtifactId = resource.getUUID();
                if (apiArtifactId != null) {
                    GenericArtifact artifact = artifactManager.getGenericArtifact(apiArtifactId);
                    // check the WebApp status
                    String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                    WebApp api = null;
                    //Check the app-manager.xml config file entry <DisplayAllAPIs> value is false
                    if (!displayAPIsWithMultipleStatus) {
                        // then we are only interested in published APIs here...
                        if (status.equals(AppMConstants.PUBLISHED)) {
                            api = AppManagerUtil.getAPI(artifact);
                        }
                    } else { // else we are interested in both deprecated/published APIs here...
                        if (status.equals(AppMConstants.PUBLISHED) || status.equals(AppMConstants.DEPRECATED)) {
                            api = AppManagerUtil.getAPI(artifact);

                        }

                    }
                    if (api != null) {
                        String key;
                        //Check the configuration to allow showing multiple versions of an WebApp true/false
                        if (!displayMultipleVersions) { //If allow only showing the latest version of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName();
                            WebApp existingAPI = latestPublishedAPIs.get(key);
                            if (existingAPI != null) {
                                // If we have already seen an WebApp with the same name, make sure
                                // this one has a higher version number
                                if (versionComparator.compare(api, existingAPI) > 0) {
                                    latestPublishedAPIs.put(key, api);
                                }
                            } else {
                                // We haven't seen this WebApp before
                                latestPublishedAPIs.put(key, api);
                            }
                        } else { //If allow showing multiple versions of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName() + ":"
                                    + api.getId().getVersion();
                            multiVersionedAPIs.add(api);
                        }
                    }
                } else {
                    throw new GovernanceException("artifact id is null of " + apiPath);
                }
            }
            if (!displayMultipleVersions) {
                for (WebApp api : latestPublishedAPIs.values()) {
                    apiSortedSet.add(api);
                }
                return apiSortedSet;
            } else {
                for (WebApp api : multiVersionedAPIs) {
                    apiVersionsSortedSet.add(api);
                }
                return apiVersionsSortedSet;
            }

        } catch (RegistryException e) {
            handleException("Failed to get Published APIs for provider : " + providerId, e);
            return null;
        }

    }

    public Set<WebApp> getPublishedAPIsByProvider(String providerId, String loggedUsername, int limit)
            throws AppManagementException {
        SortedSet<WebApp> apiSortedSet = new TreeSet<WebApp>(new APINameComparator());
        SortedSet<WebApp> apiVersionsSortedSet = new TreeSet<WebApp>(new APIVersionComparator());
        try {
            Map<String, WebApp> latestPublishedAPIs = new HashMap<String, WebApp>();
            List<WebApp> multiVersionedAPIs = new ArrayList<WebApp>();
            Comparator<WebApp> versionComparator = new APIVersionComparator();
            Boolean allowMultipleVersions = isAllowDisplayMultipleVersions();
            Boolean showAllAPIs = isAllowDisplayAPIsWithMultipleStatus();

            String providerDomain = MultitenantUtils
                    .getTenantDomain(AppManagerUtil.replaceEmailDomainBack(providerId));
            int id = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                    .getTenantId(providerDomain);
            Registry registry = ServiceReferenceHolder.getInstance().getRegistryService()
                    .getGovernanceSystemRegistry(id);

            org.wso2.carbon.user.api.AuthorizationManager manager = ServiceReferenceHolder.getInstance()
                    .getRealmService().getTenantUserRealm(id).getAuthorizationManager();

            String providerPath = AppMConstants.API_ROOT_LOCATION + RegistryConstants.PATH_SEPARATOR + providerId;
            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry,
                    AppMConstants.API_KEY);
            Association[] associations = registry.getAssociations(providerPath, AppMConstants.PROVIDER_ASSOCIATION);
            int publishedAPICount = 0;

            for (Association association1 : associations) {

                if (publishedAPICount >= limit) {
                    break;
                }

                Association association = association1;
                String apiPath = association.getDestinationPath();

                Resource resource;
                String path = RegistryUtils.getAbsolutePath(RegistryContext.getBaseInstance(),
                        RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH + apiPath);
                boolean checkAuthorized = false;
                String userNameWithoutDomain = loggedUsername;

                String loggedDomainName = "";
                if (!"".equals(loggedUsername)
                        && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(super.tenantDomain)) {
                    String[] nameParts = loggedUsername.split("@");
                    loggedDomainName = nameParts[1];
                    userNameWithoutDomain = nameParts[0];
                }

                if (loggedUsername.equals("")) {
                    // Anonymous user is viewing.
                    checkAuthorized = manager.isRoleAuthorized(AppMConstants.ANONYMOUS_ROLE, path,
                            ActionConstants.GET);
                } else {
                    // Some user is logged in.
                    checkAuthorized = manager.isUserAuthorized(userNameWithoutDomain, path, ActionConstants.GET);
                }

                String apiArtifactId = null;
                if (checkAuthorized) {
                    resource = registry.get(apiPath);
                    apiArtifactId = resource.getUUID();
                }

                if (apiArtifactId != null) {
                    GenericArtifact artifact = artifactManager.getGenericArtifact(apiArtifactId);

                    // check the WebApp status
                    String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                    WebApp api = null;
                    //Check the app-manager.xml config file entry <DisplayAllAPIs> value is false
                    if (!showAllAPIs) {
                        // then we are only interested in published APIs here...
                        if (status.equals(AppMConstants.PUBLISHED)) {
                            api = AppManagerUtil.getAPI(artifact);
                            publishedAPICount++;
                        }
                    } else { // else we are interested in both deprecated/published APIs here...
                        if (status.equals(AppMConstants.PUBLISHED) || status.equals(AppMConstants.DEPRECATED)) {
                            api = AppManagerUtil.getAPI(artifact);
                            publishedAPICount++;

                        }

                    }
                    if (api != null) {
                        String key;
                        //Check the configuration to allow showing multiple versions of an WebApp true/false
                        if (!allowMultipleVersions) { //If allow only showing the latest version of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName();
                            WebApp existingAPI = latestPublishedAPIs.get(key);
                            if (existingAPI != null) {
                                // If we have already seen an WebApp with the same name, make sure
                                // this one has a higher version number
                                if (versionComparator.compare(api, existingAPI) > 0) {
                                    latestPublishedAPIs.put(key, api);
                                }
                            } else {
                                // We haven't seen this WebApp before
                                latestPublishedAPIs.put(key, api);
                            }
                        } else { //If allow showing multiple versions of an WebApp
                            key = api.getId().getProviderName() + ":" + api.getId().getApiName() + ":"
                                    + api.getId().getVersion();
                            multiVersionedAPIs.add(api);
                        }
                    }
                }
            }
            if (!allowMultipleVersions) {
                for (WebApp api : latestPublishedAPIs.values()) {
                    apiSortedSet.add(api);
                }
                return apiSortedSet;
            } else {
                for (WebApp api : multiVersionedAPIs) {
                    apiVersionsSortedSet.add(api);
                }
                return apiVersionsSortedSet;
            }

        } catch (RegistryException e) {
            handleException("Failed to get Published APIs for provider : " + providerId, e);
            return null;
        } catch (org.wso2.carbon.user.core.UserStoreException e) {
            handleException("Failed to get Published APIs for provider : " + providerId, e);
            return null;
        } catch (org.wso2.carbon.user.api.UserStoreException e) {
            handleException("Failed to get Published APIs for provider : " + providerId, e);
            return null;
        }

    }

    public Set<WebApp> searchAPI(String searchTerm, String searchType, String requestedTenantDomain)
            throws AppManagementException {
        Set<WebApp> apiSet = new HashSet<WebApp>();
        try {
            Registry userRegistry;
            boolean isTenantMode = (requestedTenantDomain != null);
            if ((isTenantMode && this.tenantDomain == null)
                    || (isTenantMode && isTenantDomainNotMatching(requestedTenantDomain))) {//Tenant store anonymous mode
                int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(requestedTenantDomain);
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantId);
            } else {
                userRegistry = this.registry;
            }
            apiSet.addAll(searchAPI(userRegistry, searchTerm, searchType));

        } catch (Exception e) {
            handleException("Failed to Search APIs", e);
        }
        return apiSet;
    }

    public Set<WebApp> searchAPI(Registry registry, String searchTerm, String searchType)
            throws AppManagementException {
        SortedSet<WebApp> apiSet = new TreeSet<WebApp>(new APINameComparator());
        String regex = "(?i)[\\w.|-]*" + searchTerm.trim() + "[\\w.|-]*";
        Pattern pattern;
        Matcher matcher;
        try {
            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry,
                    AppMConstants.API_KEY);
            if (artifactManager != null) {
                GenericArtifact[] genericArtifacts = artifactManager.getAllGenericArtifacts();
                if (genericArtifacts == null || genericArtifacts.length == 0) {
                    return apiSet;
                }
                pattern = Pattern.compile(regex);

                for (GenericArtifact artifact : genericArtifacts) {
                    String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                    if (searchType.equalsIgnoreCase("Provider")) {
                        String api = AppManagerUtil
                                .replaceEmailDomainBack(artifact.getAttribute(AppMConstants.API_OVERVIEW_PROVIDER));
                        matcher = pattern.matcher(api);
                    } else if (searchType.equalsIgnoreCase("Version")) {
                        String api = artifact.getAttribute(AppMConstants.API_OVERVIEW_VERSION);
                        matcher = pattern.matcher(api);
                    } else if (searchType.equalsIgnoreCase("Context")) {
                        String api = artifact.getAttribute(AppMConstants.API_OVERVIEW_CONTEXT);
                        matcher = pattern.matcher(api);
                    } else {
                        String apiName = artifact.getAttribute(AppMConstants.API_OVERVIEW_NAME);
                        matcher = pattern.matcher(apiName);
                    }
                    if (isAllowDisplayAPIsWithMultipleStatus()) {
                        if (matcher.find() && (status.equals(AppMConstants.PUBLISHED)
                                || status.equals(AppMConstants.DEPRECATED))) {
                            apiSet.add(AppManagerUtil.getAPI(artifact, registry));
                        }
                    } else {
                        if (matcher.find() && status.equals(AppMConstants.PUBLISHED)) {
                            apiSet.add(AppManagerUtil.getAPI(artifact, registry));
                        }
                    }

                }
            }
        } catch (RegistryException e) {
            handleException("Failed to search APIs with type", e);
        }
        return apiSet;
    }

    public Map<String, Object> searchPaginatedAPIs(String searchTerm, String searchType,
            String requestedTenantDomain, int start, int end) throws AppManagementException {
        Map<String, Object> result = new HashMap<String, Object>();
        try {
            Registry userRegistry;
            boolean isTenantMode = (requestedTenantDomain != null);
            if ((isTenantMode && this.tenantDomain == null)
                    || (isTenantMode && isTenantDomainNotMatching(requestedTenantDomain))) {//Tenant store anonymous mode
                int tenantId = ServiceReferenceHolder.getInstance().getRealmService().getTenantManager()
                        .getTenantId(requestedTenantDomain);
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantId);
            } else {
                userRegistry = this.registry;
            }
            PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(this.username);
            result = searchPaginatedAPIs(userRegistry, searchTerm, searchType, start, end);

        } catch (Exception e) {
            handleException("Failed to Search APIs", e);
        }
        return result;
    }

    public Map<String, Object> searchPaginatedAPIs(Registry registry, String searchTerm, String searchType,
            int start, int end) throws AppManagementException {
        SortedSet<WebApp> apiSet = new TreeSet<WebApp>(new APINameComparator());
        List<WebApp> apiList = new ArrayList<WebApp>();
        String regex = "(?i)[\\w.|-]*" + searchTerm.trim() + "[\\w.|-]*";
        Pattern pattern;
        Matcher matcher;
        Map<String, Object> result = new HashMap<String, Object>();
        try {

            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry,
                    AppMConstants.API_KEY);
            if (artifactManager != null) {
                GenericArtifact[] genericArtifacts = artifactManager.getAllGenericArtifacts();
                if (genericArtifacts == null || genericArtifacts.length == 0) {

                    result.put("apis", apiSet);
                    result.put("length", 0);
                    return result;
                }
                pattern = Pattern.compile(regex);

                for (GenericArtifact artifact : genericArtifacts) {
                    String status = artifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);

                    if (searchType.equalsIgnoreCase("Provider")) {
                        String api = AppManagerUtil
                                .replaceEmailDomainBack(artifact.getAttribute(AppMConstants.API_OVERVIEW_PROVIDER));
                        matcher = pattern.matcher(api);
                    } else if (searchType.equalsIgnoreCase("Version")) {
                        String api = artifact.getAttribute(AppMConstants.API_OVERVIEW_VERSION);
                        matcher = pattern.matcher(api);
                    } else if (searchType.equalsIgnoreCase("Context")) {
                        String api = artifact.getAttribute(AppMConstants.API_OVERVIEW_CONTEXT);
                        matcher = pattern.matcher(api);
                    } else {
                        String apiName = artifact.getAttribute(AppMConstants.API_OVERVIEW_NAME);
                        matcher = pattern.matcher(apiName);
                    }
                    if (isAllowDisplayAPIsWithMultipleStatus()) {
                        if (matcher.find() && (status.equals(AppMConstants.PUBLISHED)
                                || status.equals(AppMConstants.DEPRECATED))) {
                            apiList.add(AppManagerUtil.getAPI(artifact, registry));
                        }
                    } else {
                        if (matcher.find() && status.equals(AppMConstants.PUBLISHED)) {
                            apiList.add(AppManagerUtil.getAPI(artifact, registry));
                        }
                    }

                }
                if (apiList.size() < end) {
                    end = apiList.size();
                }
                for (int i = start; i < end; i++) {
                    apiSet.add(apiList.get(i));

                }
            }
        } catch (RegistryException e) {
            handleException("Failed to search APIs with type", e);
        }
        result.put("apis", apiSet);
        result.put("length", apiList.size());
        return result;
    }

    public Set<SubscribedAPI> getSubscribedAPIs(Subscriber subscriber) throws AppManagementException {
        Set<SubscribedAPI> originalSubscribedAPIs = null;
        Set<SubscribedAPI> subscribedAPIs = new HashSet<SubscribedAPI>();
        try {
            originalSubscribedAPIs = appMDAO.getSubscribedAPIs(subscriber);
            for (SubscribedAPI subscribedApi : originalSubscribedAPIs) {
                subscribedApi.getTier().setDisplayName(
                        AppManagerUtil.getTierDisplayName(tenantId, subscribedApi.getTier().getName()));
                subscribedAPIs.add(subscribedApi);
            }

        } catch (AppManagementException e) {
            handleException("Failed to get APIs of " + subscriber.getName(), e);
        }
        return subscribedAPIs;
    }

    public Set<SubscribedAPI> getSubscribedAPIs(Subscriber subscriber, String applicationName)
            throws AppManagementException {
        Set<SubscribedAPI> subscribedAPIs = null;
        try {
            subscribedAPIs = appMDAO.getSubscribedAPIs(subscriber, applicationName);
        } catch (AppManagementException e) {
            handleException(
                    "Failed to get APIs of " + subscriber.getName() + " under application " + applicationName, e);
        }
        return subscribedAPIs;
    }

    public boolean isSubscribed(APIIdentifier apiIdentifier, String userId) throws AppManagementException {
        boolean isSubscribed;
        try {
            isSubscribed = appMDAO.isSubscribed(apiIdentifier, userId);
        } catch (AppManagementException e) {
            String msg = "Failed to check if user(" + userId + ") has subscribed to " + apiIdentifier;
            log.error(msg, e);
            throw new AppManagementException(msg, e);
        }
        return isSubscribed;
    }

    public String addSubscription(APIIdentifier identifier, String subscriptionType, String userId,
            int applicationId, String trustedIdps) throws AppManagementException {

        WebApp api = getAPI(identifier);
        String subscribedTier = identifier.getTier();

        if (APIStatus.PUBLISHED.equals(api.getStatus())) {
            if (applicationId == -1) {
                applicationId = appMDAO.getDefaultApplicationForSubscriber(userId);
            }

            int subscriptionId = -1;
            boolean shouldUpdate = false;

            Subscription subscription = appMDAO.getSubscription(identifier, applicationId, subscriptionType);

            if (subscription != null) {
                subscriptionId = subscription.getSubscriptionId();
                shouldUpdate = true;
            }

            if (shouldUpdate) {
                if (Subscription.SUBSCRIPTION_TYPE_ENTERPRISE.equals(subscriptionType)) {
                    appMDAO.updateSubscription(subscriptionId, subscriptionType, trustedIdps,
                            subscription.getSubscriptionStatus());
                } else if (Subscription.SUBSCRIPTION_TYPE_INDIVIDUAL.equals(subscriptionType)) {
                    appMDAO.updateSubscription(subscriptionId, subscriptionType, trustedIdps,
                            AppMConstants.SubscriptionStatus.ON_HOLD);
                }
            } else {
                subscriptionId = appMDAO.addSubscription(identifier, subscriptionType, api.getContext(),
                        applicationId, AppMConstants.SubscriptionStatus.ON_HOLD, trustedIdps);
            }

            // Execute workflow.
            try {
                executeWorkflow(api, applicationId, userId, subscriptionId, subscribedTier);
            } catch (WorkflowException e) {
                //If the workflow execution fails, roll back transaction by removing the subscription entry.
                appMDAO.removeSubscriptionById(subscriptionId);
                log.error("Could not execute Workflow", e);
                throw new AppManagementException("Could not execute Workflow", e);
            }

            return appMDAO.getSubscriptionStatusById(subscriptionId);
        } else {
            throw new AppManagementException(
                    "Subscriptions not allowed on APIs in the state: " + api.getStatus().getStatus());
        }
    }

    @Override
    public Subscription getSubscription(APIIdentifier apiIdentifier, int applicationId, String subscriptionType)
            throws AppManagementException {
        return appMDAO.getSubscription(apiIdentifier, applicationId, subscriptionType);
    }

    private void executeWorkflow(WebApp webApp, int applicationId, String userId, int subscriptionId,
            String subscribedTier) throws WorkflowException {

        try {

            WorkflowExecutor addSubscriptionWFExecutor = WorkflowExecutorFactory.getInstance()
                    .getWorkflowExecutor(WorkflowConstants.WF_TYPE_AM_SUBSCRIPTION_CREATION);

            SubscriptionWorkflowDTO workflowDTO = new SubscriptionWorkflowDTO();
            workflowDTO.setStatus(WorkflowStatus.CREATED);
            workflowDTO.setCreatedTime(System.currentTimeMillis());
            workflowDTO.setTenantDomain(tenantDomain);
            workflowDTO.setTenantId(tenantId);
            workflowDTO.setExternalWorkflowReference(addSubscriptionWFExecutor.generateUUID());
            workflowDTO.setWorkflowReference(String.valueOf(subscriptionId));
            workflowDTO.setWorkflowType(WorkflowConstants.WF_TYPE_AM_SUBSCRIPTION_CREATION);
            workflowDTO.setCallbackUrl(addSubscriptionWFExecutor.getCallbackURL());
            workflowDTO.setApiName(webApp.getId().getApiName());
            workflowDTO.setApiContext(webApp.getContext());
            workflowDTO.setApiVersion(webApp.getId().getVersion());
            workflowDTO.setApiProvider(webApp.getId().getProviderName());
            workflowDTO.setTierName(subscribedTier);
            workflowDTO.setApplicationName(appMDAO.getApplicationNameFromId(applicationId));
            workflowDTO.setSubscriber(userId);

            addSubscriptionWFExecutor.execute(workflowDTO);

        } catch (Exception e) {
            throw new WorkflowException("Cannot execute workflow. ", e);
        }
    }

    //This method has been introduced for rest-api workflow execution
    private void executeWorkflow(WebApp webApp, String applicationName, String userId, int subscriptionId,
            String subscribedTier) throws AppManagementException {

        WorkflowExecutor addSubscriptionWFExecutor = null;
        try {
            addSubscriptionWFExecutor = WorkflowExecutorFactory.getInstance()
                    .getWorkflowExecutor(WorkflowConstants.WF_TYPE_AM_SUBSCRIPTION_CREATION);
            SubscriptionWorkflowDTO workflowDTO = new SubscriptionWorkflowDTO();
            workflowDTO.setStatus(WorkflowStatus.CREATED);
            workflowDTO.setCreatedTime(System.currentTimeMillis());
            workflowDTO.setTenantDomain(tenantDomain);
            workflowDTO.setTenantId(tenantId);
            workflowDTO.setExternalWorkflowReference(addSubscriptionWFExecutor.generateUUID());
            workflowDTO.setWorkflowReference(String.valueOf(subscriptionId));
            workflowDTO.setWorkflowType(WorkflowConstants.WF_TYPE_AM_SUBSCRIPTION_CREATION);
            workflowDTO.setCallbackUrl(addSubscriptionWFExecutor.getCallbackURL());
            workflowDTO.setApiName(webApp.getId().getApiName());
            workflowDTO.setApiContext(webApp.getContext());
            workflowDTO.setApiVersion(webApp.getId().getVersion());
            workflowDTO.setApiProvider(webApp.getId().getProviderName());
            workflowDTO.setTierName(subscribedTier);
            workflowDTO.setApplicationName(applicationName);
            workflowDTO.setSubscriber(userId);

            addSubscriptionWFExecutor.execute(workflowDTO);
        } catch (WorkflowException e) {
            handleException("Error occurred while executing Subscription workflow for webapp with name '"
                    + webApp.getId().getApiName() + "' with version '" + webApp.getId().getVersion());
        }
    }

    public void removeSubscription(APIIdentifier identifier, String userId, int applicationId)
            throws AppManagementException {
        appMDAO.removeSubscription(identifier, applicationId);
    }

    public void removeAPISubscription(APIIdentifier identifier, String userId, String applicationName)
            throws AppManagementException {
        appMDAO.removeAPISubscription(identifier, userId, applicationName);
        /*if (AppManagerUtil.isAPIGatewayKeyCacheEnabled()) {
        invalidateCachedKeys(applicationId, identifier);
        }*/
    }

    public void removeSubscriber(APIIdentifier identifier, String userId) throws AppManagementException {
        throw new UnsupportedOperationException("Unsubscribe operation is not yet implemented");
    }

    public void updateSubscriptions(APIIdentifier identifier, String userId, int applicationId)
            throws AppManagementException {
        WebApp api = getAPI(identifier);
        appMDAO.updateSubscriptions(identifier, api.getContext(), applicationId);
    }

    /**
     * Retrieve webapp from the UUID
     * @param uuid uuid of the application
     * @return WebApp
     * @throws AppManagementException
     */
    @Override
    public WebApp getWebApp(String uuid) throws AppManagementException {
        boolean isTenantFlowStarted = false;

        if (tenantDomain != null
                && !org.wso2.carbon.base.MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
            isTenantFlowStarted = true;
            PrivilegedCarbonContext.startTenantFlow();
            PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain, true);
        }
        GenericArtifact artifact = null;
        WebApp webApp = null;

        try {
            GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry,
                    AppMConstants.WEBAPP_ASSET_TYPE);
            artifact = artifactManager.getGenericArtifact(uuid);
            if (artifact == null) {
                handleResourceNotFoundException("Webapp does not exist with app id :" + uuid);
            }
            webApp = AppManagerUtil.getAPI(artifact, registry);

        } catch (GovernanceException e) {
            handleException("Error occurred while retrieving webapp registry artifact with uuid " + uuid);
        } finally {
            if (isTenantFlowStarted) {
                PrivilegedCarbonContext.endTenantFlow();
            }
        }
        return webApp;
    }

    /**
     * Add a new Application from the store.
     * @param application - {@link Application}
     * @param userId - {@link String} 
     * @return {@link String}
     */
    //ToDo: Refactor addApplication method return type to void
    public String addApplication(Application application, String userId) throws AppManagementException {

        appMDAO.addApplication(application, userId);
        return appMDAO.getApplicationStatus(application.getName(), userId);
    }

    public void updateApplication(Application application) throws AppManagementException {
        appMDAO.updateApplication(application);
    }

    public boolean isApplicationTokenExists(String accessToken) throws AppManagementException {
        return appMDAO.isAccessTokenExists(accessToken);
    }

    public Set<SubscribedAPI> getSubscribedIdentifiers(Subscriber subscriber, APIIdentifier identifier)
            throws AppManagementException {
        Set<SubscribedAPI> subscribedAPISet = new HashSet<SubscribedAPI>();
        Set<SubscribedAPI> subscribedAPIs = getSubscribedAPIs(subscriber);
        for (SubscribedAPI api : subscribedAPIs) {
            if (api.getApiId().equals(identifier)) {
                subscribedAPISet.add(api);
            }
        }
        return subscribedAPISet;
    }

    private boolean isAllowDisplayAPIsWithMultipleStatus() {
        AppManagerConfiguration config = ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService()
                .getAPIManagerConfiguration();
        String displayAllAPIs = config.getFirstProperty(AppMConstants.API_STORE_DISPLAY_ALL_APIS);
        if (displayAllAPIs == null) {
            log.warn("The configurations related to show deprecated Apps in AppStore "
                    + "are missing in app-manager.xml.");
            return false;
        }
        return Boolean.parseBoolean(displayAllAPIs);
    }

    private boolean isAllowDisplayMultipleVersions() {
        AppManagerConfiguration config = ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService()
                .getAPIManagerConfiguration();

        String displayMultiVersions = config.getFirstProperty(AppMConstants.API_STORE_DISPLAY_MULTIPLE_VERSIONS);
        if (displayMultiVersions == null) {
            log.warn("The configurations related to show multiple versions of WebApp in AppStore "
                    + "are missing in app-manager.xml.");
            return false;
        }
        return Boolean.parseBoolean(displayMultiVersions);
    }

    /**
     * Returns a list of tiers denied
     *
     * @return Set<Tier>
     */
    public Set<String> getDeniedTiers() throws AppManagementException {
        Set<String> deniedTiers = new HashSet<String>();
        String[] currentUserRoles = new String[0];
        try {
            if (tenantId != 0) {
                /* Get the roles of the Current User */
                currentUserRoles = ((UserRegistry) ((UserAwareAPIConsumer) this).registry).getUserRealm()
                        .getUserStoreManager().getRoleListOfUser(((UserRegistry) this.registry).getUserName());

                Set<TierPermissionDTO> tierPermissions = appMDAO.getTierPermissions(tenantId);
                for (TierPermissionDTO tierPermission : tierPermissions) {
                    String type = tierPermission.getPermissionType();

                    List<String> currentRolesList = new ArrayList<String>(Arrays.asList(currentUserRoles));
                    List<String> roles = new ArrayList<String>(Arrays.asList(tierPermission.getRoles()));
                    currentRolesList.retainAll(roles);

                    if (AppMConstants.TIER_PERMISSION_ALLOW.equals(type)) {
                        /* Current User is not allowed for this Tier*/
                        if (currentRolesList.size() == 0) {
                            deniedTiers.add(tierPermission.getTierName());
                        }
                    } else {
                        /* Current User is denied for this Tier*/
                        if (currentRolesList.size() > 0) {
                            deniedTiers.add(tierPermission.getTierName());
                        }
                    }
                }
            }
        } catch (org.wso2.carbon.user.api.UserStoreException e) {
            log.error("cannot retrieve user role list for tenant" + tenantDomain);
        }
        return deniedTiers;
    }

    /**
     * Check whether given Tier is denied for the user
     *
     * @param tierName
     * @return
     * @throws org.wso2.carbon.appmgt.api.AppManagementException if failed to get the tiers
     */
    public boolean isTierDeneid(String tierName) throws AppManagementException {
        String[] currentUserRoles = new String[0];
        try {
            if (tenantId != 0) {
                /* Get the roles of the Current User */
                currentUserRoles = ((UserRegistry) ((UserAwareAPIConsumer) this).registry).getUserRealm()
                        .getUserStoreManager().getRoleListOfUser(((UserRegistry) this.registry).getUserName());
                TierPermissionDTO tierPermission = appMDAO.getTierPermission(tierName, tenantId);
                if (tierPermission == null) {
                    return false;
                } else {
                    List<String> currentRolesList = new ArrayList<String>(Arrays.asList(currentUserRoles));
                    List<String> roles = new ArrayList<String>(Arrays.asList(tierPermission.getRoles()));
                    currentRolesList.retainAll(roles);
                    if (AppMConstants.TIER_PERMISSION_ALLOW.equals(tierPermission.getPermissionType())) {
                        if (currentRolesList.size() == 0) {
                            return true;
                        }
                    } else {
                        if (currentRolesList.size() > 0) {
                            return true;
                        }
                    }
                }
            }
        } catch (org.wso2.carbon.user.api.UserStoreException e) {
            log.error("cannot retrieve user role list for tenant" + tenantDomain);
        }
        return false;
    }

    /**
     * Returned an WebApp set from a set of registry paths
     *
     * @param registry Registry object from which the APIs retrieving,
     * @param limit    Specifies the number of APIs to add.
     * @param apiPaths Array of WebApp paths.
     * @return Set<WebApp> set of APIs
     * @throws RegistryException
     * @throws org.wso2.carbon.appmgt.api.AppManagementException
     */
    private Set<WebApp> getAPIs(Registry registry, int limit, String[] apiPaths)
            throws RegistryException, AppManagementException, org.wso2.carbon.user.api.UserStoreException {

        SortedSet<WebApp> apiSortedSet = new TreeSet<WebApp>(new APINameComparator());
        SortedSet<WebApp> apiVersionsSortedSet = new TreeSet<WebApp>(new APIVersionComparator());

        Boolean allowMultipleVersions = isAllowDisplayMultipleVersions();
        Boolean showAllAPIs = isAllowDisplayAPIsWithMultipleStatus();
        Map<String, WebApp> latestPublishedAPIs = new HashMap<String, WebApp>();
        List<WebApp> multiVersionedAPIs = new ArrayList<WebApp>();
        Comparator<WebApp> versionComparator = new APIVersionComparator();

        //Find UUID
        GenericArtifactManager artifactManager = AppManagerUtil.getArtifactManager(registry, AppMConstants.API_KEY);
        for (int a = 0; a < apiPaths.length; a++) {
            Resource resource = registry.get(apiPaths[a]);
            if (resource != null && artifactManager != null) {
                GenericArtifact genericArtifact = artifactManager.getGenericArtifact(resource.getUUID());
                WebApp api = null;
                String status = genericArtifact.getAttribute(AppMConstants.API_OVERVIEW_STATUS);
                //Check the app-manager.xml config file entry <DisplayAllAPIs> value is false
                if (!showAllAPIs) {
                    // then we are only interested in published APIs here...
                    if (status.equals(AppMConstants.PUBLISHED)) {
                        api = AppManagerUtil.getAPI(genericArtifact, registry);
                    }
                } else { // else we are interested in both deprecated/published APIs here...
                    if (status.equals(AppMConstants.PUBLISHED) || status.equals(AppMConstants.DEPRECATED)) {
                        api = AppManagerUtil.getAPI(genericArtifact, registry);

                    }

                }
                if (api != null) {
                    String key;
                    //Check the configuration to allow showing multiple versions of an WebApp true/false
                    if (!allowMultipleVersions) { //If allow only showing the latest version of an WebApp
                        key = api.getId().getProviderName() + ":" + api.getId().getApiName();
                        WebApp existingAPI = latestPublishedAPIs.get(key);
                        if (existingAPI != null) {
                            // If we have already seen an WebApp with the same name, make sure
                            // this one has a higher version number
                            if (versionComparator.compare(api, existingAPI) > 0) {
                                latestPublishedAPIs.put(key, api);
                            }
                        } else {
                            // We haven't seen this WebApp before
                            latestPublishedAPIs.put(key, api);
                        }
                    } else { //If allow showing multiple versions of an WebApp
                        key = api.getId().getProviderName() + ":" + api.getId().getApiName() + ":"
                                + api.getId().getVersion();
                        multiVersionedAPIs.add(api);
                    }
                }

            }
        }
        if (!allowMultipleVersions) {
            for (WebApp api : latestPublishedAPIs.values()) {
                apiSortedSet.add(api);
            }
            return apiSortedSet;
        } else {
            for (WebApp api : multiVersionedAPIs) {
                apiVersionsSortedSet.add(api);
            }
            return apiVersionsSortedSet;
        }

    }

    private boolean isAllowDisplayAllAPIs() {
        AppManagerConfiguration config = ServiceReferenceHolder.getInstance().getAPIManagerConfigurationService()
                .getAPIManagerConfiguration();
        String displayAllAPIs = config.getFirstProperty(AppMConstants.API_STORE_DISPLAY_ALL_APIS);
        if (displayAllAPIs == null) {
            log.warn("The configurations related to show deprecated Apps in AppStore "
                    + "are missing in app-manager.xml.");
            return false;
        }
        return Boolean.parseBoolean(displayAllAPIs);
    }

    private boolean isTenantDomainNotMatching(String tenantDomain) {
        if (this.tenantDomain != null) {
            return !(this.tenantDomain.equals(tenantDomain));
        }
        return true;
    }

    public Application[] getApplications(Subscriber subscriber) throws AppManagementException {
        return appMDAO.getApplications(subscriber);
    }

    @Override
    public void addToFavouriteApps(APIIdentifier identifier, String username, int tenantIdOfUser,
            int tenantIdOfStore) throws AppManagementException {
        appMDAO.addToFavouriteApps(identifier, username, tenantIdOfUser, tenantIdOfStore);
    }

    @Override
    public void removeFromFavouriteApps(APIIdentifier identifier, String username, int tenantIdOfUser,
            int tenantIdOfStore) throws AppManagementException {
        appMDAO.removeFromFavouriteApps(identifier, username, tenantIdOfUser, tenantIdOfStore);
    }

    @Override
    public boolean isFavouriteApp(APIIdentifier identifier, String username, int tenantIdOfUser,
            int tenantIdOfStore) throws AppManagementException {
        return appMDAO.isFavouriteApp(identifier, username, tenantIdOfUser, tenantIdOfStore);
    }

    @Override
    public List<APIIdentifier> getFavouriteApps(String username, int tenantIdOfUser, int tenantIdOfStore,
            WebAppSortOption sortOption) throws AppManagementException {
        return appMDAO.getFavouriteApps(username, tenantIdOfUser, tenantIdOfStore, sortOption);
    }

    @Override
    public List<APIIdentifier> searchFavouriteApps(String username, int tenantIdOfUser, int tenantIdOfStore,
            WebAppSearchOption searchOption, String searchValue) throws AppManagementException {
        return appMDAO.searchFavouriteApps(username, tenantIdOfUser, tenantIdOfStore, searchOption, searchValue);
    }

    @Override
    public List<APIIdentifier> getUserAccessibleApps(String username, int tenantIdOfUser, int tenantIdOfStore,
            WebAppSortOption sortOption, boolean treatAsSite) throws AppManagementException {
        return appMDAO.getUserAccessibleApps(username, tenantIdOfUser, tenantIdOfStore, sortOption, treatAsSite);
    }

    @Override
    public List<APIIdentifier> searchUserAccessibleApps(String username, int tenantIdOfUser, int tenantIdOfStore,
            boolean treatAsSite, WebAppSearchOption searchOption, String searchValue)
            throws AppManagementException {
        Registry userRegistry = null;
        try {
            if (tenantIdOfStore != tenantIdOfUser) {
                // Get registry for anonymous users when searching is going in tenant.
                userRegistry = ServiceReferenceHolder.getInstance().getRegistryService()
                        .getGovernanceUserRegistry(CarbonConstants.REGISTRY_ANONNYMOUS_USERNAME, tenantIdOfStore);
            } else {
                userRegistry = registry;
            }
        } catch (RegistryException e) {
            handleException("Error occurred while obtaining apps from the registry.", e);
        }

        return appMDAO.searchUserAccessibleApps(username, tenantIdOfUser, tenantIdOfStore, treatAsSite,
                searchOption, searchValue, userRegistry);
    }

    @Override
    public void setFavouritePage(String username, int tenantIdOfUser, int tenantIdOfStore)
            throws AppManagementException {
        appMDAO.addToStoreFavouritePage(username, tenantIdOfUser, tenantIdOfStore);
    }

    @Override
    public void removeFavouritePage(String username, int tenantIdOfUser, int tenantIdOfStore)
            throws AppManagementException {
        appMDAO.removeFromStoreFavouritePage(username, tenantIdOfUser, tenantIdOfStore);
    }

    @Override
    public boolean hasFavouritePage(String username, int tenantIdOfUser, int tenantIdOfStore)
            throws AppManagementException {
        return appMDAO.hasFavouritePage(username, tenantIdOfUser, tenantIdOfStore);
    }

    @Override
    public boolean isSubscribedToMobileApp(String userId, String appId) throws AppManagementException {
        String path = "users/" + userId + "/subscriptions/mobileapp/" + appId;
        boolean isSubscribed = false;
        try {
            if (registry.resourceExists(path)) {
                isSubscribed = true;
            }
        } catch (org.wso2.carbon.registry.api.RegistryException e) {
            handleException("Error while checking subscription in registry for mobileapp with id : " + appId, e);
        }
        return isSubscribed;
    }

    public Map<String, Set<WebApp>> getTaggedAPIs() {
        return taggedAPIs;
    }

    @Override
    public void addSubscription(String subscriberName, WebApp webApp, String applicationName)
            throws AppManagementException {
        AppRepository appRepository = new DefaultAppRepository(null);
        webApp.getId().setTier(AppMConstants.UNLIMITED_TIER);
        int subscriptionId = appRepository.addSubscription(subscriberName, webApp, applicationName);
        executeWorkflow(webApp, applicationName, subscriberName, subscriptionId, webApp.getId().getTier());
    }
}