StanzaBuilder.java
- /**
- *
- * Copyright 2019-2021 Florian Schmaus
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.jivesoftware.smack.packet;
- import java.util.Collection;
- import java.util.List;
- import javax.xml.namespace.QName;
- import org.jivesoftware.smack.packet.id.StanzaIdSource;
- import org.jivesoftware.smack.util.Function;
- import org.jivesoftware.smack.util.MultiMap;
- import org.jivesoftware.smack.util.StringUtils;
- import org.jivesoftware.smack.util.ToStringUtil;
- import org.jivesoftware.smack.util.XmppElementUtil;
- import org.jxmpp.jid.Jid;
- import org.jxmpp.jid.impl.JidCreate;
- import org.jxmpp.stringprep.XmppStringprepException;
- public abstract class StanzaBuilder<B extends StanzaBuilder<B>> implements StanzaView {
- final StanzaIdSource stanzaIdSource;
- final String stanzaId;
- Jid to;
- Jid from;
- StanzaError stanzaError;
- String language;
- MultiMap<QName, XmlElement> extensionElements = new MultiMap<>();
- protected StanzaBuilder(StanzaBuilder<?> other) {
- stanzaIdSource = other.stanzaIdSource;
- stanzaId = other.stanzaId;
- to = other.to;
- from = other.from;
- stanzaError = other.stanzaError;
- language = other.language;
- extensionElements = other.extensionElements.clone();
- }
- protected StanzaBuilder(StanzaIdSource stanzaIdSource) {
- this.stanzaIdSource = stanzaIdSource;
- this.stanzaId = null;
- }
- protected StanzaBuilder(String stanzaId) {
- this.stanzaIdSource = null;
- this.stanzaId = StringUtils.requireNullOrNotEmpty(stanzaId, "Stanza ID must not be the empty String");
- }
- protected StanzaBuilder(Stanza message, String stanzaId) {
- this(stanzaId);
- copyFromStanza(message);
- }
- protected StanzaBuilder(Stanza message, StanzaIdSource stanzaIdSource) {
- this(stanzaIdSource);
- copyFromStanza(message);
- }
- private void copyFromStanza(Stanza stanza) {
- to = stanza.getTo();
- from = stanza.getFrom();
- stanzaError = stanza.getError();
- language = stanza.getLanguage();
- extensionElements = stanza.cloneExtensionsMap();
- }
- /**
- * Set the recipient address of the stanza.
- *
- * @param to whom the stanza is being sent.
- * @return a reference to this builder.
- * @throws XmppStringprepException if the provided character sequence is not a valid XMPP address.
- * @see #to(Jid)
- */
- public final B to(CharSequence to) throws XmppStringprepException {
- return to(JidCreate.from(to));
- }
- /**
- * Sets who the stanza is being sent "to". The XMPP protocol often makes the "to" attribute optional, so it does not
- * always need to be set.
- *
- * @param to who the stanza is being sent to.
- * @return a reference to this builder.
- */
- public final B to(Jid to) {
- this.to = to;
- return getThis();
- }
- /**
- * Sets who the stanza is being sent "from".
- *
- * @param from who the stanza is being sent from.
- * @return a reference to this builder.
- * @throws XmppStringprepException if the provided character sequence is not a valid XMPP address.
- * @see #from(Jid)
- */
- public final B from(CharSequence from) throws XmppStringprepException {
- return from(JidCreate.from(from));
- }
- /**
- * Sets who the stanza is being sent "from". The XMPP protocol often makes the "from" attribute optional, so it does
- * not always need to be set.
- *
- * @param from who the stanza is being sent from.
- * @return a reference to this builder.
- */
- public final B from(Jid from) {
- this.from = from;
- return getThis();
- }
- /**
- * Sets the error for this stanza.
- *
- * @param stanzaError the error to associate with this stanza.
- * @return a reference to this builder.
- */
- public final B setError(StanzaError stanzaError) {
- this.stanzaError = stanzaError;
- return getThis();
- }
- /**
- * Sets the xml:lang for this stanza.
- *
- * @param language the xml:lang of this stanza.
- * @return a reference to this builder.
- */
- public final B setLanguage(String language) {
- this.language = language;
- return getThis();
- }
- public final B addExtension(XmlElement extensionElement) {
- QName key = extensionElement.getQName();
- extensionElements.put(key, extensionElement);
- return getThis();
- }
- public final B addOptExtensions(Collection<? extends XmlElement> extensionElements) {
- if (extensionElements == null) {
- return getThis();
- }
- return addExtensions(extensionElements);
- }
- public final B addExtensions(Collection<? extends XmlElement> extensionElements) {
- for (XmlElement extensionElement : extensionElements) {
- addExtension(extensionElement);
- }
- return getThis();
- }
- public final B overrideExtension(XmlElement extensionElement) {
- QName key = extensionElement.getQName();
- extensionElements.remove(key);
- extensionElements.put(key, extensionElement);
- return getThis();
- }
- public final B removeExtension(String elementName, String namespace) {
- QName key = new QName(namespace, elementName);
- extensionElements.remove(key);
- return getThis();
- }
- public final B removeExtension(ExtensionElement extension) {
- QName key = extension.getQName();
- List<XmlElement> list = extensionElements.getAll(key);
- list.remove(extension);
- return getThis();
- }
- public abstract Stanza build();
- public abstract B getThis();
- @Override
- public final String getStanzaId() {
- return stanzaId;
- }
- @Override
- public final Jid getTo() {
- return to;
- }
- @Override
- public final Jid getFrom() {
- return from;
- }
- @Override
- public final String getLanguage() {
- return language;
- }
- @Override
- public final StanzaError getError() {
- return stanzaError;
- }
- @Override
- public final XmlElement getExtension(QName qname) {
- return extensionElements.getFirst(qname);
- }
- @Override
- public final List<XmlElement> getExtensions() {
- return extensionElements.values();
- }
- @Override
- public final List<XmlElement> getExtensions(QName qname) {
- return extensionElements.getAll(qname);
- }
- @Override
- public final <E extends ExtensionElement> List<E> getExtensions(Class<E> extensionElementClass) {
- return XmppElementUtil.getElementsFrom(extensionElements, extensionElementClass);
- }
- public final boolean willBuildStanzaWithId() {
- return stanzaIdSource != null || StringUtils.isNotEmpty(stanzaId);
- }
- public final void throwIfNoStanzaId() {
- if (willBuildStanzaWithId()) {
- return;
- }
- throw new IllegalArgumentException(
- "The builder will not build a stanza with an ID set, although it is required");
- }
- protected abstract void addStanzaSpecificAttributes(ToStringUtil.Builder builder);
- @Override
- public final String toString() {
- ToStringUtil.Builder builder = ToStringUtil.builderFor(getClass())
- .addValue("id", stanzaId)
- .addValue("from", from)
- .addValue("to", to)
- .addValue("language", language)
- .addValue("error", stanzaError)
- ;
- addStanzaSpecificAttributes(builder);
- builder.add("Extension Elements", extensionElements.values(), e -> {
- return e.getQName();
- });
- return builder.build();
- }
- public static MessageBuilder buildMessage() {
- return buildMessage(null);
- }
- public static MessageBuilder buildMessage(String stanzaId) {
- return new MessageBuilder(stanzaId);
- }
- public static MessageBuilder buildMessageFrom(Message message, String stanzaId) {
- return new MessageBuilder(message, stanzaId);
- }
- public static MessageBuilder buildMessageFrom(Message message, StanzaIdSource stanzaIdSource) {
- return new MessageBuilder(message, stanzaIdSource);
- }
- public static PresenceBuilder buildPresence() {
- return buildPresence(null);
- }
- public static PresenceBuilder buildPresence(String stanzaId) {
- return new PresenceBuilder(stanzaId);
- }
- public static PresenceBuilder buildPresenceFrom(Presence presence, String stanzaId) {
- return new PresenceBuilder(presence, stanzaId);
- }
- public static PresenceBuilder buildPresenceFrom(Presence presence, StanzaIdSource stanzaIdSource) {
- return new PresenceBuilder(presence, stanzaIdSource);
- }
- public static IqData buildIqData(String stanzaId) {
- return new IqData(stanzaId);
- }
- public static <SB extends StanzaBuilder<?>> SB buildResponse(StanzaView request, Function<SB, String> builderFromStanzaId) {
- SB responseBuilder = builderFromStanzaId.apply(request.getStanzaId());
- responseBuilder.to(request.getFrom())
- .from(request.getTo())
- ;
- return responseBuilder;
- }
- }