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.agent;
019
020import java.util.Date;
021import java.util.List;
022import java.util.Map;
023
024import org.jivesoftware.smack.SmackException.NotConnectedException;
025import org.jivesoftware.smack.XMPPConnection;
026import org.jivesoftware.smack.packet.IQ;
027import org.jivesoftware.smack.packet.Stanza;
028
029import org.jxmpp.jid.Jid;
030
031/**
032 * A class embodying the semantic agent chat offer; specific instances allow the acceptance or
033 * rejecting of the offer.<br>
034 *
035 * @author Matt Tucker
036 * @author loki der quaeler
037 * @author Derek DeMoro
038 */
039public class Offer {
040
041    private final XMPPConnection connection;
042    private final AgentSession session;
043
044    private final String sessionID;
045    private final Jid userJID;
046    private final Jid userID;
047    private final Jid workgroupName;
048    private final Date expiresDate;
049    private final Map<String, List<String>> metaData;
050    private final OfferContent content;
051
052    private boolean accepted = false;
053    private boolean rejected = false;
054
055    /**
056     * Creates a new offer.
057     *
058     * @param conn the XMPP connection with which the issuing session was created.
059     * @param agentSession the agent session instance through which this offer was issued.
060     * @param userID  the userID of the user from which the offer originates.
061     * @param userJID the XMPP address of the user from which the offer originates.
062     * @param workgroupName the fully qualified name of the workgroup.
063     * @param sessionID the session id associated with the offer.
064     * @param metaData the metadata associated with the offer.
065     * @param content content of the offer. The content explains the reason for the offer
066     *        (e.g. user request, transfer)
067     */
068    Offer(XMPPConnection conn, AgentSession agentSession, Jid userID,
069            Jid userJID, Jid workgroupName, Date expiresDate,
070            String sessionID, Map<String, List<String>> metaData, OfferContent content) {
071        this.connection = conn;
072        this.session = agentSession;
073        this.userID = userID;
074        this.userJID = userJID;
075        this.workgroupName = workgroupName;
076        this.expiresDate = expiresDate;
077        this.sessionID = sessionID;
078        this.metaData = metaData;
079        this.content = content;
080    }
081
082    /**
083     * Accepts the offer.
084     * @throws NotConnectedException if the XMPP connection is not connected.
085     * @throws InterruptedException if the calling thread was interrupted.
086     */
087    public void accept() throws NotConnectedException, InterruptedException {
088        Stanza acceptPacket = new AcceptPacket(this.session.getWorkgroupJID());
089        connection.sendStanza(acceptPacket);
090        // TODO: listen for a reply.
091        accepted = true;
092    }
093
094    /**
095     * Rejects the offer.
096     * @throws NotConnectedException if the XMPP connection is not connected.
097     * @throws InterruptedException if the calling thread was interrupted.
098     */
099    public void reject() throws NotConnectedException, InterruptedException {
100        RejectPacket rejectPacket = new RejectPacket(this.session.getWorkgroupJID());
101        connection.sendStanza(rejectPacket);
102        // TODO: listen for a reply.
103        rejected = true;
104    }
105
106    /**
107     * Returns the userID that the offer originates from. In most cases, the
108     * userID will simply be the JID of the requesting user. However, users can
109     * also manually specify a userID for their request. In that case, that value will
110     * be returned.
111     *
112     * @return the userID of the user from which the offer originates.
113     */
114    public Jid getUserID() {
115        return userID;
116    }
117
118    /**
119     * Returns the JID of the user that made the offer request.
120     *
121     * @return the user's JID.
122     */
123    public Jid getUserJID() {
124        return userJID;
125    }
126
127    /**
128     * The fully qualified name of the workgroup (e.g.support@example.com).
129     *
130     * @return the name of the workgroup.
131     */
132    public Jid getWorkgroupName() {
133        return this.workgroupName;
134    }
135
136    /**
137     * The date when the offer will expire. The agent must {@link #accept()}
138     * the offer before the expiration date or the offer will lapse and be
139     * routed to another agent. Alternatively, the agent can {@link #reject()}
140     * the offer at any time if they don't wish to accept it.
141     *
142     * @return the date at which this offer expires.
143     */
144    public Date getExpiresDate() {
145        return this.expiresDate;
146    }
147
148    /**
149     * The session ID associated with the offer.
150     *
151     * @return the session id associated with the offer.
152     */
153    public String getSessionID() {
154        return this.sessionID;
155    }
156
157    /**
158     * The meta-data associated with the offer.
159     *
160     * @return the offer meta-data.
161     */
162    public Map<String, List<String>> getMetaData() {
163        return this.metaData;
164    }
165
166    /**
167     * Returns the content of the offer. The content explains the reason for the offer
168     * (e.g. user request, transfer)
169     *
170     * @return the content of the offer.
171     */
172    public OfferContent getContent() {
173        return content;
174    }
175
176    /**
177     * Returns true if the agent accepted this offer.
178     *
179     * @return true if the agent accepted this offer.
180     */
181    public boolean isAccepted() {
182        return accepted;
183    }
184
185    /**
186     * Return true if the agent rejected this offer.
187     *
188     * @return true if the agent rejected this offer.
189     */
190    public boolean isRejected() {
191        return rejected;
192    }
193
194    /**
195     * Stanza for rejecting offers.
196     */
197    private class RejectPacket extends IQ {
198
199        RejectPacket(Jid workgroup) {
200            super("offer-reject", "http://jabber.org/protocol/workgroup");
201            this.setTo(workgroup);
202            this.setType(IQ.Type.set);
203        }
204
205        @Override
206        protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
207            xml.attribute("id", Offer.this.getSessionID());
208            xml.setEmptyElement();
209            return xml;
210        }
211    }
212
213    /**
214     * Stanza for accepting an offer.
215     */
216    private class AcceptPacket extends IQ {
217
218        AcceptPacket(Jid workgroup) {
219            super("offer-accept", "http://jabber.org/protocol/workgroup");
220            this.setTo(workgroup);
221            this.setType(IQ.Type.set);
222        }
223
224        @Override
225        protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
226            xml.attribute("id", Offer.this.getSessionID());
227            xml.setEmptyElement();
228            return xml;
229        }
230    }
231
232}