Skip to content

Commit d8acea1

Browse files
Flossyclaude
andcommitted
docs: add comprehensive Javadoc to RestApiClassSource.Builder API
Enhanced RestApiClassSource.Builder with detailed documentation: Class-level: - Basic and advanced usage examples (binary and JSON responses) - URL template variables explained ({package}, {class}, {fullclass}) - Response format comparison (BINARY, BASE64_JSON_FIELD, DIRECT) - Complete default values listed - S3-compatible and REST API integration patterns Method-level documented (9 methods): - baseUrl() - Base URL configuration with examples - classPathTemplate() - URL template with placeholders - addHeader() - Custom HTTP headers - addQueryParam() - Query parameters - auth() - Authentication types (none, basic, bearer, API key) - responseFormat() - Response parsing options - connectTimeout() - Connection timeout configuration - readTimeout() - Read timeout configuration - enableCanLoadCheck() - Performance impact of HEAD requests (doubles traffic) All methods include: - @param, @return, @throws tags - Usage examples where helpful - Performance considerations - Default values Relates to #71 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 3fac7bf commit d8acea1

1 file changed

Lines changed: 185 additions & 0 deletions

File tree

src/main/java/org/flossware/classloader/RestApiClassSource.java

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,69 @@ private String extractBase64FromJson(String json) throws IOException {
223223
return json.substring(start, end);
224224
}
225225

226+
/**
227+
* Creates a new Builder for constructing RestApiClassSource instances.
228+
*
229+
* @return A new Builder with default configuration
230+
*/
226231
public static Builder builder() {
227232
return new Builder();
228233
}
229234

235+
/**
236+
* Builder for constructing RestApiClassSource instances with fluent API.
237+
*
238+
* <p>Configures a custom REST API for class loading with flexible URL templates,
239+
* headers, query parameters, authentication, and response formats.</p>
240+
*
241+
* <p><b>Basic Example (Binary Response):</b></p>
242+
* <pre>{@code
243+
* RestApiClassSource source = RestApiClassSource.builder()
244+
* .baseUrl("https://classes.example.com/api/v1")
245+
* .classPathTemplate("classes/{fullclass}")
246+
* .auth(AuthConfig.bearer("token123"))
247+
* .build();
248+
* }</pre>
249+
*
250+
* <p><b>Advanced Example (JSON Response with Base64):</b></p>
251+
* <pre>{@code
252+
* RestApiClassSource source = RestApiClassSource.builder()
253+
* .baseUrl("https://api.example.com")
254+
* .classPathTemplate("classes/{package}/{class}")
255+
* .addHeader("X-API-Version", "2.0")
256+
* .addQueryParam("env", "production")
257+
* .auth(AuthConfig.apiKey("X-API-Key", "secret123"))
258+
* .responseFormat(ResponseFormat.BASE64_JSON_FIELD)
259+
* .connectTimeout(15000)
260+
* .readTimeout(60000)
261+
* .enableCanLoadCheck(true) // Enable HEAD requests
262+
* .build();
263+
* }</pre>
264+
*
265+
* <p><b>URL Template Variables:</b></p>
266+
* <ul>
267+
* <li>{@code {package}} - Package path (e.g., "com/example")</li>
268+
* <li>{@code {class}} - Simple class name (e.g., "MyClass")</li>
269+
* <li>{@code {fullclass}} - Full class path (e.g., "com/example/MyClass")</li>
270+
* </ul>
271+
*
272+
* <p><b>Response Formats:</b></p>
273+
* <ul>
274+
* <li><b>BINARY</b> - Raw class bytes in response body (default)</li>
275+
* <li><b>BASE64_JSON_FIELD</b> - JSON with base64-encoded class in "data" or "content" field</li>
276+
* <li><b>DIRECT</b> - Same as BINARY</li>
277+
* </ul>
278+
*
279+
* <p><b>Defaults:</b></p>
280+
* <ul>
281+
* <li>classPathTemplate: "{package}/{class}.class"</li>
282+
* <li>responseFormat: BINARY</li>
283+
* <li>connectTimeout: 10000ms (10 seconds)</li>
284+
* <li>readTimeout: 30000ms (30 seconds)</li>
285+
* <li>enableCanLoadCheck: false (skip HEAD requests for performance)</li>
286+
* <li>auth: none</li>
287+
* </ul>
288+
*/
230289
public static class Builder {
231290
private String baseUrl;
232291
private String classPathTemplate;
@@ -238,40 +297,138 @@ public static class Builder {
238297
private int readTimeout = DEFAULT_READ_TIMEOUT;
239298
private boolean enableCanLoadCheck = false; // Default: skip expensive checks
240299

300+
/**
301+
* Sets the base URL of the REST API.
302+
*
303+
* <p>This is prepended to the classPathTemplate.</p>
304+
*
305+
* <p>Examples:</p>
306+
* <ul>
307+
* <li>"https://classes.example.com/api/v1"</li>
308+
* <li>"http://localhost:8080/classes"</li>
309+
* <li>"https://cdn.example.com"</li>
310+
* </ul>
311+
*
312+
* @param baseUrl Base URL (automatically adds trailing slash if missing)
313+
* @return this builder
314+
* @throws NullPointerException if baseUrl is null
315+
*/
241316
public Builder baseUrl(String baseUrl) {
242317
this.baseUrl = Objects.requireNonNull(baseUrl, "baseUrl cannot be null");
243318
return this;
244319
}
245320

321+
/**
322+
* Sets the URL template for class paths.
323+
*
324+
* <p>Uses placeholders: {package}, {class}, {fullclass}</p>
325+
*
326+
* <p>Examples:</p>
327+
* <ul>
328+
* <li>"{package}/{class}.class" (default)</li>
329+
* <li>"classes/{fullclass}" → "classes/com/example/MyClass"</li>
330+
* <li>"v2/{package}/{class}.bin"</li>
331+
* </ul>
332+
*
333+
* @param template URL template (null to use default)
334+
* @return this builder
335+
*/
246336
public Builder classPathTemplate(String template) {
247337
this.classPathTemplate = template;
248338
return this;
249339
}
250340

341+
/**
342+
* Adds a custom HTTP header to all requests.
343+
*
344+
* <p>Useful for API versioning, custom authentication, or metadata.</p>
345+
*
346+
* <p>Example:</p>
347+
* <pre>{@code
348+
* builder.addHeader("X-API-Version", "2.0")
349+
* .addHeader("Accept", "application/octet-stream")
350+
* }</pre>
351+
*
352+
* @param name Header name
353+
* @param value Header value
354+
* @return this builder
355+
* @throws NullPointerException if name or value is null
356+
*/
251357
public Builder addHeader(String name, String value) {
252358
Objects.requireNonNull(name, "header name cannot be null");
253359
Objects.requireNonNull(value, "header value cannot be null");
254360
this.headers.put(name, value);
255361
return this;
256362
}
257363

364+
/**
365+
* Adds a query parameter to all requests.
366+
*
367+
* <p>Example:</p>
368+
* <pre>{@code
369+
* builder.addQueryParam("env", "production")
370+
* .addQueryParam("version", "1.0")
371+
* // URLs become: baseUrl/path?env=production&version=1.0
372+
* }</pre>
373+
*
374+
* @param name Parameter name
375+
* @param value Parameter value
376+
* @return this builder
377+
* @throws NullPointerException if name or value is null
378+
*/
258379
public Builder addQueryParam(String name, String value) {
259380
Objects.requireNonNull(name, "query param name cannot be null");
260381
Objects.requireNonNull(value, "query param value cannot be null");
261382
this.queryParams.put(name, value);
262383
return this;
263384
}
264385

386+
/**
387+
* Sets authentication configuration.
388+
*
389+
* <p>Supported types:</p>
390+
* <ul>
391+
* <li>AuthConfig.none() - No authentication (default)</li>
392+
* <li>AuthConfig.basic(username, password) - HTTP Basic</li>
393+
* <li>AuthConfig.bearer(token) - Bearer token</li>
394+
* <li>AuthConfig.apiKey(headerName, key) - API key header</li>
395+
* </ul>
396+
*
397+
* @param authConfig Authentication configuration (null = no auth)
398+
* @return this builder
399+
*/
265400
public Builder auth(AuthConfig authConfig) {
266401
this.authConfig = authConfig;
267402
return this;
268403
}
269404

405+
/**
406+
* Sets the response format.
407+
*
408+
* <p>Determines how to parse the API response:</p>
409+
* <ul>
410+
* <li><b>BINARY</b> - Raw bytes (default, most efficient)</li>
411+
* <li><b>BASE64_JSON_FIELD</b> - JSON with base64 in "data" or "content" field</li>
412+
* <li><b>DIRECT</b> - Same as BINARY</li>
413+
* </ul>
414+
*
415+
* @param format Response format (null = BINARY)
416+
* @return this builder
417+
*/
270418
public Builder responseFormat(ResponseFormat format) {
271419
this.responseFormat = format;
272420
return this;
273421
}
274422

423+
/**
424+
* Sets the connection timeout.
425+
*
426+
* <p>Prevents hanging indefinitely when connecting to the API.</p>
427+
*
428+
* @param timeoutMs Timeout in milliseconds (default: 10000ms = 10 seconds, 0 = infinite)
429+
* @return this builder
430+
* @throws IllegalArgumentException if timeoutMs < 0
431+
*/
275432
public Builder connectTimeout(int timeoutMs) {
276433
if (timeoutMs < 0) {
277434
throw new IllegalArgumentException("connectTimeout must be >= 0");
@@ -280,6 +437,15 @@ public Builder connectTimeout(int timeoutMs) {
280437
return this;
281438
}
282439

440+
/**
441+
* Sets the read timeout.
442+
*
443+
* <p>Prevents hanging indefinitely when reading response data.</p>
444+
*
445+
* @param timeoutMs Timeout in milliseconds (default: 30000ms = 30 seconds, 0 = infinite)
446+
* @return this builder
447+
* @throws IllegalArgumentException if timeoutMs < 0
448+
*/
283449
public Builder readTimeout(int timeoutMs) {
284450
if (timeoutMs < 0) {
285451
throw new IllegalArgumentException("readTimeout must be >= 0");
@@ -288,11 +454,30 @@ public Builder readTimeout(int timeoutMs) {
288454
return this;
289455
}
290456

457+
/**
458+
* Enables or disables canLoad() HEAD requests.
459+
*
460+
* <p><b>Performance Impact:</b> When enabled, canLoad() makes a HEAD request
461+
* to check if a class exists, which <b>doubles network traffic</b>. When disabled
462+
* (default), canLoad() always returns true and loadClassData() fails if the
463+
* class doesn't exist.</p>
464+
*
465+
* <p><b>Recommendation:</b> Leave disabled (false) unless your application
466+
* specifically needs to check class existence before loading.</p>
467+
*
468+
* @param enable true to enable HEAD requests, false to skip (default: false)
469+
* @return this builder
470+
*/
291471
public Builder enableCanLoadCheck(boolean enable) {
292472
this.enableCanLoadCheck = enable;
293473
return this;
294474
}
295475

476+
/**
477+
* Builds the RestApiClassSource with configured settings.
478+
*
479+
* @return A new RestApiClassSource instance
480+
*/
296481
public RestApiClassSource build() {
297482
return new RestApiClassSource(baseUrl, classPathTemplate, headers,
298483
queryParams, authConfig, responseFormat,

0 commit comments

Comments
 (0)