/// <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> /// RolePlayerChangeRule: typeof(ReadingOrderHasReading), FireTime=LocalCommit, Priority=ORMCoreDomainModel.BeforeDelayValidateRulePriority; /// </summary> private static void EnforceNoEmptyReadingOrderRolePlayerChangeRule(RolePlayerChangedEventArgs e) { ReadingOrderHasReading link = e.ElementLink as ReadingOrderHasReading; if (e.DomainRole.Id == ReadingOrderHasReading.ReadingOrderDomainRoleId) { ReadingOrder order = (ReadingOrder)e.OldRolePlayer; if (!order.IsDeleted && order.ReadingCollection.Count == 0) { order.Delete(); } } }
/// <summary> /// DeleteRule: typeof(ReadingOrderHasReading), FireTime=LocalCommit, Priority=ORMCoreDomainModel.BeforeDelayValidateRulePriority; /// If the ReadingOrder.ReadingCollection is empty then remove the ReadingOrder /// </summary> private static void EnforceNoEmptyReadingOrderDeleteRule(ElementDeletedEventArgs e) { ReadingOrderHasReading link = e.ModelElement as ReadingOrderHasReading; ReadingOrder readOrd = link.ReadingOrder; if (!readOrd.IsDeleted) { if (readOrd.ReadingCollection.Count == 0) { readOrd.Delete(); } } }
/// <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 } )); } } } } } } }
/// <summary> /// Verify that all <see cref="ReadingOrder"/>s have unique <see cref="ReadingOrder.RoleCollection">role collections</see> /// </summary> /// <param name="element">A <see cref="FactType"/></param> private static void DelayValidateReadingOrderCollation(ModelElement element) { if (element.IsDeleted) { return; } FactType factType = (FactType)element; LinkedElementCollection <ReadingOrder> ordersCollection = factType.ReadingOrderCollection; int orderCount = ordersCollection.Count; if (orderCount > 1) { // Get all orders in a collatable form, starting by caching information locally // so it is easily accessed. Note that this will also change the collection we're // iterating so we need to be careful about changes. ReadingOrder[] orders = new ReadingOrder[orderCount]; ordersCollection.CopyTo(orders, 0); LinkedElementCollection <RoleBase>[] roleCollections = new LinkedElementCollection <RoleBase> [orderCount]; for (int i = 0; i < orderCount; ++i) { roleCollections[i] = orders[i].RoleCollection; } // Priority is top down, so we move later readings into a higher reading order for (int i = 0; i < orderCount; ++i) { ReadingOrder currentOrder = orders[i]; for (int j = i + 1; j < orderCount; ++j) { ReadingOrder compareToOrder = orders[j]; if (compareToOrder != null) // Will be null if it has already been recognized as a duplicate { // These should all have the same count, but it doesn't hurt to be defensive LinkedElementCollection <RoleBase> currentRoles = roleCollections[i]; LinkedElementCollection <RoleBase> compareToRoles = roleCollections[j]; int roleCount = currentRoles.Count; if (roleCount == compareToRoles.Count) { int k = 0; for (; k < roleCount; ++k) { if (currentRoles[k] != compareToRoles[k]) { break; } } if (k == roleCount) { // Order is the same, collate the later readings up to the current order ReadOnlyCollection <ReadingOrderHasReading> readingLinks = ReadingOrderHasReading.GetLinksToReadingCollection(compareToOrder); int readingCount = readingLinks.Count; for (int l = 0; l < readingCount; ++l) { readingLinks[l].ReadingOrder = currentOrder; } orders[j] = null; } } } } } } }
/// <summary> /// Verify that all <see cref="ReadingOrder"/>s have unique <see cref="ReadingOrder.RoleCollection">role collections</see> /// </summary> /// <param name="element">A <see cref="FactType"/></param> private static void DelayValidateReadingOrderCollation(ModelElement element) { if (element.IsDeleted) { return; } FactType factType = (FactType)element; LinkedElementCollection<ReadingOrder> ordersCollection = factType.ReadingOrderCollection; int orderCount = ordersCollection.Count; if (orderCount > 1) { // Get all orders in a collatable form, starting by caching information locally // so it is easily accessed. Note that this will also change the collection we're // iterating so we need to be careful about changes. ReadingOrder[] orders = new ReadingOrder[orderCount]; ordersCollection.CopyTo(orders, 0); LinkedElementCollection<RoleBase>[] roleCollections = new LinkedElementCollection<RoleBase>[orderCount]; for (int i = 0; i < orderCount; ++i) { roleCollections[i] = orders[i].RoleCollection; } // Priority is top down, so we move later readings into a higher reading order for (int i = 0; i < orderCount; ++i) { ReadingOrder currentOrder = orders[i]; for (int j = i + 1; j < orderCount; ++j) { ReadingOrder compareToOrder = orders[j]; if (compareToOrder != null) // Will be null if it has already been recognized as a duplicate { // These should all have the same count, but it doesn't hurt to be defensive LinkedElementCollection<RoleBase> currentRoles = roleCollections[i]; LinkedElementCollection<RoleBase> compareToRoles = roleCollections[j]; int roleCount = currentRoles.Count; if (roleCount == compareToRoles.Count) { int k = 0; for (; k < roleCount; ++k) { if (currentRoles[k] != compareToRoles[k]) { break; } } if (k == roleCount) { // Order is the same, collate the later readings up to the current order ReadOnlyCollection<ReadingOrderHasReading> readingLinks = ReadingOrderHasReading.GetLinksToReadingCollection(compareToOrder); int readingCount = readingLinks.Count; for (int l = 0; l < readingCount; ++l) { readingLinks[l].ReadingOrder = currentOrder; } orders[j] = null; } } } } } } }
public static void ProcessFactType(FactType factType, INotifyElementAdded notifyAdded) { LinkedElementCollection <RoleBase> roleCollection = factType.RoleCollection; int roleCollectionCount = roleCollection.Count; if (roleCollectionCount == 1) { // If we have a unary, binarize it BinarizeUnary(factType, notifyAdded); return; } else if (roleCollectionCount == 2) { // If we have a binary that has an implicit boolean role in it, make sure it matches the pattern Role implicitBooleanRole = GetImplicitBooleanRole(roleCollection); if (implicitBooleanRole != null) { Role unaryRole = implicitBooleanRole.OppositeRole.Role; Debug.Assert(unaryRole != null); // Make sure the implicit boolean role has the same name as the unary role implicitBooleanRole.Name = unaryRole.Name; string implicitBooleanValueTypeName = GetImplicitBooleanValueTypeName(unaryRole); if (implicitBooleanRole.RolePlayer.Name != implicitBooleanValueTypeName) { Dictionary <object, object> contextInfo = factType.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo; object duplicateNamesKey = ORMModel.AllowDuplicateNamesKey; bool removeDuplicateNamesKey = false; object duplicateSignaturesKey = ORMModel.BlockDuplicateReadingSignaturesKey; bool addDuplicateSignaturesKey = false; try { if (!contextInfo.ContainsKey(duplicateNamesKey)) { contextInfo[duplicateNamesKey] = null; removeDuplicateNamesKey = true; } if (contextInfo.ContainsKey(duplicateSignaturesKey)) { contextInfo.Remove(duplicateSignaturesKey); addDuplicateSignaturesKey = true; } implicitBooleanRole.RolePlayer.Name = implicitBooleanValueTypeName; } finally { if (removeDuplicateNamesKey) { contextInfo.Remove(duplicateNamesKey); } if (addDuplicateSignaturesKey) { contextInfo[duplicateSignaturesKey] = null; } } } if (!ValidateConstraints(unaryRole, implicitBooleanRole) || !ValidateImplicitBooleanValueType(implicitBooleanRole.RolePlayer)) { LinkedElementCollection <RoleBase> roles = factType.RoleCollection; DebinarizeUnary(roles, false, notifyAdded); // Append to the reading orders LinkedElementCollection <ReadingOrder> readingOrders = factType.ReadingOrderCollection; int readingOrderCount = readingOrders.Count; for (int i = 0; i < readingOrderCount; ++i) { ReadingOrder order = readingOrders[i]; LinkedElementCollection <RoleBase> readingRoles = order.RoleCollection; if (!readingRoles.Contains(implicitBooleanRole)) { readingRoles.Add(implicitBooleanRole); LinkedElementCollection <Reading> readings = order.ReadingCollection; int readingCount = readings.Count; for (int j = 0; j < readingCount; ++j) { readings[j].SetAutoText(readings[j].Text + " {1}"); } } } } } } else { // If we have an n-ary, remove any implicit boolean roles in it for (int i = roleCollectionCount - 1; i >= 0; --i) { Role implicitBooleanRole = roleCollection[i].Role; if (implicitBooleanRole != null && implicitBooleanRole.RolePlayer != null && implicitBooleanRole.RolePlayer.IsImplicitBooleanValue) { DebinarizeUnary(factType.RoleCollection, true, notifyAdded); break; } } } }
private static string GenerateReadingText(string readingText, ReadingOrder order) { LinkedElementCollection<RoleBase> roles = order.RoleCollection; int roleCount = roles.Count; return Reading.ReplaceFields( readingText, delegate(int index) { if (index < roleCount) { ObjectType rolePlayer = roles[index].Role.RolePlayer; return (rolePlayer != null) ? rolePlayer.Name : ResourceStrings.ModelReadingEditorMissingRolePlayerText; } return null; }); }