📄 roundrobindispatcher.java
字号:
/**
* <p>Locate the next 'best' agent to receive an offer.</p>
* <p>Routing is based on show-status, max-chats, and who has
* already rejected the offer.
* show status is ranked from most available to least:
* chat, default (no show status), away,
* and xa. A show status of dnd indicates no offers should be routed to an agent.
* The general algorithm is:</p>
* <ul>
* <li>Mark the current position.</li>
* <li>Start iterating around the circular queue until all agents
* have been considered. For each agent:
* <ul>
* <li>Skip if session is null. Should only occur if no agents are in the list.</li>
* <li>Skip if session show state is DND. Never route to agents that are dnd.</li>
* <li>Skip if session current-chats is equal to or higher than max-chats.</li>
* <li>Replace current best if:
* <ul>
* <li>No current best. Any agent is better than none.</li>
* <li>If session hasn't rejected offer but current best has.</li>
* <li>If both session and current best have not rejected the
* offer and session show-status is higher.</li>
* <li>If both session and current best have rejected offer and
* session show-status is higher.</li>
* </ul></li>
* </ul></li>
* </li>
*
* @param initialAgent the initial agent requested by the user.
* @param ignoreAgent agent that should not be considered as available.
* @param offer the offer about to be sent to the best available agent.
* @return the best agent.
*/
private AgentSession getBestNextAgent(String initialAgent, String ignoreAgent, Offer offer) {
AgentSession bestSession;
// Look for specified agent in agent list
if (initialAgent != null) {
final AgentSessionList agentSessionList = queue.getAgentSessionList();
for (AgentSession agentSession : agentSessionList.getAgentSessions()) {
String sessionAgent = agentSession.getAgent().getAgentJID().toBareJID();
boolean match = sessionAgent.startsWith(initialAgent.toLowerCase());
Workgroup workgroup = offer.getRequest().getWorkgroup();
if (agentSession.isAvailableToChat() &&
agentSession.getCurrentChats(workgroup) < agentSession.getMaxChats(workgroup) && match) {
bestSession = agentSession;
// Log debug trace
logger.debug("RR - Initial agent: " + bestSession.getJID() +
" will receive offer for request: " +
offer.getRequest());
return bestSession;
}
}
}
// Let's iterate through each agent and check availability
final AgentSessionList agentSessionList = queue.getAgentSessionList();
final List<AgentSession> possibleSessions = new ArrayList<AgentSession>();
for (AgentSession agentSession : agentSessionList.getAgentSessions()) {
String sessionAgent = agentSession.getAgent().getAgentJID().toBareJID();
boolean ignore = ignoreAgent != null && sessionAgent.startsWith(ignoreAgent.toLowerCase());
if (!ignore && validateAgent(agentSession, offer)) {
possibleSessions.add(agentSession);
}
}
// Select the best agent from the list of possible agents
if (possibleSessions.size() > 0) {
AgentSession s = agentSelector.bestAgentFrom(possibleSessions, offer);
// Log debug trace
logger.debug("RR - Agent SELECTED: " + s.getJID() +
" for receiving offer for request: " +
offer.getRequest());
return s;
}
return null;
}
/**
* Returns true if the agent session may receive an offer. An agent session may receive new
* offers if:
*
* 1) the presence status of the agent allows to receive offers
* 2) the maximum of chats has not been reached for the agent
* 3) the agent has not rejected the offer before
* 4) the agent does not have to answer a previuos offer
*
* @param session the session to check if it may receive an offer
* @param offer the offer to send.
* @return true if the agent session may receive an offer.
*/
private boolean validateAgent(AgentSession session, Offer offer) {
if (agentSelector.validateAgent(session, offer)) {
// Log debug trace
logger.debug("RR - Agent: " + session.getJID() +
" MAY receive offer for request: " +
offer.getRequest());
return true;
}
// Log debug trace
logger.debug("RR - Agent: " + session.getJID() +
" MAY NOT receive offer for request: " +
offer.getRequest());
return false;
}
/**
* <p>Generate the agents offer list.</p>
*/
private void fillAgentsList() {
AgentSessionList agentSessionList = queue.getAgentSessionList();
agentSessionList.addAgentSessionListener(this);
for (AgentSession agentSession : agentSessionList.getAgentSessions()) {
if (!agentList.contains(agentSession)) {
agentList.add(agentSession);
}
}
}
/**
* Returns the max number of times a request may overflow. Once the request has exceded this
* number it will be cancelled. This limit avoids infinite overflow loops.
*
* @return the max number of times a request may overflow.
*/
private long getOverflowTimes() {
return JiveGlobals.getIntProperty("xmpp.live.request.overflow", 3);
}
/**
* Returns the number of milliseconds to wait until expiring an agent rejection.
*
* @return the number of milliseconds to wait until expiring an agent rejection.
*/
private long getAgentRejectionTimeout() {
return JiveGlobals.getIntProperty("xmpp.live.rejection.timeout", 20000);
}
public void notifySessionAdded(AgentSession session) {
if (!agentList.contains(session)) {
agentList.add(session);
}
}
public void notifySessionRemoved(AgentSession session) {
agentList.remove(session);
for (Offer offer : offers) {
offer.reject(session);
}
}
public DispatcherInfo getDispatcherInfo() {
return info;
}
public void setDispatcherInfo(DispatcherInfo info) throws UnauthorizedException {
try {
infoProvider.updateDispatcherInfo(queue.getID(), info);
this.info = info;
}
catch (NotFoundException e) {
logger.error(e);
}
catch (UnsupportedOperationException e) {
logger.error(e);
}
}
public int getOfferCount() {
return offers.size();
}
public Iterator getOffers() {
return offers.iterator();
}
public Iterator getOffers(WorkgroupResultFilter filter) {
return filter.filter(offers.iterator());
}
public String getProperty(String name) {
return properties.getProperty(name);
}
public void setProperty(String name, String value) throws UnauthorizedException {
properties.setProperty(name, value);
}
public void deleteProperty(String name) throws UnauthorizedException {
properties.deleteProperty(name);
}
public Collection<String> getPropertyNames() {
return properties.getPropertyNames();
}
public AgentSelector getAgentSelector() {
return agentSelector;
}
public void setAgentSelector(AgentSelector agentSelector) {
this.agentSelector = agentSelector;
// Delete all agentSelectorproperties.
try {
for (String property : getPropertyNames()) {
if (property.startsWith("agentSelector")) {
deleteProperty(property);
}
}
}
catch (Exception e) {
logger.error(e);
}
// Save the agentSelectoras a property of the dispatcher
try {
Map<String, String> propertyMap = getPropertiesMap(agentSelector, "agentSelector.");
for (Map.Entry<String, String> entry : propertyMap.entrySet()) {
setProperty(entry.getKey(), entry.getValue());
}
}
catch (Exception e) {
logger.error(e);
}
}
private Map<String, String> getPropertiesMap(AgentSelector agentSelector, String context) {
// Build the properties map that will be saved later
Map<String, String> propertyMap = new HashMap<String, String>();
// Write out class name
propertyMap.put(context + "className", agentSelector.getClass().getName());
// Write out all properties
Map<String, String> props = BeanUtils.getProperties(agentSelector);
for (Map.Entry<String, String> entry : props.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if (value != null && !"".equals(value)) {
propertyMap.put(context + "properties." + name, value);
}
}
return propertyMap;
}
private void loadAgentSelector() {
try {
String context = "agentSelector.";
String className = getProperty(context + "className");
if (className == null) {
// Do nothing and use the BasicAgentSelector
return;
}
Class agentSelectorClass = loadClass(className);
agentSelector = (AgentSelector) agentSelectorClass.newInstance();
// Load properties.
Collection<String> props = getChildrenPropertyNames(context + "properties", getPropertyNames());
Map<String, String> agentSelectorProps = new HashMap<String, String>();
for (String key : props) {
String value = getProperty(key);
// Get the bean property name, which is everything after the last '.' in the
// xml property name.
agentSelectorProps.put(key.substring(key.lastIndexOf(".")+1), value);
}
// Set properties on the bean
BeanUtils.setProperties(agentSelector, agentSelectorProps);
}
catch (Exception e) {
logger.error(e);
}
}
private Class loadClass(String className) throws ClassNotFoundException {
try {
return ClassUtils.forName(className);
}
catch (ClassNotFoundException e) {
return this.getClass().getClassLoader().loadClass(className);
}
}
/**
* Returns a child property names given a parent and an Iterator of property names.
*
* @param parent parent property name.
* @param properties all property names to search.
* @return an Iterator of child property names.
*/
private static Collection<String> getChildrenPropertyNames(String parent, Collection<String> properties) {
List<String> results = new ArrayList<String>();
for (String name : properties) {
if (name.startsWith(parent) && !name.equals(parent)) {
results.add(name);
}
}
return results;
}
public void shutdown() {
// Do nothing
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -