/// <summary> /// An IMS event to track the shape element added to the associated /// diagram during this connect action. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void InternalConstraintAddedEvent(object sender, ElementAddedEventArgs e) { if (myAddedConstraint == null) { UniquenessConstraint candidate = e.ModelElement as UniquenessConstraint; if (candidate != null && candidate.IsInternal) { ORMDiagram d = Diagram as ORMDiagram; if (d != null) { // Find the shape associated with the fact type we added to LinkedElementCollection <FactType> candidateFacts = candidate.FactTypeCollection; if (candidateFacts.Count != 0) { FactTypeShape shape = d.FindShapeForElement(candidateFacts[0]) as FactTypeShape; if (shape != null) { myDropTargetShape = shape; myAddedConstraint = candidate; } } } } } }
public void ExactlyOneTest_1b(Store store) { myTestServices.LogValidationErrors("No errors expected"); ORMModel model = store.ElementDirectory.FindElements <ORMModel>()[0]; FrequencyConstraint constraint = (FrequencyConstraint)model.ConstraintsDictionary.GetElement("FrequencyConstraint1").SingleElement; // DomainTypeDescriptor.CreatePropertyDescriptor(constraint, FrequencyConstraint.MaxFrequencyDomainPropertyId).SetValue(constraint, 1); myTestServices.LogValidationErrors("Introduce Error[FrequencyConstraintExactlyOneError]"); using (Transaction t = store.TransactionManager.BeginTransaction("Read the error")) { constraint.MinFrequency = 1; constraint.MaxFrequency = 1; t.Commit(); } myTestServices.LogValidationErrors("Fixing error with error activation service"); ((IORMToolServices)store).ModelErrorActivationService.ActivateError(constraint, constraint.FrequencyConstraintExactlyOneError); myTestServices.LogValidationErrors("[FrequencyConstraintExactlyOneError] removed, different error introduced. Removing new error"); // Deleting one of the two uniqnuess constraints... UniquenessConstraint uniqueC = (UniquenessConstraint)model.ConstraintsDictionary.GetElement("InternalUniquenessConstraint5").SingleElement; using (Transaction t = store.TransactionManager.BeginTransaction("Read the error")) { uniqueC.Delete(); t.Commit(); } myTestServices.LogValidationErrors("All errors resolved"); }
public IEnumerable<ErrorMessage> Validate(WineDTO wine) { var entity = wine.To(); var validator = new ValidateWine(entity.Name, entity.Kind.ToMaybe(), entity.Producer.ToMaybe(), entity.Alcohol); var uniqueness = new UniquenessConstraint<Wine>(() => validator.Commit()); return validator.Errors.Union(uniqueness.Errors); }
/// <summary> /// Set this mouse action as the active action on the /// diagram of the given shape. /// </summary> /// <param name="attachToShape">The shape the constraint is being attached to.</param> /// <param name="constraint">The constraint being connected.</param> /// <param name="clientView">The active DiagramClientView</param> public void ChainMouseAction(FactTypeShape attachToShape, UniquenessConstraint constraint, DiagramClientView clientView) { DiagramView activeView = Diagram.ActiveDiagramView; if (activeView != null) { // Move on to the selection action clientView.ActiveMouseAction = this; // Now emulate a mouse click in the middle of the added constraint. The click // actions provide a starting point for the connect action, so a mouse move // provides a drag line. Point emulateClickPoint = clientView.WorldToDevice(attachToShape.GetAbsoluteConstraintAttachPoint(constraint, FactSetConstraint.GetLink(constraint, attachToShape.AssociatedFactType))); DiagramMouseEventArgs mouseEventArgs = new DiagramMouseEventArgs(new MouseEventArgs(MouseButtons.Left, 1, emulateClickPoint.X, emulateClickPoint.Y, 0), clientView); MouseDown(mouseEventArgs); Click(new DiagramPointEventArgs(emulateClickPoint.X, emulateClickPoint.Y, PointRelativeTo.Client, clientView)); MouseUp(mouseEventArgs); attachToShape.Invalidate(true); // An extra move lets us chain when the mouse is not on the design surface, // such as when we are being activated via the task list. MouseMove(mouseEventArgs); ORMDiagram.SelectToolboxItem(activeView, ResourceStrings.ToolboxInternalUniquenessConstraintItemId); FactTypeShape.ActiveInternalUniquenessConstraintConnectAction = this; } }
public IEnumerable<ErrorMessage> Validate(ProducerDTO producer) { var entity = producer.To(); var validator = new ValidateProducer(entity.Name); var uniqueness = new UniquenessConstraint<Producer>(() => validator.Commit()); return validator.Errors.Union(uniqueness.Errors); }
public IEnumerable<ErrorMessage> Validate(KindDTO kind) { var kindEntity = kind.To(); var validator = new ValidateKind(kindEntity.Name, kindEntity.Type); var uniqueness = new UniquenessConstraint<Kind>(() => validator.Commit()); return validator.Errors.Union(uniqueness.Errors); }
/// <summary> /// Attempts to fix a PopulationMandatoryError /// </summary> /// <param name="error">Error to be corrected</param> /// <param name="autoCorrectObjectType">The <see cref="ObjectType"/> to correct the error for.</param> /// <returns><see langword="true"/> if the error was automatically corrected.</returns> public bool AutoCorrectMandatoryError(PopulationMandatoryError error, ObjectType autoCorrectObjectType) { // Find a role in the mandatory constraint that corresponds to // the object type Role matchingRole = null; UniquenessConstraint pid = autoCorrectObjectType.PreferredIdentifier; LinkedElementCollection <Role> pidRoles = pid != null ? pid.RoleCollection : null; foreach (Role role in error.MandatoryConstraint.RoleCollection) { SubtypeFact subtypeFact; SupertypeMetaRole supertypeRole; if (role.RolePlayer == autoCorrectObjectType || (null != (supertypeRole = role as SupertypeMetaRole) && (subtypeFact = (SubtypeFact)supertypeRole.FactType).ProvidesPreferredIdentifier && subtypeFact.Subtype == autoCorrectObjectType) || (null != pidRoles && pidRoles.Contains(role))) { if (matchingRole != null) { // Multiple matches, nothing to do matchingRole = null; break; } matchingRole = role; } } if (matchingRole != null) { return(AutoCorrectMandatoryError(error, matchingRole, null)); } return(false); }
private static void SignificantUniquenessConstraintChange(UniquenessConstraint constraint) { if (constraint != null && !constraint.IsDeleted && !ORMElementGateway.IsElementExcluded(constraint)) { FrameworkDomainModel.DelayValidateElement(constraint, SignificantUniquenessConstraintChangeDelayed); } }
/// <summary> /// DeleteRule: typeof(UniquenessConstraintIsForUniqueness) /// Propagate deletion of a Uniqueness /// </summary> private static void UniquenessDeletedRule(ElementDeletedEventArgs e) { UniquenessConstraint constraint = ((UniquenessConstraintIsForUniqueness)e.ModelElement).UniquenessConstraint; if (!constraint.IsDeleted) { constraint.Delete(); } }
private void Reset() { mySelectedRoles = null; mySourceShape = null; myIUC = null; myLastMouseMoveItem = null; myPendingOnClickedAction = OnClickedAction.Normal; FactTypeShape.ActiveInternalUniquenessConstraintConnectAction = null; }
/// <summary> /// RolePlayerChangeRule: typeof(ORMSolutions.ORMArchitect.Core.ObjectModel.EntityTypeHasPreferredIdentifier), FireTime=TopLevelCommit, Priority=DiagramFixupConstants.AddShapeRulePriority; /// </summary> private static void PreferredIdentifierRolePlayerChangeRule(RolePlayerChangedEventArgs e) { UniquenessConstraint oldPreferredIdentifier = null; if (e.DomainRole.Id == EntityTypeHasPreferredIdentifier.PreferredIdentifierDomainRoleId) { oldPreferredIdentifier = (UniquenessConstraint)e.OldRolePlayer; } ProcessPreferredIdentifier(e.ElementLink as EntityTypeHasPreferredIdentifier, oldPreferredIdentifier); }
private bool DetermineWhetherFromIsPreferredIdentifier() { foreach (ConstraintRoleSequence constraintRoleSequence in myFromRole.ConstraintRoleSequenceCollection) { UniquenessConstraint uniquenessConstraint = constraintRoleSequence as UniquenessConstraint; if (uniquenessConstraint != null && uniquenessConstraint.IsPreferred) { return(true); } } return(false); }
public void UniqueUniqueImplied_1a(Store store) { myTestServices.LogValidationErrors("Start with one Implication Error"); ORMModel model = store.ElementDirectory.FindElements <ORMModel>()[0]; UniquenessConstraint constraint = (UniquenessConstraint)model.ConstraintsDictionary.GetElement("ExternalUniquenessConstraint_A").SingleElement; myTestServices.LogMessage("Removing the Implied Uniqueness Costraint..."); using (Transaction t = store.TransactionManager.BeginTransaction("Remove Implied Uniqueness Costraint")) { constraint.Delete(); t.Commit(); } myTestServices.LogValidationErrors("Error is removed with removal of Implied Constraint"); }
/// <summary> /// Helper function for preferred identifier validation /// </summary> private static void InvalidateForPreferredIdentifier(UniquenessConstraint constraint) { if (!constraint.IsInternal && !constraint.IsDeleted) { foreach (PresentationElement pel in PresentationViewsSubject.GetPresentation(constraint)) { ExternalConstraintShape constraintShape = pel as ExternalConstraintShape; if (constraintShape != null) { constraintShape.Invalidate(true); } } } }
/// <summary> /// Binarizes the unary <see cref="FactType"/> specified by <paramref name="unaryFactType"/>, defaulting /// to using open-world assumption. The caller is responsible for making sure <paramref name="unaryFactType"/> /// is in fact a unary fact type. /// </summary> public static void BinarizeUnary(FactType unaryFactType, INotifyElementAdded notifyAdded) { Partition partition = unaryFactType.Partition; Store store = partition.Store; IHasAlternateOwner <FactType> toAlternateOwner; IAlternateElementOwner <FactType> alternateFactTypeOwner = (null == (toAlternateOwner = unaryFactType as IHasAlternateOwner <FactType>)) ? null : toAlternateOwner.AlternateOwner; LinkedElementCollection <RoleBase> roleCollection = unaryFactType.RoleCollection; Debug.Assert(roleCollection.Count == 1, "Unaries should only have one role."); Role unaryRole = (Role)roleCollection[0]; string implicitBooleanValueTypeName = GetImplicitBooleanValueTypeName(unaryRole); // UNDONE: We are using open-world assumption now // Setup the mandatory constraint (for closed-world assumption) //MandatoryConstraint mandatoryConstraint = MandatoryConstraint.CreateSimpleMandatoryConstraint(unaryRole); //mandatoryConstraint.Model = unaryFactType.Model; //if (notifyAdded != null) //{ // notifyAdded.ElementAdded(mandatoryConstraint, true); //} // Setup the uniqueness constraint (to make the newly binarized FactType valid) if (unaryRole.SingleRoleAlethicUniquenessConstraint == null) { UniquenessConstraint uniquenessConstraint = UniquenessConstraint.CreateInternalUniquenessConstraint(unaryFactType); uniquenessConstraint.RoleCollection.Add(unaryRole); if (notifyAdded != null) { notifyAdded.ElementAdded(uniquenessConstraint, true); } } // Setup the boolean role (to make the FactType a binary) Role implicitBooleanRole = new Role(partition, null); implicitBooleanRole.Name = unaryRole.Name; // Setup the boolean value type (because the boolean role needs a role player) IAlternateElementOwner <ObjectType> alternateObjectTypeOwner = null; DomainClassInfo alternateCtor = (null != alternateFactTypeOwner && null != (alternateObjectTypeOwner = alternateFactTypeOwner as IAlternateElementOwner <ObjectType>)) ? alternateObjectTypeOwner.GetOwnedElementClassInfo(typeof(ObjectType)) : null; PropertyAssignment implicitBooleanProperty = new PropertyAssignment(ObjectType.IsImplicitBooleanValueDomainPropertyId, true); ObjectType implicitBooleanValueType = (alternateCtor != null) ? (ObjectType)partition.ElementFactory.CreateElement(alternateCtor, implicitBooleanProperty) : new ObjectType(partition, implicitBooleanProperty); Dictionary <object, object> contextInfo = 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[duplicateSignaturesKey] = null; addDuplicateSignaturesKey = true; } implicitBooleanValueType.Name = implicitBooleanValueTypeName; if (alternateCtor != null) { ((IHasAlternateOwner <ObjectType>)implicitBooleanValueType).AlternateOwner = alternateObjectTypeOwner; } else { implicitBooleanValueType.Model = unaryFactType.ResolvedModel; } if (notifyAdded != null) { notifyAdded.ElementAdded(implicitBooleanValueType, true); } } finally { if (removeDuplicateNamesKey) { contextInfo.Remove(duplicateNamesKey); } if (addDuplicateSignaturesKey) { contextInfo[duplicateSignaturesKey] = null; } } implicitBooleanValueType.DataType = store.ElementDirectory.FindElements <TrueOrFalseLogicalDataType>(false)[0]; // Set value constraint on implicit boolean ValueType for open-world assumption ValueTypeValueConstraint implicitBooleanValueConstraint = implicitBooleanValueType.ValueConstraint = new ValueTypeValueConstraint(partition, null); // Add the true-only ValueRange to the value constraint for open-world assumption implicitBooleanValueConstraint.ValueRangeCollection.Add(new ValueRange(partition, new PropertyAssignment(ValueRange.MinValueDomainPropertyId, bool.TrueString), new PropertyAssignment(ValueRange.MaxValueDomainPropertyId, bool.TrueString))); // Make the boolean value type the role player for the implicit boolean role implicitBooleanRole.RolePlayer = implicitBooleanValueType; // Add the boolean role to the FactType roleCollection.Add(implicitBooleanRole); if (notifyAdded != null) { notifyAdded.ElementAdded(implicitBooleanRole, true); } }
/// <summary> /// Overrideable shape painting for use after the paint helper is initialized /// </summary> /// <param name="e">The event arguments</param> /// <param name="helper">The initialized pain helper.</param> protected virtual void OnPaintShape(DiagramPaintEventArgs e, ref PaintHelper helper) { IConstraint constraint = AssociatedConstraint; RectangleD bounds = AbsoluteBounds; RectangleF boundsF = RectangleD.ToRectangleF(bounds); Graphics g = e.Graphics; const double cos45 = 0.70710678118654752440084436210485; Pen pen = helper.Pen; Brush brush = helper.Brush; bool noDeonticDot = false; switch (constraint.ConstraintType) { #region Frequency case ConstraintType.Frequency: { break; } #endregion #region Ring case ConstraintType.Ring: // Note: goto default here restores the frowny face. However, // with the error feedback, we already have UI indicating there // is a problem. noDeonticDot = true; break; #endregion #region ValueComparison case ConstraintType.ValueComparison: noDeonticDot = true; break; #endregion // ValueComparison #region Equality case ConstraintType.Equality: { double xOffset = bounds.Width * .3; float xLeft = (float)(bounds.Left + xOffset); float xRight = (float)(bounds.Right - xOffset); double yCenter = bounds.Top + bounds.Height / 2; double yOffset = (double)pen.Width * 1.0; float y = (float)(yCenter - yOffset); g.DrawLine(pen, xLeft, y, xRight, y); y = (float)(yCenter + yOffset); g.DrawLine(pen, xLeft, y, xRight, y); break; } #endregion #region Mandatory case ConstraintType.DisjunctiveMandatory: { // Draw the dot RectangleF shrinkBounds = boundsF; shrinkBounds.Inflate(-boundsF.Width * .22f, -boundsF.Height * .22f); g.FillEllipse(brush, shrinkBounds); if (null != ExclusiveOrConstraintCoupler.GetExclusiveOrExclusionConstraint((MandatoryConstraint)constraint)) { goto case ConstraintType.Exclusion; } break; } #endregion #region Exclusion case ConstraintType.Exclusion: { // Draw the X double offset = (bounds.Width + pen.Width) * (1 - cos45) / 2; float leftX = (float)(bounds.Left + offset); float rightX = (float)(bounds.Right - offset); float topY = (float)(bounds.Top + offset); float bottomY = (float)(bounds.Bottom - offset); g.DrawLine(pen, leftX, topY, rightX, bottomY); g.DrawLine(pen, leftX, bottomY, rightX, topY); break; } #endregion #region Uniqueness case ConstraintType.ExternalUniqueness: { // Draw a single line for a uniqueness constraint and a double // line for preferred uniqueness UniquenessConstraint euc = constraint as UniquenessConstraint; double widthAdjust = (double)pen.Width / 2; float xLeft = (float)(bounds.Left + widthAdjust); float xRight = (float)(bounds.Right - widthAdjust); if (euc.IsPreferred) { double yCenter = bounds.Top + bounds.Height / 2; double yOffset = (double)pen.Width * .7; float y = (float)(yCenter - yOffset); g.DrawLine(pen, xLeft, y, xRight, y); y = (float)(yCenter + yOffset); g.DrawLine(pen, xLeft, y, xRight, y); } else { float y = (float)(bounds.Top + bounds.Height / 2); g.DrawLine(pen, xLeft, y, xRight, y); } break; } #endregion #region Subset case ConstraintType.Subset: { RectangleD arcBounds = bounds; double shrinkBy = -bounds.Height * .35; double yOffset = pen.Width * .7; double xOffset = shrinkBy * .35; arcBounds.Inflate(shrinkBy, shrinkBy); arcBounds.Offset(xOffset, -yOffset); g.DrawArc(pen, RectangleD.ToRectangleF(arcBounds), 90, 180); float xLeft = (float)arcBounds.Center.X; float xRight = (float)(bounds.Right + shrinkBy - xOffset); float y = (float)arcBounds.Top; g.DrawLine(pen, xLeft, y, xRight, y); y = (float)arcBounds.Bottom; g.DrawLine(pen, xLeft, y, xRight, y); y = (float)(arcBounds.Bottom + yOffset + yOffset); g.DrawLine(pen, (float)arcBounds.Left, y, xRight, y); break; } #endregion #region Fallback (default) default: { // Draws a frowny face float eyeY = boundsF.Y + (boundsF.Height / 3); PointF leftEyeStart = new PointF(boundsF.X + (boundsF.Width * 0.3f), eyeY); PointF leftEyeEnd = new PointF(boundsF.X + (boundsF.Width * 0.4f), eyeY); PointF rightEyeStart = new PointF(boundsF.X + (boundsF.Width * 0.6f), eyeY); PointF rightEyeEnd = new PointF(boundsF.X + (boundsF.Width * 0.7f), eyeY); g.DrawLine(pen, leftEyeStart, leftEyeEnd); g.DrawLine(pen, rightEyeStart, rightEyeEnd); float mouthLeft = boundsF.X + (boundsF.Width * 0.25f); float mouthTop = boundsF.Y + (boundsF.Height * 0.55f); RectangleF mouthRectangle = new RectangleF(mouthLeft, mouthTop, boundsF.Width * 0.5f, boundsF.Height * 0.25f); g.DrawArc(pen, mouthRectangle, 180, 180); break; } #endregion } if (!noDeonticDot && constraint.Modality == ConstraintModality.Deontic) { float startPenWidth = pen.Width; pen.Width = startPenWidth * .70f; float boxSide = (float)((1 - cos45) * bounds.Width); g.FillEllipse(this.StyleSet.GetBrush(DiagramBrushes.DiagramBackground), (float)bounds.Left, (float)bounds.Top, boxSide, boxSide); g.DrawArc(pen, (float)bounds.Left, (float)bounds.Top, boxSide, boxSide, 0, 360); pen.Width = startPenWidth; } }
/// <summary> /// Reverses the binarization process performed by <see cref="BinarizeUnary"/>. Typically used when /// <paramref name="binarizedUnaryFactRoleCollection"/> no longer qualifies as the roles for a /// binarized unary <see cref="FactType"/>. /// </summary> private static void DebinarizeUnary(LinkedElementCollection <RoleBase> binarizedUnaryFactRoleCollection, bool deleteImplicitBooleanRole, INotifyElementAdded notifyAdded) { // UNDONE: We need to make sure the debinarization happens BEFORE the implied Objectification rules run on the binarized unary FactType. // The default implied role is the second one, walk the collection backwards int roleCount = binarizedUnaryFactRoleCollection.Count; for (int i = roleCount - 1; i >= 0; --i) { Role implicitBooleanRole; ObjectType implicitBooleanValueType; if (null != (implicitBooleanRole = binarizedUnaryFactRoleCollection[i].Role) && null != (implicitBooleanValueType = implicitBooleanRole.RolePlayer) && implicitBooleanValueType.IsImplicitBooleanValue) { // Delete the implicit boolean value type (which will also remove any value constraints on it) // Note that changes to IsImplicitBooleanValue are intentionally blocked so that the // deleted implied ValueType can be identified as such by events as well as rules. // implicitBooleanValueType.IsImplicitBooleanValue = false; bool ruleDisabled = false; RuleManager ruleManager = null; try { if (notifyAdded == null) { ruleManager = implicitBooleanRole.Store.RuleManager; ruleManager.DisableRule(typeof(ObjectTypePlaysRoleDeletedRuleClass)); ruleDisabled = true; } if (deleteImplicitBooleanRole) { // We delete the role first so that rules do not // try to recreate and implied fact type for this rule // if it is part of an objectified FactType. implicitBooleanRole.Delete(); --roleCount; if (!implicitBooleanValueType.IsDeleted) { // The Objectification.RolePlayerDeletingRule rule will delet this automatically implicitBooleanValueType.Delete(); } } else { implicitBooleanValueType.Delete(); } } finally { if (ruleDisabled) { ruleManager.EnableRule(typeof(ObjectTypePlaysRoleDeletedRuleClass)); } } // Clear implied constraints for (int j = 0; j < roleCount; ++j) { Role role = binarizedUnaryFactRoleCollection[j] as Role; if (role != null) { if (role != implicitBooleanRole) { role.Name = ""; // Role cardinality is for unary fact types only, eliminate // it if we switch away. role.Cardinality = null; } UniquenessConstraint singleRoleAlethicUniquenessConstraint = role.SingleRoleAlethicUniquenessConstraint; if (singleRoleAlethicUniquenessConstraint != null) { // Delete the uniqueness constraint singleRoleAlethicUniquenessConstraint.Delete(); } // UNDONE: We are using open-world assumption now //MandatoryConstraint simpleMandatoryConstraint = role.SimpleMandatoryConstraint; //if (simpleMandatoryConstraint != null && simpleMandatoryConstraint.Modality == ConstraintModality.Alethic) //{ // // Delete the simple mandatory constraint (for closed-world assumption), if present // simpleMandatoryConstraint.Delete(); //} } } break; } } }
/// <summary> /// Rule helper method /// </summary> private static void ProcessPreferredIdentifier(EntityTypeHasPreferredIdentifier link, UniquenessConstraint preferredIdentifier) { if (preferredIdentifier == null) { preferredIdentifier = link.PreferredIdentifier; } if (!preferredIdentifier.IsDeleted) { if (preferredIdentifier.IsInternal) { LinkedElementCollection <FactType> factTypes = preferredIdentifier.FactTypeCollection; if (factTypes.Count == 1) { FactType factType = factTypes[0]; Objectification objectification; InvalidateAssociatedDisplay(factType); if (null != (objectification = factType.Objectification)) { foreach (FactType linkFactType in objectification.ImpliedFactTypeCollection) { InvalidateAssociatedDisplay(linkFactType); } } } } else { InvalidateAssociatedDisplay(preferredIdentifier); } } }
/// <summary> /// Add a source shape or commit/cancel the action by forwarding the /// click to the base class, or modify the current role sequence by handling /// the click locally. /// </summary> /// <param name="e">MouseActionEventArgs</param> protected override void OnClicked(MouseActionEventArgs e) { switch (myPendingOnClickedAction) { case OnClickedAction.Commit: myPendingOnClickedAction = OnClickedAction.Normal; // Letting the click through to the base ConnectAction // at this point (a constraint is selected and a role has been // double-clicked) will force the connect action to finish. base.OnClicked(e); return; case OnClickedAction.CheckForCommit: myPendingOnClickedAction = OnClickedAction.Normal; break; } DiagramMouseEventArgs args = CurrentDiagramArgs as DiagramMouseEventArgs; if (args != null) { DiagramItem item = args.DiagramHitTestInfo.HitDiagramItem; ModelElement currentElement = null; foreach (ModelElement elem in item.RepresentedElements) { currentElement = elem; break; } UniquenessConstraint internalUniquenessConstraint; RoleBase roleBase; if (null != (internalUniquenessConstraint = currentElement as UniquenessConstraint) && internalUniquenessConstraint.IsInternal) { if (mySourceShape == null) { // Let the click through to the base to officially begin the drag action base.OnClicked(e); mySourceShape = item.Shape as FactTypeShape; myIUC = internalUniquenessConstraint; } } else if (mySourceShape != null) { if (null != (roleBase = currentElement as RoleBase)) { Role role = roleBase.Role; if (role.FactType == mySourceShape.AssociatedFactType) { // Add or remove the role IList<Role> roles = SelectedRoleCollection; int roleIndex = roles.IndexOf(role); bool forceRedraw = false; if (roleIndex >= 0) { // Only remove a role when the control key is down. Otherwise, // there is no way to double-click on a previously selected // role without turning it off, and this is a natural gesture. // Add shift key as well for discoverability. if (0 != (0xff00 & GetKeyState(Keys.ControlKey)) || 0 != (0xff00 & GetKeyState(Keys.ShiftKey))) { forceRedraw = true; roles.RemoveAt(roleIndex); } } else { forceRedraw = true; roles.Add(role); } if (mySourceShape != null) { myPendingOnClickedAction = OnClickedAction.CheckForCommit; } if (forceRedraw) { // Force the shape to redraw Debug.Assert(mySourceShape != null); //source shape should have been set mySourceShape.Invalidate(true); } } } else if (currentElement is ORMDiagram) { base.OnClicked(e); // Let through to allow a cancel } } } }
private static void EnsureSingleColumnUniqueAndMandatory(SubtypeFact subtypeFact, Role role, bool requireMandatory, INotifyElementAdded notifyAdded) { LinkedElementCollection <ConstraintRoleSequence> sequences = role.ConstraintRoleSequenceCollection; int sequenceCount = sequences.Count; bool haveUniqueness = false; bool haveMandatory = !requireMandatory; SetConstraint ic; for (int i = sequenceCount - 1; i >= 0; --i) { ic = sequences[i] as SetConstraint; if (ic != null && ic.Constraint.ConstraintIsInternal) { if (ic.RoleCollection.Count == 1 && ic.Modality == ConstraintModality.Alethic) { switch (ic.Constraint.ConstraintType) { case ConstraintType.InternalUniqueness: if (haveUniqueness) { ic.Delete(); } else { haveUniqueness = true; } break; case ConstraintType.SimpleMandatory: if (haveMandatory) { ic.Delete(); } else { haveMandatory = true; } break; } } else { ic.Delete(); } } } if (!haveUniqueness || !haveMandatory) { IHasAlternateOwner <FactType> toAlternateOwner; IAlternateElementOwner <SetConstraint> alternateConstraintOwner; if (null != (toAlternateOwner = subtypeFact as IHasAlternateOwner <FactType>) && null != (alternateConstraintOwner = toAlternateOwner.AlternateOwner as IAlternateElementOwner <SetConstraint>)) { if (!haveUniqueness) { ic = UniquenessConstraint.CreateInternalUniquenessConstraint(subtypeFact); ic.RoleCollection.Add(role); notifyAdded.ElementAdded(ic, true); } } if (!haveMandatory) { ic = MandatoryConstraint.CreateSimpleMandatoryConstraint(role); notifyAdded.ElementAdded(ic, true); } } }
/// <summary>See <see cref="ORMShapeToolboxHelperBase.CreateElementToolPrototype"/>.</summary> protected sealed override ElementGroupPrototype CreateElementToolPrototype(Store store, Guid domainClassId) { // WARNING: This method is _extremely_ order-sensitive. If the order that the toolbox items are listed // in the .dsl file changes, or if the DSL Tools text template that is used to generate ORMShapeModelToolboxHelperBase // changes, this method will most likely need to be changed as well. ElementGroup group = null; bool unknownItem = false; if (domainClassId.Equals(ObjectType.DomainClassId)) { group = new ElementGroup(store); ObjectType objectType = new ObjectType(store); group.AddGraph(objectType, true); switch (myObjectTypeCount++) { case 0: // EntityType - We don't need to do anything else... break; case 1: // ValueType // Do not try to set the IsValueType property here. IsValueType picks // up the default data type for the model, which can only be done // when the model is known. Instead, flag the element so that it // can be set during MergeRelate on the model. group.UserData = ORMModel.ValueTypeUserDataKey; break; case 2: // ObjectifiedFactType group.AddGraph(new Objectification(objectType, AddFactType(store, group, 2)), false); break; default: unknownItem = true; break; } } else if (domainClassId.Equals(FactType.DomainClassId)) { group = new ElementGroup(store); Debug.Assert(myFactTypeCount < 3); AddFactType(store, group, ++myFactTypeCount); } else if (domainClassId.Equals(ExclusiveOrConstraintCoupler.DomainClassId)) { group = new ElementGroup(store); MandatoryConstraint mandatory = new MandatoryConstraint(store, null); group.AddGraph(mandatory, true); ExclusionConstraint exclusion = new ExclusionConstraint(store, null); group.AddGraph(exclusion, true); group.AddGraph(new ExclusiveOrConstraintCoupler(mandatory, exclusion), false); } else if (domainClassId.Equals(UniquenessConstraint.DomainClassId)) { group = new ElementGroup(store); if (myUniquenessConstraintCount == 0) { // Add this here so that we can distinguish between internal and external uniqueness // constraints without unpacking the model. We want to merge internals into a fact // and externals into the model. group.UserData = ORMModel.InternalUniquenessConstraintUserDataKey; group.AddGraph(UniquenessConstraint.CreateInternalUniquenessConstraint(store.DefaultPartition), true); } else { Debug.Assert(myUniquenessConstraintCount == 1); group.AddGraph(new UniquenessConstraint(store), true); } myUniquenessConstraintCount++; } return((group == null || unknownItem) ? base.CreateElementToolPrototype(store, domainClassId) : group.CreatePrototype()); }
/// <summary> /// Central function to return member variables to a clean state. /// Called by the constructor and the deactivation sequence. /// </summary> private void Reset() { myAddedConstraint = null; myDropTargetShape = null; }
/// <summary> /// Set this mouse action as the active action on the /// diagram of the given shape. /// </summary> /// <param name="attachToShape">The shape the constraint is being attached to.</param> /// <param name="constraint">The constraint being connected.</param> /// <param name="clientView">The active DiagramClientView</param> public void ChainMouseAction(FactTypeShape attachToShape, UniquenessConstraint constraint, DiagramClientView clientView) { DiagramView activeView = Diagram.ActiveDiagramView; if (activeView != null) { // Move on to the selection action clientView.ActiveMouseAction = this; // Now emulate a mouse click in the middle of the added constraint. The click // actions provide a starting point for the connect action, so a mouse move // provides a drag line. Point emulateClickPoint = clientView.WorldToDevice(attachToShape.GetAbsoluteConstraintAttachPoint(constraint)); DiagramMouseEventArgs mouseEventArgs = new DiagramMouseEventArgs(new MouseEventArgs(MouseButtons.Left, 1, emulateClickPoint.X, emulateClickPoint.Y, 0), clientView); MouseDown(mouseEventArgs); Click(new DiagramPointEventArgs(emulateClickPoint.X, emulateClickPoint.Y, PointRelativeTo.Client, clientView)); MouseUp(mouseEventArgs); attachToShape.Invalidate(true); // An extra move lets us chain when the mouse is not on the design surface, // such as when we are being activated via the task list. MouseMove(mouseEventArgs); ORMDiagram.SelectToolboxItem(activeView, ResourceStrings.ToolboxInternalUniquenessConstraintItemId); FactTypeShape.ActiveInternalUniquenessConstraintConnectAction = this; } }
/// <summary> /// Rule helper method /// </summary> private static void ProcessPreferredIdentifier(EntityTypeHasPreferredIdentifier link, UniquenessConstraint preferredIdentifier) { if (preferredIdentifier == null) { preferredIdentifier = link.PreferredIdentifier; } if (!preferredIdentifier.IsDeleted) { if (preferredIdentifier.IsInternal) { LinkedElementCollection<FactType> factTypes = preferredIdentifier.FactTypeCollection; if (factTypes.Count == 1) { FactType factType = factTypes[0]; Objectification objectification; InvalidateAssociatedDisplay(factType); if (null != (objectification = factType.Objectification)) { foreach (FactType linkFactType in objectification.ImpliedFactTypeCollection) { InvalidateAssociatedDisplay(linkFactType); } } } } else { InvalidateAssociatedDisplay(preferredIdentifier); } } }
/// <summary> /// Ensure that the <see cref="UniquenessConstraint.IsPreferred"/> property is read-only /// when the <see cref="FactType.InternalUniquenessConstraintChangeRule"/> is /// unable to make it <see langword="true"/>. /// Make sure the <see cref="SetConstraint.Modality">Modality</see> property /// is read only for single-role uniqueness constraints on the Objectification end of an implied fact type. /// </summary> protected override bool IsPropertyDescriptorReadOnly(ElementPropertyDescriptor propertyDescriptor) { UniquenessConstraint uniquenessConstraint; Guid propertyId = propertyDescriptor.DomainPropertyInfo.Id; LinkedElementCollection <Role> roles; FactType factType; if (propertyId == UniquenessConstraint.IsPreferredDomainPropertyId) { uniquenessConstraint = ModelElement; ObjectType identifierFor = uniquenessConstraint.PreferredIdentifierFor; if (identifierFor != null) { // If this is the preferred identifier for an objectifying type and // is the only alethic internal uniqueness constraint for the nested FactType, // then it will automatically be readded as the preferred identifier if it is // changed to false. Don't allow it to change. if (uniquenessConstraint.IsInternal && null != (factType = identifierFor.NestedFactType)) { UniquenessConstraint candidate = null; LinkedElementCollection <Role> constraintRoles = uniquenessConstraint.RoleCollection; if (constraintRoles.Count == 1 && constraintRoles[0] is ObjectifiedUnaryRole) // Note there is only one FactType for an internal constraint { candidate = uniquenessConstraint; } else if (factType == uniquenessConstraint.FactTypeCollection[0] && null == factType.UnaryRole) { foreach (UniquenessConstraint constraint in factType.GetInternalConstraints <UniquenessConstraint>()) { if (constraint.Modality == ConstraintModality.Alethic) { if (candidate != null || constraint != uniquenessConstraint) { candidate = null; break; } else { candidate = constraint; } } } } if (candidate != null) { bool haveSupertype = false; ObjectType.WalkSupertypeRelationships( identifierFor, delegate(SubtypeFact subtypeFact, ObjectType type, int depth) { // Note that we do not check if the supertype is a preferred // path here, only that supertypes are available. haveSupertype = true; return(ObjectTypeVisitorResult.Stop); }); return(!haveSupertype); } } return(false); } else { return(!uniquenessConstraint.TestAllowPreferred(null, false)); } } else if (propertyId == UniquenessConstraint.ModalityDomainPropertyId && (uniquenessConstraint = ModelElement).Store != null && uniquenessConstraint.IsInternal && (roles = uniquenessConstraint.RoleCollection).Count == 1 && ((factType = roles[0].FactType).ImpliedByObjectification != null || factType is SubtypeFact)) { return(true); } return(base.IsPropertyDescriptorReadOnly(propertyDescriptor)); }
/// <summary> /// An IMS event to track the shape element added to the associated /// diagram during this connect action. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void InternalConstraintAddedEvent(object sender, ElementAddedEventArgs e) { if (myAddedConstraint == null) { UniquenessConstraint candidate = e.ModelElement as UniquenessConstraint; if (candidate != null && candidate.IsInternal) { ORMDiagram d = Diagram as ORMDiagram; if (d != null) { // Find the shape associated with the fact type we added to LinkedElementCollection<FactType> candidateFacts = candidate.FactTypeCollection; if (candidateFacts.Count != 0) { FactTypeShape shape = d.FindShapeForElement(candidateFacts[0]) as FactTypeShape; if (shape != null) { myDropTargetShape = shape; myAddedConstraint = candidate; } } } } } }
/// <summary> /// Add a source shape or commit/cancel the action by forwarding the /// click to the base class, or modify the current role sequence by handling /// the click locally. /// </summary> /// <param name="e">MouseActionEventArgs</param> protected override void OnClicked(MouseActionEventArgs e) { switch (myPendingOnClickedAction) { case OnClickedAction.Commit: myPendingOnClickedAction = OnClickedAction.Normal; // Letting the click through to the base ConnectAction // at this point (a constraint is selected and a role has been // double-clicked) will force the connect action to finish. base.OnClicked(e); return; case OnClickedAction.CheckForCommit: myPendingOnClickedAction = OnClickedAction.Normal; break; } DiagramMouseEventArgs args = CurrentDiagramArgs as DiagramMouseEventArgs; if (args != null) { DiagramItem item = args.DiagramHitTestInfo.HitDiagramItem; ModelElement currentElement = null; foreach (ModelElement elem in item.RepresentedElements) { currentElement = elem; break; } UniquenessConstraint internalUniquenessConstraint; RoleBase roleBase; if (null != (internalUniquenessConstraint = currentElement as UniquenessConstraint) && internalUniquenessConstraint.IsInternal) { if (mySourceShape == null) { // Let the click through to the base to officially begin the drag action base.OnClicked(e); mySourceShape = item.Shape as FactTypeShape; myIUC = internalUniquenessConstraint; } } else if (mySourceShape != null) { if (null != (roleBase = currentElement as RoleBase)) { Role role = roleBase.Role; if (role.FactType == mySourceShape.AssociatedFactType) { // Add or remove the role IList <Role> roles = SelectedRoleCollection; int roleIndex = roles.IndexOf(role); bool forceRedraw = false; if (roleIndex >= 0) { // Only remove a role when the control key is down. Otherwise, // there is no way to double-click on a previously selected // role without turning it off, and this is a natural gesture. // Add shift key as well for discoverability. if (0 != (0xff00 & GetKeyState(Keys.ControlKey)) || 0 != (0xff00 & GetKeyState(Keys.ShiftKey))) { forceRedraw = true; roles.RemoveAt(roleIndex); } } else { forceRedraw = true; roles.Add(role); } if (mySourceShape != null) { myPendingOnClickedAction = OnClickedAction.CheckForCommit; } if (forceRedraw) { // Force the shape to redraw Debug.Assert(mySourceShape != null); //source shape should have been set mySourceShape.Invalidate(true); } } } else if (currentElement is ORMDiagram) { base.OnClicked(e); // Let through to allow a cancel } } } }
/// <summary> /// Get all value roles including all roles directly attached to the provided /// object type and any roles descended from this one through prefererred identifiers. /// Walks the opposite direction of <see cref="Role.GetValueRoles()"/> /// </summary> /// <param name="anchorType">The <see cref="ObjectType"/> to walk descended roles for</param> /// <param name="unattachedRole">A role to test that is not currently attached to the anchorType. /// If unattachedRole is not null, then only this role will be tested. Otherwise, all current played /// roles will be walked.</param> /// <param name="unattachedPreferredIdentifier">A preferred identifier to test that is not currently /// attached to the anchorType.</param> /// <param name="visitor">A <see cref="ValueRoleVisitor"/> callback delegate.</param> public static void WalkDescendedValueRoles(ObjectType anchorType, Role unattachedRole, UniquenessConstraint unattachedPreferredIdentifier, ValueRoleVisitor visitor) { ValueTypeHasDataType dataTypeLink = anchorType.GetDataTypeLink(); if (null == unattachedPreferredIdentifier && null != (dataTypeLink = anchorType.GetDataTypeLink())) { ObjectType unattachedRolePlayer; WalkDescendedValueRoles( (unattachedRole != null) ? new Role[] { unattachedRole } as IList<Role> : anchorType.PlayedRoleCollection, RolePathObjectTypeRoot.GetLinksToRolePathCollection(anchorType), dataTypeLink, anchorType.ValueConstraint, null, (null == unattachedRole || null == (unattachedRolePlayer = unattachedRole.RolePlayer)) ? false : !unattachedRolePlayer.IsValueType, visitor); } else { LinkedElementCollection<Role> roles; UniquenessConstraint preferredIdentifier; if (null != (preferredIdentifier = unattachedPreferredIdentifier ?? anchorType.ResolvedPreferredIdentifier) && (roles = preferredIdentifier.RoleCollection).Count == 1) { Role currentRole = roles[0]; Role[] valueRoles = currentRole.GetValueRoles(); if (valueRoles != null) { ValueConstraint nearestValueConstraint = null; int valueRolesCount = valueRoles.Length; for (int i = valueRolesCount - 1; i >= 0; --i) { nearestValueConstraint = valueRoles[i].ValueConstraint; if (nearestValueConstraint != null) { break; } } ObjectType valueType = valueRoles[0].RolePlayer; dataTypeLink = valueType.GetDataTypeLink(); if (nearestValueConstraint == null) { nearestValueConstraint = valueType.ValueConstraint; } RoleBase nextSkipRole = currentRole.OppositeRoleAlwaysResolveProxy; if (nextSkipRole != null) { WalkDescendedValueRoles( (unattachedRole != null) ? new Role[] { unattachedRole } as IList<Role> : anchorType.PlayedRoleCollection, RolePathObjectTypeRoot.GetLinksToRolePathCollection(anchorType), dataTypeLink, nearestValueConstraint, nextSkipRole.Role, true, visitor); } } } } }