// Constructors /// <summary> /// Initializes new instance of this type. /// </summary> /// <exception cref="InvalidOperationException">No current Comparer.</exception> public UpgradeContext() { Upgrader = Upgrader.Current; if (Upgrader == null) { throw new InvalidOperationException(Strings.ExNoCurrentUpgrader); } Parent = Upgrader.Context; if (Parent == null) { PreConditions = new GroupingNodeAction(); Actions = new GroupingNodeAction() { Comment = Upgrader.Stage.ToString() }; Renames = new GroupingNodeAction(); PostConditions = new GroupingNodeAction(); return; } Difference = Parent.Difference; Property = Parent.Property; IsImmutable = Parent.IsImmutable; IsRemoved = Parent.IsRemoved; DependencyRootType = Parent.DependencyRootType; PreConditions = Parent.PreConditions; Actions = Parent.Actions; Renames = Parent.Renames; PostConditions = Parent.PostConditions; }
/// <summary> /// Generate actions for specific <see cref="UpgradeStage"/>. /// </summary> /// <param name="stage">The stage.</param> /// <param name="action">The parent action.</param> protected void ProcessStage(UpgradeStage stage, GroupingNodeAction action) { Stage = stage; if (stage == UpgradeStage.Upgrade) { UpdateHints(); Difference = Comparer.Compare(CurrentModel, TargetModel, Hints); } var stageActions = Visit(Difference); if (stageActions != null) { action.Add(stageActions); } CoreLog.Info(string.Format("Stage {0} complete.", stage)); }
/// <inheritdoc/> /// <exception cref="ArgumentOutOfRangeException"><c>hints.SourceModel</c> or <c>hints.TargetModel</c> /// is out of range.</exception> /// <exception cref="InvalidOperationException">Upgrade sequence validation has failed.</exception> public ReadOnlyList <NodeAction> GetUpgradeSequence(Difference difference, HintSet hints, IComparer comparer) { ArgumentValidator.EnsureArgumentNotNull(hints, nameof(hints)); ArgumentValidator.EnsureArgumentNotNull(comparer, nameof(comparer)); if (difference == null) { return(new ReadOnlyList <NodeAction>(Enumerable.Empty <NodeAction>().ToList())); } TemporaryRenames = new Dictionary <string, Node>(StringComparer.OrdinalIgnoreCase); SourceModel = (IModel)difference.Source; TargetModel = (IModel)difference.Target; Hints = hints ?? new HintSet(SourceModel, TargetModel); Comparer = comparer; if (Hints.SourceModel != SourceModel) { throw new ArgumentOutOfRangeException("hints.SourceModel"); } if (Hints.TargetModel != TargetModel) { throw new ArgumentOutOfRangeException("hints.TargetModel"); } CurrentModel = (IModel)SourceModel.Clone(null, SourceModel.Name); Difference = difference; var previous = currentAsync.Value; currentAsync.Value = this; using (NullActionHandler.Instance.Activate()) { try { var actions = new GroupingNodeAction(); ProcessStage(UpgradeStage.CleanupData, actions); ProcessStage(UpgradeStage.Prepare, actions); ProcessStage(UpgradeStage.TemporaryRename, actions); ProcessStage(UpgradeStage.Upgrade, actions); ProcessStage(UpgradeStage.CopyData, actions); ProcessStage(UpgradeStage.PostCopyData, actions); ProcessStage(UpgradeStage.Cleanup, actions); var validationHints = new HintSet(CurrentModel, TargetModel); Hints.OfType <IgnoreHint>() .Where(h => CurrentModel.Resolve(h.Path, false) != null && SourceModel.Resolve(h.Path, false) != null) .ForEach(validationHints.Add); var diff = comparer.Compare(CurrentModel, TargetModel, validationHints); if (diff != null) { CoreLog.InfoRegion(Strings.LogAutomaticUpgradeSequenceValidation); CoreLog.Info(Strings.LogValidationFailed); CoreLog.Info(Strings.LogItemFormat, Strings.Difference); CoreLog.Info("{0}", diff); CoreLog.Info(Strings.LogItemFormat + "\r\n{1}", Strings.UpgradeSequence, new ActionSequence() { actions }); CoreLog.Info(Strings.LogItemFormat, Strings.ExpectedTargetModel); TargetModel.Dump(); CoreLog.Info(Strings.LogItemFormat, Strings.ActualTargetModel); CurrentModel.Dump(); throw new InvalidOperationException(Strings.ExUpgradeSequenceValidationFailure); } return(new ReadOnlyList <NodeAction>(actions.Actions, true)); } finally { currentAsync.Value = previous; } } }