001/**
002 *
003 * Copyright 2015-2020 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 */
017package org.jivesoftware.smackx.muc;
018
019import java.util.Date;
020
021import org.jivesoftware.smack.XMPPConnection;
022import org.jivesoftware.smack.packet.Presence;
023import org.jivesoftware.smack.packet.PresenceBuilder;
024import org.jivesoftware.smack.util.Consumer;
025import org.jivesoftware.smack.util.Objects;
026
027import org.jivesoftware.smackx.muc.packet.MUCInitialPresence;
028
029import org.jxmpp.jid.EntityFullJid;
030import org.jxmpp.jid.impl.JidCreate;
031import org.jxmpp.jid.parts.Resourcepart;
032
033/**
034 * The configuration used to enter a MUC room. This configuration is usually used when joining an
035 * existing room. When creating a new room, only the Nickname setting is relevant.
036 * <p>
037 * A builder for this can be obtained by calling {@link MultiUserChat#getEnterConfigurationBuilder(Resourcepart)}.
038 * </p>
039 *
040 * @author Florian Schmaus
041 * @since 4.2
042 */
043public final class MucEnterConfiguration {
044
045    private final Resourcepart nickname;
046    private final String password;
047    private final int maxChars;
048    private final int maxStanzas;
049    private final int seconds;
050    private final Date since;
051    private final long timeout;
052    private final Presence joinPresence;
053
054    MucEnterConfiguration(Builder builder) {
055        nickname = builder.nickname;
056        password = builder.password;
057        maxChars = builder.maxChars;
058        maxStanzas = builder.maxStanzas;
059        seconds = builder.seconds;
060        since = builder.since;
061        timeout = builder.timeout;
062
063        final PresenceBuilder joinPresenceBuilder;
064        if (builder.joinPresence == null) {
065            joinPresenceBuilder = builder.joinPresenceBuilder.ofType(Presence.Type.available);
066        }
067        else {
068            joinPresenceBuilder = builder.joinPresence.asBuilder();
069        }
070        // Indicate the client supports MUC
071        joinPresenceBuilder.addExtension(new MUCInitialPresence(password, maxChars, maxStanzas, seconds,
072                        since));
073        joinPresence = joinPresenceBuilder.build();
074    }
075
076    Presence getJoinPresence(MultiUserChat multiUserChat) {
077        final EntityFullJid jid = JidCreate.entityFullFrom(multiUserChat.getRoom(), nickname);
078        joinPresence.setTo(jid);
079        return joinPresence;
080    }
081
082    long getTimeout() {
083        return timeout;
084    }
085
086    public static final class Builder {
087        private final Resourcepart nickname;
088
089        private String password;
090        private int maxChars = -1;
091        private int maxStanzas = -1;
092        private int seconds = -1;
093        private Date since;
094        private long timeout;
095
096        private final PresenceBuilder joinPresenceBuilder;
097
098        // TODO: Remove in Smack 4.5.
099        private Presence joinPresence;
100
101        Builder(Resourcepart nickname, XMPPConnection connection) {
102            this.nickname = Objects.requireNonNull(nickname, "Nickname must not be null");
103
104            timeout = connection.getReplyTimeout();
105            timeoutAfter(timeout);
106
107            joinPresenceBuilder = connection.getStanzaFactory().buildPresenceStanza();
108        }
109
110        /**
111         * Set the presence used to join the MUC room.
112         * <p>
113         * The 'to' value of the given presence will be overridden and the given presence must be of type
114         * 'available', otherwise an {@link IllegalArgumentException} will be thrown.
115         * <p>
116         *
117         * @param presence TODO javadoc me please
118         * @return a reference to this builder.
119         * @deprecated use {@link #withPresence(Consumer)} instead.
120         */
121        @Deprecated
122        // TODO: Remove in Smack 4.5.
123        public Builder withPresence(Presence presence) {
124            if (presence.getType() != Presence.Type.available) {
125                throw new IllegalArgumentException("Presence must be of type 'available'");
126            }
127
128            joinPresence = presence;
129            return this;
130        }
131
132        /**
133         * Set the presence used to join the MUC room.
134         * <p>
135         * The consumer must not modify the presence type, otherwise an {@link IllegalArgumentException} will be thrown.
136         * <p>
137         *
138         * @param presenceBuilderConsumer a consumer which will be passed the presence build.
139         * @return a reference to this builder.
140         * @since 4.4.0
141         */
142        public Builder withPresence(Consumer<? super PresenceBuilder> presenceBuilderConsumer) {
143            presenceBuilderConsumer.accept(joinPresenceBuilder);
144
145            if (joinPresenceBuilder.getType() != Presence.Type.available) {
146                throw new IllegalArgumentException("Presence must be of type 'available'");
147            }
148
149            return this;
150        }
151
152        /**
153         * Use the given password to join the MUC room.
154         *
155         * @param password the password used to join.
156         * @return a reference to this builder.
157         */
158        public Builder withPassword(String password) {
159            this.password = password;
160            return this;
161        }
162
163        /**
164         * Set the timeout used when joining the MUC room.
165         *
166         * @param timeout the timeout to use when joining.
167         * @return a reference to this builder.
168         */
169        public Builder timeoutAfter(long timeout) {
170            if (timeout <= 0) {
171                throw new IllegalArgumentException("timeout must be positive");
172            }
173            this.timeout = timeout;
174            return this;
175        }
176
177        /**
178         * Request that that MUC is going to sent us no history when joining.
179         *
180         * @return a reference to this builder.
181         */
182        public Builder requestNoHistory() {
183            maxChars = 0;
184            maxStanzas = -1;
185            seconds = -1;
186            since = null;
187            return this;
188        }
189
190        /**
191         * Sets the total number of characters to receive in the history.
192         *
193         * @param maxChars the total number of characters to receive in the history.
194         * @return a reference to this builder.
195         */
196        public Builder requestMaxCharsHistory(int maxChars) {
197            this.maxChars = maxChars;
198            return this;
199        }
200
201        /**
202         * Sets the total number of messages to receive in the history.
203         *
204         * @param maxStanzas the total number of messages to receive in the history.
205         * @return a reference to this builder.
206         */
207        public Builder requestMaxStanzasHistory(int maxStanzas) {
208            this.maxStanzas = maxStanzas;
209            return this;
210        }
211
212        /**
213         * Sets the number of seconds to use to filter the messages received during that time.
214         * In other words, only the messages received in the last "X" seconds will be included in
215         * the history.
216         *
217         * @param seconds the number of seconds to use to filter the messages received during
218         * that time.
219         * @return a reference to this builder.
220         */
221        public Builder requestHistorySince(int seconds) {
222            this.seconds = seconds;
223            return this;
224        }
225
226        /**
227         * Sets the since date to use to filter the messages received during that time.
228         * In other words, only the messages received since the datetime specified will be
229         * included in the history.
230         *
231         * @param since the since date to use to filter the messages received during that time.
232         * @return a reference to this builder.
233         */
234        public Builder requestHistorySince(Date since) {
235            this.since = since;
236            return this;
237        }
238
239        /**
240         * Build a new {@link MucEnterConfiguration} with the current builder.
241         *
242         * @return a new {@code MucEnterConfiguration}.
243         */
244        public MucEnterConfiguration build() {
245            return new MucEnterConfiguration(this);
246        }
247
248    }
249}