Skip to content

Commit 51604e4

Browse files
committed
refactor: Address SonarQube code smells across new packages
1 parent 123c301 commit 51604e4

14 files changed

Lines changed: 82 additions & 69 deletions

src/main/java/com/retailsvc/http/Handlers.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public static ExceptionHandler defaultExceptionHandler() {
2929
exchange.sendResponseHeaders(HTTP_BAD_REQUEST, body.length);
3030
exchange.getResponseBody().write(body);
3131
}
32-
case NotFoundException nf -> exchange.sendResponseHeaders(HTTP_NOT_FOUND, 0);
32+
case NotFoundException _ -> exchange.sendResponseHeaders(HTTP_NOT_FOUND, 0);
3333
case MethodNotAllowedException mna -> {
3434
String allow = mna.allowed().stream().map(Enum::name).collect(Collectors.joining(", "));
3535
exchange.getResponseHeaders().add("Allow", allow);

src/main/java/com/retailsvc/http/ValidationException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.retailsvc.http.validate.ValidationError;
44

55
public final class ValidationException extends RuntimeException {
6-
private final ValidationError error;
6+
private final transient ValidationError error;
77

88
public ValidationException(ValidationError error) {
99
super(error.pointer() + " [" + error.keyword() + "] " + error.message());

src/main/java/com/retailsvc/http/internal/ProblemDetailRenderer.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,16 @@ public final class ProblemDetailRenderer {
1414
private static final String PROBLEM_TITLE = "Bad Request";
1515
private static final int PROBLEM_STATUS = 400;
1616

17+
/** Initial capacity of the JSON buffer; sized for a typical problem-detail document. */
18+
private static final int INITIAL_BUFFER_CAPACITY = 128;
19+
1720
/** Codepoints below this value are control characters and must be unicode-escaped in JSON. */
1821
private static final int FIRST_PRINTABLE_ASCII = 0x20;
1922

2023
private ProblemDetailRenderer() {}
2124

2225
public static String render(ValidationError error) {
23-
StringBuilder out = new StringBuilder(128);
26+
StringBuilder out = new StringBuilder(INITIAL_BUFFER_CAPACITY);
2427
out.append('{');
2528
appendStringField(out, "type", PROBLEM_TYPE);
2629
out.append(',');

src/main/java/com/retailsvc/http/spec/Spec.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public record Spec(
1818
Map<String, Schema> componentSchemas,
1919
Map<String, Parameter> componentParameters) {
2020

21+
private static final String SCHEMA_KEY = "schema";
22+
2123
@SuppressWarnings("unchecked")
2224
public static Spec from(Map<String, Object> raw) {
2325
String openapi = (String) raw.get("openapi");
@@ -106,7 +108,7 @@ private static Parameter parseParameter(Map<String, Object> raw) {
106108
Parameter.Location.valueOf(((String) raw.get("in")).toUpperCase(Locale.ROOT)),
107109
Boolean.TRUE.equals(raw.get("required")),
108110
SchemaParser.parse(
109-
(Map<String, Object>) raw.getOrDefault("schema", Map.of("type", "string"))));
111+
(Map<String, Object>) raw.getOrDefault(SCHEMA_KEY, Map.of("type", "string"))));
110112
}
111113

112114
@SuppressWarnings("unchecked")
@@ -174,7 +176,7 @@ private static RequestBody parseRequestBody(Map<String, Object> raw) {
174176
e.getKey(),
175177
new MediaType(
176178
SchemaParser.parse(
177-
(Map<String, Object>) mt.getOrDefault("schema", Map.of("type", "object")))));
179+
(Map<String, Object>) mt.getOrDefault(SCHEMA_KEY, Map.of("type", "object")))));
178180
}
179181
return new RequestBody(Boolean.TRUE.equals(raw.get("required")), Map.copyOf(content));
180182
}
@@ -188,10 +190,10 @@ private static Map<String, Response> parseResponses(Map<String, Object> raw) {
188190
Map<String, MediaType> content = new LinkedHashMap<>();
189191
for (var ce : contentRaw.entrySet()) {
190192
Map<String, Object> mt = (Map<String, Object>) ce.getValue();
191-
if (mt.containsKey("schema")) {
193+
if (mt.containsKey(SCHEMA_KEY)) {
192194
content.put(
193195
ce.getKey(),
194-
new MediaType(SchemaParser.parse((Map<String, Object>) mt.get("schema"))));
196+
new MediaType(SchemaParser.parse((Map<String, Object>) mt.get(SCHEMA_KEY))));
195197
}
196198
}
197199
out.put(e.getKey(), new Response(Map.copyOf(content)));

src/main/java/com/retailsvc/http/spec/schema/SchemaParser.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
public final class SchemaParser {
1111
private SchemaParser() {}
1212

13+
private static final String FORMAT_KEY = "format";
14+
1315
@SuppressWarnings("unchecked")
1416
public static Schema parse(Map<String, Object> raw) {
1517
if (raw.containsKey("$ref")) {
@@ -75,7 +77,7 @@ private static StringSchema parseString(Map<String, Object> raw, Set<TypeName> t
7577
(String) raw.get("pattern"),
7678
toIntOrNull(raw.get("minLength")),
7779
toIntOrNull(raw.get("maxLength")),
78-
(String) raw.get("format"),
80+
(String) raw.get(FORMAT_KEY),
7981
(List<String>) raw.get("enum"));
8082
}
8183

@@ -87,7 +89,7 @@ private static IntegerSchema parseInteger(Map<String, Object> raw, Set<TypeName>
8789
toLongOrNull(raw.get("exclusiveMinimum")),
8890
toLongOrNull(raw.get("exclusiveMaximum")),
8991
toLongOrNull(raw.get("multipleOf")),
90-
(String) raw.get("format"));
92+
(String) raw.get(FORMAT_KEY));
9193
}
9294

9395
private static NumberSchema parseNumber(Map<String, Object> raw, Set<TypeName> types) {
@@ -98,7 +100,7 @@ private static NumberSchema parseNumber(Map<String, Object> raw, Set<TypeName> t
98100
(Number) raw.get("exclusiveMinimum"),
99101
(Number) raw.get("exclusiveMaximum"),
100102
(Number) raw.get("multipleOf"),
101-
(String) raw.get("format"));
103+
(String) raw.get(FORMAT_KEY));
102104
}
103105

104106
@SuppressWarnings("unchecked")
@@ -121,13 +123,12 @@ private static ObjectSchema parseObject(Map<String, Object> raw, Set<TypeName> t
121123

122124
@SuppressWarnings("unchecked")
123125
private static AdditionalProperties parseAdditionalProperties(Object value) {
124-
if (value == null || Boolean.TRUE.equals(value)) {
125-
return new AdditionalProperties.Allowed();
126-
}
127-
if (Boolean.FALSE.equals(value)) {
128-
return new AdditionalProperties.Forbidden();
129-
}
130-
return new AdditionalProperties.SchemaConstraint(parse((Map<String, Object>) value));
126+
return switch (value) {
127+
case null -> new AdditionalProperties.Allowed();
128+
case Boolean b when b -> new AdditionalProperties.Allowed();
129+
case Boolean b -> new AdditionalProperties.Forbidden();
130+
default -> new AdditionalProperties.SchemaConstraint(parse((Map<String, Object>) value));
131+
};
131132
}
132133

133134
@SuppressWarnings("unchecked")

src/main/java/com/retailsvc/http/validate/DefaultValidator.java

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.math.BigDecimal;
2222
import java.time.LocalDate;
2323
import java.time.OffsetDateTime;
24+
import java.time.format.DateTimeParseException;
2425
import java.util.ArrayList;
2526
import java.util.HashSet;
2627
import java.util.List;
@@ -46,21 +47,21 @@ public void validate(Object value, Schema schema, String pointer) {
4647

4748
switch (schema) {
4849
case RefSchema r -> validate(value, refResolver.apply(r.pointer()), pointer);
49-
case BooleanSchema b -> validateBoolean(value, pointer);
50-
case NullSchema n -> require(value == null, pointer, "type", "expected null");
50+
case BooleanSchema _ -> validateBoolean(value, pointer);
51+
case NullSchema _ -> require(value == null, pointer, "type", "expected null");
5152
case StringSchema s -> validateString(value, s, pointer);
5253
case IntegerSchema i -> validateInteger(value, i, pointer);
5354
case NumberSchema n -> validateNumber(value, n, pointer);
5455
case ObjectSchema o -> validateObject(value, o, pointer);
5556
case ArraySchema a -> validateArray(value, a, pointer);
56-
case EnumSchema e ->
57-
require(e.values().contains(value), pointer, "enum", "value not in enum");
58-
case ConstSchema c ->
59-
require(Objects.equals(c.value(), value), pointer, "const", "value does not equal const");
60-
case OneOfSchema o -> throw new UnsupportedOperationException("oneOf not yet supported");
61-
case AnyOfSchema a -> throw new UnsupportedOperationException("anyOf not yet supported");
62-
case AllOfSchema a -> throw new UnsupportedOperationException("allOf not yet supported");
63-
case NotSchema n -> throw new UnsupportedOperationException("not not yet supported");
57+
case EnumSchema(List<Object> values) ->
58+
require(values.contains(value), pointer, "enum", "value not in enum");
59+
case ConstSchema(Object expected) ->
60+
require(Objects.equals(expected, value), pointer, "const", "value does not equal const");
61+
case OneOfSchema _ -> throw new UnsupportedOperationException("oneOf not yet supported");
62+
case AnyOfSchema _ -> throw new UnsupportedOperationException("anyOf not yet supported");
63+
case AllOfSchema _ -> throw new UnsupportedOperationException("allOf not yet supported");
64+
case NotSchema _ -> throw new UnsupportedOperationException("not not yet supported");
6465
}
6566
}
6667

@@ -93,42 +94,46 @@ private void validateStringFormat(String str, String format, String pointer) {
9394
case "uuid" -> {
9495
try {
9596
UUID.fromString(str);
96-
} catch (IllegalArgumentException e) {
97+
} catch (IllegalArgumentException _) {
9798
fail(pointer, "format", "not a valid uuid", str);
9899
}
99100
}
100101
case "date" -> {
101102
try {
102103
LocalDate.parse(str);
103-
} catch (Exception e) {
104+
} catch (DateTimeParseException _) {
104105
fail(pointer, "format", "not a valid date", str);
105106
}
106107
}
107108
case "date-time" -> {
108109
try {
109110
OffsetDateTime.parse(str);
110-
} catch (Exception e) {
111+
} catch (DateTimeParseException _) {
111112
fail(pointer, "format", "not a valid date-time", str);
112113
}
113114
}
114-
default -> {}
115+
default -> {
116+
/* unknown format ignored — handled in 3.1 follow-up */
117+
}
115118
}
116119
}
117120

118121
private void validateInteger(Object value, IntegerSchema s, String pointer) {
119122
long n;
120-
if (value instanceof Number num) {
121-
n = num.longValue();
122-
} else if (value instanceof String str) {
123-
try {
124-
n = Long.parseLong(str);
125-
} catch (NumberFormatException e) {
123+
switch (value) {
124+
case Number num -> n = num.longValue();
125+
case String str -> {
126+
try {
127+
n = Long.parseLong(str);
128+
} catch (NumberFormatException _) {
129+
fail(pointer, "type", "expected integer", value);
130+
return;
131+
}
132+
}
133+
case null, default -> {
126134
fail(pointer, "type", "expected integer", value);
127135
return;
128136
}
129-
} else {
130-
fail(pointer, "type", "expected integer", value);
131-
return;
132137
}
133138

134139
if (s.minimum() != null && n < s.minimum()) {
@@ -150,18 +155,20 @@ private void validateInteger(Object value, IntegerSchema s, String pointer) {
150155

151156
private void validateNumber(Object value, NumberSchema s, String pointer) {
152157
double n;
153-
if (value instanceof Number num) {
154-
n = num.doubleValue();
155-
} else if (value instanceof String str) {
156-
try {
157-
n = Double.parseDouble(str);
158-
} catch (NumberFormatException e) {
158+
switch (value) {
159+
case Number num -> n = num.doubleValue();
160+
case String str -> {
161+
try {
162+
n = Double.parseDouble(str);
163+
} catch (NumberFormatException _) {
164+
fail(pointer, "type", "expected number", value);
165+
return;
166+
}
167+
}
168+
case null, default -> {
159169
fail(pointer, "type", "expected number", value);
160170
return;
161171
}
162-
} else {
163-
fail(pointer, "type", "expected number", value);
164-
return;
165172
}
166173

167174
if (s.minimum() != null && n < s.minimum().doubleValue()) {
@@ -219,8 +226,8 @@ private void validateObject(Object value, ObjectSchema s, String pointer) {
219226
validate(entry.getValue(), propSchema, childPointer);
220227
} else {
221228
switch (s.additionalProperties()) {
222-
case AdditionalProperties.Allowed a -> {}
223-
case AdditionalProperties.Forbidden f ->
229+
case AdditionalProperties.Allowed _ -> {}
230+
case AdditionalProperties.Forbidden _ ->
224231
fail(
225232
childPointer,
226233
"additionalProperties",

src/test/java/com/retailsvc/http/JsonMapperTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class JsonMapperTest {
88
@Test
99
void usableAsLambda() {
10-
JsonMapper m = body -> new String(body);
10+
JsonMapper m = String::new;
1111
assertThat(m.mapFrom("hello".getBytes())).isEqualTo("hello");
1212
}
1313
}

src/test/java/com/retailsvc/http/OpenApiServerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ void shouldStartHttpServerWithValidConfiguration() {
2525

2626
assertDoesNotThrow(
2727
() -> {
28-
try (var ignore = new OpenApiServer(validSpec, jsonMapper, handlers, onError, 0)) {
28+
try (var _ = new OpenApiServer(validSpec, jsonMapper, handlers, onError, 0)) {
2929
// also close on exit
3030
}
3131
});

src/test/java/com/retailsvc/http/internal/DispatchHandlerTest.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,11 @@
66
import com.retailsvc.http.Request;
77
import com.sun.net.httpserver.HttpExchange;
88
import com.sun.net.httpserver.HttpHandler;
9-
import java.util.HashMap;
109
import java.util.Map;
1110
import org.junit.jupiter.api.Test;
1211
import org.mockito.Mockito;
1312

1413
class DispatchHandlerTest {
15-
private final Map<String, Object> attrs = new HashMap<>();
16-
1714
private HttpExchange exchange(String operationId) {
1815
HttpExchange ex = Mockito.mock(HttpExchange.class);
1916
Mockito.when(ex.getAttribute(Request.OPERATION_ID)).thenReturn(operationId);
@@ -30,7 +27,7 @@ void invokesRegisteredHandler() throws Exception {
3027
@Test
3128
void throwsWhenHandlerMissing() {
3229
DispatchHandler d = new DispatchHandler(Map.of());
33-
assertThatThrownBy(() -> d.handle(exchange("ghost")))
34-
.isInstanceOf(MissingOperationHandlerException.class);
30+
HttpExchange ex = exchange("ghost");
31+
assertThatThrownBy(() -> d.handle(ex)).isInstanceOf(MissingOperationHandlerException.class);
3532
}
3633
}

src/test/java/com/retailsvc/http/internal/RequestPreparationFilterTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void successPathSetsAttributes() throws Exception {
6464
List.of(),
6565
Map.of());
6666
Spec spec = specWith(op);
67-
JsonMapper m = body -> new String(body);
67+
JsonMapper m = String::new;
6868
Filter f =
6969
new RequestPreparationFilter(
7070
spec, new Router(spec.operations()), new DefaultValidator(spec::resolveSchema), m);
@@ -90,7 +90,7 @@ void unknownPathThrowsNotFound() {
9090
Optional.empty(),
9191
List.of(),
9292
Map.of()));
93-
JsonMapper m = body -> new String(body);
93+
JsonMapper m = String::new;
9494
Filter f =
9595
new RequestPreparationFilter(
9696
spec, new Router(spec.operations()), new DefaultValidator(spec::resolveSchema), m);
@@ -111,7 +111,7 @@ void wrongMethodThrowsMethodNotAllowed() {
111111
Optional.empty(),
112112
List.of(),
113113
Map.of()));
114-
JsonMapper m = body -> new String(body);
114+
JsonMapper m = String::new;
115115
Filter f =
116116
new RequestPreparationFilter(
117117
spec, new Router(spec.operations()), new DefaultValidator(spec::resolveSchema), m);
@@ -133,7 +133,7 @@ void invalidQueryParamThrowsValidation() {
133133
List.of(new Parameter("q", Parameter.Location.QUERY, true, stringSchema)),
134134
Map.of());
135135
Spec spec = specWith(op);
136-
JsonMapper m = body -> new String(body);
136+
JsonMapper m = String::new;
137137
Filter f =
138138
new RequestPreparationFilter(
139139
spec, new Router(spec.operations()), new DefaultValidator(spec::resolveSchema), m);

0 commit comments

Comments
 (0)