1package im.conversations.android.xmpp.model.jingle;
2
3import androidx.annotation.NonNull;
4
5import com.google.common.base.CaseFormat;
6import com.google.common.base.Preconditions;
7import com.google.common.base.Strings;
8import com.google.common.collect.ImmutableMap;
9
10import eu.siacs.conversations.xml.Element;
11import eu.siacs.conversations.xml.Namespace;
12import eu.siacs.conversations.xmpp.Jid;
13import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
14import eu.siacs.conversations.xmpp.jingle.stanzas.Group;
15import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
16
17import im.conversations.android.annotation.XmlElement;
18import im.conversations.android.xmpp.model.Extension;
19
20import java.util.Map;
21
22@XmlElement
23public class Jingle extends Extension {
24
25 public Jingle() {
26 super(Jingle.class);
27 }
28
29 public Jingle(final Action action, final String sessionId) {
30 this();
31 this.setAttribute("sid", sessionId);
32 this.setAttribute("action", action.toString());
33 }
34
35 public String getSessionId() {
36 return this.getAttribute("sid");
37 }
38
39 public Action getAction() {
40 return Action.of(this.getAttribute("action"));
41 }
42
43 public ReasonWrapper getReason() {
44 final Element reasonElement = this.findChild("reason");
45 if (reasonElement == null) {
46 return new ReasonWrapper(Reason.UNKNOWN, null);
47 }
48 String text = null;
49 Reason reason = Reason.UNKNOWN;
50 for (Element child : reasonElement.getChildren()) {
51 if ("text".equals(child.getName())) {
52 text = child.getContent();
53 } else {
54 reason = Reason.of(child.getName());
55 }
56 }
57 return new ReasonWrapper(reason, text);
58 }
59
60 public void setReason(final Reason reason, final String text) {
61 final Element reasonElement = this.addChild("reason");
62 reasonElement.addChild(reason.toString());
63 if (!Strings.isNullOrEmpty(text)) {
64 reasonElement.addChild("text").setContent(text);
65 }
66 }
67
68 // RECOMMENDED for session-initiate, NOT RECOMMENDED otherwise
69 public void setInitiator(final Jid initiator) {
70 Preconditions.checkArgument(initiator.isFullJid(), "initiator should be a full JID");
71 this.setAttribute("initiator", initiator);
72 }
73
74 // RECOMMENDED for session-accept, NOT RECOMMENDED otherwise
75 public void setResponder(final Jid responder) {
76 Preconditions.checkArgument(responder.isFullJid(), "responder should be a full JID");
77 this.setAttribute("responder", responder);
78 }
79
80 public Group getGroup() {
81 final Element group = this.findChild("group", Namespace.JINGLE_APPS_GROUPING);
82 return group == null ? null : Group.upgrade(group);
83 }
84
85 public void addGroup(final Group group) {
86 this.addChild(group);
87 }
88
89 // TODO deprecate this somehow and make file transfer fail if there are multiple (or something)
90 public Content getJingleContent() {
91 final Element content = this.findChild("content");
92 return content == null ? null : Content.upgrade(content);
93 }
94
95 public void addJingleContent(final Content content) { // take content interface
96 this.addChild(content);
97 }
98
99
100 public Map<String, Content> getJingleContents() {
101 ImmutableMap.Builder<String, Content> builder = new ImmutableMap.Builder<>();
102 for (final Element child : this.getChildren()) {
103 if ("content".equals(child.getName())) {
104 final Content content = Content.upgrade(child);
105 builder.put(content.getContentName(), content);
106 }
107 }
108 return builder.build();
109 }
110
111 public enum Action {
112 CONTENT_ACCEPT,
113 CONTENT_ADD,
114 CONTENT_MODIFY,
115 CONTENT_REJECT,
116 CONTENT_REMOVE,
117 DESCRIPTION_INFO,
118 SECURITY_INFO,
119 SESSION_ACCEPT,
120 SESSION_INFO,
121 SESSION_INITIATE,
122 SESSION_TERMINATE,
123 TRANSPORT_ACCEPT,
124 TRANSPORT_INFO,
125 TRANSPORT_REJECT,
126 TRANSPORT_REPLACE;
127
128 public static Action of(final String value) {
129 if (Strings.isNullOrEmpty(value)) {
130 return null;
131 }
132 try {
133 return Action.valueOf(
134 CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, value));
135 } catch (final IllegalArgumentException e) {
136 return null;
137 }
138 }
139
140 @Override
141 @NonNull
142 public String toString() {
143 return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, super.toString());
144 }
145 }
146
147 public static class ReasonWrapper {
148 public final Reason reason;
149 public final String text;
150
151 public ReasonWrapper(Reason reason, String text) {
152 this.reason = reason;
153 this.text = text;
154 }
155 }
156}