001/**
002 *
003 * Copyright 2015-2016 Ishan Khanna
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.jivesoftware.smackx.geoloc.packet;
018
019import java.io.Serializable;
020import java.net.URI;
021import java.util.Date;
022import java.util.logging.Level;
023import java.util.logging.Logger;
024
025import org.jivesoftware.smack.packet.ExtensionElement;
026import org.jivesoftware.smack.packet.Message;
027import org.jivesoftware.smack.util.StringUtils;
028import org.jivesoftware.smack.util.XmlStringBuilder;
029
030/**
031 * A GeoLocation Extension packet, which is used by the XMPP clients to exchange their respective geographic locations.
032 * 
033 * @see <a href="http://www.xmpp.org/extensions/xep-0080.html">XEP-0080</a>
034 * @author Ishan Khanna
035 */
036public final class GeoLocation implements Serializable, ExtensionElement {
037
038    private static final long serialVersionUID = 1L;
039    public static final String NAMESPACE = "http://jabber.org/protocol/geoloc";
040    public static final String ELEMENT = "geoloc";
041
042    private static final Logger LOGGER = Logger.getLogger(GeoLocation.class.getName());
043
044    private final Double accuracy;
045    private final Double alt;
046    private final String area;
047    private final Double bearing;
048    private final String building;
049    private final String country;
050    private final String countryCode;
051    private final String datum;
052    private final String description;
053    private final Double error;
054    private final String floor;
055    private final Double lat;
056    private final String locality;
057    private final Double lon;
058    private final String postalcode;
059    private final String region;
060    private final String room;
061    private final Double speed;
062    private final String street;
063    private final String text;
064    private final Date timestamp;
065    private final String tzo;
066    private final URI uri;
067
068    private GeoLocation(Double accuracy, Double alt, String area, Double bearing, String building, String country,
069                    String countryCode, String datum, String description, Double error, String floor, Double lat,
070                    String locality, Double lon, String postalcode, String region, String room, Double speed,
071                    String street, String text, Date timestamp, String tzo, URI uri) {
072        this.accuracy = accuracy;
073        this.alt = alt;
074        this.area = area;
075        this.bearing = bearing;
076        this.building = building;
077        this.country = country;
078        this.countryCode = countryCode;
079
080        // If datum is not included, receiver MUST assume WGS84; receivers MUST implement WGS84; senders MAY use another
081        // datum, but it is not recommended.
082
083        if (StringUtils.isNullOrEmpty(datum)) {
084            datum = "WGS84";
085        }
086
087        this.datum = datum;
088        this.description = description;
089
090        // error element is deprecated in favor of accuracy
091        if (accuracy != null) {
092            error = null;
093            LOGGER.log(Level.WARNING,
094                            "Error and accuracy set. Ignoring error as it is deprecated in favor of accuracy");
095        }
096
097        this.error = error;
098        this.floor = floor;
099        this.lat = lat;
100        this.locality = locality;
101        this.lon = lon;
102        this.postalcode = postalcode;
103        this.region = region;
104        this.room = room;
105        this.speed = speed;
106        this.street = street;
107        this.text = text;
108        this.timestamp = timestamp;
109        this.tzo = tzo;
110        this.uri = uri;
111    }
112
113    public Double getAccuracy() {
114        return accuracy;
115    }
116
117    public Double getAlt() {
118        return alt;
119    }
120
121    public String getArea() {
122        return area;
123    }
124
125    public Double getBearing() {
126        return bearing;
127    }
128
129    public String getBuilding() {
130        return building;
131    }
132
133    public String getCountry() {
134        return country;
135    }
136
137    public String getCountryCode() {
138        return countryCode;
139    }
140
141    public String getDatum() {
142        return datum;
143    }
144
145    public String getDescription() {
146        return description;
147    }
148
149    public Double getError() {
150        return error;
151    }
152
153    public String getFloor() {
154        return floor;
155    }
156
157    public Double getLat() {
158        return lat;
159    }
160
161    public String getLocality() {
162        return locality;
163    }
164
165    public Double getLon() {
166        return lon;
167    }
168
169    public String getPostalcode() {
170        return postalcode;
171    }
172
173    public String getRegion() {
174        return region;
175    }
176
177    public String getRoom() {
178        return room;
179    }
180
181    public Double getSpeed() {
182        return speed;
183    }
184
185    public String getStreet() {
186        return street;
187    }
188
189    public String getText() {
190        return text;
191    }
192
193    public Date getTimestamp() {
194        return timestamp;
195    }
196
197    public String getTzo() {
198        return tzo;
199    }
200
201    public URI getUri() {
202        return uri;
203    }
204
205    @Override
206    public String getElementName() {
207        return ELEMENT;
208    }
209
210    @Override
211    public CharSequence toXML() {
212        XmlStringBuilder xml = new XmlStringBuilder(this);
213        xml.rightAngleBracket();
214        xml.optElement("accuracy", accuracy);
215        xml.optElement("alt", alt);
216        xml.optElement("area", area);
217        xml.optElement("bearing", bearing);
218        xml.optElement("building", building);
219        xml.optElement("country", country);
220        xml.optElement("countrycode", countryCode);
221        xml.optElement("datum", datum);
222        xml.optElement("description", description);
223        xml.optElement("error", error);
224        xml.optElement("floor", floor);
225        xml.optElement("lat", lat);
226        xml.optElement("locality", locality);
227        xml.optElement("lon", lon);
228        xml.optElement("postalcode", postalcode);
229        xml.optElement("region", region);
230        xml.optElement("room", room);
231        xml.optElement("speed", speed);
232        xml.optElement("street", street);
233        xml.optElement("text", text);
234        xml.optElement("timestamp", timestamp);
235        xml.optElement("tzo", tzo);
236        xml.optElement("uri", uri);
237        xml.closeElement(this);
238        return xml;
239    }
240
241    @Override
242    public String getNamespace() {
243        return NAMESPACE;
244    }
245
246    public static Builder builder() {
247        return new GeoLocation.Builder();
248    }
249
250    public static GeoLocation from(Message message) {
251        return message.getExtension(ELEMENT, NAMESPACE);
252    }
253
254    public static class Builder {
255
256        private Double accuracy;
257        private Double alt;
258        private String area;
259        private Double bearing;
260        private String building;
261        private String country;
262        private String countryCode;
263        private String datum;
264        private String description;
265        private Double error;
266        private String floor;
267        private Double lat;
268        private String locality;
269        private Double lon;
270        private String postalcode;
271        private String region;
272        private String room;
273        private Double speed;
274        private String street;
275        private String text;
276        private Date timestamp;
277        private String tzo;
278        private URI uri;
279
280        public Builder setAccuracy(Double accuracy) {
281            this.accuracy = accuracy;
282            return this;
283        }
284
285        public Builder setAlt(Double alt) {
286            this.alt = alt;
287            return this;
288        }
289
290        public Builder setArea(String area) {
291            this.area = area;
292            return this;
293        }
294
295        public Builder setBearing(Double bearing) {
296            this.bearing = bearing;
297            return this;
298        }
299
300        public Builder setBuilding(String building) {
301            this.building = building;
302            return this;
303        }
304
305        public Builder setCountry(String country) {
306            this.country = country;
307            return this;
308        }
309
310        public Builder setCountryCode(String countryCode) {
311            this.countryCode = countryCode;
312            return this;
313        }
314
315        public Builder setDatum(String datum) {
316            this.datum = datum;
317            return this;
318        }
319
320        public Builder setDescription(String description) {
321            this.description = description;
322            return this;
323        }
324
325        public Builder setError(Double error) {
326            this.error = error;
327            return this;
328        }
329
330        public Builder setFloor(String floor) {
331            this.floor = floor;
332            return this;
333        }
334
335        public Builder setLat(Double lat) {
336            this.lat = lat;
337            return this;
338        }
339
340        public Builder setLocality(String locality) {
341            this.locality = locality;
342            return this;
343        }
344
345        public Builder setLon(Double lon) {
346            this.lon = lon;
347            return this;
348        }
349
350        public Builder setPostalcode(String postalcode) {
351            this.postalcode = postalcode;
352            return this;
353        }
354
355        public Builder setRegion(String region) {
356            this.region = region;
357            return this;
358        }
359
360        public Builder setRoom(String room) {
361            this.room = room;
362            return this;
363        }
364
365        public Builder setSpeed(Double speed) {
366            this.speed = speed;
367            return this;
368        }
369
370        public Builder setStreet(String street) {
371            this.street = street;
372            return this;
373        }
374
375        public Builder setText(String text) {
376            this.text = text;
377            return this;
378        }
379
380        public Builder setTimestamp(Date timestamp) {
381            this.timestamp = timestamp;
382            return this;
383        }
384
385        public Builder setTzo(String tzo) {
386            this.tzo = tzo;
387            return this;
388        }
389
390        public Builder setUri(URI uri) {
391            this.uri = uri;
392            return this;
393        }
394
395        public GeoLocation build() {
396
397            return new GeoLocation(accuracy, alt, area, bearing, building, country, countryCode, datum, description,
398                            error, floor, lat, locality, lon, postalcode, region, room, speed, street, text, timestamp,
399                            tzo, uri);
400        }
401
402    }
403
404}