2026-01-16 15:27:09 -04:00

207 lines
7.3 KiB
Java

package com.banesco.common.application.helper;
import com.banesco.common.domain.exception.HttpStatusCodeException;
import com.banesco.common.domain.model.ApiResponse;
import com.banesco.common.domain.model.ErrorMapping;
import com.banesco.common.domain.model.StatusResponse;
import com.banesco.common.infrastructure.config.MessagesConfig;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.runtime.annotations.RegisterForReflection;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@ApplicationScoped
@RegisterForReflection
public class MessageHelper {
private final MessagesConfig messagesConfig;
private final Map<String, ErrorMapping> errorMappings;
private static final String ERROR_DEFAULT = "default";
private static final String SUCCESS_DEFAULT = "200";
private static final String ERROR_FILE_PATH = "errors-mapping/errors.json";
private final ObjectMapper objectMapper;
@Inject
public MessageHelper(
ObjectMapper objectMapper,
MessagesConfig messagesConfig
) {
this.objectMapper = objectMapper;
this.messagesConfig = messagesConfig;
this.errorMappings = initializeErrorMappings();
}
public Response handleException(HttpStatusCodeException exception) {
log.error(
"Error interno controlado: {} -> {}",
exception.getStatusCode(),
exception.getErrorCode()
);
return buildErrorResponse(exception);
}
public Response handleGenericException(Exception exception) {
log.error("Error interno no controlado: {}", exception.getMessage());
return buildErrorResponse(HttpStatusCodeException.internalServer("500"));
}
public StatusResponse createStatusResponse(String code) {
ErrorMapping successMapping = getError(code);
return StatusResponse.builder()
.statusCode(successMapping.getStatusCode())
.message(successMapping.getDescription())
.build();
}
public StatusResponse createError(
ErrorMapping mapping,
String fieldPath
) {
String message = mapping.getDescription();
if (fieldPath != null && message != null && message.contains("%s")) {
message = String.format(message, fieldPath);
}
return StatusResponse.builder()
.statusCode(mapping.getStatusCode())
.message(message)
.build();
}
public <T> ApiResponse<T> buildServiceUnavailableResponse() {
return new ApiResponse<>(createStatusResponse("503"));
}
private ErrorMapping getError(String errorCode) {
return errorMappings.getOrDefault(
errorCode, errorMappings.getOrDefault(ERROR_DEFAULT, createDefaultMapping())
);
}
private Response buildErrorResponse(HttpStatusCodeException exception) {
ErrorMapping mapping = errorMappings.getOrDefault(
exception.getErrorCode(), errorMappings.getOrDefault(
String.valueOf(exception.getStatusCode()),
createDefaultMapping()
)
);
StatusResponse status = createError(mapping, exception.getFieldPath());
log.error(
"[{}] Message {} -> {}",
exception.getExceptionType(),
exception.getErrorCode(),
status.getMessage()
);
return Response.status(mapping.getHttpCode())
.entity(new ApiResponse<>(status))
.build();
}
private Map<String, ErrorMapping> initializeErrorMappings() {
try {
String json;
if (isReadingFromProps()) {
json = messagesConfig.getErrorMessagesJson();
log.info("Cargando mensajes de errores desde properties");
} else {
json = loadFromJsonFile();
log.info("Cargando mensajes de errores desde archivo JSON");
}
if (json == null || json.isEmpty()) {
log.warn("No se encontro JSON de errores");
return createDefaultMappings();
}
List<ErrorMapping> mappings = objectMapper.readValue(json, new TypeReference<List<ErrorMapping>>() {});
Map<String, ErrorMapping> result = new ConcurrentHashMap<>();
for (ErrorMapping mapping : mappings) {
if (mapping.getBackendCode() != null && !mapping.getBackendCode().trim().isEmpty()) {
if (result.containsKey(mapping.getBackendCode())) {
log.warn("Clave duplicada encontrada en mappings de errores: {}", mapping.getBackendCode());
} else {
result.put(mapping.getBackendCode(), mapping);
}
} else {
log.warn("Ignorando mapping sin backendCode valido: {}", mapping.getDescription());
}
}
log.info("Mappings de errores cargados exitosamente, total validos: {}", result.size());
return result;
} catch (Exception e) {
log.error("Error cargando mappings de errores: {}", e.getMessage());
return createDefaultMappings();
}
}
private String loadFromJsonFile() {
try (InputStream is = MessageHelper.class.getClassLoader().getResourceAsStream(ERROR_FILE_PATH)) {
if (is == null) {
log.warn("No se encontro el archivo de errores: {}", ERROR_FILE_PATH);
return "";
}
return new String(is.readAllBytes());
} catch (Exception e) {
log.error("Error leyendo archivo de errores: {}", e.getMessage());
return "";
}
}
private Map<String, ErrorMapping> createDefaultMappings() {
Map<String, ErrorMapping> defaults = new ConcurrentHashMap<>();
defaults.put(ERROR_DEFAULT, createDefaultMapping());
defaults.put(SUCCESS_DEFAULT, createSuccessMapping());
return defaults;
}
private ErrorMapping createDefaultMapping() {
ErrorMapping mapping = new ErrorMapping();
mapping.setBackendCode(ERROR_DEFAULT);
mapping.setHttpCode(409);
mapping.setStatusCode("409");
mapping.setDescription("Conflicto");
return mapping;
}
private ErrorMapping createSuccessMapping() {
ErrorMapping mapping = new ErrorMapping();
mapping.setBackendCode(SUCCESS_DEFAULT);
mapping.setHttpCode(200);
mapping.setStatusCode("200");
mapping.setDescription("Operacion exitosa");
return mapping;
}
public boolean isReadingFromProps() {
return messagesConfig.isReadFromProps();
}
public boolean isSuccessStatusCode(StatusResponse statusResponse) {
if (statusResponse == null || statusResponse.getStatusCode() == null) {
return false;
}
try {
int statusCode = Integer.parseInt(statusResponse.getStatusCode());
return statusCode >= 200 && statusCode < 300;
} catch (NumberFormatException e) {
return false;
}
}
}