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 */
017
018package org.jivesoftware.smackx.workgroup.packet;
019
020import java.io.IOException;
021import java.text.ParseException;
022import java.text.SimpleDateFormat;
023import java.util.Date;
024import java.util.HashSet;
025import java.util.Iterator;
026import java.util.Set;
027import java.util.logging.Logger;
028
029import org.jivesoftware.smack.SmackException;
030import org.jivesoftware.smack.packet.ExtensionElement;
031import org.jivesoftware.smack.provider.ExtensionElementProvider;
032
033import org.jivesoftware.smackx.workgroup.QueueUser;
034
035import org.xmlpull.v1.XmlPullParser;
036import org.xmlpull.v1.XmlPullParserException;
037
038/**
039 * Queue details stanza(/packet) extension, which contains details about the users
040 * currently in a queue.
041 */
042public final class QueueDetails implements ExtensionElement {
043    private static final Logger LOGGER = Logger.getLogger(QueueDetails.class.getName());
044
045    /**
046     * Element name of the stanza(/packet) extension.
047     */
048    public static final String ELEMENT_NAME = "notify-queue-details";
049
050    /**
051     * Namespace of the stanza(/packet) extension.
052     */
053    public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
054
055    private static final String DATE_FORMAT = "yyyyMMdd'T'HH:mm:ss";
056
057    private final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
058    /**
059     * The list of users in the queue.
060     */
061    private final Set<QueueUser> users = new HashSet<>();
062
063    /**
064     * Returns the number of users currently in the queue that are waiting to
065     * be routed to an agent.
066     *
067     * @return the number of users in the queue.
068     */
069    public int getUserCount() {
070        return users.size();
071    }
072
073    /**
074     * Returns the set of users in the queue that are waiting to
075     * be routed to an agent (as QueueUser objects).
076     *
077     * @return a Set for the users waiting in a queue.
078     */
079    public Set<QueueUser> getUsers() {
080        synchronized (users) {
081            return users;
082        }
083    }
084
085    /**
086     * Adds a user to the packet.
087     *
088     * @param user the user.
089     */
090    private void addUser(QueueUser user) {
091        synchronized (users) {
092            users.add(user);
093        }
094    }
095
096    @Override
097    public String getElementName() {
098        return ELEMENT_NAME;
099    }
100
101    @Override
102    public String getNamespace() {
103        return NAMESPACE;
104    }
105
106    @Override
107    public String toXML() {
108        StringBuilder buf = new StringBuilder();
109        buf.append('<').append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
110
111        synchronized (users) {
112            for (Iterator<QueueUser> i = users.iterator(); i.hasNext(); ) {
113                QueueUser user = i.next();
114                int position = user.getQueuePosition();
115                int timeRemaining = user.getEstimatedRemainingTime();
116                Date timestamp = user.getQueueJoinTimestamp();
117
118                buf.append("<user jid=\"").append(user.getUserID()).append("\">");
119
120                if (position != -1) {
121                    buf.append("<position>").append(position).append("</position>");
122                }
123
124                if (timeRemaining != -1) {
125                    buf.append("<time>").append(timeRemaining).append("</time>");
126                }
127
128                if (timestamp != null) {
129                    buf.append("<join-time>");
130                    buf.append(dateFormat.format(timestamp));
131                    buf.append("</join-time>");
132                }
133
134                buf.append("</user>");
135            }
136        }
137        buf.append("</").append(ELEMENT_NAME).append('>');
138        return buf.toString();
139    }
140
141    /**
142     * Provider class for QueueDetails stanza(/packet) extensions.
143     */
144    public static class Provider extends ExtensionElementProvider<QueueDetails> {
145
146        @Override
147        public QueueDetails parse(XmlPullParser parser,
148                        int initialDepth) throws XmlPullParserException,
149                        IOException, SmackException {
150
151            SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
152            QueueDetails queueDetails = new QueueDetails();
153
154            int eventType = parser.getEventType();
155            while (eventType != XmlPullParser.END_TAG &&
156                    "notify-queue-details".equals(parser.getName()))
157            {
158                eventType = parser.next();
159                while ((eventType == XmlPullParser.START_TAG) && "user".equals(parser.getName())) {
160                    String uid;
161                    int position = -1;
162                    int time = -1;
163                    Date joinTime = null;
164
165                    uid = parser.getAttributeValue("", "jid");
166
167                    if (uid == null) {
168                        // throw exception
169                    }
170
171                    eventType = parser.next();
172                    while ((eventType != XmlPullParser.END_TAG)
173                                || (!"user".equals(parser.getName())))
174                    {
175                        if ("position".equals(parser.getName())) {
176                            position = Integer.parseInt(parser.nextText());
177                        }
178                        else if ("time".equals(parser.getName())) {
179                            time = Integer.parseInt(parser.nextText());
180                        }
181                        else if ("join-time".equals(parser.getName())) {
182                            try {
183                                joinTime = dateFormat.parse(parser.nextText());
184                            } catch (ParseException e) {
185                                throw new SmackException(e);
186                            }
187                        }
188                        else if (parser.getName().equals("waitTime")) {
189                            Date wait;
190                            try {
191                                wait = dateFormat.parse(parser.nextText());
192                            } catch (ParseException e) {
193                                throw new SmackException(e);
194                            }
195                            LOGGER.fine(wait.toString());
196                        }
197
198                        eventType = parser.next();
199
200                        if (eventType != XmlPullParser.END_TAG) {
201                            // throw exception
202                        }
203                    }
204
205                    queueDetails.addUser(new QueueUser(uid, position, time, joinTime));
206
207                    eventType = parser.next();
208                }
209            }
210            return queueDetails;
211        }
212    }
213}