private EtatInfos Ajouter( EtatInfos etatInfos) { try { etatInfos.EstActif = true; using (lockeur.RecupererLockEcriture()) { #if DEBUG if (dicoEtatsInfos.ContainsKey(etatInfos.EtatOrigine)) { // L'état est déjà dans l'arbre => erreur throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage()); } #endif dicoEtatsInfos .Add( etatInfos.EtatOrigine, etatInfos); return(etatInfos); } } catch (Exception ex) { throw EncapsulerEtGererException <ExceptionTechniqueArbreConstruction>( ex); } }
private EtatInfos AjouterEtatEtSesInfos() { try { EtatInfos etatInfos = CreerEtatEtSesInfos(); return(Ajouter( etatInfos)); } catch (Exception ex) { throw EncapsulerEtGererException <ExceptionTechniqueArbreConstruction>( ex); } }
private EtatInfos CreerEtatEtSesInfos() { try { var etat = new Etat(); var etatInfos = new EtatInfos( etat); return(etatInfos); } catch (Exception ex) { throw EncapsulerEtGererException <ExceptionTechniqueArbreConstruction>( ex); } }
private Etat AjouterEtatDansConstructeur() { try { var etat = new Etat(); var etatInfos = new EtatInfos( etat); etatInfos.EstActif = true; dicoEtatsInfos .Add( etat, etatInfos); return(etat); } catch (Exception ex) { throw EncapsulerEtGererException <ExceptionTechniqueArbreConstruction>( ex); } }
internal EtatInfos RecupererInfos( Etat etat) { try { EtatInfos etatInfos = null; using (lockeur.RecupererLockLecture()) { dicoEtatsInfos .TryGetValue( etat, out etatInfos); } return(etatInfos); } catch (Exception ex) { throw EncapsulerEtGererException <ExceptionTechniqueArbreConstruction>( ex); } }
public void Etiquetter( string id, EnumTypeBlock typeBlock, Etat etatEntree, Etat etatSortie) { try { // Récupération des infos sur les états en entrée et en sortie EtatInfos etatInfosEntree = null, etatInfosSortie = null; using (lockeur.RecupererLockLecture()) { bool etatEntreeDansArbre = dicoEtatsInfos .TryGetValue( etatEntree, out etatInfosEntree); bool etatSortieDansArbre = dicoEtatsInfos .TryGetValue( etatSortie, out etatInfosSortie); if (!etatEntreeDansArbre || !etatSortieDansArbre) { throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage()); } } // Note : on lève le verrou sur le dico pour maintenir les performances. On vérifie plus loin que les états existent encore (après les avoir lockés)... // Lock sur les états source et cible en évitant les inter-locks : lock toujours dans le même ordre var lockeurs = RecupererLockeurs( etatInfosEntree, etatInfosSortie); using (lockeurs[0].RecupererLockEcriture()) { if (!etatInfosEntree.EstActif) { throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage()); } etatEntree.Etiquette = new EtiquetteDto( id, typeBlock, EnumExtremiteEtiquette.Entree); etatInfosEntree .InterdireTransitionSortante(); } if (lockeurs.Length == 2) { using (lockeurs[1].RecupererLockEcriture()) { if (!etatInfosSortie.EstActif) { throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage()); } etatSortie.Etiquette = new EtiquetteDto( id, typeBlock, EnumExtremiteEtiquette.Sortie); etatInfosSortie .InterdireTransitionEntrante(); } } } catch (Exception ex) { throw EncapsulerEtGererException <ExceptionTechniqueArbreConstruction>( ex); } }
public Transition AjouterTransition( Etat etatSource, Etat etatCible, char?symbole) { try { // Récupération des infos sur les états source et cible EtatInfos etatInfosSource = null, etatInfosCible = null; using (lockeur.RecupererLockLecture()) { bool etatSourceDansArbre = dicoEtatsInfos .TryGetValue( etatSource, out etatInfosSource); bool etatCibleDansArbre = dicoEtatsInfos .TryGetValue( etatCible, out etatInfosCible); if (!etatSourceDansArbre || !etatCibleDansArbre) { throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage()); } } // Note : on lève le verrou sur le dico pour maintenir les performances. On vérifie plus loin que les états existent encore (après les avoir lockés)... // Lock sur les états source et cible en évitant les inter-locks : lock toujours dans le même ordre var lockeurs = RecupererLockeurs( etatInfosSource, etatInfosCible); using (lockeurs[0].RecupererLockEcriture()) { using ((lockeurs.Length == 2 ? lockeurs[1] : new LockEcritureEtLectureFake()) // Si la transition est récursive, alors Fake .RecupererLockEcriture()) { // Les états source et cible sont-ils encore dans l'arbre ? (vérification pour se prémunir dans un environnement multi-threads) if (!etatInfosSource.EstActif || !etatInfosCible.EstActif) { // L'état source et/ou l'état cible n'existe(nt) plus dans l'arbre => erreur throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage()); } // La transition existe t'elle déjà ? var transition = new Transition( etatSource, etatCible, symbole); var etatSourceTransitionsSortantes = etatInfosSource.TransitionsSortantes; var transitionEquivalente = etatSourceTransitionsSortantes .RecupererTransitionEquivalente(transition); if (null != transitionEquivalente) { // La transition existe déjà => pas d'ajout // RDG 1 : Il ne peut y avoir qu'une seule transition pour un état cible et un symbole (même vide) donné, pour un état source. return(transitionEquivalente); } else { // La transition n'existe pas encore => ajout if (!etatInfosSource.AjoutTransitionSortantePossible) { throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage( $"L'ajout d'une transition sortante sur l'état {etatInfosCible.EtatOrigine.Identifiant} est interdit")); } if (!etatInfosCible.AjoutTransitionEntrantePossible) { throw new ExceptionTechniqueArbreConstruction( ExceptionBase.RecupererLibelleMessage( $"L'ajout d'une transition entrante sur l'état {etatInfosCible.EtatOrigine.Identifiant} est interdit")); } if (symbole.HasValue) { // Ajout d'une transition avec symbole // Le symbole existe t'il déjà sur une transition sortante ? // RDG 2 : Un état ne doit avoir qu'une transition sortante par symbole. // RDG 3 : Il peut y avoir plusieurs transitions sans symbole vers des états différents. transitionEquivalente = etatSourceTransitionsSortantes .RecupererTransitionAvecSymbole( symbole.Value); if (null != transitionEquivalente) { // Une transition existe déjà avec le même symbole (vers un autre état) => reconstruction pour respecter les RDG // Création d'un état intermédiaire qui deviendra la cible du symbole. // Il sera également la source de transitions sans symbole : // - vers l'état ciblé par la transition équivalente // - et l'état ciblé en paramètre. var etatCibleSurEquivalence = transitionEquivalente.EtatCible; var etatInfosIntermediaire = CreerEtatEtSesInfos(); // Création de l'état intermédiaire sans l'ajouter dans l'arbre, ce qui permet de le locker var etatIntermediaire = etatInfosIntermediaire.EtatOrigine; var etatIntermediaireTransitionsSortantes = etatInfosIntermediaire.TransitionsSortantes; // Préparation des transitions var transitionIntermediaire = new Transition( etatSource, etatIntermediaire, symbole.Value); var transitionVersEtatCibleOrigine = new Transition( etatIntermediaire, etatCibleSurEquivalence); var transitionVersEtatCible = new Transition( etatIntermediaire, etatCible); // Ajout de l'état intermédiaire et des transitions dans l'arbre using (etatInfosIntermediaire.Lockeur.RecupererLockEcriture()) { Ajouter( etatInfosIntermediaire); etatIntermediaireTransitionsSortantes .Ajouter(transitionVersEtatCibleOrigine) .Ajouter(transitionVersEtatCible); etatSourceTransitionsSortantes .Supprimer(transitionEquivalente) .Ajouter(transitionIntermediaire); } return(transitionVersEtatCible); } else { // Transition avec symbole, le symbole n'est pas encore déclaré => ajout } } else { // Transition sans symbole vers un état pas encore ciblé => ajout } // Ajout de la transition etatSourceTransitionsSortantes .Ajouter(transition); return(transition); } } } } catch (Exception ex) { throw EncapsulerEtGererException <ExceptionTechniqueArbreConstruction>( ex); } }