001/**
002 *
003 * Copyright © 2014-2017 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jxmpp.jid.impl;
018
019import org.jxmpp.jid.EntityBareJid;
020import org.jxmpp.jid.DomainBareJid;
021import org.jxmpp.jid.DomainFullJid;
022import org.jxmpp.jid.EntityFullJid;
023import org.jxmpp.jid.Jid;
024import org.jxmpp.jid.EntityJid;
025import org.jxmpp.jid.FullJid;
026import org.jxmpp.jid.parts.Localpart;
027import org.jxmpp.jid.parts.Resourcepart;
028
029public abstract class AbstractJid implements Jid {
030
031        /**
032         *
033         */
034        private static final long serialVersionUID = 1L;
035
036        /**
037         * Cache for the String representation of this JID.
038         */
039        protected String cache;
040
041        @Override
042        public final boolean isEntityJid() {
043                return isEntityBareJid() || isEntityFullJid();
044        }
045
046        @Override
047        public final boolean isEntityBareJid() {
048                return this instanceof EntityBareJid;
049        }
050
051        @Override
052        public final boolean isEntityFullJid() {
053                return this instanceof EntityFullJid;
054        }
055
056        @Override
057        public final boolean isDomainBareJid() {
058                return this instanceof DomainBareJid;
059        }
060
061        @Override
062        public final boolean isDomainFullJid() {
063                return this instanceof DomainFullJid;
064        }
065
066        @Override
067        public abstract boolean hasNoResource();
068
069        @Override
070        public final boolean hasResource() {
071                return this instanceof FullJid;
072        }
073
074        @Override
075        public final boolean hasLocalpart() {
076                return this instanceof EntityJid;
077        }
078
079        @Override
080        public final <T extends Jid> T downcast(Class<T> jidClass) {
081                return jidClass.cast(this);
082        }
083
084        @Override
085        public int length() {
086                return toString().length();
087        }
088
089        @Override
090        public char charAt(int index) {
091                return toString().charAt(index);
092        }
093
094        @Override
095        public CharSequence subSequence(int start, int end) {
096                return toString().subSequence(start, end);
097        }
098
099        @Override
100        public final EntityBareJid asEntityBareJidOrThrow() {
101                EntityBareJid entityBareJid = asEntityBareJidIfPossible();
102                if (entityBareJid == null) throwIse("can not be converted to EntityBareJid");
103                return entityBareJid;
104        }
105
106        @Override
107        public EntityFullJid asEntityFullJidOrThrow() {
108                EntityFullJid entityFullJid = asEntityFullJidIfPossible();
109                if (entityFullJid == null) throwIse("can not be converted to EntityFullJid");
110                return entityFullJid;
111        }
112
113        @Override
114        public EntityJid asEntityJidOrThrow() {
115                EntityJid entityJid = asEntityJidIfPossible();
116                if (entityJid == null) throwIse("can not be converted to EntityJid");
117                return entityJid;
118        }
119
120        @Override
121        public EntityFullJid asFullJidOrThrow() {
122                EntityFullJid entityFullJid = asEntityFullJidIfPossible();
123                if (entityFullJid == null) throwIse("can not be converted to EntityBareJid");
124                return entityFullJid;
125        }
126
127        @Override
128        public DomainFullJid asDomainFullJidOrThrow() {
129                DomainFullJid domainFullJid = asDomainFullJidIfPossible();
130                if (domainFullJid == null) throwIse("can not be converted to DomainFullJid");
131                return domainFullJid;
132        }
133
134        @Override
135        public abstract Resourcepart getResourceOrNull();
136
137        @Override
138        public final Resourcepart getResourceOrEmpty() {
139                Resourcepart resourcepart = getResourceOrNull();
140                if (resourcepart == null) return Resourcepart.EMPTY;
141                return resourcepart;
142        }
143
144        @Override
145        public final Resourcepart getResourceOrThrow() {
146                Resourcepart resourcepart = getResourceOrNull();
147                if (resourcepart == null) throwIse("has no resourcepart");
148                return resourcepart;
149        }
150
151        @Override
152        public abstract Localpart getLocalpartOrNull();
153
154        @Override
155        public final Localpart getLocalpartOrThrow() {
156                Localpart localpart = getLocalpartOrNull();
157                if (localpart == null) throwIse("has no localpart");
158                return localpart;
159        }
160
161        @Override
162        public final boolean isParentOf(Jid jid) {
163                EntityFullJid fullJid = jid.asEntityFullJidIfPossible();
164                if (fullJid != null) {
165                        return isParentOf(fullJid);
166                }
167                EntityBareJid bareJid = jid.asEntityBareJidIfPossible();
168                if (bareJid != null) {
169                        return isParentOf(bareJid);
170                }
171                DomainFullJid domainFullJid = jid.asDomainFullJidIfPossible();
172                if (domainFullJid != null) {
173                        return isParentOf(domainFullJid);
174                }
175
176                return isParentOf(jid.asDomainBareJid());
177        }
178
179        @Override
180        public final int hashCode() {
181                return toString().hashCode();
182        }
183
184        @Override
185        public final boolean equals(Object other) {
186                if (other == null) {
187                        return false;
188                }
189                if (this == other) {
190                        return true;
191                }
192                if (other instanceof CharSequence) {
193                        return equals((CharSequence) other);
194                }
195                return false;
196        }
197
198        @SuppressWarnings("NonOverridingEquals")
199        @Override
200        public final boolean equals(CharSequence charSequence) {
201                if (charSequence == null) {
202                        return false;
203                }
204                return equals(charSequence.toString());
205        }
206
207        @SuppressWarnings("NonOverridingEquals")
208        @Override
209        public final boolean equals(String string) {
210                return toString().equals(string);
211        }
212
213        @Override
214        public final int compareTo(Jid  other) {
215                String otherString = other.toString();
216                String myString = toString();
217                return myString.compareTo(otherString);
218        }
219
220        /**
221         * The cache holding the internalized value of this part. This needs to be transient so that the
222         * cache is recreated once the data was de-serialized.
223         */
224        private transient String internalizedCache;
225
226        @Override
227        public final String intern() {
228                if (internalizedCache == null) {
229                        cache = internalizedCache = toString().intern();
230                }
231                return internalizedCache;
232        }
233
234        private void throwIse(String message) {
235                String exceptionMessage = "The JID '" + this + "' " + message;
236                throw new IllegalStateException(exceptionMessage);
237        }
238
239        static <O extends Object> O requireNonNull(O object, String message) {
240                if (object != null) {
241                        return object;
242                }
243                throw new IllegalArgumentException(message);
244        }
245}