001/**
002 *
003 * Copyright 2015-2024 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 = builder.joinPresenceBuilder.ofType(Presence.Type.available);
064
065        // Indicate the client supports MUC
066        joinPresenceBuilder.addExtension(new MUCInitialPresence(password, maxChars, maxStanzas, seconds,
067                        since));
068        joinPresence = joinPresenceBuilder.build();
069    }
070
071    Presence getJoinPresence(MultiUserChat multiUserChat) {
072        final EntityFullJid jid = JidCreate.entityFullFrom(multiUserChat.getRoom(), nickname);
073        joinPresence.setTo(jid);
074        return joinPresence;
075    }
076
077    long getTimeout() {
078        return timeout;
079    }
080
081    public static final class Builder {
082        private final Resourcepart nickname;
083
084        private String password;
085        private int maxChars = -1;
086        private int maxStanzas = -1;
087        private int seconds = -1;
088        private Date since;
089        private long timeout;
090
091        private final PresenceBuilder joinPresenceBuilder;
092
093        Builder(Resourcepart nickname, XMPPConnection connection) {
094            this.nickname = Objects.requireNonNull(nickname, "Nickname must not be null");
095
096            timeout = connection.getReplyTimeout();
097            timeoutAfter(timeout);
098
099            joinPresenceBuilder = connection.getStanzaFactory().buildPresenceStanza();
100        }
101
102        /**
103         * Set the presence used to join the MUC room.
104         * <p>
105         * The consumer must not modify the presence type, otherwise an {@link IllegalArgumentException} will be thrown.
106         * <p>
107         *
108         * @param presenceBuilderConsumer a consumer which will be passed the presence build.
109         * @return a reference to this builder.
110         * @since 4.4.0
111         */
112        public Builder withPresence(Consumer<? super PresenceBuilder> presenceBuilderConsumer) {
113            presenceBuilderConsumer.accept(joinPresenceBuilder);
114
115            if (joinPresenceBuilder.getType() != Presence.Type.available) {
116                throw new IllegalArgumentException("Presence must be of type 'available'");
117            }
118
119            return this;
120        }
121
122        /**
123         * Use the given password to join the MUC room.
124         *
125         * @param password the password used to join.
126         * @return a reference to this builder.
127         */
128        public Builder withPassword(String password) {
129            this.password = password;
130            return this;
131        }
132
133        /**
134         * Set the timeout used when joining the MUC room.
135         *
136         * @param timeout the timeout to use when joining.
137         * @return a reference to this builder.
138         */
139        public Builder timeoutAfter(long timeout) {
140            if (timeout <= 0) {
141                throw new IllegalArgumentException("timeout must be positive");
142            }
143            this.timeout = timeout;
144            return this;
145        }
146
147        /**
148         * Request that that MUC is going to sent us no history when joining.
149         *
150         * @return a reference to this builder.
151         */
152        public Builder requestNoHistory() {
153            maxChars = 0;
154            maxStanzas = -1;
155            seconds = -1;
156            since = null;
157            return this;
158        }
159
160        /**
161         * Sets the total number of characters to receive in the history.
162         *
163         * @param maxChars the total number of characters to receive in the history.
164         * @return a reference to this builder.
165         */
166        public Builder requestMaxCharsHistory(int maxChars) {
167            this.maxChars = maxChars;
168            return this;
169        }
170
171        /**
172         * Sets the total number of messages to receive in the history.
173         *
174         * @param maxStanzas the total number of messages to receive in the history.
175         * @return a reference to this builder.
176         */
177        public Builder requestMaxStanzasHistory(int maxStanzas) {
178            this.maxStanzas = maxStanzas;
179            return this;
180        }
181
182        /**
183         * Sets the number of seconds to use to filter the messages received during that time.
184         * In other words, only the messages received in the last "X" seconds will be included in
185         * the history.
186         *
187         * @param seconds the number of seconds to use to filter the messages received during
188         * that time.
189         * @return a reference to this builder.
190         */
191        public Builder requestHistorySince(int seconds) {
192            this.seconds = seconds;
193            return this;
194        }
195
196        /**
197         * Sets the since date to use to filter the messages received during that time.
198         * In other words, only the messages received since the datetime specified will be
199         * included in the history.
200         *
201         * @param since the since date to use to filter the messages received during that time.
202         * @return a reference to this builder.
203         */
204        public Builder requestHistorySince(Date since) {
205            this.since = since;
206            return this;
207        }
208
209        /**
210         * Build a new {@link MucEnterConfiguration} with the current builder.
211         *
212         * @return a new {@code MucEnterConfiguration}.
213         */
214        public MucEnterConfiguration build() {
215            return new MucEnterConfiguration(this);
216        }
217
218    }
219}