ReferenceElement.java

  1. /**
  2.  *
  3.  * Copyright 2018 Paul Schaub
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.reference.element;

  18. import java.net.URI;
  19. import java.net.URISyntaxException;
  20. import java.util.ArrayList;
  21. import java.util.List;

  22. import javax.xml.namespace.QName;

  23. import org.jivesoftware.smack.packet.ExtensionElement;
  24. import org.jivesoftware.smack.packet.Stanza;
  25. import org.jivesoftware.smack.packet.XmlElement;
  26. import org.jivesoftware.smack.util.Objects;
  27. import org.jivesoftware.smack.util.XmlStringBuilder;

  28. import org.jivesoftware.smackx.reference.ReferenceManager;

  29. import org.jxmpp.jid.BareJid;

  30. public class ReferenceElement implements ExtensionElement {

  31.     public static final String ELEMENT = "reference";
  32.     public static final String NAMESPACE = ReferenceManager.NAMESPACE;
  33.     public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

  34.     public static final String ATTR_BEGIN = "begin";
  35.     public static final String ATTR_END = "end";
  36.     public static final String ATTR_TYPE = "type";
  37.     public static final String ATTR_ANCHOR = "anchor";
  38.     public static final String ATTR_URI = "uri";

  39.     public enum Type {
  40.         mention,
  41.         data
  42.     }

  43.     private final Integer begin;
  44.     private final Integer end;
  45.     private final Type type;
  46.     private final String anchor;
  47.     private final URI uri;

  48.     // Non-XEP-compliant, but needed for SIMS
  49.     private final XmlElement child;

  50.     /**
  51.      * XEP-incompliant (v0.2) constructor. This is needed for SIMS.
  52.      *
  53.      * @param begin TODO javadoc me please
  54.      * @param end TODO javadoc me please
  55.      * @param type TODO javadoc me please
  56.      * @param anchor TODO javadoc me please
  57.      * @param uri TODO javadoc me please
  58.      * @param child TODO javadoc me please
  59.      */
  60.     public ReferenceElement(Integer begin, Integer end, Type type, String anchor, URI uri, XmlElement child) {
  61.         if (begin != null && begin < 0) {
  62.             throw new IllegalArgumentException("Attribute 'begin' MUST NOT be smaller than 0.");
  63.         }
  64.         if (end != null && end < 0) {
  65.             throw new IllegalArgumentException("Attribute 'end' MUST NOT be smaller than 0.");
  66.         }
  67.         if (begin != null && end != null && begin >= end) {
  68.             throw new IllegalArgumentException("Attribute 'begin' MUST be smaller than attribute 'end'.");
  69.         }
  70.         Objects.requireNonNull(type);
  71.         // TODO: The uri attribute is not mandatory according to SIMS, but it is according to references.
  72.         /*if (uri == null) {
  73.             throw new NullPointerException("Attribute 'uri' MUST NOT be null.");
  74.         }*/
  75.         this.begin = begin;
  76.         this.end = end;
  77.         this.type = type;
  78.         this.anchor = anchor;
  79.         this.uri = uri;
  80.         this.child = child;
  81.     }

  82.     /**
  83.      * XEP-Compliant constructor.
  84.      *
  85.      * @param begin TODO javadoc me please
  86.      * @param end TODO javadoc me please
  87.      * @param type TODO javadoc me please
  88.      * @param anchor TODO javadoc me please
  89.      * @param uri TODO javadoc me please
  90.      */
  91.     public ReferenceElement(Integer begin, Integer end, Type type, String anchor, URI uri) {
  92.         this(begin, end, type, anchor, uri, null);
  93.     }

  94.     public Integer getBegin() {
  95.         return begin;
  96.     }

  97.     public Integer getEnd() {
  98.         return end;
  99.     }

  100.     public Type getType() {
  101.         return type;
  102.     }

  103.     public String getAnchor() {
  104.         return anchor;
  105.     }

  106.     public URI getUri() {
  107.         return uri;
  108.     }

  109.     /**
  110.      * Add a reference to another users bare jid to a stanza.
  111.      *
  112.      * @param stanza stanza.
  113.      * @param begin start index of the mention in the messages body.
  114.      * @param end end index of the mention in the messages body.
  115.      * @param jid referenced jid.
  116.      */
  117.     public static void addMention(Stanza stanza, int begin, int end, BareJid jid) {
  118.         URI uri;
  119.         try {
  120.             uri = new URI("xmpp:" + jid.toString());
  121.         } catch (URISyntaxException e) {
  122.             throw new AssertionError("Cannot create URI from bareJid.");
  123.         }
  124.         ReferenceElement reference = new ReferenceElement(begin, end, ReferenceElement.Type.mention, null, uri);
  125.         stanza.addExtension(reference);
  126.     }

  127.     /**
  128.      * Return a list of all reference extensions contained in a stanza.
  129.      * If there are no reference elements, return an empty list.
  130.      *
  131.      * @param stanza stanza
  132.      * @return list of all references contained in the stanza
  133.      */
  134.     public static List<ReferenceElement> getReferencesFromStanza(Stanza stanza) {
  135.         List<ReferenceElement> references = new ArrayList<>();
  136.         List<ReferenceElement> extensions = stanza.getExtensions(ReferenceElement.class);
  137.         for (ReferenceElement e : extensions) {
  138.             references.add(e);
  139.         }
  140.         return references;
  141.     }

  142.     /**
  143.      * Return true, if the stanza contains at least one reference extension.
  144.      *
  145.      * @param stanza stanza
  146.      * @return true if stanza contains references
  147.      */
  148.     public static boolean containsReferences(Stanza stanza) {
  149.         return getReferencesFromStanza(stanza).size() > 0;
  150.     }

  151.     @Override
  152.     public String getNamespace() {
  153.         return QNAME.getNamespaceURI();
  154.     }

  155.     @Override
  156.     public String getElementName() {
  157.         return QNAME.getLocalPart();
  158.     }

  159.     @Override
  160.     public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
  161.         XmlStringBuilder xml = new XmlStringBuilder(this)
  162.                 .optIntAttribute(ATTR_BEGIN, begin != null ? begin : -1)
  163.                 .optIntAttribute(ATTR_END, end != null ? end : -1)
  164.                 .attribute(ATTR_TYPE, type.toString())
  165.                 .optAttribute(ATTR_ANCHOR, anchor)
  166.                 .optAttribute(ATTR_URI, uri != null ? uri.toString() : null);

  167.         if (child == null) {
  168.             return xml.closeEmptyElement();
  169.         } else {
  170.             return xml.rightAngleBracket()
  171.                     .append(child.toXML())
  172.                     .closeElement(this);
  173.         }
  174.     }
  175. }