View Javadoc
1   package com.guinetik.rr.request;
2   
3   import com.guinetik.rr.http.RocketHeaders;
4   
5   import java.util.HashMap;
6   import java.util.Map;
7   
8   /**
9    * Fluent builder for constructing {@link RequestSpec} instances.
10   *
11   * <p>This builder provides a clean, type-safe API for creating HTTP request specifications
12   * with all necessary parameters like endpoint, method, headers, body, and response type.
13   *
14   * <h2>Static Factory Methods</h2>
15   * <pre class="language-java"><code>
16   * // GET request
17   * RequestSpec&lt;Void, User&gt; getUser = RequestBuilder.&lt;Void, User&gt;get("/users/1")
18   *     .responseType(User.class)
19   *     .build();
20   *
21   * // POST request with body
22   * RequestSpec&lt;CreateUser, User&gt; createUser = RequestBuilder.&lt;CreateUser, User&gt;post("/users")
23   *     .body(new CreateUser("John", "john@example.com"))
24   *     .responseType(User.class)
25   *     .build();
26   *
27   * // PUT request
28   * RequestSpec&lt;UpdateUser, User&gt; updateUser = RequestBuilder.&lt;UpdateUser, User&gt;put("/users/1")
29   *     .body(new UpdateUser("John Doe"))
30   *     .responseType(User.class)
31   *     .build();
32   *
33   * // DELETE request
34   * RequestSpec&lt;Void, Void&gt; deleteUser = RequestBuilder.&lt;Void, Void&gt;delete("/users/1")
35   *     .responseType(Void.class)
36   *     .build();
37   * </code></pre>
38   *
39   * <h2>With Headers and Query Params</h2>
40   * <pre class="language-java"><code>
41   * Map&lt;String, String&gt; params = new HashMap&lt;&gt;();
42   * params.put("page", "1");
43   * params.put("limit", "10");
44   *
45   * RequestSpec&lt;Void, UserList&gt; request = RequestBuilder.&lt;Void, UserList&gt;get("/users")
46   *     .queryParams(params)
47   *     .headers(RocketHeaders.defaultJson().set("X-Custom", "value"))
48   *     .responseType(UserList.class)
49   *     .build();
50   * </code></pre>
51   *
52   * @param <Req> the type of the request body
53   * @param <Res> the type of the response
54   * @author guinetik &lt;guinetik@gmail.com&gt;
55   * @see RequestSpec
56   * @since 1.0.0
57   */
58  public class RequestBuilder<Req, Res> {
59      private String endpoint;
60      private String method = "GET";
61      private Map<String, String> queryParams = new HashMap<>();
62      private RocketHeaders headers = RocketHeaders.defaultJson();
63      private Req body;
64      private Class<Res> responseType;
65  
66      /**
67       * Creates a GET request builder for the specified endpoint.
68       *
69       * @param endpoint the API endpoint.
70       * @param <Req> The type of the request body.
71       * @param <Res> The type of the response.
72       * @return a new builder instance.
73       */
74      public static <Req, Res> RequestBuilder<Req, Res> get(String endpoint) {
75          return new RequestBuilder<Req, Res>().endpoint(endpoint).method("GET");
76      }
77  
78      /**
79       * Creates a POST request builder for the specified endpoint.
80       *
81       * @param endpoint the API endpoint.
82       * @param <Req> The type of the request body.
83       * @param <Res> The type of the response.
84       * @return a new builder instance.
85       */
86      public static <Req, Res> RequestBuilder<Req, Res> post(String endpoint) {
87          return new RequestBuilder<Req, Res>().endpoint(endpoint).method("POST");
88      }
89  
90      /**
91       * Creates a PUT request builder for the specified endpoint.
92       *
93       * @param endpoint the API endpoint.
94       * @param <Req> The type of the request body.
95       * @param <Res> The type of the response.
96       * @return a new builder instance.
97       */
98      public static <Req, Res> RequestBuilder<Req, Res> put(String endpoint) {
99          return new RequestBuilder<Req, Res>().endpoint(endpoint).method("PUT");
100     }
101 
102     /**
103      * Creates a DELETE request builder for the specified endpoint.
104      *
105      * @param endpoint the API endpoint.
106      * @param <Req> The type of the request body.
107      * @param <Res> The type of the response.
108      * @return a new builder instance.
109      */
110     public static <Req, Res> RequestBuilder<Req, Res> delete(String endpoint) {
111         return new RequestBuilder<Req, Res>().endpoint(endpoint).method("DELETE");
112     }
113 
114     /**
115      * Sets the API endpoint for the request.
116      *
117      * @param endpoint the API endpoint.
118      * @return the builder instance.
119      */
120     public RequestBuilder<Req, Res> endpoint(String endpoint) {
121         this.endpoint = endpoint;
122         return this;
123     }
124 
125     /**
126      * Sets the HTTP method for the request.
127      *
128      * @param method the HTTP method (e.g., GET, POST, PUT, DELETE).
129      * @return the builder instance.
130      */
131     public RequestBuilder<Req, Res> method(String method) {
132         this.method = method;
133         return this;
134     }
135 
136     /**
137      * Sets the query parameters for the request.
138      *
139      * @param queryParams a map of query parameters.
140      * @return the builder instance.
141      */
142     public RequestBuilder<Req, Res> queryParams(Map<String, String> queryParams) {
143         this.queryParams = queryParams;
144         return this;
145     }
146 
147     /**
148      * Adds a single query parameter to the request.
149      *
150      * @param name the parameter name.
151      * @param value the parameter value.
152      * @return the builder instance.
153      */
154     public RequestBuilder<Req, Res> queryParam(String name, String value) {
155         this.queryParams.put(name, value);
156         return this;
157     }
158 
159     /**
160      * Sets the headers for the request.
161      *
162      * @param headers a map of headers.
163      * @return the builder instance.
164      */
165     public RequestBuilder<Req, Res> headers(RocketHeaders headers) {
166         this.headers = headers;
167         return this;
168     }
169 
170     /**
171      * Sets the body of the request.
172      *
173      * @param body the request body.
174      * @return the builder instance.
175      */
176     public RequestBuilder<Req, Res> body(Req body) {
177         this.body = body;
178         return this;
179     }
180 
181     /**
182      * Sets the expected response type of the request.
183      *
184      * @param responseType the response type.
185      * @return the builder instance.
186      */
187     public RequestBuilder<Req, Res> responseType(Class<Res> responseType) {
188         this.responseType = responseType;
189         return this;
190     }
191 
192     /**
193      * Builds and returns a {@link RequestSpec} instance.
194      *
195      * @return the constructed {@link RequestSpec}.
196      */
197     public RequestSpec<Req, Res> build() {
198         return new RequestSpec<>(endpoint, method, queryParams, headers, body, responseType);
199     }
200 }