001/**
002 *
003 * Copyright 2017-2022 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.jingle.element;
018
019import java.util.HashMap;
020import java.util.Map;
021
022import org.jivesoftware.smack.packet.XmlElement;
023import org.jivesoftware.smack.packet.XmlEnvironment;
024import org.jivesoftware.smack.util.StringUtils;
025import org.jivesoftware.smack.util.XmlStringBuilder;
026
027/**
028 * The Jingle 'reason' element.
029 *
030 * @see <a href="https://xmpp.org/extensions/xep-0166.html#def-reason">XEP-0166 ยง 7.4</a>
031 *
032 */
033public class JingleReason implements XmlElement {
034
035    public static final String ELEMENT = "reason";
036    public static final String NAMESPACE = Jingle.NAMESPACE;
037    public static final String TEXT_ELEMENT = "text";
038
039    public static AlternativeSession AlternativeSession(String sessionId) {
040        return new AlternativeSession(sessionId);
041    }
042
043    public static final JingleReason Busy = new JingleReason(Reason.busy);
044    public static final JingleReason Cancel = new JingleReason(Reason.cancel);
045    public static final JingleReason ConnectivityError = new JingleReason(Reason.connectivity_error);
046    public static final JingleReason Decline = new JingleReason(Reason.decline);
047    public static final JingleReason Expired = new JingleReason(Reason.expired);
048    public static final JingleReason FailedApplication = new JingleReason(Reason.failed_application);
049    public static final JingleReason FailedTransport = new JingleReason(Reason.failed_transport);
050    public static final JingleReason GeneralError = new JingleReason(Reason.general_error);
051    public static final JingleReason Gone = new JingleReason(Reason.gone);
052    public static final JingleReason IncompatibleParameters = new JingleReason(Reason.incompatible_parameters);
053    public static final JingleReason MediaError = new JingleReason(Reason.media_error);
054    public static final JingleReason SecurityError = new JingleReason(Reason.security_error);
055    public static final JingleReason Success = new JingleReason(Reason.success);
056    public static final JingleReason Timeout = new JingleReason(Reason.timeout);
057    public static final JingleReason UnsupportedApplications = new JingleReason(Reason.unsupported_applications);
058    public static final JingleReason UnsupportedTransports = new JingleReason(Reason.unsupported_transports);
059
060    public enum Reason {
061        alternative_session,
062        busy,
063        cancel,
064        connectivity_error,
065        decline,
066        expired,
067        failed_application,
068        failed_transport,
069        general_error,
070        gone,
071        incompatible_parameters,
072        media_error,
073        security_error,
074        success,
075        timeout,
076        unsupported_applications,
077        unsupported_transports,
078        ;
079
080        static final Map<String, Reason> LUT = new HashMap<>(Reason.values().length);
081
082        static {
083            for (Reason reason : Reason.values()) {
084                LUT.put(reason.toString(), reason);
085            }
086        }
087
088        final String asString;
089
090        Reason() {
091            asString = name().replace('_', '-');
092        }
093
094        @Override
095        public String toString() {
096            return asString;
097        }
098
099        public static Reason fromString(String string) {
100            Reason reason = LUT.get(string);
101            if (reason == null) {
102                throw new IllegalArgumentException("Unknown reason: " + string);
103            }
104            return reason;
105        }
106    }
107
108    protected final Reason reason;
109    private final String text;
110    private final XmlElement element;
111
112    public JingleReason(Reason reason) {
113        this(reason, null, null);
114    }
115
116    public JingleReason(Reason reason, String text, XmlElement element) {
117        this.reason = reason;
118        this.text = text;
119        this.element = element;
120    }
121
122    @Override
123    public String getElementName() {
124        return ELEMENT;
125    }
126
127    @Override
128    public String getNamespace() {
129        return NAMESPACE;
130    }
131
132    /**
133     * An optional text that provides human-readable information about the reason for the action.
134     *
135     * @return a human-readable text with information regarding this reason or <code>null</code>.
136     * @since 4.4.5
137     */
138    public String getText() {
139        return text;
140    }
141
142    /**
143     * An optional element that provides more detailed machine-readable information about the reason for the action.
144     *
145     * @return an element with machine-readable information about this reason or <code>null</code>.
146     * @since 4.4.5
147     */
148    public XmlElement getElement() {
149        return element;
150    }
151
152    @Override
153    public XmlStringBuilder toXML(XmlEnvironment enclosingXmlEnvironment) {
154        XmlStringBuilder xml = new XmlStringBuilder(this, enclosingXmlEnvironment);
155        xml.rightAngleBracket();
156
157        xml.emptyElement(reason);
158        xml.optElement(TEXT_ELEMENT, text);
159        xml.optAppend(element);
160
161        xml.closeElement(this);
162        return xml;
163    }
164
165    public Reason asEnum() {
166        return reason;
167    }
168
169
170    public static class AlternativeSession extends JingleReason {
171
172        public static final String SID = "sid";
173        private final String sessionId;
174
175        public AlternativeSession(String sessionId) {
176            this(sessionId, null, null);
177        }
178
179        public AlternativeSession(String sessionId, String text, XmlElement element) {
180            super(Reason.alternative_session, text, element);
181            if (StringUtils.isNullOrEmpty(sessionId)) {
182                throw new NullPointerException("SessionID must not be null or empty.");
183            }
184            this.sessionId = sessionId;
185        }
186
187        @Override
188        public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
189            XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
190            xml.rightAngleBracket();
191
192            xml.openElement(reason.asString);
193            xml.openElement(SID);
194            xml.append(sessionId);
195            xml.closeElement(SID);
196            xml.closeElement(reason.asString);
197
198            xml.closeElement(this);
199            return xml;
200        }
201
202        public String getAlternativeSessionId() {
203            return sessionId;
204        }
205    }
206}