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         * The consumer must not modify the presence type, otherwise an {@link IllegalArgumentException} will be thrown.
105         *
106         * @param presenceBuilderConsumer a consumer which will be passed the presence build.
107         * @return a reference to this builder.
108         * @since 4.4.0
109         */
110        public Builder withPresence(Consumer<? super PresenceBuilder> presenceBuilderConsumer) {
111            presenceBuilderConsumer.accept(joinPresenceBuilder);
112
113            if (joinPresenceBuilder.getType() != Presence.Type.available) {
114                throw new IllegalArgumentException("Presence must be of type 'available'");
115            }
116
117            return this;
118        }
119
120        /**
121         * Use the given password to join the MUC room.
122         *
123         * @param password the password used to join.
124         * @return a reference to this builder.
125         */
126        public Builder withPassword(String password) {
127            this.password = password;
128            return this;
129        }
130
131        /**
132         * Set the timeout used when joining the MUC room.
133         *
134         * @param timeout the timeout to use when joining.
135         * @return a reference to this builder.
136         */
137        public Builder timeoutAfter(long timeout) {
138            if (timeout <= 0) {
139                throw new IllegalArgumentException("timeout must be positive");
140            }
141            this.timeout = timeout;
142            return this;
143        }
144
145        /**
146         * Request that that MUC is going to sent us no history when joining.
147         *
148         * @return a reference to this builder.
149         */
150        public Builder requestNoHistory() {
151            maxChars = 0;
152            maxStanzas = -1;
153            seconds = -1;
154            since = null;
155            return this;
156        }
157
158        /**
159         * Sets the total number of characters to receive in the history.
160         *
161         * @param maxChars the total number of characters to receive in the history.
162         * @return a reference to this builder.
163         */
164        public Builder requestMaxCharsHistory(int maxChars) {
165            this.maxChars = maxChars;
166            return this;
167        }
168
169        /**
170         * Sets the total number of messages to receive in the history.
171         *
172         * @param maxStanzas the total number of messages to receive in the history.
173         * @return a reference to this builder.
174         */
175        public Builder requestMaxStanzasHistory(int maxStanzas) {
176            this.maxStanzas = maxStanzas;
177            return this;
178        }
179
180        /**
181         * Sets the number of seconds to use to filter the messages received during that time.
182         * In other words, only the messages received in the last "X" seconds will be included in
183         * the history.
184         *
185         * @param seconds the number of seconds to use to filter the messages received during
186         * that time.
187         * @return a reference to this builder.
188         */
189        public Builder requestHistorySince(int seconds) {
190            this.seconds = seconds;
191            return this;
192        }
193
194        /**
195         * Sets the since date to use to filter the messages received during that time.
196         * In other words, only the messages received since the datetime specified will be
197         * included in the history.
198         *
199         * @param since the since date to use to filter the messages received during that time.
200         * @return a reference to this builder.
201         */
202        public Builder requestHistorySince(Date since) {
203            this.since = since;
204            return this;
205        }
206
207        /**
208         * Build a new {@link MucEnterConfiguration} with the current builder.
209         *
210         * @return a new {@code MucEnterConfiguration}.
211         */
212        public MucEnterConfiguration build() {
213            return new MucEnterConfiguration(this);
214        }
215
216    }
217}