Esempio n. 1
0
        /// <inheritdoc/>
        /// <exception cref="InvalidOperationException">One of paths returned by
        /// <see cref="Hint.GetTargets"/> method isn't found.</exception>
        public void Add(Hint hint)
        {
            ArgumentValidator.EnsureArgumentNotNull(hint, "hint");

            if (set.Contains(hint))
            {
                throw new InvalidOperationException(Strings.ExItemAlreadyExists);
            }

            try {
                var targets = hint.GetTargets().ToList();
                var nodes   = new List <Node>();
                foreach (var target in targets)
                {
                    Node node;
                    if (target.Model == ModelType.Source)
                    {
                        node = (Node)SourceModel.Resolve(target.Path, true);
                    }
                    else
                    {
                        node = (Node)TargetModel.Resolve(target.Path, true);
                    }
                    nodes.Add(node);

                    if (!hintMap.ContainsKey(node))
                    {
                        hintMap.Add(node, new Dictionary <Type, object>());
                    }
                    var nodeHintMap = hintMap[node];
                    var hintType    = hint.GetType();

                    if (!nodeHintMap.ContainsKey(hintType))
                    {
                        nodeHintMap.Add(hintType, null);
                    }

                    var hintOrList = nodeHintMap[hintType];
                    if (hintOrList == null)
                    {
                        nodeHintMap[hintType] = hint;
                    }
                    else
                    {
                        var list = hintOrList as List <Hint>;
                        if (list == null)
                        {
                            var oldHint = (Hint)hintOrList;
                            nodeHintMap[hintType] = new List <Hint>(new[] { oldHint, hint });
                        }
                        else
                        {
                            list.Add(hint);
                        }
                    }
                }
            }
            catch (Exception) {
                var oldHints = list.ToList(); // Cloning  the list
                Clear();
                foreach (var oldHint in oldHints)
                {
                    Add(oldHint);
                }
                throw;
            }
            set.Add(hint);
            list.Add(hint);
        }
Esempio n. 2
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;
                }
            }
        }