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.util; 015 016import javax.annotation.Nullable; 017import javax.validation.constraints.NotNull; 018 019import io.swagger.v3.oas.annotations.media.Schema; 020 021/** Simplified version of guava's {@code Range}. */ 022public class Range<T extends Comparable<? super T>> { 023 024 /** Lower bound. Unbound if it is {@code null}. */ 025 @Schema(description = "The lower bound. Unbound if null/unspecified.") 026 private final T from; 027 028 /** Upper bound. Unbound if it is {@code null}. */ 029 @Schema(description = "The upper bound. Unbound if null/unspecified.") 030 private final T to; 031 032 /** 033 * Create a range with bounds {@code from} and {@code to}. Use factory method instead. 034 * 035 * @throws IllegalArgumentException if {@code from} is greater than {@code to} 036 */ 037 private Range(T from, T to) { 038 if (from != null && to != null && from.compareTo(to) > 0) { 039 throw new IllegalArgumentException(String.format("Invalid range: (%s,%s)", from, to)); 040 } 041 this.from = from; 042 this.to = to; 043 } 044 045 /** Factory method. */ 046 public static <T extends Comparable<? super T>> Range<T> closed(T from, T to) { 047 return new Range<>(from, to); 048 } 049 050 /** Returns {@code true} if this range has a lower endpoint. */ 051 public boolean hasLowerBound() { 052 return from != null; 053 } 054 055 /** Returns {@code true} if this range has an upper endpoint. */ 056 public boolean hasUpperBound() { 057 return to != null; 058 } 059 060 /** Returns {@code true} if {@code value} is within the bounds of this range. */ 061 public boolean contains(@NotNull T value) { 062 return from.compareTo(value) <= 0 && to.compareTo(value) >= 0; 063 } 064 065 /** 066 * Returns {@code true} if the bounds of {@code other} do not extend outside the bounds of this 067 * range. 068 */ 069 public boolean encloses(@NotNull Range<T> other) { 070 return from.compareTo(other.from) <= 0 && to.compareTo(other.to) >= 0; 071 } 072 073 @Nullable 074 public T lowerEndpoint() { 075 return from; 076 } 077 078 @Nullable 079 public T upperEndpoint() { 080 return to; 081 } 082 083 @Override 084 public String toString() { 085 String lower = "*"; 086 if (this.lowerEndpoint() != null) { 087 lower = this.lowerEndpoint().toString(); 088 } 089 090 String upper = "*"; 091 if (this.upperEndpoint() != null) { 092 upper = this.upperEndpoint().toString(); 093 } 094 095 return lower + "," + upper; 096 } 097}