Jid.java

  1/*
  2 * The MIT License (MIT)
  3 *
  4 * Copyright (c) 2014-2017 Christian Schudt
  5 *
  6 * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 * of this software and associated documentation files (the "Software"), to deal
  8 * in the Software without restriction, including without limitation the rights
  9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10 * copies of the Software, and to permit persons to whom the Software is
 11 * furnished to do so, subject to the following conditions:
 12 *
 13 * The above copyright notice and this permission notice shall be included in
 14 * all copies or substantial portions of the Software.
 15 *
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22 * THE SOFTWARE.
 23 */
 24
 25package rocks.xmpp.addr;
 26
 27import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 28import java.io.Serializable;
 29
 30/**
 31 * Represents the JID as described in <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>.
 32 * <p>
 33 * A JID consists of three parts:
 34 * <p>
 35 * [ localpart "@" ] domainpart [ "/" resourcepart ]
 36 * </p>
 37 * The easiest way to create a JID is to use the {@link #of(CharSequence)} method:
 38 * ```java
 39 * Jid jid = Jid.of("juliet@capulet.lit/balcony");
 40 * ```
 41 * You can then get the parts from it via the respective methods:
 42 * ```java
 43 * String local = jid.getLocal(); // juliet
 44 * String domain = jid.getDomain(); // capulet.lit
 45 * String resource = jid.getResource(); // balcony
 46 * ```
 47 * Implementations of this interface should override <code>equals()</code> and <code>hashCode()</code>, so that different instances with the same value are equal:
 48 * ```java
 49 * Jid.of("romeo@capulet.lit/balcony").equals(Jid.of("romeo@capulet.lit/balcony")); // true
 50 * ```
 51 * The default implementation of this class also supports <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>, i.e.
 52 * ```java
 53 * Jid.of("d'artagnan@musketeers.lit")
 54 * ```
 55 * is escaped as <code>d\\27artagnan@musketeers.lit</code>.
 56 * <p>
 57 * Implementations of this interface should be thread-safe and immutable.
 58 *
 59 * @author Christian Schudt
 60 * @see <a href="https://tools.ietf.org/html/rfc7622">RFC 7622 - Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
 61 */
 62@XmlJavaTypeAdapter(JidAdapter.class)
 63public interface Jid extends Comparable<Jid>, Serializable, CharSequence {
 64
 65    /**
 66     * The maximal length of a full JID, which is 3071.
 67     * <blockquote>
 68     * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.1">3.1.  Fundamentals</a></cite></p>
 69     * <p>Each allowable portion of a JID (localpart, domainpart, and
 70     * resourcepart) is 1 to 1023 octets in length, resulting in a maximum
 71     * total size (including the '@' and '/' separators) of 3071 octets.
 72     * </p>
 73     * </blockquote>
 74     * Note that the length is based on bytes, not characters.
 75     *
 76     * @see #MAX_BARE_JID_LENGTH
 77     */
 78    int MAX_FULL_JID_LENGTH = 3071;
 79
 80    /**
 81     * The maximal length of a bare JID, which is 2047 (1023 + 1 + 1023).
 82     * Note that the length is based on bytes, not characters.
 83     *
 84     * @see #MAX_FULL_JID_LENGTH
 85     */
 86    int MAX_BARE_JID_LENGTH = 2047;
 87
 88    /**
 89     * The service discovery feature used for determining support of JID escaping (<code>jid\20escaping</code>).
 90     */
 91    String ESCAPING_FEATURE = "jid\\20escaping";
 92
 93    /**
 94     * Returns a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
 95     *
 96     * @param local    The local part.
 97     * @param domain   The domain.
 98     * @param resource The resource part.
 99     * @return The JID.
100     * @throws NullPointerException     If the domain is null.
101     * @throws IllegalArgumentException If the domain, local or resource part are not valid.
102     */
103    static Jid of(CharSequence local, CharSequence domain, CharSequence resource) {
104        return new FullJid(local, domain, resource);
105    }
106
107    /**
108     * Creates a bare JID with only the domain part, e.g. <code>capulet.com</code>
109     *
110     * @param domain The domain.
111     * @return The JID.
112     * @throws NullPointerException     If the domain is null.
113     * @throws IllegalArgumentException If the domain or local part are not valid.
114     */
115    static Jid ofDomain(CharSequence domain) {
116        return new FullJid(null, domain, null);
117    }
118
119    /**
120     * Creates a bare JID with a local and domain part, e.g. <code>juliet@capulet.com</code>
121     *
122     * @param local  The local part.
123     * @param domain The domain.
124     * @return The JID.
125     * @throws NullPointerException     If the domain is null.
126     * @throws IllegalArgumentException If the domain or local part are not valid.
127     */
128    static Jid ofLocalAndDomain(CharSequence local, CharSequence domain) {
129        return new FullJid(local, domain, null);
130    }
131
132    /**
133     * Creates a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
134     *
135     * @param domain   The domain.
136     * @param resource The resource part.
137     * @return The JID.
138     * @throws NullPointerException     If the domain is null.
139     * @throws IllegalArgumentException If the domain or resource are not valid.
140     */
141    static Jid ofDomainAndResource(CharSequence domain, CharSequence resource) {
142        return new FullJid(null, domain, resource);
143    }
144
145    /**
146     * Creates a JID from an unescaped string. The format must be
147     * <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
148     * The input string will be escaped.
149     *
150     * @param jid The JID.
151     * @return The JID.
152     * @throws NullPointerException     If the jid is null.
153     * @throws IllegalArgumentException If the jid could not be parsed or is not valid.
154     * @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
155     */
156    static Jid of(CharSequence jid) {
157        if (jid instanceof Jid) {
158            return (Jid) jid;
159        }
160        return FullJid.of(jid.toString(), false);
161    }
162
163    /**
164     * Creates a JID from a escaped JID string. The format must be
165     * <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
166     * This method should be used, when parsing JIDs from the XMPP stream.
167     *
168     * @param jid The JID.
169     * @return The JID.
170     * @throws NullPointerException     If the jid is null.
171     * @throws IllegalArgumentException If the jid could not be parsed or is not valid.
172     * @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
173     */
174    static Jid ofEscaped(CharSequence jid) {
175        return FullJid.of(jid.toString(), true);
176    }
177
178    /**
179     * Checks if the JID is a full JID.
180     * <blockquote>
181     * <p>The term "full JID" refers to an XMPP address of the form &lt;localpart@domainpart/resourcepart&gt; (for a particular authorized client or device associated with an account) or of the form &lt;domainpart/resourcepart&gt; (for a particular resource or script associated with a server).</p>
182     * </blockquote>
183     *
184     * @return True, if the JID is a full JID; otherwise false.
185     */
186    boolean isFullJid();
187
188    /**
189     * Checks if the JID is a bare JID.
190     * <blockquote>
191     * <p>The term "bare JID" refers to an XMPP address of the form &lt;localpart@domainpart&gt; (for an account at a server) or of the form &lt;domainpart&gt; (for a server).</p>
192     * </blockquote>
193     *
194     * @return True, if the JID is a bare JID; otherwise false.
195     */
196    boolean isBareJid();
197
198    /**
199     * Checks if the JID is a domain JID, i.e. if it has no local part.
200     *
201     * @return True, if the JID is a domain JID, i.e. if it has no local part.
202     */
203    boolean isDomainJid();
204
205    /**
206     * Gets the bare JID representation of this JID, i.e. removes the resource part.
207     * <blockquote>
208     * <p>The term "bare JID" refers to an XMPP address of the form &lt;localpart@domainpart&gt; (for an account at a server) or of the form &lt;domainpart&gt; (for a server).</p>
209     * </blockquote>
210     *
211     * @return The bare JID.
212     * @see #withResource(CharSequence)
213     */
214    Jid asBareJid();
215
216    /**
217     * Creates a new JID with a new local part and the same domain and resource part of the current JID.
218     *
219     * @param local The local part.
220     * @return The JID with a new local part.
221     * @throws IllegalArgumentException If the local is not a valid local part.
222     * @see #withResource(CharSequence)
223     */
224    Jid withLocal(CharSequence local);
225
226    /**
227     * Creates a new full JID with a resource and the same local and domain part of the current JID.
228     *
229     * @param resource The resource.
230     * @return The full JID with a resource.
231     * @throws IllegalArgumentException If the resource is not a valid resource part.
232     * @see #asBareJid()
233     * @see #withLocal(CharSequence)
234     */
235    Jid withResource(CharSequence resource);
236
237    /**
238     * Creates a new JID at a subdomain and at the same domain as this JID.
239     *
240     * @param subdomain The subdomain.
241     * @return The JID at a subdomain.
242     * @throws NullPointerException     If subdomain is null.
243     * @throws IllegalArgumentException If subdomain is not a valid subdomain name.
244     */
245    Jid atSubdomain(CharSequence subdomain);
246
247    /**
248     * Gets the local part of the JID, also known as the name or node.
249     * <blockquote>
250     * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.3">3.3.  Localpart</a></cite></p>
251     * <p>The localpart of a JID is an optional identifier placed before the
252     * domainpart and separated from the latter by the '@' character.
253     * Typically, a localpart uniquely identifies the entity requesting and
254     * using network access provided by a server (i.e., a local account),
255     * although it can also represent other kinds of entities (e.g., a
256     * chatroom associated with a multi-user chat service [XEP-0045]).  The
257     * entity represented by an XMPP localpart is addressed within the
258     * context of a specific domain (i.e., &lt;localpart@domainpart&gt;).</p>
259     * </blockquote>
260     *
261     * @return The local part or null.
262     * @see #getEscapedLocal()
263     */
264    String getLocal();
265
266    /**
267     * Gets the escaped local part of the JID.
268     *
269     * @return The escaped local part or null.
270     * @see #getLocal()
271     * @since 0.8.0
272     */
273    String getEscapedLocal();
274
275    /**
276     * Gets the domain part.
277     * <blockquote>
278     * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.2">3.2.  Domainpart</a></cite></p>
279     * <p>The domainpart is the primary identifier and is the only REQUIRED
280     * element of a JID (a mere domainpart is a valid JID).  Typically,
281     * a domainpart identifies the "home" server to which clients connect
282     * for XML routing and data management functionality.</p>
283     * </blockquote>
284     *
285     * @return The domain part.
286     */
287    String getDomain();
288
289    /**
290     * Gets the resource part.
291     * <blockquote>
292     * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.4">3.4.  Resourcepart</a></cite></p>
293     * <p>The resourcepart of a JID is an optional identifier placed after the
294     * domainpart and separated from the latter by the '/' character.  A
295     * resourcepart can modify either a &lt;localpart@domainpart&gt; address or a
296     * mere &lt;domainpart&gt; address.  Typically, a resourcepart uniquely
297     * identifies a specific connection (e.g., a device or location) or
298     * object (e.g., an occupant in a multi-user chatroom [XEP-0045])
299     * belonging to the entity associated with an XMPP localpart at a domain
300     * (i.e., &lt;localpart@domainpart/resourcepart&gt;).</p>
301     * </blockquote>
302     *
303     * @return The resource part or null.
304     */
305    String getResource();
306
307    /**
308     * Returns the JID in escaped form as described in <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>.
309     *
310     * @return The escaped JID.
311     * @see #toString()
312     */
313    String toEscapedString();
314}