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:
Matt Tucker 2007-03-07 23:38:36 +00:00 committed by matt
parent 939feb9017
commit fe545abeae
64 changed files with 9744 additions and 0 deletions

View File

@ -0,0 +1,67 @@
/**
* $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;
import java.util.Map;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* MetaData packet extension.
*/
public class MetaData implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "metadata";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private Map metaData;
public MetaData(Map metaData) {
this.metaData = metaData;
}
/**
* @return the Map of metadata contained by this instance
*/
public Map getMetaData() {
return metaData;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
return MetaDataUtils.serializeMetaData(this.getMetaData());
}
}

View File

@ -0,0 +1,85 @@
/**
* $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;
import java.util.Date;
/**
* An immutable class which wraps up customer-in-queue data return from the server; depending on
* the type of information dispatched from the server, not all information will be available in
* any given instance.
*
* @author loki der quaeler
*/
public class QueueUser {
private String userID;
private int queuePosition;
private int estimatedTime;
private Date joinDate;
/**
* @param uid the user jid of the customer in the queue
* @param position the position customer sits in the queue
* @param time the estimate of how much longer the customer will be in the queue in seconds
* @param joinedAt the timestamp of when the customer entered the queue
*/
public QueueUser (String uid, int position, int time, Date joinedAt) {
super();
this.userID = uid;
this.queuePosition = position;
this.estimatedTime = time;
this.joinDate = joinedAt;
}
/**
* @return the user jid of the customer in the queue
*/
public String getUserID () {
return this.userID;
}
/**
* @return the position in the queue at which the customer sits, or -1 if the update which
* this instance embodies is only a time update instead
*/
public int getQueuePosition () {
return this.queuePosition;
}
/**
* @return the estimated time remaining of the customer in the queue in seconds, or -1 if
* if the update which this instance embodies is only a position update instead
*/
public int getEstimatedRemainingTime () {
return this.estimatedTime;
}
/**
* @return the timestamp of when this customer entered the queue, or null if the server did not
* provide this information
*/
public Date getQueueJoinTimestamp () {
return this.joinDate;
}
}

View File

@ -0,0 +1,133 @@
/**
* $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;
import java.util.Map;
/**
* An immutable class wrapping up the basic information which comprises a group chat invitation.
*
* @author loki der quaeler
*/
public class WorkgroupInvitation {
protected String uniqueID;
protected String sessionID;
protected String groupChatName;
protected String issuingWorkgroupName;
protected String messageBody;
protected String invitationSender;
protected Map metaData;
/**
* This calls the 5-argument constructor with a null MetaData argument value
*
* @param jid the jid string with which the issuing AgentSession or Workgroup instance
* was created
* @param group the jid of the room to which the person is invited
* @param workgroup the jid of the workgroup issuing the invitation
* @param sessID the session id associated with the pending chat
* @param msgBody the body of the message which contained the invitation
* @param from the user jid who issued the invitation, if known, null otherwise
*/
public WorkgroupInvitation (String jid, String group, String workgroup,
String sessID, String msgBody, String from) {
this(jid, group, workgroup, sessID, msgBody, from, null);
}
/**
* @param jid the jid string with which the issuing AgentSession or Workgroup instance
* was created
* @param group the jid of the room to which the person is invited
* @param workgroup the jid of the workgroup issuing the invitation
* @param sessID the session id associated with the pending chat
* @param msgBody the body of the message which contained the invitation
* @param from the user jid who issued the invitation, if known, null otherwise
* @param metaData the metadata sent with the invitation
*/
public WorkgroupInvitation (String jid, String group, String workgroup, String sessID, String msgBody,
String from, Map metaData) {
super();
this.uniqueID = jid;
this.sessionID = sessID;
this.groupChatName = group;
this.issuingWorkgroupName = workgroup;
this.messageBody = msgBody;
this.invitationSender = from;
this.metaData = metaData;
}
/**
* @return the jid string with which the issuing AgentSession or Workgroup instance
* was created.
*/
public String getUniqueID () {
return this.uniqueID;
}
/**
* @return the session id associated with the pending chat; working backwards temporally,
* this session id should match the session id to the corresponding offer request
* which resulted in this invitation.
*/
public String getSessionID () {
return this.sessionID;
}
/**
* @return the jid of the room to which the person is invited.
*/
public String getGroupChatName () {
return this.groupChatName;
}
/**
* @return the name of the workgroup from which the invitation was issued.
*/
public String getWorkgroupName () {
return this.issuingWorkgroupName;
}
/**
* @return the contents of the body-block of the message that housed this invitation.
*/
public String getMessageBody () {
return this.messageBody;
}
/**
* @return the user who issued the invitation, or null if it wasn't known.
*/
public String getInvitationSender () {
return this.invitationSender;
}
/**
* @return the meta data associated with the invitation, or null if this instance was
* constructed with none
*/
public Map getMetaData () {
return this.metaData;
}
}

View File

@ -0,0 +1,39 @@
/**
* $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;
/**
* An interface which all classes interested in hearing about group chat invitations should
* implement.
*
* @author loki der quaeler
*/
public interface WorkgroupInvitationListener {
/**
* The implementing class instance will be notified via this method when an invitation
* to join a group chat has been received from the server.
*
* @param invitation an Invitation instance embodying the information pertaining to the
* invitation
*/
public void invitationReceived(WorkgroupInvitation invitation);
}

View 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;
}
}

View 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;
}
}
}
}

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}

View 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" + "\"/>";
}
}
}

View File

@ -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" + "\"/>";
}
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View 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 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;
}
}
}

View File

@ -0,0 +1,82 @@
/**
* $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.ext.forms;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
public class WorkgroupForm extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "workgroup-form";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for WebForm packets.
*
* @author Derek DeMoro
*/
public static class InternalProvider implements IQProvider {
public InternalProvider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
WorkgroupForm answer = new WorkgroupForm();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
// Parse the packet extension
answer.addExtension(PacketParserUtils.parsePacketExtension(parser.getName(),
parser.getNamespace(), parser));
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return answer;
}
}
}

View File

@ -0,0 +1,155 @@
/**
* $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.ext.history;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* IQ provider used to retrieve individual agent information. Each chat session can be mapped
* to one or more jids and therefore retrievable.
*/
public class AgentChatHistory extends IQ {
private String agentJID;
private int maxSessions;
private long startDate;
private List agentChatSessions = new ArrayList();
public AgentChatHistory(String agentJID, int maxSessions, Date startDate) {
this.agentJID = agentJID;
this.maxSessions = maxSessions;
this.startDate = startDate.getTime();
}
public AgentChatHistory(String agentJID, int maxSessions) {
this.agentJID = agentJID;
this.maxSessions = maxSessions;
this.startDate = 0;
}
public AgentChatHistory() {
}
public void addChatSession(AgentChatSession chatSession) {
agentChatSessions.add(chatSession);
}
public Collection getAgentChatSessions() {
return agentChatSessions;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "chat-sessions";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append(" agentJID=\"" + agentJID + "\"");
buf.append(" maxSessions=\"" + maxSessions + "\"");
buf.append(" startDate=\"" + startDate + "\"");
buf.append("></").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for AgentHistory packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
AgentChatHistory agentChatHistory = new AgentChatHistory();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("chat-session".equals(parser.getName()))) {
agentChatHistory.addChatSession(parseChatSetting(parser));
}
else if (eventType == XmlPullParser.END_TAG && ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return agentChatHistory;
}
private AgentChatSession parseChatSetting(XmlPullParser parser) throws Exception {
boolean done = false;
Date date = null;
long duration = 0;
String visitorsName = null;
String visitorsEmail = null;
String sessionID = null;
String question = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("date".equals(parser.getName()))) {
String dateStr = parser.nextText();
long l = Long.valueOf(dateStr).longValue();
date = new Date(l);
}
else if ((eventType == XmlPullParser.START_TAG) && ("duration".equals(parser.getName()))) {
duration = Long.valueOf(parser.nextText()).longValue();
}
else if ((eventType == XmlPullParser.START_TAG) && ("visitorsName".equals(parser.getName()))) {
visitorsName = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("visitorsEmail".equals(parser.getName()))) {
visitorsEmail = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("sessionID".equals(parser.getName()))) {
sessionID = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("question".equals(parser.getName()))) {
question = parser.nextText();
}
else if (eventType == XmlPullParser.END_TAG && "chat-session".equals(parser.getName())) {
done = true;
}
}
return new AgentChatSession(date, duration, visitorsName, visitorsEmail, sessionID, question);
}
}
}

View File

@ -0,0 +1,93 @@
/**
* $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.ext.history;
import java.util.Date;
/**
* Represents one chat session for an agent.
*/
public class AgentChatSession {
public Date startDate;
public long duration;
public String visitorsName;
public String visitorsEmail;
public String sessionID;
public String question;
public AgentChatSession(Date date, long duration, String visitorsName, String visitorsEmail, String sessionID, String question) {
this.startDate = date;
this.duration = duration;
this.visitorsName = visitorsName;
this.visitorsEmail = visitorsEmail;
this.sessionID = sessionID;
this.question = question;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
public String getVisitorsName() {
return visitorsName;
}
public void setVisitorsName(String visitorsName) {
this.visitorsName = visitorsName;
}
public String getVisitorsEmail() {
return visitorsEmail;
}
public void setVisitorsEmail(String visitorsEmail) {
this.visitorsEmail = visitorsEmail;
}
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
public void setQuestion(String question){
this.question = question;
}
public String getQuestion(){
return question;
}
}

View File

@ -0,0 +1,115 @@
/**
* $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.ext.history;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.HashMap;
import java.util.Map;
public class ChatMetadata extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "chat-metadata";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String sessionID;
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
private Map map = new HashMap();
public void setMetadata(Map metadata){
this.map = metadata;
}
public Map getMetadata(){
return map;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
buf.append("<sessionID>").append(getSessionID()).append("</sessionID>");
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for Metadata packets.
*
* @author Derek DeMoro
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
final ChatMetadata chatM = new ChatMetadata();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("sessionID")) {
chatM.setSessionID(parser.nextText());
}
else if (parser.getName().equals("metadata")) {
Map map = MetaDataUtils.parseMetaData(parser);
chatM.setMetadata(map);
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return chatM;
}
}
}

View File

@ -0,0 +1,68 @@
/**
* $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.ext.macros;
/**
* Macro datamodel.
*/
public class Macro {
public static final int TEXT = 0;
public static final int URL = 1;
public static final int IMAGE = 2;
private String title;
private String description;
private String response;
private int type;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}

View File

@ -0,0 +1,116 @@
/**
* $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.ext.macros;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* MacroGroup datamodel.
*/
public class MacroGroup {
private List macros;
private List macroGroups;
// Define MacroGroup
private String title;
public MacroGroup() {
macros = new ArrayList();
macroGroups = new ArrayList();
}
public void addMacro(Macro macro) {
macros.add(macro);
}
public void removeMacro(Macro macro) {
macros.remove(macro);
}
public Macro getMacroByTitle(String title) {
Collection col = Collections.unmodifiableList(macros);
Iterator iter = col.iterator();
while (iter.hasNext()) {
Macro macro = (Macro)iter.next();
if (macro.getTitle().equalsIgnoreCase(title)) {
return macro;
}
}
return null;
}
public void addMacroGroup(MacroGroup group) {
macroGroups.add(group);
}
public void removeMacroGroup(MacroGroup group) {
macroGroups.remove(group);
}
public Macro getMacro(int location) {
return (Macro)macros.get(location);
}
public MacroGroup getMacroGroupByTitle(String title) {
Collection col = Collections.unmodifiableList(macroGroups);
Iterator iter = col.iterator();
while (iter.hasNext()) {
MacroGroup group = (MacroGroup)iter.next();
if (group.getTitle().equalsIgnoreCase(title)) {
return group;
}
}
return null;
}
public MacroGroup getMacroGroup(int location) {
return (MacroGroup)macroGroups.get(location);
}
public List getMacros() {
return macros;
}
public void setMacros(List macros) {
this.macros = macros;
}
public List getMacroGroups() {
return macroGroups;
}
public void setMacroGroups(List macroGroups) {
this.macroGroups = macroGroups;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}

View File

@ -0,0 +1,144 @@
/**
* $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.ext.macros;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.StringUtils;
import org.xmlpull.v1.XmlPullParser;
/**
* Macros iq is responsible for handling global and personal macros in the a Live Assistant
* Workgroup.
*/
public class Macros extends IQ {
private MacroGroup rootGroup;
private boolean personal;
private MacroGroup personalMacroGroup;
private static ClassLoader cl;
public static void setClassLoader(ClassLoader cloader) {
cl = cloader;
}
public MacroGroup getRootGroup() {
return rootGroup;
}
public void setRootGroup(MacroGroup rootGroup) {
this.rootGroup = rootGroup;
}
public boolean isPersonal() {
return personal;
}
public void setPersonal(boolean personal) {
this.personal = personal;
}
public MacroGroup getPersonalMacroGroup() {
return personalMacroGroup;
}
public void setPersonalMacroGroup(MacroGroup personalMacroGroup) {
this.personalMacroGroup = personalMacroGroup;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "macros";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
if (isPersonal()) {
buf.append("<personal>true</personal>");
}
// TODO: REMOVE XSTREAM
// if (getPersonalMacroGroup() != null) {
// final XStream xstream = new XStream();
// xstream.alias("macro", Macro.class);
// xstream.alias("macrogroup", MacroGroup.class);
//
// if (cl != null) {
// xstream.setClassLoader(cl);
// }
// String persitedGroup = StringUtils.escapeForXML(xstream.toXML(getPersonalMacroGroup()));
// buf.append("<personalMacro>").append(persitedGroup).append("</personalMacro>");
// }
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for Macro packets.
*
* @author Derek DeMoro
*/
public static class InternalProvider implements IQProvider {
public InternalProvider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
Macros macroGroup = new Macros();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("model")) {
String macros = parser.nextText();
// TODO: REMOVE XSTREAM
// XStream xstream = new XStream();
// if(cl != null){
// xstream.setClassLoader(cl);
// }
// xstream.alias("macro", Macro.class);
// xstream.alias("macrogroup", MacroGroup.class);
// MacroGroup group = (MacroGroup)xstream.fromXML(macros);
// macroGroup.setRootGroup(group);
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return macroGroup;
}
}
}

View File

@ -0,0 +1,155 @@
/**
* $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.ext.notes;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* IQ packet for retrieving and adding Chat Notes.
*/
public class ChatNotes extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "chat-notes";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String sessionID;
private String notes;
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
buf.append("<sessionID>").append(getSessionID()).append("</sessionID>");
if (getNotes() != null) {
buf.append("<notes>").append(getNotes()).append("</notes>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for ChatNotes packets.
*
* @author Derek DeMoro
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
ChatNotes chatNotes = new ChatNotes();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("sessionID")) {
chatNotes.setSessionID(parser.nextText());
}
else if (parser.getName().equals("text")) {
String note = parser.nextText();
note = note.replaceAll("\\\\n", "\n");
chatNotes.setNotes(note);
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return chatNotes;
}
}
/**
* Replaces all instances of oldString with newString in string.
*
* @param string the String to search to perform replacements on
* @param oldString the String that should be replaced by newString
* @param newString the String that will replace all instances of oldString
* @return a String will all instances of oldString replaced by newString
*/
public static final String replace(String string, String oldString, String newString) {
if (string == null) {
return null;
}
// If the newString is null or zero length, just return the string since there's nothing
// to replace.
if (newString == null) {
return string;
}
int i = 0;
// Make sure that oldString appears at least once before doing any processing.
if ((i = string.indexOf(oldString, i)) >= 0) {
// Use char []'s, as they are more efficient to deal with.
char[] string2 = string.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuilder buf = new StringBuilder(string2.length);
buf.append(string2, 0, i).append(newString2);
i += oLength;
int j = i;
// Replace all remaining instances of oldString with newString.
while ((i = string.indexOf(oldString, i)) > 0) {
buf.append(string2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(string2, j, string2.length - j);
return buf.toString();
}
return string;
}
}

View File

@ -0,0 +1,132 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* IQ packet for retrieving and changing the Agent personal information.
*/
public class AgentInfo extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "agent-info";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String jid;
private String name;
/**
* Returns the Agent's jid.
*
* @return the Agent's jid.
*/
public String getJid() {
return jid;
}
/**
* Sets the Agent's jid.
*
* @param jid the jid of the agent.
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Returns the Agent's name. The name of the agent may be different than the user's name.
* This property may be shown in the webchat client.
*
* @return the Agent's name.
*/
public String getName() {
return name;
}
/**
* Sets the Agent's name. The name of the agent may be different than the user's name.
* This property may be shown in the webchat client.
*
* @param name the new name of the agent.
*/
public void setName(String name) {
this.name = name;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
if (jid != null) {
buf.append("<jid>").append(getJid()).append("</jid>");
}
if (name != null) {
buf.append("<name>").append(getName()).append("</name>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for AgentInfo packets.
*
* @author Gaston Dombiak
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
AgentInfo answer = new AgentInfo();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("jid")) {
answer.setJid(parser.nextText());
}
else if (parser.getName().equals("name")) {
answer.setName(parser.nextText());
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return answer;
}
}
}

View File

@ -0,0 +1,266 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Agent status packet.
*
* @author Matt Tucker
*/
public class AgentStatus implements PacketExtension {
private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "agent-status";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private String workgroupJID;
private List currentChats = new ArrayList();
private int maxChats = -1;
AgentStatus() {
}
public String getWorkgroupJID() {
return workgroupJID;
}
/**
* Returns a collection of ChatInfo where each ChatInfo represents a Chat where this agent
* is participating.
*
* @return a collection of ChatInfo where each ChatInfo represents a Chat where this agent
* is participating.
*/
public List getCurrentChats() {
return Collections.unmodifiableList(currentChats);
}
public int getMaxChats() {
return maxChats;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\"");
if (workgroupJID != null) {
buf.append(" jid=\"").append(workgroupJID).append("\"");
}
buf.append(">");
if (maxChats != -1) {
buf.append("<max-chats>").append(maxChats).append("</max-chats>");
}
if (!currentChats.isEmpty()) {
buf.append("<current-chats xmlns= \"http://jivesoftware.com/protocol/workgroup\">");
for (Iterator it = currentChats.iterator(); it.hasNext();) {
buf.append(((ChatInfo)it.next()).toXML());
}
buf.append("</current-chats>");
}
buf.append("</").append(this.getElementName()).append("> ");
return buf.toString();
}
/**
* Represents information about a Chat where this Agent is participating.
*
* @author Gaston Dombiak
*/
public static class ChatInfo {
private String sessionID;
private String userID;
private Date date;
private String email;
private String username;
private String question;
public ChatInfo(String sessionID, String userID, Date date, String email, String username, String question) {
this.sessionID = sessionID;
this.userID = userID;
this.date = date;
this.email = email;
this.username = username;
this.question = question;
}
/**
* Returns the sessionID associated to this chat. Each chat will have a unique sessionID
* that could be used for retrieving the whole transcript of the conversation.
*
* @return the sessionID associated to this chat.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the user unique identification of the user that made the initial request and
* for which this chat was generated. If the user joined using an anonymous connection
* then the userID will be the value of the ID attribute of the USER element. Otherwise,
* the userID will be the bare JID of the user that made the request.
*
* @return the user unique identification of the user that made the initial request.
*/
public String getUserID() {
return userID;
}
/**
* Returns the date when this agent joined the chat.
*
* @return the date when this agent joined the chat.
*/
public Date getDate() {
return date;
}
/**
* Returns the email address associated with the user.
*
* @return the email address associated with the user.
*/
public String getEmail() {
return email;
}
/**
* Returns the username(nickname) associated with the user.
*
* @return the username associated with the user.
*/
public String getUsername() {
return username;
}
/**
* Returns the question the user asked.
*
* @return the question the user asked, if any.
*/
public String getQuestion() {
return question;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<chat ");
if (sessionID != null) {
buf.append(" sessionID=\"").append(sessionID).append("\"");
}
if (userID != null) {
buf.append(" userID=\"").append(userID).append("\"");
}
if (date != null) {
buf.append(" startTime=\"").append(UTC_FORMAT.format(date)).append("\"");
}
if (email != null) {
buf.append(" email=\"").append(email).append("\"");
}
if (username != null) {
buf.append(" username=\"").append(username).append("\"");
}
if (question != null) {
buf.append(" question=\"").append(question).append("\"");
}
buf.append("/>");
return buf.toString();
}
}
/**
* Packet extension provider for AgentStatus packets.
*/
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
AgentStatus agentStatus = new AgentStatus();
agentStatus.workgroupJID = parser.getAttributeValue("", "jid");
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if ("chat".equals(parser.getName())) {
agentStatus.currentChats.add(parseChatInfo(parser));
}
else if ("max-chats".equals(parser.getName())) {
agentStatus.maxChats = Integer.parseInt(parser.nextText());
}
}
else if (eventType == XmlPullParser.END_TAG &&
ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return agentStatus;
}
private ChatInfo parseChatInfo(XmlPullParser parser) {
String sessionID = parser.getAttributeValue("", "sessionID");
String userID = parser.getAttributeValue("", "userID");
Date date = null;
try {
date = UTC_FORMAT.parse(parser.getAttributeValue("", "startTime"));
}
catch (ParseException e) {
}
String email = parser.getAttributeValue("", "email");
String username = parser.getAttributeValue("", "username");
String question = parser.getAttributeValue("", "question");
return new ChatInfo(sessionID, userID, date, email, username, question);
}
}
}

View File

@ -0,0 +1,163 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Agent status request packet. This packet is used by agents to request the list of
* agents in a workgroup. The response packet contains a list of packets. Presence
* packets from individual agents follow.
*
* @author Matt Tucker
*/
public class AgentStatusRequest extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "agent-status-request";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private Set agents;
public AgentStatusRequest() {
agents = new HashSet();
}
public int getAgentCount() {
return agents.size();
}
public Set getAgents() {
return Collections.unmodifiableSet(agents);
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
synchronized (agents) {
for (Iterator i=agents.iterator(); i.hasNext(); ) {
Item item = (Item) i.next();
buf.append("<agent jid=\"").append(item.getJID()).append("\">");
if (item.getName() != null) {
buf.append("<name xmlns=\""+ AgentInfo.NAMESPACE + "\">");
buf.append(item.getName());
buf.append("</name>");
}
buf.append("</agent>");
}
}
buf.append("</").append(this.getElementName()).append("> ");
return buf.toString();
}
public static class Item {
private String jid;
private String type;
private String name;
public Item(String jid, String type, String name) {
this.jid = jid;
this.type = type;
this.name = name;
}
public String getJID() {
return jid;
}
public String getType() {
return type;
}
public String getName() {
return name;
}
}
/**
* Packet extension provider for AgentStatusRequest packets.
*/
public static class Provider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
AgentStatusRequest statusRequest = new AgentStatusRequest();
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("agent".equals(parser.getName()))) {
statusRequest.agents.add(parseAgent(parser));
}
else if (eventType == XmlPullParser.END_TAG &&
"agent-status-request".equals(parser.getName()))
{
done = true;
}
}
return statusRequest;
}
private Item parseAgent(XmlPullParser parser) throws Exception {
boolean done = false;
String jid = parser.getAttributeValue("", "jid");
String type = parser.getAttributeValue("", "type");
String name = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("name".equals(parser.getName()))) {
name = parser.nextText();
}
else if (eventType == XmlPullParser.END_TAG &&
"agent".equals(parser.getName()))
{
done = true;
}
}
return new Item(jid, type, name);
}
}
}

View File

@ -0,0 +1,129 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Represents a request for getting the jid of the workgroups where an agent can work or could
* represent the result of such request which will contain the list of workgroups JIDs where the
* agent can work.
*
* @author Gaston Dombiak
*/
public class AgentWorkgroups extends IQ {
private String agentJID;
private List workgroups;
/**
* Creates an AgentWorkgroups request for the given agent. This IQ will be sent and an answer
* will be received with the jid of the workgroups where the agent can work.
*
* @param agentJID the id of the agent to get his workgroups.
*/
public AgentWorkgroups(String agentJID) {
this.agentJID = agentJID;
this.workgroups = new ArrayList();
}
/**
* Creates an AgentWorkgroups which will contain the JIDs of the workgroups where an agent can
* work.
*
* @param agentJID the id of the agent that can work in the list of workgroups.
* @param workgroups the list of workgroup JIDs where the agent can work.
*/
public AgentWorkgroups(String agentJID, List workgroups) {
this.agentJID = agentJID;
this.workgroups = workgroups;
}
public String getAgentJID() {
return agentJID;
}
/**
* Returns a list of workgroup JIDs where the agent can work.
*
* @return a list of workgroup JIDs where the agent can work.
*/
public List getWorkgroups() {
return Collections.unmodifiableList(workgroups);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<workgroups xmlns=\"http://jabber.org/protocol/workgroup\" jid=\"")
.append(agentJID)
.append("\">");
for (Iterator it=workgroups.iterator(); it.hasNext();) {
String workgroupJID = (String) it.next();
buf.append("<workgroup jid=\"" + workgroupJID + "\"/>");
}
buf.append("</workgroups>");
return buf.toString();
}
/**
* An IQProvider for AgentWorkgroups packets.
*
* @author Gaston Dombiak
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
String agentJID = parser.getAttributeValue("", "jid");
List workgroups = new ArrayList();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("workgroup")) {
workgroups.add(parser.getAttributeValue("", "jid"));
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("workgroups")) {
done = true;
}
}
}
return new AgentWorkgroups(agentJID, workgroups);
}
}
}

View File

@ -0,0 +1,75 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
/**
* A IQ packet used to depart a workgroup queue. There are two cases for issuing a depart
* queue request:<ul>
* <li>The user wants to leave the queue. In this case, an instance of this class
* should be created without passing in a user address.
* <li>An administrator or the server removes wants to remove a user from the queue.
* In that case, the address of the user to remove from the queue should be
* used to create an instance of this class.</ul>
*
* @author loki der quaeler
*/
public class DepartQueuePacket extends IQ {
private String user;
/**
* Creates a depart queue request packet to the specified workgroup.
*
* @param workgroup the workgroup to depart.
*/
public DepartQueuePacket(String workgroup) {
this(workgroup, null);
}
/**
* Creates a depart queue request to the specified workgroup and for the
* specified user.
*
* @param workgroup the workgroup to depart.
* @param user the user to make depart from the queue.
*/
public DepartQueuePacket(String workgroup, String user) {
this.user = user;
setTo(workgroup);
setType(IQ.Type.SET);
setFrom(user);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder("<depart-queue xmlns=\"http://jabber.org/protocol/workgroup\"");
if (this.user != null) {
buf.append("><jid>").append(this.user).append("</jid></depart-queue>");
}
else {
buf.append("/>");
}
return buf.toString();
}
}

View File

@ -0,0 +1,48 @@
/**
* $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.packet;
import java.util.Map;
import org.jivesoftware.smackx.workgroup.MetaData;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* This provider parses meta data if it's not contained already in a larger extension provider.
*
* @author loki der quaeler
*/
public class MetaDataProvider implements PacketExtensionProvider {
/**
* PacketExtensionProvider implementation
*/
public PacketExtension parseExtension (XmlPullParser parser)
throws Exception {
Map metaData = MetaDataUtils.parseMetaData(parser);
return new MetaData(metaData);
}
}

View File

@ -0,0 +1,107 @@
/**
* $RCSfile: ,v $
* $Revision: $
* $Date: $
*
* Copyright (C) 1999-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
public class MonitorPacket extends IQ {
private String sessionID;
private boolean isMonitor;
public boolean isMonitor() {
return isMonitor;
}
public void setMonitor(boolean monitor) {
isMonitor = monitor;
}
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "monitor";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append(">");
if (sessionID != null) {
buf.append("<makeOwner sessionID=\""+sessionID+"\"></makeOwner>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for Monitor Packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
MonitorPacket packet = new MonitorPacket();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("isMonitor".equals(parser.getName()))) {
String value = parser.nextText();
if ("false".equalsIgnoreCase(value)) {
packet.setMonitor(false);
}
else {
packet.setMonitor(true);
}
}
else if (eventType == XmlPullParser.END_TAG && "monitor".equals(parser.getName())) {
done = true;
}
}
return packet;
}
}
}

View File

@ -0,0 +1,173 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Packet used for requesting information about occupants of a room or for retrieving information
* such information.
*
* @author Gaston Dombiak
*/
public class OccupantsInfo extends IQ {
private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "occupants-info";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String roomID;
private final Set<OccupantInfo> occupants;
public OccupantsInfo(String roomID) {
this.roomID = roomID;
this.occupants = new HashSet<OccupantInfo>();
}
public String getRoomID() {
return roomID;
}
public int getOccupantsCount() {
return occupants.size();
}
public Set<OccupantInfo> getOccupants() {
return Collections.unmodifiableSet(occupants);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE);
buf.append("\" roomID=\"").append(roomID).append("\">");
synchronized (occupants) {
for (OccupantInfo occupant : occupants) {
buf.append("<occupant>");
// Add the occupant jid
buf.append("<jid>");
buf.append(occupant.getJID());
buf.append("</jid>");
// Add the occupant nickname
buf.append("<name>");
buf.append(occupant.getNickname());
buf.append("</name>");
// Add the date when the occupant joined the room
buf.append("<joined>");
buf.append(UTC_FORMAT.format(occupant.getJoined()));
buf.append("</joined>");
buf.append("</occupant>");
}
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
public static class OccupantInfo {
private String jid;
private String nickname;
private Date joined;
public OccupantInfo(String jid, String nickname, Date joined) {
this.jid = jid;
this.nickname = nickname;
this.joined = joined;
}
public String getJID() {
return jid;
}
public String getNickname() {
return nickname;
}
public Date getJoined() {
return joined;
}
}
/**
* Packet extension provider for AgentStatusRequest packets.
*/
public static class Provider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
OccupantsInfo occupantsInfo = new OccupantsInfo(parser.getAttributeValue("", "roomID"));
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) &&
("occupant".equals(parser.getName()))) {
occupantsInfo.occupants.add(parseOccupantInfo(parser));
} else if (eventType == XmlPullParser.END_TAG &&
ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return occupantsInfo;
}
private OccupantInfo parseOccupantInfo(XmlPullParser parser) throws Exception {
boolean done = false;
String jid = null;
String nickname = null;
Date joined = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("jid".equals(parser.getName()))) {
jid = parser.nextText();
} else if ((eventType == XmlPullParser.START_TAG) &&
("nickname".equals(parser.getName()))) {
nickname = parser.nextText();
} else if ((eventType == XmlPullParser.START_TAG) &&
("joined".equals(parser.getName()))) {
joined = UTC_FORMAT.parse(parser.nextText());
} else if (eventType == XmlPullParser.END_TAG &&
"occupant".equals(parser.getName())) {
done = true;
}
}
return new OccupantInfo(jid, nickname, joined);
}
}
}

View File

@ -0,0 +1,210 @@
/**
* $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.packet;
import org.jivesoftware.smackx.workgroup.MetaData;
import org.jivesoftware.smackx.workgroup.agent.InvitationRequest;
import org.jivesoftware.smackx.workgroup.agent.OfferContent;
import org.jivesoftware.smackx.workgroup.agent.TransferRequest;
import org.jivesoftware.smackx.workgroup.agent.UserRequest;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
import java.util.HashMap;
import java.util.Map;
/**
* An IQProvider for agent offer requests.
*
* @author loki der quaeler
*/
public class OfferRequestProvider implements IQProvider {
public OfferRequestProvider() {
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
int eventType = parser.getEventType();
String sessionID = null;
int timeout = -1;
OfferContent content = null;
boolean done = false;
Map metaData = new HashMap();
if (eventType != XmlPullParser.START_TAG) {
// throw exception
}
String userJID = parser.getAttributeValue("", "jid");
// Default userID to the JID.
String userID = userJID;
while (!done) {
eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
String elemName = parser.getName();
if ("timeout".equals(elemName)) {
timeout = Integer.parseInt(parser.nextText());
}
else if (MetaData.ELEMENT_NAME.equals(elemName)) {
metaData = MetaDataUtils.parseMetaData(parser);
}
else if (SessionID.ELEMENT_NAME.equals(elemName)) {
sessionID = parser.getAttributeValue("", "id");
}
else if (UserID.ELEMENT_NAME.equals(elemName)) {
userID = parser.getAttributeValue("", "id");
}
else if ("user-request".equals(elemName)) {
content = UserRequest.getInstance();
}
else if (RoomInvitation.ELEMENT_NAME.equals(elemName)) {
RoomInvitation invitation = (RoomInvitation) PacketParserUtils
.parsePacketExtension(RoomInvitation.ELEMENT_NAME, RoomInvitation.NAMESPACE, parser);
content = new InvitationRequest(invitation.getInviter(), invitation.getRoom(),
invitation.getReason());
}
else if (RoomTransfer.ELEMENT_NAME.equals(elemName)) {
RoomTransfer transfer = (RoomTransfer) PacketParserUtils
.parsePacketExtension(RoomTransfer.ELEMENT_NAME, RoomTransfer.NAMESPACE, parser);
content = new TransferRequest(transfer.getInviter(), transfer.getRoom(), transfer.getReason());
}
}
else if (eventType == XmlPullParser.END_TAG) {
if ("offer".equals(parser.getName())) {
done = true;
}
}
}
OfferRequestPacket offerRequest =
new OfferRequestPacket(userJID, userID, timeout, metaData, sessionID, content);
offerRequest.setType(IQ.Type.SET);
return offerRequest;
}
public static class OfferRequestPacket extends IQ {
private int timeout;
private String userID;
private String userJID;
private Map metaData;
private String sessionID;
private OfferContent content;
public OfferRequestPacket(String userJID, String userID, int timeout, Map metaData,
String sessionID, OfferContent content)
{
this.userJID = userJID;
this.userID = userID;
this.timeout = timeout;
this.metaData = metaData;
this.sessionID = sessionID;
this.content = content;
}
/**
* Returns the userID, which is either the same as the userJID or a special
* value that the user provided as part of their "join queue" request.
*
* @return the user ID.
*/
public String getUserID() {
return userID;
}
/**
* The JID of the user that made the "join queue" request.
*
* @return the user JID.
*/
public String getUserJID() {
return userJID;
}
/**
* Returns the session ID associated with the request and ensuing chat. If the offer
* does not contain a session ID, <tt>null</tt> will be returned.
*
* @return the session id associated with the request.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the number of seconds the agent has to accept the offer before
* it times out.
*
* @return the offer timeout (in seconds).
*/
public int getTimeout() {
return this.timeout;
}
public OfferContent getContent() {
return content;
}
/**
* Returns any meta-data associated with the offer.
*
* @return meta-data associated with the offer.
*/
public Map getMetaData() {
return this.metaData;
}
public String getChildElementXML () {
StringBuilder buf = new StringBuilder();
buf.append("<offer xmlns=\"http://jabber.org/protocol/workgroup\" jid=\"").append(userJID).append("\">");
buf.append("<timeout>").append(timeout).append("</timeout>");
if (sessionID != null) {
buf.append('<').append(SessionID.ELEMENT_NAME);
buf.append(" session=\"");
buf.append(getSessionID()).append("\" xmlns=\"");
buf.append(SessionID.NAMESPACE).append("\"/>");
}
if (metaData != null) {
buf.append(MetaDataUtils.serializeMetaData(metaData));
}
if (userID != null) {
buf.append('<').append(UserID.ELEMENT_NAME);
buf.append(" id=\"");
buf.append(userID).append("\" xmlns=\"");
buf.append(UserID.NAMESPACE).append("\"/>");
}
buf.append("</offer>");
return buf.toString();
}
}
}

View File

@ -0,0 +1,112 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* An IQProvider class which has savvy about the offer-revoke tag.<br>
*
* @author loki der quaeler
*/
public class OfferRevokeProvider implements IQProvider {
public IQ parseIQ (XmlPullParser parser) throws Exception {
// The parser will be positioned on the opening IQ tag, so get the JID attribute.
String userJID = parser.getAttributeValue("", "jid");
// Default the userID to the JID.
String userID = userJID;
String reason = null;
String sessionID = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && parser.getName().equals("reason")) {
reason = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG)
&& parser.getName().equals(SessionID.ELEMENT_NAME)) {
sessionID = parser.getAttributeValue("", "id");
}
else if ((eventType == XmlPullParser.START_TAG)
&& parser.getName().equals(UserID.ELEMENT_NAME)) {
userID = parser.getAttributeValue("", "id");
}
else if ((eventType == XmlPullParser.END_TAG) && parser.getName().equals(
"offer-revoke"))
{
done = true;
}
}
return new OfferRevokePacket(userJID, userID, reason, sessionID);
}
public class OfferRevokePacket extends IQ {
private String userJID;
private String userID;
private String sessionID;
private String reason;
public OfferRevokePacket (String userJID, String userID, String cause, String sessionID) {
this.userJID = userJID;
this.userID = userID;
this.reason = cause;
this.sessionID = sessionID;
}
public String getUserJID() {
return userJID;
}
public String getUserID() {
return this.userID;
}
public String getReason() {
return this.reason;
}
public String getSessionID() {
return this.sessionID;
}
public String getChildElementXML () {
StringBuilder buf = new StringBuilder();
buf.append("<offer-revoke xmlns=\"http://jabber.org/protocol/workgroup\" jid=\"").append(userID).append("\">");
if (reason != null) {
buf.append("<reason>").append(reason).append("</reason>");
}
if (sessionID != null) {
buf.append(new SessionID(sessionID).toXML());
}
if (userID != null) {
buf.append(new UserID(userID).toXML());
}
buf.append("</offer-revoke>");
return buf.toString();
}
}
}

View File

@ -0,0 +1,200 @@
/**
* $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.packet;
import org.jivesoftware.smackx.workgroup.QueueUser;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Queue details packet extension, which contains details about the users
* currently in a queue.
*/
public class QueueDetails implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "notify-queue-details";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
/**
* The list of users in the queue.
*/
private Set users;
/**
* Creates a new QueueDetails packet
*/
private QueueDetails() {
users = new HashSet();
}
/**
* Returns the number of users currently in the queue that are waiting to
* be routed to an agent.
*
* @return the number of users in the queue.
*/
public int getUserCount() {
return users.size();
}
/**
* Returns the set of users in the queue that are waiting to
* be routed to an agent (as QueueUser objects).
*
* @return a Set for the users waiting in a queue.
*/
public Set getUsers() {
synchronized (users) {
return users;
}
}
/**
* Adds a user to the packet.
*
* @param user the user.
*/
private void addUser(QueueUser user) {
synchronized (users) {
users.add(user);
}
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
synchronized (users) {
for (Iterator i=users.iterator(); i.hasNext(); ) {
QueueUser user = (QueueUser)i.next();
int position = user.getQueuePosition();
int timeRemaining = user.getEstimatedRemainingTime();
Date timestamp = user.getQueueJoinTimestamp();
buf.append("<user jid=\"").append(user.getUserID()).append("\">");
if (position != -1) {
buf.append("<position>").append(position).append("</position>");
}
if (timeRemaining != -1) {
buf.append("<time>").append(timeRemaining).append("</time>");
}
if (timestamp != null) {
buf.append("<join-time>");
buf.append(DATE_FORMATTER.format(timestamp));
buf.append("</join-time>");
}
buf.append("</user>");
}
}
buf.append("</").append(ELEMENT_NAME).append(">");
return buf.toString();
}
/**
* Provider class for QueueDetails packet extensions.
*/
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
QueueDetails queueDetails = new QueueDetails();
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_TAG &&
"notify-queue-details".equals(parser.getName()))
{
eventType = parser.next();
while ((eventType == XmlPullParser.START_TAG) && "user".equals(parser.getName())) {
String uid = null;
int position = -1;
int time = -1;
Date joinTime = null;
uid = parser.getAttributeValue("", "jid");
if (uid == null) {
// throw exception
}
eventType = parser.next();
while ((eventType != XmlPullParser.END_TAG)
|| (! "user".equals(parser.getName())))
{
if ("position".equals(parser.getName())) {
position = Integer.parseInt(parser.nextText());
}
else if ("time".equals(parser.getName())) {
time = Integer.parseInt(parser.nextText());
}
else if ("join-time".equals(parser.getName())) {
joinTime = DATE_FORMATTER.parse(parser.nextText());
}
else if( parser.getName().equals( "waitTime" ) ) {
Date wait = DATE_FORMATTER.parse( parser.nextText() );
System.out.println( wait );
}
eventType = parser.next();
if (eventType != XmlPullParser.END_TAG) {
// throw exception
}
}
queueDetails.addUser(new QueueUser(uid, position, time, joinTime));
eventType = parser.next();
}
}
return queueDetails;
}
}
}

View File

@ -0,0 +1,158 @@
/**
* $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.packet;
import org.jivesoftware.smackx.workgroup.agent.WorkgroupQueue;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.SimpleDateFormat;
import java.util.Date;
public class QueueOverview implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static String ELEMENT_NAME = "notify-queue";
/**
* Namespace of the packet extension.
*/
public static String NAMESPACE = "http://jabber.org/protocol/workgroup";
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
private int averageWaitTime;
private Date oldestEntry;
private int userCount;
private WorkgroupQueue.Status status;
QueueOverview() {
this.averageWaitTime = -1;
this.oldestEntry = null;
this.userCount = -1;
this.status = null;
}
void setAverageWaitTime(int averageWaitTime) {
this.averageWaitTime = averageWaitTime;
}
public int getAverageWaitTime () {
return averageWaitTime;
}
void setOldestEntry(Date oldestEntry) {
this.oldestEntry = oldestEntry;
}
public Date getOldestEntry() {
return oldestEntry;
}
void setUserCount(int userCount) {
this.userCount = userCount;
}
public int getUserCount() {
return userCount;
}
public WorkgroupQueue.Status getStatus() {
return status;
}
void setStatus(WorkgroupQueue.Status status) {
this.status = status;
}
public String getElementName () {
return ELEMENT_NAME;
}
public String getNamespace () {
return NAMESPACE;
}
public String toXML () {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
if (userCount != -1) {
buf.append("<count>").append(userCount).append("</count>");
}
if (oldestEntry != null) {
buf.append("<oldest>").append(DATE_FORMATTER.format(oldestEntry)).append("</oldest>");
}
if (averageWaitTime != -1) {
buf.append("<time>").append(averageWaitTime).append("</time>");
}
if (status != null) {
buf.append("<status>").append(status).append("</status>");
}
buf.append("</").append(ELEMENT_NAME).append(">");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension (XmlPullParser parser) throws Exception {
int eventType = parser.getEventType();
QueueOverview queueOverview = new QueueOverview();
if (eventType != XmlPullParser.START_TAG) {
// throw exception
}
eventType = parser.next();
while ((eventType != XmlPullParser.END_TAG)
|| (!ELEMENT_NAME.equals(parser.getName())))
{
if ("count".equals(parser.getName())) {
queueOverview.setUserCount(Integer.parseInt(parser.nextText()));
}
else if ("time".equals(parser.getName())) {
queueOverview.setAverageWaitTime(Integer.parseInt(parser.nextText()));
}
else if ("oldest".equals(parser.getName())) {
queueOverview.setOldestEntry((DATE_FORMATTER.parse(parser.nextText())));
}
else if ("status".equals(parser.getName())) {
queueOverview.setStatus(WorkgroupQueue.Status.fromString(parser.nextText()));
}
eventType = parser.next();
if (eventType != XmlPullParser.END_TAG) {
// throw exception
}
}
if (eventType != XmlPullParser.END_TAG) {
// throw exception
}
return queueOverview;
}
}
}

View File

@ -0,0 +1,122 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* An IQ packet that encapsulates both types of workgroup queue
* status notifications -- position updates, and estimated time
* left in the queue updates.
*/
public class QueueUpdate implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "queue-status";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private int position;
private int remainingTime;
public QueueUpdate(int position, int remainingTime) {
this.position = position;
this.remainingTime = remainingTime;
}
/**
* Returns the user's position in the workgroup queue, or -1 if the
* value isn't set on this packet.
*
* @return the position in the workgroup queue.
*/
public int getPosition() {
return this.position;
}
/**
* Returns the user's estimated time left in the workgroup queue, or
* -1 if the value isn't set on this packet.
*
* @return the estimated time left in the workgroup queue.
*/
public int getRemaingTime() {
return remainingTime;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<queue-status xmlns=\"http://jabber.org/protocol/workgroup\">");
if (position != -1) {
buf.append("<position>").append(position).append("</position>");
}
if (remainingTime != -1) {
buf.append("<time>").append(remainingTime).append("</time>");
}
buf.append("</queue-status>");
return buf.toString();
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
boolean done = false;
int position = -1;
int timeRemaining = -1;
while (!done) {
parser.next();
String elementName = parser.getName();
if (parser.getEventType() == XmlPullParser.START_TAG && "position".equals(elementName)) {
try {
position = Integer.parseInt(parser.nextText());
}
catch (NumberFormatException nfe) {
}
}
else if (parser.getEventType() == XmlPullParser.START_TAG && "time".equals(elementName)) {
try {
timeRemaining = Integer.parseInt(parser.nextText());
}
catch (NumberFormatException nfe) {
}
}
else if (parser.getEventType() == XmlPullParser.END_TAG && "queue-status".equals(elementName)) {
done = true;
}
}
return new QueueUpdate(position, timeRemaining);
}
}
}

View File

@ -0,0 +1,177 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* Packet extension for {@link org.jivesoftware.smackx.workgroup.agent.InvitationRequest}.
*
* @author Gaston Dombiak
*/
public class RoomInvitation implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "invite";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
/**
* Type of entity being invited to a groupchat support session.
*/
private Type type;
/**
* JID of the entity being invited. The entity could be another agent, user , a queue or a workgroup. In
* the case of a queue or a workgroup the server will select the best agent to invite.
*/
private String invitee;
/**
* Full JID of the user that sent the invitation.
*/
private String inviter;
/**
* ID of the session that originated the initial user request.
*/
private String sessionID;
/**
* JID of the room to join if offer is accepted.
*/
private String room;
/**
* Text provided by the inviter explaining the reason why the invitee is invited.
*/
private String reason;
public RoomInvitation(Type type, String invitee, String sessionID, String reason) {
this.type = type;
this.invitee = invitee;
this.sessionID = sessionID;
this.reason = reason;
}
private RoomInvitation() {
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getInviter() {
return inviter;
}
public String getRoom() {
return room;
}
public String getReason() {
return reason;
}
public String getSessionID() {
return sessionID;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE);
buf.append("\" type=\"").append(type).append("\">");
buf.append("<session xmlns=\"http://jivesoftware.com/protocol/workgroup\" id=\"").append(sessionID).append("\"></session>");
if (invitee != null) {
buf.append("<invitee>").append(invitee).append("</invitee>");
}
if (inviter != null) {
buf.append("<inviter>").append(inviter).append("</inviter>");
}
if (reason != null) {
buf.append("<reason>").append(reason).append("</reason>");
}
// Add packet extensions, if any are defined.
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Type of entity being invited to a groupchat support session.
*/
public static enum Type {
/**
* A user is being invited to a groupchat support session. The user could be another agent
* or just a regular XMPP user.
*/
user,
/**
* Some agent of the specified queue will be invited to the groupchat support session.
*/
queue,
/**
* Some agent of the specified workgroup will be invited to the groupchat support session.
*/
workgroup
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
final RoomInvitation invitation = new RoomInvitation();
invitation.type = Type.valueOf(parser.getAttributeValue("", "type"));
boolean done = false;
while (!done) {
parser.next();
String elementName = parser.getName();
if (parser.getEventType() == XmlPullParser.START_TAG) {
if ("session".equals(elementName)) {
invitation.sessionID = parser.getAttributeValue("", "id");
}
else if ("invitee".equals(elementName)) {
invitation.invitee = parser.nextText();
}
else if ("inviter".equals(elementName)) {
invitation.inviter = parser.nextText();
}
else if ("reason".equals(elementName)) {
invitation.reason = parser.nextText();
}
else if ("room".equals(elementName)) {
invitation.room = parser.nextText();
}
}
else if (parser.getEventType() == XmlPullParser.END_TAG && ELEMENT_NAME.equals(elementName)) {
done = true;
}
}
return invitation;
}
}
}

View File

@ -0,0 +1,177 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* Packet extension for {@link org.jivesoftware.smackx.workgroup.agent.TransferRequest}.
*
* @author Gaston Dombiak
*/
public class RoomTransfer implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "transfer";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
/**
* Type of entity being invited to a groupchat support session.
*/
private RoomTransfer.Type type;
/**
* JID of the entity being invited. The entity could be another agent, user , a queue or a workgroup. In
* the case of a queue or a workgroup the server will select the best agent to invite.
*/
private String invitee;
/**
* Full JID of the user that sent the invitation.
*/
private String inviter;
/**
* ID of the session that originated the initial user request.
*/
private String sessionID;
/**
* JID of the room to join if offer is accepted.
*/
private String room;
/**
* Text provided by the inviter explaining the reason why the invitee is invited.
*/
private String reason;
public RoomTransfer(RoomTransfer.Type type, String invitee, String sessionID, String reason) {
this.type = type;
this.invitee = invitee;
this.sessionID = sessionID;
this.reason = reason;
}
private RoomTransfer() {
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getInviter() {
return inviter;
}
public String getRoom() {
return room;
}
public String getReason() {
return reason;
}
public String getSessionID() {
return sessionID;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE);
buf.append("\" type=\"").append(type).append("\">");
buf.append("<session xmlns=\"http://jivesoftware.com/protocol/workgroup\" id=\"").append(sessionID).append("\"></session>");
if (invitee != null) {
buf.append("<invitee>").append(invitee).append("</invitee>");
}
if (inviter != null) {
buf.append("<inviter>").append(inviter).append("</inviter>");
}
if (reason != null) {
buf.append("<reason>").append(reason).append("</reason>");
}
// Add packet extensions, if any are defined.
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Type of entity being invited to a groupchat support session.
*/
public static enum Type {
/**
* A user is being invited to a groupchat support session. The user could be another agent
* or just a regular XMPP user.
*/
user,
/**
* Some agent of the specified queue will be invited to the groupchat support session.
*/
queue,
/**
* Some agent of the specified workgroup will be invited to the groupchat support session.
*/
workgroup
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
final RoomTransfer invitation = new RoomTransfer();
invitation.type = RoomTransfer.Type.valueOf(parser.getAttributeValue("", "type"));
boolean done = false;
while (!done) {
parser.next();
String elementName = parser.getName();
if (parser.getEventType() == XmlPullParser.START_TAG) {
if ("session".equals(elementName)) {
invitation.sessionID = parser.getAttributeValue("", "id");
}
else if ("invitee".equals(elementName)) {
invitation.invitee = parser.nextText();
}
else if ("inviter".equals(elementName)) {
invitation.inviter = parser.nextText();
}
else if ("reason".equals(elementName)) {
invitation.reason = parser.nextText();
}
else if ("room".equals(elementName)) {
invitation.room = parser.nextText();
}
}
else if (parser.getEventType() == XmlPullParser.END_TAG && ELEMENT_NAME.equals(elementName)) {
done = true;
}
}
return invitation;
}
}
}

View File

@ -0,0 +1,77 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
public class SessionID implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "session";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String sessionID;
public SessionID(String sessionID) {
this.sessionID = sessionID;
}
public String getSessionID() {
return this.sessionID;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\" ");
buf.append("id=\"").append(this.getSessionID());
buf.append("\"/>");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
String sessionID = parser.getAttributeValue("", "id");
// Advance to end of extension.
parser.next();
return new SessionID(sessionID);
}
}
}

View File

@ -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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Represents the conversation transcript that occured in a group chat room between an Agent
* and a user that requested assistance. The transcript contains all the Messages that were sent
* to the room as well as the sent presences.
*
* @author Gaston Dombiak
*/
public class Transcript extends IQ {
private String sessionID;
private List packets;
/**
* Creates a transcript request for the given sessionID.
*
* @param sessionID the id of the session to get the conversation transcript.
*/
public Transcript(String sessionID) {
this.sessionID = sessionID;
this.packets = new ArrayList();
}
/**
* Creates a new transcript for the given sessionID and list of packets. The list of packets
* may include Messages and/or Presences.
*
* @param sessionID the id of the session that generated this conversation transcript.
* @param packets the list of messages and presences send to the room.
*/
public Transcript(String sessionID, List packets) {
this.sessionID = sessionID;
this.packets = packets;
}
/**
* Returns id of the session that generated this conversation transcript. The sessionID is a
* value generated by the server when a new request is received.
*
* @return id of the session that generated this conversation transcript.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the list of Messages and Presences that were sent to the room.
*
* @return the list of Messages and Presences that were sent to the room.
*/
public List getPackets() {
return Collections.unmodifiableList(packets);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<transcript xmlns=\"http://jivesoftware.com/protocol/workgroup\" sessionID=\"")
.append(sessionID)
.append("\">");
for (Iterator it=packets.iterator(); it.hasNext();) {
Packet packet = (Packet) it.next();
buf.append(packet.toXML());
}
buf.append("</transcript>");
return buf.toString();
}
}

View File

@ -0,0 +1,65 @@
/**
* $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.packet;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.List;
/**
* An IQProvider for transcripts.
*
* @author Gaston Dombiak
*/
public class TranscriptProvider implements IQProvider {
public TranscriptProvider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
String sessionID = parser.getAttributeValue("", "sessionID");
List packets = new ArrayList();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("message")) {
packets.add(PacketParserUtils.parseMessage(parser));
}
else if (parser.getName().equals("presence")) {
packets.add(PacketParserUtils.parsePresence(parser));
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("transcript")) {
done = true;
}
}
}
return new Transcript(sessionID, packets);
}
}

View File

@ -0,0 +1,87 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
/**
* IQ packet for retrieving the transcript search form, submiting the completed search form
* or retrieving the answer of a transcript search.
*
* @author Gaston Dombiak
*/
public class TranscriptSearch extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "transcript-search";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for TranscriptSearch packets.
*
* @author Gaston Dombiak
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
TranscriptSearch answer = new TranscriptSearch();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
// Parse the packet extension
answer.addExtension(PacketParserUtils.parsePacketExtension(parser.getName(), parser.getNamespace(), parser));
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return answer;
}
}
}

View File

@ -0,0 +1,247 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Represents a list of conversation transcripts that a user had in all his history. Each
* transcript summary includes the sessionID which may be used for getting more detailed
* information about the conversation. {@link org.jivesoftware.smackx.workgroup.packet.Transcript}
*
* @author Gaston Dombiak
*/
public class Transcripts extends IQ {
private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
}
private String userID;
private List<Transcripts.TranscriptSummary> summaries;
/**
* Creates a transcripts request for the given userID.
*
* @param userID the id of the user to get his conversations transcripts.
*/
public Transcripts(String userID) {
this.userID = userID;
this.summaries = new ArrayList<Transcripts.TranscriptSummary>();
}
/**
* Creates a Transcripts which will contain the transcript summaries of the given user.
*
* @param userID the id of the user. Could be a real JID or a unique String that identifies
* anonymous users.
* @param summaries the list of TranscriptSummaries.
*/
public Transcripts(String userID, List<Transcripts.TranscriptSummary> summaries) {
this.userID = userID;
this.summaries = summaries;
}
/**
* Returns the id of the user that was involved in the conversations. The userID could be a
* real JID if the connected user was not anonymous. Otherwise, the userID will be a String
* that was provided by the anonymous user as a way to idenitify the user across many user
* sessions.
*
* @return the id of the user that was involved in the conversations.
*/
public String getUserID() {
return userID;
}
/**
* Returns a list of TranscriptSummary. A TranscriptSummary does not contain the conversation
* transcript but some summary information like the sessionID and the time when the
* conversation started and finished. Once you have the sessionID it is possible to get the
* full conversation transcript.
*
* @return a list of TranscriptSummary.
*/
public List<Transcripts.TranscriptSummary> getSummaries() {
return Collections.unmodifiableList(summaries);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<transcripts xmlns=\"http://jivesoftware.com/protocol/workgroup\" userID=\"")
.append(userID)
.append("\">");
for (TranscriptSummary transcriptSummary : summaries) {
buf.append(transcriptSummary.toXML());
}
buf.append("</transcripts>");
return buf.toString();
}
/**
* A TranscriptSummary contains some information about a conversation such as the ID of the
* session or the date when the conversation started and finished. You will need to use the
* sessionID to get the full conversation transcript.
*/
public static class TranscriptSummary {
private String sessionID;
private Date joinTime;
private Date leftTime;
private List<AgentDetail> agentDetails;
public TranscriptSummary(String sessionID, Date joinTime, Date leftTime, List<AgentDetail> agentDetails) {
this.sessionID = sessionID;
this.joinTime = joinTime;
this.leftTime = leftTime;
this.agentDetails = agentDetails;
}
/**
* Returns the ID of the session that is related to this conversation transcript. The
* sessionID could be used for getting the full conversation transcript.
*
* @return the ID of the session that is related to this conversation transcript.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the Date when the conversation started.
*
* @return the Date when the conversation started.
*/
public Date getJoinTime() {
return joinTime;
}
/**
* Returns the Date when the conversation finished.
*
* @return the Date when the conversation finished.
*/
public Date getLeftTime() {
return leftTime;
}
/**
* Returns a list of AgentDetails. For each Agent that was involved in the conversation
* the list will include an AgentDetail. An AgentDetail contains the JID of the agent
* as well as the time when the Agent joined and left the conversation.
*
* @return a list of AgentDetails.
*/
public List<AgentDetail> getAgentDetails() {
return agentDetails;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<transcript sessionID=\"")
.append(sessionID)
.append("\">");
if (joinTime != null) {
buf.append("<joinTime>").append(UTC_FORMAT.format(joinTime)).append("</joinTime>");
}
if (leftTime != null) {
buf.append("<leftTime>").append(UTC_FORMAT.format(leftTime)).append("</leftTime>");
}
buf.append("<agents>");
for (AgentDetail agentDetail : agentDetails) {
buf.append(agentDetail.toXML());
}
buf.append("</agents></transcript>");
return buf.toString();
}
}
/**
* An AgentDetail contains information of an Agent that was involved in a conversation.
*/
public static class AgentDetail {
private String agentJID;
private Date joinTime;
private Date leftTime;
public AgentDetail(String agentJID, Date joinTime, Date leftTime) {
this.agentJID = agentJID;
this.joinTime = joinTime;
this.leftTime = leftTime;
}
/**
* Returns the bare JID of the Agent that was involved in the conversation.
*
* @return the bared JID of the Agent that was involved in the conversation.
*/
public String getAgentJID() {
return agentJID;
}
/**
* Returns the Date when the Agent joined the conversation.
*
* @return the Date when the Agent joined the conversation.
*/
public Date getJoinTime() {
return joinTime;
}
/**
* Returns the Date when the Agent left the conversation.
*
* @return the Date when the Agent left the conversation.
*/
public Date getLeftTime() {
return leftTime;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<agent>");
if (agentJID != null) {
buf.append("<agentJID>").append(agentJID).append("</agentJID>");
}
if (joinTime != null) {
buf.append("<joinTime>").append(UTC_FORMAT.format(joinTime)).append("</joinTime>");
}
if (leftTime != null) {
buf.append("<leftTime>").append(UTC_FORMAT.format(leftTime)).append("</leftTime>");
}
buf.append("</agent>");
return buf.toString();
}
}
}

View File

@ -0,0 +1,148 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
/**
* An IQProvider for transcripts summaries.
*
* @author Gaston Dombiak
*/
public class TranscriptsProvider implements IQProvider {
private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
}
public TranscriptsProvider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
String userID = parser.getAttributeValue("", "userID");
List<Transcripts.TranscriptSummary> summaries = new ArrayList<Transcripts.TranscriptSummary>();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("transcript")) {
summaries.add(parseSummary(parser));
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("transcripts")) {
done = true;
}
}
}
return new Transcripts(userID, summaries);
}
private Transcripts.TranscriptSummary parseSummary(XmlPullParser parser) throws IOException,
XmlPullParserException {
String sessionID = parser.getAttributeValue("", "sessionID");
Date joinTime = null;
Date leftTime = null;
List<Transcripts.AgentDetail> agents = new ArrayList<Transcripts.AgentDetail>();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("joinTime")) {
try {
joinTime = UTC_FORMAT.parse(parser.nextText());
} catch (ParseException e) {}
}
else if (parser.getName().equals("leftTime")) {
try {
leftTime = UTC_FORMAT.parse(parser.nextText());
} catch (ParseException e) {}
}
else if (parser.getName().equals("agents")) {
agents = parseAgents(parser);
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("transcript")) {
done = true;
}
}
}
return new Transcripts.TranscriptSummary(sessionID, joinTime, leftTime, agents);
}
private List<Transcripts.AgentDetail> parseAgents(XmlPullParser parser) throws IOException, XmlPullParserException {
List<Transcripts.AgentDetail> agents = new ArrayList<Transcripts.AgentDetail>();
String agentJID = null;
Date joinTime = null;
Date leftTime = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("agentJID")) {
agentJID = parser.nextText();
}
else if (parser.getName().equals("joinTime")) {
try {
joinTime = UTC_FORMAT.parse(parser.nextText());
} catch (ParseException e) {}
}
else if (parser.getName().equals("leftTime")) {
try {
leftTime = UTC_FORMAT.parse(parser.nextText());
} catch (ParseException e) {}
}
else if (parser.getName().equals("agent")) {
agentJID = null;
joinTime = null;
leftTime = null;
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("agents")) {
done = true;
}
else if (parser.getName().equals("agent")) {
agents.add(new Transcripts.AgentDetail(agentJID, joinTime, leftTime));
}
}
}
return agents;
}
}

View File

@ -0,0 +1,77 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
public class UserID implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "user";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String userID;
public UserID(String userID) {
this.userID = userID;
}
public String getUserID() {
return this.userID;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\" ");
buf.append("id=\"").append(this.getUserID());
buf.append("\"/>");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
String userID = parser.getAttributeValue("", "id");
// Advance to end of extension.
parser.next();
return new UserID(userID);
}
}
}

View File

@ -0,0 +1,86 @@
/**
* $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.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* A packet extension that contains information about the user and agent in a
* workgroup chat. The packet extension is attached to group chat invitations.
*/
public class WorkgroupInformation implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "workgroup";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private String workgroupJID;
public WorkgroupInformation(String workgroupJID){
this.workgroupJID = workgroupJID;
}
public String getWorkgroupJID() {
return workgroupJID;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append('<').append(ELEMENT_NAME);
buf.append(" jid=\"").append(getWorkgroupJID()).append("\"");
buf.append(" xmlns=\"").append(NAMESPACE).append("\" />");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider {
/**
* PacketExtensionProvider implementation
*/
public PacketExtension parseExtension (XmlPullParser parser)
throws Exception {
String workgroupJID = parser.getAttributeValue("", "jid");
// since this is a start and end tag, and we arrive on the start, this should guarantee
// we leave on the end
parser.next();
return new WorkgroupInformation(workgroupJID);
}
}
}

View File

@ -0,0 +1,56 @@
/**
* $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.settings;
public class ChatSetting {
private String key;
private String value;
private int type;
public ChatSetting(String key, String value, int type){
setKey(key);
setValue(value);
setType(type);
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}

View File

@ -0,0 +1,179 @@
/**
* $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.settings;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class ChatSettings extends IQ {
/**
* Defined as image type.
*/
public static final int IMAGE_SETTINGS = 0;
/**
* Defined as Text settings type.
*/
public static final int TEXT_SETTINGS = 1;
/**
* Defined as Bot settings type.
*/
public static final int BOT_SETTINGS = 2;
private List settings;
private String key;
private int type = -1;
public ChatSettings() {
settings = new ArrayList();
}
public ChatSettings(String key) {
setKey(key);
}
public void setKey(String key) {
this.key = key;
}
public void setType(int type) {
this.type = type;
}
public void addSetting(ChatSetting setting) {
settings.add(setting);
}
public Collection getSettings() {
return settings;
}
public ChatSetting getChatSetting(String key) {
Collection col = getSettings();
if (col != null) {
Iterator iter = col.iterator();
while (iter.hasNext()) {
ChatSetting chatSetting = (ChatSetting)iter.next();
if (chatSetting.getKey().equals(key)) {
return chatSetting;
}
}
}
return null;
}
public ChatSetting getFirstEntry() {
if (settings.size() > 0) {
return (ChatSetting)settings.get(0);
}
return null;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "chat-settings";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
if (key != null) {
buf.append(" key=\"" + key + "\"");
}
if (type != -1) {
buf.append(" type=\"" + type + "\"");
}
buf.append("></").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for AgentStatusRequest packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
ChatSettings chatSettings = new ChatSettings();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("chat-setting".equals(parser.getName()))) {
chatSettings.addSetting(parseChatSetting(parser));
}
else if (eventType == XmlPullParser.END_TAG && ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return chatSettings;
}
private ChatSetting parseChatSetting(XmlPullParser parser) throws Exception {
boolean done = false;
String key = null;
String value = null;
int type = 0;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("key".equals(parser.getName()))) {
key = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("value".equals(parser.getName()))) {
value = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("type".equals(parser.getName()))) {
type = Integer.parseInt(parser.nextText());
}
else if (eventType == XmlPullParser.END_TAG && "chat-setting".equals(parser.getName())) {
done = true;
}
}
return new ChatSetting(key, value, type);
}
}
}

View File

@ -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.settings;
import org.jivesoftware.smackx.workgroup.util.ModelUtil;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.HashMap;
import java.util.Map;
public class GenericSettings extends IQ {
private Map map = new HashMap();
private String query;
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "generic-metadata";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append(">");
if (ModelUtil.hasLength(getQuery())) {
buf.append("<query>" + getQuery() + "</query>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for SoundSetting Packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
GenericSettings setting = new GenericSettings();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("entry".equals(parser.getName()))) {
eventType = parser.next();
String name = parser.nextText();
eventType = parser.next();
String value = parser.nextText();
setting.getMap().put(name, value);
}
else if (eventType == XmlPullParser.END_TAG && ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return setting;
}
}
}

View File

@ -0,0 +1,155 @@
/**
* $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.settings;
import org.jivesoftware.smackx.workgroup.util.ModelUtil;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
public class OfflineSettings extends IQ {
private String redirectURL;
private String offlineText;
private String emailAddress;
private String subject;
public String getRedirectURL() {
if (!ModelUtil.hasLength(redirectURL)) {
return "";
}
return redirectURL;
}
public void setRedirectURL(String redirectURL) {
this.redirectURL = redirectURL;
}
public String getOfflineText() {
if (!ModelUtil.hasLength(offlineText)) {
return "";
}
return offlineText;
}
public void setOfflineText(String offlineText) {
this.offlineText = offlineText;
}
public String getEmailAddress() {
if (!ModelUtil.hasLength(emailAddress)) {
return "";
}
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getSubject() {
if (!ModelUtil.hasLength(subject)) {
return "";
}
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public boolean redirects() {
return (ModelUtil.hasLength(getRedirectURL()));
}
public boolean isConfigured(){
return ModelUtil.hasLength(getEmailAddress()) &&
ModelUtil.hasLength(getSubject()) &&
ModelUtil.hasLength(getOfflineText());
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "offline-settings";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append("></").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for AgentStatusRequest packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
OfflineSettings offlineSettings = new OfflineSettings();
boolean done = false;
String redirectPage = null;
String subject = null;
String offlineText = null;
String emailAddress = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("redirectPage".equals(parser.getName()))) {
redirectPage = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("subject".equals(parser.getName()))) {
subject = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("offlineText".equals(parser.getName()))) {
offlineText = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("emailAddress".equals(parser.getName()))) {
emailAddress = parser.nextText();
}
else if (eventType == XmlPullParser.END_TAG && "offline-settings".equals(parser.getName())) {
done = true;
}
}
offlineSettings.setEmailAddress(emailAddress);
offlineSettings.setRedirectURL(redirectPage);
offlineSettings.setSubject(subject);
offlineSettings.setOfflineText(offlineText);
return offlineSettings;
}
}
}

View File

@ -0,0 +1,108 @@
/**
* $RCSfile$
* $Revision: 38648 $
* $Date: 2006-12-27 01:46:18 -0800 (Wed, 27 Dec 2006) $
*
* Copyright (C) 1999-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software. Use is
subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.settings;
import org.jivesoftware.smackx.workgroup.util.ModelUtil;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
public class SearchSettings extends IQ {
private String forumsLocation;
private String kbLocation;
public boolean isSearchEnabled() {
return ModelUtil.hasLength(getForumsLocation()) && ModelUtil.hasLength(getKbLocation());
}
public String getForumsLocation() {
return forumsLocation;
}
public void setForumsLocation(String forumsLocation) {
this.forumsLocation = forumsLocation;
}
public String getKbLocation() {
return kbLocation;
}
public void setKbLocation(String kbLocation) {
this.kbLocation = kbLocation;
}
public boolean hasKB(){
return ModelUtil.hasLength(getKbLocation());
}
public boolean hasForums(){
return ModelUtil.hasLength(getForumsLocation());
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "search-settings";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append("></").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for AgentStatusRequest packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
SearchSettings settings = new SearchSettings();
boolean done = false;
String kb = null;
String forums = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("forums".equals(parser.getName()))) {
forums = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("kb".equals(parser.getName()))) {
kb = parser.nextText();
}
else if (eventType == XmlPullParser.END_TAG && "search-settings".equals(parser.getName())) {
done = true;
}
}
settings.setForumsLocation(forums);
settings.setKbLocation(kb);
return settings;
}
}
}

View File

@ -0,0 +1,103 @@
/**
* $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.settings;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.StringUtils;
import org.xmlpull.v1.XmlPullParser;
public class SoundSettings extends IQ {
private String outgoingSound;
private String incomingSound;
public void setOutgoingSound(String outgoingSound) {
this.outgoingSound = outgoingSound;
}
public void setIncomingSound(String incomingSound) {
this.incomingSound = incomingSound;
}
public byte[] getIncomingSoundBytes() {
return StringUtils.decodeBase64(incomingSound);
}
public byte[] getOutgoingSoundBytes() {
return StringUtils.decodeBase64(outgoingSound);
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "sound-settings";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append("></").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for SoundSetting Packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
SoundSettings soundSettings = new SoundSettings();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("outgoingSound".equals(parser.getName()))) {
soundSettings.setOutgoingSound(parser.nextText());
}
else if ((eventType == XmlPullParser.START_TAG) && ("incomingSound".equals(parser.getName()))) {
soundSettings.setIncomingSound(parser.nextText());
}
else if (eventType == XmlPullParser.END_TAG && "sound-settings".equals(parser.getName())) {
done = true;
}
}
return soundSettings;
}
}
}

View File

@ -0,0 +1,125 @@
/**
* $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.settings;
import org.jivesoftware.smackx.workgroup.util.ModelUtil;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
public class WorkgroupProperties extends IQ {
private boolean authRequired;
private String email;
private String fullName;
private String jid;
public boolean isAuthRequired() {
return authRequired;
}
public void setAuthRequired(boolean authRequired) {
this.authRequired = authRequired;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getJid() {
return jid;
}
public void setJid(String jid) {
this.jid = jid;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "workgroup-properties";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
if (ModelUtil.hasLength(getJid())) {
buf.append("jid=\"" + getJid() + "\" ");
}
buf.append("></").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for SoundSetting Packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
WorkgroupProperties props = new WorkgroupProperties();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("authRequired".equals(parser.getName()))) {
props.setAuthRequired(new Boolean(parser.nextText()).booleanValue());
}
else if ((eventType == XmlPullParser.START_TAG) && ("email".equals(parser.getName()))) {
props.setEmail(parser.nextText());
}
else if ((eventType == XmlPullParser.START_TAG) && ("name".equals(parser.getName()))) {
props.setFullName(parser.nextText());
}
else if (eventType == XmlPullParser.END_TAG && "workgroup-properties".equals(parser.getName())) {
done = true;
}
}
return props;
}
}
}

View File

@ -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.user;
/**
* Listener interface for those that wish to be notified of workgroup queue events.
*
* @see Workgroup#addQueueListener(QueueListener)
* @author loki der quaeler
*/
public interface QueueListener {
/**
* The user joined the workgroup queue.
*/
public void joinedQueue();
/**
* The user departed the workgroup queue.
*/
public void departedQueue();
/**
* The user's queue position has been updated to a new value.
*
* @param currentPosition the user's current position in the queue.
*/
public void queuePositionUpdated(int currentPosition);
/**
* The user's estimated remaining wait time in the queue has been updated.
*
* @param secondsRemaining the estimated number of seconds remaining until the
* the user is routed to the agent.
*/
public void queueWaitTimeUpdated(int secondsRemaining);
}

View File

@ -0,0 +1,938 @@
/**
* $RCSfile$
* $Revision: 38648 $
* $Date: 2006-12-27 01:46:18 -0800 (Wed, 27 Dec 2006) $
*
* Copyright (C) 2003-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.user;
import org.jivesoftware.smackx.workgroup.MetaData;
import org.jivesoftware.smackx.workgroup.WorkgroupInvitation;
import org.jivesoftware.smackx.workgroup.WorkgroupInvitationListener;
import org.jivesoftware.smackx.workgroup.ext.email.EmailIQ;
import org.jivesoftware.smackx.workgroup.ext.forms.WorkgroupForm;
import org.jivesoftware.smackx.workgroup.packet.DepartQueuePacket;
import org.jivesoftware.smackx.workgroup.packet.QueueUpdate;
import org.jivesoftware.smackx.workgroup.packet.SessionID;
import org.jivesoftware.smackx.workgroup.packet.UserID;
import org.jivesoftware.smackx.workgroup.settings.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.filter.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.Form;
import org.jivesoftware.smackx.FormField;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.packet.DataForm;
import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.smackx.packet.MUCUser;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Provides workgroup services for users. Users can join the workgroup queue, depart the
* queue, find status information about their placement in the queue, and register to
* be notified when they are routed to an agent.<p>
* <p/>
* This class only provides a users perspective into a workgroup and is not intended
* for use by agents.
*
* @author Matt Tucker
* @author Derek DeMoro
*/
public class Workgroup {
private String workgroupJID;
private XMPPConnection connection;
private boolean inQueue;
private List invitationListeners;
private List queueListeners;
private List siteInviteListeners;
private int queuePosition = -1;
private int queueRemainingTime = -1;
/**
* Creates a new workgroup instance using the specified workgroup JID
* (eg support@workgroup.example.com) and XMPP connection. The connection must have
* undergone a successful login before being used to construct an instance of
* this class.
*
* @param workgroupJID the JID of the workgroup.
* @param connection an XMPP connection which must have already undergone a
* successful login.
*/
public Workgroup(String workgroupJID, XMPPConnection connection) {
// Login must have been done before passing in connection.
if (!connection.isAuthenticated()) {
throw new IllegalStateException("Must login to server before creating workgroup.");
}
this.workgroupJID = workgroupJID;
this.connection = connection;
inQueue = false;
invitationListeners = new ArrayList();
queueListeners = new ArrayList();
siteInviteListeners = new ArrayList();
// Register as a queue listener for internal usage by this instance.
addQueueListener(new QueueListener() {
public void joinedQueue() {
inQueue = true;
}
public void departedQueue() {
inQueue = false;
queuePosition = -1;
queueRemainingTime = -1;
}
public void queuePositionUpdated(int currentPosition) {
queuePosition = currentPosition;
}
public void queueWaitTimeUpdated(int secondsRemaining) {
queueRemainingTime = secondsRemaining;
}
});
/**
* Internal handling of an invitation.Recieving an invitation removes the user from the queue.
*/
MultiUserChat.addInvitationListener(connection,
new org.jivesoftware.smackx.muc.InvitationListener() {
public void invitationReceived(XMPPConnection conn, String room, String inviter,
String reason, String password, Message message) {
inQueue = false;
queuePosition = -1;
queueRemainingTime = -1;
}
});
// Register a packet listener for all the messages sent to this client.
PacketFilter typeFilter = new PacketTypeFilter(Message.class);
connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
handlePacket(packet);
}
}, typeFilter);
}
/**
* Returns the name of this workgroup (eg support@example.com).
*
* @return the name of the workgroup.
*/
public String getWorkgroupJID() {
return workgroupJID;
}
/**
* Returns true if the user is currently waiting in the workgroup queue.
*
* @return true if currently waiting in the queue.
*/
public boolean isInQueue() {
return inQueue;
}
/**
* Returns true if the workgroup is available for receiving new requests. The workgroup will be
* available only when agents are available for this workgroup.
*
* @return true if the workgroup is available for receiving new requests.
*/
public boolean isAvailable() {
Presence directedPresence = new Presence(Presence.Type.available);
directedPresence.setTo(workgroupJID);
PacketFilter typeFilter = new PacketTypeFilter(Presence.class);
PacketFilter fromFilter = new FromContainsFilter(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new AndFilter(fromFilter,
typeFilter));
connection.sendPacket(directedPresence);
Presence response = (Presence)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
return false;
}
else if (response.getError() != null) {
return false;
}
else {
return Presence.Type.available == response.getType();
}
}
/**
* Returns the users current position in the workgroup queue. A value of 0 means
* the user is next in line to be routed; therefore, if the queue position
* is being displayed to the end user it is usually a good idea to add 1 to
* the value this method returns before display. If the user is not currently
* waiting in the workgroup, or no queue position information is available, -1
* will be returned.
*
* @return the user's current position in the workgroup queue, or -1 if the
* position isn't available or if the user isn't in the queue.
*/
public int getQueuePosition() {
return queuePosition;
}
/**
* Returns the estimated time (in seconds) that the user has to left wait in
* the workgroup queue before being routed. If the user is not currently waiting
* int he workgroup, or no queue time information is available, -1 will be
* returned.
*
* @return the estimated time remaining (in seconds) that the user has to
* wait inthe workgroupu queue, or -1 if time information isn't available
* or if the user isn't int the queue.
*/
public int getQueueRemainingTime() {
return queueRemainingTime;
}
/**
* Joins the workgroup queue to wait to be routed to an agent. After joining
* the queue, queue status events will be sent to indicate the user's position and
* estimated time left in the queue. Once joining the queue, there are three ways
* the user can leave the queue: <ul>
* <p/>
* <li>The user is routed to an agent, which triggers a GroupChat invitation.
* <li>The user asks to leave the queue by calling the {@link #departQueue} method.
* <li>A server error occurs, or an administrator explicitly removes the user
* from the queue.
* </ul>
* <p/>
* A user cannot request to join the queue again if already in the queue. Therefore,
* this method will throw an IllegalStateException if the user is already in the queue.<p>
* <p/>
* Some servers may be configured to require certain meta-data in order to
* join the queue. In that case, the {@link #joinQueue(Form)} method should be
* used instead of this method so that meta-data may be passed in.<p>
* <p/>
* The server tracks the conversations that a user has with agents over time. By
* default, that tracking is done using the user's JID. However, this is not always
* possible. For example, when the user is logged in anonymously using a web client.
* In that case the user ID might be a randomly generated value put into a persistent
* cookie or a username obtained via the session. A userID can be explicitly
* passed in by using the {@link #joinQueue(Form, String)} method. When specified,
* that userID will be used instead of the user's JID to track conversations. The
* server will ignore a manually specified userID if the user's connection to the server
* is not anonymous.
*
* @throws XMPPException if an error occured joining the queue. An error may indicate
* that a connection failure occured or that the server explicitly rejected the
* request to join the queue.
*/
public void joinQueue() throws XMPPException {
joinQueue(null);
}
/**
* Joins the workgroup queue to wait to be routed to an agent. After joining
* the queue, queue status events will be sent to indicate the user's position and
* estimated time left in the queue. Once joining the queue, there are three ways
* the user can leave the queue: <ul>
* <p/>
* <li>The user is routed to an agent, which triggers a GroupChat invitation.
* <li>The user asks to leave the queue by calling the {@link #departQueue} method.
* <li>A server error occurs, or an administrator explicitly removes the user
* from the queue.
* </ul>
* <p/>
* A user cannot request to join the queue again if already in the queue. Therefore,
* this method will throw an IllegalStateException if the user is already in the queue.<p>
* <p/>
* Some servers may be configured to require certain meta-data in order to
* join the queue.<p>
* <p/>
* The server tracks the conversations that a user has with agents over time. By
* default, that tracking is done using the user's JID. However, this is not always
* possible. For example, when the user is logged in anonymously using a web client.
* In that case the user ID might be a randomly generated value put into a persistent
* cookie or a username obtained via the session. A userID can be explicitly
* passed in by using the {@link #joinQueue(Form, String)} method. When specified,
* that userID will be used instead of the user's JID to track conversations. The
* server will ignore a manually specified userID if the user's connection to the server
* is not anonymous.
*
* @param answerForm the completed form the send for the join request.
* @throws XMPPException if an error occured joining the queue. An error may indicate
* that a connection failure occured or that the server explicitly rejected the
* request to join the queue.
*/
public void joinQueue(Form answerForm) throws XMPPException {
joinQueue(answerForm, null);
}
/**
* <p>Joins the workgroup queue to wait to be routed to an agent. After joining
* the queue, queue status events will be sent to indicate the user's position and
* estimated time left in the queue. Once joining the queue, there are three ways
* the user can leave the queue: <ul>
* <p/>
* <li>The user is routed to an agent, which triggers a GroupChat invitation.
* <li>The user asks to leave the queue by calling the {@link #departQueue} method.
* <li>A server error occurs, or an administrator explicitly removes the user
* from the queue.
* </ul>
* <p/>
* A user cannot request to join the queue again if already in the queue. Therefore,
* this method will throw an IllegalStateException if the user is already in the queue.<p>
* <p/>
* Some servers may be configured to require certain meta-data in order to
* join the queue.<p>
* <p/>
* The server tracks the conversations that a user has with agents over time. By
* default, that tracking is done using the user's JID. However, this is not always
* possible. For example, when the user is logged in anonymously using a web client.
* In that case the user ID might be a randomly generated value put into a persistent
* cookie or a username obtained via the session. When specified, that userID will
* be used instead of the user's JID to track conversations. The server will ignore a
* manually specified userID if the user's connection to the server is not anonymous.
*
* @param answerForm the completed form associated with the join reqest.
* @param userID String that represents the ID of the user when using anonymous sessions
* or <tt>null</tt> if a userID should not be used.
* @throws XMPPException if an error occured joining the queue. An error may indicate
* that a connection failure occured or that the server explicitly rejected the
* request to join the queue.
*/
public void joinQueue(Form answerForm, String userID) throws XMPPException {
// If already in the queue ignore the join request.
if (inQueue) {
throw new IllegalStateException("Already in queue " + workgroupJID);
}
JoinQueuePacket joinPacket = new JoinQueuePacket(workgroupJID, answerForm, userID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(joinPacket.getPacketID()));
this.connection.sendPacket(joinPacket);
IQ response = (IQ)collector.nextResult(10000);
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from the server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
// Notify listeners that we've joined the queue.
fireQueueJoinedEvent();
}
/**
* <p>Joins the workgroup queue to wait to be routed to an agent. After joining
* the queue, queue status events will be sent to indicate the user's position and
* estimated time left in the queue. Once joining the queue, there are three ways
* the user can leave the queue: <ul>
* <p/>
* <li>The user is routed to an agent, which triggers a GroupChat invitation.
* <li>The user asks to leave the queue by calling the {@link #departQueue} method.
* <li>A server error occurs, or an administrator explicitly removes the user
* from the queue.
* </ul>
* <p/>
* A user cannot request to join the queue again if already in the queue. Therefore,
* this method will throw an IllegalStateException if the user is already in the queue.<p>
* <p/>
* Some servers may be configured to require certain meta-data in order to
* join the queue.<p>
* <p/>
* The server tracks the conversations that a user has with agents over time. By
* default, that tracking is done using the user's JID. However, this is not always
* possible. For example, when the user is logged in anonymously using a web client.
* In that case the user ID might be a randomly generated value put into a persistent
* cookie or a username obtained via the session. When specified, that userID will
* be used instead of the user's JID to track conversations. The server will ignore a
* manually specified userID if the user's connection to the server is not anonymous.
*
* @param metadata metadata to create a dataform from.
* @param userID String that represents the ID of the user when using anonymous sessions
* or <tt>null</tt> if a userID should not be used.
* @throws XMPPException if an error occured joining the queue. An error may indicate
* that a connection failure occured or that the server explicitly rejected the
* request to join the queue.
*/
public void joinQueue(Map metadata, String userID) throws XMPPException {
// If already in the queue ignore the join request.
if (inQueue) {
throw new IllegalStateException("Already in queue " + workgroupJID);
}
// Build dataform from metadata
Form form = new Form(Form.TYPE_SUBMIT);
Iterator iter = metadata.keySet().iterator();
while (iter.hasNext()) {
String name = (String)iter.next();
String value = (String)metadata.get(name).toString();
String escapedName = StringUtils.escapeForXML(name);
String escapedValue = StringUtils.escapeForXML(value);
FormField field = new FormField(escapedName);
field.setType(FormField.TYPE_TEXT_SINGLE);
form.addField(field);
form.setAnswer(escapedName, escapedValue);
}
joinQueue(form, userID);
}
/**
* Departs the workgroup queue. If the user is not currently in the queue, this
* method will do nothing.<p>
* <p/>
* Normally, the user would not manually leave the queue. However, they may wish to
* under certain circumstances -- for example, if they no longer wish to be routed
* to an agent because they've been waiting too long.
*
* @throws XMPPException if an error occured trying to send the depart queue
* request to the server.
*/
public void departQueue() throws XMPPException {
// If not in the queue ignore the depart request.
if (!inQueue) {
return;
}
DepartQueuePacket departPacket = new DepartQueuePacket(this.workgroupJID);
PacketCollector collector = this.connection.createPacketCollector(new PacketIDFilter(departPacket.getPacketID()));
connection.sendPacket(departPacket);
IQ response = (IQ)collector.nextResult(5000);
collector.cancel();
if (response == null) {
throw new XMPPException("No response from the server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
// Notify listeners that we're no longer in the queue.
fireQueueDepartedEvent();
}
/**
* Adds a queue listener that will be notified of queue events for the user
* that created this Workgroup instance.
*
* @param queueListener the queue listener.
*/
public void addQueueListener(QueueListener queueListener) {
synchronized (queueListeners) {
if (!queueListeners.contains(queueListener)) {
queueListeners.add(queueListener);
}
}
}
/**
* Removes a queue listener.
*
* @param queueListener the queue listener.
*/
public void removeQueueListener(QueueListener queueListener) {
synchronized (queueListeners) {
queueListeners.remove(queueListener);
}
}
/**
* Adds an invitation listener that will be notified of groupchat invitations
* from the workgroup for the the user that created this Workgroup instance.
*
* @param invitationListener the invitation listener.
*/
public void addInvitationListener(WorkgroupInvitationListener invitationListener) {
synchronized (invitationListeners) {
if (!invitationListeners.contains(invitationListener)) {
invitationListeners.add(invitationListener);
}
}
}
/**
* Removes an invitation listener.
*
* @param invitationListener the invitation listener.
*/
public void removeQueueListener(WorkgroupInvitationListener invitationListener) {
synchronized (invitationListeners) {
invitationListeners.remove(invitationListener);
}
}
private void fireInvitationEvent(WorkgroupInvitation invitation) {
synchronized (invitationListeners) {
for (Iterator i = invitationListeners.iterator(); i.hasNext();) {
WorkgroupInvitationListener listener = (WorkgroupInvitationListener)i.next();
listener.invitationReceived(invitation);
}
}
}
private void fireQueueJoinedEvent() {
synchronized (queueListeners) {
for (Iterator i = queueListeners.iterator(); i.hasNext();) {
QueueListener listener = (QueueListener)i.next();
listener.joinedQueue();
}
}
}
private void fireQueueDepartedEvent() {
synchronized (queueListeners) {
for (Iterator i = queueListeners.iterator(); i.hasNext();) {
QueueListener listener = (QueueListener)i.next();
listener.departedQueue();
}
}
}
private void fireQueuePositionEvent(int currentPosition) {
synchronized (queueListeners) {
for (Iterator i = queueListeners.iterator(); i.hasNext();) {
QueueListener listener = (QueueListener)i.next();
listener.queuePositionUpdated(currentPosition);
}
}
}
private void fireQueueTimeEvent(int secondsRemaining) {
synchronized (queueListeners) {
for (Iterator i = queueListeners.iterator(); i.hasNext();) {
QueueListener listener = (QueueListener)i.next();
listener.queueWaitTimeUpdated(secondsRemaining);
}
}
}
// PacketListener Implementation.
private void handlePacket(Packet packet) {
if (packet instanceof Message) {
Message msg = (Message)packet;
// Check to see if the user left the queue.
PacketExtension pe = msg.getExtension("depart-queue", "http://jabber.org/protocol/workgroup");
PacketExtension queueStatus = msg.getExtension("queue-status", "http://jabber.org/protocol/workgroup");
if (pe != null) {
fireQueueDepartedEvent();
}
else if (queueStatus != null) {
QueueUpdate queueUpdate = (QueueUpdate)queueStatus;
if (queueUpdate.getPosition() != -1) {
fireQueuePositionEvent(queueUpdate.getPosition());
}
if (queueUpdate.getRemaingTime() != -1) {
fireQueueTimeEvent(queueUpdate.getRemaingTime());
}
}
else {
// Check if a room invitation was sent and if the sender is the workgroup
MUCUser mucUser = (MUCUser)msg.getExtension("x", "http://jabber.org/protocol/muc#user");
MUCUser.Invite invite = mucUser != null ? mucUser.getInvite() : null;
if (invite != null && workgroupJID.equals(invite.getFrom())) {
String sessionID = null;
Map metaData = null;
pe = msg.getExtension(SessionID.ELEMENT_NAME,
SessionID.NAMESPACE);
if (pe != null) {
sessionID = ((SessionID)pe).getSessionID();
}
pe = msg.getExtension(MetaData.ELEMENT_NAME,
MetaData.NAMESPACE);
if (pe != null) {
metaData = ((MetaData)pe).getMetaData();
}
WorkgroupInvitation inv = new WorkgroupInvitation(connection.getUser(), msg.getFrom(),
workgroupJID, sessionID, msg.getBody(),
msg.getFrom(), metaData);
fireInvitationEvent(inv);
}
}
}
}
/**
* IQ packet to request joining the workgroup queue.
*/
private class JoinQueuePacket extends IQ {
private String userID = null;
private DataForm form;
public JoinQueuePacket(String workgroup, Form answerForm, String userID) {
this.userID = userID;
setTo(workgroup);
setType(IQ.Type.SET);
form = answerForm.getDataFormToSend();
addExtension(form);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<join-queue xmlns=\"http://jabber.org/protocol/workgroup\">");
buf.append("<queue-notifications/>");
// Add the user unique identification if the session is anonymous
if (connection.isAnonymous()) {
buf.append(new UserID(userID).toXML());
}
// Append data form text
buf.append(form.toXML());
buf.append("</join-queue>");
return buf.toString();
}
}
/**
* Returns a single chat setting based on it's identified key.
*
* @param key the key to find.
* @return the ChatSetting if found, otherwise false.
* @throws XMPPException if an error occurs while getting information from the server.
*/
public ChatSetting getChatSetting(String key) throws XMPPException {
ChatSettings chatSettings = getChatSettings(key, -1);
return chatSettings.getFirstEntry();
}
/**
* Returns ChatSettings based on type.
*
* @param type the type of ChatSettings to return.
* @return the ChatSettings of given type, otherwise null.
* @throws XMPPException if an error occurs while getting information from the server.
*/
public ChatSettings getChatSettings(int type) throws XMPPException {
return getChatSettings(null, type);
}
/**
* Returns all ChatSettings.
*
* @return all ChatSettings of a given workgroup.
* @throws XMPPException if an error occurs while getting information from the server.
*/
public ChatSettings getChatSettings() throws XMPPException {
return getChatSettings(null, -1);
}
/**
* Asks the workgroup for it's Chat Settings.
*
* @return key specify a key to retrieve only that settings. Otherwise for all settings, key should be null.
* @throws XMPPException if an error occurs while getting information from the server.
*/
private ChatSettings getChatSettings(String key, int type) throws XMPPException {
ChatSettings request = new ChatSettings();
if (key != null) {
request.setKey(key);
}
if (type != -1) {
request.setType(type);
}
request.setType(IQ.Type.GET);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
connection.sendPacket(request);
ChatSettings response = (ChatSettings)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response;
}
/**
* The workgroup service may be configured to send email. This queries the Workgroup Service
* to see if the email service has been configured and is available.
*
* @return true if the email service is available, otherwise return false.
*/
public boolean isEmailAvailable() {
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
try {
String workgroupService = StringUtils.parseServer(workgroupJID);
DiscoverInfo infoResult = discoManager.discoverInfo(workgroupService);
return infoResult.containsFeature("jive:email:provider");
}
catch (XMPPException e) {
return false;
}
}
/**
* Send an email from the workgroup.
*
* @param to the to address of the the user to send to.
* @param from who the email is from.
* @param subject the subject of the email.
* @param message the body of the email.
* @param sendAsHTML true if the message should be sent as html, otherwise specify false for plain text.
* @return true if the email was sent successfully, otherwise false.
* @throws XMPPException if an error occurs while sending the email.
*/
public boolean sendMail(String to, String from, String subject, String message, boolean sendAsHTML) throws XMPPException {
EmailIQ request = new EmailIQ();
request.setToAddress(to);
request.setFromAddress(from);
request.setSubject(subject);
request.setMessage(message);
request.setHtml(sendAsHTML);
request.setType(IQ.Type.SET);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
connection.sendPacket(request);
Packet response = collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return true;
}
/**
* Send an email from the workgroup.
*
* @param to the to address of the the user to send to.
* @param sessionID the sessionID of the chat.
* @return true if the email was sent successfully, otherwise false.
* @throws XMPPException if an error occurs while sending the email.
*/
public boolean sendTranscript(String to, String sessionID) throws XMPPException {
EmailIQ request = new EmailIQ();
request.setToAddress(to);
request.setSessionID(sessionID);
request.setType(IQ.Type.SET);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
connection.sendPacket(request);
Packet response = collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return true;
}
/**
* Asks the workgroup for it's Offline Settings.
*
* @return offlineSettings the offline settings for this workgroup.
* @throws XMPPException if an error occurs while getting information from the server.
*/
public OfflineSettings getOfflineSettings() throws XMPPException {
OfflineSettings request = new OfflineSettings();
request.setType(IQ.Type.GET);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
connection.sendPacket(request);
OfflineSettings response = (OfflineSettings)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response;
}
/**
* Asks the workgroup for it's Sound Settings.
*
* @return soundSettings the sound settings for the specified workgroup.
* @throws XMPPException if an error occurs while getting information from the server.
*/
public SoundSettings getSoundSettings() throws XMPPException {
SoundSettings request = new SoundSettings();
request.setType(IQ.Type.GET);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
connection.sendPacket(request);
SoundSettings response = (SoundSettings)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response;
}
/**
* Asks the workgroup for it's Properties
*
* @return the WorkgroupProperties for the specified workgroup.
* @throws XMPPException if an error occurs while getting information from the server.
*/
public WorkgroupProperties getWorkgroupProperties() throws XMPPException {
WorkgroupProperties request = new WorkgroupProperties();
request.setType(IQ.Type.GET);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
connection.sendPacket(request);
WorkgroupProperties response = (WorkgroupProperties)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response;
}
/**
* Asks the workgroup for it's Properties
*
* @param jid the jid of the user who's information you would like the workgroup to retreive.
* @return the WorkgroupProperties for the specified workgroup.
* @throws XMPPException if an error occurs while getting information from the server.
*/
public WorkgroupProperties getWorkgroupProperties(String jid) throws XMPPException {
WorkgroupProperties request = new WorkgroupProperties();
request.setJid(jid);
request.setType(IQ.Type.GET);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
connection.sendPacket(request);
WorkgroupProperties response = (WorkgroupProperties)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response;
}
/**
* Returns the Form to use for all clients of a workgroup. 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.
*
* @return the Form to use for searching transcripts.
* @throws XMPPException if an error occurs while sending the request to the server.
*/
public Form getWorkgroupForm() throws XMPPException {
WorkgroupForm workgroupForm = new WorkgroupForm();
workgroupForm.setType(IQ.Type.GET);
workgroupForm.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(workgroupForm.getPacketID()));
connection.sendPacket(workgroupForm);
WorkgroupForm response = (WorkgroupForm)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);
}
/*
public static void main(String args[]) throws Exception {
XMPPConnection con = new XMPPConnection("anteros");
con.connect();
con.loginAnonymously();
Workgroup workgroup = new Workgroup("demo@workgroup.anteros", con);
WorkgroupProperties props = workgroup.getWorkgroupProperties("derek@anteros.com");
System.out.print(props);
con.disconnect();
}
*/
}

View File

@ -0,0 +1,126 @@
/**
* $RCSfile$
* $Revision: 19406 $
* $Date: 2005-07-28 18:12:09 -0700 (Thu, 28 Jul 2005) $
*
* Copyright (C) 2003-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.util;
import java.lang.reflect.Method;
import java.util.*;
/**
* This class is a very flexible event dispatcher which implements Runnable so that it can
* dispatch easily from a newly created thread. The usage of this in code is more or less:
* create a new instance of this class, use addListenerTriplet to add as many listeners
* as desired to be messaged, create a new Thread using the instance of this class created
* as the argument to the constructor, start the new Thread instance.<p>
*
* Also, this is intended to be used to message methods that either return void, or have
* a return which the developer using this class is uninterested in receiving.
*
* @author loki der quaeler
*/
public class ListenerEventDispatcher
implements Runnable {
protected transient ArrayList triplets;
protected transient boolean hasFinishedDispatching;
protected transient boolean isRunning;
public ListenerEventDispatcher () {
super();
this.triplets = new ArrayList();
this.hasFinishedDispatching = false;
this.isRunning = false;
}
/**
* Add a listener triplet - the instance of the listener to be messaged, the Method on which
* the listener should be messaged, and the Object array of arguments to be supplied to the
* Method. No attempts are made to determine whether this triplet was already added.<br>
*
* Messages are dispatched in the order in which they're added via this method; so if triplet
* X is added after triplet Z, then triplet Z will undergo messaging prior to triplet X.<br>
*
* This method should not be called once the owning Thread instance has been started; if it
* is called, the triplet will not be added to the messaging queue.<br>
*
* @param listenerInstance the instance of the listener to receive the associated notification
* @param listenerMethod the Method instance representing the method through which notification
* will occur
* @param methodArguments the arguments supplied to the notification method
*/
public void addListenerTriplet(Object listenerInstance, Method listenerMethod,
Object[] methodArguments)
{
if (!this.isRunning) {
this.triplets.add(new TripletContainer(listenerInstance, listenerMethod,
methodArguments));
}
}
/**
* @return whether this instance has finished dispatching its messages
*/
public boolean hasFinished() {
return this.hasFinishedDispatching;
}
public void run() {
ListIterator li = null;
this.isRunning = true;
li = this.triplets.listIterator();
while (li.hasNext()) {
TripletContainer tc = (TripletContainer)li.next();
try {
tc.getListenerMethod().invoke(tc.getListenerInstance(), tc.getMethodArguments());
} catch (Exception e) {
System.err.println("Exception dispatching an event: " + e);
e.printStackTrace();
}
}
this.hasFinishedDispatching = true;
}
protected class TripletContainer {
protected Object listenerInstance;
protected Method listenerMethod;
protected Object[] methodArguments;
protected TripletContainer (Object inst, Method meth, Object[] args) {
super();
this.listenerInstance = inst;
this.listenerMethod = meth;
this.methodArguments = args;
}
protected Object getListenerInstance() {
return this.listenerInstance;
}
protected Method getListenerMethod() {
return this.listenerMethod;
}
protected Object[] getMethodArguments() {
return this.methodArguments;
}
}
}

View File

@ -0,0 +1,106 @@
/**
* $RCSfile$
* $Revision: 38648 $
* $Date: 2006-12-27 01:46:18 -0800 (Wed, 27 Dec 2006) $
*
* Copyright (C) 2003-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.util;
import org.jivesoftware.smackx.workgroup.MetaData;
import org.jivesoftware.smack.util.StringUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.*;
/**
* Utility class for meta-data parsing and writing.
*
* @author Matt Tucker
*/
public class MetaDataUtils {
/**
* Parses any available meta-data and returns it as a Map of String name/value pairs. The
* parser must be positioned at an opening meta-data tag, or the an empty map will be returned.
*
* @param parser the XML parser positioned at an opening meta-data tag.
* @return the meta-data.
* @throws XmlPullParserException if an error occurs while parsing the XML.
* @throws IOException if an error occurs while parsing the XML.
*/
public static Map parseMetaData(XmlPullParser parser) throws XmlPullParserException, IOException {
int eventType = parser.getEventType();
// If correctly positioned on an opening meta-data tag, parse meta-data.
if ((eventType == XmlPullParser.START_TAG)
&& parser.getName().equals(MetaData.ELEMENT_NAME)
&& parser.getNamespace().equals(MetaData.NAMESPACE)) {
Map metaData = new Hashtable();
eventType = parser.nextTag();
// Keep parsing until we've gotten to end of meta-data.
while ((eventType != XmlPullParser.END_TAG)
|| (!parser.getName().equals(MetaData.ELEMENT_NAME))) {
String name = parser.getAttributeValue(0);
String value = parser.nextText();
if (metaData.containsKey(name)) {
List values = (List)metaData.get(name);
values.add(value);
}
else {
List values = new ArrayList();
values.add(value);
metaData.put(name, values);
}
eventType = parser.nextTag();
}
return metaData;
}
return Collections.EMPTY_MAP;
}
/**
* Serializes a Map of String name/value pairs into the meta-data XML format.
*
* @param metaData the Map of meta-data.
* @return the meta-data values in XML form.
*/
public static String serializeMetaData(Map metaData) {
StringBuilder buf = new StringBuilder();
if (metaData != null && metaData.size() > 0) {
buf.append("<metadata xmlns=\"http://jivesoftware.com/protocol/workgroup\">");
for (Iterator i = metaData.keySet().iterator(); i.hasNext();) {
Object key = i.next();
Object value = metaData.get(key);
if (value instanceof List) {
List values = (List)metaData.get(key);
for (Iterator it = values.iterator(); it.hasNext();) {
String v = (String)it.next();
buf.append("<value name=\"").append(key).append("\">");
buf.append(StringUtils.escapeForXML(v));
buf.append("</value>");
}
}
else if (value instanceof String) {
buf.append("<value name=\"").append(key).append("\">");
buf.append(StringUtils.escapeForXML((String)value));
buf.append("</value>");
}
}
buf.append("</metadata>");
}
return buf.toString();
}
}

View File

@ -0,0 +1,318 @@
/**
* $RCSfile$
* $Revision: 38648 $
* $Date: 2006-12-27 01:46:18 -0800 (Wed, 27 Dec 2006) $
*
* Copyright (C) 2004-2005 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.smackx.workgroup.util;
import java.util.*;
/**
* Utility methods frequently used by data classes and design-time
* classes.
*/
public final class ModelUtil {
private ModelUtil() {
// Prevents instantiation.
}
/**
* This is a utility method that compares two objects when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
* according to the <CODE>==</CODE> operator, return
* <CODE>true</CODE>.
* <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
* <CODE>null</CODE>, return <CODE>false</CODE>.
* <LI>Otherwise, return <CODE>o1.equals(o2)</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areDifferent(Object, Object)} method.<P>
* <p/>
* For array types, one of the <CODE>equals</CODE> methods in
* {@link java.util.Arrays} should be used instead of this method.
* Note that arrays with more than one dimension will require some
* custom code in order to implement <CODE>equals</CODE> properly.
*/
public static final boolean areEqual(Object o1, Object o2) {
if (o1 == o2) {
return true;
}
else if (o1 == null || o2 == null) {
return false;
}
else {
return o1.equals(o2);
}
}
/**
* This is a utility method that compares two Booleans when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
* neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
* return <CODE>true</CODE>.
* <LI>Otherwise, return <CODE>false</CODE>.
* </OL>
* <p/>
*/
public static final boolean areBooleansEqual(Boolean b1, Boolean b2) {
// !jwetherb treat NULL the same as Boolean.FALSE
return (b1 == Boolean.TRUE && b2 == Boolean.TRUE) ||
(b1 != Boolean.TRUE && b2 != Boolean.TRUE);
}
/**
* This is a utility method that compares two objects when one or
* both of the objects might be <CODE>null</CODE>. The result
* returned by this method is determined as follows:
* <OL>
* <LI>If <CODE>o1</CODE> and <CODE>o2</CODE> are the same object
* according to the <CODE>==</CODE> operator, return
* <CODE>false</CODE>.
* <LI>Otherwise, if either <CODE>o1</CODE> or <CODE>o2</CODE> is
* <CODE>null</CODE>, return <CODE>true</CODE>.
* <LI>Otherwise, return <CODE>!o1.equals(o2)</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areEqual(Object, Object)} method.<P>
* <p/>
* For array types, one of the <CODE>equals</CODE> methods in
* {@link java.util.Arrays} should be used instead of this method.
* Note that arrays with more than one dimension will require some
* custom code in order to implement <CODE>equals</CODE> properly.
*/
public static final boolean areDifferent(Object o1, Object o2) {
return !areEqual(o1, o2);
}
/**
* This is a utility method that compares two Booleans when one or
* both of the objects might be <CODE>null</CODE> The result of
* this method is determined as follows:
* <OL>
* <LI>If <CODE>b1</CODE> and <CODE>b2</CODE> are both TRUE or
* neither <CODE>b1</CODE> nor <CODE>b2</CODE> is TRUE,
* return <CODE>false</CODE>.
* <LI>Otherwise, return <CODE>true</CODE>.
* </OL>
* <p/>
* This method produces the exact logically inverted result as the
* {@link #areBooleansEqual(Boolean, Boolean)} method.<P>
*/
public static final boolean areBooleansDifferent(Boolean b1, Boolean b2) {
return !areBooleansEqual(b1, b2);
}
/**
* Returns <CODE>true</CODE> if the specified array is not null
* and contains a non-null element. Returns <CODE>false</CODE>
* if the array is null or if all the array elements are null.
*/
public static final boolean hasNonNullElement(Object[] array) {
if (array != null) {
final int n = array.length;
for (int i = 0; i < n; i++) {
if (array[i] != null) {
return true;
}
}
}
return false;
}
/**
* Returns a single string that is the concatenation of all the
* strings in the specified string array. A single space is
* put between each string array element. Null array elements
* are skipped. If the array itself is null, the empty string
* is returned. This method is guaranteed to return a non-null
* value, if no expections are thrown.
*/
public static final String concat(String[] strs) {
return concat(strs, " "); //NOTRANS
}
/**
* Returns a single string that is the concatenation of all the
* strings in the specified string array. The strings are separated
* by the specified delimiter. Null array elements are skipped. If
* the array itself is null, the empty string is returned. This
* method is guaranteed to return a non-null value, if no expections
* are thrown.
*/
public static final String concat(String[] strs, String delim) {
if (strs != null) {
final StringBuilder buf = new StringBuilder();
final int n = strs.length;
for (int i = 0; i < n; i++) {
final String str = strs[i];
if (str != null) {
buf.append(str).append(delim);
}
}
final int length = buf.length();
if (length > 0) {
// Trim trailing space.
buf.setLength(length - 1);
}
return buf.toString();
}
else {
return ""; // NOTRANS
}
}
/**
* Returns <CODE>true</CODE> if the specified {@link String} is not
* <CODE>null</CODE> and has a length greater than zero. This is
* a very frequently occurring check.
*/
public static final boolean hasLength(String s) {
return (s != null && s.length() > 0);
}
/**
* Returns <CODE>null</CODE> if the specified string is empty or
* <CODE>null</CODE>. Otherwise the string itself is returned.
*/
public static final String nullifyIfEmpty(String s) {
return ModelUtil.hasLength(s) ? s : null;
}
/**
* Returns <CODE>null</CODE> if the specified object is null
* or if its <CODE>toString()</CODE> representation is empty.
* Otherwise, the <CODE>toString()</CODE> representation of the
* object itself is returned.
*/
public static final String nullifyingToString(Object o) {
return o != null ? nullifyIfEmpty(o.toString()) : null;
}
/**
* Determines if a string has been changed.
*
* @param oldString is the initial value of the String
* @param newString is the new value of the String
* @return true If both oldString and newString are null or if they are
* both not null and equal to each other. Otherwise returns false.
*/
public static boolean hasStringChanged(String oldString, String newString) {
if (oldString == null && newString == null) {
return false;
}
else if ((oldString == null && newString != null)
|| (oldString != null && newString == null)) {
return true;
}
else {
return !oldString.equals(newString);
}
}
public static String getTimeFromLong(long diff) {
final String HOURS = "h";
final String MINUTES = "min";
final String SECONDS = "sec";
final long MS_IN_A_DAY = 1000 * 60 * 60 * 24;
final long MS_IN_AN_HOUR = 1000 * 60 * 60;
final long MS_IN_A_MINUTE = 1000 * 60;
final long MS_IN_A_SECOND = 1000;
Date currentTime = new Date();
long numDays = diff / MS_IN_A_DAY;
diff = diff % MS_IN_A_DAY;
long numHours = diff / MS_IN_AN_HOUR;
diff = diff % MS_IN_AN_HOUR;
long numMinutes = diff / MS_IN_A_MINUTE;
diff = diff % MS_IN_A_MINUTE;
long numSeconds = diff / MS_IN_A_SECOND;
diff = diff % MS_IN_A_SECOND;
long numMilliseconds = diff;
StringBuilder buf = new StringBuilder();
if (numHours > 0) {
buf.append(numHours + " " + HOURS + ", ");
}
if (numMinutes > 0) {
buf.append(numMinutes + " " + MINUTES + ", ");
}
buf.append(numSeconds + " " + SECONDS);
String result = buf.toString();
return result;
}
/**
* Build a List of all elements in an Iterator.
*/
public static List iteratorAsList(Iterator i) {
ArrayList list = new ArrayList(10);
while (i.hasNext()) {
list.add(i.next());
}
return list;
}
/**
* Creates an Iterator that is the reverse of a ListIterator.
*/
public static Iterator reverseListIterator(ListIterator i) {
return new ReverseListIterator(i);
}
}
/**
* An Iterator that is the reverse of a ListIterator.
*/
class ReverseListIterator implements Iterator {
private ListIterator _i;
ReverseListIterator(ListIterator i) {
_i = i;
while (_i.hasNext())
_i.next();
}
public boolean hasNext() {
return _i.hasPrevious();
}
public Object next() {
return _i.previous();
}
public void remove() {
_i.remove();
}
}