org.sipfoundry.sipxconfig.openacd.OpenAcdContextImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.sipfoundry.sipxconfig.openacd.OpenAcdContextImpl.java

Source

/**
 *
 *
 * Copyright (c) 2010 / 2011 eZuce, Inc. All rights reserved.
 * Contributed to SIPfoundry under a Contributor Agreement
 *
 * This software is free software; you can redistribute it and/or modify it under
 * the terms of the Affero General Public License (AGPL) as published by the
 * Free Software Foundation; either version 3 of the License, or (at your option)
 * any later version.
 *
 * This software is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 */
package org.sipfoundry.sipxconfig.openacd;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import static java.lang.Integer.parseInt;

import org.apache.commons.lang.StringUtils;
import org.sipfoundry.sipxconfig.address.Address;
import org.sipfoundry.sipxconfig.address.AddressManager;
import org.sipfoundry.sipxconfig.address.AddressProvider;
import org.sipfoundry.sipxconfig.address.AddressType;
import org.sipfoundry.sipxconfig.alias.AliasManager;
import org.sipfoundry.sipxconfig.common.BeanId;
import org.sipfoundry.sipxconfig.common.CoreContext;
import org.sipfoundry.sipxconfig.common.DaoUtils;
import org.sipfoundry.sipxconfig.common.ExtensionInUseException;
import org.sipfoundry.sipxconfig.common.NameInUseException;
import org.sipfoundry.sipxconfig.common.SameExtensionException;
import org.sipfoundry.sipxconfig.common.SipxHibernateDaoSupport;
import org.sipfoundry.sipxconfig.common.User;
import org.sipfoundry.sipxconfig.common.UserException;
import org.sipfoundry.sipxconfig.common.event.DaoEventListener;
import org.sipfoundry.sipxconfig.commserver.Location;
import org.sipfoundry.sipxconfig.commserver.LocationsManager;
import org.sipfoundry.sipxconfig.commserver.imdb.ReplicationManager;
import org.sipfoundry.sipxconfig.feature.Bundle;
import org.sipfoundry.sipxconfig.feature.FeatureChangeRequest;
import org.sipfoundry.sipxconfig.feature.FeatureChangeValidator;
import org.sipfoundry.sipxconfig.feature.FeatureManager;
import org.sipfoundry.sipxconfig.feature.FeatureProvider;
import org.sipfoundry.sipxconfig.feature.GlobalFeature;
import org.sipfoundry.sipxconfig.feature.LocationFeature;
import org.sipfoundry.sipxconfig.firewall.DefaultFirewallRule;
import org.sipfoundry.sipxconfig.firewall.FirewallManager;
import org.sipfoundry.sipxconfig.firewall.FirewallProvider;
import org.sipfoundry.sipxconfig.firewall.FirewallRule;
import org.sipfoundry.sipxconfig.freeswitch.FreeswitchAction;
import org.sipfoundry.sipxconfig.freeswitch.FreeswitchCondition;
import org.sipfoundry.sipxconfig.freeswitch.FreeswitchFeature;
import org.sipfoundry.sipxconfig.im.ImAccount;
import org.sipfoundry.sipxconfig.setting.BeanWithSettingsDao;
import org.sipfoundry.sipxconfig.setting.Group;
import org.sipfoundry.sipxconfig.setting.SettingDao;
import org.sipfoundry.sipxconfig.setup.SetupListener;
import org.sipfoundry.sipxconfig.setup.SetupManager;
import org.sipfoundry.sipxconfig.snmp.ProcessDefinition;
import org.sipfoundry.sipxconfig.snmp.ProcessProvider;
import org.sipfoundry.sipxconfig.snmp.SnmpManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.dao.support.DataAccessUtils;

public class OpenAcdContextImpl extends SipxHibernateDaoSupport implements OpenAcdContext, BeanFactoryAware,
        FeatureProvider, AddressProvider, ProcessProvider, DaoEventListener, FirewallProvider, SetupListener {

    private static final Collection<AddressType> ADDRESSES = Arrays
            .asList(new AddressType[] { OPENACD_WEB, OPENACD_SECURE_WEB });
    private static final String VALUE = "value";
    private static final String OPEN_ACD_EXTENSION_WITH_NAME = "openAcdExtensionWithName";
    private static final String OPEN_ACD_AGENT_GROUP_WITH_NAME = "openAcdAgentGroupWithName";
    private static final String OPEN_ACD_SKILL_GROUPWITH_NAME = "openAcdSkillGroupWithName";
    private static final String OPEN_ACD_SKILL_WITH_NAME = "openAcdSkillWithName";
    private static final String OPEN_ACD_SKILL_WITH_ATOM = "openAcdSkillWithAtom";
    private static final String OPEN_ACD_CLIENT_WITH_NAME = "openAcdClientWithName";
    private static final String OPEN_ACD_CLIENT_WITH_IDENTITY = "openAcdClientWithIdentity";
    private static final String DEFAULT_OPEN_ACD_SKILLS = "defaultOpenAcdSkills";
    private static final String OPEN_ACD_AGENT_BY_USERID = "openAcdAgentByUserId";
    private static final String LINE_NAME = "line";
    private static final String OPEN_ACD_QUEUE_GROUP_WITH_NAME = "openAcdQueueGroupWithName";
    private static final String OPEN_ACD_QUEUE_WITH_NAME = "openAcdQueueWithName";
    private static final String DEFAULT_QUEUE = "default_queue";
    private static final String FS_ACTIONS_WITH_DATA = "freeswitchActionsWithData";
    private static final String OPEN_ACD_RELEASE_CODE_WITH_LABEL = "openAcdClientReleaseCodeWithLabel";
    private static final String OPEN_ACD_PROCESS_NAME = "openacd";
    private static final String AGENT_GROUP_NAME = "Contact-center-agents";
    private static final String ALIAS = "alias";
    private static final String EXTENSION = "extension";
    private static final String DID = "did";
    //commands
    private static final String DESTINATION_NUMBER = "destination_number";
    private static final String ANSWER = "answer";
    private static final String ERLANG_SENDMSG = "erlang_sendmsg";
    private static final String SLEEP = "sleep";
    private static final String SLEEP_MS = "2000";
    private static final String HANGUP = "hangup";
    private static final String NORMAL_CLEARING = "NORMAL CLEARING";
    private static final String AGENT_DP_LISTENER = "agent_dialplan_listener openacd@";

    private AliasManager m_aliasManager;
    private FeatureManager m_featureManager;
    private BeanWithSettingsDao<OpenAcdSettings> m_settingsDao;
    private ListableBeanFactory m_beanFactory;
    private CoreContext m_coreContext;
    private ReplicationManager m_replicationManager;
    private SettingDao m_settingDao;
    private LocationsManager m_locationsManager;

    @Override
    public Collection<GlobalFeature> getAvailableGlobalFeatures(FeatureManager featureManager) {
        return null;
    }

    @Override
    public Collection<LocationFeature> getAvailableLocationFeatures(FeatureManager featureManager, Location l) {
        return Collections.singleton(FEATURE);
    }

    @Override
    public Collection<DefaultFirewallRule> getFirewallRules(FirewallManager manager) {
        if (m_featureManager.isFeatureEnabled(FEATURE)) {
            List<DefaultFirewallRule> rules = new ArrayList<DefaultFirewallRule>();
            OpenAcdSettings settings = getSettings();
            if (settings.isAgentWebUiEnabled()) {
                rules.add(new DefaultFirewallRule(OPENACD_WEB, FirewallRule.SystemId.PUBLIC));
            }
            if (settings.isAgentWebUiSSlEnabled()) {
                rules.add(new DefaultFirewallRule(OPENACD_SECURE_WEB, FirewallRule.SystemId.PUBLIC));
            }
            return rules;
        }

        return Collections.EMPTY_LIST;
    }

    @Override
    public Collection<Address> getAvailableAddresses(AddressManager manager, AddressType type, Location requester) {
        if (!ADDRESSES.contains(type) || !manager.getFeatureManager().isFeatureEnabled(FEATURE)) {
            return null;
        }

        OpenAcdSettings settings = getSettings();
        List<Location> locations = manager.getFeatureManager().getLocationsForEnabledFeature(FEATURE);
        List<Address> addresses = new ArrayList<Address>(locations.size());
        Address address = null;
        for (Location location : locations) {
            if (type.equals(OPENACD_WEB) && settings.isAgentWebUiEnabled()) {
                address = new Address(OPENACD_WEB, location.getAddress(), parseInt(settings.getAgentWebUiPort()));
            } else if (type.equals(OPENACD_SECURE_WEB) && settings.isAgentWebUiSSlEnabled()) {
                address = new Address(OPENACD_SECURE_WEB, location.getAddress(),
                        parseInt(settings.getAgentWebUiSSlPort()));
            }

            addresses.add(address);
        }
        return addresses;
    }

    public OpenAcdSettings getSettings() {
        return m_settingsDao.findOrCreateOne();
    }

    public void saveSettings(OpenAcdSettings settings) {
        m_settingsDao.upsert(settings);
    }

    public OpenAcdLine newOpenAcdLine() {
        return m_beanFactory.getBean(OpenAcdLine.class);
    }

    public OpenAcdCommand newOpenAcdCommand() {
        return m_beanFactory.getBean(OpenAcdCommand.class);
    }

    @Override
    public OpenAcdExtension getExtensionById(Integer extensionId) {
        return getHibernateTemplate().load(OpenAcdExtension.class, extensionId);
    }

    @Override
    public OpenAcdExtension getExtensionByName(String extensionName) {
        List<OpenAcdLine> extensions = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_EXTENSION_WITH_NAME, VALUE, extensionName);
        return DataAccessUtils.singleResult(extensions);
    }

    @Override
    public List<OpenAcdExtension> getFreeswitchExtensions() {
        return getHibernateTemplate().loadAll(OpenAcdExtension.class);
    }

    @Override
    public Set<OpenAcdLine> getLines() {
        List<OpenAcdLine> openacdLines = getHibernateTemplate().loadAll(OpenAcdLine.class);
        Set<OpenAcdLine> lines = new HashSet<OpenAcdLine>();
        for (OpenAcdLine ext : openacdLines) {
            if (ext.getExtension() != null) {
                lines.add(ext);
            }
        }
        return lines;
    }

    public Set<OpenAcdCommand> getCommands() {
        List<OpenAcdCommand> openacdCommands = getHibernateTemplate().loadAll(OpenAcdCommand.class);
        Set<OpenAcdCommand> comms = new HashSet<OpenAcdCommand>();
        for (OpenAcdCommand ext : openacdCommands) {
            if (ext.getExtension() != null) {
                comms.add(ext);
            }
        }
        return comms;
    }

    @Override
    public String[] getOpenAcdApplicationNames() {
        Set<String> applications = new HashSet<String>();
        List<FreeswitchAction> actions = getHibernateTemplate().loadAll(FreeswitchAction.class);
        for (FreeswitchAction freeswitchAction : actions) {
            applications.add(freeswitchAction.getApplication());
        }
        applications.addAll(FreeswitchAction.PredefinedAction.valuesAsStrings());
        return applications.toArray(new String[0]);
    }

    @Override
    public boolean isEnabled() {
        return m_featureManager.isFeatureEnabled(FEATURE);
    }

    public void deleteExtension(OpenAcdExtension ext) {
        getHibernateTemplate().delete(ext);
        getHibernateTemplate().flush();
    }

    public void saveExtension(OpenAcdExtension extension) {
        if (extension.getName() == null) {
            throw new UserException("&null.name");
        }
        if (extension.getExtension() == null) {
            throw new UserException("&null.extension");
        }
        String capturedExt = extension.getCapturedExtension();

        if (!m_aliasManager.canObjectUseAlias(extension, extension.getName())) {
            throw new NameInUseException(LINE_NAME, extension.getName());
        } else if (!m_aliasManager.canObjectUseAlias(extension, capturedExt)) {
            throw new ExtensionInUseException(LINE_NAME, capturedExt);
        } else if (extension.getAlias() != null
                && !m_aliasManager.canObjectUseAlias(extension, extension.getAlias())) {
            throw new ExtensionInUseException(LINE_NAME, extension.getAlias());
        } else if (extension.getAlias() != null && extension.getAlias().equals(extension.getExtension())) {
            throw new SameExtensionException(ALIAS, EXTENSION);
        } else if (extension.getDid() != null && !m_aliasManager.canObjectUseAlias(extension, extension.getDid())) {
            throw new ExtensionInUseException(LINE_NAME, extension.getDid());
        } else if (extension.getDid() != null && extension.getDid().equals(extension.getExtension())) {
            throw new SameExtensionException(DID, EXTENSION);
        } else if (extension.getDid() != null && extension.getAlias() != null
                && extension.getDid().equals(extension.getAlias())) {
            throw new SameExtensionException(ALIAS, DID);
        }
        removeNullActions(extension);
        if (extension.isNew()) {
            getHibernateTemplate().saveOrUpdate(extension);
        } else {
            getHibernateTemplate().merge(extension);
        }
    }

    private void removeNullActions(OpenAcdExtension extension) {
        if (extension.getConditions() == null) {
            return;
        }
        for (FreeswitchCondition condition : extension.getConditions()) {
            for (FreeswitchAction action : condition.getActions()) {
                if (action != null && action.getApplication() == null) {
                    condition.removeAction(action);
                }
            }
        }
    }

    private List<FreeswitchAction> getActionsByData(String actionData) {
        return getHibernateTemplate().findByNamedQueryAndNamedParam(FS_ACTIONS_WITH_DATA, VALUE, actionData);
    }

    @Override
    public Collection getBeanIdsOfObjectsWithAlias(String alias) {
        Collection<BeanId> bids = new ArrayList<BeanId>();

        List<OpenAcdLine> lines = getHibernateTemplate().loadAll(OpenAcdLine.class);
        for (OpenAcdLine line : lines) {
            if (line.getExtension() != null && (line.getExtension().equals(alias) || line.getName().equals(alias))
                    || (line.getAlias() != null && line.getAlias().equals(alias))
                    || (line.getDid() != null && line.getDid().equals(alias))) {
                bids.add(new BeanId(line.getId(), OpenAcdLine.class));
            }
        }
        List<OpenAcdCommand> commands = getHibernateTemplate().loadAll(OpenAcdCommand.class);
        for (OpenAcdCommand openAcdCommand : commands) {
            if (openAcdCommand.getExtension() != null && (openAcdCommand.getExtension().equals(alias))
                    || openAcdCommand.getName().equals(alias)) {
                bids.add(new BeanId(openAcdCommand.getId(), OpenAcdCommand.class));
            }
        }
        return bids;
    }

    @Override
    public boolean isAliasInUse(String alias) {
        List<OpenAcdExtension> extensions = getFreeswitchExtensions();
        for (OpenAcdExtension openAcdExtension : extensions) {
            if (openAcdExtension.getExtension() != null && (openAcdExtension.getExtension().equals(alias)
                    || openAcdExtension.getName().equals(alias))) {
                return true;
            }
            if (openAcdExtension.getAlias() != null && openAcdExtension.getAlias().equals(alias)) {
                return true;
            }
            if (openAcdExtension.getDid() != null && openAcdExtension.getDid().equals(alias)) {
                return true;
            }
        }
        return false;
    }

    public List<OpenAcdAgentGroup> getAgentGroups() {
        return getHibernateTemplate().loadAll(OpenAcdAgentGroup.class);
    }

    public OpenAcdAgentGroup getAgentGroupById(Integer agentGroupId) {
        return getHibernateTemplate().load(OpenAcdAgentGroup.class, agentGroupId);
    }

    public OpenAcdAgentGroup getAgentGroupByName(String agentGroupName) {
        List<OpenAcdAgentGroup> agentGroups = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_AGENT_GROUP_WITH_NAME, VALUE, agentGroupName);
        return DataAccessUtils.singleResult(agentGroups);
    }

    public void saveAgentGroup(OpenAcdAgentGroup agentGroup) {
        // check if agent group name is empty
        if (StringUtils.isBlank(agentGroup.getName())) {
            throw new UserException("&blank.agentGroupName.error");
        }
        // Check for duplicate names before saving the agent group
        if (agentGroup.isNew() || (!agentGroup.isNew() && isNameChanged(agentGroup))) {
            checkForDuplicateName(agentGroup);
        }

        if (!agentGroup.isNew()) {
            if (isNameChanged(agentGroup)) {
                // don't rename the default group
                OpenAcdAgentGroup defaultAgentGroup = getAgentGroupByName(GROUP_NAME_DEFAULT);
                if (defaultAgentGroup != null && defaultAgentGroup.getId().equals(agentGroup.getId())) {
                    throw new UserException("&msg.err.defaultAgentGroupRename");
                }
            }
            getHibernateTemplate().merge(agentGroup);
        } else {
            getHibernateTemplate().save(agentGroup);
        }
    }

    private boolean isNameChanged(OpenAcdAgentGroup agentGroup) {
        String oldName = getAgentGroupById(agentGroup.getId()).getName();
        agentGroup.setOldName(oldName);
        return !oldName.equals(agentGroup.getName());
    }

    private void checkForDuplicateName(OpenAcdAgentGroup agentGroup) {
        String agentGroupName = agentGroup.getName();
        OpenAcdAgentGroup existingAgentGroup = getAgentGroupByName(agentGroupName);
        if (existingAgentGroup != null) {
            throw new UserException("&duplicate.agentGroupName.error", agentGroupName);
        }
    }

    public void deleteAgentGroup(OpenAcdAgentGroup group) {
        if (group.getName().equals(GROUP_NAME_DEFAULT)) {
            throw new DefaultAgentGroupDeleteException();
        }
        getHibernateTemplate().delete(group);
    }

    public class DefaultAgentGroupDeleteException extends UserException {
    }

    public List<OpenAcdAgent> getAgents() {
        return getHibernateTemplate().loadAll(OpenAcdAgent.class);
    }

    public List<OpenAcdRecipeAction> getRecipeActions() {
        return getHibernateTemplate().loadAll(OpenAcdRecipeAction.class);
    }

    public OpenAcdAgent getAgentById(Integer agentId) {
        return getHibernateTemplate().load(OpenAcdAgent.class, agentId);
    }

    public OpenAcdAgent getAgentByUserId(Integer userId) {
        Collection<OpenAcdAgent> agents = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_AGENT_BY_USERID, VALUE, userId);
        return DaoUtils.requireOneOrZero(agents, OPEN_ACD_AGENT_BY_USERID);
    }

    private Group createAgentsGroup() {
        Group agentGroup = m_settingDao.getGroupByName(User.GROUP_RESOURCE_ID, AGENT_GROUP_NAME);
        if (agentGroup == null) {
            agentGroup = new Group();
            agentGroup.setName(AGENT_GROUP_NAME);
            agentGroup.setResource(User.GROUP_RESOURCE_ID);
            agentGroup.setDescription("All contact center agents");
            agentGroup.setSettingValue(ImAccount.IM_ACCOUNT, "1");
            m_settingDao.saveGroup(agentGroup);
        }
        return agentGroup;
    }

    @Override
    public void saveAgent(OpenAcdAgent agent) {
        checkAgent(agent);
        getHibernateTemplate().saveOrUpdate(agent);
        agent.getUser().getGroups().add(createAgentsGroup());
        m_coreContext.saveUser(agent.getUser());
    }

    private void checkAgent(OpenAcdAgent agent) {
        // check if agent group is empty
        if (StringUtils.isBlank(agent.getAgentGroup())) {
            throw new UserException("&blank.agentGroup.error");
        }

        // check if agent security is empty
        if (StringUtils.isBlank(agent.getSecurity())) {
            throw new UserException("&blank.agentSecurity.error");
        }
    }

    @Override
    public void deleteAgent(OpenAcdAgent agent) {
        agent.getUser().getGroups()
                .remove(m_settingDao.getGroupByName(CoreContext.USER_GROUP_RESOURCE_ID, AGENT_GROUP_NAME));
        getHibernateTemplate().delete(agent);
        m_coreContext.saveUser(agent.getUser());
    }

    @Override
    public OpenAcdAgent getAgentByUser(User user) {
        return getAgentByUserId(user.getId());
    }

    @Override
    public boolean isOpenAcdAgent(User user) {
        if (getAgentByUser(user) != null) {
            return true;
        }
        return false;
    }

    @Override
    public List<OpenAcdSkillGroup> getSkillGroups() {
        return getHibernateTemplate().loadAll(OpenAcdSkillGroup.class);
    }

    @Override
    public OpenAcdSkillGroup getSkillGroupById(Integer skillGroupId) {
        return getHibernateTemplate().load(OpenAcdSkillGroup.class, skillGroupId);
    }

    @Override
    public OpenAcdSkillGroup getSkillGroupByName(String skillGroupName) {
        List<OpenAcdSkillGroup> skillGroups = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_SKILL_GROUPWITH_NAME, VALUE, skillGroupName);
        return DataAccessUtils.singleResult(skillGroups);
    }

    @Override
    public void saveSkillGroup(OpenAcdSkillGroup skillGroup) {
        if (StringUtils.isBlank(skillGroup.getName())) {
            throw new UserException("&blank.skillGroupName.error");
        }
        if (skillGroup.isNew() || (!skillGroup.isNew() && isNameChanged(skillGroup))) {
            checkForDuplicateName(skillGroup);
        }

        if (!skillGroup.isNew()) {
            if (isNameChanged(skillGroup)) {
                // don't rename the Magic skill group
                OpenAcdSkillGroup magicSkillGroup = getSkillGroupByName(MAGIC_SKILL_GROUP_NAME);
                if (magicSkillGroup != null && magicSkillGroup.getId().equals(skillGroup.getId())) {
                    throw new UserException("&msg.err.magicSkillGroupRename");
                }

                List<OpenAcdSkill> skills = new LinkedList<OpenAcdSkill>();
                for (OpenAcdSkill skill : skillGroup.getSkills()) {
                    skills.add(skill);
                }
            }
            getHibernateTemplate().merge(skillGroup);
        } else {
            getHibernateTemplate().save(skillGroup);
        }
    }

    private boolean isNameChanged(OpenAcdSkillGroup skillGroup) {
        String oldName = getSkillGroupById(skillGroup.getId()).getName();
        skillGroup.setOldName(oldName);
        return !oldName.equals(skillGroup.getName());
    }

    private void checkForDuplicateName(OpenAcdSkillGroup skillGroup) {
        String skillGroupName = skillGroup.getName();
        OpenAcdSkillGroup existingSkillGroup = getSkillGroupByName(skillGroupName);
        if (existingSkillGroup != null) {
            throw new UserException("&duplicate.skillGroupName.error", skillGroupName);
        }
    }

    @Override
    public List<String> removeSkillGroups(Collection<Integer> skillGroupIds) {
        List<OpenAcdSkillGroup> groups = new LinkedList<OpenAcdSkillGroup>();
        List<String> usedSkillGroups = new ArrayList<String>();
        for (Integer id : skillGroupIds) {
            OpenAcdSkillGroup group = getSkillGroupById(id);
            if (group.getName().equals(MAGIC_SKILL_GROUP_NAME) || containsUsedSkills(group)) {
                usedSkillGroups.add(group.getName());
            } else {
                groups.add(group);
            }
        }
        getDaoEventPublisher().publishDeleteCollection(groups);
        getHibernateTemplate().deleteAll(groups);

        return usedSkillGroups;
    }

    @Override
    public boolean containsUsedSkills(OpenAcdSkillGroup skillGroup) {
        for (OpenAcdSkill skill : skillGroup.getSkills()) {
            if (skill.isDefaultSkill() || isSkillInUse(skill)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public List<OpenAcdSkill> getSkills() {
        return getHibernateTemplate().loadAll(OpenAcdSkill.class);
    }

    @Override
    public List<OpenAcdSkill> getDefaultSkills() {
        return getHibernateTemplate().findByNamedQuery(DEFAULT_OPEN_ACD_SKILLS);
    }

    @Override
    public OpenAcdSkill getSkillById(Integer skillId) {
        return getHibernateTemplate().load(OpenAcdSkill.class, skillId);
    }

    @Override
    public OpenAcdSkill getSkillByName(String skillName) {
        List<OpenAcdSkill> skills = getHibernateTemplate().findByNamedQueryAndNamedParam(OPEN_ACD_SKILL_WITH_NAME,
                VALUE, skillName);
        return DataAccessUtils.singleResult(skills);
    }

    @Override
    public OpenAcdSkill getSkillByAtom(String atom) {
        List<OpenAcdSkill> skills = getHibernateTemplate().findByNamedQueryAndNamedParam(OPEN_ACD_SKILL_WITH_ATOM,
                VALUE, atom);
        return DataAccessUtils.singleResult(skills);
    }

    @Override
    public void saveSkill(OpenAcdSkill skill) {
        // Check if skill name is empty
        if (StringUtils.isBlank(skill.getName())) {
            throw new UserException("&blank.skillName.error");
        }
        // Check if skill atom is empty
        if (StringUtils.isBlank(skill.getAtom())) {
            throw new UserException("&blank.skillAtom.error");
        }
        // Check if skill group is empty
        if (skill.getGroup() == null) {
            throw new UserException("&error.requiredSkillGroup");
        }
        // Check for duplicate names before saving the skill
        if (skill.isNew() || (!skill.isNew() && isNameChanged(skill))) {
            checkForDuplicateName(skill);
        }
        // Check for duplicate atoms before saving the skill
        if (skill.isNew() || (!skill.isNew() && isAtomChanged(skill))) {
            checkForDuplicateAtom(skill);
        }
        // Magic skills cannot be added, changed or deleted
        if (skill.getGroupName().equals(MAGIC_SKILL_GROUP_NAME)) {
            throw new UserException("&error.forbiddenMagicSkillGroup");
        }

        if (!skill.isNew()) {
            getHibernateTemplate().merge(skill);
        } else {
            getHibernateTemplate().save(skill);
        }
    }

    public void deleteSkill(OpenAcdSkill skill) {
        List<OpenAcdSkill> skills = new LinkedList<OpenAcdSkill>();
        if (skill.isDefaultSkill() || isSkillInUse(skill)) {
            throw new SkillInUseException();
        } else {
            OpenAcdSkillGroup group = skill.getGroup();
            group.removeSkill(skill);
            getHibernateTemplate().saveOrUpdate(group);
            skills.add(skill);
        }
        getDaoEventPublisher().publishDeleteCollection(skills);
        getHibernateTemplate().deleteAll(skills);
    }

    public class SkillInUseException extends UserException {
    }

    private boolean isSkillInUse(OpenAcdSkill skill) {
        if (countObjectWithSkillId(skill.getId(), "countOpenAcdAgentGroupWithSkill") > 0
                || countObjectWithSkillId(skill.getId(), "countOpenAcdAgentWithSkill") > 0
                || countObjectWithSkillId(skill.getId(), "countOpenAcdQueueGroupWithSkill") > 0
                || countObjectWithSkillId(skill.getId(), "countOpenAcdQueueWithSkill") > 0) {
            return true;
        }
        return false;

    }

    private int countObjectWithSkillId(Integer id, String queryName) {
        List countAgentGroups = getHibernateTemplate().findByNamedQueryAndNamedParam(queryName,
                new String[] { VALUE }, new Object[] { id });

        return DataAccessUtils.intResult(countAgentGroups);
    }

    public Map<String, List<OpenAcdSkill>> getGroupedSkills() {
        return getFilteredGroupedSkills(new ArrayList<String>());
    }

    public Map<String, List<OpenAcdSkill>> getAgentGroupedSkills() {
        List<String> atomsToFilter = new ArrayList<String>();
        atomsToFilter.add("_brand");
        atomsToFilter.add("_queue");
        return getFilteredGroupedSkills(atomsToFilter);
    }

    public Map<String, List<OpenAcdSkill>> getQueueGroupedSkills() {
        List<String> atomsToFilter = new ArrayList<String>();
        atomsToFilter.add("_agent");
        atomsToFilter.add("_profile");
        return getFilteredGroupedSkills(atomsToFilter);
    }

    private Map<String, List<OpenAcdSkill>> getFilteredGroupedSkills(List<String> atomsToFilter) {
        Map<String, List<OpenAcdSkill>> groupedSkills = new TreeMap<String, List<OpenAcdSkill>>();
        List<OpenAcdSkill> skills = getSkills();
        if (!skills.isEmpty()) {
            for (OpenAcdSkill skill : skills) {
                if (!atomsToFilter.contains(skill.getAtom())) {
                    String skillGroupName = skill.getGroupName();
                    if (groupedSkills.containsKey(skillGroupName)) {
                        groupedSkills.get(skillGroupName).add(skill);
                    } else {
                        LinkedList<OpenAcdSkill> groupNameSkills = new LinkedList<OpenAcdSkill>();
                        groupNameSkills.add(skill);
                        groupedSkills.put(skill.getGroupName(), groupNameSkills);
                    }
                }
            }
        }
        return groupedSkills;
    }

    @Override
    public void saveClient(OpenAcdClient client) {
        // Check for duplicate names before saving the skill
        if (client.isNew() || (!client.isNew() && isNameChanged(client))) {
            checkForDuplicateName(client);
        }
        // Check for duplicate atoms before saving the skill
        if (client.isNew() || (!client.isNew() && isIdentityChanged(client))) {
            checkForDuplicateIdentity(client);
        }

        if (client.isNew()) {
            getHibernateTemplate().save(client);
        } else {
            getHibernateTemplate().merge(client);
        }
    }

    private boolean isNameChanged(OpenAcdClient client) {
        return !getClientById(client.getId()).getName().equals(client.getName());
    }

    private boolean isIdentityChanged(OpenAcdClient client) {
        return !getClientById(client.getId()).getIdentity().equals(client.getIdentity());
    }

    private void checkForDuplicateName(OpenAcdClient client) {
        String clientName = client.getName();
        OpenAcdClient existingClient = getClientByName(clientName);
        if (existingClient != null) {
            throw new UserException("&duplicate.clientName.error", existingClient);
        }
    }

    private void checkForDuplicateIdentity(OpenAcdClient client) {
        String identity = client.getIdentity();
        OpenAcdClient existingClient = getClientByIdentity(identity);
        if (existingClient != null) {
            throw new UserException("&duplicate.clientIdentity.error", existingClient);
        }
    }

    public OpenAcdClient getClientByName(String clientName) {
        List<OpenAcdClient> clients = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_CLIENT_WITH_NAME, VALUE, clientName);
        return DataAccessUtils.singleResult(clients);
    }

    @Override
    public OpenAcdClient getClientByIdentity(String identity) {
        List<OpenAcdClient> clients = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_CLIENT_WITH_IDENTITY, VALUE, identity);
        return DataAccessUtils.singleResult(clients);
    }

    @Override
    public void deleteClient(OpenAcdClient client) {
        if (isUsedByLine(OpenAcdLine.BRAND + client.getIdentity())) {
            throw new ClientInUseException();
        } else {
            getHibernateTemplate().delete(client);
        }
    }

    public final class ClientInUseException extends UserException {
    }

    @Override
    public List<OpenAcdClient> getClients() {
        return getHibernateTemplate().loadAll(OpenAcdClient.class);
    }

    @Override
    public OpenAcdClient getClientById(Integer clientId) {
        return getHibernateTemplate().load(OpenAcdClient.class, clientId);
    }

    private boolean isNameChanged(OpenAcdSkill skill) {
        return !getSkillById(skill.getId()).getName().equals(skill.getName());
    }

    private void checkForDuplicateName(OpenAcdSkill skill) {
        String skillName = skill.getName();
        OpenAcdSkill existingSkill = getSkillByName(skillName);
        if (existingSkill != null) {
            throw new UserException("&duplicate.skillName.error", existingSkill);
        }
    }

    private boolean isAtomChanged(OpenAcdSkill skill) {
        return !getSkillById(skill.getId()).getAtom().equals(skill.getAtom());
    }

    private void checkForDuplicateAtom(OpenAcdSkill skill) {
        String atom = skill.getAtom();
        OpenAcdSkill existingSkill = getSkillByAtom(atom);
        if (existingSkill != null) {
            throw new UserException("&duplicate.skillAtom.error", existingSkill);
        }
    }

    @Override
    public List<OpenAcdQueueGroup> getQueueGroups() {
        return getHibernateTemplate().loadAll(OpenAcdQueueGroup.class);
    }

    @Override
    public OpenAcdQueueGroup getQueueGroupById(Integer queueGroupId) {
        return getHibernateTemplate().load(OpenAcdQueueGroup.class, queueGroupId);
    }

    @Override
    public OpenAcdQueueGroup getQueueGroupByName(String queueGroupName) {
        List<OpenAcdQueueGroup> queueGroups = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_QUEUE_GROUP_WITH_NAME, VALUE, queueGroupName);
        return DataAccessUtils.singleResult(queueGroups);
    }

    @Override
    public void saveQueueGroup(OpenAcdQueueGroup queueGroup) {
        // check if queue group name is empty
        if (StringUtils.isBlank(queueGroup.getName())) {
            throw new UserException("&blank.queueGroupName.error");
        }
        // Check for duplicate names before saving the queue group
        if (queueGroup.isNew() || (!queueGroup.isNew() && isNameChanged(queueGroup))) {
            checkForDuplicateName(queueGroup);
        }

        if (!queueGroup.isNew()) {
            if (isNameChanged(queueGroup)) {
                // don't rename the default queue group
                OpenAcdQueueGroup defaultQueueGroup = getQueueGroupByName(GROUP_NAME_DEFAULT);
                if (defaultQueueGroup != null && defaultQueueGroup.getId().equals(queueGroup.getId())) {
                    throw new UserException("&msg.err.defaultQueueGroupRename");
                }
            }
            getHibernateTemplate().merge(queueGroup);
        } else {
            getHibernateTemplate().save(queueGroup);
        }
    }

    @Override
    public void deleteQueueGroup(OpenAcdQueueGroup group) {
        List<OpenAcdQueueGroup> groups = new LinkedList<OpenAcdQueueGroup>();
        if (group.getName().equals(GROUP_NAME_DEFAULT) || containsUsedQueues(group)) {
            throw new QueueGroupInUseException();
        } else {
            groups.add(group);
        }
        getHibernateTemplate().deleteAll(groups);
    }

    public final class QueueGroupInUseException extends UserException {
    }

    private boolean isNameChanged(OpenAcdQueueGroup queueGroup) {
        String oldName = getQueueGroupById(queueGroup.getId()).getName();
        queueGroup.setOldName(oldName);
        return !oldName.equals(queueGroup.getName());
    }

    private void checkForDuplicateName(OpenAcdQueueGroup queueGroup) {
        String queueGroupName = queueGroup.getName();
        OpenAcdQueueGroup existingQueueGroup = getQueueGroupByName(queueGroupName);
        if (existingQueueGroup != null) {
            throw new UserException("&duplicate.queueGroupName.error", queueGroupName);
        }
    }

    private boolean containsUsedQueues(OpenAcdQueueGroup group) {
        for (OpenAcdQueue queue : group.getQueues()) {
            if (isUsedByLine(OpenAcdLine.Q + queue.getName())) {
                return true;
            }
        }
        return false;
    }

    public List<OpenAcdQueue> getQueues() {
        return getHibernateTemplate().loadAll(OpenAcdQueue.class);
    }

    public OpenAcdQueue getQueueById(Integer queueId) {
        return getHibernateTemplate().load(OpenAcdQueue.class, queueId);
    }

    public OpenAcdQueue getQueueByName(String queueName) {
        List<OpenAcdQueue> queues = getHibernateTemplate().findByNamedQueryAndNamedParam(OPEN_ACD_QUEUE_WITH_NAME,
                VALUE, queueName);
        return DataAccessUtils.singleResult(queues);
    }

    @Override
    public void saveQueue(OpenAcdQueue queue) {
        // check if queue name is empty
        if (StringUtils.isBlank(queue.getName())) {
            throw new UserException("&blank.queueName.error");
        }
        // Check for duplicate names before saving the queue
        boolean nameChanged = !queue.isNew() && isNameChanged(queue);
        if (queue.isNew() || nameChanged) {
            checkForDuplicateName(queue);
        }

        // Check if the queue is associated with lines
        if (nameChanged) {
            checkLines(queue);
        }

        if (!queue.isNew()) {
            if (isNameChanged(queue)) {
                // don't rename the queue
                throw new UserException("&msg.err.queueRename");
            }
            getHibernateTemplate().merge(queue);
        } else {
            getHibernateTemplate().save(queue);
        }
    }

    private boolean isNameChanged(OpenAcdQueue queue) {
        String oldName = getQueueById(queue.getId()).getName();
        queue.setOldName(oldName);
        return !oldName.equals(queue.getName());
    }

    private void checkForDuplicateName(OpenAcdQueue queue) {
        String queueName = queue.getName();
        OpenAcdQueue existingQueue = getQueueByName(queueName);
        if (existingQueue != null) {
            throw new UserException("&duplicate.queueName.error", queueName);
        }
    }

    private void checkLines(OpenAcdQueue queue) {
        List<FreeswitchAction> actions = getActionsByData(OpenAcdLine.Q + queue.getOldName());
        if (actions.size() > 0) {
            for (FreeswitchAction action : actions) {
                action.setData(OpenAcdLine.Q + queue.getName());
                getHibernateTemplate().merge(action);
            }
            getHibernateTemplate().flush();
        }
    }

    @Override
    public void deleteQueue(OpenAcdQueue queue) {
        if (queue.getName().equals(DEFAULT_QUEUE) || isUsedByLine(OpenAcdLine.Q + queue.getName())) {
            throw new QueueInUseException();
        } else {
            OpenAcdQueueGroup group = queue.getGroup();
            group.removeQueue(queue);
            getHibernateTemplate().saveOrUpdate(group);
            getHibernateTemplate().delete(queue);
        }
    }

    public final class QueueInUseException extends UserException {
    }

    private boolean isUsedByLine(String data) {
        if (getActionsByData(data).size() > 0) {
            return true;
        }
        return false;
    }

    @Override
    public OpenAcdRecipeStep getRecipeStepById(Integer recipeStepId) {
        return getHibernateTemplate().load(OpenAcdRecipeStep.class, recipeStepId);
    }

    @Override
    public List<OpenAcdReleaseCode> getReleaseCodes() {
        return getHibernateTemplate().loadAll(OpenAcdReleaseCode.class);
    }

    @Override
    public OpenAcdReleaseCode getReleaseCodeById(Integer id) {
        return getHibernateTemplate().load(OpenAcdReleaseCode.class, id);
    }

    @Override
    public void saveReleaseCode(OpenAcdReleaseCode code) {
        // Check for duplicate labels
        if (code.isNew() || (!code.isNew() && isLabelChanged(code))) {
            checkForDuplicateLabel(code);
        }

        if (code.isNew()) {
            getHibernateTemplate().save(code);
        } else {
            getHibernateTemplate().merge(code);
        }
    }

    private boolean isLabelChanged(OpenAcdReleaseCode code) {
        return !getReleaseCodeById(code.getId()).getLabel().equals(code.getLabel());
    }

    private void checkForDuplicateLabel(OpenAcdReleaseCode code) {
        String labelCode = code.getLabel();
        OpenAcdReleaseCode existingCode = getReleaseCodeByLabel(labelCode);
        if (existingCode != null) {
            throw new UserException("&duplicate.codeLabel.error", existingCode);
        }
    }

    private OpenAcdReleaseCode getReleaseCodeByLabel(String label) {
        List<OpenAcdReleaseCode> codes = getHibernateTemplate()
                .findByNamedQueryAndNamedParam(OPEN_ACD_RELEASE_CODE_WITH_LABEL, VALUE, label);
        return DataAccessUtils.singleResult(codes);
    }

    @Override
    public void removeReleaseCodes(Collection<Integer> codesId) {
        List<OpenAcdReleaseCode> codes = new ArrayList<OpenAcdReleaseCode>();
        for (Integer id : codesId) {
            OpenAcdReleaseCode code = getReleaseCodeById(id);
            codes.add(code);
        }
        getDaoEventPublisher().publishDeleteCollection(codes);
        getHibernateTemplate().deleteAll(codes);
    }

    public void onSave(Object entity) {
        if (entity instanceof OpenAcdSettings) {
            OpenAcdSettings settings = (OpenAcdSettings) entity;
            m_replicationManager.replicateEntity(new OpenAcdLogConfigCommand(settings.getLogLevel(),
                    settings.getLogDir() + OpenAcdContext.OPENACD_LOG));
            m_replicationManager.replicateEntity(
                    new OpenAcdAgentWebConfigCommand(settings.isAgentWebUiEnabled(), settings.getAgentWebUiPort(),
                            settings.isAgentWebUiSSlEnabled(), settings.getAgentWebUiSSlPort()));
        }
        if (entity instanceof User) {
            User u = (User) entity;
            OpenAcdAgent agent = getAgentByUserId(u.getId());
            if (agent != null) {
                getDaoEventPublisher().publishSave(agent);
            }
        }
    }

    public void onDelete(Object entity) {
        if (entity instanceof User) {
            User user = (User) entity;
            OpenAcdAgent agent = getAgentByUser(user);
            if (agent != null) {
                // must manually de-associate group-agent
                agent.getGroup().removeAgent(agent);
                getDaoEventPublisher().publishDelete(agent);
                // do not call deleteAgent here b/c it will re-insert user into mongo
                // (we don't care about user-group association update since the user is deleted
                // anyway)
                getHibernateTemplate().delete(agent);
            }
        } else if (entity instanceof OpenAcdQueueGroup) {
            getHibernateTemplate().flush();
            OpenAcdQueueGroup qgr = (OpenAcdQueueGroup) entity;
            for (OpenAcdQueue q : qgr.getQueues()) {
                m_replicationManager.removeEntity(q);
            }
        } else if (entity instanceof OpenAcdAgentGroup) {
            OpenAcdAgentGroup aggr = (OpenAcdAgentGroup) entity;
            for (OpenAcdAgent agent : aggr.getAgents()) {
                m_replicationManager.removeEntity(agent);
            }
        } else if (entity instanceof OpenAcdSkillGroup) {
            getHibernateTemplate().flush();
            OpenAcdSkillGroup skillGroup = (OpenAcdSkillGroup) entity;
            for (OpenAcdSkill skill : skillGroup.getSkills()) {
                m_replicationManager.removeEntity(skill);
            }
        }
    }

    @Override
    public boolean setup(SetupManager manager) {
        String id = "init-openacd-commands";
        if (!manager.isTrue(id)) {
            OpenAcdCommand login = newOpenAcdCommand();
            FreeswitchCondition loginCondition = new FreeswitchCondition();
            loginCondition.setField(DESTINATION_NUMBER);
            loginCondition.setExpression("^*87$");
            login.setName("login");
            login.setDescription("Default login dial string");
            FreeswitchAction loginActionAnswer = new FreeswitchAction();
            loginActionAnswer.setApplication(ANSWER);
            FreeswitchAction loginActionErlang = new FreeswitchAction();
            loginActionErlang.setApplication(ERLANG_SENDMSG);
            loginActionErlang.setData(
                    new StringBuilder(AGENT_DP_LISTENER).append(m_locationsManager.getPrimaryLocation().getFqdn())
                            .append(" agent_login ${sip_from_user} pstn ${sip_from_uri}").toString());
            FreeswitchAction loginActionSleep = new FreeswitchAction();
            loginActionSleep.setApplication(SLEEP);
            loginActionSleep.setData(SLEEP_MS);
            FreeswitchAction loginActionHangup = new FreeswitchAction();
            loginActionHangup.setApplication(HANGUP);
            loginActionHangup.setData(NORMAL_CLEARING);
            loginCondition.addAction(loginActionAnswer);
            loginCondition.addAction(loginActionErlang);
            loginCondition.addAction(loginActionSleep);
            loginCondition.addAction(loginActionHangup);
            login.addCondition(loginCondition);
            saveExtension(login);

            OpenAcdCommand available = newOpenAcdCommand();
            FreeswitchCondition availableCondition = new FreeswitchCondition();
            availableCondition.setField(DESTINATION_NUMBER);
            availableCondition.setExpression("^*90$");
            available.setName("available");
            available.setDescription("Default available dial string");
            FreeswitchAction availableActionAnswer = new FreeswitchAction();
            availableActionAnswer.setApplication(ANSWER);
            FreeswitchAction availableActionErlang = new FreeswitchAction();
            availableActionErlang.setApplication(ERLANG_SENDMSG);
            availableActionErlang.setData(
                    new StringBuilder(AGENT_DP_LISTENER).append(m_locationsManager.getPrimaryLocation().getFqdn())
                            .append(" agent_available ${sip_from_user}").toString());
            FreeswitchAction availableActionSleep = new FreeswitchAction();
            availableActionSleep.setApplication(SLEEP);
            availableActionSleep.setData(SLEEP_MS);
            FreeswitchAction availableActionHangup = new FreeswitchAction();
            availableActionHangup.setApplication(HANGUP);
            availableActionHangup.setData(NORMAL_CLEARING);
            availableCondition.addAction(availableActionAnswer);
            availableCondition.addAction(availableActionErlang);
            availableCondition.addAction(availableActionSleep);
            availableCondition.addAction(availableActionHangup);
            available.addCondition(availableCondition);
            saveExtension(available);

            OpenAcdCommand release = newOpenAcdCommand();
            FreeswitchCondition releaseCondition = new FreeswitchCondition();
            releaseCondition.setField(DESTINATION_NUMBER);
            releaseCondition.setExpression("^*89$");
            release.setName("release");
            release.setDescription("Default release dial string");
            FreeswitchAction releaseActionAnswer = new FreeswitchAction();
            releaseActionAnswer.setApplication(ANSWER);
            FreeswitchAction releaseActionErlang = new FreeswitchAction();
            releaseActionErlang.setApplication(ERLANG_SENDMSG);
            releaseActionErlang.setData(
                    new StringBuilder(AGENT_DP_LISTENER).append(m_locationsManager.getPrimaryLocation().getFqdn())
                            .append(" agent_release ${sip_from_user}").toString());
            FreeswitchAction releaseActionSleep = new FreeswitchAction();
            releaseActionSleep.setApplication(SLEEP);
            releaseActionSleep.setData(SLEEP_MS);
            FreeswitchAction releaseActionHangup = new FreeswitchAction();
            releaseActionHangup.setApplication(HANGUP);
            releaseActionHangup.setData(NORMAL_CLEARING);
            releaseCondition.addAction(releaseActionAnswer);
            releaseCondition.addAction(releaseActionErlang);
            releaseCondition.addAction(releaseActionSleep);
            releaseCondition.addAction(releaseActionHangup);
            release.addCondition(releaseCondition);
            saveExtension(release);

            OpenAcdCommand logoff = newOpenAcdCommand();
            FreeswitchCondition logoffCondition = new FreeswitchCondition();
            logoffCondition.setField(DESTINATION_NUMBER);
            logoffCondition.setExpression("^*91$");
            logoff.setName("logoff");
            logoff.setDescription("Default logoff dial string");
            FreeswitchAction logoffActionAnswer = new FreeswitchAction();
            logoffActionAnswer.setApplication(ANSWER);
            FreeswitchAction logoffActionErlang = new FreeswitchAction();
            logoffActionErlang.setApplication(ERLANG_SENDMSG);
            logoffActionErlang.setData(
                    new StringBuilder(AGENT_DP_LISTENER).append(m_locationsManager.getPrimaryLocation().getFqdn())
                            .append(" agent_logoff ${sip_from_user}").toString());
            FreeswitchAction logoffActionSleep = new FreeswitchAction();
            logoffActionSleep.setApplication(SLEEP);
            logoffActionSleep.setData(SLEEP_MS);
            FreeswitchAction logoffActionHangup = new FreeswitchAction();
            logoffActionHangup.setApplication(HANGUP);
            logoffActionHangup.setData(NORMAL_CLEARING);
            logoffCondition.addAction(logoffActionAnswer);
            logoffCondition.addAction(logoffActionErlang);
            logoffCondition.addAction(logoffActionSleep);
            logoffCondition.addAction(logoffActionHangup);
            logoff.addCondition(logoffCondition);
            saveExtension(logoff);
            manager.setTrue(id);
        }

        // add default agent group
        if (getAgentGroupByName(GROUP_NAME_DEFAULT) == null) {
            String addDefaultAgentGroup = "add-default-agent-group";
            if (!manager.isTrue(addDefaultAgentGroup)) {
                OpenAcdAgentGroup defaultAgentGroup = new OpenAcdAgentGroup();
                defaultAgentGroup.setName(GROUP_NAME_DEFAULT);
                defaultAgentGroup.setDescription("Default agent group");
                saveAgentGroup(defaultAgentGroup);
                manager.setTrue(addDefaultAgentGroup);
            }
        }

        return true;
    }

    public void setAliasManager(AliasManager aliasManager) {
        m_aliasManager = aliasManager;
    }

    @Override
    public void resync() {
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        m_beanFactory = (ListableBeanFactory) beanFactory;
    }

    public void setFeatureManager(FeatureManager featureManager) {
        m_featureManager = featureManager;
    }

    public void setSettingsDao(BeanWithSettingsDao<OpenAcdSettings> settingsDao) {
        m_settingsDao = settingsDao;
    }

    public void setCoreContext(CoreContext coreContext) {
        m_coreContext = coreContext;
    }

    @Override
    public Collection<ProcessDefinition> getProcessDefinitions(SnmpManager manager, Location location) {
        if (!manager.getFeatureManager().isFeatureEnabled(FEATURE, location)) {

            return null;
        }
        ProcessDefinition def = ProcessDefinition.sysvByRegex(OPEN_ACD_PROCESS_NAME,
                "/bin/" + OPEN_ACD_PROCESS_NAME);
        return Collections.singleton(def);
    }

    public void setReplicationManager(ReplicationManager replicationManager) {
        m_replicationManager = replicationManager;
    }

    @Override
    public void getBundleFeatures(FeatureManager featureManager, Bundle b) {
        if (b == Bundle.CALL_CENTER) {
            b.addFeature(FEATURE);
        }
    }

    @Override
    public void featureChangePrecommit(FeatureManager manager, FeatureChangeValidator validator) {
        validator.requiredOnSameHost(FEATURE, FreeswitchFeature.FEATURE);
    }

    @Override
    public void featureChangePostcommit(FeatureManager manager, FeatureChangeRequest request) {
    }

    public void setSettingDao(SettingDao settingDao) {
        m_settingDao = settingDao;
    }

    public void setLocationsManager(LocationsManager locationsManager) {
        m_locationsManager = locationsManager;
    }

}