Location.java
001 /*
002  * Java GPX Library (jpx-3.1.0).
003  * Copyright (c) 2016-2023 Franz Wilhelmstötter
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  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics.jpx.format;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 
025 import java.util.Objects;
026 import java.util.Optional;
027 
028 import io.jenetics.jpx.Latitude;
029 import io.jenetics.jpx.Length;
030 import io.jenetics.jpx.Longitude;
031 import io.jenetics.jpx.Point;
032 import io.jenetics.jpx.WayPoint;
033 
034 /**
035  * Aggregation of the three location components: latitude, longitude and
036  * elevation.
037  *
038  @see Point
039  *
040  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
041  @version 2.2
042  @since 1.4
043  */
044 public final class Location {
045     private final Latitude _latitude;
046     private final Longitude _longitude;
047     private final Length _elevation;
048 
049     private Location(
050         final Latitude latitude,
051         final Longitude longitude,
052         final Length elevation
053     ) {
054         _latitude = latitude;
055         _longitude = longitude;
056         _elevation = elevation;
057     }
058 
059     /**
060      * Return the <em>latitude</em> of {@code this} location.
061      *
062      @return the <em>latitude</em> of {@code this} location, or
063      *         {@link Optional#empty()} if not available
064      */
065     public Optional<Latitude> latitude() {
066         return Optional.ofNullable(_latitude);
067     }
068 
069     /**
070      * Return the <em>longitude</em> of {@code this} location.
071      *
072      @return the <em>longitude</em> of {@code this} location, or
073      *         {@link Optional#empty()} if not available
074      */
075     public Optional<Longitude> longitude() {
076         return Optional.ofNullable(_longitude);
077     }
078 
079     /**
080      * Return the <em>elevation</em> of {@code this} location.
081      *
082      @return the <em>elevation</em> of {@code this} location, or
083      *         {@link Optional#empty()} if not available
084      */
085     public Optional<Length> elevation() {
086         return Optional.ofNullable(_elevation);
087     }
088 
089     /**
090      * Return a new {@link Point} from {@code this} location. If the
091      {@link #latitude()} or the {@link #longitude()} is not given,
092      {@link Optional#empty()} is returned
093      *
094      @return a new {@link Point} if the latitude and longitude is given,
095      *         {@link Optional#empty()} otherwise
096      */
097     public Optional<Point> toPoint() {
098         return latitude().flatMap(lat ->
099             longitude().map(lon ->
100                 WayPoint.of(lat, lon, _elevation, null)
101             )
102         );
103     }
104 
105     @Override
106     public int hashCode(){
107         return Objects.hash(_latitude, _longitude, _elevation);
108     }
109 
110     @Override
111     public boolean equals(final Object other) {
112         return other == this ||
113             other instanceof Location loc &&
114             Objects.equals(_latitude, loc._latitude&&
115             Objects.equals(_longitude, loc._longitude&&
116             Objects.equals(_elevation, loc._elevation);
117     }
118 
119     @Override
120     public String toString() {
121         return format(
122             "[lat=%s, lon=%s, ele=%s]",
123             _latitude, _longitude, _elevation
124         );
125     }
126 
127     /**
128      * Create a new location form the given GPS point.
129      *
130      @param point the GPS point
131      @return a new location form the given GPS point
132      @throws NullPointerException if the given {@code point} is {@code null}
133      */
134     public static Location of(final Point point) {
135         requireNonNull(point);
136         return of(
137             point.getLatitude(),
138             point.getLongitude(),
139             point.getElevation().orElse(null)
140         );
141     }
142 
143     /**
144      * Create a new <em>location</em> object from the given {@code latitude},
145      * {@code longitude} and {@code elevation}.
146      *
147      @param latitude the latitude of the location, maybe {@code null}
148      @param longitude the longitude of the location, maybe {@code null}
149      @param elevation the elevation if the location, maybe {@code null}
150      @return a new location object from the given input data
151      */
152     public static Location of(
153         final Latitude latitude,
154         final Longitude longitude,
155         final Length elevation
156     ) {
157         return new Location(latitude, longitude, elevation);
158     }
159 
160     /**
161      * Create a new <em>location</em> object from the given {@code latitude}
162      * and {@code longitude}.
163      *
164      @param latitude the latitude of the location, maybe {@code null}
165      @param longitude the longitude of the location, maybe {@code null}
166      @return a new location object from the given input data
167      */
168     public static Location of(final Latitude latitude, final Longitude longitude) {
169         return new Location(latitude, longitude, null);
170     }
171 
172     /**
173      * Create a new <em>location</em> object from the given {@code latitude}.
174      *
175      @param latitude the latitude of the location, maybe {@code null}
176      @return a new location object from the given input data
177      */
178     public static Location of(final Latitude latitude) {
179         return new Location(latitude, null, null);
180     }
181 
182     /**
183      * Create a new <em>location</em> object from the given {@code longitude}.
184      *
185      @param longitude the longitude of the location, maybe {@code null}
186      @return a new location object from the given input data
187      */
188     public static Location of(final Longitude longitude) {
189         return new Location(null, longitude, null);
190     }
191 
192     /**
193      * Create a new <em>location</em> object from the given {@code elevation}.
194      *
195      @param elevation the elevation of the location, maybe {@code null}
196      @return a new location object from the given input data
197      */
198     public static Location of(final Length elevation) {
199         return new Location(null, null, elevation);
200     }
201 
202 }