Example #1
0
        /// <summary>
        /// AddRule: typeof(SetComparisonConstraintHasRoleSequence)
        /// Validate subtype external constraint patterns when a role sequence
        /// is added with preexisting roles
        /// </summary>
        private static void LimitSubtypeSetComparisonConstraintSequenceAddRule(ElementAddedEventArgs e)
        {
            SetComparisonConstraintHasRoleSequence link     = e.ModelElement as SetComparisonConstraintHasRoleSequence;
            SetComparisonConstraintRoleSequence    sequence = link.RoleSequence;
            LinkedElementCollection <Role>         roles    = sequence.RoleCollection;
            int roleCount = roles.Count;

            if (roleCount != 0)
            {
                SetComparisonConstraint constraint = link.ExternalConstraint;
                bool isExclusion = constraint is ExclusionConstraint;
                bool isSubset    = !isExclusion && constraint is SubsetConstraint;
                bool addExclusionDelayValidate = false;
                bool addSubtypeDelayValidate   = false;
                for (int i = 0; i < roleCount; ++i)
                {
                    Role untypedRole = roles[i];
                    if (untypedRole is SubtypeMetaRole)
                    {
                        ThrowInvalidSubtypeMetaRoleConstraint();
                    }
                    else if (isExclusion)
                    {
                        addExclusionDelayValidate = true;
                    }
                    else if (isSubset)
                    {
                        addSubtypeDelayValidate = true;
                    }
                    else if (untypedRole is SupertypeMetaRole)
                    {
                        ThrowInvalidSupertypeMetaRoleConstraint();
                    }
                }
                if (addExclusionDelayValidate)
                {
                    FrameworkDomainModel.DelayValidateElement(constraint, DelayValidateSupertypeExclusionSingleColumnOnly);
                }
                else if (addSubtypeDelayValidate)
                {
                    FrameworkDomainModel.DelayValidateElement(constraint, DelayValidateSupertypeSubsetPattern);
                }
            }
        }
			/// <summary>
			/// Create a connection between an ExternalConstraintShape and a FactType. Roles
			/// used in the connection are stored with the currently active connect action.
			/// </summary>
			/// <param name="sourceShapeElement">The source of the requested connection</param>
			/// <param name="targetShapeElement">The target of the requested connection</param>
			/// <param name="paintFeedbackArgs">PaintFeedbackArgs</param>
			public override void CreateConnection(ShapeElement sourceShapeElement, ShapeElement targetShapeElement, PaintFeedbackArgs paintFeedbackArgs)
			{
				ExternalConstraintShape constraintShape;
				IConstraint constraint;
				ExternalConstraintConnectAction action;
				IList<Role> selectedRoles;
				int rolesCount;
				if ((null != (constraintShape = sourceShapeElement as ExternalConstraintShape)) &&
					(null != (constraint = constraintShape.AssociatedConstraint)) &&
					(null != (action = (sourceShapeElement.Diagram as ORMDiagram).ExternalConstraintConnectAction)) &&
					(null != (selectedRoles = action.SelectedRoleCollection)) &&
					(0 != (rolesCount = selectedRoles.Count)))
				{
					SetComparisonConstraint mcConstraint;
					SetConstraint scConstraint;
					ConstraintRoleSequence modifyRoleSequence = null;
					if (null != (mcConstraint = constraint as SetComparisonConstraint))
					{
						ConstraintRoleSequence constraintRoleSequenceBeingEdited = action.ConstraintRoleSequenceToEdit;
						// Add a new role set
						if (null == constraintRoleSequenceBeingEdited)
						{
							LinkedElementCollection<SetComparisonConstraintRoleSequence> roleSequences = mcConstraint.RoleSequenceCollection;
							if (action.mySubtypeConnection)
							{
								// All editing is done as a single column, add role sequences to the constraint
								// instead of roles to the sequence
								Store store = mcConstraint.Store;
								for (int i = 0; i < rolesCount; ++i)
								{
									SetComparisonConstraintRoleSequence roleSequence = new SetComparisonConstraintRoleSequence(store);
									roleSequence.RoleCollection.Add(selectedRoles[i]);
									roleSequences.Add(roleSequence);
								}
							}
							else
							{
								SetComparisonConstraintRoleSequence roleSequence = new SetComparisonConstraintRoleSequence(mcConstraint.Store);
								LinkedElementCollection<Role> roles = roleSequence.RoleCollection;
								for (int i = 0; i < rolesCount; ++i)
								{
									roles.Add(selectedRoles[i]);
								}
								roleSequences.Add(roleSequence);
							}
						}
						else if (action.mySubtypeConnection)
						{
							LinkedElementCollection<SetComparisonConstraintRoleSequence> existingSequences = mcConstraint.RoleSequenceCollection;
							int existingSequenceCount = existingSequences.Count;
							// Pull out removed ones first
							for (int i = existingSequenceCount - 1; i >= 0; --i)
							{
								SetComparisonConstraintRoleSequence existingSequence = existingSequences[i];
								LinkedElementCollection<Role> sequenceRoles = existingSequence.RoleCollection;
								if (sequenceRoles.Count != 1 || !selectedRoles.Contains(sequenceRoles[0]))
								{
									existingSequences.Remove(existingSequence);
									--existingSequenceCount;
								}
							}
							Store store = mcConstraint.Store;
							for (int i = 0; i < rolesCount; ++i)
							{
								Role selectedRole = selectedRoles[i];
								int existingIndex = -1;
								for (int j = 0; j < existingSequenceCount; ++j)
								{
									if (existingSequences[j].RoleCollection[0] == selectedRole)
									{
										existingIndex = j;
										break;
									}
								}
								if (existingIndex == -1)
								{
									SetComparisonConstraintRoleSequence roleSequence = new SetComparisonConstraintRoleSequence(store);
									roleSequence.RoleCollection.Add(selectedRoles[i]);
									if (i < existingSequenceCount)
									{
										existingSequences.Insert(i, roleSequence);
									}
									else
									{
										existingSequences.Add(roleSequence);
									}
									++existingSequenceCount;
								}
								else if (existingIndex != i)
								{
									existingSequences.Move(existingIndex, i);
								}
							}
						}
						// Edit the existing role set.
						else
						{
							modifyRoleSequence = constraintRoleSequenceBeingEdited;
						}
					}
					else if (null != (scConstraint = constraint as SetConstraint))
					{
						// The single-column constraint is its own role set, just add the roles.
						modifyRoleSequence = scConstraint;
						switch (constraint.ConstraintType)
						{
							case ConstraintType.ExternalUniqueness:
							case ConstraintType.Frequency:
								// Translate selected unary roles back to the implied role
								bool duplicatedSelectedRoles = false;
								for (int i = 0; i < rolesCount; ++i)
								{
									Role testRole = selectedRoles[i];
									Role oppositeRole;
									ObjectType oppositeRolePlayer;
									if (null != (oppositeRole = testRole.OppositeRole as Role) &&
										null != (oppositeRolePlayer = oppositeRole.RolePlayer) &&
										oppositeRolePlayer.IsImplicitBooleanValue)
									{
										if (!duplicatedSelectedRoles)
										{
											duplicatedSelectedRoles = true;
											Role[] dupRoles = new Role[rolesCount];
											selectedRoles.CopyTo(dupRoles, 0);
											selectedRoles = dupRoles;
										}
										selectedRoles[i] = oppositeRole;
									}
								}
								break;
						}
					}
					if (modifyRoleSequence != null)
					{
						// Note that we don't just blow away the collection here, there are too
						// many side effects (such as removing the preferred identifier when a compatible
						// link is added)
						LinkedElementCollection<Role> roles = modifyRoleSequence.RoleCollection;
						int existingRolesCount = roles.Count;
						for (int i = existingRolesCount - 1; i >= 0; --i)
						{
							Role testRole = roles[i];
							if (!selectedRoles.Contains(testRole))
							{
								roles.Remove(testRole);
								--existingRolesCount;
							}
						}
						for (int i = 0; i < rolesCount; ++i)
						{
							Role selectedRole = selectedRoles[i];
							int existingIndex = roles.IndexOf(selectedRole);
							if (existingIndex == -1)
							{
								if (i < existingRolesCount)
								{
									roles.Insert(i, selectedRole);
								}
								else if (!roles.Contains(selectedRole))
								{
									roles.Add(selectedRole);
								}
								++existingRolesCount;
							}
							else if (existingIndex != i)
							{
								roles.Move(existingIndex, i);
							}
						}
					}
				}
			}