// 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 com.cloud.user;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.inject.Inject;

import com.cloud.api.query.dao.NetworkOfferingJoinDao;
import com.cloud.api.query.dao.VpcOfferingJoinDao;
import com.cloud.api.query.vo.NetworkOfferingJoinVO;
import com.cloud.api.query.vo.VpcOfferingJoinVO;
import com.cloud.configuration.Resource;
import com.cloud.domain.dao.DomainDetailsDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpc.dao.VpcOfferingDao;
import com.cloud.network.vpc.dao.VpcOfferingDetailsDao;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
import com.cloud.exception.ResourceAllocationException;
import org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDao;
import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.domain.ListDomainChildrenCmd;
import org.apache.cloudstack.api.command.admin.domain.ListDomainsCmd;
import org.apache.cloudstack.api.command.admin.domain.MoveDomainCmd;
import org.apache.cloudstack.api.command.admin.domain.UpdateDomainCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.region.RegionManager;
import org.apache.cloudstack.resourcedetail.dao.DiskOfferingDetailsDao;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.BooleanUtils;
import org.springframework.stereotype.Component;

import com.cloud.api.query.dao.DiskOfferingJoinDao;
import com.cloud.api.query.dao.ServiceOfferingJoinDao;
import com.cloud.api.query.vo.DiskOfferingJoinVO;
import com.cloud.api.query.vo.ServiceOfferingJoinVO;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource.ResourceOwnerType;
import com.cloud.configuration.ResourceLimit;
import com.cloud.configuration.dao.ResourceCountDao;
import com.cloud.configuration.dao.ResourceLimitDao;
import com.cloud.dc.DedicatedResourceVO;
import com.cloud.dc.dao.DedicatedResourceDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.dao.NetworkDomainDao;
import com.cloud.projects.ProjectManager;
import com.cloud.projects.ProjectVO;
import com.cloud.projects.dao.ProjectDao;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.service.dao.ServiceOfferingDetailsDao;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.db.TransactionCallback;
import com.cloud.utils.db.TransactionCallbackNoReturn;
import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.ReservationContextImpl;
import com.cloud.vm.dao.VMInstanceDao;

import org.apache.commons.lang3.StringUtils;

@Component
public class DomainManagerImpl extends ManagerBase implements DomainManager, DomainService {

    @Inject
    private DomainDao _domainDao;
    @Inject
    private AccountManager _accountMgr;
    @Inject
    private ResourceCountDao _resourceCountDao;
    @Inject
    private AccountDao _accountDao;
    @Inject
    private DiskOfferingJoinDao diskOfferingJoinDao;
    @Inject
    private DiskOfferingDao diskOfferingDao;
    @Inject
    private DiskOfferingDetailsDao diskOfferingDetailsDao;
    @Inject
    private NetworkOfferingDao networkOfferingDao;
    @Inject
    private NetworkOfferingJoinDao networkOfferingJoinDao;
    @Inject
    private NetworkOfferingDetailsDao networkOfferingDetailsDao;
    @Inject
    private ServiceOfferingJoinDao serviceOfferingJoinDao;
    @Inject
    private ServiceOfferingDao serviceOfferingDao;
    @Inject
    private ServiceOfferingDetailsDao serviceOfferingDetailsDao;
    @Inject
    private VpcOfferingDao vpcOfferingDao;
    @Inject
    private VpcOfferingJoinDao vpcOfferingJoinDao;
    @Inject
    private VpcOfferingDetailsDao vpcOfferingDetailsDao;
    @Inject
    private ProjectDao _projectDao;
    @Inject
    private VMInstanceDao vmInstanceDao;
    @Inject
    private NetworkDao networkDao;
    @Inject
    private VolumeDao volumeDao;
    @Inject
    private VpcDao vpcDao;
    @Inject
    private ProjectManager _projectMgr;
    @Inject
    private RegionManager _regionMgr;
    @Inject
    private ResourceLimitDao _resourceLimitDao;
    @Inject
    private DedicatedResourceDao _dedicatedDao;
    @Inject
    private NetworkOrchestrationService _networkMgr;
    @Inject
    private NetworkDomainDao _networkDomainDao;
    @Inject
    private ConfigurationManager _configMgr;
    @Inject
    private DomainDetailsDao _domainDetailsDao;
    @Inject
    private AnnotationDao annotationDao;
    @Inject
    private ResourceLimitService resourceLimitService;
    @Inject
    private AffinityGroupDomainMapDao affinityGroupDomainMapDao;
    @Inject
    private RoutedIpv4Manager routedIpv4Manager;

    @Inject
    MessageBus _messageBus;

    protected GlobalLock getGlobalLock(String name) {
        return GlobalLock.getInternLock(name);
    }

    protected Account getCaller() {
        return CallContext.current().getCallingAccount();
    }

    @Override
    public Domain getDomain(long domainId) {
        return _domainDao.findById(domainId);
    }

    @Override
    public Domain getDomain(String domainUuid) {
        return _domainDao.findByUuid(domainUuid);
    }

    @Override
    public Domain getDomainByName(String name, long parentId) {
        SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        Domain domain = _domainDao.findOneBy(sc);
        return domain;
    }

    @Override
    public Set<Long> getDomainChildrenIds(String parentDomainPath) {
        Set<Long> childDomains = new HashSet<Long>();
        SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
        sc.addAnd("path", SearchCriteria.Op.LIKE, parentDomainPath + "%");

        List<DomainVO> domains = _domainDao.search(sc, null);

        for (DomainVO domain : domains) {
            childDomains.add(domain.getId());
        }

        return childDomains;
    }

    @Override
    public boolean isChildDomain(Long parentId, Long childId) {
        return _domainDao.isChildDomain(parentId, childId);
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_DOMAIN_CREATE, eventDescription = "creating Domain")
    public Domain createDomain(String name, Long parentId, String networkDomain, String domainUUID) {
        Account caller = getCaller();

        if (parentId == null) {
            parentId = Long.valueOf(Domain.ROOT_DOMAIN);
        }

        DomainVO parentDomain = _domainDao.findById(parentId);
        if (parentDomain == null) {
            throw new InvalidParameterValueException("Unable to create domain " + name + ", parent domain " + parentId + " not found.");
        }

        if (parentDomain.getState().equals(Domain.State.Inactive)) {
            throw new CloudRuntimeException("The domain cannot be created as the parent domain " + parentDomain.getName() + " is being deleted");
        }

        _accountMgr.checkAccess(caller, parentDomain);

        return createDomain(name, parentId, caller.getId(), networkDomain, domainUUID);

    }

    @Override
    @DB
    public Domain createDomain(final String name, final Long parentId, final Long ownerId, final String networkDomain, String domainUuid) {
        validateDomainNameAndNetworkDomain(name, parentId, networkDomain);

        DomainVO domainVO = createDomainVo(name, parentId, ownerId, networkDomain, domainUuid);

        DomainVO domain = Transaction.execute(new TransactionCallback<DomainVO>() {
            @Override
            public DomainVO doInTransaction(TransactionStatus status) {
                DomainVO domain = _domainDao.create(domainVO);
                _resourceCountDao.createResourceCounts(domain.getId(), ResourceLimit.ResourceOwnerType.Domain);

                CallContext.current().putContextParameter(Domain.class, domain.getUuid());
                return domain;
            }
        });
        if (domain != null) {
            _messageBus.publish(_name, MESSAGE_ADD_DOMAIN_EVENT, PublishScope.LOCAL, domain.getId());
            _messageBus.publish(_name, MESSAGE_CREATE_TUNGSTEN_DOMAIN_EVENT, PublishScope.LOCAL, domain);
        }
        return domain;
    }

    protected DomainVO createDomainVo(String name, Long parentId, Long ownerId, String networkDomain, String domainUuid) {
        if (StringUtils.isBlank(domainUuid)) {
            domainUuid = UUID.randomUUID().toString();
            logger.info(String.format("Domain UUID [%s] generated for domain name [%s].", domainUuid, name));
        }

        DomainVO domainVO = new DomainVO(name, ownerId, parentId, networkDomain, domainUuid);
        return domainVO;
    }

    protected void validateDomainNameAndNetworkDomain(String name, Long parentId, String networkDomain) {
        validateNetworkDomain(networkDomain);
        validateUniqueDomainName(name, parentId);
    }

    protected void validateUniqueDomainName(String name, Long parentId) {
        SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
        sc.addAnd("name", SearchCriteria.Op.EQ, name);
        sc.addAnd("parent", SearchCriteria.Op.EQ, parentId);
        List<DomainVO> domains = _domainDao.search(sc, null);

        if (!domains.isEmpty()) {
            throw new InvalidParameterValueException(String.format("Domain with name [%s] already exists for the parent with ID [%s].", name, parentId));
        }
    }

    protected void validateNetworkDomain(String networkDomain) {
        if (networkDomain != null && !NetUtils.verifyDomainName(networkDomain)) {
            throw new InvalidParameterValueException(
                    "Invalid network domain. Total length should not exceed 190 chars. Each domain label must be between 1 and 63 characters long." +
                            " It can contain ASCII letters 'a' through 'z', the digits '0' through '9', and the hyphen ('-'); it cannot start or end with \"-\"."
            );
        }
    }

    @Override
    public DomainVO findDomainByPath(String domainPath) {
        return _domainDao.findDomainByPath(domainPath);
    }

    @Override
    public Domain findDomainByIdOrPath(final Long id, final String domainPath) {
        Long domainId = id;
        if (domainId == null || domainId < 1L) {
            if (StringUtils.isBlank(domainPath)) {
                domainId = Domain.ROOT_DOMAIN;
            } else {
                final Domain domainVO = findDomainByPath(domainPath.trim());
                if (domainVO != null) {
                    return domainVO;
                }
            }
        }
        if (domainId != null && domainId > 0L) {
            return _domainDao.findById(domainId);
        }
        return null;
    }

    @Override
    public Set<Long> getDomainParentIds(long domainId) {
        return _domainDao.getDomainParentIds(domainId);
    }

    @Override
    public boolean removeDomain(long domainId) {
        return _domainDao.remove(domainId);
    }

    @Override
    public List<? extends Domain> findInactiveDomains() {
        return _domainDao.findInactiveDomains();
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_DOMAIN_DELETE, eventDescription = "deleting Domain", async = true)
    public boolean deleteDomain(long domainId, Boolean cleanup) {
        Account caller = getCaller();

        DomainVO domain = _domainDao.findById(domainId);

        if (domain == null) {
            throw new InvalidParameterValueException("Failed to delete domain " + domainId + ", domain not found");
        } else if (domainId == Domain.ROOT_DOMAIN) {
            throw new PermissionDeniedException("Can't delete ROOT domain");
        }

        _accountMgr.checkAccess(caller, domain);

        return deleteDomain(domain, cleanup);
    }

    @Override
    public boolean deleteDomain(DomainVO domain, Boolean cleanup) {
        GlobalLock lock = getGlobalLock();
        if (lock == null) return false;

        try {
            // mark domain as inactive
            logger.debug("Marking domain {} as {} before actually deleting it", domain, Domain.State.Inactive);
            domain.setState(Domain.State.Inactive);
            _domainDao.update(domain.getId(), domain);

            return cleanDomain(domain, cleanup);
        }
        finally {
            lock.unlock();
        }
    }

    private GlobalLock getGlobalLock() {
        GlobalLock lock = getGlobalLock("DomainCleanup");
        if (lock == null) {
            logger.debug("Couldn't get the global lock");
            return null;
        }

        if (!lock.lock(30)) {
            logger.debug("Couldn't lock the db");
            return null;
        }
        return lock;
    }

    private boolean cleanDomain(DomainVO domain, Boolean cleanup) {
        try {
            long ownerId = domain.getAccountId();
            if (BooleanUtils.toBoolean(cleanup)) {
                tryCleanupDomain(domain, ownerId);
            } else {
                removeDomainWithNoAccountsForCleanupNetworksOrDedicatedResources(domain);
            }

            // remove dedicated IPv4 subnets
            routedIpv4Manager.removeIpv4SubnetsForZoneByDomainId(domain.getId());

            // remove dedicated BGP peers
            routedIpv4Manager.removeBgpPeersByDomainId(domain.getId());

            if (!_configMgr.releaseDomainSpecificVirtualRanges(domain)) {
                CloudRuntimeException e = new CloudRuntimeException("Can't delete the domain yet because failed to release domain specific virtual ip ranges");
                e.addProxyObject(domain.getUuid(), "domainId");
                throw e;
            } else {
                logger.debug("Domain specific Virtual IP ranges  are successfully released as a part of domain {} cleanup.", domain);
            }

            cleanupDomainDetails(domain.getId());
            cleanupDomainOfferings(domain.getId());
            annotationDao.removeByEntityType(AnnotationService.EntityType.DOMAIN.name(), domain.getUuid());
            CallContext.current().putContextParameter(Domain.class, domain.getUuid());
            return true;
        } catch (Exception ex) {
            logger.error("Exception deleting domain {}", domain, ex);
            if (ex instanceof CloudRuntimeException) {
                rollbackDomainState(domain);
                throw (CloudRuntimeException)ex;
            }
            else
                return false;
        }
    }

    /**
     * Roll back domain state to Active
     * @param domain domain
     */
    protected void rollbackDomainState(DomainVO domain) {
        logger.debug("Changing domain {} state back to {} because it can't be removed due to resources referencing to it", domain, Domain.State.Active);
        domain.setState(Domain.State.Active);
        _domainDao.update(domain.getId(), domain);
    }

    /**
     * Try cleaning up domain. If it couldn't throws CloudRuntimeException
     * @param domain domain
     * @param ownerId owner id
     * @throws ConcurrentOperationException
     * @throws ResourceUnavailableException
     * @throws CloudRuntimeException when cleanupDomain
     */
    protected void tryCleanupDomain(DomainVO domain, long ownerId) throws ConcurrentOperationException, ResourceUnavailableException, CloudRuntimeException {
        if (!cleanupDomain(domain.getId(), ownerId)) {
            CloudRuntimeException e =
                new CloudRuntimeException(String.format("Failed to clean up domain resources and sub domains, delete failed on domain %s", domain));
            e.addProxyObject(domain.getUuid(), "domainId");
            throw e;
        }
    }

    /**
     * First check domain resources before removing domain. There are 2 cases:
     * <ol>
     * <li>Domain doesn't have accounts for cleanup, non-removed networks, or dedicated resources</li>
     * <ul><li>Delete domain</li></ul>
     * <li>Domain has one of the following: accounts set for cleanup, non-removed networks, dedicated resources</li>
     * <ul><li>Dont' delete domain</li><li>Fail operation</li></ul>
     * </ol>
     * @param domain domain to remove
     * @throws CloudRuntimeException when case 2 or when domain cannot be deleted on case 1
     */
    protected void removeDomainWithNoAccountsForCleanupNetworksOrDedicatedResources(DomainVO domain) {
        boolean hasDedicatedResources = false;
        List<Long> networkIds = _networkDomainDao.listNetworkIdsByDomain(domain.getId());
        List<AccountVO> accountsForCleanup = _accountDao.findCleanupsForRemovedAccounts(domain.getId());
        List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByDomainId(domain.getId());
        if (CollectionUtils.isNotEmpty(dedicatedResources)) {
            logger.error("There are dedicated resources for the domain {}", domain);
            hasDedicatedResources = true;
        }
        if (accountsForCleanup.isEmpty() && networkIds.isEmpty() && !hasDedicatedResources) {
            publishRemoveEventsAndRemoveDomain(domain);
        } else {
            failRemoveOperation(domain, accountsForCleanup, networkIds, hasDedicatedResources);
        }
    }

    /**
     * Fail domain remove operation including proper message
     * @param domain domain
     * @param accountsForCleanup domain accounts for cleanup
     * @param networkIds domain network ids
     * @param hasDedicatedResources indicates if domain has dedicated resources
     * @throws CloudRuntimeException including descriptive message indicating the reason for failure
     */
    protected void failRemoveOperation(DomainVO domain, List<AccountVO> accountsForCleanup, List<Long> networkIds, boolean hasDedicatedResources) {
        String msg = null;
        if (!accountsForCleanup.isEmpty()) {
            msg = accountsForCleanup.size() + " accounts to cleanup";
        } else if (!networkIds.isEmpty()) {
            msg = networkIds.size() + " non-removed networks";
        } else if (hasDedicatedResources) {
            msg = "dedicated resources.";
        }

        CloudRuntimeException e = new CloudRuntimeException("Can't delete the domain yet because it has " + msg);
        e.addProxyObject(domain.getUuid(), "domainId");
        throw e;
    }

    /**
     * Publish pre-remove and remove domain events and remove domain
     * @param domain domain to remove
     * @throws CloudRuntimeException when domain cannot be removed
     */
    protected void publishRemoveEventsAndRemoveDomain(DomainVO domain) {
        _messageBus.publish(_name, MESSAGE_PRE_REMOVE_DOMAIN_EVENT, PublishScope.LOCAL, domain);
        if (!_domainDao.remove(domain.getId())) {
            CloudRuntimeException e =
                new CloudRuntimeException(String.format("Delete failed on domain %s; Please make sure all users and sub domains have been removed from the domain before deleting", domain));
            e.addProxyObject(domain.getUuid(), "domainId");
            throw e;
        }
        _messageBus.publish(_name, MESSAGE_REMOVE_DOMAIN_EVENT, PublishScope.LOCAL, domain);
    }

    protected void cleanupDomainDetails(Long domainId) {
        _domainDetailsDao.deleteDetails(domainId);
    }

    protected void cleanupDomainOfferings(Long domainId) {
        if (domainId == null) {
            return;
        }

        String domainIdString = String.valueOf(domainId);

        removeDiskOfferings(domainId, domainIdString);

        removeServiceOfferings(domainId, domainIdString);

        removeNetworkOfferings(domainId, domainIdString);

        removeVpcOfferings(domainId, domainIdString);
    }

    private void removeVpcOfferings(Long domainId, String domainIdString) {
        List<Long> vpcOfferingsDetailsToRemove = new ArrayList<>();
        List<VpcOfferingJoinVO> vpcOfferingsForThisDomain = vpcOfferingJoinDao.findByDomainId(domainId);
        for (VpcOfferingJoinVO vpcOffering : vpcOfferingsForThisDomain) {
            int vpcCount = vpcDao.getVpcCountByOfferingId(vpcOffering.getId());
            if (vpcCount == 0) {
                vpcOfferingDao.remove(vpcOffering.getId());
            } else {
                vpcOfferingsDetailsToRemove.add(vpcOffering.getId());
            }
        }
        for (final Long vpcOfferingId : vpcOfferingsDetailsToRemove) {
            vpcOfferingDetailsDao.removeDetail(vpcOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
        }
    }

    private void removeNetworkOfferings(Long domainId, String domainIdString) {
        List<Long> networkOfferingsDetailsToRemove = new ArrayList<>();
        List<NetworkOfferingJoinVO> networkOfferingsForThisDomain = networkOfferingJoinDao.findByDomainId(domainId, false);
        for (NetworkOfferingJoinVO networkOffering : networkOfferingsForThisDomain) {
            int networkCount = networkDao.getNetworkCountByNetworkOffId(networkOffering.getId());
            if (networkCount == 0) {
                networkOfferingDao.remove(networkOffering.getId());
            } else {
                networkOfferingsDetailsToRemove.add(networkOffering.getId());
            }
        }
        for (final Long networkOfferingId : networkOfferingsDetailsToRemove) {
            networkOfferingDetailsDao.removeDetail(networkOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
        }
    }

    private void removeServiceOfferings(Long domainId, String domainIdString) {
        List<Long> serviceOfferingsDetailsToRemove = new ArrayList<>();
        List<ServiceOfferingJoinVO> serviceOfferingsForThisDomain = serviceOfferingJoinDao.findByDomainId(domainId);
        for (ServiceOfferingJoinVO serviceOffering : serviceOfferingsForThisDomain) {
            int vmCount = vmInstanceDao.getVmCountByOfferingId(serviceOffering.getId());
            if (vmCount == 0) {
                serviceOfferingDao.remove(serviceOffering.getId());
            } else {
                serviceOfferingsDetailsToRemove.add(serviceOffering.getId());
            }
        }
        for (final Long serviceOfferingId : serviceOfferingsDetailsToRemove) {
            serviceOfferingDetailsDao.removeDetail(serviceOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
        }
    }

    private void removeDiskOfferings(Long domainId, String domainIdString) {
        List<Long> diskOfferingsDetailsToRemove = new ArrayList<>();
        List<DiskOfferingJoinVO> diskOfferingsForThisDomain = diskOfferingJoinDao.findByDomainId(domainId);
        for (DiskOfferingJoinVO diskOffering : diskOfferingsForThisDomain) {
            int volumeCount = volumeDao.getVolumeCountByOfferingId(diskOffering.getId());
            if (volumeCount == 0) {
                diskOfferingDao.remove(diskOffering.getId());
            } else {
                diskOfferingsDetailsToRemove.add(diskOffering.getId());
            }
        }
        // Remove domain IDs for offerings which may be multi-domain
        for (final Long diskOfferingId : diskOfferingsDetailsToRemove) {
            diskOfferingDetailsDao.removeDetail(diskOfferingId, ApiConstants.DOMAIN_ID, domainIdString);
        }
    }

    protected boolean cleanupDomain(Long domainId, Long ownerId) throws ConcurrentOperationException, ResourceUnavailableException {
        boolean success = true;
        DomainVO domainHandle = _domainDao.findById(domainId);
        logger.debug("Cleaning up domain {}", domainHandle);
        {
            domainHandle.setState(Domain.State.Inactive);
            _domainDao.update(domainId, domainHandle);

            SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
            List<DomainVO> domains = _domainDao.search(sc, null);

            SearchCriteria<DomainVO> sc1 = _domainDao.createSearchCriteria();
            sc1.addAnd("path", SearchCriteria.Op.LIKE, "%" + "replace(" + domainHandle.getPath() + ", '%', '[%]')" + "%");
            List<DomainVO> domainsToBeInactivated = _domainDao.search(sc1, null);

            // update all subdomains to inactive so no accounts/users can be created
            for (DomainVO domain : domainsToBeInactivated) {
                domain.setState(Domain.State.Inactive);
                _domainDao.update(domain.getId(), domain);
            }

            // cleanup sub-domains first
            for (DomainVO domain : domains) {
                success = (success && cleanupDomain(domain.getId(), domain.getAccountId()));
                if (!success) {
                    logger.warn("Failed to cleanup domain {}", domain);
                }
            }
        }

        // delete users which will also delete accounts and release resources for those accounts
        SearchCriteria<AccountVO> sc = _accountDao.createSearchCriteria();
        sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId);
        List<AccountVO> accounts = _accountDao.search(sc, null);
        for (AccountVO account : accounts) {
            if (account.getType() != Account.Type.PROJECT) {
                logger.debug("Deleting account {} as a part of domain {} cleanup", account, domainHandle);
                boolean deleteAccount = _accountMgr.deleteAccount(account, CallContext.current().getCallingUserId(), getCaller());
                if (!deleteAccount) {
                    logger.warn("Failed to cleanup account {} as a part of domain cleanup", account);
                }
                success = (success && deleteAccount);
            } else {
                ProjectVO project = _projectDao.findByProjectAccountId(account.getId());
                logger.debug("Deleting project {} as a part of domain {} cleanup", project, domainHandle);
                boolean deleteProject = _projectMgr.deleteProject(getCaller(), CallContext.current().getCallingUserId(), project);
                if (!deleteProject) {
                    logger.warn("Failed to cleanup project " + project + " as a part of domain cleanup");
                }
                success = (success && deleteProject);
            }
        }

        //delete the domain shared networks
        boolean networksDeleted = true;
        logger.debug("Deleting networks for domain {}", domainHandle);
        List<Long> networkIds = _networkDomainDao.listNetworkIdsByDomain(domainId);
        CallContext ctx = CallContext.current();
        ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(ctx.getCallingUserId()), ctx.getCallingAccount());
        for (Long networkId : networkIds) {
            logger.debug("Deleting network id={} as a part of domain {} cleanup", networkId, domainHandle);
            if (!_networkMgr.destroyNetwork(networkId, context, false)) {
                logger.warn("Unable to destroy network id={} as a part of domain {} cleanup.", networkId, domainHandle);
                networksDeleted = false;
            } else {
                logger.debug("Network {} successfully deleted as a part of domain {} cleanup.", networkId, domainHandle);
            }
        }

        //don't proceed if networks failed to cleanup. The cleanup will be performed for inactive domain once again
        if (!networksDeleted) {
            logger.debug("Failed to delete the shared networks as a part of domain {} cleanup", domainHandle);
            return false;
        }

        // don't remove the domain if there are accounts required cleanup
        boolean deleteDomainSuccess = true;
        List<AccountVO> accountsForCleanup = _accountDao.findCleanupsForRemovedAccounts(domainId);
        if (accountsForCleanup.isEmpty()) {
            //release dedication if any, before deleting the domain
            List<DedicatedResourceVO> dedicatedResources = _dedicatedDao.listByDomainId(domainId);
            if (dedicatedResources != null && !dedicatedResources.isEmpty()) {
                logger.debug("Releasing dedicated resources for domain {}", domainHandle);
                for (DedicatedResourceVO dr : dedicatedResources) {
                    if (!_dedicatedDao.remove(dr.getId())) {
                        logger.warn("Fail to release dedicated resources for domain {}", domainHandle);
                        return false;
                    }
                }
            }
            //delete domain
            _messageBus.publish(_name, MESSAGE_PRE_REMOVE_DOMAIN_EVENT, PublishScope.LOCAL, domainHandle);
            deleteDomainSuccess = _domainDao.remove(domainId);
            _messageBus.publish(_name, MESSAGE_REMOVE_DOMAIN_EVENT, PublishScope.LOCAL, domainHandle);

            // Delete resource count and resource limits entries set for this domain (if there are any).
            _resourceCountDao.removeEntriesByOwner(domainId, ResourceOwnerType.Domain);
            _resourceLimitDao.removeEntriesByOwner(domainId, ResourceOwnerType.Domain);
        } else {
            logger.debug("Can't delete the domain yet because it has " + accountsForCleanup.size() + "accounts that need a cleanup");
            return false;
        }

        return success && deleteDomainSuccess;
    }

    @Override
    public Pair<List<? extends Domain>, Integer> searchForDomains(ListDomainsCmd cmd) {
        Account caller = getCaller();
        Long domainId = cmd.getId();
        boolean listAll = cmd.listAll();
        boolean isRecursive = false;

        if (domainId != null) {
            Domain domain = getDomain(domainId);
            if (domain == null) {
                throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist");
            }
            _accountMgr.checkAccess(caller, domain);
        } else {
            if (!_accountMgr.isRootAdmin(caller.getId())) {
            domainId = caller.getDomainId();
            }
            if (listAll) {
                isRecursive = true;
            }
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        String domainName = cmd.getDomainName();
        Integer level = cmd.getLevel();
        Object keyword = cmd.getKeyword();

        SearchBuilder<DomainVO> sb = _domainDao.createSearchBuilder();
        sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
        sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
        sb.and("level", sb.entity().getLevel(), SearchCriteria.Op.EQ);
        sb.and("path", sb.entity().getPath(), SearchCriteria.Op.LIKE);
        sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);

        SearchCriteria<DomainVO> sc = sb.create();

        if (keyword != null) {
            SearchCriteria<DomainVO> ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");
            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainName != null) {
            sc.setParameters("name", domainName);
        }

        if (level != null) {
            sc.setParameters("level", level);
        }

        if (domainId != null) {
            if (isRecursive) {
                sc.setParameters("path", getDomain(domainId).getPath() + "%");
            } else {
                sc.setParameters("id", domainId);
            }
        }

        // return only Active domains to the API
        sc.setParameters("state", Domain.State.Active);

        Pair<List<DomainVO>, Integer> result = _domainDao.searchAndCount(sc, searchFilter);
        return new Pair<List<? extends Domain>, Integer>(result.first(), result.second());
    }

    @Override
    public Pair<List<? extends Domain>, Integer> searchForDomainChildren(ListDomainChildrenCmd cmd) throws PermissionDeniedException {
        Long domainId = cmd.getId();
        String domainName = cmd.getDomainName();
        Boolean isRecursive = cmd.isRecursive();
        Object keyword = cmd.getKeyword();
        boolean listAll = cmd.listAll();
        String path = null;

        Account caller = getCaller();
        if (domainId != null) {
            _accountMgr.checkAccess(caller, getDomain(domainId));
        } else {
            domainId = caller.getDomainId();
        }

        DomainVO domain = _domainDao.findById(domainId);
        if (domain != null && isRecursive && !listAll) {
            path = domain.getPath();
            domainId = null;
        }

        Filter searchFilter = new Filter(DomainVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
        Pair<List<DomainVO>, Integer> result = searchForDomainChildren(searchFilter, domainId, domainName, keyword, path, true);

        return new Pair<List<? extends Domain>, Integer>(result.first(), result.second());
    }

    private Pair<List<DomainVO>, Integer> searchForDomainChildren(Filter searchFilter, Long domainId, String domainName, Object keyword, String path,
        boolean listActiveOnly) {
        SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();

        if (keyword != null) {
            SearchCriteria<DomainVO> ssc = _domainDao.createSearchCriteria();
            ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%");

            sc.addAnd("name", SearchCriteria.Op.SC, ssc);
        }

        if (domainId != null) {
            sc.addAnd("parent", SearchCriteria.Op.EQ, domainId);
        }

        if (domainName != null) {
            sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + domainName + "%");
        }

        if (path != null) {
            sc.addAnd("path", SearchCriteria.Op.NEQ, path);
            sc.addAnd("path", SearchCriteria.Op.LIKE, path + "%");
        }

        if (listActiveOnly) {
            sc.addAnd("state", SearchCriteria.Op.EQ, Domain.State.Active);
        }

        return _domainDao.searchAndCount(sc, searchFilter);
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_DOMAIN_UPDATE, eventDescription = "updating Domain")
    @DB
    public DomainVO updateDomain(UpdateDomainCmd cmd) {
        final Long domainId = cmd.getId();
        final String domainName = cmd.getDomainName();
        final String networkDomain = cmd.getNetworkDomain();

        // check if domain exists in the system
        final DomainVO domain = _domainDao.findById(domainId);
        if (domain == null) {
            InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find domain with specified domain id");
            ex.addProxyObject(domainId.toString(), "domainId");
            throw ex;
        } else if (domain.getParent() == null && domainName != null) {
            // check if domain is ROOT domain - and deny to edit it with the new name
            throw new InvalidParameterValueException("ROOT domain can not be edited with a new name");
        }

        // check permissions
        Account caller = getCaller();
        _accountMgr.checkAccess(caller, domain);

        // domain name is unique in the cloud
        if (domainName != null) {
            SearchCriteria<DomainVO> sc = _domainDao.createSearchCriteria();
            sc.addAnd("name", SearchCriteria.Op.EQ, domainName);
            sc.addAnd("parent", SearchCriteria.Op.EQ, domain.getParent());
            List<DomainVO> domains = _domainDao.search(sc, null);

            boolean sameDomain = (domains.size() == 1 && domains.get(0).getId() == domainId);

            if (!domains.isEmpty() && !sameDomain) {
                InvalidParameterValueException ex =
                    new InvalidParameterValueException("Failed to update specified domain id with name '" + domainName + "' since it already exists in the system");
                ex.addProxyObject(domain.getUuid(), "domainId");
                throw ex;
            }
        }

        // validate network domain
        if (networkDomain != null && !networkDomain.isEmpty()) {
            if (!NetUtils.verifyDomainName(networkDomain)) {
                throw new InvalidParameterValueException(
                        "Invalid network domain. Total length shouldn't exceed 190 chars. Each domain label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', the digits '0' through '9', "
                                + "and the hyphen ('-'); can't start or end with \"-\"");
            }
        }

        Transaction.execute(new TransactionCallbackNoReturn() {
            @Override
            public void doInTransactionWithoutResult(TransactionStatus status) {
        if (domainName != null) {
            String updatedDomainPath = getUpdatedDomainPath(domain.getPath(), domainName);
            updateDomainChildren(domain, updatedDomainPath);
            domain.setName(domainName);
            domain.setPath(updatedDomainPath);
        }

        if (networkDomain != null) {
            if (networkDomain.isEmpty()) {
                domain.setNetworkDomain(null);
            } else {
                domain.setNetworkDomain(networkDomain);
            }
        }
        _domainDao.update(domainId, domain);
        CallContext.current().putContextParameter(Domain.class, domain.getUuid());
            }
        });

        return _domainDao.findById(domainId);

    }

    private String getUpdatedDomainPath(String oldPath, String newName) {
        String[] tokenizedPath = oldPath.split("/");
        tokenizedPath[tokenizedPath.length - 1] = newName;
        StringBuilder finalPath = new StringBuilder();
        for (String token : tokenizedPath) {
            finalPath.append(token);
            finalPath.append("/");
        }
        return finalPath.toString();
    }

    private void updateDomainChildren(DomainVO domain, String updatedDomainPrefix) {
        List<DomainVO> domainChildren = _domainDao.findAllChildren(domain.getPath(), domain.getId());
        // for each child, update the path
        for (DomainVO dom : domainChildren) {
            dom.setPath(dom.getPath().replaceFirst(domain.getPath(), updatedDomainPrefix));
            _domainDao.update(dom.getId(), dom);
        }
    }

    @Override
    @ActionEvent(eventType = EventTypes.EVENT_DOMAIN_MOVE, eventDescription = "moving Domain")
    @DB
    public Domain moveDomainAndChildrenToNewParentDomain(MoveDomainCmd cmd) throws ResourceAllocationException {
        Long idOfDomainToBeMoved = cmd.getDomainId();
        Long idOfNewParentDomain = cmd.getParentDomainId();

        if (idOfDomainToBeMoved == Domain.ROOT_DOMAIN) {
            throw new InvalidParameterValueException("The domain to be moved cannot be the ROOT domain.");
        }

        if (idOfDomainToBeMoved.equals(idOfNewParentDomain)) {
            throw new InvalidParameterValueException("The domain to be moved and the new parent domain cannot be the same.");
        }

        DomainVO domainToBeMoved = returnDomainIfExistsAndIsActive(idOfDomainToBeMoved);
        logger.debug(String.format("Found the domain [%s] as the domain to be moved.", domainToBeMoved));

        DomainVO newParentDomain = returnDomainIfExistsAndIsActive(idOfNewParentDomain);
        logger.debug(String.format("Found the domain [%s] as the new parent domain of the domain to be moved [%s].", newParentDomain, domainToBeMoved));

        Account caller = getCaller();
        _accountMgr.checkAccess(caller, domainToBeMoved);
        _accountMgr.checkAccess(caller, newParentDomain);

        Long idOfCurrentParentOfDomainToBeMoved = domainToBeMoved.getParent();
        if (idOfCurrentParentOfDomainToBeMoved.equals(idOfNewParentDomain)) {
            throw new InvalidParameterValueException(String.format("The current parent domain of the domain to be moved is equal to the new parent domain [%s].", newParentDomain));
        }

        if (newParentDomain.getPath().startsWith(domainToBeMoved.getPath())) {
            throw new InvalidParameterValueException("The new parent domain of the domain cannot be one of its children.");
        }

        validateUniqueDomainName(domainToBeMoved.getName(), idOfNewParentDomain);

        validateNewParentDomainResourceLimits(domainToBeMoved, newParentDomain);

        String currentPathOfDomainToBeMoved = domainToBeMoved.getPath();
        String domainToBeMovedName = domainToBeMoved.getName().concat("/");
        String newPathOfDomainToBeMoved = newParentDomain.getPath().concat(domainToBeMovedName);

        validateNewParentDomainCanAccessAllDomainToBeMovedResources(domainToBeMoved, newParentDomain, currentPathOfDomainToBeMoved, newPathOfDomainToBeMoved);

        DomainVO parentOfDomainToBeMoved = _domainDao.findById(idOfCurrentParentOfDomainToBeMoved);
        Transaction.execute(new TransactionCallbackNoReturn() {
            @Override
            public void doInTransactionWithoutResult(TransactionStatus status) {
                logger.debug(String.format("Setting the new parent of the domain to be moved [%s] as [%s].", domainToBeMoved, newParentDomain));
                domainToBeMoved.setParent(idOfNewParentDomain);

                updateDomainAndChildrenPathAndLevel(domainToBeMoved, newParentDomain, currentPathOfDomainToBeMoved, newPathOfDomainToBeMoved);

                updateResourceCounts(idOfCurrentParentOfDomainToBeMoved, idOfNewParentDomain);

                updateChildCounts(parentOfDomainToBeMoved, newParentDomain);
            }
        });

        return domainToBeMoved;
    }

    protected void validateNewParentDomainResourceLimit(DomainVO domainToBeMoved, DomainVO newParentDomain,
            Resource.ResourceType resourceType, String tag) throws ResourceAllocationException {
        long domainToBeMovedId = domainToBeMoved.getId();
        long newParentDomainId = newParentDomain.getId();
        long currentDomainResourceCount = _resourceCountDao.getResourceCount(domainToBeMovedId, ResourceOwnerType.Domain, resourceType, tag);
        long newParentDomainResourceCount = _resourceCountDao.getResourceCount(newParentDomainId, ResourceOwnerType.Domain, resourceType, tag);
        long newParentDomainResourceLimit = resourceLimitService.findCorrectResourceLimitForDomain(newParentDomain, resourceType, tag);

        if (newParentDomainResourceLimit == Resource.RESOURCE_UNLIMITED) {
            return;
        }

        if (currentDomainResourceCount + newParentDomainResourceCount > newParentDomainResourceLimit) {
            String message = String.format("Cannot move domain [%s] to parent domain [%s] as maximum domain resource limit of type [%s] would be exceeded. The current resource "
                            + "count for domain [%s] is [%s], the resource count for the new parent domain [%s] is [%s], and the limit is [%s].", domainToBeMoved,
                    newParentDomain, resourceType, domainToBeMoved, currentDomainResourceCount, newParentDomain, newParentDomainResourceCount,
                    newParentDomainResourceLimit);
            logger.error(message);
            throw new ResourceAllocationException(message, resourceType);
        }
    }


    protected void validateNewParentDomainResourceLimits(DomainVO domainToBeMoved, DomainVO newParentDomain) throws ResourceAllocationException {
        List<String> hostTags = resourceLimitService.getResourceLimitHostTags();
        List<String> storageTags = resourceLimitService.getResourceLimitStorageTags();
        for (Resource.ResourceType resourceType : Resource.ResourceType.values()) {
            validateNewParentDomainResourceLimit(domainToBeMoved, newParentDomain, resourceType, null);
            if (ResourceLimitService.HostTagsSupportingTypes.contains(resourceType)) {
                for (String tag : hostTags) {
                    validateNewParentDomainResourceLimit(domainToBeMoved, newParentDomain, resourceType, tag);
                }
            }
            if (ResourceLimitService.StorageTagsSupportingTypes.contains(resourceType)) {
                for (String tag : storageTags) {
                    validateNewParentDomainResourceLimit(domainToBeMoved, newParentDomain, resourceType, tag);
                }
            }
        }
    }

    protected void validateNewParentDomainCanAccessAllDomainToBeMovedResources(DomainVO domainToBeMoved, DomainVO newParentDomain, String currentPathOfDomainToBeMoved,
                                                                               String newPathOfDomainToBeMoved) {
        Map<Long, List<String>> idsOfDomainsWithNetworksUsedByDomainToBeMoved = _networkDomainDao.listDomainsOfSharedNetworksUsedByDomainPath(currentPathOfDomainToBeMoved);
        validateNewParentDomainCanAccessResourcesOfDomainToBeMoved(newPathOfDomainToBeMoved, domainToBeMoved, newParentDomain, idsOfDomainsWithNetworksUsedByDomainToBeMoved, "Networks");

        Map<Long, List<String>> idsOfDomainsOfAffinityGroupsUsedByDomainToBeMoved =
                affinityGroupDomainMapDao.listDomainsOfAffinityGroupsUsedByDomainPath(currentPathOfDomainToBeMoved);
        validateNewParentDomainCanAccessResourcesOfDomainToBeMoved(newPathOfDomainToBeMoved, domainToBeMoved, newParentDomain, idsOfDomainsOfAffinityGroupsUsedByDomainToBeMoved, "Affinity groups");

        Map<Long, List<String>> idsOfDomainsOfServiceOfferingsUsedByDomainToBeMoved =
                serviceOfferingJoinDao.listDomainsOfServiceOfferingsUsedByDomainPath(currentPathOfDomainToBeMoved);
        validateNewParentDomainCanAccessResourcesOfDomainToBeMoved(newPathOfDomainToBeMoved, domainToBeMoved, newParentDomain, idsOfDomainsOfServiceOfferingsUsedByDomainToBeMoved, "Service offerings");

        Map<Long, List<String>> idsOfDomainsOfNetworkOfferingsUsedByDomainToBeMoved =
                networkOfferingJoinDao.listDomainsOfNetworkOfferingsUsedByDomainPath(currentPathOfDomainToBeMoved);
        validateNewParentDomainCanAccessResourcesOfDomainToBeMoved(newPathOfDomainToBeMoved, domainToBeMoved, newParentDomain, idsOfDomainsOfNetworkOfferingsUsedByDomainToBeMoved, "Network offerings");

        Map<Long, List<String>> idsOfDomainsOfDedicatedResourcesUsedByDomainToBeMoved =
                _dedicatedDao.listDomainsOfDedicatedResourcesUsedByDomainPath(currentPathOfDomainToBeMoved);
        validateNewParentDomainCanAccessResourcesOfDomainToBeMoved(newPathOfDomainToBeMoved, domainToBeMoved, newParentDomain, idsOfDomainsOfDedicatedResourcesUsedByDomainToBeMoved, "Dedicated resources");
    }

    protected void validateNewParentDomainCanAccessResourcesOfDomainToBeMoved(String newPathOfDomainToBeMoved, DomainVO domainToBeMoved, DomainVO newParentDomain,
                                                                              Map<Long, List<String>> idsOfDomainsWithResourcesUsedByDomainToBeMoved, String resourceToLog) {
        Map<DomainVO, List<String>> domainsOfResourcesInaccessibleToNewParentDomain = new HashMap<>();
        for (Map.Entry<Long, List<String>> entry : idsOfDomainsWithResourcesUsedByDomainToBeMoved.entrySet()) {
            DomainVO domainWithResourceUsedByDomainToBeMoved = _domainDao.findById(entry.getKey());

            Pattern pattern = Pattern.compile(domainWithResourceUsedByDomainToBeMoved.getPath().replace("/", "\\/").concat(".*"));
            Matcher matcher = pattern.matcher(newPathOfDomainToBeMoved);
            if (!matcher.matches()) {
                domainsOfResourcesInaccessibleToNewParentDomain.put(domainWithResourceUsedByDomainToBeMoved, entry.getValue());
            }
        }

        if (!domainsOfResourcesInaccessibleToNewParentDomain.isEmpty()) {
            logger.error(String.format("The new parent domain [%s] does not have access to domains [%s] used by [%s] in the domain to be moved [%s].",
                    newParentDomain, domainsOfResourcesInaccessibleToNewParentDomain.keySet(), domainsOfResourcesInaccessibleToNewParentDomain.values(), domainToBeMoved));
            throw new InvalidParameterValueException(String.format("New parent domain [%s] does not have access to [%s] used by domain [%s], therefore, domain [%s] cannot be moved.",
                    newParentDomain, resourceToLog, domainToBeMoved, domainToBeMoved));
        }
    }

    protected DomainVO returnDomainIfExistsAndIsActive(Long idOfDomain) {
        logger.debug(String.format("Checking if domain with ID [%s] exists and is active.", idOfDomain));
        DomainVO domain = _domainDao.findById(idOfDomain);

        if (domain == null) {
            throw new InvalidParameterValueException(String.format("Unable to find a domain with the specified ID [%s].", idOfDomain));
        } else if (domain.getState().equals(Domain.State.Inactive)) {
            throw new InvalidParameterValueException(String.format("Unable to use the domain [%s] as it is in state [%s].", domain, Domain.State.Inactive));
        }

        return domain;
    }

    protected void updateDomainAndChildrenPathAndLevel(DomainVO domainToBeMoved, DomainVO newParentDomain, String oldPath, String newPath) {
        Integer oldRootLevel = domainToBeMoved.getLevel();
        Integer newLevel = newParentDomain.getLevel() + 1;

        updateDomainPathAndLevel(domainToBeMoved, oldPath, newPath, oldRootLevel, newLevel);

        List<DomainVO> childrenDomain = _domainDao.findAllChildren(oldPath, domainToBeMoved.getId());
        for (DomainVO childDomain : childrenDomain) {
            updateDomainPathAndLevel(childDomain, oldPath, newPath, oldRootLevel, newLevel);
        }
    }

    protected void updateDomainPathAndLevel(DomainVO domain, String oldPath, String newPath, Integer oldRootLevel, Integer newLevel) {
        String finalPath = StringUtils.replaceOnce(domain.getPath(), oldPath, newPath);
        domain.setPath(finalPath);

        Integer currentLevel = domain.getLevel();
        int finalLevel = newLevel + currentLevel - oldRootLevel;
        domain.setLevel(finalLevel);

        logger.debug(String.format("Updating the path to [%s] and the level to [%s] of the domain [%s].", finalPath, finalLevel, domain));
        _domainDao.update(domain.getId(), domain);
    }

    protected void updateResourceCounts(Long idOfOldParentDomain, Long idOfNewParentDomain) {
        logger.debug(String.format("Updating the resource counts of the old parent domain [%s] and of the new parent domain [%s].", idOfOldParentDomain, idOfNewParentDomain));
        resourceLimitService.recalculateResourceCount(null, idOfOldParentDomain, null);
        resourceLimitService.recalculateResourceCount(null, idOfNewParentDomain, null);
    }

    protected void updateChildCounts(DomainVO oldParentDomain, DomainVO newParentDomain) {
        int finalOldParentChildCount = oldParentDomain.getChildCount() - 1;

        oldParentDomain.setChildCount(finalOldParentChildCount);
        oldParentDomain.setNextChildSeq(finalOldParentChildCount + 1);

        logger.debug(String.format("Updating the child count of the old parent domain [%s] to [%s].", oldParentDomain, finalOldParentChildCount));
        _domainDao.update(oldParentDomain.getId(), oldParentDomain);

        int finalNewParentChildCount = newParentDomain.getChildCount() + 1;

        newParentDomain.setChildCount(finalNewParentChildCount);
        newParentDomain.setNextChildSeq(finalNewParentChildCount + 1);

        logger.debug(String.format("Updating the child count of the new parent domain [%s] to [%s].", newParentDomain, finalNewParentChildCount));
        _domainDao.update(newParentDomain.getId(), newParentDomain);
    }
}
