GeoLocation.java

  1. /**
  2.  *
  3.  * Copyright 2015-2017 Ishan Khanna, Fernando Ramirez, 2019-2020 Florian Schmaus
  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.geoloc.packet;

  18. import java.io.Serializable;
  19. import java.net.URI;
  20. import java.util.Date;

  21. import javax.xml.namespace.QName;

  22. import org.jivesoftware.smack.packet.ExtensionElement;
  23. import org.jivesoftware.smack.packet.Message;
  24. import org.jivesoftware.smack.util.EqualsUtil;
  25. import org.jivesoftware.smack.util.HashCode;
  26. import org.jivesoftware.smack.util.XmlStringBuilder;

  27. import org.jivesoftware.smackx.xdata.FormField;
  28. import org.jivesoftware.smackx.xdata.FormFieldChildElement;

  29. /**
  30.  * A GeoLocation Extension packet, which is used by the XMPP clients to exchange their respective geographic locations.
  31.  *
  32.  * @see <a href="http://www.xmpp.org/extensions/xep-0080.html">XEP-0080</a>
  33.  * @author Ishan Khanna
  34.  */
  35. public final class GeoLocation implements Serializable, ExtensionElement, FormFieldChildElement {

  36.     private static final long serialVersionUID = 1L;

  37.     public static final String NAMESPACE = "http://jabber.org/protocol/geoloc";

  38.     public static final String ELEMENT = "geoloc";

  39.     public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

  40.     public static final GeoLocation EMPTY_GEO_LOCATION = GeoLocation.builder().build();

  41.     private final Double accuracy;
  42.     private final Double alt;
  43.     private final Double altAccuracy;
  44.     private final String area;
  45.     private final Double bearing;
  46.     private final String building;
  47.     private final String country;
  48.     private final String countryCode;
  49.     private final String datum;
  50.     private final String description;
  51.     private final Double error;
  52.     private final String floor;
  53.     private final Double lat;
  54.     private final String locality;
  55.     private final Double lon;
  56.     private final String postalcode;
  57.     private final String region;
  58.     private final String room;
  59.     private final Double speed;
  60.     private final String street;
  61.     private final String text;
  62.     private final Date timestamp;
  63.     private final String tzo;
  64.     private final URI uri;

  65.     private GeoLocation(Builder builder) {
  66.         accuracy = builder.accuracy;
  67.         alt = builder.alt;
  68.         altAccuracy = builder.altAccuracy;
  69.         area = builder.area;
  70.         bearing = builder.bearing;
  71.         building = builder.building;
  72.         country = builder.country;
  73.         countryCode = builder.countryCode;
  74.         datum = builder.datum;
  75.         description = builder.description;
  76.         error = builder.error;
  77.         floor = builder.floor;
  78.         lat = builder.lat;
  79.         locality = builder.locality;
  80.         lon = builder.lon;
  81.         postalcode = builder.postalcode;
  82.         region = builder.region;
  83.         room = builder.room;
  84.         speed = builder.speed;
  85.         street = builder.street;
  86.         text = builder.text;
  87.         timestamp = builder.timestamp;
  88.         tzo = builder.tzo;
  89.         uri = builder.uri;
  90.     }

  91.     public Double getAccuracy() {
  92.         return accuracy;
  93.     }

  94.     public Double getAlt() {
  95.         return alt;
  96.     }

  97.     public Double getAltAccuracy() {
  98.         return altAccuracy;
  99.     }

  100.     public String getArea() {
  101.         return area;
  102.     }

  103.     public Double getBearing() {
  104.         return bearing;
  105.     }

  106.     public String getBuilding() {
  107.         return building;
  108.     }

  109.     public String getCountry() {
  110.         return country;
  111.     }

  112.     public String getCountryCode() {
  113.         return countryCode;
  114.     }

  115.     public String getDatum() {
  116.         return datum;
  117.     }

  118.     public String getDescription() {
  119.         return description;
  120.     }

  121.     /**
  122.      * Get the error.
  123.      *
  124.      * @return the error.
  125.      * @deprecated use {@link #getAccuracy()} instead.
  126.      */
  127.     @Deprecated
  128.     public Double getError() {
  129.         return error;
  130.     }

  131.     public String getFloor() {
  132.         return floor;
  133.     }

  134.     public Double getLat() {
  135.         return lat;
  136.     }

  137.     public String getLocality() {
  138.         return locality;
  139.     }

  140.     public Double getLon() {
  141.         return lon;
  142.     }

  143.     public String getPostalcode() {
  144.         return postalcode;
  145.     }

  146.     public String getRegion() {
  147.         return region;
  148.     }

  149.     public String getRoom() {
  150.         return room;
  151.     }

  152.     public Double getSpeed() {
  153.         return speed;
  154.     }

  155.     public String getStreet() {
  156.         return street;
  157.     }

  158.     public String getText() {
  159.         return text;
  160.     }

  161.     public Date getTimestamp() {
  162.         return timestamp;
  163.     }

  164.     public String getTzo() {
  165.         return tzo;
  166.     }

  167.     public URI getUri() {
  168.         return uri;
  169.     }

  170.     @Override
  171.     public QName getQName() {
  172.         return QNAME;
  173.     }

  174.     @Override
  175.     public String getElementName() {
  176.         return ELEMENT;
  177.     }

  178.     @Override
  179.     public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
  180.         XmlStringBuilder xml = new XmlStringBuilder(this);
  181.         xml.rightAngleBracket();
  182.         xml.optElement("accuracy", accuracy);
  183.         xml.optElement("alt", alt);
  184.         xml.optElement("altaccuracy", altAccuracy);
  185.         xml.optElement("area", area);
  186.         xml.optElement("bearing", bearing);
  187.         xml.optElement("building", building);
  188.         xml.optElement("country", country);
  189.         xml.optElement("countrycode", countryCode);
  190.         xml.optElement("datum", datum);
  191.         xml.optElement("description", description);
  192.         xml.optElement("error", error);
  193.         xml.optElement("floor", floor);
  194.         xml.optElement("lat", lat);
  195.         xml.optElement("locality", locality);
  196.         xml.optElement("lon", lon);
  197.         xml.optElement("postalcode", postalcode);
  198.         xml.optElement("region", region);
  199.         xml.optElement("room", room);
  200.         xml.optElement("speed", speed);
  201.         xml.optElement("street", street);
  202.         xml.optElement("text", text);
  203.         xml.optElement("timestamp", timestamp);
  204.         xml.optElement("tzo", tzo);
  205.         xml.optElement("uri", uri);
  206.         xml.closeElement(this);
  207.         return xml;
  208.     }

  209.     @Override
  210.     public String getNamespace() {
  211.         return NAMESPACE;
  212.     }

  213.     private final HashCode.Cache hashCodeCache = new HashCode.Cache();

  214.     @Override
  215.     public int hashCode() {
  216.         return hashCodeCache.getHashCode(c ->
  217.             c
  218.             .append(accuracy)
  219.             .append(alt)
  220.             .append(altAccuracy)
  221.             .append(area)
  222.             .append(bearing)
  223.             .append(building)
  224.             .append(country)
  225.             .append(countryCode)
  226.             .append(datum)
  227.             .append(description)
  228.             .append(error)
  229.             .append(floor)
  230.             .append(lat)
  231.             .append(locality)
  232.             .append(lon)
  233.             .append(postalcode)
  234.             .append(region)
  235.             .append(room)
  236.             .append(speed)
  237.             .append(street)
  238.             .append(text)
  239.             .append(timestamp)
  240.             .append(tzo)
  241.             .append(uri)
  242.         );
  243.     }

  244.     @Override
  245.     public boolean equals(Object obj) {
  246.         return EqualsUtil.equals(this, obj, (e, o) -> {
  247.             e
  248.             .append(accuracy, o.accuracy)
  249.             .append(altAccuracy, o.altAccuracy)
  250.             .append(area, o.area)
  251.             .append(bearing, o.bearing)
  252.             .append(building, o.building)
  253.             .append(country, o.country)
  254.             .append(countryCode, o.countryCode)
  255.             .append(datum, o.datum)
  256.             .append(description, o.description)
  257.             .append(error, o.error)
  258.             .append(floor, o.floor)
  259.             .append(lat, o.lat)
  260.             .append(locality, o.locality)
  261.             .append(lon, o.lon)
  262.             .append(postalcode, o.postalcode)
  263.             .append(region, o.region)
  264.             .append(room, o.room)
  265.             .append(speed, o.speed)
  266.             .append(street, o.street)
  267.             .append(text, o.text)
  268.             .append(timestamp, o.timestamp)
  269.             .append(tzo, o.tzo)
  270.             .append(uri, o.uri)
  271.             ;
  272.         });
  273.     }

  274.     /**
  275.      * Returns a new instance of {@link Builder}.
  276.      * @return Builder
  277.      */
  278.     public static Builder builder() {
  279.         return new GeoLocation.Builder();
  280.     }

  281.     @Override
  282.     public boolean isExclusiveElement() {
  283.         return true;
  284.     }

  285.     /**
  286.      * Returns the first GeoLocation, or <code>null</code> if it doesn't exist in {@link Message}.
  287.      * <br>
  288.      * @param message The Message stanza containing GeoLocation
  289.      * @return GeoLocation
  290.      */
  291.     public static GeoLocation from(Message message) {
  292.         return message.getExtension(GeoLocation.class);
  293.     }

  294.     /**
  295.      * Returns the first GeoLocation, or <code>null</code> if it doesn't exist in {@link FormField}.
  296.      * <br>
  297.      * @param formField the Formfield containing GeoLocation
  298.      * @return GeoLocation
  299.      */
  300.     public static GeoLocation from(FormField formField) {
  301.         return (GeoLocation) formField.getFormFieldChildElement(QNAME);
  302.     }

  303.     /**
  304.      * This class defines a builder class for {@link GeoLocation}.
  305.      * <br>
  306.      * {@link GeoLocation} instance can be obtained using {@link #build()} method as follows.<br><br>
  307.      * <code>GeoLocation.Builder builder = GeoLocation.builder(); <br>
  308.      *       GeoLocation geoLocation = builder.build();</code>
  309.      *  <br><br>
  310.      *  To set GeoLocation parameters, use their respective setters.
  311.      */
  312.     public static final class Builder {

  313.         private Double accuracy;
  314.         private Double alt;
  315.         private Double altAccuracy;
  316.         private String area;
  317.         private Double bearing;
  318.         private String building;
  319.         private String country;
  320.         private String countryCode;

  321.         // If datum is not included, receiver MUST assume WGS84; receivers MUST implement WGS84; senders MAY use another
  322.         // datum, but it is not recommended.
  323.         private String datum = "WGS84";

  324.         private String description;
  325.         private Double error;
  326.         private String floor;
  327.         private Double lat;
  328.         private String locality;
  329.         private Double lon;
  330.         private String postalcode;
  331.         private String region;
  332.         private String room;
  333.         private Double speed;
  334.         private String street;
  335.         private String text;
  336.         private Date timestamp;
  337.         private String tzo;
  338.         private URI uri;

  339.         /**
  340.          * Deprecated, do not use.
  341.          * @deprecated use {@link GeoLocation#builder()} instead.
  342.          */
  343.         @Deprecated
  344.         // TODO Make constructor private in Smack 4.6.
  345.         public Builder() {
  346.         }

  347.         /**
  348.          * Sets accuracy of horizontal GPS error in meters.
  349.          *
  350.          * @param accuracy accuracy in meters
  351.          * @return Builder
  352.          */
  353.         public Builder setAccuracy(Double accuracy) {
  354.             this.accuracy = accuracy;
  355.             return this;
  356.         }

  357.         /**
  358.          * Sets Altitude in meters above or below sea level.
  359.          *
  360.          * @param alt altitude in meters
  361.          * @return Builder
  362.          */
  363.         public Builder setAlt(Double alt) {
  364.             this.alt = alt;
  365.             return this;
  366.         }

  367.         /**
  368.          * Sets Vertical GPS error in meters.
  369.          *
  370.          * @param altAccuracy altAccuracy in meters
  371.          * @return Builder
  372.          */
  373.         public Builder setAltAccuracy(Double altAccuracy) {
  374.             this.altAccuracy = altAccuracy;
  375.             return this;
  376.         }

  377.         /**
  378.          * Sets a named area such as a campus or neighborhood.
  379.          *
  380.          * @param area the named area
  381.          * @return Builder
  382.          */
  383.         public Builder setArea(String area) {
  384.             this.area = area;
  385.             return this;
  386.         }

  387.         /**
  388.          * Sets GPS bearing (direction in which the entity is heading<br>
  389.          * to reach its next waypoint), measured in decimal degrees,<br>
  390.          * relative to true north.
  391.          *
  392.          * @param bearing bearing in decimal degrees
  393.          * @return Builder
  394.          */
  395.         public Builder setBearing(Double bearing) {
  396.             this.bearing = bearing;
  397.             return this;
  398.         }

  399.         /**
  400.          * Sets a specific building on a street or in an area.
  401.          *
  402.          * @param building name of the building
  403.          * @return Builder
  404.          */
  405.         public Builder setBuilding(String building) {
  406.             this.building = building;
  407.             return this;
  408.         }

  409.         /**
  410.          * Sets the nation where the user is located.
  411.          *
  412.          * @param country user's country of location
  413.          * @return Builder
  414.          */
  415.         public Builder setCountry(String country) {
  416.             this.country = country;
  417.             return this;
  418.         }

  419.         /**
  420.          * Sets The ISO 3166 two-letter country code.
  421.          *
  422.          * @param countryCode two-letter country code
  423.          * @return Builder
  424.          */
  425.         public Builder setCountryCode(String countryCode) {
  426.             this.countryCode = countryCode;
  427.             return this;
  428.         }

  429.         /**
  430.          * Sets GPS Datum.
  431.          *
  432.          * @param datum GPS datum
  433.          * @return Builder
  434.          */
  435.         public Builder setDatum(String datum) {
  436.             this.datum = datum;
  437.             return this;
  438.         }

  439.         /**
  440.          * Sets A natural-language name for or description of the location.
  441.          *
  442.          * @param description description of the location
  443.          * @return Builder
  444.          */
  445.         public Builder setDescription(String description) {
  446.             this.description = description;
  447.             return this;
  448.         }

  449.         /**
  450.          * Sets Horizontal GPS error in arc minutes;<br>
  451.          * this element is deprecated in favor of accuracy.
  452.          *
  453.          * @param error error in arc minutes
  454.          * @return Builder
  455.          * @deprecated use {@link #setAccuracy(Double)} instead.
  456.          */
  457.         @Deprecated
  458.         public Builder setError(Double error) {
  459.             this.error = error;
  460.             return this;
  461.         }

  462.         /**
  463.          * Sets a particular floor in a building.
  464.          *
  465.          * @param floor floor in a building
  466.          * @return Builder
  467.          */
  468.         public Builder setFloor(String floor) {
  469.             this.floor = floor;
  470.             return this;
  471.         }

  472.         /**
  473.          * Sets Latitude in decimal degrees North.
  474.          *
  475.          * @param lat latitude in decimal degrees
  476.          * @return Builder
  477.          */
  478.         public Builder setLat(Double lat) {
  479.             this.lat = lat;
  480.             return this;
  481.         }

  482.         /**
  483.          * Sets Locality within the administrative region,<br>
  484.          * such as a town or city.
  485.          *
  486.          * @param locality locality in a region
  487.          * @return Builder
  488.          */
  489.         public Builder setLocality(String locality) {
  490.             this.locality = locality;
  491.             return this;
  492.         }

  493.         /**
  494.          * Sets Longitude in decimal degrees East.
  495.          *
  496.          * @param lon longitude in decimal degrees
  497.          * @return Builder
  498.          */
  499.         public Builder setLon(Double lon) {
  500.             this.lon = lon;
  501.             return this;
  502.         }

  503.         /**
  504.          * Sets PostalCode used for postal delivery.
  505.          *
  506.          * @param postalcode code for postal delivery
  507.          * @return Builder
  508.          */
  509.         public Builder setPostalcode(String postalcode) {
  510.             this.postalcode = postalcode;
  511.             return this;
  512.         }

  513.         /**
  514.          * Sets an administrative region of the nation,<br>
  515.          * such as a state or province.
  516.          *
  517.          * @param region an administrative region
  518.          * @return Builder
  519.          */
  520.         public Builder setRegion(String region) {
  521.             this.region = region;
  522.             return this;
  523.         }

  524.         /**
  525.          * Sets a particular room in a building.
  526.          *
  527.          * @param room room inside a building
  528.          * @return Builder
  529.          */
  530.         public Builder setRoom(String room) {
  531.             this.room = room;
  532.             return this;
  533.         }

  534.         /**
  535.          * Sets Speed at which the entity is moving, in meters per second.
  536.          *
  537.          * @param speed speed in meters per second
  538.          * @return Builder
  539.          */
  540.         public Builder setSpeed(Double speed) {
  541.             this.speed = speed;
  542.             return this;
  543.         }

  544.         /**
  545.          * Sets a thoroughfare within the locality, or a crossing of two thoroughfares.
  546.          *
  547.          * @param street name of the street
  548.          * @return Builder
  549.          */
  550.         public Builder setStreet(String street) {
  551.             this.street = street;
  552.             return this;
  553.         }

  554.         /**
  555.          * Sets a catch-all element that captures any other information about the location.
  556.          *
  557.          * @param text distinctive feature about the location
  558.          * @return Builder
  559.          */
  560.         public Builder setText(String text) {
  561.             this.text = text;
  562.             return this;
  563.         }

  564.         /**
  565.          * Sets UTC timestamp specifying the moment when the reading was taken.
  566.          *
  567.          * @param timestamp timestamp of the reading
  568.          * @return Builder
  569.          */
  570.         public Builder setTimestamp(Date timestamp) {
  571.             this.timestamp = timestamp;
  572.             return this;
  573.         }

  574.         /**
  575.          * Sets the time zone offset from UTC for the current location.
  576.          *
  577.          * @param tzo time zone offset
  578.          * @return Builder
  579.          */
  580.         public Builder setTzo(String tzo) {
  581.             this.tzo = tzo;
  582.             return this;
  583.         }

  584.         /**
  585.          * Sets URI or URL pointing to information about the location.
  586.          *
  587.          * @param uri uri to the location
  588.          * @return Builder
  589.          */
  590.         public Builder setUri(URI uri) {
  591.             this.uri = uri;
  592.             return this;
  593.         }

  594.         /**
  595.          * This method is called to build {@link GeoLocation} from the Builder.
  596.          *
  597.          * @return GeoLocation
  598.          */
  599.         public GeoLocation build() {
  600.             return new GeoLocation(this);
  601.         }
  602.     }
  603. }