コード例 #1
0
ファイル: ModificationTracker.cs プロジェクト: ozialien/NORMA
 private static void ValidateReferenceModeNamingChanged(ReferenceModeNamingCustomizesObjectType referenceModeNamingCustomizesObjectType)
 {
     if (null != referenceModeNamingCustomizesObjectType)
     {
         ORMCore.ObjectType objectType = referenceModeNamingCustomizesObjectType.ObjectType;
         if (objectType != null)
         {
             ConceptType conceptType = ConceptTypeIsForObjectType.GetConceptType(objectType);
             if (null == conceptType)
             {
                 foreach (ORMCore.Role role in objectType.PlayedRoleCollection)
                 {
                     foreach (ConceptTypeChild conceptTypeChild in ConceptTypeChildHasPathFactType.GetConceptTypeChild(role.FactType))
                     {
                         ValidateConceptTypeChildNameChanged(conceptTypeChild);
                     }
                 }
             }
             else
             {
                 ValidateConceptTypeNameChanged(conceptType);
             }
         }
     }
 }
コード例 #2
0
 private static void UpdateChildNamesForFactTypeDelayedWorker(ModelElement element)
 {
     if (!element.IsDeleted)
     {
         FactType factType = (FactType)element;
         foreach (ConceptTypeChild child in ConceptTypeChildHasPathFactType.GetConceptTypeChild(factType))
         {
             LinkedElementCollection <FactType> factTypePath = ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(child);
             int      pathCount;
             RoleBase towardsRole;
             RoleBase fromRole;
             if (0 != (pathCount = factTypePath.Count) &&
                 factType == factTypePath[pathCount - 1] &&
                 null != (towardsRole = FactTypeMapsTowardsRole.GetTowardsRole(factType)) &&
                 null != (fromRole = towardsRole.OppositeRole))
             {
                 string resolvedName = ResolveRoleName(fromRole);
                 ConceptTypeReferencesConceptType reference;
                 if (null != (reference = child as ConceptTypeReferencesConceptType))
                 {
                     // Match original backwards pattern
                     reference.OppositeName = resolvedName;
                     child.Name             = ResolveRoleName(towardsRole);
                 }
                 else
                 {
                     child.Name = resolvedName;
                 }
             }
         }
     }
 }
コード例 #3
0
 private static void ValidateMandatoryDelayed(ModelElement element)
 {
     if (!element.IsDeleted)
     {
         ConceptTypeChild child        = (ConceptTypeChild)element;
         bool             newMandatory = true;
         foreach (FactType factType in ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(child))
         {
             FactTypeMapsTowardsRole towardsRoleLink = FactTypeMapsTowardsRole.GetLinkToTowardsRole(factType);
             if (null == towardsRoleLink)
             {
                 newMandatory = false;
                 break;
             }
             else
             {
                 switch (towardsRoleLink.MandatoryPattern)
                 {
                 case MappingMandatoryPattern.None:
                 case MappingMandatoryPattern.NotMandatory:
                 case MappingMandatoryPattern.OppositeRoleMandatory:
                     newMandatory = false;
                     break;
                 }
                 if (!newMandatory)
                 {
                     break;
                 }
             }
         }
         child.IsMandatory = newMandatory;
     }
 }
コード例 #4
0
            private static void FactTypeConstraintPatternChangedDelayed(ModelElement element)
            {
                FactType factType;
                ORMModel model;

                if (!element.IsDeleted &&
                    null != (model = (factType = (FactType)element).Model) &&
                    !ORMElementGateway.IsElementExcluded(factType))
                {
                    // If we're not previously mapped, then we will have been added at this point
                    FactTypeMapsTowardsRole mapToRole = FactTypeMapsTowardsRole.GetLinkToTowardsRole(factType);
                    if (mapToRole != null)
                    {
                        MappingMandatoryPattern startMandatoryPattern = mapToRole.MandatoryPattern;
                        if (mapToRole.SynchronizeMappingPatterns())
                        {
                            MappingMandatoryPattern endMandatoryPattern = mapToRole.MandatoryPattern;
                            if (endMandatoryPattern != startMandatoryPattern)
                            {
                                foreach (ConceptTypeChild child in ConceptTypeChildHasPathFactType.GetConceptTypeChild(factType))
                                {
                                    ValidateMandatory(child, startMandatoryPattern, endMandatoryPattern);
                                }
                            }
                        }
                        else
                        {
                            AddTransactedModelElement(factType, ModelElementModification.ORMElementChanged);
                            FrameworkDomainModel.DelayValidateElement(model, DelayValidateModel);
                        }
                    }
                }
            }
コード例 #5
0
 private static void UpdateNamesForObjectTypeDelayed(ModelElement element)
 {
     if (!element.IsDeleted)
     {
         ObjectType  objectType     = (ObjectType)element;
         string      objectTypeName = objectType.Name;
         ConceptType conceptType    = ConceptTypeIsForObjectType.GetConceptType(objectType);
         LinkedElementCollection <FactType> pathFactTypes;
         int      factTypeCount;
         RoleBase towardsRole;
         RoleBase oppositeRole;
         if (null != conceptType)
         {
             // Precheck name to minimize downstream calls, the property change
             // will check itself.
             if (conceptType.Name != objectTypeName)
             {
                 conceptType.Name = objectTypeName;
                 foreach (ConceptTypeReferencesConceptType reference in ConceptTypeReferencesConceptType.GetLinksToReferencingConceptTypeCollection(conceptType))
                 {
                     pathFactTypes = ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(reference);
                     if (0 != (factTypeCount = pathFactTypes.Count) &&
                         null != (towardsRole = FactTypeMapsTowardsRole.GetTowardsRole(pathFactTypes[factTypeCount - 1])) &&
                         null != (oppositeRole = towardsRole.OppositeRole))
                     {
                         reference.OppositeName = ResolveRoleName(oppositeRole);
                     }
                 }
                 foreach (ConceptTypeReferencesConceptType reference in ConceptTypeReferencesConceptType.GetLinksToReferencedConceptTypeCollection(conceptType))
                 {
                     pathFactTypes = ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(reference);
                     if (0 != (factTypeCount = pathFactTypes.Count) &&
                         null != (towardsRole = FactTypeMapsTowardsRole.GetTowardsRole(pathFactTypes[factTypeCount - 1])))
                     {
                         reference.Name = ResolveRoleName(towardsRole);
                     }
                 }
             }
         }
         InformationTypeFormat informationTypeFormat = InformationTypeFormatIsForValueType.GetInformationTypeFormat(objectType);
         if (null != informationTypeFormat)
         {
             if (informationTypeFormat.Name != objectTypeName)
             {
                 informationTypeFormat.Name = objectTypeName;
                 foreach (InformationType informationType in InformationType.GetLinksToConceptTypeCollection(informationTypeFormat))
                 {
                     pathFactTypes = ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(informationType);
                     if (0 != (factTypeCount = pathFactTypes.Count) &&
                         null != (towardsRole = FactTypeMapsTowardsRole.GetTowardsRole(pathFactTypes[factTypeCount - 1])) &&
                         null != (oppositeRole = towardsRole.OppositeRole))
                     {
                         informationType.Name = ResolveRoleName(oppositeRole);
                     }
                 }
             }
         }
     }
 }
            /// <summary>
            /// Make sure we have our tracker attached to all loaded models.
            /// </summary>
            /// <param name="element">An ORMModel element</param>
            /// <param name="store">The context store</param>
            /// <param name="notifyAdded">The listener to notify if elements are added during fixup</param>
            protected sealed override void ProcessElement(ORMModel element, Store store, INotifyElementAdded notifyAdded)
            {
                AbstractionModel oil = AbstractionModelIsForORMModel.GetAbstractionModel(element);

                if (oil == null)
                {
                    // UNDONE: DelayValidateModel currently deletes and recreates any existing
                    // bridge relationship, so there is no point deleting it up front, we'll
                    // just retrieve it later. Also note that DelayValidateModel does not call notifyAdded.
                    DelayValidateModel(element);
                    oil = AbstractionModelIsForORMModel.GetAbstractionModel(element);
                    if (oil != null)
                    {
                        notifyAdded.ElementAdded(oil, true);
                    }
                }
                else
                {
                    AbstractionModelGenerationSetting generationSetting;
                    bool regenerateForVersion   = null == (generationSetting = GenerationSettingTargetsAbstractionModel.GetGenerationSetting(oil)) || generationSetting.AlgorithmVersion != CurrentAlgorithmVersion;
                    bool excludedBridgedElement = false;
                    ORMElementGateway.Initialize(
                        element,
                        regenerateForVersion ? (ORMElementGateway.NotifyORMElementExcluded) null :
                        delegate(ORMModelElement modelElement)
                    {
                        if (excludedBridgedElement)
                        {
                            return;
                        }
                        ObjectType objectType;
                        FactType factType;
                        // Note that the types we're checking here are synchronized with the ORMElementGateway.ExclusionAdded method
                        if (null != (objectType = modelElement as ObjectType))
                        {
                            if (null != ConceptTypeIsForObjectType.GetLinkToConceptType(objectType) ||
                                null != InformationTypeFormatIsForValueType.GetLinkToInformationTypeFormat(objectType))
                            {
                                excludedBridgedElement = true;
                            }
                        }
                        else if (null != (factType = modelElement as FactType))
                        {
                            if (null != FactTypeMapsTowardsRole.GetLinkToTowardsRole(factType) ||
                                ConceptTypeChildHasPathFactType.GetLinksToConceptTypeChild(factType).Count != 0)
                            {
                                excludedBridgedElement = true;
                            }
                        }
                    });
                    if (regenerateForVersion || excludedBridgedElement)
                    {
                        // Something is very wrong, regenerate (does not regenerate the excluded elements we already have)
                        DelayValidateModel(element);
                    }
                }
            }
コード例 #7
0
ファイル: Verbalization.cs プロジェクト: ozialien/NORMA
        /// <summary>
        /// Implements <see cref="IVerbalize.GetVerbalization"/>
        /// </summary>
        protected bool GetVerbalization(TextWriter writer, IDictionary <Type, IVerbalizationSets> snippetsDictionary, IVerbalizationContext verbalizationContext, VerbalizationSign sign)
        {
            // We are redirected to this point by the associated Column element
            Column column     = this.Column;
            bool   firstWrite = true;

            foreach (ConceptTypeChild child in ColumnHasConceptTypeChild.GetConceptTypeChildPath(this.Column))
            {
                foreach (FactType factType in ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(child))
                {
                    if (firstWrite)
                    {
                        firstWrite = false;
                    }
                    else
                    {
                        writer.WriteLine();
                    }
                    verbalizationContext.DeferVerbalization(factType, DeferVerbalizationOptions.MultipleVerbalizations, null);
                }
            }
            return(false);
        }
コード例 #8
0
ファイル: ModificationTracker.cs プロジェクト: ozialien/NORMA
            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);
                    }
                }
            }
コード例 #9
0
        /// <summary>
        /// Get a minimal unique identifier for a column based on mapped roles. The identifer
        /// will stop as soon as the fact type is used in a single column or in a partitioned
        /// or separated column.
        /// </summary>
        /// <param name="column">The <see cref="Column"/> to analyze</param>
        /// <param name="idList">Scratch list used to determine keys</param>
        /// <param name="minKeySize">The minimum number of ids that uniquely
        /// identify this column. The actually key may be longer than this
        /// minimimum for partitioned and separated tables. Key comparisons
        /// may be performed down to this minimum size.</param>
        /// <returns><see langword="true"/> if the key was available.</returns>
        private static bool BuildKey(Column column, List <Guid> idList, out int minKeySize)
        {
            idList.Clear();
            int uniqueUseIndex = -1;

            minKeySize = 0;
            LinkedElementCollection <ConceptTypeChild> childNodes = ColumnHasConceptTypeChild.GetConceptTypeChildPath(column);

            for (int i = childNodes.Count - 1; i >= 0; --i)
            {
                ConceptTypeChild child       = childNodes[i];
                bool             uniqueChild = ColumnHasConceptTypeChild.GetLinksToColumn(child).Count == 1;
                LinkedElementCollection <FactType> pathFactTypes = ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(child);
                int             factTypeCount = pathFactTypes.Count;
                InformationType infoType;
                ObjectType      objectType;
                if (0 != (factTypeCount = pathFactTypes.Count))
                {
                    for (int j = factTypeCount - 1; j >= 0; --j)
                    {
                        FactType factType = pathFactTypes[j];
                        idList.Add(FactTypeMapsTowardsRole.GetTowardsRole(factType).Id);
                        if (-1 == uniqueUseIndex &&
                            uniqueChild &&
                            ConceptTypeChildHasPathFactType.GetLinksToConceptTypeChild(factType).Count == 1)
                        {
                            minKeySize     = idList.Count;
                            uniqueUseIndex = minKeySize - 1;
                        }
                    }
                    ConceptTypeAssimilatesConceptType assimilation;
                    if (uniqueUseIndex != -1 &&
                        null != (assimilation = child as ConceptTypeAssimilatesConceptType) &&
                        AssimilationMapping.GetAbsorptionChoiceFromAssimilation(assimilation) != AssimilationAbsorptionChoice.Absorb)
                    {
                        uniqueUseIndex = idList.Count - 1;
                    }
                }
                else if (null != (infoType = child as InformationType) &&
                         null != (objectType = ConceptTypeIsForObjectType.GetObjectType(infoType.ConceptType)))
                {
                    // Happens for a value column in an object type table, which has one concept type child
                    idList.Add(objectType.Id);
                }
            }
            int count = idList.Count;

            if (0 == count)
            {
                return(false);
            }
            if (uniqueUseIndex != -1 &&
                (uniqueUseIndex + 1) < count)
            {
                idList.RemoveRange(uniqueUseIndex + 1, count - uniqueUseIndex - 1);
            }
            if (minKeySize == 0)
            {
                minKeySize = idList.Count;
            }
            return(true);
        }
コード例 #10
0
		/// <summary>
		/// Generates the appropriate <see cref="ConceptTypeChild">concept type children</see> in <paramref name="parentConceptType"/>
		/// for <paramref name="factTypeMapping"/>.
		/// </summary>
		/// <param name="factTypeMappings">
		/// The set of all decided <see cref="FactTypeMapping">fact type mappings</see>.
		/// </param>
		/// <param name="parentConceptType">
		/// The <see cref="ConceptType"/> into which <see cref="ConceptTypeChild">concept type children</see> should be generated.
		/// </param>
		/// <param name="parentConceptTypeHasDeepAway">
		/// Test if the parent concept type has a deep mapping away from it. Handles some cyclic cases by making a potential assimilation
		/// into a reference. Delay calculated because this is not always needed.
		/// </param>
		/// <param name="factTypeMapping">
		/// The <see cref="FactTypeMapping"/> for which <see cref="ConceptTypeChild">concept type children</see> should be generated.
		/// </param>
		/// <param name="factTypePath">
		/// The path of <see cref="FactType">fact types</see> leading from <paramref name="parentConceptType"/> to <paramref name="factTypeMapping"/>
		/// </param>
		/// <param name="isMandatorySoFar">
		/// Indicates whether every step in <paramref name="factTypePath"/> is mandatory for the parent concept type (towards object type).
		/// </param>
		private static void GenerateConceptTypeChildrenForFactTypeMapping(FactTypeMappingDictionary factTypeMappings, ConceptType parentConceptType, ref bool? parentConceptTypeHasDeepAway, FactTypeMapping factTypeMapping, List<FactType> factTypePath, bool isMandatorySoFar)
		{
			// Push the current fact type onto the path.
			factTypePath.Add(factTypeMapping.FactType);

			bool isMandatory = isMandatorySoFar && (factTypeMapping.TowardsRoleMandatory);

			ConceptTypeChild newConceptTypeChild;

			ConceptType fromConceptType = ConceptTypeIsForObjectType.GetConceptType(factTypeMapping.FromObjectType);
			if (fromConceptType != null)
			{
				// The mapping is coming from a concept type, so we will create a concept type reference to it.

				// Set up the property assignments that are common to both kinds of concept type references.
				PropertyAssignment isMandatoryPropertyAssignment = new PropertyAssignment(ConceptTypeChild.IsMandatoryDomainPropertyId, isMandatory);

				string name = ResolveRoleName(factTypeMapping.FromRole);
				string oppositeName = ResolveRoleName(factTypeMapping.TowardsRole);

				// UNDONE: Yes, these are backwards, but they need to remain so for compatibility reasons until we do a file format change.
				PropertyAssignment namePropertyAssignment = new PropertyAssignment(ConceptTypeChild.NameDomainPropertyId, oppositeName);
				PropertyAssignment oppositeNamePropertyAssignment = new PropertyAssignment(ConceptTypeReferencesConceptType.OppositeNameDomainPropertyId, name);

				if (factTypeMapping.MappingDepth == MappingDepth.Deep)
				{
					// Since this is a deep mapping, we will create a concept type assimilation for it.

					SubtypeFact subtypeFact = factTypeMapping.FactType as SubtypeFact;

					// UNDONE: The handling here for IsPreferredForParent and IsPreferredForTarget may not be correct
					// if we have more than one fact type in the fact type path.

					bool isPreferredForTarget;
					if (subtypeFact != null)
					{
						// For subtype assimilations, IsPreferredForTarget matches the ProvidesPreferredIdentifier
						// property of the ORM subtype fact.
						isPreferredForTarget = subtypeFact.ProvidesPreferredIdentifier;
					}
					else
					{
						// For non-subtype assimilations, IsPreferredForTarget is true if the role played by the object
						// type corresponding to the parent concept type has the preferred identifying uniqueness constraint
						// for the target concept type.
						isPreferredForTarget = factTypeMapping.TowardsRole.SingleRoleAlethicUniquenessConstraint.IsPreferred;
					}

					bool isPreferredForParent = factTypeMapping.IsFromPreferredIdentifier;
					// The IsPreferredForParent property on concept type assimilations indicates that the assimilation, on its own,
					// provides the preferred identifier for the assimilating concept type. Although the IsFromPreferredIdentifier
					// property on the fact type mapping will be true even if the from role is part of a multi-role preferred identifier,
					// ORM currently doesn't allow a role with a single role alethic uniqueness constraint (which is required for this to
					// be a deep mapping) to be part of any other uniqueness constraint. However, this may change in the future as our
					// handling of derivations, implications, equivalences, and logical rules becomes more sophisticated. We assert here
					// in order to make this case easier to catch if it happens, since this method may need to be adjusted in that case
					// to ensure that it continues to produce correct results.
					Debug.Assert(!isPreferredForParent || factTypeMapping.FromRole.SingleRoleAlethicUniquenessConstraint.IsPreferred);

					newConceptTypeChild = new ConceptTypeAssimilatesConceptType(parentConceptType.Partition,
						new RoleAssignment[]
						{
							new RoleAssignment(ConceptTypeAssimilatesConceptType.AssimilatorConceptTypeDomainRoleId, parentConceptType),
							new RoleAssignment(ConceptTypeAssimilatesConceptType.AssimilatedConceptTypeDomainRoleId, fromConceptType)
						},
						new PropertyAssignment[]
						{
							isMandatoryPropertyAssignment,
							namePropertyAssignment,
							oppositeNamePropertyAssignment,
							new PropertyAssignment(ConceptTypeAssimilatesConceptType.RefersToSubtypeDomainPropertyId, subtypeFact != null),
							new PropertyAssignment(ConceptTypeAssimilatesConceptType.IsPreferredForParentDomainPropertyId, isPreferredForParent),
							new PropertyAssignment(ConceptTypeAssimilatesConceptType.IsPreferredForTargetDomainPropertyId, isPreferredForTarget),
						});
				}
				else
				{
					Debug.Assert(factTypeMapping.MappingDepth == MappingDepth.Shallow,
						"Collapse mappings should not come from object types that have a concept type.");
					
					// Since this is a shallow mapping, we will create a concept type relation for it.
					newConceptTypeChild = new ConceptTypeRelatesToConceptType(parentConceptType.Partition,
						new RoleAssignment[]
						{
							new RoleAssignment(ConceptTypeRelatesToConceptType.RelatingConceptTypeDomainRoleId, parentConceptType),
							new RoleAssignment(ConceptTypeRelatesToConceptType.RelatedConceptTypeDomainRoleId, fromConceptType)
						},
						new PropertyAssignment[]
						{
							isMandatoryPropertyAssignment,
							namePropertyAssignment,
							oppositeNamePropertyAssignment
						});
				}
			}
			else
			{
				// The mapping is not coming from a concept type, meaning that we either need an information
				// type for an atomic value type (which will already have an information type format created
				// for it), or we need to collapse the preferred identifier of an entity type or structured
				// value type.

				InformationTypeFormat fromInformationTypeFormat = InformationTypeFormatIsForValueType.GetInformationTypeFormat(factTypeMapping.FromObjectType);
				if (fromInformationTypeFormat != null)
				{
					// We have an information type format, which means that we need to create an information type.

					string name = ResolveRoleName(factTypeMapping.FromRole);

					newConceptTypeChild = new InformationType(parentConceptType.Partition,
						new RoleAssignment[]
						{
							new RoleAssignment(InformationType.ConceptTypeDomainRoleId, parentConceptType),
							new RoleAssignment(InformationType.InformationTypeFormatDomainRoleId, fromInformationTypeFormat)
						},
						new PropertyAssignment[]
						{
							new PropertyAssignment(ConceptTypeChild.IsMandatoryDomainPropertyId, isMandatory),
							new PropertyAssignment(ConceptTypeChild.NameDomainPropertyId, name)
						});
				}
				else
				{
					// We do not have an information type format, which means that we need to collapse the fact
					// types in the preferred identifier of the FromObjectType into the parent concept type.

					newConceptTypeChild = null;

					UniquenessConstraint preferredIdentifier = factTypeMapping.FromObjectType.PreferredIdentifier;
					Debug.Assert(preferredIdentifier != null);

					foreach (Role preferredIdentifierRole in preferredIdentifier.RoleCollection)
					{
						// NOTE: We don't need the ShouldIgnoreFactType filter here, because we would have ignored
						// this object type if we were ignoring any of the fact types in its preferred identifier.
						FactType preferredIdentifierFactType = preferredIdentifierRole.BinarizedFactType;

						FactTypeMapping preferredIdentifierFactTypeMapping = factTypeMappings[preferredIdentifierFactType];

						if (preferredIdentifierFactType == factTypeMapping.FactType)
						{
							// We just got back to the fact that we were already mapping. This should only happen
							// when the object type has a single fact type in its preferred identifier and it is
							// deeply mapped away from the object type.
							Debug.Assert(preferredIdentifier.RoleCollection.Count == 1 && preferredIdentifierFactTypeMapping.MappingDepth == MappingDepth.Deep);

							// UNDONE: For now, we just ignore this fact type entirely. What we should be doing is:
							// 1) If everything along the path is mandatory, then we're done, since we know that instances of the parent
							// concept type always identify an instance of the object type that we're trying to map.
							// 2) Otherwise, check if there are any other relationships that would allow use to derive whether an instance
							// of the parent concept type identifies an instance of the object type that we're trying to map. Examples
							// of things that would allow us to do this would be a mandatory role played by the object type that we're
							// we're trying to map that gets absorbed into some concept type. The reference to an instance of this concept
							// type from it allows us to tell if this instance identifies an instance of the object type.
							// 3) If no other relationship allows us to derive this information, we need to add a boolean information type
							// that indicates for each instance of the parent concept type whether it identifies an instance of the object
							// type that we're trying to map.
							break;
						}

						// If we have a single fact type in the preferred identifier, it might be mapped
						// deeply away from the object type that we are collapsing. For this case, we need
						// to create a "fake" mapping and process it instead.
						if (preferredIdentifierFactTypeMapping.TowardsRole == preferredIdentifierRole)
						{
							// Make sure this is actually the situation we are trying to handle, since it shouldn't be possible in any other scenario.
							Debug.Assert(preferredIdentifier.RoleCollection.Count == 1 && preferredIdentifierFactTypeMapping.MappingDepth == MappingDepth.Deep);

							// UNDONE: Would we ever want to use a depth other than shallow here? Probably not, but it might be worth looking in to.
							FactTypeMappingFlags currentFlags = preferredIdentifierFactTypeMapping.Flags;
							preferredIdentifierFactTypeMapping = new FactTypeMapping(preferredIdentifierFactType, preferredIdentifierFactTypeMapping.TowardsRole, preferredIdentifierFactTypeMapping.FromRole, (currentFlags & FactTypeMappingFlags.Subtype) | GetFlags(false, 0 != (currentFlags & FactTypeMappingFlags.TowardsValueType), 0 != (currentFlags & FactTypeMappingFlags.TowardsRoleMandatory), 0 != (currentFlags & FactTypeMappingFlags.TowardsRoleImpliedMandatory), 0 != (currentFlags & FactTypeMappingFlags.FromValueType), 0 != (currentFlags & FactTypeMappingFlags.FromRoleMandatory), 0 != (currentFlags & FactTypeMappingFlags.FromRoleImpliedMandatory)));
						}
						else if (preferredIdentifierFactTypeMapping.MappingDepth == MappingDepth.Deep)
						{
							// Handle cyclic deep mapping scenario with collapsed entities.
							// The primary scenario here is:
							// 1) B is a subtype of A and identified by A's identifier
							// 2) A and B participate in an objectified 1-1 FactType
							// 3) The uniqueness constraint on the A role is the preferred identifier
							// 4) The A role is mandatory
							// In this case, without this code, you get an assimilation mapping B into A
							// and mapping A into B. We fix this case by forwarding a shallow mapping,
							// which generates a reference instad of an assimilation.
							if (!parentConceptTypeHasDeepAway.HasValue)
							{
								ObjectType objectType = ConceptTypeIsForObjectType.GetObjectType(parentConceptType);
								foreach (Role role in ConceptTypeIsForObjectType.GetObjectType(parentConceptType).PlayedRoleCollection)
								{
									FactType factType;
									FactTypeMapping testMapping;
									if (null != (factType = role.BinarizedFactType) &&
										factTypeMappings.TryGetValue(factType, out testMapping) &&
										testMapping.MappingDepth == MappingDepth.Deep &&
										testMapping.FromObjectType == objectType)
									{
										preferredIdentifierFactTypeMapping = new FactTypeMapping(preferredIdentifierFactType, preferredIdentifierFactTypeMapping.FromRole, preferredIdentifierFactTypeMapping.TowardsRole, preferredIdentifierFactTypeMapping.Flags & ~FactTypeMappingFlags.DeepMapping);
										parentConceptTypeHasDeepAway = true;
										break;
									}
								}
								if (!parentConceptTypeHasDeepAway.HasValue)
								{
									parentConceptTypeHasDeepAway = false;
								}
							}
							else if (parentConceptTypeHasDeepAway.Value)
							{
								preferredIdentifierFactTypeMapping = new FactTypeMapping(preferredIdentifierFactType, preferredIdentifierFactTypeMapping.FromRole, preferredIdentifierFactTypeMapping.TowardsRole, preferredIdentifierFactTypeMapping.Flags & ~FactTypeMappingFlags.DeepMapping);
							}
						}

						GenerateConceptTypeChildrenForFactTypeMapping(factTypeMappings, parentConceptType, ref parentConceptTypeHasDeepAway, preferredIdentifierFactTypeMapping, factTypePath, isMandatory);
					}
				}
			}

			// If we created a new concept type child, populate its fact type path.
			if (newConceptTypeChild != null)
			{
				foreach (FactType pathFactType in factTypePath)
				{
					ConceptTypeChildHasPathFactType conceptTypeChildHasPathFactType = new ConceptTypeChildHasPathFactType(newConceptTypeChild, pathFactType);
				}
			}

			// Pop the current fact type off of the path.
			Debug.Assert(factTypePath[factTypePath.Count - 1] == factTypeMapping.FactType, "Fact type path stack is corrupt.");
			factTypePath.RemoveAt(factTypePath.Count - 1);
		}
コード例 #11
0
        /// <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);
            }
        }