/// <summary> /// ChangeRule: typeof(ORMSolutions.ORMArchitect.Core.ObjectModel.Role) /// </summary> private static void RoleNameChangedRule(ElementPropertyChangedEventArgs e) { if (e.DomainProperty.Id == ORMCore.Role.NameDomainPropertyId) { ORMCore.FactType factType = ((ORMCore.Role)e.ModelElement).FactType; if (null != factType) { FactTypeNamePartChanged(factType); } } }
/// <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)}); }
/// <summary> /// Internal constraints are not fully connected at this point (FactSetConstraint instances /// are not implicitly constructed until a later phase), so we need to work a little harder /// to remove them. /// </summary> /// <param name="factType">The fact to clear of external constraints</param> private static void RemoveFactType(FactType factType) { LinkedElementCollection <RoleBase> factRoles = factType.RoleCollection; int roleCount = factRoles.Count; for (int i = 0; i < roleCount; ++i) { Role role = factRoles[i].Role; LinkedElementCollection <ConstraintRoleSequence> sequences = role.ConstraintRoleSequenceCollection; int sequenceCount = sequences.Count; for (int j = sequenceCount - 1; j >= 0; --j) { SetConstraint ic = sequences[j] as SetConstraint; if (ic != null && ic.Constraint.ConstraintIsInternal) { ic.Delete(); } } } factType.Delete(); }
/// <summary> /// DeletingRule: typeof(FactTypeHasRole) /// </summary> private static void FactTypeHasRoleDeletingRule(ElementDeletingEventArgs e) { FactType factType = (e.ModelElement as FactTypeHasRole).FactType; if (!factType.IsDeleting && !(factType is QueryBase || factType is SubtypeFact)) { LinkedElementCollection <RoleBase> factRoles = factType.RoleCollection; int? unaryIndex = GetUnaryRoleIndex(factRoles); Role implicitRole; ObjectType implicitRolePlayer; if (unaryIndex.HasValue && null != (implicitRole = factRoles[(unaryIndex.Value == 0) ? 1 : 0].Role) && null != (implicitRolePlayer = implicitRole.RolePlayer)) { // Delete the Implicit Boolean ValueType implicitRole.Delete(); // Delete the Unary FactType factType.Delete(); } } }
/// <summary> /// RolePlayerChangeRule: typeof(ObjectTypePlaysRole) /// </summary> private static void ObjectTypePlaysRoleRolePlayerChangedRule(RolePlayerChangedEventArgs e) { bool rolePlayerRoleChanged = e.DomainRole.Id == ObjectTypePlaysRole.RolePlayerDomainRoleId; ObjectType rolePlayer = rolePlayerRoleChanged ? (ObjectType)e.OldRolePlayer : ((ObjectTypePlaysRole)e.ElementLink).RolePlayer; if (rolePlayer.IsImplicitBooleanValue) { throw new InvalidOperationException(ResourceStrings.ModelExceptionFactTypeEnforceNoImplicitBooleanValueTypeRolePlayerChange); } if (!rolePlayerRoleChanged) { FactType factType = ((Role)e.OldRolePlayer).FactType; if (factType != null) { FrameworkDomainModel.DelayValidateElement(factType, DelayValidateUnaryBinarization); } factType = ((Role)e.NewRolePlayer).FactType; if (factType != null) { FrameworkDomainModel.DelayValidateElement(factType, DelayValidateUnaryBinarization); } } }
private static void FactTypeNamePartChanged(ORMCore.FactType factType) { bool checkPrimaryFactType = true; ORMCore.Objectification objectification = factType.Objectification; if (null != objectification) { foreach (ORMCore.FactType impliedFactType in objectification.ImpliedFactTypeCollection) { foreach (ConceptTypeChild child in ConceptTypeChildHasPathFactType.GetConceptTypeChild(impliedFactType)) { ValidateConceptTypeChildNameChanged(child); } } checkPrimaryFactType = factType.UnaryRole != null; } if (checkPrimaryFactType) { foreach (ConceptTypeChild child in ConceptTypeChildHasPathFactType.GetConceptTypeChild(factType)) { ValidateConceptTypeChildNameChanged(child); } } }
/// <summary> /// Verify that all <see cref="ReadingOrder"/>s have unique <see cref="ReadingOrder.RoleCollection">role collections</see> /// </summary> /// <param name="element">A <see cref="FactType"/></param> private static void DelayValidateReadingOrderCollation(ModelElement element) { if (element.IsDeleted) { return; } FactType factType = (FactType)element; LinkedElementCollection <ReadingOrder> ordersCollection = factType.ReadingOrderCollection; int orderCount = ordersCollection.Count; if (orderCount > 1) { // Get all orders in a collatable form, starting by caching information locally // so it is easily accessed. Note that this will also change the collection we're // iterating so we need to be careful about changes. ReadingOrder[] orders = new ReadingOrder[orderCount]; ordersCollection.CopyTo(orders, 0); LinkedElementCollection <RoleBase>[] roleCollections = new LinkedElementCollection <RoleBase> [orderCount]; for (int i = 0; i < orderCount; ++i) { roleCollections[i] = orders[i].RoleCollection; } // Priority is top down, so we move later readings into a higher reading order for (int i = 0; i < orderCount; ++i) { ReadingOrder currentOrder = orders[i]; for (int j = i + 1; j < orderCount; ++j) { ReadingOrder compareToOrder = orders[j]; if (compareToOrder != null) // Will be null if it has already been recognized as a duplicate { // These should all have the same count, but it doesn't hurt to be defensive LinkedElementCollection <RoleBase> currentRoles = roleCollections[i]; LinkedElementCollection <RoleBase> compareToRoles = roleCollections[j]; int roleCount = currentRoles.Count; if (roleCount == compareToRoles.Count) { int k = 0; for (; k < roleCount; ++k) { if (currentRoles[k] != compareToRoles[k]) { break; } } if (k == roleCount) { // Order is the same, collate the later readings up to the current order ReadOnlyCollection <ReadingOrderHasReading> readingLinks = ReadingOrderHasReading.GetLinksToReadingCollection(compareToOrder); int readingCount = readingLinks.Count; for (int l = 0; l < readingCount; ++l) { readingLinks[l].ReadingOrder = currentOrder; } orders[j] = null; } } } } } } }
/// <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 } )); } } } } } } }
/// <summary> /// Processes the specified FactType and adds the appropriate constraints based on the specified filter /// </summary> private static void ProcessFactTypeConstraints(FactType factType, VerbalizationReportContent reportContent, IDictionary<ConstraintType, IList<IConstraint>> typedConstraintLists) { foreach (IFactConstraint factConstraint in factType.FactConstraintCollection) { IConstraint constraint = factConstraint.Constraint; ConstraintType constraintType = constraint.ConstraintType; VerbalizationReportContent allowedContent; switch (constraintType) { case ConstraintType.DisjunctiveMandatory: allowedContent = VerbalizationReportContent.DisjunctiveMandatoryConstraints; break; case ConstraintType.Equality: allowedContent = VerbalizationReportContent.EqualityConstraints; break; case ConstraintType.Exclusion: allowedContent = VerbalizationReportContent.ExclusionConstraints; break; case ConstraintType.ExternalUniqueness: allowedContent = VerbalizationReportContent.ExternalUniquenessConstraints; break; case ConstraintType.Frequency: allowedContent = VerbalizationReportContent.FrequencyConstraints; break; case ConstraintType.InternalUniqueness: allowedContent = VerbalizationReportContent.InternalUniquenessConstraints; break; case ConstraintType.Ring: allowedContent = VerbalizationReportContent.RingConstraints; break; case ConstraintType.SimpleMandatory: allowedContent = VerbalizationReportContent.SimpleMandatoryConstraints; break; case ConstraintType.Subset: allowedContent = VerbalizationReportContent.SubsetConstraints; break; default: continue; } if (0 != (reportContent & allowedContent)) { IList<IConstraint> typedList = typedConstraintLists[constraintType]; if (!typedList.Contains(constraint)) { typedList.Add(constraint); } } } }
/// <summary> /// Select the primary reading of the order matching /// the display order of the fact, if one doesn't /// exist select the new entry. /// </summary> /// <param name="fact">Fact</param> public void ActivateReading(FactType fact) { myReadingEditor.ActivateReading(fact); }
private static void ExcludeFactType(FactType factType) { AbstractionModel model = AbstractionModelIsForORMModel.GetAbstractionModel(factType.Model); if (model != null) { ExcludeFactType(factType, model, false, null); } }
/// <summary> /// Consider a new <see cref="FactType"/> for absorption. Any FactType /// that is no longer excluded is also consider to be new to the absorption algorithm. /// </summary> private static void AddFactType(FactType factType) { if (!factType.IsDeleted) { FrameworkDomainModel.DelayValidateElement(factType, AddFactTypeDelayed); } }
public static void ProcessFactType(FactType factType, INotifyElementAdded notifyAdded) { LinkedElementCollection <RoleBase> roleCollection = factType.RoleCollection; int roleCollectionCount = roleCollection.Count; if (roleCollectionCount == 1) { // If we have a unary, binarize it BinarizeUnary(factType, notifyAdded); return; } else if (roleCollectionCount == 2) { // If we have a binary that has an implicit boolean role in it, make sure it matches the pattern Role implicitBooleanRole = GetImplicitBooleanRole(roleCollection); if (implicitBooleanRole != null) { Role unaryRole = implicitBooleanRole.OppositeRole.Role; Debug.Assert(unaryRole != null); // Make sure the implicit boolean role has the same name as the unary role implicitBooleanRole.Name = unaryRole.Name; string implicitBooleanValueTypeName = GetImplicitBooleanValueTypeName(unaryRole); if (implicitBooleanRole.RolePlayer.Name != implicitBooleanValueTypeName) { Dictionary <object, object> contextInfo = factType.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.Remove(duplicateSignaturesKey); addDuplicateSignaturesKey = true; } implicitBooleanRole.RolePlayer.Name = implicitBooleanValueTypeName; } finally { if (removeDuplicateNamesKey) { contextInfo.Remove(duplicateNamesKey); } if (addDuplicateSignaturesKey) { contextInfo[duplicateSignaturesKey] = null; } } } if (!ValidateConstraints(unaryRole, implicitBooleanRole) || !ValidateImplicitBooleanValueType(implicitBooleanRole.RolePlayer)) { LinkedElementCollection <RoleBase> roles = factType.RoleCollection; DebinarizeUnary(roles, false, notifyAdded); // Append to the reading orders LinkedElementCollection <ReadingOrder> readingOrders = factType.ReadingOrderCollection; int readingOrderCount = readingOrders.Count; for (int i = 0; i < readingOrderCount; ++i) { ReadingOrder order = readingOrders[i]; LinkedElementCollection <RoleBase> readingRoles = order.RoleCollection; if (!readingRoles.Contains(implicitBooleanRole)) { readingRoles.Add(implicitBooleanRole); LinkedElementCollection <Reading> readings = order.ReadingCollection; int readingCount = readings.Count; for (int j = 0; j < readingCount; ++j) { readings[j].SetAutoText(readings[j].Text + " {1}"); } } } } } } else { // If we have an n-ary, remove any implicit boolean roles in it for (int i = roleCollectionCount - 1; i >= 0; --i) { Role implicitBooleanRole = roleCollection[i].Role; if (implicitBooleanRole != null && implicitBooleanRole.RolePlayer != null && implicitBooleanRole.RolePlayer.IsImplicitBooleanValue) { DebinarizeUnary(factType.RoleCollection, true, notifyAdded); break; } } } }
/// <summary> /// A <see cref="FactType"/> has been directly or indirectly modified in /// such a way that its exclusion status in the absorption process may change. /// </summary> /// <param name="factType">The modified <see cref="FactType"/></param> /// <param name="filterImpliedFactTypes">Set to <see langword="true"/> to check for and filter implied fact types</param> private static void FilterModifiedFactType(FactType factType, bool filterImpliedFactTypes) { if (factType != null && !factType.IsDeleted) { FrameworkDomainModel.DelayValidateElement(factType, FilterModifiedFactTypeDelayed); Objectification objectification; if (filterImpliedFactTypes && null != (objectification = factType.Objectification)) { foreach (FactType impliedFactType in objectification.ImpliedFactTypeCollection) { FrameworkDomainModel.DelayValidateElement(impliedFactType, FilterModifiedFactTypeDelayed); } FrameworkDomainModel.DelayValidateElement(objectification.NestingType, FilterModifiedObjectTypeDelayed); } } }
/// <summary> /// Initializes a new instance of <see cref="ObjectifyingEntityTypePropertyDescriptor"/>. /// </summary> public ObjectifyingEntityTypePropertyDescriptor(FactType sourcePlayer, DomainRoleInfo domainRole, Attribute[] sourceDomainRoleInfoAttributes) : base(sourcePlayer, domainRole, sourceDomainRoleInfoAttributes) { // The base class constructor has already checked domainRole for null. if (domainRole.Id != Objectification.NestingTypeDomainRoleId) { throw new ArgumentException(); } }
/// <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> /// 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; } } } }
private static void SignificantFactTypeChange(FactType factType) { if (factType != null && !factType.IsDeleted && !ORMElementGateway.IsElementExcluded(factType)) { FrameworkDomainModel.DelayValidateElement(factType, SignificantFactTypeChangeDelayed); } }
/// <summary> /// The constraint pattern for a <see cref="FactType"/> may have changed /// </summary> private static void FactTypeConstraintPatternChanged(FactType factType) { if (factType != null && !factType.IsDeleted && !ORMElementGateway.IsElementExcluded(factType)) { FrameworkDomainModel.DelayValidateElement(factType, FactTypeConstraintPatternChangedDelayed); } }
/// <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> /// Initializes a new instance of the <see cref="FactTypeVerbalizationWrapper"/> class. /// </summary> /// <param name="verbalizationObject">The verbalization object.</param> public FactTypeVerbalizationWrapper(FactType verbalizationObject) { myVerbalizationObject = verbalizationObject; }
/// <summary> /// Determine if an <see cref="FactType"/> should be considered during /// absorption. Considers the state of the FactType, and the current exclusion /// markings on its role players. /// </summary> /// <param name="factType">The <see cref="FactType"/> to test</param> /// <param name="ignoreRolePlayer">No not excluded the <paramref name="factType"/> because this <see cref="ObjectType"/> is currently excluded.</param> /// <param name="ignoreRolePlayersFilteredForThisFactType">Do block consideration because a role player is filtered for this <paramref name="factType"/>.</param> /// <returns><see langword="true"/> if the <paramref name="factType"/> passes all necessary conditions for consideration.</returns> private static bool ShouldConsiderFactType(FactType factType, ObjectType ignoreRolePlayer, bool ignoreRolePlayersFilteredForThisFactType) { // Note that any changes to the list of errors must correspond to changes in // FactTypeErrorAddedRule and FactTypeErrorDeletedRule if (null == factType.InternalUniquenessConstraintRequiredError && null == factType.ImpliedInternalUniquenessConstraintError) { if (!(factType is SubtypeFact)) { // Ignore non-stored derived fact types FactTypeDerivationRule rule; FactTypeDerivationExpression expression; if (null != (rule = factType.DerivationRule)) { if (rule.DerivationCompleteness == DerivationCompleteness.FullyDerived && (!rule.ExternalDerivation || rule.DerivationStorage == DerivationStorage.NotStored)) { return false; } } else if (null != (expression = factType.DerivationExpression)) { if (expression.DerivationStorage == DerivationExpressionStorageType.Derived) { return false; } } } foreach (RoleBase role in factType.RoleCollection) { ObjectType rolePlayer = role.Role.RolePlayer; if (rolePlayer == null || (ignoreRolePlayer != rolePlayer && IsElementExcluded(rolePlayer) && !(!ignoreRolePlayersFilteredForThisFactType || ShouldConsiderObjectType(rolePlayer, factType, true)))) { return false; } } return true; } return false; }
private static void ProcessFactTypeForObjectificationDeleted(FactType factType) { if (!factType.IsDeleted && factType.UnaryRole == null) { FilterModifiedFactType(factType, false); // false because there are no implied facttypes without an objectification } }
private bool ShouldIgnoreFactType(FactType factType) { return ORMElementGateway.IsElementExcluded(factType) || (null != factType.Objectification && factType.UnaryRole == null); }
/// <summary> /// Initializes a new instance of ObjectTypePageFactTypeSection /// </summary> /// <param name="objectTypeSnippet">The object type snippet.</param> /// <param name="factType">The FactType.</param> public FactTypePageObjectTypeSection(ReportVerbalizationSnippetType objectTypeSnippet, FactType factType) { myObjectTypeSnippet = objectTypeSnippet; myFactType = factType; }
private static void ExcludeFactType(FactType factType, AbstractionModel model, bool forceCreate, NotifyORMElementExcluded notifyExcluded) { if (forceCreate || null == ExcludedORMModelElement.GetAbstractionModel(factType)) { if (null == factType.Objectification || factType.UnaryRole != null) { new ExcludedORMModelElement(factType, model); } if (notifyExcluded != null) { notifyExcluded(factType); } foreach (IFactConstraint constraint in factType.FactConstraintCollection) { ObjectType preferredFor = constraint.Constraint.PreferredIdentifierFor; if (preferredFor != null) { ExcludeObjectType(preferredFor, model, false, notifyExcluded); } } Objectification objectification; if (null != (objectification = factType.ImpliedByObjectification)) { ExcludeObjectType(objectification.NestingType, model, false, notifyExcluded); } } }
/// <summary> /// Initializes a new instance of FactTypePageReport /// </summary> public FactTypePageReport(FactType factType, VerbalizationReportContent reportContent, IVerbalizationSets<ReportVerbalizationSnippetType> snippets) { myFactType = factType; myReportContent = reportContent; mySnippets = snippets; }
private static void ProcessFactTypeForObjectificationAdded(FactType factType) { if (factType.UnaryRole == null) { ExcludedORMModelElement excludedLink = ExcludedORMModelElement.GetLinkToAbstractionModel(factType); if (excludedLink != null) { // We don't keep the exclusion link on objectified FactTypes, but deleting // it does not imply any additional processing because we were already not // considering this FactType excludedLink.Delete(); } else { FilterModifiedFactType(factType, false); // false because new implied FactTypes will get notifications on their own } } }
/// <summary> /// Retrieves a dictionary of all Constraints for the given Fact Type, filtered by the specified VerbalizationReportContent, indexed by ConstraintType /// </summary> /// <param name="factType">The Fact Type to retrieve constraints for</param> /// <param name="reportContent">The VerbalizationReportContent to filter constraints</param> /// <returns>dictionary of all Constraints for the given Fact Type, filtered by the specified VerbalizationReportContent, indexed by ConstraintType</returns> protected static IDictionary<ConstraintType, IList<IConstraint>> GetConstraintsFromFactType(FactType factType, VerbalizationReportContent reportContent) { IDictionary<ConstraintType, IList<IConstraint>> constraintList = GetConstraintDictionary(reportContent); ProcessFactTypeConstraints(factType, reportContent, constraintList); return constraintList; }
/// <summary> /// Determine if an <see cref="ObjectType"/> should be considered during /// absorption. Considers the object state, and the current exclusion /// markings on its preferred identifier. /// </summary> /// <param name="objectType">The <see cref="ObjectType"/> to test</param> /// <param name="ignoreFactTypesFilteredForThisObjectType">Don't block consideration of this <paramref name="objectType"/> if a <see cref="FactType"/> is excluded because this <see cref="ObjectType"/> is currently excluded.</param> /// <param name="ignoreFactType">Succeed even if this <see cref="FactType"/> is excluded. Can be <see langword="null"/>.</param> /// <returns><see langword="true"/> if the <paramref name="objectType"/> passes all necessary conditions for consideration.</returns> private static bool ShouldConsiderObjectType(ObjectType objectType, FactType ignoreFactType, bool ignoreFactTypesFilteredForThisObjectType) { // Look at the error states we care about. If any of these error // states are present then we do not consider. // Note that any changes to the list of errors must correspond to changes in // ObjectTypeErrorAddedRule and ObjectTypeErrorDeletedRule if (null == objectType.ReferenceSchemeError && null == objectType.PreferredIdentifierRequiresMandatoryError && null == objectType.CompatibleSupertypesError && null == objectType.DataTypeNotSpecifiedError) { UniquenessConstraint pid = objectType.PreferredIdentifier; if (pid != null) { // Make sure none of the associated FactTypes are not excluded. // Not that this causes a recursive situation, so the answers here // can change over time and an ObjectType that can be considered now // may not be valid for consideration by the time the model is processed. foreach (FactType factType in pid.FactTypeCollection) { if (factType != ignoreFactType && IsElementExcluded(factType)) { if (ignoreFactTypesFilteredForThisObjectType && ShouldConsiderFactType(factType, objectType, true)) { // This pattern is used only during delay validation. A cleaner model would // be a delegate callback, but it isn't worth the additional overhead given // that this would be the only code that would ever run there. FilterModifiedFactType(factType, true); } else { return false; } } } } else if (!objectType.IsValueType) { // If this is a subtype, then we need to resolve // the preferred identifier back to a non-excluded super type ObjectType preferridentifierFrom = null; ObjectType.WalkSupertypes( objectType, delegate(ObjectType type, int depth, bool isPrimary) { ObjectTypeVisitorResult result = ObjectTypeVisitorResult.Continue; if (isPrimary) { if (IsElementExcluded(type)) { result = ObjectTypeVisitorResult.Stop; } else if (type.PreferredIdentifier != null) { preferridentifierFrom = type; result = ObjectTypeVisitorResult.Stop; } else { result = ObjectTypeVisitorResult.SkipFollowingSiblings; // We already have the primary, no need to look further at this level } } else if (depth != 0) { result = ObjectTypeVisitorResult.SkipChildren; } return result; }); return preferridentifierFrom != null; } return true; } return false; }
/// <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> /// 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> /// Sets the isVisible for each of the Roles in the given FactType /// </summary> public static void SetRoleNameDisplay(FactType fact) { foreach (PresentationElement element in PresentationViewsSubject.GetPresentation(fact)) { FactTypeShape fts = element as FactTypeShape; if (fts != null) { bool shouldDisplay = false; bool shouldRemove = false; if (fts.DisplayRoleNames == DisplayRoleNames.UserDefault && OptionsPage.CurrentRoleNameDisplay == RoleNameDisplay.On) { shouldDisplay = true; } else if (fts.DisplayRoleNames == DisplayRoleNames.On) { shouldDisplay = true; } else if (fts.DisplayRoleNames == DisplayRoleNames.Off) { shouldRemove = true; } foreach (RoleBase roleBase in fact.RoleCollection) { Role role = roleBase as Role; if (role != null && !string.IsNullOrEmpty(role.Name)) { SetRoleNameDisplay(role, fts, shouldDisplay, shouldRemove); } } } } }
/// <summary> /// Determins wheather or not an object type has any possible (potential or decided) /// deep fact type mappings away from it. /// </summary> /// <param name="objectType">The object type to consider</param> /// <param name="excludedFactType">The fact type to ignore. This parameter may be null.</param> /// <param name="decidedFactTypeMappings">The decided <see cref="FactTypeMapping"/> objects.</param> /// <param name="undecidedFactTypeMappings">The undecided <see cref="FactTypeMapping"/> possibilities.</param> /// <returns>True if objectType has possible deep mappings away from it, otherwise false.</returns> private bool ObjectTypeHasPossibleDeepMappingsAway(ObjectType objectType, FactType excludedFactType, FactTypeMappingDictionary decidedFactTypeMappings, FactTypeMappingListDictionary undecidedFactTypeMappings) { LinkedElementCollection<Role> rolesPlayed = ObjectTypePlaysRole.GetPlayedRoleCollection(objectType); foreach (Role rolePlayed in rolesPlayed) { // NOTE: We don't need the ShouldIgnoreFactType filter here, because fact types that we want to ignore won't be in the dictionaries in the first place. FactType factType = rolePlayed.BinarizedFactType; if (factType == excludedFactType) { continue; } FactTypeMapping decidedFactTypeMapping; bool decidedFactTypeMappingExists = decidedFactTypeMappings.TryGetValue(factType, out decidedFactTypeMapping); FactTypeMappingList potentialFactTypeMappings; bool potentialFactTypeMappingsExist = undecidedFactTypeMappings.TryGetValue(factType, out potentialFactTypeMappings); // If there's a decided deep fact type mapping away from objectType... if (decidedFactTypeMappingExists && decidedFactTypeMapping.MappingDepth == MappingDepth.Deep && decidedFactTypeMapping.FromObjectType == objectType) { return true; } else if (potentialFactTypeMappingsExist) { foreach (FactTypeMapping potentialFactTypeMapping in potentialFactTypeMappings) { // If there's a potential deep fact type mapping away from objectType... if (potentialFactTypeMapping.MappingDepth == MappingDepth.Deep && potentialFactTypeMapping.FromObjectType == objectType) { return true; } } } } return false; }
/// <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 } )); } } } } } } }
public static void ProcessFactType(FactType factType, INotifyElementAdded notifyAdded) { LinkedElementCollection<RoleBase> roleCollection = factType.RoleCollection; int roleCollectionCount = roleCollection.Count; if (roleCollectionCount == 1) { // If we have a unary, binarize it BinarizeUnary(factType, notifyAdded); return; } else if (roleCollectionCount == 2) { // If we have a binary that has an implicit boolean role in it, make sure it matches the pattern Role implicitBooleanRole = GetImplicitBooleanRole(roleCollection); if (implicitBooleanRole != null) { Role unaryRole = implicitBooleanRole.OppositeRole.Role; Debug.Assert(unaryRole != null); // Make sure the implicit boolean role has the same name as the unary role implicitBooleanRole.Name = unaryRole.Name; string implicitBooleanValueTypeName = GetImplicitBooleanValueTypeName(unaryRole); if (implicitBooleanRole.RolePlayer.Name != implicitBooleanValueTypeName) { Dictionary<object, object> contextInfo = factType.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo; try { contextInfo[ORMModel.AllowDuplicateNamesKey] = null; implicitBooleanRole.RolePlayer.Name = implicitBooleanValueTypeName; } finally { contextInfo.Remove(ORMModel.AllowDuplicateNamesKey); } } if (!ValidateConstraints(unaryRole, implicitBooleanRole) || !ValidateImplicitBooleanValueType(implicitBooleanRole.RolePlayer)) { LinkedElementCollection<RoleBase> roles = factType.RoleCollection; DebinarizeUnary(roles, false, notifyAdded); // Append to the reading orders LinkedElementCollection<ReadingOrder> readingOrders = factType.ReadingOrderCollection; int readingOrderCount = readingOrders.Count; for (int i = 0; i < readingOrderCount; ++i) { ReadingOrder order = readingOrders[i]; LinkedElementCollection<RoleBase> readingRoles = order.RoleCollection; if (!readingRoles.Contains(implicitBooleanRole)) { readingRoles.Add(implicitBooleanRole); LinkedElementCollection<Reading> readings = order.ReadingCollection; int readingCount = readings.Count; for (int j = 0; j < readingCount; ++j) { readings[j].SetAutoText(readings[j].Text + " {1}"); } } } } } } else { // If we have an n-ary, remove any implicit boolean roles in it for (int i = roleCollectionCount - 1; i >= 0; --i) { Role implicitBooleanRole = roleCollection[i].Role; if (implicitBooleanRole != null && implicitBooleanRole.RolePlayer != null && implicitBooleanRole.RolePlayer.IsImplicitBooleanValue) { DebinarizeUnary(factType.RoleCollection, true, notifyAdded); break; } } } }
/// <summary> /// Select the primary reading for the reading order /// matching the role order of the fact, if there /// isn't one activate the new entry for that order. /// </summary> /// <param name="fact">FactType</param> public void ActivateReading(FactType fact) { ReadingsViewForm form = myForm; if (form != null) { form.ActivateReading(fact); } }