001/**
002 *
003 * Copyright 2019-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.smack.packet;
018
019import org.jivesoftware.smack.packet.Message.Body;
020import org.jivesoftware.smack.packet.Message.Subject;
021import org.jivesoftware.smack.packet.id.StanzaIdSource;
022import org.jivesoftware.smack.util.StringUtils;
023import org.jivesoftware.smack.util.ToStringUtil;
024
025public final class MessageBuilder extends MessageOrPresenceBuilder<Message, MessageBuilder> implements MessageView {
026    static final MessageBuilder EMPTY = new MessageBuilder(() -> {
027        return null;
028    });
029
030    Message.Type type;
031
032    MessageBuilder(Message message, String stanzaId) {
033        super(message, stanzaId);
034        copyFromMessage(message);
035    }
036
037    MessageBuilder(Message message, StanzaIdSource stanzaIdSource) {
038        super(message, stanzaIdSource);
039        copyFromMessage(message);
040    }
041
042    MessageBuilder(StanzaIdSource stanzaIdSource) {
043        super(stanzaIdSource);
044    }
045
046    MessageBuilder(String stanzaId) {
047        super(stanzaId);
048    }
049
050    private void copyFromMessage(Message message) {
051        type = message.getType();
052    }
053
054    @Override
055    protected void addStanzaSpecificAttributes(ToStringUtil.Builder builder) {
056        builder.addValue("type", type)
057               ;
058    }
059
060    public MessageBuilder ofType(Message.Type type) {
061        this.type = type;
062        return getThis();
063    }
064
065    public MessageBuilder setThread(String thread) {
066        return setThread(thread, null);
067    }
068
069    public MessageBuilder setThread(String thread, String parent) {
070        addExtension(new Message.Thread(thread, parent));
071        return getThis();
072    }
073
074    /**
075     * Sets the subject of the message. The subject is a short description of
076     * message contents.
077     *
078     * @param subject the subject of the message.
079     * @return a reference to this builder.
080     */
081    public MessageBuilder setSubject(String subject) {
082        return addSubject(null, subject);
083    }
084
085    /**
086     * Adds a subject with a corresponding language.
087     *
088     * @param language the language of the subject being added.
089     * @param subject the subject being added to the message.
090     * @return a reference to this builder.
091     * @throws NullPointerException if the subject is null.
092     */
093    public MessageBuilder addSubject(String language, String subject) {
094        language = StringUtils.requireNullOrNotEmpty(language, "language must be null or not empty");
095
096        for (Subject currentSubject : getExtensions(Subject.class)) {
097            if (StringUtils.nullSafeCharSequenceEquals(language, currentSubject.getLanguage())) {
098                throw new IllegalArgumentException("Subject with the language " + language + " already exists");
099            }
100        }
101
102        Subject messageSubject = new Subject(language, subject);
103        addExtension(messageSubject);
104
105        return this;
106    }
107
108    /**
109     * Sets the body of the message.
110     *
111     * @param body the body of the message.
112     * @return a reference to this builder.
113     * @see #setBody(String)
114     */
115    public MessageBuilder setBody(CharSequence body) {
116        return setBody(body.toString());
117    }
118
119    /**
120     * Sets the body of the message. The body is the main message contents.
121     *
122     * @param body the body of the message.
123     * @return a reference to this builder.
124     */
125    public MessageBuilder setBody(String body) {
126        return addBody(null, body);
127    }
128
129    /**
130     * Adds a body with a corresponding language.
131     *
132     * @param language the language of the body being added.
133     * @param body the body being added to the message.
134     * @return a reference to this builder.
135     */
136    public MessageBuilder addBody(String language, String body) {
137        language = StringUtils.requireNullOrNotEmpty(language, "language must be null or not empty");
138
139        for (Body currentBody : getExtensions(Body.class)) {
140            if (StringUtils.nullSafeCharSequenceEquals(language, currentBody.getLanguage())) {
141                throw new IllegalArgumentException("Bodyt with the language " + language + " already exists");
142            }
143        }
144
145        Body messageBody = new Body(language, body);
146        addExtension(messageBody);
147
148        return this;
149    }
150
151    @Override
152    public MessageBuilder getThis() {
153        return this;
154    }
155
156    @Override
157    public Message build() {
158        return new Message(this);
159    }
160
161    @Override
162    public Message.Type getType() {
163        return type;
164    }
165}