📄 workgroup.java
字号:
/**
* $RCSfile$
* $Revision$
* $Date: 2006-08-07 21:12:21 -0700 (Mon, 07 Aug 2006) $
*
* Copyright (C) 2004-2008 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution, or a commercial license
* agreement with Jive.
*/
package org.jivesoftware.xmpp.workgroup;
import org.jivesoftware.openfire.fastpath.util.TaskEngine;
import org.jivesoftware.xmpp.workgroup.chatbot.Chatbot;
import org.jivesoftware.xmpp.workgroup.dispatcher.BasicDispatcherInfo;
import org.jivesoftware.xmpp.workgroup.dispatcher.DispatcherInfoProvider;
import org.jivesoftware.xmpp.workgroup.event.WorkgroupEventDispatcher;
import org.jivesoftware.xmpp.workgroup.interceptor.InterceptorManager;
import org.jivesoftware.xmpp.workgroup.interceptor.PacketRejectedException;
import org.jivesoftware.xmpp.workgroup.interceptor.RoomInterceptorManager;
import org.jivesoftware.xmpp.workgroup.interceptor.WorkgroupInterceptorManager;
import org.jivesoftware.xmpp.workgroup.request.InvitationRequest;
import org.jivesoftware.xmpp.workgroup.request.Request;
import org.jivesoftware.xmpp.workgroup.request.TransferRequest;
import org.jivesoftware.xmpp.workgroup.request.UserRequest;
import org.jivesoftware.xmpp.workgroup.routing.RoutingManager;
import org.jivesoftware.xmpp.workgroup.spi.BasicRequestFilterFactory;
import org.jivesoftware.xmpp.workgroup.spi.JiveLiveProperties;
import org.jivesoftware.xmpp.workgroup.spi.dispatcher.DbDispatcherInfoProvider;
import org.jivesoftware.xmpp.workgroup.utils.DbWorkgroup;
import org.jivesoftware.xmpp.workgroup.utils.FastpathConstants;
import org.jivesoftware.xmpp.workgroup.utils.ModelUtil;
import org.dom4j.Element;
import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.database.SequenceManager;
import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.util.FastDateFormat;
import org.jivesoftware.util.NotFoundException;
import org.jivesoftware.util.StringUtils;
import org.xmpp.component.ComponentManagerFactory;
import org.xmpp.muc.*;
import org.xmpp.packet.*;
import java.net.URL;
import java.sql.*;
import java.sql.Date;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* <p>Database implementation of a workgroup agent.</p>
* <p>The current implementation doesn't store any meta data about an agent.</p>
*
* @author Derek DeMoro
*/
public class Workgroup {
private static final String LOAD_WORKGROUP =
"SELECT jid, displayName, description, status, modes, creationDate, " +
"modificationDate, maxchats, minchats, offerTimeout, requestTimeout, " +
"schedule FROM fpWorkgroup WHERE workgroupID=?";
private static final String UPDATE_WORKGRUP =
"UPDATE fpWorkgroup SET displayName=?,description=?,status=?,modes=?," +
"creationDate=?,modificationDate=?,maxchats=?,minchats=?,offerTimeout=?," +
"requestTimeout=?,schedule=? WHERE workgroupID=?";
private static final String LOAD_QUEUES =
"SELECT queueID FROM fpQueue WHERE workgroupID=?";
private static final String CREATE_QUEUE =
"INSERT into fpQueue (queueID,workgroupID,name,priority,maxchats,minchats," +
"overflow,backupQueue) VALUES (?,?,?,?,?,?,0,0)";
private static final String DELETE_QUEUE =
"DELETE FROM fpQueue WHERE queueID=?";
private static final String DELETE_QUEUE_PROPS =
"DELETE FROM fpDispatcherProp WHERE ownerID=?";
private static final FastDateFormat UTC_FORMAT = FastDateFormat
.getInstance("yyyyMMdd'T'HH:mm:ss", TimeZone.getTimeZone("GMT+0"));
/**
* Flag indicating if the workgroup should accept new requests.
*/
private boolean open;
/**
* Flag indicating if the workgroup is following its schedule.
*/
private boolean followSchedule;
/**
* The schedule the workgroup follows when followSchedule is true.
*/
private Schedule schedule;
/**
* The description for the workgroup (used in the admin UI only - lazily loaded).
*/
private String description = null;
private Date creationDate;
private Date modDate;
private long offerTimeout = -1;
private long requestTimeout = -1;
private int maxChats;
private int minChats;
/**
* Convenience copy of the WorkgroupManager's agent manager (similar to deliverer convenience).
*/
private AgentManager agentManager;
/**
* Used when creating queues.
*/
private DispatcherInfoProvider dispatcherInfoProvider = new DbDispatcherInfoProvider();
/**
* Factory to produce request filters.
*/
private RequestFilterFactory requestFilterFactory = new BasicRequestFilterFactory();
/**
* Chatbot that will handle all the messages sent to this workgroup. If no chatbot was
* defined then messages will not be answered.
*/
private Chatbot chatbot;
// ------------------------------------------------------------------------
// Packet handlers
// ------------------------------------------------------------------------
private WorkgroupPresence workgroupPresenceHandler;
private WorkgroupIQHandler workgroupIqHandler;
private MessageHandler messageHandler;
private Map<Long, RequestQueue> queues = new HashMap<Long, RequestQueue>();
/**
* Custom properties for the workgroup.
*/
private JiveLiveProperties properties;
private String workgroupName;
private String displayName;
private long id;
/**
* Keep the conversation transcript of each room that this workgroup has created. Rooms are
* destroyed after the support session is over. Therefore, this variable keeps track of the
* chat transcripts of the current support sessions.
*/
private Map<String, Map<Packet, java.util.Date>> transcripts =
new ConcurrentHashMap<String, Map<Packet, java.util.Date>>();
/**
* Keep a counter of occupants for each room that the workgroup created. The
* occupants will be updated every time a presence packet is received from the
* room. When all the occupants (except the workgroup) has left the room then the
* workgroup will leave the room thus destroying it.
*/
private Map<String, Set<String>> occupantsCounter = new ConcurrentHashMap<String, Set<String>>();
/**
* Keep a list of the requests for which a room was created and still hasn't been destroyed.
* A new entry is added when sending room invitations and the same entry will be removed when
* the room is destroyed.
* Key: sessionID (ie. roomID), value: Request
*/
private Map<String, UserRequest> requests = new ConcurrentHashMap<String, UserRequest>();
public Workgroup(long id, AgentManager agentManager) {
this.id = id;
this.agentManager = agentManager;
// Initialize standalone runtime fields
// Initialize runtime fields that only save reference to the workgroup
workgroupPresenceHandler = new WorkgroupPresence(this);
workgroupIqHandler = new WorkgroupIQHandler();
workgroupIqHandler.setWorkgroup(this);
messageHandler = new MessageHandler(this);
// Load settings from database
loadWorkgroup();
loadQueues();
// Send presence to let everyone know you're available/unavailable
broadcastPresence();
broadcastQueuesStatus();
}
/**
* Broadcasts the presence of the workgroup to all users and agents of the workgroup.
*/
public void broadcastPresence() {
// TODO Send presence from the workgroup to the server
TaskEngine.getInstance().submit(new Runnable() {
public void run() {
try {
// Send the status of this workgroup to all the connected agents
Collection<AgentSession> sessions = getAgentSessions();
for (AgentSession session : sessions) {
workgroupPresenceHandler.sendPresence(session.getJID());
}
// Get all the users' JID in a Set since a user may be having a chat with
// many agents
Set<JID> jids = new HashSet<JID>();
for (AgentSession session : sessions) {
jids.addAll(session.getUsersJID(Workgroup.this));
}
// Send the status to all the users that are having a chat with agents of
// the workgroup
for (JID jid : jids) {
workgroupPresenceHandler.sendPresence(jid);
}
}
catch (Exception e) {
ComponentManagerFactory.getComponentManager().getLog().error("Error broadcasting workgroup presence", e);
}
}
});
}
/**
* Broadcasts the presence of all the queues in the workgroup to all agents.
*/
public void broadcastQueuesStatus() {
TaskEngine.getInstance().submit(new Runnable() {
public void run() {
try {
// Send status of each queue to all the connected agents
for (RequestQueue requestQueue : getRequestQueues()) {
requestQueue.getAgentSessionList().broadcastQueueStatus(requestQueue);
}
}
catch (Exception e) {
ComponentManagerFactory.getComponentManager().getLog().error("Error broadcasting status of queues", e);
}
}
});
}
/**
* Return true if the Workgroup is available to take requests.
*
* @return true if the workgroup is available to take requests.
*/
public boolean isAvailable() {
for (RequestQueue requestQueue : getRequestQueues()) {
Presence presence = requestQueue.getDetailedStatusPresence();
if (presence.getType() == null) {
return true;
}
}
return false;
}
// ###############################################################################
// Request queue management
// ###############################################################################
public RequestQueue createRequestQueue(String name) throws UnauthorizedException {
RequestQueue queue = null;
long queueID = SequenceManager.nextID(FastpathConstants.WORKGROUP_QUEUE);
// This should probably be moved into a queue manager class
// First create the queue, then the dispatcher,
// then the queue implementation object
boolean queueCreated = createQueue(queueID, name);
if (queueCreated) {
BasicDispatcherInfo info = new BasicDispatcherInfo(this, queueID,
"Round Robin Dispatcher", "None", -1, -1);
try {
dispatcherInfoProvider.insertDispatcherInfo(queueID, info);
queue = new RequestQueue(this, queueID);
}
catch (UserAlreadyExistsException e) {
ComponentManagerFactory.getComponentManager().getLog().error(e);
}
}
else {
throw new UnauthorizedException();
}
queues.put(queueID, queue);
return queue;
}
public void deleteRequestQueue(RequestQueue queue) {
queues.remove(queue.getID());
// Delete the RequestQueue from the database
if (deleteQueue(queue.getID())) {
// Stop processing requests in this queue
queue.shutdown();
// Remove the agents from this queue
for (Agent agent : queue.getMembers()) {
queue.removeMember(agent);
}
// Remove the agent groups from this queue
for (Group group : queue.getGroups()) {
queue.removeGroup(group);
}
try {
// Delete the dispatcher of this queue from the database
dispatcherInfoProvider.deleteDispatcherInfo(queue.getID());
}
catch (UnauthorizedException e) {
ComponentManagerFactory.getComponentManager().getLog().error(e);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -