mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2025-12-06 13:11:08 +01:00
Adding workgroup API (SMACK-185).
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@7400 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
939feb9017
commit
fe545abeae
64 changed files with 9744 additions and 0 deletions
138
source/org/jivesoftware/smackx/workgroup/agent/Agent.java
Normal file
138
source/org/jivesoftware/smackx/workgroup/agent/Agent.java
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import org.jivesoftware.smackx.workgroup.packet.AgentInfo;
|
||||
import org.jivesoftware.smackx.workgroup.packet.AgentWorkgroups;
|
||||
import org.jivesoftware.smack.PacketCollector;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.PacketIDFilter;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* The <code>Agent</code> class is used to represent one agent in a Workgroup Queue.
|
||||
*
|
||||
* @author Derek DeMoro
|
||||
*/
|
||||
public class Agent {
|
||||
private XMPPConnection connection;
|
||||
private String workgroupJID;
|
||||
|
||||
public static Collection getWorkgroups(String serviceJID, String agentJID, XMPPConnection connection) throws XMPPException {
|
||||
AgentWorkgroups request = new AgentWorkgroups(agentJID);
|
||||
request.setTo(serviceJID);
|
||||
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
|
||||
// Send the request
|
||||
connection.sendPacket(request);
|
||||
|
||||
AgentWorkgroups response = (AgentWorkgroups)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
return response.getWorkgroups();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an Agent.
|
||||
*/
|
||||
Agent(XMPPConnection connection, String workgroupJID) {
|
||||
this.connection = connection;
|
||||
this.workgroupJID = workgroupJID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the agents JID
|
||||
*
|
||||
* @return - the agents JID.
|
||||
*/
|
||||
public String getUser() {
|
||||
return connection.getUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the agents name.
|
||||
*
|
||||
* @return - the agents name.
|
||||
*/
|
||||
public String getName() throws XMPPException {
|
||||
AgentInfo agentInfo = new AgentInfo();
|
||||
agentInfo.setType(IQ.Type.GET);
|
||||
agentInfo.setTo(workgroupJID);
|
||||
agentInfo.setFrom(getUser());
|
||||
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(agentInfo.getPacketID()));
|
||||
// Send the request
|
||||
connection.sendPacket(agentInfo);
|
||||
|
||||
AgentInfo response = (AgentInfo)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
return response.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the name of the agent in the server. The server may have this functionality
|
||||
* disabled for all the agents or for this agent in particular. If the agent is not
|
||||
* allowed to change his name then an exception will be thrown with a service_unavailable
|
||||
* error code.
|
||||
*
|
||||
* @param newName the new name of the agent.
|
||||
* @throws XMPPException if the agent is not allowed to change his name or no response was
|
||||
* obtained from the server.
|
||||
*/
|
||||
public void setName(String newName) throws XMPPException {
|
||||
AgentInfo agentInfo = new AgentInfo();
|
||||
agentInfo.setType(IQ.Type.SET);
|
||||
agentInfo.setTo(workgroupJID);
|
||||
agentInfo.setFrom(getUser());
|
||||
agentInfo.setName(newName);
|
||||
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(agentInfo.getPacketID()));
|
||||
// Send the request
|
||||
connection.sendPacket(agentInfo);
|
||||
|
||||
IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
386
source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java
Normal file
386
source/org/jivesoftware/smackx/workgroup/agent/AgentRoster.java
Normal file
|
|
@ -0,0 +1,386 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import org.jivesoftware.smackx.workgroup.packet.AgentStatus;
|
||||
import org.jivesoftware.smackx.workgroup.packet.AgentStatusRequest;
|
||||
import org.jivesoftware.smack.PacketListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.filter.PacketFilter;
|
||||
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Manges information about the agents in a workgroup and their presence.
|
||||
*
|
||||
* @author Matt Tucker
|
||||
* @see AgentSession#getAgentRoster()
|
||||
*/
|
||||
public class AgentRoster {
|
||||
|
||||
private static final int EVENT_AGENT_ADDED = 0;
|
||||
private static final int EVENT_AGENT_REMOVED = 1;
|
||||
private static final int EVENT_PRESENCE_CHANGED = 2;
|
||||
|
||||
private XMPPConnection connection;
|
||||
private String workgroupJID;
|
||||
private List entries;
|
||||
private List listeners;
|
||||
private Map presenceMap;
|
||||
// The roster is marked as initialized when at least a single roster packet
|
||||
// has been recieved and processed.
|
||||
boolean rosterInitialized = false;
|
||||
|
||||
/**
|
||||
* Constructs a new AgentRoster.
|
||||
*
|
||||
* @param connection an XMPP connection.
|
||||
*/
|
||||
AgentRoster(XMPPConnection connection, String workgroupJID) {
|
||||
this.connection = connection;
|
||||
this.workgroupJID = workgroupJID;
|
||||
entries = new ArrayList();
|
||||
listeners = new ArrayList();
|
||||
presenceMap = new HashMap();
|
||||
// Listen for any roster packets.
|
||||
PacketFilter rosterFilter = new PacketTypeFilter(AgentStatusRequest.class);
|
||||
connection.addPacketListener(new AgentStatusListener(), rosterFilter);
|
||||
// Listen for any presence packets.
|
||||
connection.addPacketListener(new PresencePacketListener(),
|
||||
new PacketTypeFilter(Presence.class));
|
||||
|
||||
// Send request for roster.
|
||||
AgentStatusRequest request = new AgentStatusRequest();
|
||||
request.setTo(workgroupJID);
|
||||
connection.sendPacket(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the entire roster from the server. This is an asynchronous operation,
|
||||
* which means the method will return immediately, and the roster will be
|
||||
* reloaded at a later point when the server responds to the reload request.
|
||||
*/
|
||||
public void reload() {
|
||||
AgentStatusRequest request = new AgentStatusRequest();
|
||||
request.setTo(workgroupJID);
|
||||
connection.sendPacket(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a listener to this roster. The listener will be fired anytime one or more
|
||||
* changes to the roster are pushed from the server.
|
||||
*
|
||||
* @param listener an agent roster listener.
|
||||
*/
|
||||
public void addListener(AgentRosterListener listener) {
|
||||
synchronized (listeners) {
|
||||
if (!listeners.contains(listener)) {
|
||||
listeners.add(listener);
|
||||
|
||||
// Fire events for the existing entries and presences in the roster
|
||||
for (Iterator it = getAgents().iterator(); it.hasNext();) {
|
||||
String jid = (String)it.next();
|
||||
// Check again in case the agent is no longer in the roster (highly unlikely
|
||||
// but possible)
|
||||
if (entries.contains(jid)) {
|
||||
// Fire the agent added event
|
||||
listener.agentAdded(jid);
|
||||
Map userPresences = (Map)presenceMap.get(jid);
|
||||
if (userPresences != null) {
|
||||
Iterator presences = userPresences.values().iterator();
|
||||
while (presences.hasNext()) {
|
||||
// Fire the presence changed event
|
||||
listener.presenceChanged((Presence)presences.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a listener from this roster. The listener will be fired anytime one or more
|
||||
* changes to the roster are pushed from the server.
|
||||
*
|
||||
* @param listener a roster listener.
|
||||
*/
|
||||
public void removeListener(AgentRosterListener listener) {
|
||||
synchronized (listeners) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a count of all agents in the workgroup.
|
||||
*
|
||||
* @return the number of agents in the workgroup.
|
||||
*/
|
||||
public int getAgentCount() {
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all agents (String JID values) in the workgroup.
|
||||
*
|
||||
* @return all entries in the roster.
|
||||
*/
|
||||
public Set getAgents() {
|
||||
Set agents = new HashSet();
|
||||
synchronized (entries) {
|
||||
for (Iterator i = entries.iterator(); i.hasNext();) {
|
||||
agents.add(i.next());
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(agents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified XMPP address is an agent in the workgroup.
|
||||
*
|
||||
* @param jid the XMPP address of the agent (eg "jsmith@example.com"). The
|
||||
* address can be in any valid format (e.g. "domain/resource", "user@domain"
|
||||
* or "user@domain/resource").
|
||||
* @return true if the XMPP address is an agent in the workgroup.
|
||||
*/
|
||||
public boolean contains(String jid) {
|
||||
if (jid == null) {
|
||||
return false;
|
||||
}
|
||||
synchronized (entries) {
|
||||
for (Iterator i = entries.iterator(); i.hasNext();) {
|
||||
String entry = (String)i.next();
|
||||
if (entry.toLowerCase().equals(jid.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the presence info for a particular agent, or <tt>null</tt> if the agent
|
||||
* is unavailable (offline) or if no presence information is available.<p>
|
||||
*
|
||||
* @param user a fully qualified xmpp JID. The address could be in any valid format (e.g.
|
||||
* "domain/resource", "user@domain" or "user@domain/resource").
|
||||
* @return the agent's current presence, or <tt>null</tt> if the agent is unavailable
|
||||
* or if no presence information is available..
|
||||
*/
|
||||
public Presence getPresence(String user) {
|
||||
String key = getPresenceMapKey(user);
|
||||
Map userPresences = (Map)presenceMap.get(key);
|
||||
if (userPresences == null) {
|
||||
Presence presence = new Presence(Presence.Type.unavailable);
|
||||
presence.setFrom(user);
|
||||
return presence;
|
||||
}
|
||||
else {
|
||||
// Find the resource with the highest priority
|
||||
// Might be changed to use the resource with the highest availability instead.
|
||||
Iterator it = userPresences.keySet().iterator();
|
||||
Presence p;
|
||||
Presence presence = null;
|
||||
|
||||
while (it.hasNext()) {
|
||||
p = (Presence)userPresences.get(it.next());
|
||||
if (presence == null){
|
||||
presence = p;
|
||||
}
|
||||
else {
|
||||
if (p.getPriority() > presence.getPriority()) {
|
||||
presence = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (presence == null) {
|
||||
presence = new Presence(Presence.Type.unavailable);
|
||||
presence.setFrom(user);
|
||||
return presence;
|
||||
}
|
||||
else {
|
||||
return presence;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key to use in the presenceMap for a fully qualified xmpp ID. The roster
|
||||
* can contain any valid address format such us "domain/resource", "user@domain" or
|
||||
* "user@domain/resource". If the roster contains an entry associated with the fully qualified
|
||||
* xmpp ID then use the fully qualified xmpp ID as the key in presenceMap, otherwise use the
|
||||
* bare address. Note: When the key in presenceMap is a fully qualified xmpp ID, the
|
||||
* userPresences is useless since it will always contain one entry for the user.
|
||||
*
|
||||
* @param user the fully qualified xmpp ID, e.g. jdoe@example.com/Work.
|
||||
* @return the key to use in the presenceMap for the fully qualified xmpp ID.
|
||||
*/
|
||||
private String getPresenceMapKey(String user) {
|
||||
String key = user;
|
||||
if (!contains(user)) {
|
||||
key = StringUtils.parseBareAddress(user).toLowerCase();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires event to listeners.
|
||||
*/
|
||||
private void fireEvent(int eventType, Object eventObject) {
|
||||
AgentRosterListener[] listeners = null;
|
||||
synchronized (this.listeners) {
|
||||
listeners = new AgentRosterListener[this.listeners.size()];
|
||||
this.listeners.toArray(listeners);
|
||||
}
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
switch (eventType) {
|
||||
case EVENT_AGENT_ADDED:
|
||||
listeners[i].agentAdded((String)eventObject);
|
||||
break;
|
||||
case EVENT_AGENT_REMOVED:
|
||||
listeners[i].agentRemoved((String)eventObject);
|
||||
break;
|
||||
case EVENT_PRESENCE_CHANGED:
|
||||
listeners[i].presenceChanged((Presence)eventObject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for all presence packets and processes them.
|
||||
*/
|
||||
private class PresencePacketListener implements PacketListener {
|
||||
public void processPacket(Packet packet) {
|
||||
Presence presence = (Presence)packet;
|
||||
String from = presence.getFrom();
|
||||
if (from == null) {
|
||||
// TODO Check if we need to ignore these presences or this is a server bug?
|
||||
System.out.println("Presence with no FROM: " + presence.toXML());
|
||||
return;
|
||||
}
|
||||
String key = getPresenceMapKey(from);
|
||||
|
||||
// If an "available" packet, add it to the presence map. Each presence map will hold
|
||||
// for a particular user a map with the presence packets saved for each resource.
|
||||
if (presence.getType() == Presence.Type.available) {
|
||||
// Ignore the presence packet unless it has an agent status extension.
|
||||
AgentStatus agentStatus = (AgentStatus)presence.getExtension(
|
||||
AgentStatus.ELEMENT_NAME, AgentStatus.NAMESPACE);
|
||||
if (agentStatus == null) {
|
||||
return;
|
||||
}
|
||||
// Ensure that this presence is coming from an Agent of the same workgroup
|
||||
// of this Agent
|
||||
else if (!workgroupJID.equals(agentStatus.getWorkgroupJID())) {
|
||||
return;
|
||||
}
|
||||
Map userPresences;
|
||||
// Get the user presence map
|
||||
if (presenceMap.get(key) == null) {
|
||||
userPresences = new HashMap();
|
||||
presenceMap.put(key, userPresences);
|
||||
}
|
||||
else {
|
||||
userPresences = (Map)presenceMap.get(key);
|
||||
}
|
||||
// Add the new presence, using the resources as a key.
|
||||
synchronized (userPresences) {
|
||||
userPresences.put(StringUtils.parseResource(from), presence);
|
||||
}
|
||||
// Fire an event.
|
||||
synchronized (entries) {
|
||||
for (Iterator i = entries.iterator(); i.hasNext();) {
|
||||
String entry = (String)i.next();
|
||||
if (entry.toLowerCase().equals(StringUtils.parseBareAddress(key).toLowerCase())) {
|
||||
fireEvent(EVENT_PRESENCE_CHANGED, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If an "unavailable" packet, remove any entries in the presence map.
|
||||
else if (presence.getType() == Presence.Type.unavailable) {
|
||||
if (presenceMap.get(key) != null) {
|
||||
Map userPresences = (Map)presenceMap.get(key);
|
||||
synchronized (userPresences) {
|
||||
userPresences.remove(StringUtils.parseResource(from));
|
||||
}
|
||||
if (userPresences.isEmpty()) {
|
||||
presenceMap.remove(key);
|
||||
}
|
||||
}
|
||||
// Fire an event.
|
||||
synchronized (entries) {
|
||||
for (Iterator i = entries.iterator(); i.hasNext();) {
|
||||
String entry = (String)i.next();
|
||||
if (entry.toLowerCase().equals(StringUtils.parseBareAddress(key).toLowerCase())) {
|
||||
fireEvent(EVENT_PRESENCE_CHANGED, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for all roster packets and processes them.
|
||||
*/
|
||||
private class AgentStatusListener implements PacketListener {
|
||||
|
||||
public void processPacket(Packet packet) {
|
||||
if (packet instanceof AgentStatusRequest) {
|
||||
AgentStatusRequest statusRequest = (AgentStatusRequest)packet;
|
||||
for (Iterator i = statusRequest.getAgents().iterator(); i.hasNext();) {
|
||||
AgentStatusRequest.Item item = (AgentStatusRequest.Item)i.next();
|
||||
String agentJID = item.getJID();
|
||||
if ("remove".equals(item.getType())) {
|
||||
|
||||
// Removing the user from the roster, so remove any presence information
|
||||
// about them.
|
||||
String key = StringUtils.parseName(StringUtils.parseName(agentJID) + "@" +
|
||||
StringUtils.parseServer(agentJID));
|
||||
presenceMap.remove(key);
|
||||
// Fire event for roster listeners.
|
||||
fireEvent(EVENT_AGENT_REMOVED, agentJID);
|
||||
}
|
||||
else {
|
||||
entries.add(agentJID);
|
||||
// Fire event for roster listeners.
|
||||
fireEvent(EVENT_AGENT_ADDED, agentJID);
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the roster as initialized.
|
||||
rosterInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Matt Tucker
|
||||
*/
|
||||
public interface AgentRosterListener {
|
||||
|
||||
public void agentAdded(String jid);
|
||||
|
||||
public void agentRemoved(String jid);
|
||||
|
||||
public void presenceChanged(Presence presence);
|
||||
}
|
||||
1184
source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java
Normal file
1184
source/org/jivesoftware/smackx/workgroup/agent/AgentSession.java
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
/**
|
||||
* Request sent by an agent to invite another agent or user.
|
||||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
public class InvitationRequest extends OfferContent {
|
||||
|
||||
private String inviter;
|
||||
private String room;
|
||||
private String reason;
|
||||
|
||||
public InvitationRequest(String inviter, String room, String reason) {
|
||||
this.inviter = inviter;
|
||||
this.room = room;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public String getInviter() {
|
||||
return inviter;
|
||||
}
|
||||
|
||||
public String getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
boolean isUserRequest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isInvitation() {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isTransfer() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
222
source/org/jivesoftware/smackx/workgroup/agent/Offer.java
Normal file
222
source/org/jivesoftware/smackx/workgroup/agent/Offer.java
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A class embodying the semantic agent chat offer; specific instances allow the acceptance or
|
||||
* rejecting of the offer.<br>
|
||||
*
|
||||
* @author Matt Tucker
|
||||
* @author loki der quaeler
|
||||
* @author Derek DeMoro
|
||||
*/
|
||||
public class Offer {
|
||||
|
||||
private XMPPConnection connection;
|
||||
private AgentSession session;
|
||||
|
||||
private String sessionID;
|
||||
private String userJID;
|
||||
private String userID;
|
||||
private String workgroupName;
|
||||
private Date expiresDate;
|
||||
private Map metaData;
|
||||
private OfferContent content;
|
||||
|
||||
private boolean accepted = false;
|
||||
private boolean rejected = false;
|
||||
|
||||
/**
|
||||
* Creates a new offer.
|
||||
*
|
||||
* @param conn the XMPP connection with which the issuing session was created.
|
||||
* @param agentSession the agent session instance through which this offer was issued.
|
||||
* @param userID the userID of the user from which the offer originates.
|
||||
* @param userJID the XMPP address of the user from which the offer originates.
|
||||
* @param workgroupName the fully qualified name of the workgroup.
|
||||
* @param expiresDate the date at which this offer expires.
|
||||
* @param sessionID the session id associated with the offer.
|
||||
* @param metaData the metadata associated with the offer.
|
||||
* @param content content of the offer. The content explains the reason for the offer
|
||||
* (e.g. user request, transfer)
|
||||
*/
|
||||
Offer(XMPPConnection conn, AgentSession agentSession, String userID,
|
||||
String userJID, String workgroupName, Date expiresDate,
|
||||
String sessionID, Map metaData, OfferContent content)
|
||||
{
|
||||
this.connection = conn;
|
||||
this.session = agentSession;
|
||||
this.userID = userID;
|
||||
this.userJID = userJID;
|
||||
this.workgroupName = workgroupName;
|
||||
this.expiresDate = expiresDate;
|
||||
this.sessionID = sessionID;
|
||||
this.metaData = metaData;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts the offer.
|
||||
*/
|
||||
public void accept() {
|
||||
Packet acceptPacket = new AcceptPacket(this.session.getWorkgroupJID());
|
||||
connection.sendPacket(acceptPacket);
|
||||
// TODO: listen for a reply.
|
||||
accepted = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejects the offer.
|
||||
*/
|
||||
public void reject() {
|
||||
RejectPacket rejectPacket = new RejectPacket(this.session.getWorkgroupJID());
|
||||
connection.sendPacket(rejectPacket);
|
||||
// TODO: listen for a reply.
|
||||
rejected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the userID that the offer originates from. In most cases, the
|
||||
* userID will simply be the JID of the requesting user. However, users can
|
||||
* also manually specify a userID for their request. In that case, that value will
|
||||
* be returned.
|
||||
*
|
||||
* @return the userID of the user from which the offer originates.
|
||||
*/
|
||||
public String getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JID of the user that made the offer request.
|
||||
*
|
||||
* @return the user's JID.
|
||||
*/
|
||||
public String getUserJID() {
|
||||
return userJID;
|
||||
}
|
||||
|
||||
/**
|
||||
* The fully qualified name of the workgroup (eg support@example.com).
|
||||
*
|
||||
* @return the name of the workgroup.
|
||||
*/
|
||||
public String getWorkgroupName() {
|
||||
return this.workgroupName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The date when the offer will expire. The agent must {@link #accept()}
|
||||
* the offer before the expiration date or the offer will lapse and be
|
||||
* routed to another agent. Alternatively, the agent can {@link #reject()}
|
||||
* the offer at any time if they don't wish to accept it..
|
||||
*
|
||||
* @return the date at which this offer expires.
|
||||
*/
|
||||
public Date getExpiresDate() {
|
||||
return this.expiresDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The session ID associated with the offer.
|
||||
*
|
||||
* @return the session id associated with the offer.
|
||||
*/
|
||||
public String getSessionID() {
|
||||
return this.sessionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* The meta-data associated with the offer.
|
||||
*
|
||||
* @return the offer meta-data.
|
||||
*/
|
||||
public Map getMetaData() {
|
||||
return this.metaData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content of the offer. The content explains the reason for the offer
|
||||
* (e.g. user request, transfer)
|
||||
*
|
||||
* @return the content of the offer.
|
||||
*/
|
||||
public OfferContent getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the agent accepted this offer.
|
||||
*
|
||||
* @return true if the agent accepted this offer.
|
||||
*/
|
||||
public boolean isAccepted() {
|
||||
return accepted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the agent rejected this offer.
|
||||
*
|
||||
* @return true if the agent rejected this offer.
|
||||
*/
|
||||
public boolean isRejected() {
|
||||
return rejected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet for rejecting offers.
|
||||
*/
|
||||
private class RejectPacket extends IQ {
|
||||
|
||||
RejectPacket(String workgroup) {
|
||||
this.setTo(workgroup);
|
||||
this.setType(IQ.Type.SET);
|
||||
}
|
||||
|
||||
public String getChildElementXML() {
|
||||
return "<offer-reject id=\"" + Offer.this.getSessionID() +
|
||||
"\" xmlns=\"http://jabber.org/protocol/workgroup" + "\"/>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet for accepting an offer.
|
||||
*/
|
||||
private class AcceptPacket extends IQ {
|
||||
|
||||
AcceptPacket(String workgroup) {
|
||||
this.setTo(workgroup);
|
||||
this.setType(IQ.Type.SET);
|
||||
}
|
||||
|
||||
public String getChildElementXML() {
|
||||
return "<offer-accept id=\"" + Offer.this.getSessionID() +
|
||||
"\" xmlns=\"http://jabber.org/protocol/workgroup" + "\"/>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
|
||||
public class OfferConfirmation extends IQ {
|
||||
private String userJID;
|
||||
private long sessionID;
|
||||
|
||||
public String getUserJID() {
|
||||
return userJID;
|
||||
}
|
||||
|
||||
public void setUserJID(String userJID) {
|
||||
this.userJID = userJID;
|
||||
}
|
||||
|
||||
public long getSessionID() {
|
||||
return sessionID;
|
||||
}
|
||||
|
||||
public void setSessionID(long sessionID) {
|
||||
this.sessionID = sessionID;
|
||||
}
|
||||
|
||||
|
||||
public void notifyService(XMPPConnection con, String workgroup, String createdRoomName) {
|
||||
NotifyServicePacket packet = new NotifyServicePacket(workgroup, createdRoomName);
|
||||
con.sendPacket(packet);
|
||||
}
|
||||
|
||||
public String getChildElementXML() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<offer-confirmation xmlns=\"http://jabber.org/protocol/workgroup\">");
|
||||
buf.append("</offer-confirmation>");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static class Provider implements IQProvider {
|
||||
|
||||
public IQ parseIQ(XmlPullParser parser) throws Exception {
|
||||
final OfferConfirmation confirmation = new OfferConfirmation();
|
||||
|
||||
boolean done = false;
|
||||
while (!done) {
|
||||
parser.next();
|
||||
String elementName = parser.getName();
|
||||
if (parser.getEventType() == XmlPullParser.START_TAG && "user-jid".equals(elementName)) {
|
||||
try {
|
||||
confirmation.setUserJID(parser.nextText());
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
else if (parser.getEventType() == XmlPullParser.START_TAG && "session-id".equals(elementName)) {
|
||||
try {
|
||||
confirmation.setSessionID(Long.valueOf(parser.nextText()));
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
}
|
||||
}
|
||||
else if (parser.getEventType() == XmlPullParser.END_TAG && "offer-confirmation".equals(elementName)) {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return confirmation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Packet for notifying server of RoomName
|
||||
*/
|
||||
private class NotifyServicePacket extends IQ {
|
||||
String roomName;
|
||||
|
||||
NotifyServicePacket(String workgroup, String roomName) {
|
||||
this.setTo(workgroup);
|
||||
this.setType(IQ.Type.RESULT);
|
||||
|
||||
this.roomName = roomName;
|
||||
}
|
||||
|
||||
public String getChildElementXML() {
|
||||
return "<offer-confirmation roomname=\"" + roomName + "\" xmlns=\"http://jabber.org/protocol/workgroup" + "\"/>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
public interface OfferConfirmationListener {
|
||||
|
||||
|
||||
/**
|
||||
* The implementing class instance will be notified via this when the AgentSession has confirmed
|
||||
* the acceptance of the <code>Offer</code>. The instance will then have the ability to create the room and
|
||||
* send the service the room name created for tracking.
|
||||
*
|
||||
* @param confirmedOffer the ConfirmedOffer
|
||||
*/
|
||||
void offerConfirmed(OfferConfirmation confirmedOffer);
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
/**
|
||||
* Type of content being included in the offer. The content actually explains the reason
|
||||
* the agent is getting an offer.
|
||||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
public abstract class OfferContent {
|
||||
|
||||
/**
|
||||
* Returns true if the content of the offer is related to a user request. This is the
|
||||
* most common type of offers an agent should receive.
|
||||
*
|
||||
* @return true if the content of the offer is related to a user request.
|
||||
*/
|
||||
abstract boolean isUserRequest();
|
||||
|
||||
/**
|
||||
* Returns true if the content of the offer is related to a room invitation made by another
|
||||
* agent. This type of offer include the room to join, metadata sent by the user while joining
|
||||
* the queue and the reason why the agent is being invited.
|
||||
*
|
||||
* @return true if the content of the offer is related to a room invitation made by another agent.
|
||||
*/
|
||||
abstract boolean isInvitation();
|
||||
|
||||
/**
|
||||
* Returns true if the content of the offer is related to a service transfer made by another
|
||||
* agent. This type of offers include the room to join, metadata sent by the user while joining the
|
||||
* queue and the reason why the agent is receiving the transfer offer.
|
||||
*
|
||||
* @return true if the content of the offer is related to a service transfer made by another agent.
|
||||
*/
|
||||
abstract boolean isTransfer();
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
/**
|
||||
* An interface which all classes interested in hearing about chat offers associated to a particular
|
||||
* AgentSession instance should implement.<br>
|
||||
*
|
||||
* @author Matt Tucker
|
||||
* @author loki der quaeler
|
||||
* @see org.jivesoftware.smackx.workgroup.agent.AgentSession
|
||||
*/
|
||||
public interface OfferListener {
|
||||
|
||||
/**
|
||||
* The implementing class instance will be notified via this when the AgentSession has received
|
||||
* an offer for a chat. The instance will then have the ability to accept, reject, or ignore
|
||||
* the request (resulting in a revocation-by-timeout).
|
||||
*
|
||||
* @param request the Offer instance embodying the details of the offer
|
||||
*/
|
||||
public void offerReceived (Offer request);
|
||||
|
||||
/**
|
||||
* The implementing class instance will be notified via this when the AgentSessino has received
|
||||
* a revocation of a previously extended offer.
|
||||
*
|
||||
* @param revokedOffer the RevokedOffer instance embodying the details of the revoked offer
|
||||
*/
|
||||
public void offerRevoked (RevokedOffer revokedOffer);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
public interface QueueUsersListener {
|
||||
|
||||
/**
|
||||
* The status of the queue was updated.
|
||||
*
|
||||
* @param queue the workgroup queue.
|
||||
* @param status the status of queue.
|
||||
*/
|
||||
public void statusUpdated(WorkgroupQueue queue, WorkgroupQueue.Status status);
|
||||
|
||||
/**
|
||||
* The average wait time of the queue was updated.
|
||||
*
|
||||
* @param queue the workgroup queue.
|
||||
* @param averageWaitTime the average wait time of the queue.
|
||||
*/
|
||||
public void averageWaitTimeUpdated(WorkgroupQueue queue, int averageWaitTime);
|
||||
|
||||
/**
|
||||
* The date of oldest entry waiting in the queue was updated.
|
||||
*
|
||||
* @param queue the workgroup queue.
|
||||
* @param oldestEntry the date of the oldest entry waiting in the queue.
|
||||
*/
|
||||
public void oldestEntryUpdated(WorkgroupQueue queue, Date oldestEntry);
|
||||
|
||||
/**
|
||||
* The list of users waiting in the queue was updated.
|
||||
*
|
||||
* @param queue the workgroup queue.
|
||||
* @param users the list of users waiting in the queue.
|
||||
*/
|
||||
public void usersUpdated(WorkgroupQueue queue, Set users);
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An immutable simple class to embody the information concerning a revoked offer, this is namely
|
||||
* the reason, the workgroup, the userJID, and the timestamp which the message was received.<br>
|
||||
*
|
||||
* @author loki der quaeler
|
||||
*/
|
||||
public class RevokedOffer {
|
||||
|
||||
private String userJID;
|
||||
private String userID;
|
||||
private String workgroupName;
|
||||
private String sessionID;
|
||||
private String reason;
|
||||
private Date timestamp;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param userJID the JID of the user for which this revocation was issued.
|
||||
* @param userID the user ID of the user for which this revocation was issued.
|
||||
* @param workgroupName the fully qualified name of the workgroup
|
||||
* @param sessionID the session id attributed to this chain of packets
|
||||
* @param reason the server issued message as to why this revocation was issued.
|
||||
* @param timestamp the timestamp at which the revocation was issued
|
||||
*/
|
||||
RevokedOffer(String userJID, String userID, String workgroupName, String sessionID,
|
||||
String reason, Date timestamp) {
|
||||
super();
|
||||
|
||||
this.userJID = userJID;
|
||||
this.userID = userID;
|
||||
this.workgroupName = workgroupName;
|
||||
this.sessionID = sessionID;
|
||||
this.reason = reason;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getUserJID() {
|
||||
return userJID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the jid of the user for which this revocation was issued
|
||||
*/
|
||||
public String getUserID() {
|
||||
return this.userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fully qualified name of the workgroup
|
||||
*/
|
||||
public String getWorkgroupName() {
|
||||
return this.workgroupName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the session id which will associate all packets for the pending chat
|
||||
*/
|
||||
public String getSessionID() {
|
||||
return this.sessionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the server issued message as to why this revocation was issued
|
||||
*/
|
||||
public String getReason() {
|
||||
return this.reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the timestamp at which the revocation was issued
|
||||
*/
|
||||
public Date getTimestamp() {
|
||||
return this.timestamp;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import org.jivesoftware.smackx.workgroup.packet.Transcript;
|
||||
import org.jivesoftware.smackx.workgroup.packet.Transcripts;
|
||||
import org.jivesoftware.smack.PacketCollector;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.PacketIDFilter;
|
||||
|
||||
/**
|
||||
* A TranscriptManager helps to retrieve the full conversation transcript of a given session
|
||||
* {@link #getTranscript(String, String)} or to retrieve a list with the summary of all the
|
||||
* conversations that a user had {@link #getTranscripts(String, String)}.
|
||||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
public class TranscriptManager {
|
||||
private XMPPConnection connection;
|
||||
|
||||
public TranscriptManager(XMPPConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full conversation transcript of a given session.
|
||||
*
|
||||
* @param sessionID the id of the session to get the full transcript.
|
||||
* @param workgroupJID the JID of the workgroup that will process the request.
|
||||
* @return the full conversation transcript of a given session.
|
||||
* @throws XMPPException if an error occurs while getting the information.
|
||||
*/
|
||||
public Transcript getTranscript(String workgroupJID, String sessionID) throws XMPPException {
|
||||
Transcript request = new Transcript(sessionID);
|
||||
request.setTo(workgroupJID);
|
||||
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
|
||||
// Send the request
|
||||
connection.sendPacket(request);
|
||||
|
||||
Transcript response = (Transcript) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the transcripts of a given user. The answer will contain the complete history of
|
||||
* conversations that a user had.
|
||||
*
|
||||
* @param userID the id of the user to get his conversations.
|
||||
* @param workgroupJID the JID of the workgroup that will process the request.
|
||||
* @return the transcripts of a given user.
|
||||
* @throws XMPPException if an error occurs while getting the information.
|
||||
*/
|
||||
public Transcripts getTranscripts(String workgroupJID, String userID) throws XMPPException {
|
||||
Transcripts request = new Transcripts(userID);
|
||||
request.setTo(workgroupJID);
|
||||
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
|
||||
// Send the request
|
||||
connection.sendPacket(request);
|
||||
|
||||
Transcripts response = (Transcripts) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import org.jivesoftware.smackx.workgroup.packet.TranscriptSearch;
|
||||
import org.jivesoftware.smack.PacketCollector;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.PacketIDFilter;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smackx.Form;
|
||||
import org.jivesoftware.smackx.ReportedData;
|
||||
|
||||
/**
|
||||
* A TranscriptSearchManager helps to retrieve the form to use for searching transcripts
|
||||
* {@link #getSearchForm(String)} or to submit a search form and return the results of
|
||||
* the search {@link #submitSearch(String, Form)}.
|
||||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
public class TranscriptSearchManager {
|
||||
private XMPPConnection connection;
|
||||
|
||||
public TranscriptSearchManager(XMPPConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Form to use for searching transcripts. It is unlikely that the server
|
||||
* will change the form (without a restart) so it is safe to keep the returned form
|
||||
* for future submissions.
|
||||
*
|
||||
* @param serviceJID the address of the workgroup service.
|
||||
* @return the Form to use for searching transcripts.
|
||||
* @throws XMPPException if an error occurs while sending the request to the server.
|
||||
*/
|
||||
public Form getSearchForm(String serviceJID) throws XMPPException {
|
||||
TranscriptSearch search = new TranscriptSearch();
|
||||
search.setType(IQ.Type.GET);
|
||||
search.setTo(serviceJID);
|
||||
|
||||
PacketCollector collector = connection.createPacketCollector(
|
||||
new PacketIDFilter(search.getPacketID()));
|
||||
connection.sendPacket(search);
|
||||
|
||||
TranscriptSearch response = (TranscriptSearch) collector.nextResult(
|
||||
SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
return Form.getFormFrom(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the completed form and returns the result of the transcript search. The result
|
||||
* will include all the data returned from the server so be careful with the amount of
|
||||
* data that the search may return.
|
||||
*
|
||||
* @param serviceJID the address of the workgroup service.
|
||||
* @param completedForm the filled out search form.
|
||||
* @return the result of the transcript search.
|
||||
* @throws XMPPException if an error occurs while submiting the search to the server.
|
||||
*/
|
||||
public ReportedData submitSearch(String serviceJID, Form completedForm) throws XMPPException {
|
||||
TranscriptSearch search = new TranscriptSearch();
|
||||
search.setType(IQ.Type.GET);
|
||||
search.setTo(serviceJID);
|
||||
search.addExtension(completedForm.getDataFormToSend());
|
||||
|
||||
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(search.getPacketID()));
|
||||
connection.sendPacket(search);
|
||||
|
||||
TranscriptSearch response = (TranscriptSearch) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
||||
|
||||
// Cancel the collector.
|
||||
collector.cancel();
|
||||
if (response == null) {
|
||||
throw new XMPPException("No response from server on status set.");
|
||||
}
|
||||
if (response.getError() != null) {
|
||||
throw new XMPPException(response.getError());
|
||||
}
|
||||
return ReportedData.getReportedDataFrom(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
/**
|
||||
* Request sent by an agent to transfer a support session to another agent or user.
|
||||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
public class TransferRequest extends OfferContent {
|
||||
|
||||
private String inviter;
|
||||
private String room;
|
||||
private String reason;
|
||||
|
||||
public TransferRequest(String inviter, String room, String reason) {
|
||||
this.inviter = inviter;
|
||||
this.room = room;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public String getInviter() {
|
||||
return inviter;
|
||||
}
|
||||
|
||||
public String getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
boolean isUserRequest() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isInvitation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isTransfer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
/**
|
||||
* Requests made by users to get support by some agent.
|
||||
*
|
||||
* @author Gaston Dombiak
|
||||
*/
|
||||
public class UserRequest extends OfferContent {
|
||||
// TODO Do we want to use a singleton? Should we store the userID here?
|
||||
private static UserRequest instance = new UserRequest();
|
||||
|
||||
public static OfferContent getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
boolean isUserRequest() {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isInvitation() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isTransfer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
/**
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright 2003-2007 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.smackx.workgroup.agent;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A queue in a workgroup, which is a pool of agents that are routed a specific type of
|
||||
* chat request.
|
||||
*/
|
||||
public class WorkgroupQueue {
|
||||
|
||||
private String name;
|
||||
private Status status = Status.CLOSED;
|
||||
|
||||
private int averageWaitTime = -1;
|
||||
private Date oldestEntry = null;
|
||||
private Set users = Collections.EMPTY_SET;
|
||||
|
||||
private int maxChats = 0;
|
||||
private int currentChats = 0;
|
||||
|
||||
/**
|
||||
* Creates a new workgroup queue instance.
|
||||
*
|
||||
* @param name the name of the queue.
|
||||
*/
|
||||
WorkgroupQueue(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the queue.
|
||||
*
|
||||
* @return the name of the queue.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the queue.
|
||||
*
|
||||
* @return the status of the queue.
|
||||
*/
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
void setStatus(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of users waiting in the queue waiting to be routed to
|
||||
* an agent.
|
||||
*
|
||||
* @return the number of users waiting in the queue.
|
||||
*/
|
||||
public int getUserCount() {
|
||||
if (users == null) {
|
||||
return 0;
|
||||
}
|
||||
return users.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Iterator for the users in the queue waiting to be routed to
|
||||
* an agent (QueueUser instances).
|
||||
*
|
||||
* @return an Iterator for the users waiting in the queue.
|
||||
*/
|
||||
public Iterator getUsers() {
|
||||
if (users == null) {
|
||||
return Collections.EMPTY_SET.iterator();
|
||||
}
|
||||
return Collections.unmodifiableSet(users).iterator();
|
||||
}
|
||||
|
||||
void setUsers(Set users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average amount of time users wait in the queue before being
|
||||
* routed to an agent. If average wait time info isn't available, -1 will
|
||||
* be returned.
|
||||
*
|
||||
* @return the average wait time
|
||||
*/
|
||||
public int getAverageWaitTime() {
|
||||
return averageWaitTime;
|
||||
}
|
||||
|
||||
void setAverageWaitTime(int averageTime) {
|
||||
this.averageWaitTime = averageTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date of the oldest request waiting in the queue. If there
|
||||
* are no requests waiting to be routed, this method will return <tt>null</tt>.
|
||||
*
|
||||
* @return the date of the oldest request in the queue.
|
||||
*/
|
||||
public Date getOldestEntry() {
|
||||
return oldestEntry;
|
||||
}
|
||||
|
||||
void setOldestEntry(Date oldestEntry) {
|
||||
this.oldestEntry = oldestEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of simultaneous chats the queue can handle.
|
||||
*
|
||||
* @return the max number of chats the queue can handle.
|
||||
*/
|
||||
public int getMaxChats() {
|
||||
return maxChats;
|
||||
}
|
||||
|
||||
void setMaxChats(int maxChats) {
|
||||
this.maxChats = maxChats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current number of active chat sessions in the queue.
|
||||
*
|
||||
* @return the current number of active chat sessions in the queue.
|
||||
*/
|
||||
public int getCurrentChats() {
|
||||
return currentChats;
|
||||
}
|
||||
|
||||
void setCurrentChats(int currentChats) {
|
||||
this.currentChats = currentChats;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent the status of the workgroup. The possible values are:
|
||||
*
|
||||
* <ul>
|
||||
* <li>WorkgroupQueue.Status.OPEN -- the queue is active and accepting new chat requests.
|
||||
* <li>WorkgroupQueue.Status.ACTIVE -- the queue is active but NOT accepting new chat
|
||||
* requests.
|
||||
* <li>WorkgroupQueue.Status.CLOSED -- the queue is NOT active and NOT accepting new
|
||||
* chat requests.
|
||||
* </ul>
|
||||
*/
|
||||
public static class Status {
|
||||
|
||||
/**
|
||||
* The queue is active and accepting new chat requests.
|
||||
*/
|
||||
public static final Status OPEN = new Status("open");
|
||||
|
||||
/**
|
||||
* The queue is active but NOT accepting new chat requests. This state might
|
||||
* occur when the workgroup has closed because regular support hours have closed,
|
||||
* but there are still several requests left in the queue.
|
||||
*/
|
||||
public static final Status ACTIVE = new Status("active");
|
||||
|
||||
/**
|
||||
* The queue is NOT active and NOT accepting new chat requests.
|
||||
*/
|
||||
public static final Status CLOSED = new Status("closed");
|
||||
|
||||
/**
|
||||
* Converts a String into the corresponding status. Valid String values
|
||||
* that can be converted to a status are: "open", "active", and "closed".
|
||||
*
|
||||
* @param type the String value to covert.
|
||||
* @return the corresponding Type.
|
||||
*/
|
||||
public static Status fromString(String type) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
type = type.toLowerCase();
|
||||
if (OPEN.toString().equals(type)) {
|
||||
return OPEN;
|
||||
}
|
||||
else if (ACTIVE.toString().equals(type)) {
|
||||
return ACTIVE;
|
||||
}
|
||||
else if (CLOSED.toString().equals(type)) {
|
||||
return CLOSED;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String value;
|
||||
|
||||
private Status(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue