001/*
002 *
003 * Copyright 2003-2007 Jive Software.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.workgroup.packet;
018
019import java.io.IOException;
020import java.text.ParseException;
021import java.text.SimpleDateFormat;
022import java.util.ArrayList;
023import java.util.Collections;
024import java.util.Date;
025import java.util.Iterator;
026import java.util.List;
027import java.util.TimeZone;
028
029import javax.xml.namespace.QName;
030
031import org.jivesoftware.smack.packet.ExtensionElement;
032import org.jivesoftware.smack.packet.XmlEnvironment;
033import org.jivesoftware.smack.provider.ExtensionElementProvider;
034import org.jivesoftware.smack.util.ParserUtils;
035import org.jivesoftware.smack.xml.XmlPullParser;
036import org.jivesoftware.smack.xml.XmlPullParserException;
037
038import org.jxmpp.JxmppContext;
039import org.jxmpp.jid.EntityBareJid;
040
041/**
042 * Agent status packet.
043 *
044 * @author Matt Tucker
045 */
046public class AgentStatus implements ExtensionElement {
047
048    @SuppressWarnings("DateFormatConstant")
049    private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
050
051    static {
052        UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
053    }
054
055    /**
056     * Element name of the stanza extension.
057     */
058    public static final String ELEMENT_NAME = "agent-status";
059
060    /**
061     * Namespace of the stanza extension.
062     */
063    public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
064
065    public static final QName QNAME = new QName(NAMESPACE, ELEMENT_NAME);
066
067    private EntityBareJid workgroupJID;
068    private final List<ChatInfo> currentChats = new ArrayList<>();
069    private int maxChats = -1;
070
071    AgentStatus() {
072    }
073
074    public EntityBareJid getWorkgroupJID() {
075        return workgroupJID;
076    }
077
078    /**
079     * Returns a collection of ChatInfo where each ChatInfo represents a Chat where this agent
080     * is participating.
081     *
082     * @return a collection of ChatInfo where each ChatInfo represents a Chat where this agent
083     *         is participating.
084     */
085    public List<ChatInfo> getCurrentChats() {
086        return Collections.unmodifiableList(currentChats);
087    }
088
089    public int getMaxChats() {
090        return maxChats;
091    }
092
093    @Override
094    public String getElementName() {
095        return ELEMENT_NAME;
096    }
097
098    @Override
099    public String getNamespace() {
100        return NAMESPACE;
101    }
102
103    @Override
104    public String toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
105        StringBuilder buf = new StringBuilder();
106
107        buf.append('<').append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append('"');
108        if (workgroupJID != null) {
109            buf.append(" jid=\"").append(workgroupJID).append('"');
110        }
111        buf.append('>');
112        if (maxChats != -1) {
113            buf.append("<max-chats>").append(maxChats).append("</max-chats>");
114        }
115        if (!currentChats.isEmpty()) {
116            buf.append("<current-chats xmlns= \"http://jivesoftware.com/protocol/workgroup\">");
117            for (Iterator<ChatInfo> it = currentChats.iterator(); it.hasNext();) {
118                buf.append(it.next().toXML());
119            }
120            buf.append("</current-chats>");
121        }
122        buf.append("</").append(this.getElementName()).append("> ");
123
124        return buf.toString();
125    }
126
127    /**
128     * Represents information about a Chat where this Agent is participating.
129     *
130     * @author Gaston Dombiak
131     */
132    public static class ChatInfo {
133
134        private final String sessionID;
135        private final String userID;
136        private final Date date;
137        private final String email;
138        private final String username;
139        private final String question;
140
141        public ChatInfo(String sessionID, String userID, Date date, String email, String username, String question) {
142            this.sessionID = sessionID;
143            this.userID = userID;
144            this.date = date;
145            this.email = email;
146            this.username = username;
147            this.question = question;
148        }
149
150        /**
151         * Returns the sessionID associated to this chat. Each chat will have a unique sessionID
152         * that could be used for retrieving the whole transcript of the conversation.
153         *
154         * @return the sessionID associated to this chat.
155         */
156        public String getSessionID() {
157            return sessionID;
158        }
159
160        /**
161         * Returns the user unique identification of the user that made the initial request and
162         * for which this chat was generated. If the user joined using an anonymous connection
163         * then the userID will be the value of the ID attribute of the USER element. Otherwise,
164         * the userID will be the bare JID of the user that made the request.
165         *
166         * @return the user unique identification of the user that made the initial request.
167         */
168        public String getUserID() {
169            return userID;
170        }
171
172        /**
173         * Returns the date when this agent joined the chat.
174         *
175         * @return the date when this agent joined the chat.
176         */
177        public Date getDate() {
178            return date;
179        }
180
181        /**
182         * Returns the email address associated with the user.
183         *
184         * @return the email address associated with the user.
185         */
186        public String getEmail() {
187            return email;
188        }
189
190        /**
191         * Returns the username(nickname) associated with the user.
192         *
193         * @return the username associated with the user.
194         */
195        public String getUsername() {
196            return username;
197        }
198
199        /**
200         * Returns the question the user asked.
201         *
202         * @return the question the user asked, if any.
203         */
204        public String getQuestion() {
205            return question;
206        }
207
208        public String toXML() {
209            StringBuilder buf = new StringBuilder();
210
211            buf.append("<chat ");
212            if (sessionID != null) {
213                buf.append(" sessionID=\"").append(sessionID).append('"');
214            }
215            if (userID != null) {
216                buf.append(" userID=\"").append(userID).append('"');
217            }
218            if (date != null) {
219                buf.append(" startTime=\"");
220                synchronized (UTC_FORMAT) {
221                    buf.append(UTC_FORMAT.format(date));
222                }
223                buf.append('"');
224            }
225            if (email != null) {
226                buf.append(" email=\"").append(email).append('"');
227            }
228            if (username != null) {
229                buf.append(" username=\"").append(username).append('"');
230            }
231            if (question != null) {
232                buf.append(" question=\"").append(question).append('"');
233            }
234            buf.append("/>");
235
236            return buf.toString();
237        }
238    }
239
240    /**
241     * Stanza extension provider for AgentStatus packets.
242     */
243    public static class Provider extends ExtensionElementProvider<AgentStatus> {
244
245        @Override
246        public AgentStatus parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext)
247                        throws XmlPullParserException, IOException, ParseException {
248            AgentStatus agentStatus = new AgentStatus();
249
250            agentStatus.workgroupJID = ParserUtils.getBareJidAttribute(parser, jxmppContext);
251
252            boolean done = false;
253            while (!done) {
254                XmlPullParser.Event eventType = parser.next();
255
256                if (eventType == XmlPullParser.Event.START_ELEMENT) {
257                    if ("chat".equals(parser.getName())) {
258                        ChatInfo chatInfo = parseChatInfo(parser);
259                        agentStatus.currentChats.add(chatInfo);
260                    }
261                    else if ("max-chats".equals(parser.getName())) {
262                        agentStatus.maxChats = Integer.parseInt(parser.nextText());
263                    }
264                }
265                else if (eventType == XmlPullParser.Event.END_ELEMENT &&
266                    ELEMENT_NAME.equals(parser.getName())) {
267                    done = true;
268                }
269            }
270            return agentStatus;
271        }
272
273        private static ChatInfo parseChatInfo(XmlPullParser parser) throws ParseException {
274
275            String sessionID = parser.getAttributeValue("", "sessionID");
276            String userID = parser.getAttributeValue("", "userID");
277            Date date = null;
278            synchronized (UTC_FORMAT) {
279                date = UTC_FORMAT.parse(parser.getAttributeValue("", "startTime"));
280            }
281
282            String email = parser.getAttributeValue("", "email");
283            String username = parser.getAttributeValue("", "username");
284            String question = parser.getAttributeValue("", "question");
285
286            return new ChatInfo(sessionID, userID, date, email, username, question);
287        }
288    }
289}