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