/* * Copyright (C) 2004-2008 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.xmpp.workgroup.spi.routers; import java.util.List; import java.util.Map; import org.jivesoftware.xmpp.workgroup.DbProperties; import org.jivesoftware.xmpp.workgroup.RequestQueue; import org.jivesoftware.xmpp.workgroup.Workgroup; import org.jivesoftware.xmpp.workgroup.request.UserRequest; import org.jivesoftware.xmpp.workgroup.routing.RequestRouter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * <p>Routes requests to the queue with the most matching meta-data.</p> * * @author Derek DeMoro */ public class MetaDataRouter extends RequestRouter { private static final Logger Log = LoggerFactory.getLogger(MetaDataRouter.class); public MetaDataRouter() { } public String getTitle(){ return "Live Assistant Metadata Router"; } public String getDescription(){ return "Used for routing to the best possible queue based on it's metadata name-value pairs in the queue."; } @Override public boolean isConfigurable(){ return false; } @Override public boolean handleRequest(Workgroup workgroup, UserRequest request) { boolean success = false; Map<String,List<String>> metaData = request.getMetaData(); if (metaData != null) { // Route to queue with most matching meta-data RequestQueue bestQueue = routeNoOverflow(workgroup, metaData); if (bestQueue != null) { setRoutingQueue(bestQueue.getID()); success = true; } } return success; } private RequestQueue routeNoOverflow(Workgroup workgroup, Map<String,List<String>> metaData) { RequestQueue bestQueue = null; int bestMatch = -1; int currentMatch; for (RequestQueue requestQueue : workgroup.getRequestQueues()) { // Skip queues that doesn't have agents at the moment if (!requestQueue.isOpened()) { continue; } int overflowValue = requestQueue.getOverflowType().ordinal(); switch (overflowValue) { case 1: // random - route to best that's available // (or none if no queues are available) if (requestQueue.getAgentSessionList().containsAvailableAgents()) { currentMatch = calculateMatchScore(requestQueue, metaData); if (currentMatch > bestMatch) { bestQueue = requestQueue; bestMatch = currentMatch; } } break; case 2: // backup - route to best or best's backup currentMatch = calculateMatchScore(requestQueue, metaData); if (currentMatch > bestMatch) { if (!requestQueue.getAgentSessionList().containsAvailableAgents() && requestQueue.getBackupQueue() != null) { // Route to backup queue if no agents available and // backup queue set bestQueue = requestQueue.getBackupQueue(); } else { bestQueue = requestQueue; } bestMatch = currentMatch; } break; default: // none - route to best currentMatch = calculateMatchScore(requestQueue, metaData); if (currentMatch > bestMatch) { bestQueue = requestQueue; bestMatch = currentMatch; } } } return bestQueue; } /** * <p>Calculates the match score between the queue's properties and the * given info metadata</p> * <p/> * <p>Matching is done by simple comparison of the metadata name value * pairs, and the property name value pairs of the queue. The total * number of matches found is the match score.</p> * * @param queue The queue to inspect for properties * @param metaData The metada to locate name value pairs * @return The number of matches found */ private int calculateMatchScore(RequestQueue queue, Map<String,List<String>> metaData) { int currentMatch = 0; try { DbProperties queueProps = queue.getProperties(); for (String name : metaData.keySet()) { List<String> values = metaData.get(name); String queueProp = queueProps.getProperty(name); for (String value : values) { if (queueProp != null && queueProp.equalsIgnoreCase(value)) { currentMatch++; break; } } } } catch (Exception e) { Log.error(e.getMessage(), e); } return currentMatch; } }