DATACMNS-1114 - Introduced usage of nullable annotations for API validation.
Marked all packages with Spring Frameworks @NonNullApi. Added Spring's @Nullable to methods, parameters and fields that take or produce null values. Adapted using code to make sure the IDE can evaluate the null flow properly. Fixed Javadoc in places where an invalid null handling policy was advertised. Strengthened null requirements for types that expose null-instances. Removed null handling from converters for JodaTime and ThreeTenBP. Introduced factory methods Page.empty() and Page.empty(Pageable). Introduced default methods getRequiredGetter(), …Setter() and …Field() on PersistentProperty to allow non-nullable lookups of members. The same for TypeInformation.getrequiredActualType(), …SuperTypeInformation(). Tweaked PersistentPropertyCreator.addPropertiesForRemainingDescriptors() to filter unsuitable PropertyDescriptors before actually trying to create a Property instance from them as the new stronger nullability requirements would cause exceptions downstream. Lazy.get() now expects a non-null return value. Clients being able to cope with null need to call ….orElse(…). Original pull request: #232.
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -109,7 +110,7 @@ public class Box implements Shape {
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -26,6 +28,7 @@ import org.springframework.util.Assert;
|
||||
* @author Thomas Darimont
|
||||
* @since 1.8
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class Circle implements Shape {
|
||||
|
||||
private static final long serialVersionUID = 5215611530535947924L;
|
||||
@@ -98,39 +101,4 @@ public class Circle implements Shape {
|
||||
public String toString() {
|
||||
return String.format("Circle: [center=%s, radius=%s]", center, radius);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Circle)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Circle that = (Circle) obj;
|
||||
|
||||
return this.center.equals(that.center) && this.radius.equals(that.radius);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
|
||||
result += 31 * center.hashCode();
|
||||
result += 31 * radius.hashCode();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.domain.Range;
|
||||
import org.springframework.data.domain.Range.Bound;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -27,11 +31,19 @@ import org.springframework.util.Assert;
|
||||
* @author Thomas Darimont
|
||||
* @since 1.8
|
||||
*/
|
||||
@Value
|
||||
public class Distance implements Serializable, Comparable<Distance> {
|
||||
|
||||
private static final long serialVersionUID = 2460886201934027744L;
|
||||
|
||||
/**
|
||||
* The distance value in the current {@link Metric}.
|
||||
*/
|
||||
private final double value;
|
||||
|
||||
/**
|
||||
* The {@link Metric} of the {@link Distance}.
|
||||
*/
|
||||
private final Metric metric;
|
||||
|
||||
/**
|
||||
@@ -47,12 +59,14 @@ public class Distance implements Serializable, Comparable<Distance> {
|
||||
* Creates a new {@link Distance} with the given {@link Metric}.
|
||||
*
|
||||
* @param value
|
||||
* @param metric can be {@literal null}.
|
||||
* @param metric must not be {@literal null}.
|
||||
*/
|
||||
public Distance(double value, Metric metric) {
|
||||
|
||||
Assert.notNull(metric, "Metric must not be null!");
|
||||
|
||||
this.value = value;
|
||||
this.metric = metric == null ? Metrics.NEUTRAL : metric;
|
||||
this.metric = metric;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +77,7 @@ public class Distance implements Serializable, Comparable<Distance> {
|
||||
* @return will never be {@literal null}.
|
||||
*/
|
||||
public static Range<Distance> between(Distance min, Distance max) {
|
||||
return new Range<>(min, max);
|
||||
return Range.from(Bound.inclusive(min)).to(Bound.inclusive(max));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,15 +93,6 @@ public class Distance implements Serializable, Comparable<Distance> {
|
||||
return between(new Distance(minValue, minMetric), new Distance(maxValue, maxMetric));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance value in the current {@link Metric}.
|
||||
*
|
||||
* @return the value
|
||||
*/
|
||||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normalized value regarding the underlying {@link Metric}.
|
||||
*
|
||||
@@ -97,15 +102,6 @@ public class Distance implements Serializable, Comparable<Distance> {
|
||||
return value / metric.getMultiplier();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Metric} of the {@link Distance}.
|
||||
*
|
||||
* @return the metric
|
||||
*/
|
||||
public Metric getMetric() {
|
||||
return metric;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link String} representation of the unit the distance is in.
|
||||
*
|
||||
@@ -160,6 +156,7 @@ public class Distance implements Serializable, Comparable<Distance> {
|
||||
public Distance in(Metric metric) {
|
||||
|
||||
Assert.notNull(metric, "Metric must not be null!");
|
||||
|
||||
return this.metric.equals(metric) ? this : new Distance(getNormalizedValue() * metric.getMultiplier(), metric);
|
||||
}
|
||||
|
||||
@@ -168,49 +165,19 @@ public class Distance implements Serializable, Comparable<Distance> {
|
||||
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Distance o) {
|
||||
public int compareTo(@Nullable Distance that) {
|
||||
|
||||
double difference = this.getNormalizedValue() - o.getNormalizedValue();
|
||||
if (that == null) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
double difference = this.getNormalizedValue() - that.getNormalizedValue();
|
||||
|
||||
return difference == 0 ? 0 : difference > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Distance)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Distance that = (Distance) obj;
|
||||
|
||||
return this.value == that.value && this.metric.equals(that.metric);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
|
||||
result += 31 * Double.doubleToLongBits(value);
|
||||
result += 31 * metric.hashCode();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
@@ -31,7 +34,11 @@ import org.springframework.util.ObjectUtils;
|
||||
public class GeoPage<T> extends PageImpl<GeoResult<T>> {
|
||||
|
||||
private static final long serialVersionUID = -5655267379242128600L;
|
||||
private final Distance averageDistance;
|
||||
|
||||
/**
|
||||
* The average distance of the underlying results.
|
||||
*/
|
||||
private final @Getter Distance averageDistance;
|
||||
|
||||
/**
|
||||
* Creates a new {@link GeoPage} from the given {@link GeoResults}.
|
||||
@@ -59,21 +66,12 @@ public class GeoPage<T> extends PageImpl<GeoResult<T>> {
|
||||
this.averageDistance = results.getAverageDistance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average distance of the underlying results.
|
||||
*
|
||||
* @return the averageDistance
|
||||
*/
|
||||
public Distance getAverageDistance() {
|
||||
return averageDistance;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.domain.PageImpl#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.NonNull;
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Value object capturing some arbitrary object plus a distance.
|
||||
@@ -26,80 +27,13 @@ import org.springframework.util.Assert;
|
||||
* @author Thomas Darimont
|
||||
* @since 1.8
|
||||
*/
|
||||
@Value
|
||||
public class GeoResult<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1637452570977581370L;
|
||||
|
||||
private final T content;
|
||||
private final Distance distance;
|
||||
|
||||
/**
|
||||
* Creates a new {@link GeoResult} for the given content and distance.
|
||||
*
|
||||
* @param content must not be {@literal null}.
|
||||
* @param distance must not be {@literal null}.
|
||||
*/
|
||||
public GeoResult(T content, Distance distance) {
|
||||
|
||||
Assert.notNull(content, "Content must not be null!");
|
||||
Assert.notNull(distance, "Distance must not be null!");
|
||||
|
||||
this.content = content;
|
||||
this.distance = distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual content object.
|
||||
*
|
||||
* @return the content
|
||||
*/
|
||||
public T getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance the actual content object has from the origin.
|
||||
*
|
||||
* @return the distance
|
||||
*/
|
||||
public Distance getDistance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof GeoResult)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GeoResult<?> that = (GeoResult<?>) obj;
|
||||
|
||||
return this.content.equals(that.content) && this.distance.equals(that.distance);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
|
||||
result += 31 * distance.hashCode();
|
||||
result += 31 * content.hashCode();
|
||||
|
||||
return result;
|
||||
}
|
||||
@NonNull T content;
|
||||
@NonNull Distance distance;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
@@ -31,6 +33,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Thomas Darimont
|
||||
* @since 1.8
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8347363491300219485L;
|
||||
@@ -45,7 +48,7 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
|
||||
* @param results must not be {@literal null}.
|
||||
*/
|
||||
public GeoResults(List<? extends GeoResult<T>> results) {
|
||||
this(results, (Metric) null);
|
||||
this(results, Metrics.NEUTRAL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,12 +66,13 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
|
||||
* Creates a new {@link GeoResults} instance from the given {@link GeoResult}s and average distance.
|
||||
*
|
||||
* @param results must not be {@literal null}.
|
||||
* @param averageDistance can be {@literal null}.
|
||||
* @param averageDistance must not be {@literal null}.
|
||||
*/
|
||||
@PersistenceConstructor
|
||||
public GeoResults(List<? extends GeoResult<T>> results, Distance averageDistance) {
|
||||
|
||||
Assert.notNull(results, "Results must not be null!");
|
||||
Assert.notNull(averageDistance, "Average Distance must not be null!");
|
||||
|
||||
this.results = results;
|
||||
this.averageDistance = averageDistance;
|
||||
@@ -101,41 +105,6 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
|
||||
return (Iterator<GeoResult<T>>) results.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof GeoResults)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GeoResults<?> that = (GeoResults<?>) obj;
|
||||
|
||||
return this.results.equals(that.results) && this.averageDistance.equals(that.averageDistance);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
|
||||
int result = 17;
|
||||
|
||||
result += 31 * results.hashCode();
|
||||
result += 31 * averageDistance.hashCode();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
@@ -148,16 +117,17 @@ public class GeoResults<T> implements Iterable<GeoResult<T>>, Serializable {
|
||||
|
||||
private static Distance calculateAverageDistance(List<? extends GeoResult<?>> results, Metric metric) {
|
||||
|
||||
Assert.notNull(results, "Results must not be null!");
|
||||
Assert.notNull(metric, "Metric must not be null!");
|
||||
|
||||
if (results.isEmpty()) {
|
||||
return new Distance(0, metric);
|
||||
}
|
||||
|
||||
double averageDistance = 0;
|
||||
double averageDistance = results.stream()//
|
||||
.mapToDouble(it -> it.getDistance().getValue())//
|
||||
.average().orElse(0);
|
||||
|
||||
for (GeoResult<?> result : results) {
|
||||
averageDistance += result.getDistance().getValue();
|
||||
}
|
||||
|
||||
return new Distance(averageDistance / results.size(), metric);
|
||||
return new Distance(averageDistance, metric);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -102,7 +103,7 @@ public class Point implements Serializable {
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -32,6 +34,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Thomas Darimont
|
||||
* @since 1.8
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public class Polygon implements Iterable<Point>, Shape {
|
||||
|
||||
private static final long serialVersionUID = -2705040068154648988L;
|
||||
@@ -98,35 +101,6 @@ public class Polygon implements Iterable<Point>, Shape {
|
||||
return this.points.iterator();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof Polygon)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Polygon that = (Polygon) obj;
|
||||
|
||||
return this.points.equals(that.points);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return points.hashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.data.geo.Distance;
|
||||
import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.geo.Metrics;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -60,6 +61,7 @@ public enum DistanceFormatter implements Converter<String, Distance>, Formatter<
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public final Distance convert(String source) {
|
||||
return source == null ? null : doConvert(source.trim().toLowerCase(Locale.US));
|
||||
@@ -80,7 +82,7 @@ public enum DistanceFormatter implements Converter<String, Distance>, Formatter<
|
||||
*/
|
||||
@Override
|
||||
public Distance parse(String text, Locale locale) throws ParseException {
|
||||
return !StringUtils.hasText(text) ? null : doConvert(text.trim().toLowerCase(locale));
|
||||
return doConvert(text.trim().toLowerCase(locale));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,11 +18,12 @@ package org.springframework.data.geo.format;
|
||||
import java.text.ParseException;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.format.Formatter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Converter to parse two comma-separated doubles into a {@link Point}.
|
||||
@@ -41,6 +42,7 @@ public enum PointFormatter implements Converter<String, Point>, Formatter<Point>
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@Nonnull
|
||||
@Override
|
||||
public Point convert(String source) {
|
||||
|
||||
@@ -77,6 +79,6 @@ public enum PointFormatter implements Converter<String, Point>, Formatter<Point>
|
||||
*/
|
||||
@Override
|
||||
public Point parse(String text, Locale locale) throws ParseException {
|
||||
return !StringUtils.hasText(text) ? null : convert(text);
|
||||
return convert(text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Formatters for geo-spatial types.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @since 1.8
|
||||
*/
|
||||
@org.springframework.lang.NonNullApi
|
||||
package org.springframework.data.geo.format;
|
||||
@@ -5,4 +5,5 @@
|
||||
* @author Oliver Gierke
|
||||
* @since 1.8
|
||||
*/
|
||||
package org.springframework.data.geo;
|
||||
@org.springframework.lang.NonNullApi
|
||||
package org.springframework.data.geo;
|
||||
|
||||
Reference in New Issue
Block a user