Example #1
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;
                }
            }
        }