/// <summary> /// Clone une action pour qu'elle soit utilisée dans un nouveau scénario. /// </summary> /// <param name="action">The action.</param> /// <param name="cloneBehavior">The clone behavior.</param> /// <returns></returns> public static KAction CloneAction(KAction action, ActionCloneBehavior cloneBehavior) { var newAction = new KAction(); var originalValues = action.GetCurrentValues(); // Ignorer certaines propriétés var excludedPropertyNames = new List <string> { "ActionId", "ScenarioId", "OriginalActionId", "Predecessors", "Successors", "Reduced" }; // Quand on passe vers un scénario de validation, il ne faut pas copier la vignette car on supprime les leins avec les vidéos if (cloneBehavior == ActionCloneBehavior.TargetToRealized) { excludedPropertyNames.Add("Thumbnail"); excludedPropertyNames.Add("IsThumbnailSpecific"); excludedPropertyNames.Add("ThumbnailPosition"); } // Vérifier que ces noms de propriétés soient corrects if (excludedPropertyNames.Except(originalValues.Keys).Any()) { throw new InvalidOperationException("Les noms de propriétés présents dans excludedPropertyNames ne sont pas valides."); } foreach (var kvp in originalValues) { if (!excludedPropertyNames.Contains(kvp.Key)) { newAction.SetPropertyValue(kvp.Key, kvp.Value); } } // Copier les liens actions / référentiel CloneReferentialActionsLinks(action, newAction); // Copier la partie Reduced switch (cloneBehavior) { case ActionCloneBehavior.InitialToTarget: { // S'il existe un prétypage par la catégorie, il est prioritaire. Sinon, utiliser celui sur l'action s'il y en a. string actionTypeCode; if (action.Category != null && action.Category.ActionTypeCode != null) { actionTypeCode = action.Category.ActionTypeCode; } else { actionTypeCode = action.IsReduced ? action.Reduced.ActionTypeCode : KnownActionCategoryTypes.I; } SharedScenarioActionsOperations.ApplyNewReduced(newAction, actionTypeCode); } break; case ActionCloneBehavior.TargetToTarget: if (action.Reduced.ActionTypeCode == null) { throw new InvalidOperationException("Une action cible doit toujours être réduite avec un type"); } if (!ActionsTimingsMoveManagement.GetIsSolutionApproved(action).GetValueOrDefault(true)) { // Tache I provenant du grand parent, on n'applique pas le prétype mais on applique la réduc SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.I); } else { switch (action.Reduced.ActionTypeCode) { case KnownActionCategoryTypes.I: // Déterminer si la tâche provient d'un scénario ancêtre if (action.OriginalActionId != null) { // Tache I provenant du grand parent, on n'applique pas le prétype mais on applique la réduc SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.I); } else { // Tache I provenant du parent, on applique le prétypage et la réduc s'il y en a string actionTypeCode; if (action.Category != null && action.Category.ActionTypeCode != null) { actionTypeCode = action.Category.ActionTypeCode; } else { actionTypeCode = KnownActionCategoryTypes.I; } SharedScenarioActionsOperations.ApplyNewReduced(newAction, actionTypeCode); } break; case KnownActionCategoryTypes.E: // Tâche E, on conserve E et on applique la réduc SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.E); break; case KnownActionCategoryTypes.S: SharedScenarioActionsOperations.ApplyReduced(action, newAction); break; default: throw new ArgumentOutOfRangeException(nameof(action), new ArgumentOutOfRangeException(nameof(KAction.Reduced), new ArgumentOutOfRangeException(nameof(KActionReduced.ActionTypeCode)))); } } break; case ActionCloneBehavior.TargetToRealized: // Pour les tâches externes, il faut les faire réapparaitre comme externes // Pour les tâches internes, il faut qu'elle aient une partie réduite pour pouvoir les repasser à exerne. switch (action.Reduced.ActionTypeCode) { case KnownActionCategoryTypes.I: SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.I); break; case KnownActionCategoryTypes.E: SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.E); break; } break; case ActionCloneBehavior.Cascade: SharedScenarioActionsOperations.ApplyReduced(action, newAction); break; case ActionCloneBehavior.RealizedToNewInitial: case ActionCloneBehavior.TargetToNewInitial: case ActionCloneBehavior.InitialToNewInitial: // Pour les tâches externes, il faut les faire réapparaitre comme externes // Pour les tâches internes, il faut qu'elle aient une partie réduite pour pouvoir les repasser à exerne. if (action.Reduced != null) { switch (action.Reduced.ActionTypeCode) { case KnownActionCategoryTypes.I: SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.I); break; case KnownActionCategoryTypes.E: SharedScenarioActionsOperations.ApplyNewReduced(newAction, KnownActionCategoryTypes.E); break; } } break; default: throw new ArgumentOutOfRangeException(nameof(cloneBehavior)); } return(newAction); }