/// <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> /// Creates a FactTypeMapsTowardsRole link in the same Partition as the given FactType /// </summary> /// <param name="source">FactType to use as the source of the relationship.</param> /// <param name="target">RoleBase to use as the target of the relationship.</param> /// <param name="depth">Initial value for the <see cref="Depth"/> property.</param> public static FactTypeMapsTowardsRole Create(FactType source, RoleBase target, MappingDepth depth) { if (source == null) { throw new ArgumentNullException("source"); } if (target == null) { throw new ArgumentNullException("target"); } MappingMandatoryPattern mandatoryPattern; MappingUniquenessPattern uniquenessPattern; GetMappingPatterns(target, out uniquenessPattern, out mandatoryPattern); return new FactTypeMapsTowardsRole( source.Partition, new RoleAssignment[] { new RoleAssignment(FactTypeMapsTowardsRole.FactTypeDomainRoleId, source), new RoleAssignment(FactTypeMapsTowardsRole.TowardsRoleDomainRoleId, target) }, new PropertyAssignment[] { new PropertyAssignment(DepthDomainPropertyId, depth), new PropertyAssignment(UniquenessPatternDomainPropertyId, uniquenessPattern), new PropertyAssignment(MandatoryPatternDomainPropertyId, mandatoryPattern)}); }
/// <summary> /// Provide an implicit reading for a subtype fact /// </summary> /// <param name="leadRole">The role that should begin the reading</param> /// <returns>An appropriate reading</returns> protected override IReading GetImplicitReading(RoleBase leadRole) { LinkedElementCollection <RoleBase> roles = RoleCollection; if (roles.Count == 2) // Sanity check { IList <RoleBase> order = null; if (roles[0] == leadRole) { order = roles; } else if (roles[1] == leadRole) { order = new RoleBase[] { leadRole, roles[0] }; } if (order != null) { return(new ImplicitReading(leadRole is SubtypeMetaRole ? ResourceStrings.SubtypeFactPredicateReading : ResourceStrings.SubtypeFactPredicateInverseReading, order)); } } return(null); }
/// <summary> /// AddRule: typeof(FactTypeHasRole) /// Block roles from being added to a subtype /// after it is included in a model. /// </summary> private static void LimitSubtypeRolesAddRule(ElementAddedEventArgs e) { FactTypeHasRole link = (FactTypeHasRole)e.ModelElement; SubtypeFact subtypeFact; if (null != (subtypeFact = link.FactType as SubtypeFact)) { Store store; if (subtypeFact.ResolvedModel != null && CopyMergeUtility.GetIntegrationPhase(store = link.Store) == CopyClosureIntegrationPhase.None) { // Allow before adding to model, not afterwards ThrowPatternModifiedException(store); } } else { RoleBase role = link.Role; if (role is SubtypeMetaRole || role is SupertypeMetaRole) { throw new InvalidOperationException(ResourceStrings.ModelExceptionSubtypeFactMustBeParentOfMetaRole); } } }
private void Reset() { mySourceRole = null; mySourceRoleMissingConnector = false; myRoleReorderConnector = false; mySourceObjectType = null; myLastMouseDownRole = null; myLastMouseMoveRole = null; myEmulateDrag = false; }
/// <summary> /// If the current item is a role, then cache it as the /// last mouse mouse hit role /// </summary> /// <param name="e"></param> protected override void OnMouseMove(DiagramMouseEventArgs e) { myLastMouseMoveRole = HitRole(e); base.OnMouseMove(e); }
/// <summary> /// Get the source object type or role after the /// base class sets the source shape /// </summary> /// <param name="e">MouseActionEventArgs</param> protected override void OnClicked(MouseActionEventArgs e) { base.OnClicked(e); if (mySourceObjectType == null && mySourceRole == null) { RoleBase roleBase = myLastMouseDownRole; if (roleBase != null) { Role role = roleBase.Role; mySourceRole = roleBase; FactTypeShape factShape; if (null != role.RolePlayer && null != (factShape = MouseDownHitShape as FactTypeShape)) { bool haveConnectorForRole = false; foreach (RolePlayerLink connector in MultiShapeUtility.GetEffectiveAttachedLinkShapesFrom<RolePlayerLink>(factShape)) { if (connector.AssociatedRolePlayerLink.PlayedRole == role) { haveConnectorForRole = true; break; } } mySourceRoleMissingConnector = !haveConnectorForRole; } } else { mySourceObjectType = ObjectTypeFromShape(MouseDownHitShape); } } }
/// <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 } )); } } } } } } }
private static void GetMappingPatterns(RoleBase towardsRole, out MappingUniquenessPattern uniquenessPattern, out MappingMandatoryPattern mandatoryPattern) { Role role = towardsRole.Role; GetMappingPatterns(role, role.OppositeRoleAlwaysResolveProxy.Role, out uniquenessPattern, out mandatoryPattern); }
/// <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) { Debug.Assert(factType.Store.TransactionManager.InTransaction); 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> /// The error message for role player required events includes the role number. /// If a role is added or deleted, then this numbering can change, so we need to /// regenerated the text. /// </summary> /// <param name="factType">The owning factType</param> /// <param name="roleAdded">The added role, or null if a role was removed.</param> private static void RenumberErrorsWithRoleNumbers(FactType factType, RoleBase roleAdded) { if (!factType.IsDeleted) { LinkedElementCollection<RoleBase> roles = factType.RoleCollection; bool regenerate = roleAdded == null; int roleCount = roles.Count; for (int i = 0; i < roleCount; ++i) { Role currentRole = roles[i] as Role; if (regenerate && currentRole != null) { RolePlayerRequiredError error = currentRole.RolePlayerRequiredError; if (error != null) { error.GenerateErrorText(); } RoleValueConstraint valueConstraint = currentRole.ValueConstraint; if (valueConstraint != null) { foreach (ValueRange range in valueConstraint.ValueRangeCollection) { MinValueMismatchError minError = range.MinValueMismatchError; if (minError != null) { minError.GenerateErrorText(); } MaxValueMismatchError maxError = range.MaxValueMismatchError; if (maxError != null) { maxError.GenerateErrorText(); } } ValueRangeOverlapError rangeOverlap = valueConstraint.ValueRangeOverlapError; if (rangeOverlap != null) { rangeOverlap.GenerateErrorText(); } } } else if (roleAdded == currentRole) { // Regenerate on the next pass regenerate = true; } } } }