Add equals/hashCode methods to ProblemDetail

Closes gh-29606
This commit is contained in:
Juergen Hoeller
2022-12-01 15:47:40 +01:00
parent e47978e168
commit 1e4c10cef1
2 changed files with 128 additions and 48 deletions

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Representation for an RFC 7807 problem detail. Includes spec-defined
@@ -40,8 +41,8 @@ import org.springframework.util.Assert;
* {@link org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler}.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 6.0
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc7807">RFC 7807</a>
* @see org.springframework.web.ErrorResponse
* @see org.springframework.web.ErrorResponseException
@@ -108,6 +109,13 @@ public class ProblemDetail {
this.type = type;
}
/**
* Return the configured {@link #setType(URI) problem type}.
*/
public URI getType() {
return this.type;
}
/**
* Setter for the {@link #getTitle() problem title}.
* <p>By default, if not explicitly set and the status is well-known, this
@@ -118,6 +126,20 @@ public class ProblemDetail {
this.title = title;
}
/**
* Return the configured {@link #setTitle(String) problem title}.
*/
@Nullable
public String getTitle() {
if (this.title == null) {
HttpStatus httpStatus = HttpStatus.resolve(this.status);
if (httpStatus != null) {
return httpStatus.getReasonPhrase();
}
}
return this.title;
}
/**
* Setter for the {@link #getStatus() problem status}.
* @param httpStatus the problem status
@@ -134,6 +156,14 @@ public class ProblemDetail {
this.status = status;
}
/**
* Return the status associated with the problem, provided either to the
* constructor or configured via {@link #setStatus(int)}.
*/
public int getStatus() {
return this.status;
}
/**
* Setter for the {@link #getDetail() problem detail}.
* <p>By default, this is not set.
@@ -143,6 +173,14 @@ public class ProblemDetail {
this.detail = detail;
}
/**
* Return the configured {@link #setDetail(String) problem detail}.
*/
@Nullable
public String getDetail() {
return this.detail;
}
/**
* Setter for the {@link #getInstance() problem instance}.
* <p>By default, when {@code ProblemDetail} is returned from an
@@ -153,6 +191,14 @@ public class ProblemDetail {
this.instance = instance;
}
/**
* Return the configured {@link #setInstance(URI) problem instance}.
*/
@Nullable
public URI getInstance() {
return this.instance;
}
/**
* Set a "dynamic" property to be added to a generic {@link #getProperties()
* properties map}.
@@ -168,52 +214,6 @@ public class ProblemDetail {
this.properties.put(name, value);
}
/**
* Return the configured {@link #setType(URI) problem type}.
*/
public URI getType() {
return this.type;
}
/**
* Return the configured {@link #setTitle(String) problem title}.
*/
@Nullable
public String getTitle() {
if (this.title == null) {
HttpStatus httpStatus = HttpStatus.resolve(this.status);
if (httpStatus != null) {
return httpStatus.getReasonPhrase();
}
}
return this.title;
}
/**
* Return the status associated with the problem, provided either to the
* constructor or configured via {@link #setStatus(int)}.
*/
public int getStatus() {
return this.status;
}
/**
* Return the configured {@link #setDetail(String) problem detail}.
*/
@Nullable
public String getDetail() {
return this.detail;
}
/**
* Return the configured {@link #setInstance(URI) problem instance}.
*/
@Nullable
public URI getInstance() {
return this.instance;
}
/**
* Return a generic map of properties that are not known ahead of time,
* possibly {@code null} if no properties have been added. To add a property,
@@ -229,6 +229,33 @@ public class ProblemDetail {
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (!(other instanceof ProblemDetail otherDetail)) {
return false;
}
return (this.type.equals(otherDetail.type) &&
ObjectUtils.nullSafeEquals(this.title, otherDetail.title) &&
this.status == otherDetail.status &&
ObjectUtils.nullSafeEquals(this.detail, otherDetail.detail) &&
ObjectUtils.nullSafeEquals(this.instance, otherDetail.instance) &&
ObjectUtils.nullSafeEquals(this.properties, otherDetail.properties));
}
@Override
public int hashCode() {
int result = this.type.hashCode();
result = 31 * result + ObjectUtils.nullSafeHashCode(this.title);
result = 31 * result + this.status;
result = 31 * result + ObjectUtils.nullSafeHashCode(this.detail);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.instance);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.properties);
return result;
}
@Override
public String toString() {
return getClass().getSimpleName() + "[" + initToStringContent() + "]";
@@ -239,7 +266,7 @@ public class ProblemDetail {
* Subclasses can override this to append additional fields.
*/
protected String initToStringContent() {
return "type='" + this.type + "'" +
return "type='" + getType() + "'" +
", title='" + getTitle() + "'" +
", status=" + getStatus() +
", detail='" + getDetail() + "'" +