|
4 | 4 | import com.fasterxml.jackson.databind.JsonNode; |
5 | 5 | import com.fasterxml.jackson.databind.ObjectMapper; |
6 | 6 | import io.facturapi.FacturapiException; |
7 | | -import io.facturapi.models.ApiError; |
8 | 7 | import java.io.IOException; |
9 | 8 | import java.io.InputStream; |
10 | 9 | import java.net.URI; |
@@ -147,7 +146,7 @@ private InputStream requestStream(String method, String path, Object body) { |
147 | 146 | responseBytes = errorStream == null ? new byte[0] : errorStream.readAllBytes(); |
148 | 147 | } |
149 | 148 | String bodyText = responseBytes.length == 0 ? "" : new String(responseBytes, StandardCharsets.UTF_8); |
150 | | - throw new FacturapiException(parseApiError(bodyText, statusCode), bodyText); |
| 149 | + throw buildApiException(bodyText, statusCode); |
151 | 150 | } |
152 | 151 | return response.body(); |
153 | 152 | } catch (IOException e) { |
@@ -202,64 +201,67 @@ private static JsonNode firstDefined(JsonNode node, String... keys) { |
202 | 201 | return null; |
203 | 202 | } |
204 | 203 |
|
205 | | - private ApiError parseApiError(String bodyText, int statusCode) { |
206 | | - ApiError apiError = null; |
| 204 | + private FacturapiException buildApiException(String bodyText, int statusCode) { |
| 205 | + int resolvedStatus = statusCode; |
| 206 | + Object errorCode = null; |
| 207 | + String errorPath = null; |
| 208 | + String message = "Request failed with status " + statusCode; |
| 209 | + |
207 | 210 | if (bodyText != null && !bodyText.isBlank()) { |
208 | 211 | try { |
209 | | - apiError = objectMapper.readValue(bodyText, ApiError.class); |
210 | | - } catch (Exception ignored) { |
211 | | - try { |
212 | | - JsonNode error = objectMapper.readTree(bodyText); |
213 | | - apiError = new ApiError(); |
214 | | - |
215 | | - JsonNode messageNode = firstDefined(error, "message", "error", "detail"); |
| 212 | + JsonNode root = objectMapper.readTree(bodyText); |
| 213 | + if (root != null) { |
| 214 | + JsonNode messageNode = firstDefined(root, "message", "error", "detail"); |
216 | 215 | if (messageNode != null && messageNode.isTextual()) { |
217 | | - apiError.setMessage(messageNode.asText()); |
| 216 | + message = messageNode.asText(); |
| 217 | + } else if (root.isTextual()) { |
| 218 | + message = root.asText(); |
218 | 219 | } else { |
219 | | - apiError.setMessage(bodyText); |
| 220 | + message = bodyText; |
220 | 221 | } |
221 | 222 |
|
222 | | - JsonNode statusNode = firstDefined(error, "status"); |
| 223 | + JsonNode statusNode = firstDefined(root, "status"); |
223 | 224 | if (statusNode != null) { |
224 | | - apiError.setStatus(statusNode); |
| 225 | + if (statusNode.isIntegralNumber()) { |
| 226 | + resolvedStatus = statusNode.intValue(); |
| 227 | + } else if (statusNode.isNumber()) { |
| 228 | + resolvedStatus = (int) Math.round(statusNode.asDouble()); |
| 229 | + } else if (statusNode.isTextual()) { |
| 230 | + try { |
| 231 | + resolvedStatus = Integer.parseInt(statusNode.asText()); |
| 232 | + } catch (NumberFormatException ignored) { |
| 233 | + resolvedStatus = statusCode; |
| 234 | + } |
| 235 | + } |
225 | 236 | } |
226 | 237 |
|
227 | | - JsonNode codeNode = firstDefined(error, "code"); |
228 | | - if (codeNode != null) { |
229 | | - apiError.setCode(codeNode); |
| 238 | + JsonNode codeNode = firstDefined(root, "code"); |
| 239 | + if (codeNode != null && !codeNode.isNull()) { |
| 240 | + if (codeNode.isTextual()) { |
| 241 | + errorCode = codeNode.asText(); |
| 242 | + } else if (codeNode.isIntegralNumber()) { |
| 243 | + errorCode = codeNode.intValue(); |
| 244 | + } else if (codeNode.isNumber()) { |
| 245 | + errorCode = codeNode.numberValue(); |
| 246 | + } else if (codeNode.isBoolean()) { |
| 247 | + errorCode = codeNode.asBoolean(); |
| 248 | + } else { |
| 249 | + errorCode = codeNode.toString(); |
| 250 | + } |
230 | 251 | } |
231 | 252 |
|
232 | | - JsonNode pathNode = firstDefined(error, "path"); |
| 253 | + JsonNode pathNode = firstDefined(root, "path"); |
233 | 254 | if (pathNode != null && pathNode.isTextual()) { |
234 | | - apiError.setPath(pathNode.asText()); |
| 255 | + errorPath = pathNode.asText(); |
235 | 256 | } |
236 | 257 |
|
237 | | - JsonNode okNode = firstDefined(error, "ok"); |
238 | | - if (okNode != null && okNode.isBoolean()) { |
239 | | - apiError.setOk(okNode.asBoolean()); |
240 | | - } |
241 | | - } catch (Exception secondaryIgnored) { |
242 | | - apiError = new ApiError(); |
243 | | - apiError.setMessage(bodyText.isBlank() ? "Request failed with status " + statusCode : bodyText); |
244 | 258 | } |
| 259 | + } catch (Exception ignored) { |
| 260 | + message = bodyText.isBlank() ? message : bodyText; |
245 | 261 | } |
246 | 262 | } |
247 | 263 |
|
248 | | - if (apiError == null) { |
249 | | - apiError = new ApiError(); |
250 | | - apiError.setMessage("Request failed with status " + statusCode); |
251 | | - } |
252 | | - |
253 | | - if (apiError.getMessage() == null || apiError.getMessage().isBlank()) { |
254 | | - apiError.setMessage("Request failed with status " + statusCode); |
255 | | - } |
256 | | - if (apiError.getStatus() == null) { |
257 | | - apiError.setStatus(statusCode); |
258 | | - } |
259 | | - if (!apiError.isOk()) { |
260 | | - apiError.setOk(false); |
261 | | - } |
262 | | - return apiError; |
| 264 | + return new FacturapiException(message, resolvedStatus, errorCode, errorPath); |
263 | 265 | } |
264 | 266 |
|
265 | 267 | private HttpRequest buildRequest( |
@@ -295,7 +297,7 @@ private void validateResponse(HttpResponse<byte[]> response) { |
295 | 297 | int statusCode = response.statusCode(); |
296 | 298 | if (statusCode < 200 || statusCode >= 300) { |
297 | 299 | String bodyText = response.body() == null ? "" : new String(response.body(), StandardCharsets.UTF_8); |
298 | | - throw new FacturapiException(parseApiError(bodyText, statusCode), bodyText); |
| 300 | + throw buildApiException(bodyText, statusCode); |
299 | 301 | } |
300 | 302 | } |
301 | 303 |
|
|
0 commit comments