package dev.lions.exceptions; import java.util.Map; import lombok.Builder; import lombok.Getter; import lombok.extern.slf4j.Slf4j; /** * Exception spécialisée pour la gestion des erreurs d'initialisation. * Cette classe traite les erreurs survenant lors de l'initialisation * des composants, services et ressources de l'application. * * @author Lions Dev Team * @version 1.0 */ @Slf4j public class InitializationException extends BusinessException { private static final long serialVersionUID = 1L; /** * Contexte détaillé de l'erreur d'initialisation */ private final InitializationContext context; /** * Phase d'initialisation durant laquelle l'erreur est survenue */ private final InitializationPhase phase; /** * Crée une nouvelle instance avec un message d'erreur simple. * * @param message Description de l'erreur */ public InitializationException(String message) { this(message, null, null, null); log.error("Erreur d'initialisation : {}", message); } /** * Crée une nouvelle instance avec un message et une cause. * * @param message Description de l'erreur * @param cause Exception à l'origine de l'erreur */ public InitializationException(String message, Throwable cause) { this(message, cause, null, null); log.error("Erreur d'initialisation : {}", message, cause); } /** * Crée une nouvelle instance avec tous les détails de l'erreur. * * @param message Description de l'erreur * @param cause Exception à l'origine de l'erreur * @param context Contexte de l'initialisation * @param phase Phase d'initialisation */ public InitializationException(String message, Throwable cause, InitializationContext context, InitializationPhase phase) { super(message, cause); this.context = context; this.phase = phase; log.error("Erreur d'initialisation détaillée : {} - Phase : {} - Contexte : {}", message, phase, context); } /** * Récupère le contexte de l'erreur d'initialisation. * * @return Contexte de l'erreur ou null si non disponible */ public InitializationContext getContext() { return context; } /** * Récupère la phase d'initialisation. * * @return Phase d'initialisation ou null si non disponible */ public InitializationPhase getPhase() { return phase; } /** * Représente les différentes phases d'initialisation possibles. */ public enum InitializationPhase { CONFIGURATION("Configuration"), RESOURCE_LOADING("Chargement des ressources"), DATABASE("Base de données"), DEPENDENCY_INJECTION("Injection de dépendances"), SECURITY("Sécurité"), CACHE("Cache"), SERVICE_STARTUP("Démarrage des services"); private final String description; InitializationPhase(String description) { this.description = description; } public String getDescription() { return description; } } /** * Classe interne représentant le contexte d'une erreur d'initialisation. */ @Getter @Builder public static class InitializationContext { private final String componentName; private final String resourceName; private final String configurationKey; private final String expectedState; private final String actualState; private final Map additionalInfo; @Override public String toString() { StringBuilder sb = new StringBuilder() .append("InitializationContext[") .append("component=").append(componentName) .append(", resource=").append(resourceName) .append(", config=").append(configurationKey); if (expectedState != null) { sb.append(", expected=").append(expectedState); } if (actualState != null) { sb.append(", actual=").append(actualState); } if (additionalInfo != null && !additionalInfo.isEmpty()) { sb.append(", info=").append(additionalInfo); } return sb.append("]").toString(); } } /** * Crée une exception pour une ressource manquante. * * @param resourceName Nom de la ressource * @param componentName Nom du composant * @return Instance de InitializationException */ public static InitializationException resourceNotFound(String resourceName, String componentName) { String message = String.format( "Ressource requise '%s' non trouvée pour le composant '%s'", resourceName, componentName ); InitializationContext context = InitializationContext.builder() .componentName(componentName) .resourceName(resourceName) .build(); return new InitializationException(message, null, context, InitializationPhase.RESOURCE_LOADING); } /** * Crée une exception pour une configuration invalide. * * @param key Clé de configuration * @param expectedValue Valeur attendue * @param actualValue Valeur actuelle * @return Instance de InitializationException */ public static InitializationException invalidConfiguration(String key, String expectedValue, String actualValue) { String message = String.format( "Configuration invalide pour '%s'. Attendu : %s, Actuel : %s", key, expectedValue, actualValue ); InitializationContext context = InitializationContext.builder() .configurationKey(key) .expectedState(expectedValue) .actualState(actualValue) .build(); return new InitializationException(message, null, context, InitializationPhase.CONFIGURATION); } /** * Crée une exception pour un échec de démarrage de service. * * @param serviceName Nom du service * @param reason Raison de l'échec * @return Instance de InitializationException */ public static InitializationException serviceStartupFailure(String serviceName, String reason) { String message = String.format( "Échec du démarrage du service '%s' : %s", serviceName, reason ); InitializationContext context = InitializationContext.builder() .componentName(serviceName) .additionalInfo(Map.of("reason", reason)) .build(); return new InitializationException(message, null, context, InitializationPhase.SERVICE_STARTUP); } }