/// <summary>
        /// DeletingRule: typeof(ReadingOrderHasRole)
        /// Handles the clean up of the readings that the role is involved in by replacing
        /// the place holder with the text DELETED
        /// </summary>
        private static void ReadingOrderHasRoleDeletingRule(ElementDeletingEventArgs e)
        {
            ReadingOrderHasRole link             = e.ModelElement as ReadingOrderHasRole;
            RoleBase            linkRole         = link.Role;
            ReadingOrder        linkReadingOrder = link.ReadingOrder;

            if (linkReadingOrder.IsDeleting || linkReadingOrder.IsDeleted)
            {
                // Don't validate if we're removing the reading order
                return;
            }
            FactType factType = linkReadingOrder.FactType;

            if (factType != null)
            {
                FrameworkDomainModel.DelayValidateElement(factType, DelayValidateReadingOrderCollation);
            }

            int pos = linkReadingOrder.RoleCollection.IndexOf(linkRole);

            if (pos >= 0)
            {
                bool isUnaryFactType = factType.UnaryRole != null;
                LinkedElementCollection <Reading> readings = linkReadingOrder.ReadingCollection;
                int numReadings = readings.Count;
                int roleCount   = linkReadingOrder.RoleCollection.Count;
                for (int iReading = 0; iReading < numReadings; ++iReading)
                {
                    Reading linkReading = readings[iReading];
                    if (!linkReading.IsDeleting)
                    {
                        Debug.Assert(!linkReading.IsDeleted);
                        string          text           = linkReading.Text;
                        IFormatProvider formatProvider = CultureInfo.InvariantCulture;
                        linkReading.SetAutoText(Reading.ReplaceFields(
                                                    linkReading.Text,
                                                    delegate(int replaceIndex)
                        {
                            if (replaceIndex == pos)
                            {
                                return(isUnaryFactType ? "" : ResourceStrings.ModelReadingRoleDeletedRoleText);
                            }
                            else if (replaceIndex > pos)
                            {
                                return("{" + (replaceIndex - 1).ToString(formatProvider) + "}");
                            }
                            return(null);
                        }
                                                    ));
                    }
                }
            }
        }
        /// <summary>
        /// Common place for code to deal with roles that exist in a fact
        /// but do not exist in the ReadingOrder objects that it contains.
        /// This allows it to be used by both the rule and to be called
        /// during post load model fixup.
        /// </summary>
        private static void ValidateReadingOrdersRoleCollection(FactType factType, RoleBase addedRole)
        {
            LinkedElementCollection <ReadingOrder> readingOrders;
            int orderCount;

            if (null == factType.UnaryRole &&
                0 != (orderCount = (readingOrders = factType.ReadingOrderCollection).Count))
            {
                bool            checkedContext = false;
                bool            insertAfter    = false;
                RoleBase        insertBeside   = null;
                IFormatProvider formatProvider = CultureInfo.InvariantCulture;
                for (int i = 0; i < orderCount; ++i)
                {
                    ReadingOrder ord = readingOrders[i];
                    LinkedElementCollection <RoleBase> roles = ord.RoleCollection;
                    if (!roles.Contains(addedRole))
                    {
                        if (!checkedContext)
                        {
                            checkedContext = true;
                            Dictionary <object, object> contextInfo = factType.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo;
                            object contextRole;
                            if (contextInfo.TryGetValue(FactType.InsertAfterRoleKey, out contextRole))
                            {
                                insertBeside = contextRole as RoleBase;
                                insertAfter  = true;
                            }
                            else if (contextInfo.TryGetValue(FactType.InsertBeforeRoleKey, out contextRole))
                            {
                                insertBeside = contextRole as RoleBase;
                            }
                        }
                        int insertIndex = -1;
                        if (insertBeside != null)
                        {
                            insertIndex = roles.IndexOf(insertBeside);
                        }

                        if (insertIndex != -1)
                        {
                            roles.Insert(insertIndex + (insertAfter ? 1 : 0), addedRole);
                        }
                        else
                        {
                            roles.Add(addedRole);
                        }
                        LinkedElementCollection <Reading> readings = ord.ReadingCollection;
                        int readingCount = readings.Count;
                        if (readingCount != 0)
                        {
                            if (insertIndex == -1)
                            {
                                string appendText = string.Concat("  {", (roles.Count - 1).ToString(CultureInfo.InvariantCulture), "}");
                                for (int j = 0; j < readingCount; ++j)
                                {
                                    Reading reading = readings[j];
                                    reading.SetAutoText(reading.Text + appendText);
                                }
                            }
                            else
                            {
                                for (int j = 0; j < readingCount; ++j)
                                {
                                    Reading reading = readings[j];
                                    reading.SetAutoText(Reading.ReplaceFields(
                                                            reading.Text,
                                                            delegate(int replaceIndex)
                                    {
                                        // UNDONE: Respect leading/trailing hyphen binding and keep them associated
                                        // with the corresponding role. Will require work well beyond the scope of this
                                        // routine.
                                        if (replaceIndex == insertIndex)
                                        {
                                            return(string.Concat("{", insertIndex.ToString(formatProvider), "} {", (insertIndex + 1).ToString(formatProvider), "}"));
                                        }
                                        else if (replaceIndex > insertIndex)
                                        {
                                            return(string.Concat("{", (replaceIndex + 1).ToString(formatProvider), "}"));
                                        }
                                        return(null);                                                // Leave as is
                                    }
                                                            ));
                                }
                            }
                        }
                    }
                }
            }
        }