Skip to content

Commit 2ed1790

Browse files
committed
Introduce ProblemStatus as object to assign both title and status at once
1 parent 7a0e560 commit 2ed1790

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

src/main/java/io/github/malczuuu/problem4j/core/ProblemBuilder.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public interface ProblemBuilder {
1212

1313
ProblemBuilder status(int status);
1414

15+
ProblemBuilder status(ProblemStatus status);
16+
1517
ProblemBuilder detail(String detail);
1618

1719
ProblemBuilder instance(URI instance);

src/main/java/io/github/malczuuu/problem4j/core/ProblemBuilderImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.net.URI;
44
import java.util.LinkedHashMap;
55
import java.util.Map;
6+
import java.util.Optional;
67

78
final class ProblemBuilderImpl implements ProblemBuilder {
89

@@ -38,6 +39,13 @@ public ProblemBuilder status(int status) {
3839
return this;
3940
}
4041

42+
@Override
43+
public ProblemBuilder status(ProblemStatus status) {
44+
this.title = status.getTitle();
45+
this.status = status.getStatus();
46+
return this;
47+
}
48+
4149
@Override
4250
public ProblemBuilder detail(String detail) {
4351
this.detail = detail;
@@ -62,6 +70,13 @@ public ProblemBuilder extension(String name, Object value) {
6270
}
6371

6472
public Problem build() {
73+
String title = this.title;
74+
if (title == null) {
75+
Optional<ProblemStatus> status = StatusCode.findValue(this.status);
76+
if (status.isPresent()) {
77+
title = status.get().getTitle();
78+
}
79+
}
6580
return new Problem(type, title, status, detail, instance, extensions);
6681
}
6782
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.github.malczuuu.problem4j.core;
2+
3+
public interface ProblemStatus {
4+
5+
String getTitle();
6+
7+
int getStatus();
8+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package io.github.malczuuu.problem4j.core;
2+
3+
import java.util.Arrays;
4+
import java.util.Map;
5+
import java.util.Optional;
6+
import java.util.function.Function;
7+
import java.util.stream.Collectors;
8+
9+
/**
10+
* Represents a generic status code, similar to HTTP status codes.
11+
*
12+
* <p>This enum can be used to represent response status codes in a library-agnostic way, without
13+
* introducing dependencies on specific frameworks like Spring.
14+
*
15+
* @see <a href="https://datatracker.ietf.org/doc/html/rfc9110#name-status-codes">RFC9110 - HTTP
16+
* Semantics</a>
17+
* @see <a href="https://http.cat/">HTTP Cats</a>
18+
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status">HTTP response
19+
* status codes - HTTP | MDN</a>
20+
*/
21+
public enum StatusCode implements ProblemStatus {
22+
CONTINUE(100, "Continue"),
23+
SWITCHING_PROTOCOLS(101, "Switching Protocols"),
24+
PROCESSING(102, "Processing"),
25+
CHECKPOINT(103, "Checkpoint"),
26+
OK(200, "OK"),
27+
CREATED(201, "Created"),
28+
ACCEPTED(202, "Accepted"),
29+
NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"),
30+
NO_CONTENT(204, "No Content"),
31+
RESET_CONTENT(205, "Reset Content"),
32+
PARTIAL_CONTENT(206, "Partial Content"),
33+
MULTI_STATUS(207, "Multi-Status"),
34+
ALREADY_REPORTED(208, "Already Reported"),
35+
IM_USED(226, "IM Used"),
36+
MULTIPLE_CHOICES(300, "Multiple Choices"),
37+
MOVED_PERMANENTLY(301, "Moved Permanently"),
38+
FOUND(302, "Found"),
39+
SEE_OTHER(303, "See Other"),
40+
NOT_MODIFIED(304, "Not Modified"),
41+
USE_PROXY(305, "Use Proxy"),
42+
TEMPORARY_REDIRECT(307, "Temporary Redirect"),
43+
PERMANENT_REDIRECT(308, "Permanent Redirect"),
44+
BAD_REQUEST(400, "Bad Request"),
45+
UNAUTHORIZED(401, "Unauthorized"),
46+
PAYMENT_REQUIRED(402, "Payment Required"),
47+
FORBIDDEN(403, "Forbidden"),
48+
NOT_FOUND(404, "Not Found"),
49+
METHOD_NOT_ALLOWED(405, "Method Not Allowed"),
50+
NOT_ACCEPTABLE(406, "Not Acceptable"),
51+
PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"),
52+
REQUEST_TIMEOUT(408, "Request Timeout"),
53+
CONFLICT(409, "Conflict"),
54+
GONE(410, "Gone"),
55+
LENGTH_REQUIRED(411, "Length Required"),
56+
PRECONDITION_FAILED(412, "Precondition Failed"),
57+
REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large"),
58+
REQUEST_URI_TOO_LONG(414, "Request-URI Too Long"),
59+
UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),
60+
REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested Range Not Satisfiable"),
61+
EXPECTATION_FAILED(417, "Expectation Failed"),
62+
I_AM_A_TEAPOT(418, "I'm a teapot"),
63+
UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"),
64+
LOCKED(423, "Locked"),
65+
FAILED_DEPENDENCY(424, "Failed Dependency"),
66+
UPGRADE_REQUIRED(426, "Upgrade Required"),
67+
PRECONDITION_REQUIRED(428, "Precondition Required"),
68+
TOO_MANY_REQUESTS(429, "Too Many Requests"),
69+
REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"),
70+
UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons"),
71+
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
72+
NOT_IMPLEMENTED(501, "Not Implemented"),
73+
BAD_GATEWAY(502, "Bad Gateway"),
74+
SERVICE_UNAVAILABLE(503, "Service Unavailable"),
75+
GATEWAY_TIMEOUT(504, "Gateway Timeout"),
76+
HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version Not Supported"),
77+
VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates"),
78+
INSUFFICIENT_STORAGE(507, "Insufficient Storage"),
79+
LOOP_DETECTED(508, "Loop Detected"),
80+
BANDWIDTH_LIMIT_EXCEEDED(509, "Bandwidth Limit Exceeded"),
81+
NOT_EXTENDED(510, "Not Extended"),
82+
NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required"),
83+
;
84+
85+
private static final Map<Integer, StatusCode> STATUSES =
86+
Arrays.stream(values())
87+
.collect(Collectors.toMap(ProblemStatus::getStatus, Function.identity()));
88+
89+
public static Optional<ProblemStatus> findValue(int status) {
90+
return Optional.ofNullable(STATUSES.get(status));
91+
}
92+
93+
private final String title;
94+
private final int status;
95+
96+
StatusCode(int status, String title) {
97+
this.title = title;
98+
this.status = status;
99+
}
100+
101+
@Override
102+
public String getTitle() {
103+
return title;
104+
}
105+
106+
@Override
107+
public int getStatus() {
108+
return status;
109+
}
110+
}

0 commit comments

Comments
 (0)