JinglePacket.java

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