001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.gbif.api.model.predicate; 015 016import com.fasterxml.jackson.annotation.JsonIgnore; 017 018import org.gbif.api.model.occurrence.geo.DistanceUnit; 019import org.gbif.api.util.SearchTypeValidator; 020 021import java.util.Objects; 022import java.util.StringJoiner; 023 024import javax.validation.constraints.NotNull; 025 026import com.fasterxml.jackson.annotation.JsonCreator; 027import com.fasterxml.jackson.annotation.JsonIgnore; 028import com.fasterxml.jackson.annotation.JsonProperty; 029 030import io.swagger.v3.oas.annotations.Hidden; 031import io.swagger.v3.oas.annotations.media.Schema; 032 033/** 034 * This predicate checks if an occurrence location falls within a distance of a location. 035 */ 036@Schema( 037 description = "This predicate checks if an occurrence falls within a distance of a location." 038) 039public class GeoDistancePredicate implements Predicate { 040 041 @Hidden 042 @NotNull 043 private final DistanceUnit.GeoDistance geoDistance; 044 045 @Schema( 046 description = "The latitude of the location." 047 ) 048 @NotNull 049 private final String latitude; 050 051 @Schema( 052 description = "The longitude of the location." 053 ) 054 @NotNull 055 private final String longitude; 056 057 @Schema( 058 description = "The distance as a number and unit, e.g. `5km` or `5000m`." 059 ) 060 @NotNull 061 private final String distance; 062 063 /** 064 * Builds a new geodistance predicate that matches records within a given distance of a geopoint.. 065 * 066 * @param latitude 067 * @param longitude 068 * @param distance 069 */ 070 @JsonCreator 071 public GeoDistancePredicate(@JsonProperty("latitude") String latitude, 072 @JsonProperty("longitude") String longitude, 073 @JsonProperty("distance") String distance) { 074 Objects.requireNonNull(latitude, "<latitude> may not be null"); 075 Objects.requireNonNull(longitude, "<longitude> may not be null"); 076 Objects.requireNonNull(distance, "<distance> may not be null"); 077 this.latitude = latitude; 078 this.longitude = longitude; 079 this.distance = distance; 080 // test if it is a valid GeoDistance 081 SearchTypeValidator.validateGeoDistance(latitude, longitude, distance); 082 083 this.geoDistance = DistanceUnit.GeoDistance.parseGeoDistance(latitude, longitude, distance); 084 } 085 086 public GeoDistancePredicate(@NotNull DistanceUnit.GeoDistance geoDistance) { 087 this.geoDistance = geoDistance; 088 089 this.latitude = Double.toString(geoDistance.getLatitude()); 090 this.longitude = Double.toString(geoDistance.getLongitude()); 091 this.distance = geoDistance.getDistance().toString(); 092 } 093 094 public String getLatitude() { 095 return latitude; 096 } 097 098 public String getLongitude() { 099 return longitude; 100 } 101 102 public String getDistance() { 103 return distance; 104 } 105 106 @JsonIgnore 107 public DistanceUnit.GeoDistance getGeoDistance() { 108 return geoDistance; 109 } 110 111 @Override 112 public boolean equals(Object o) { 113 if (this == o) return true; 114 if (o == null || getClass() != o.getClass()) return false; 115 GeoDistancePredicate that = (GeoDistancePredicate) o; 116 return Objects.equals(geoDistance, that.geoDistance); 117 } 118 119 @Override 120 public int hashCode() { 121 return Objects.hash(geoDistance); 122 } 123 124 @Override 125 public String toString() { 126 return new StringJoiner(", ", GeoDistancePredicate.class.getSimpleName() + "[", "]") 127 .add("geoDistance=" + geoDistance).toString(); 128 } 129}