001/*
002 *
003 * Copyright 2003-2007 Jive Software, 2014-2019 Florian Schmaus
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.iqlast.packet;
019
020import java.io.IOException;
021
022import org.jivesoftware.smack.packet.IQ;
023import org.jivesoftware.smack.packet.IqData;
024import org.jivesoftware.smack.packet.XmlEnvironment;
025import org.jivesoftware.smack.provider.IqProvider;
026import org.jivesoftware.smack.xml.XmlPullParser;
027import org.jivesoftware.smack.xml.XmlPullParserException;
028
029import org.jxmpp.JxmppContext;
030import org.jxmpp.jid.Jid;
031
032/**
033 * A last activity IQ for retrieving information about the last activity associated with a Jabber ID.
034 * LastActivity (XEP-0012) allows for retrieval of how long a particular user has been idle and the
035 * message the specified when doing so. Use {@link org.jivesoftware.smackx.iqlast.LastActivityManager}
036 * to get the last activity of a user.
037 *
038 * @author Derek DeMoro
039 * @author Florian Schmaus
040 */
041public class LastActivity extends IQ {
042
043    public static final String ELEMENT = QUERY_ELEMENT;
044    public static final String NAMESPACE = "jabber:iq:last";
045
046    public long lastActivity = -1;
047    public String message;
048
049    @SuppressWarnings("this-escape")
050    public LastActivity() {
051        super(ELEMENT, NAMESPACE);
052        setType(IQ.Type.get);
053    }
054
055    @SuppressWarnings("this-escape")
056    public LastActivity(Jid to) {
057        this();
058        setTo(to);
059    }
060
061    @Override
062    protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
063        xml.optLongAttribute("seconds", lastActivity);
064
065        // We don't support adding the optional message attribute, because it is usually only added
066        // by XMPP servers and not by client entities.
067        xml.setEmptyElement();
068        return xml;
069    }
070
071
072    public void setLastActivity(long lastActivity) {
073        this.lastActivity = lastActivity;
074    }
075
076
077    private void setMessage(String message) {
078        this.message = message;
079    }
080
081    /**
082     * Returns number of seconds that have passed since the user last logged out.
083     * If the user is offline, 0 will be returned.
084     *
085     * @return the number of seconds that have passed since the user last logged out.
086     */
087    public long getIdleTime() {
088        return lastActivity;
089    }
090
091
092    /**
093     * Returns the status message of the last unavailable presence received from the user.
094     *
095     * @return the status message of the last unavailable presence received from the user
096     */
097    public String getStatusMessage() {
098        return message;
099    }
100
101
102    /**
103     * The IQ Provider for LastActivity.
104     *
105     * @author Derek DeMoro
106     */
107    public static class Provider extends IqProvider<LastActivity> {
108
109        @Override
110        public LastActivity parse(XmlPullParser parser, int initialDepth, IqData iqData, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException {
111            LastActivity lastActivity = new LastActivity();
112            String seconds = parser.getAttributeValue("", "seconds");
113            if (seconds != null) {
114                try {
115                    lastActivity.setLastActivity(Long.parseLong(seconds));
116                } catch (NumberFormatException e) {
117                    // TODO: Should be SmackParseException (or a SmackParseNumberException subclass of).
118                    throw new IOException("Could not parse last activity number", e);
119                }
120            }
121            lastActivity.setMessage(parser.nextText());
122            return lastActivity;
123        }
124    }
125}