/// <summary>
        /// RolePlayerChangeRule: typeof(Microsoft.VisualStudio.Modeling.Diagrams.LinkConnectsToNode)
        /// External constraint shapes can only be drawn if they show all of their
        /// links, so automatically remove them if a link is moved off the constraint
        /// shape.
        /// </summary>
        private static void VerifyConnectedShapeShapeRolePlayerChangedRule(RolePlayerChangedEventArgs e)
        {
            ShapeElement shape;

            if (e.DomainRole.Id == LinkConnectsToNode.NodesDomainRoleId &&
                ((LinkConnectsToNode)e.ElementLink).Link is ExternalConstraintLink &&
                null != (shape = e.OldRolePlayer as ShapeElement))
            {
                ExternalConstraintShape constraintShape;
                FactTypeShape           factTypeShape;
                if (null != (constraintShape = shape as ExternalConstraintShape))
                {
                    FrameworkDomainModel.DelayValidateElement(constraintShape, DelayValidateExternalConstraintShapeFullyConnected);
                }
                else if (null != (factTypeShape = MultiShapeUtility.ResolvePrimaryShape(shape) as FactTypeShape))
                {
                    FrameworkDomainModel.DelayValidateElement(factTypeShape, DelayValidateFactTypeShapeSize);
                    if (null != (shape = e.NewRolePlayer as ShapeElement) &&
                        null != (factTypeShape = MultiShapeUtility.ResolvePrimaryShape(shape) as FactTypeShape))
                    {
                        FrameworkDomainModel.DelayValidateElement(factTypeShape, DelayValidateFactTypeShapeSize);
                    }
                }
            }
        }
        /// <summary>
        /// DeletingRule: typeof(Microsoft.VisualStudio.Modeling.Diagrams.LinkConnectsToNode)
        /// External constraint shapes can only be drawn if they show all of their
        /// links, so automatically remove them if a connecting shape is removed.
        /// </summary>
        private static void VerifyConnectedShapeShapeDeletingRule(ElementDeletingEventArgs e)
        {
            LinkConnectsToNode     connectLink = (LinkConnectsToNode)e.ModelElement;
            ExternalConstraintLink link;
            ModelElement           linkMel;
            ModelElement           shapeMel;

            if (null != (link = connectLink.Link as ExternalConstraintLink) &&
                null != (linkMel = link.ModelElement) &&
                !linkMel.IsDeleting)
            {
                NodeShape linkNode = connectLink.Nodes;
                ExternalConstraintShape constraintShape = linkNode as ExternalConstraintShape;
                NodeShape oppositeShape = null;
                // The ToShape (as opposed to FromShape) here needs to be in
                // sync with the code in ConfiguringAsChildOf
                if (constraintShape == null)
                {
                    constraintShape = link.ToShape as ExternalConstraintShape;
                    oppositeShape   = linkNode;
                }
                else
                {
                    oppositeShape = link.FromShape;
                }
                if (oppositeShape != null &&
                    constraintShape != null &&
                    null != (shapeMel = constraintShape.ModelElement) &&
                    !shapeMel.IsDeleting)
                {
                    if (!constraintShape.IsDeleting)
                    {
                        FrameworkDomainModel.DelayValidateElement(constraintShape, DelayValidateExternalConstraintShapeFullyConnected);
                    }
                    // Delay, fact type shape size will not be accurate until deletion is completed.
                    FactTypeShape factTypeShape = MultiShapeUtility.ResolvePrimaryShape(oppositeShape) as FactTypeShape;
                    if (factTypeShape != null &&
                        !factTypeShape.IsDeleting)
                    {
                        FrameworkDomainModel.DelayValidateElement(factTypeShape, DelayValidateFactTypeShapeSize);
                    }
                }
            }
        }