77 lines
3.2 KiB
Java
77 lines
3.2 KiB
Java
package builder;
|
|
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
|
|
public final class HttpRequest {
|
|
|
|
// All fields are final: the object is immutable after build() returns.
|
|
private final String url;
|
|
private final String method;
|
|
private final String body;
|
|
private final Map<String, String> headers;
|
|
private final int timeoutMs;
|
|
private final int maxRetries;
|
|
|
|
// Private: the only path to an HttpRequest is through Builder.build()
|
|
private HttpRequest(Builder builder) {
|
|
this.url = Objects.requireNonNull(builder.url, "URL is required");
|
|
this.method = builder.method;
|
|
this.body = builder.body;
|
|
this.headers = Collections.unmodifiableMap(new HashMap<>(builder.headers));
|
|
this.timeoutMs = builder.timeoutMs;
|
|
this.maxRetries = builder.maxRetries;
|
|
}
|
|
|
|
// Getters only — no setters, enforcing immutability
|
|
public String getUrl() { return url; }
|
|
public String getMethod() { return method; }
|
|
public String getBody() { return body; }
|
|
public Map<String, String> getHeaders() { return headers; }
|
|
public int getTimeoutMs() { return timeoutMs; }
|
|
public int getMaxRetries() { return maxRetries; }
|
|
|
|
@Override
|
|
public String toString() {
|
|
return String.format("%s %s (timeout=%dms, retries=%d, headers=%s, body=%s)",
|
|
method, url, timeoutMs, maxRetries, headers, body);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
// THE BUILDER — static inner class so it can call the private constructor
|
|
// -----------------------------------------------------------------------
|
|
public static class Builder {
|
|
|
|
// Required field — no default, must be set
|
|
private String url;
|
|
|
|
// Optional fields with sensible defaults
|
|
private String method = "GET";
|
|
private String body = null;
|
|
private Map<String, String> headers = new HashMap<>();
|
|
private int timeoutMs = 30_000; // 30 seconds
|
|
private int maxRetries = 0;
|
|
|
|
// Fluent methods: each returns 'this' so calls can be chained
|
|
public Builder url(String url) { this.url = url; return this; }
|
|
public Builder method(String method) { this.method = method; return this; }
|
|
public Builder body(String body) { this.body = body; return this; }
|
|
public Builder header(String key, String v) { headers.put(key, v); return this; }
|
|
public Builder timeoutMs(int ms) { this.timeoutMs = ms; return this; }
|
|
public Builder maxRetries(int n) { this.maxRetries = n; return this; }
|
|
|
|
// Terminal method: validates and creates the immutable HttpRequest
|
|
public HttpRequest build() {
|
|
if (url == null || url.isBlank()) {
|
|
throw new IllegalStateException("url() is required before calling build()");
|
|
}
|
|
if (maxRetries < 0) {
|
|
throw new IllegalStateException("maxRetries must be >= 0");
|
|
}
|
|
return new HttpRequest(this); // calls the private constructor
|
|
}
|
|
}
|
|
}
|