/// <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)});
		}
Beispiel #3
0
        /// <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);
        }
Beispiel #4
0
        /// <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);
                }
            }
        }
Beispiel #5
0
		private void Reset()
		{
			mySourceRole = null;
			mySourceRoleMissingConnector = false;
			myRoleReorderConnector = false;
			mySourceObjectType = null;
			myLastMouseDownRole = null;
			myLastMouseMoveRole = null;
			myEmulateDrag = false;
		}
Beispiel #6
0
		/// <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);
		}
Beispiel #7
0
		/// <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);
		}
Beispiel #10
0
		/// <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
										}
										));
								}
							}
						}
					}
				}
			}
		}
Beispiel #11
0
		/// <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;
					}
				}
			}
		}