Example #1
0
        private List <WixActionSymbol> ScheduleActions(Dictionary <string, WixActionSymbol> requiredActionSymbols)
        {
            var scheduledActionSymbols = new List <WixActionSymbol>();

            // Process each sequence table individually.
            foreach (SequenceTable sequenceTable in Enum.GetValues(typeof(SequenceTable)))
            {
                // Create a collection of just the action symbols in this sequence
                var sequenceActionSymbols = requiredActionSymbols.Values.Where(a => a.SequenceTable == sequenceTable).ToList();

                // Schedule the absolutely scheduled actions (by sorting them by their sequence numbers).
                var absoluteActionSymbols = new List <WixActionSymbol>();
                foreach (var actionSymbol in sequenceActionSymbols)
                {
                    if (actionSymbol.Sequence.HasValue)
                    {
                        // Look for sequence number collisions
                        foreach (var sequenceScheduledActionSymbol in absoluteActionSymbols)
                        {
                            if (sequenceScheduledActionSymbol.Sequence == actionSymbol.Sequence)
                            {
                                this.Messaging.Write(WarningMessages.ActionSequenceCollision(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action, sequenceScheduledActionSymbol.Action, actionSymbol.Sequence ?? 0));
                                if (null != sequenceScheduledActionSymbol.SourceLineNumbers)
                                {
                                    this.Messaging.Write(WarningMessages.ActionSequenceCollision2(sequenceScheduledActionSymbol.SourceLineNumbers));
                                }
                            }
                        }

                        absoluteActionSymbols.Add(actionSymbol);
                    }
                }

                absoluteActionSymbols.Sort((x, y) => (x.Sequence ?? 0).CompareTo(y.Sequence ?? 0));

                // Schedule the relatively scheduled actions (by resolving the dependency trees).
                var previousUsedSequence  = 0;
                var relativeActionSymbols = new List <WixActionSymbol>();
                for (int j = 0; j < absoluteActionSymbols.Count; j++)
                {
                    var absoluteActionSymbol = absoluteActionSymbols[j];

                    // Get all the relatively scheduled action symbols occuring before and after this absolutely scheduled action symbol.
                    var relativeActions = this.GetAllRelativeActionsForSequenceType(sequenceTable, absoluteActionSymbol);

                    // Check for relatively scheduled actions occuring before/after a special action
                    // (those actions with a negative sequence number).
                    if (absoluteActionSymbol.Sequence < 0 && (relativeActions.PreviousActions.Any() || relativeActions.NextActions.Any()))
                    {
                        // Create errors for all the before actions.
                        foreach (var actionSymbol in relativeActions.PreviousActions)
                        {
                            this.Messaging.Write(ErrorMessages.ActionScheduledRelativeToTerminationAction(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action, absoluteActionSymbol.Action));
                        }

                        // Create errors for all the after actions.
                        foreach (var actionSymbol in relativeActions.NextActions)
                        {
                            this.Messaging.Write(ErrorMessages.ActionScheduledRelativeToTerminationAction(actionSymbol.SourceLineNumbers, actionSymbol.SequenceTable.ToString(), actionSymbol.Action, absoluteActionSymbol.Action));
                        }

                        // If there is source line information for the absolutely scheduled action display it
                        if (absoluteActionSymbol.SourceLineNumbers != null)
                        {
                            this.Messaging.Write(ErrorMessages.ActionScheduledRelativeToTerminationAction2(absoluteActionSymbol.SourceLineNumbers));
                        }

                        continue;
                    }

                    // Schedule the action symbols before this one.
                    var unusedSequence = absoluteActionSymbol.Sequence - 1;
                    for (var i = relativeActions.PreviousActions.Count - 1; i >= 0; i--)
                    {
                        var relativeActionSymbol = relativeActions.PreviousActions[i];

                        // look for collisions
                        if (unusedSequence == previousUsedSequence)
                        {
                            this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber(relativeActionSymbol.SourceLineNumbers, relativeActionSymbol.SequenceTable.ToString(), relativeActionSymbol.Action, absoluteActionSymbol.Action));
                            if (absoluteActionSymbol.SourceLineNumbers != null)
                            {
                                this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber2(absoluteActionSymbol.SourceLineNumbers));
                            }

                            unusedSequence++;
                        }

                        relativeActionSymbol.Sequence = unusedSequence;
                        relativeActionSymbols.Add(relativeActionSymbol);

                        unusedSequence--;
                    }

                    // Determine the next used action sequence number.
                    var nextUsedSequence = Int16.MaxValue + 1;
                    if (absoluteActionSymbols.Count > j + 1)
                    {
                        nextUsedSequence = absoluteActionSymbols[j + 1].Sequence ?? 0;
                    }

                    // Schedule the action symbols after this one.
                    unusedSequence = absoluteActionSymbol.Sequence + 1;
                    for (var i = 0; i < relativeActions.NextActions.Count; i++)
                    {
                        var relativeActionSymbol = relativeActions.NextActions[i];

                        if (unusedSequence == nextUsedSequence)
                        {
                            this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber(relativeActionSymbol.SourceLineNumbers, relativeActionSymbol.SequenceTable.ToString(), relativeActionSymbol.Action, absoluteActionSymbol.Action));
                            if (absoluteActionSymbol.SourceLineNumbers != null)
                            {
                                this.Messaging.Write(ErrorMessages.NoUniqueActionSequenceNumber2(absoluteActionSymbol.SourceLineNumbers));
                            }

                            unusedSequence--;
                        }

                        relativeActionSymbol.Sequence = unusedSequence;
                        relativeActionSymbols.Add(relativeActionSymbol);

                        unusedSequence++;
                    }

                    // keep track of this sequence number as the previous used sequence number for the next iteration
                    previousUsedSequence = absoluteActionSymbol.Sequence ?? 0;
                }

                // add the absolutely and relatively scheduled actions to the list of scheduled actions
                scheduledActionSymbols.AddRange(absoluteActionSymbols);
                scheduledActionSymbols.AddRange(relativeActionSymbols);
            }

            return(scheduledActionSymbols);
        }