private static string GetImplicitBooleanValueTypeName(Role unaryRole) { string unaryRoleName = unaryRole.Name; ObjectType unaryRolePlayer = unaryRole.RolePlayer; FactType unaryFactType; IReading defaultReading; if (unaryRolePlayer != null && !string.IsNullOrEmpty(unaryRoleName)) { // UNDONE: Localize the space? (Some languages may not use spaces between words.) return unaryRolePlayer.Name + " " + unaryRoleName; } else if (null != (defaultReading = (unaryFactType = unaryRole.FactType).GetDefaultReading())) { return string.Format(CultureInfo.InvariantCulture, defaultReading.Text.Replace('-', ' '), (unaryRolePlayer != null) ? unaryRolePlayer.Name.Replace('-', ' ') : ResourceStrings.ModelReadingEditorMissingRolePlayerText); } return unaryFactType.Name; }
/// <summary> /// Attempts to fix a PopulationMandatoryError /// </summary> /// <param name="error">Error to be corrected</param> /// <param name="autoCorrectRole">The <see cref="Role"/> to correct the error for.</param> /// <param name="autoCorrectFactType">If the <paramref name="autoCorrectRole"/> is not specified, select /// a unique constrained role from this <see cref="FactType"/></param> /// <returns><see langword="true"/> if the error was automatically corrected.</returns> public bool AutoCorrectMandatoryError(PopulationMandatoryError error, Role autoCorrectRole, FactType autoCorrectFactType) { bool retVal = false; ObjectTypeInstance objectInstance = error.ObjectTypeInstance; LinkedElementCollection<Role> constraintRoles = error.MandatoryConstraint.RoleCollection; // If the constraint has multiple roles, then we need to pick // a role to activate. This is trivial for a simple mandatory // constraint, or if a role in the constraint is selected. However, // if we have only a FactType selection, then there may be multiple // potential roles in the constraint for ring situations. if (constraintRoles.Count == 1) { autoCorrectRole = constraintRoles[0]; autoCorrectFactType = autoCorrectRole.FactType; } else { // We're only interested in one selected item, this code // path should not be running with multiple items selected. if (autoCorrectRole == null) { if (autoCorrectFactType != null) { foreach (Role testRole in constraintRoles) { if (testRole.FactType == autoCorrectFactType) { if (autoCorrectRole == null) { autoCorrectRole = testRole; } else { // Ambiguous selection, there is nothing further we can do autoCorrectRole = null; break; } } } } } else if (autoCorrectFactType == null) { autoCorrectFactType = autoCorrectRole.FactType; } } if (autoCorrectFactType != null) { // Verify the selection, which needs to be set before this method is called SubtypeFact subtypeFact; bool correctSelection; if (CurrentFrameVisibility != FrameVisibility.Visible) { // If the window is not active then it does not have a selection this.ShowNoActivate(); } if (null != (subtypeFact = autoCorrectFactType as SubtypeFact) && subtypeFact.ProvidesPreferredIdentifier) { ObjectType subtype = subtypeFact.Subtype; ObjectType selectedEntityType; FactType objectifiedFactType; correctSelection = (null != (selectedEntityType = SelectedEntityType) && selectedEntityType == subtype) || (null != (objectifiedFactType = subtype.NestedFactType) && objectifiedFactType == SelectedFactType); } else if (!(correctSelection = SelectedFactType == autoCorrectFactType)) { FactTypeInstanceImplication implication = new FactTypeInstanceImplication(autoCorrectFactType); correctSelection = implication.IsImplied && implication.ImpliedProxyRole == null && implication.IdentifyingSupertype != null && implication.ImpliedByEntityType == SelectedEntityType; } if (correctSelection) { this.Show(); if (autoCorrectRole != null) { retVal = myEditor.AutoCorrectMandatoryError(error, autoCorrectRole); } } } return retVal; }
/// <summary> /// If a role is actively selected, return the 0-based selection index, /// or -1 if the role is not actively selected. /// </summary> /// <param name="role">A role to test</param> /// <returns>0-based role index, or -1 if not selected</returns> public int GetActiveRoleIndex(Role role) { if (IsActive && mySelectedRoles != null) { return mySelectedRoles.IndexOf(role); } return -1; }
/// <summary> /// Sets the isVisible property for the given Role /// </summary> private static void SetRoleNameDisplay(Role role, FactTypeShape parentShape, bool shouldDisplay, bool shouldRemove) { if (!shouldRemove) { Diagram.FixUpDiagram(role.FactType, role); } LinkedElementCollection<PresentationElement> pels = PresentationViewsSubject.GetPresentation(role); int pelCount = pels.Count; for (int i = pelCount - 1; i >= 0; --i) { RoleNameShape rns = pels[i] as RoleNameShape; if (rns != null && (parentShape == null || rns.ParentShape == parentShape)) { if (shouldRemove) { rns.Delete(); } else { if (shouldDisplay) { rns.Show(); } else { rns.Hide(); rns.Size = SizeD.Empty; } } } } }
/// <summary> /// Checks the <see cref="IConstraint"/>s on the binarized unary <see cref="FactType"/> as specified by /// the <see cref="FactType"/>'s <paramref name="unaryRole"/> and the <paramref name="implicitBooleanRole"/>. /// </summary> private static bool ValidateConstraints(Role unaryRole, Role implicitBooleanRole) { ConstraintRoleSequence unaryRoleUniquenessConstraint = unaryRole.SingleRoleAlethicUniquenessConstraint; if (unaryRoleUniquenessConstraint == null) { // The alethic single role uniqueness constraint is missing from the unary role. return false; } // Validate the constraints on the unary role foreach (ConstraintRoleSequence constraintRoleSequence in unaryRole.ConstraintRoleSequenceCollection) { IConstraint constraint = constraintRoleSequence.Constraint; switch (constraint.ConstraintType) { case ConstraintType.InternalUniqueness: case ConstraintType.ExternalUniqueness: case ConstraintType.Frequency: if (constraintRoleSequence != unaryRoleUniquenessConstraint) { // The unary role has a constraint attached to it that it shouldn't return false; } break; } } // Validate the constraints on the implicit boolean role foreach (ConstraintRoleSequence constraintRoleSequence in implicitBooleanRole.ConstraintRoleSequenceCollection) { IConstraint constraint = constraintRoleSequence.Constraint; switch (constraint.ConstraintType) { case ConstraintType.DisjunctiveMandatory: case ConstraintType.Equality: case ConstraintType.Exclusion: case ConstraintType.Ring: case ConstraintType.SimpleMandatory: case ConstraintType.Subset: case ConstraintType.InternalUniqueness: // The implicit boolean role has a constraint attached to it that it shouldn't return false; } } return true; }
/// <summary> /// Resolve the name that will be used for a <see cref="ConceptTypeChild"/> given the <see cref="Role"/> it's resulting from. /// </summary> /// <param name="role">The <see cref="Role"/> that the <see cref="ConceptTypeChild"/> is resulting from.</param> /// <returns>The name to use for the <see cref="ConceptTypeChild"/>.</returns> private static string ResolveRoleName(Role role) { // HACK: This is only here until we implement a better alternative. string name = role.Name; if (String.IsNullOrEmpty(name)) { name = role.RolePlayer.Name; } return name; }
private static void ProcessRolePlayerDeleted(ObjectTypePlaysRole link, ObjectType rolePlayer, Role role) { if (role == null) { role = link.PlayedRole; } if (rolePlayer == null) { rolePlayer = link.RolePlayer; } FilterModifiedFactType(role.FactType, false); RoleProxy proxy = role.Proxy; if (proxy != null) { FilterModifiedFactType(proxy.FactType, false); } FilterModifiedObjectType(rolePlayer); }
/// <summary> /// Creates a new <see cref="FactType"/> with the specified <paramref name="arity"/>. /// </summary> /// <param name="store"> /// The <see cref="Store"/> in which the new <see cref="FactType"/> should be created. /// </param> /// <param name="group"> /// The <see cref="ElementGroup"/> to which the new <see cref="FactType"/> and its <see cref="Role"/>s should /// be added. /// </param> /// <param name="arity"> /// The number of <see cref="Role"/>s that the new <see cref="FactType"/> should contain. /// </param> /// <returns> /// The newly created <see cref="FactType"/>. /// </returns> /// <remarks> /// The new <see cref="FactType"/> is added to <paramref name="group"/> as a root element. /// </remarks> private static FactType AddFactType(Store store, ElementGroup group, int arity) { FactType factType = new FactType(store, null); group.AddGraph(factType, true); LinkedElementCollection<RoleBase> roles = factType.RoleCollection; for (int i = 0; i < arity; i++) { Role role = new Role(store); roles.Add(role); group.AddGraph(role); } return factType; }
/// <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); } } } } }
/// <summary> /// Recursively retrieve a sequence of roles that are /// allowed to have value constraints. /// </summary> /// <param name="currentRole">The current role to test</param> /// <param name="rolePlayer">The role player for the current role.</param> /// <param name="depth">The current depth. Pass in -1 to skip populating the output /// roles and 0 to seed recursion.</param> /// <param name="roles">An array of roles. The roles are in reverse order, so /// roles[0] will always have a ValueType as its RolePlayer.</param> /// <returns>true if the current role can have a value constraint</returns> private static bool GetValueRoles(Role currentRole, ObjectType rolePlayer, int depth, out Role[] roles) { roles = null; if (depth == 100 || depth == -101) { // Cycling return false; } if (rolePlayer != null) { if (rolePlayer.IsValueType) { if (depth < 0) { return true; } // This is the first element in the chain and // can be used to retrieve the value type. roles = new Role[depth + 1]; roles[0] = currentRole; } else { UniquenessConstraint preferredIdentifier = rolePlayer.ResolvedPreferredIdentifier; LinkedElementCollection<Role> identifierRoles; Role nextRole; if (preferredIdentifier != null && (identifierRoles = preferredIdentifier.RoleCollection).Count == 1 && (nextRole = identifierRoles[0]).FactType != currentRole.FactType) { if (depth < 0) { return GetValueRoles(nextRole, nextRole.RolePlayer, depth - 1, out roles); } if (GetValueRoles(nextRole, nextRole.RolePlayer, depth + 1, out roles)) { roles[roles.Length - depth - 1] = currentRole; } } } } return roles != null; }
public void DisposeHelper() { myRole = null; }
public void Initialize(Role role) { myRole = role; }
/// <summary> /// Replaces <paramref name="existingRole"/> with <paramref name="replacementRole"/>, including altering all relationships /// in which <paramref name="existingRole"/> participates. /// </summary> public static void ReplaceRole(Role existingRole, Role replacementRole) { // Synchronize the names replacementRole.Name = existingRole.Name; // Alter the relationships that refer to existingRole to instead refer to replacementRole ReadOnlyCollection<ElementLink> elementLinks = DomainRoleInfo.GetAllElementLinks(existingRole); int elementLinksCount = elementLinks.Count; for (int i = 0; i < elementLinksCount; i++) { ElementLink elementLink = elementLinks[i]; ReadOnlyCollection<DomainRoleInfo> domainRoles = elementLink.GetDomainRelationship().DomainRoles; DomainRoleInfo domainRoleInfo; if (DomainRoleInfo.GetSourceRolePlayer(elementLink) == existingRole) { Debug.Assert(DomainRoleInfo.GetTargetRolePlayer(elementLink) != existingRole, "We shouldn't have a relationship from ourselves to ourselves."); domainRoleInfo = domainRoles[0]; Debug.Assert(domainRoleInfo.IsSource); } else { domainRoleInfo = domainRoles[1]; Debug.Assert(!domainRoleInfo.IsSource); } DomainRoleInfo.SetRolePlayer(elementLink, domainRoleInfo.Id, replacementRole); } }
/// <summary> /// Determines the index of a specific Role in the list, resolving /// RoleProxy elements as needed /// </summary> /// <param name="roleBaseCollection">The list in which to locate the role</param> /// <param name="value">The Role to locate in the list</param> /// <returns>index of object</returns> public static int IndexOf(LinkedElementCollection<RoleBase> roleBaseCollection, Role value) { int count = roleBaseCollection.Count; for (int i = 0; i < count; ++i) { if (roleBaseCollection[i].Role == value) { return i; } } return -1; }
public ColumnPathStep(Role fromRole, ObjectType targetObjectType, ObjectType alternateObjectType, ColumnPathStepFlags flags) { myFromRole = fromRole; myObjectType = targetObjectType; myAlternateObjectType = alternateObjectType; myFlags = flags; }
private static void GetMappingPatterns(Role towardsRole, Role fromRole, out MappingUniquenessPattern uniquenessPattern, out MappingMandatoryPattern mandatoryPattern) { if (towardsRole.FactType is SubtypeFact) { uniquenessPattern = MappingUniquenessPattern.Subtype; mandatoryPattern = (towardsRole is SubtypeMetaRole) ? MappingMandatoryPattern.TowardsRoleMandatory : MappingMandatoryPattern.OppositeRoleMandatory; } else { bool towardsRoleUnique; bool towardsRoleMandatory; bool towardsRoleImpliedMandatory; bool fromRoleUnique; bool fromRoleMandatory; bool fromRoleImpliedMandatory; bool oneToOne = false; GetUniqueAndMandatory(towardsRole, out towardsRoleUnique, out towardsRoleMandatory, out towardsRoleImpliedMandatory); GetUniqueAndMandatory(fromRole, out fromRoleUnique, out fromRoleMandatory, out fromRoleImpliedMandatory); uniquenessPattern = towardsRoleUnique ? ((oneToOne = fromRoleUnique) ? MappingUniquenessPattern.OneToOne : MappingUniquenessPattern.OneToMany) : MappingUniquenessPattern.ManyToOne; if (oneToOne && (fromRoleImpliedMandatory ^ towardsRoleImpliedMandatory)) { // Adjust mandatory patterns to ignore implied mandatory on naturally asymmetric // one-to-one relationships. if (fromRoleImpliedMandatory) { fromRoleMandatory = !towardsRoleMandatory; } else { towardsRoleMandatory = !fromRoleMandatory; } } mandatoryPattern = towardsRoleMandatory ? (fromRoleMandatory ? MappingMandatoryPattern.BothRolesMandatory : MappingMandatoryPattern.TowardsRoleMandatory) : (fromRoleMandatory ? MappingMandatoryPattern.OppositeRoleMandatory : MappingMandatoryPattern.NotMandatory); } }
private static void GetUniqueAndMandatory(Role role, out bool hasUniqueness, out bool hasMandatory, out bool mandatoryIsImplied) { hasUniqueness = false; hasMandatory = false; mandatoryIsImplied = false; LinkedElementCollection<ConstraintRoleSequence> constraintRoleSequences = role.ConstraintRoleSequenceCollection; int roleSequenceCount = constraintRoleSequences.Count; for (int i = 0; i < roleSequenceCount; ++i) { ConstraintRoleSequence roleSequence = constraintRoleSequences[i]; IConstraint constraint = roleSequence.Constraint; if (constraint != null && constraint.Modality == ConstraintModality.Alethic) { switch (constraint.ConstraintType) { case ConstraintType.SimpleMandatory: hasMandatory = true; if (hasUniqueness) { return; } break; case ConstraintType.InternalUniqueness: // Ignore spanning internal constraints, these are treated as external // uniquenesses in the binarized form if (roleSequence.RoleCollection.Count == 1) { hasUniqueness = true; if (hasMandatory) { return; } } break; case ConstraintType.ImpliedMandatory: if (roleSequence.RoleCollection.Count == 1) { hasMandatory = true; mandatoryIsImplied = true; if (hasUniqueness) { return; } } break; } } } }
/// <summary> /// Helper method to recursively walk value roles. A value role /// is any role that is allowed to have a value constraint. /// </summary> /// <param name="playedRoles">Roles from an ObjectType to walk. The assumption is made that the /// owning ObjectType is either a value type or has a preferred identifier with exactly one role</param> /// <param name="dataTypeLink">The data type information for the constraint</param> /// <param name="pathRoots">The <see cref="RolePathObjectTypeRoot"/> relationships from a role path associated /// with the root path.</param> /// <param name="previousValueConstraint">The value constraint nearest this value role. /// Any value constraint on the current set of roles must be a subset of the previousValueConstraint.</param> /// <param name="skipRole">A role to skip. If the playedRoles came from a preferred identifier, /// then the skipRole is the opposite role.</param> /// <param name="walkSubtypes">true to walk subtypes. Should be true if the playedRoles come from an /// EntityType and false if they come from a ValueType</param> /// <param name="visitor">The callback delegate</param> /// <returns>true to continue iteration</returns> private static bool WalkDescendedValueRoles(IList<Role> playedRoles, IList<RolePathObjectTypeRoot> pathRoots, ValueTypeHasDataType dataTypeLink, ValueConstraint previousValueConstraint, Role skipRole, bool walkSubtypes, ValueRoleVisitor visitor) { int count = pathRoots.Count; for (int i = 0; i < count; ++i) { RolePathObjectTypeRoot pathRoot = pathRoots[i]; if (!visitor(null, null, pathRoot, dataTypeLink, pathRoot.ValueConstraint, previousValueConstraint)) { return false; } } count = playedRoles.Count; for (int i = 0; i < count; ++i) { Role role = playedRoles[i]; SupertypeMetaRole supertypeRole; if (role == skipRole) { // Nothing to do } else if (null != (supertypeRole = role as SupertypeMetaRole)) { if (walkSubtypes) { SubtypeFact subtypeFact = (SubtypeFact)role.FactType; ObjectType subtype; if (subtypeFact.ProvidesPreferredIdentifier && null != (subtype = subtypeFact.Subtype) && subtype.PreferredIdentifier == null) { if (!WalkDescendedValueRoles(subtype.PlayedRoleCollection, RolePathObjectTypeRoot.GetLinksToRolePathCollection(subtype), dataTypeLink, previousValueConstraint, null, true, visitor)) { return false; } } } } else if (!(role is SubtypeMetaRole)) { RoleValueConstraint currentValueConstraint = role.ValueConstraint; if (!visitor(role, null, null, dataTypeLink, currentValueConstraint, previousValueConstraint)) { return false; } if (currentValueConstraint != null && !currentValueConstraint.IsDeleted) { previousValueConstraint = currentValueConstraint; } foreach (PathedRole pathedRole in PathedRole.GetLinksToRolePathCollection(role)) { // UNDONE: VALUEROLE This does not correctly report a value constraint from a previous // path node. Note that this, as well as allowing value restrictions on supertype roles // (and possibly other patterns), can result in multiple previous value constraints, so // the callback signature may possibly need to be modified here. As of changeset 1442, // none of the callbacks use the previousValueConstraint information, so we can ignore // this for now. // Note that we visit for the pathed role even if no value constraint is present // to allow processing for this pathed role. if (!visitor(role, pathedRole, null, dataTypeLink, pathedRole.ValueConstraint, previousValueConstraint)) { return false; } } // Walk sequences to find a single-role preferred identifier so // we can get to the next link. LinkedElementCollection<ConstraintRoleSequence> sequences = role.ConstraintRoleSequenceCollection; int sequencesCount = sequences.Count; for (int j = 0; j < sequencesCount; ++j) { UniquenessConstraint constraint = sequences[j] as UniquenessConstraint; ObjectType identifierFor; if (null != (constraint = sequences[j] as UniquenessConstraint) && null != (identifierFor = constraint.PreferredIdentifierFor) && constraint.RoleCollection.Count == 1) { RoleBase nextSkipRole = role.OppositeRoleAlwaysResolveProxy; if (nextSkipRole == null) { return false; } if (!WalkDescendedValueRoles(identifierFor.PlayedRoleCollection, RolePathObjectTypeRoot.GetLinksToRolePathCollection(identifierFor), dataTypeLink, previousValueConstraint, nextSkipRole.Role, true, visitor)) { return false; } } } } } return true; }
/// <summary> /// for regular relationships /// </summary> /// <param name="relation"></param> /// <param name="source"></param> /// <param name="target"></param> /// <param name="notifyAdded"></param> /// <param name="associationCounter"></param> /// <returns></returns> private static bool CreateBinaryAssociation(ConceptTypeChild relation, ConceptType source, ConceptType target, INotifyElementAdded notifyAdded, ref int associationCounter) { if (BinaryAssociationHasConceptTypeChild.GetBinaryAssociation(relation).Count > 0) { //it has already been created return(true); } else if (EntityTypeIsPrimarilyForConceptType.GetEntityType(target) != null) { #region create association BinaryAssociation b = new BinaryAssociation(relation.Store, new PropertyAssignment[] { new PropertyAssignment(BinaryAssociation.NumberDomainPropertyId, associationCounter++) }); //new BinaryAssociationHasConceptTypeChild(b, relation); BinaryAssociationHasConceptTypeChild.GetConceptTypeChildPath(b).Add(relation); Role r1 = new Role(relation.Store, new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, source.Name) }); Role r2 = new Role(relation.Store, new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, target.Name) }); b.RoleCollection.Add(r1); b.RoleCollection.Add(r2); EntityType sourceEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(source); EntityType targetEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(target); sourceEntity.RoleCollection.Add(r1); targetEntity.RoleCollection.Add(r2); sourceEntity.BarkerErModel.BinaryAssociationCollection.Add(b); #endregion //determine whether roles are mandatory or optional List <ConceptTypeChild> links = new List <ConceptTypeChild>(1); links.Add(relation); r1.IsMandatory = AllStepsMandatory(targetEntity, links); if (relation is ConceptTypeAssimilatesConceptType) { r2.IsMandatory = AllStepsMandatory(sourceEntity, links); } #region determine whether roles are multivalued or not - and possibly rename ORMCore.ObjectType sourceObjectType = ConceptTypeIsForObjectType.GetObjectType(source); ORMCore.ObjectType targetObjectType = ConceptTypeIsForObjectType.GetObjectType(target); ORMCore.UniquenessConstraint uSource = null, uTarget = null; foreach (ORMCore.FactType factType in ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(relation)) { Debug.Assert(factType.RoleCollection.Count == 2, "Error when mapping to Barker ER; the fact type is not binary"); foreach (ORMCore.RoleBase r in factType.RoleCollection) { //need to use RoleBase because we might run into RoleProxy ORMCore.Role role = r.Role; foreach (ORMCore.ConstraintRoleSequence constraintRoleSequence in role.ConstraintRoleSequenceCollection) { ORMCore.UniquenessConstraint uninquenessConstraint = constraintRoleSequence as ORMCore.UniquenessConstraint; if (uninquenessConstraint != null && //check that it's a uniqueness constraint uninquenessConstraint.Modality == ORMCore.ConstraintModality.Alethic && //check it's alethic uninquenessConstraint.IsInternal) //check it's internal { if (role.RolePlayer == sourceObjectType) { uSource = uninquenessConstraint; } if (role.RolePlayer == targetObjectType) { uTarget = uninquenessConstraint; } } } } //name the roles properly //TODO this is a hack; proper name generation is yet to be implemented foreach (ORMCore.ReadingOrder order in factType.ReadingOrderCollection) { string text = order.ReadingText; int first = text.IndexOf('}') + 1; text = text.Substring(first, text.LastIndexOf('{') - first); text = text.Trim(); if (!string.IsNullOrEmpty(text) && order.RoleCollection != null && order.RoleCollection.Count > 0 && order.RoleCollection[0].Role != null) { ORMCore.ObjectType o = order.RoleCollection[0].Role.RolePlayer; if (o == sourceObjectType) { r1.PredicateText = text; } else if (o == targetObjectType) { r2.PredicateText = text; } } } } if (uSource != null && uSource == uTarget) { //it's many-to-many r1.IsMultiValued = true; r2.IsMultiValued = true; } else if (uSource == null || uTarget == null) { //it's one-to-many r1.IsMultiValued = uSource != null; r2.IsMultiValued = uTarget != null; } else if (uSource != null && uTarget != null) { //it's one-to-one r1.IsMultiValued = false; r2.IsMultiValued = false; } else { Debug.Fail("Found a fact type with no uniqueness constraints!"); } #endregion #region primary id? foreach (Uniqueness u in UniquenessIncludesConceptTypeChild.GetUniquenessCollection(relation)) { if (u.IsPreferred) { r1.IsPrimaryIdComponent = true; break; } } #endregion //notify elements added if (notifyAdded != null) { notifyAdded.ElementAdded(b, true); notifyAdded.ElementAdded(r1, true); notifyAdded.ElementAdded(r2, true); } return(true); } else { //should not create binary association in this case return(false); } }
/// <summary> /// Helper function to update the mandatory dot in response to events /// </summary> private static void UpdateDotDisplayOnMandatoryConstraintChange(Role role) { InvalidateRolePlayerLinks(role); if (OptionsPage.CurrentEntityRelationshipBinaryMultiplicityDisplay == EntityRelationshipBinaryMultiplicityDisplay.InformationEngineering) { // The opposite links also need updating RoleBase oppositeRole = role.OppositeRole; if (oppositeRole != null) { InvalidateRolePlayerLinks(oppositeRole.Role); } } }
private static void NotifyRoleChanged(INotifySurveyElementChanged eventNotify, Role role) { foreach (ConstraintRoleSequence sequence in role.ConstraintRoleSequenceCollection) { UniquenessConstraint uniquenessConstraint; EntityTypeHasPreferredIdentifier identifierLink; if (null != (uniquenessConstraint = sequence as UniquenessConstraint) && null != (identifierLink = EntityTypeHasPreferredIdentifier.GetLinkToPreferredIdentifierFor(uniquenessConstraint))) { NotifyErrorStateChanged(eventNotify, identifierLink); } } eventNotify.ElementChanged(role, SurveyGlyphQuestionTypes); eventNotify.ElementRenamed(role); }
/// <summary> /// Helper function to invalidate roles /// </summary> private static void InvalidateRolePlayerLinks(Role role) { foreach (ObjectTypePlaysRole objectTypePlaysRole in DomainRoleInfo.GetElementLinks<ObjectTypePlaysRole>(role, ObjectTypePlaysRole.PlayedRoleDomainRoleId)) { foreach (PresentationElement pel in PresentationViewsSubject.GetPresentation(objectTypePlaysRole)) { ShapeElement shape = pel as ShapeElement; if (shape != null) { shape.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) { Store store = unaryFactType.Store; 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); uniquenessConstraint.Model = unaryFactType.Model; if (notifyAdded != null) { notifyAdded.ElementAdded(uniquenessConstraint, true); } } // Setup the boolean role (to make the FactType a binary) Role implicitBooleanRole = new Role(store, null); implicitBooleanRole.Name = unaryRole.Name; // Setup the boolean value type (because the boolean role needs a role player) ObjectType implicitBooleanValueType = new ObjectType(store, new PropertyAssignment(ObjectType.IsImplicitBooleanValueDomainPropertyId, true)); Dictionary<object, object> contextInfo = store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo; try { contextInfo[ORMModel.AllowDuplicateNamesKey] = null; implicitBooleanValueType.Name = implicitBooleanValueTypeName; implicitBooleanValueType.Model = unaryFactType.Model; if (notifyAdded != null) { notifyAdded.ElementAdded(implicitBooleanValueType, true); } } finally { contextInfo.Remove(ORMModel.AllowDuplicateNamesKey); } 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(implicitBooleanValueType.Store, null); // Add the true-only ValueRange to the value constraint for open-world assumption implicitBooleanValueConstraint.ValueRangeCollection.Add(new ValueRange(store, 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> /// 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); } } } } }
private static void RedrawOwningFactType(Role role) { FactType factType = role.FactType; if (factType != null) { LinkedElementCollection<PresentationElement> pels = PresentationViewsSubject.GetPresentation(factType); int pelsCount = pels.Count; for (int i = 0; i < pelsCount; ++i) { ShapeElement shape = pels[i] as ShapeElement; if (shape != null) { shape.Invalidate(true); } } } }
/// <summary> /// Removes the RoleNameShape from the associated Role /// </summary> public static void RemoveRoleNameShapeFromRole(Role role) { LinkedElementCollection<PresentationElement> pels = PresentationViewsSubject.GetPresentation(role); int pelCount = pels.Count; for (int i = pelCount - 1; i >= 0; --i) { RoleNameShape pel = pels[i] as RoleNameShape; if (pel != null) { pel.Delete(); } } }