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