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.Collections;
024import java.util.Date;
025import java.util.HashSet;
026import java.util.Set;
027import java.util.TimeZone;
028
029import org.jivesoftware.smack.packet.IQ;
030import org.jivesoftware.smack.packet.IqData;
031import org.jivesoftware.smack.packet.XmlEnvironment;
032import org.jivesoftware.smack.provider.IqProvider;
033import org.jivesoftware.smack.xml.XmlPullParser;
034import org.jivesoftware.smack.xml.XmlPullParserException;
035
036import org.jxmpp.JxmppContext;
037
038/**
039 * Stanza used for requesting information about occupants of a room or for retrieving information
040 * such information.
041 *
042 * @author Gaston Dombiak
043 */
044public class OccupantsInfo extends IQ {
045
046    @SuppressWarnings("DateFormatConstant")
047    private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
048
049    static {
050        UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
051    }
052
053    /**
054     * Element name of the stanza extension.
055     */
056    public static final String ELEMENT_NAME = "occupants-info";
057
058    /**
059     * Namespace of the stanza extension.
060     */
061    public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
062
063    private final String roomID;
064    private final Set<OccupantInfo> occupants;
065
066    public OccupantsInfo(String roomID) {
067        super(ELEMENT_NAME, NAMESPACE);
068        this.roomID = roomID;
069        this.occupants = new HashSet<>();
070    }
071
072    public String getRoomID() {
073        return roomID;
074    }
075
076    public int getOccupantsCount() {
077        return occupants.size();
078    }
079
080    public Set<OccupantInfo> getOccupants() {
081        return Collections.unmodifiableSet(occupants);
082    }
083
084    @Override
085    protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder buf) {
086        buf.append(" roomID=\"").append(roomID).append("\">");
087        synchronized (occupants) {
088            for (OccupantInfo occupant : occupants) {
089                buf.append("<occupant>");
090                // Add the occupant jid
091                buf.append("<jid>");
092                buf.append(occupant.getJID());
093                buf.append("</jid>");
094                // Add the occupant nickname
095                buf.append("<name>");
096                buf.append(occupant.getNickname());
097                buf.append("</name>");
098                // Add the date when the occupant joined the room
099                buf.append("<joined>");
100                synchronized (UTC_FORMAT) {
101                    buf.append(UTC_FORMAT.format(occupant.getJoined()));
102                }
103                buf.append("</joined>");
104                buf.append("</occupant>");
105            }
106        }
107        return buf;
108    }
109
110    public static class OccupantInfo {
111
112        private final String jid;
113        private final String nickname;
114        private final Date joined;
115
116        public OccupantInfo(String jid, String nickname, Date joined) {
117            this.jid = jid;
118            this.nickname = nickname;
119            this.joined = joined;
120        }
121
122        public String getJID() {
123            return jid;
124        }
125
126        public String getNickname() {
127            return nickname;
128        }
129
130        public Date getJoined() {
131            return joined;
132        }
133    }
134
135    /**
136     * Stanza extension provider for AgentStatusRequest packets.
137     */
138    public static class Provider extends IqProvider<OccupantsInfo> {
139
140        @Override
141        public OccupantsInfo parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext)
142                        throws XmlPullParserException, IOException, ParseException {
143            OccupantsInfo occupantsInfo = new OccupantsInfo(parser.getAttributeValue("", "roomID"));
144
145            boolean done = false;
146            while (!done) {
147                XmlPullParser.Event eventType = parser.next();
148                if (eventType == XmlPullParser.Event.START_ELEMENT &&
149                        "occupant".equals(parser.getName())) {
150                    occupantsInfo.occupants.add(parseOccupantInfo(parser));
151                } else if (eventType == XmlPullParser.Event.END_ELEMENT &&
152                        ELEMENT_NAME.equals(parser.getName())) {
153                    done = true;
154                }
155            }
156            return occupantsInfo;
157        }
158
159        private static OccupantInfo parseOccupantInfo(XmlPullParser parser)
160                        throws XmlPullParserException, IOException, ParseException {
161            boolean done = false;
162            String jid = null;
163            String nickname = null;
164            Date joined = null;
165            while (!done) {
166                XmlPullParser.Event eventType = parser.next();
167                if (eventType == XmlPullParser.Event.START_ELEMENT && "jid".equals(parser.getName())) {
168                    jid = parser.nextText();
169                } else if (eventType == XmlPullParser.Event.START_ELEMENT &&
170                        "nickname".equals(parser.getName())) {
171                    nickname = parser.nextText();
172                } else if (eventType == XmlPullParser.Event.START_ELEMENT &&
173                        "joined".equals(parser.getName())) {
174                        synchronized (UTC_FORMAT) {
175                            joined = UTC_FORMAT.parse(parser.nextText());
176                        }
177                } else if (eventType == XmlPullParser.Event.END_ELEMENT &&
178                        "occupant".equals(parser.getName())) {
179                    done = true;
180                }
181            }
182            return new OccupantInfo(jid, nickname, joined);
183        }
184    }
185}