// 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;
        }
예제 #2
0
        /// <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));
        }
예제 #3
0
        /// <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;
                }
            }
        }