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