예제 #1
0
				public FactTypeChainer(FactTypeMappingDictionary predecidedManyToOneFactTypeMappings, FactTypeMappingDictionary predecidedOneToOneFactTypeMappings, FactTypeMappingListDictionary undecidedOneToOneFactTypeMappings)
				{
					myChains = new ChainList();

					myPredecidedManyToOneFactTypeMappings = predecidedManyToOneFactTypeMappings;
					myPredecidedOneToOneFactTypeMappings = predecidedOneToOneFactTypeMappings;
					myUndecidedOneToOneFactTypeMappings = undecidedOneToOneFactTypeMappings;
				}
예제 #2
0
 public FactTypeMappingDictionary(FactTypeMappingDictionary values)
     : base(values.Count)
 {
     foreach (KeyValuePair <FactType, FactTypeMapping> pair in values)
     {
         Add(pair.Key, pair.Value);
     }
 }
예제 #3
0
				public int Run(FactTypeMappingDictionary allDecidedMappings)
				{
					BuildChains();
					ReduceChains(allDecidedMappings);

					// Delete empty chains and find the largest chain.
					int largestChainCount = 0;
					for (int i = myChains.Count - 1; i >= 0; --i)
					{
						Chain chain = myChains[i];
						if (chain.UndecidedOneToOneFactTypeMappings.Count == 0)
						{
							myChains.RemoveAt(i);
							continue;
						}
						int chainCount = chain.OneToOneFactTypeCount;
						if (chainCount > largestChainCount)
						{
							largestChainCount = chainCount;
						}
					}

					return largestChainCount;
				}
예제 #4
0
		/// <summary>
		/// Maps one-to-one fact types with two simple alethic mandatories away from the object type that has no possible
		/// (potential or decided) deep mappings away from it.  If both role players meet this criteria then no action is
		/// taken.
		/// </summary>
		/// <param name="decidedOneToOneFactTypeMappings">The decided <see cref="FactTypeMapping"/> objects.</param>
		/// <param name="undecidedOneToOneFactTypeMappings">The undecided <see cref="FactTypeMapping"/> posibilities.</param>
		/// <returns>The number of previously potential one-to-one fact type mappings that are now decided.</returns>
		private int MapTrivialOneToOneFactTypesWithTwoMandatories(FactTypeMappingDictionary decidedOneToOneFactTypeMappings, FactTypeMappingListDictionary undecidedOneToOneFactTypeMappings)
		{
			List<FactType> factTypesPendingDeletion = new List<FactType>();

			foreach (KeyValuePair<FactType, FactTypeMappingList> undecidedPair in undecidedOneToOneFactTypeMappings)
			{
				FactType factType = undecidedPair.Key;
				FactTypeMappingList potentialFactTypeMappings = undecidedPair.Value;
				LinkedElementCollection<RoleBase> roles = factType.RoleCollection;

				Debug.Assert(roles.Count == 2, "All fact type mappings should be for fact types with exactly two roles.");

				Role firstRole = roles[0].Role;
				Role secondRole = roles[1].Role;
				ObjectType firstRolePlayer = firstRole.RolePlayer;
				ObjectType secondRolePlayer = secondRole.RolePlayer;

				// If this is a one-to-one fact type with two simple alethic mandatories...
				if (firstRole.SingleRoleAlethicMandatoryConstraint != null && secondRole.SingleRoleAlethicMandatoryConstraint != null)
				{
					FactTypeMapping deepMappingTowardsFirstRole = null;
					FactTypeMapping deepMappingTowardsSecondRole = null;

					// Find our potential deep mappings.
					foreach (FactTypeMapping potentialFactTypeMapping in potentialFactTypeMappings)
					{
						if (potentialFactTypeMapping.MappingDepth == MappingDepth.Deep)
						{
							if (potentialFactTypeMapping.TowardsRole == firstRole)
							{
								deepMappingTowardsFirstRole = potentialFactTypeMapping;
							}
							else
							{
								Debug.Assert(potentialFactTypeMapping.TowardsRole == secondRole);
								deepMappingTowardsSecondRole = potentialFactTypeMapping;
							}
						}
					}

					bool firstRolePlayerHasPossibleDeepMappingsAway = ObjectTypeHasPossibleDeepMappingsAway(firstRolePlayer, factType, decidedOneToOneFactTypeMappings, undecidedOneToOneFactTypeMappings);
					bool secondRolePlayerHasPossibleDeepMappingsAway = ObjectTypeHasPossibleDeepMappingsAway(secondRolePlayer, factType, decidedOneToOneFactTypeMappings, undecidedOneToOneFactTypeMappings);

					// UNDONE: We need to do cycle checking at or before this point, since otherwise this can create a decided deep mapping cycle.

					// If secondRolePlayer has no possible deep mappings away from it, and firstRolePlayer does...
					if (firstRolePlayerHasPossibleDeepMappingsAway && !secondRolePlayerHasPossibleDeepMappingsAway)
					{
						// Make sure that this deep mapping was one of our potentials.
						if (deepMappingTowardsFirstRole != null)
						{
							Debug.Assert(firstRole.SingleRoleAlethicUniquenessConstraint != null);
							// Make sure we're not going towards a preferred identifier. Doing so is valid, and sometimes optimal,
							// but not always, hence the permuter needs to consider it.
							if (!firstRole.SingleRoleAlethicUniquenessConstraint.IsPreferred)
							{
								// Deep map toward firstRolePlayer
								decidedOneToOneFactTypeMappings.Add(factType, deepMappingTowardsFirstRole);
								factTypesPendingDeletion.Add(factType);
							}
						}
					}
					// ...and vice-versa...
					else if (!firstRolePlayerHasPossibleDeepMappingsAway && secondRolePlayerHasPossibleDeepMappingsAway)
					{
						// Make sure that this deep mapping was one of our potentials.
						if (deepMappingTowardsSecondRole != null)
						{
							Debug.Assert(secondRole.SingleRoleAlethicUniquenessConstraint != null);
							// Make sure we're not going towards a preferred identifier. Doing so is valid, and sometimes optimal,
							// but not always, hence the permuter needs to consider it.
							if (!secondRole.SingleRoleAlethicUniquenessConstraint.IsPreferred)
							{
								// Deep map toward secondRolePlayer
								decidedOneToOneFactTypeMappings.Add(factType, deepMappingTowardsSecondRole);
								factTypesPendingDeletion.Add(factType);
							}
						}
					}
				}
			}

			// Delete each undecided (now decided) fact type mapping marked for deletion.
			foreach (FactType key in factTypesPendingDeletion)
			{
				undecidedOneToOneFactTypeMappings.Remove(key);
			}

			return factTypesPendingDeletion.Count;
		}
예제 #5
0
		/// <summary>
		/// Filters out deep potential mappings that are from an <see cref="ObjectType"/> that already has a decided deep
		/// mapping from it.
		/// </summary>
		/// <param name="decidedOneToOneFactTypeMappings">The decided <see cref="FactTypeMapping"/> objects.</param>
		/// <param name="undecidedOneToOneFactTypeMappings">The undecided <see cref="FactTypeMapping"/> possibilities.</param>
		private void RemoveImpossiblePotentialFactTypeMappings(FactTypeMappingDictionary decidedOneToOneFactTypeMappings, FactTypeMappingListDictionary undecidedOneToOneFactTypeMappings)
		{
			Dictionary<ObjectType, object> deeplyMappedObjectTypes = new Dictionary<ObjectType, object>(decidedOneToOneFactTypeMappings.Count + undecidedOneToOneFactTypeMappings.Count);

			// For each decided fact type mapping...
			foreach (FactTypeMapping factTypeMapping in decidedOneToOneFactTypeMappings.Values)
			{
				// If it's a deep mapping...
				if (factTypeMapping.MappingDepth == MappingDepth.Deep)
				{
					deeplyMappedObjectTypes[factTypeMapping.FromObjectType] = null;
				}
			}

			List<FactType> factsPendingDeletion = new List<FactType>();

			foreach (KeyValuePair<FactType, FactTypeMappingList> undecidedFactTypeMapping in undecidedOneToOneFactTypeMappings)
			{
				FactType factType = undecidedFactTypeMapping.Key;
				FactTypeMappingList potentialFactTypeMappings = undecidedFactTypeMapping.Value;

				// For each potential fact type mapping...
				for (int i = potentialFactTypeMappings.Count - 1; i >= 0; --i)
				{
					FactTypeMapping potentialFactTypeMapping = potentialFactTypeMappings[i];

					// If it is maped away from an ObjectType that is already determined to be mapped elsewhere...
					if (potentialFactTypeMapping.MappingDepth == MappingDepth.Deep &&  deeplyMappedObjectTypes.ContainsKey(potentialFactTypeMapping.FromObjectType))
					{
						// Remove it as a possibility.
						potentialFactTypeMappings.RemoveAt(i);
					}
				}

				Debug.Assert(potentialFactTypeMappings.Count > 0);

				// If there is only one possibility left...
				if (potentialFactTypeMappings.Count == 1)
				{
					// Mark it decided.
					decidedOneToOneFactTypeMappings.Add(factType, potentialFactTypeMappings[0]);
					factsPendingDeletion.Add(factType);
				}
			}

			// Delete each undecided (now decided) fact type mapping marked for deletion.
			foreach (FactType key in factsPendingDeletion)
			{
				undecidedOneToOneFactTypeMappings.Remove(key);
			}
		}
예제 #6
0
		/// <summary>
		/// Runs various algorithms on the undecided fact type mappings in an attempt to decide as many as possible.
		/// </summary>
		/// <param name="decidedManyToOneFactTypeMappings">The decided many-to-one <see cref="FactTypeMapping"/> objects.</param>
		/// <param name="decidedOneToOneFactTypeMappings">The decided one-to-one <see cref="FactTypeMapping"/> objects.</param>
		/// <param name="undecidedOneToOneFactTypeMappings">The undecided <see cref="FactTypeMapping"/> possibilities.</param>
		private void FilterFactTypeMappings(FactTypeMappingDictionary decidedManyToOneFactTypeMappings, FactTypeMappingDictionary decidedOneToOneFactTypeMappings, FactTypeMappingListDictionary undecidedOneToOneFactTypeMappings)
		{
			bool changed;
			do
			{
				RemoveImpossiblePotentialFactTypeMappings(decidedOneToOneFactTypeMappings, undecidedOneToOneFactTypeMappings);

				changed = MapTrivialOneToOneFactTypesWithTwoMandatories(decidedOneToOneFactTypeMappings, undecidedOneToOneFactTypeMappings) > 0;
			} while (changed);
		}
예제 #7
0
		/// <summary>
		/// Determines the obvious fact type mappings, and all other potential mappings.
		/// </summary>
		/// <param name="modelFactTypes">The <see cref="FactType"/> objects of the model</param>
		/// <param name="decidedManyToOneFactTypeMappings">The decided many-to-one <see cref="FactTypeMapping"/> objects.</param>
		/// <param name="decidedOneToOneFactTypeMappings">The decided one-to-one <see cref="FactTypeMapping"/> objects.</param>
		/// <param name="undecidedOneToOneFactTypeMappings">The undecided <see cref="FactTypeMapping"/> possibilities.</param>
		private void PerformInitialFactTypeMappings(LinkedElementCollection<FactType> modelFactTypes, FactTypeMappingDictionary decidedManyToOneFactTypeMappings, FactTypeMappingDictionary decidedOneToOneFactTypeMappings, FactTypeMappingListDictionary undecidedOneToOneFactTypeMappings)
		{
			// For each fact type in the model...
			foreach (FactType factType in modelFactTypes)
			{
				if (ShouldIgnoreFactType(factType))
				{
					continue;
				}
				SubtypeFact subtypeFact = factType as SubtypeFact;

				// If it's a subtype relation...
				MandatoryConstraint mandatory;
				if (subtypeFact != null)
				{
					Role subtypeRole = subtypeFact.SubtypeRole;
					Role supertypeRole = subtypeFact.SupertypeRole;
					mandatory = supertypeRole.SingleRoleAlethicMandatoryConstraint; // Note that the only way to get a mandatory on the supertype role is with an implied mandatory, verified explicitly below

					// Map deeply toward the supertype.
					FactTypeMapping factTypeMapping = new FactTypeMapping(
						subtypeFact,
						subtypeRole,
						supertypeRole,
						FactTypeMappingFlags.Subtype | FactTypeMappingFlags.DeepMapping | FactTypeMappingFlags.FromRoleMandatory | ((mandatory != null && mandatory.IsImplied) ? FactTypeMappingFlags.TowardsRoleMandatory | FactTypeMappingFlags.TowardsRoleImpliedMandatory : FactTypeMappingFlags.None) | (subtypeRole.RolePlayer.IsValueType ? FactTypeMappingFlags.FromValueType | FactTypeMappingFlags.TowardsValueType : FactTypeMappingFlags.None));
					decidedOneToOneFactTypeMappings.Add(subtypeFact, factTypeMapping);
				}
				else
				{
					LinkedElementCollection<RoleBase> roles = factType.RoleCollection;

					Debug.Assert(roles.Count == 2 && (factType.Objectification == null || factType.UnaryRole != null), "Non-binarized fact types should have been filtered out already.");

					Role firstRole = roles[0].Role;
					Role secondRole = roles[1].Role;
					ObjectType firstRolePlayer = firstRole.RolePlayer;
					ObjectType secondRolePlayer = secondRole.RolePlayer;

					UniquenessConstraint firstRoleUniquenessConstraint = (UniquenessConstraint)firstRole.SingleRoleAlethicUniquenessConstraint;
					UniquenessConstraint secondRoleUniquenessConstraint = (UniquenessConstraint)secondRole.SingleRoleAlethicUniquenessConstraint;
					
					bool firstRolePlayerIsValueType = firstRolePlayer.IsValueType;
					bool secondRolePlayerIsValueType = secondRolePlayer.IsValueType;
					
					bool firstRoleIsUnique = (firstRoleUniquenessConstraint != null);
					bool secondRoleIsUnique = (secondRoleUniquenessConstraint != null);
					
					bool firstRoleIsMandatory = null != (mandatory = firstRole.SingleRoleAlethicMandatoryConstraint);
					bool firstRoleIsImplicitlyMandatory = firstRoleIsMandatory && mandatory.IsImplied;
					bool firstRoleIsExplicitlyMandatory = firstRoleIsMandatory && !firstRoleIsImplicitlyMandatory;
					bool secondRoleIsMandatory = null != (mandatory = secondRole.SingleRoleAlethicMandatoryConstraint);
					bool secondRoleIsImplicitlyMandatory = secondRoleIsMandatory && mandatory.IsImplied;
					bool secondRoleIsExplicitlyMandatory = secondRoleIsMandatory && !secondRoleIsImplicitlyMandatory;

					// We don't need to worry about shallow mappings towards preferred identifiers on many-to-ones, since the preferred
					// identifier pattern ensures that these cases will always map towards the object type being identified anyway.

					const int FIRST_SECOND_SHALLOW = 1;
					const int FIRST_SECOND_DEEP = 2;
					const int SECOND_FIRST_SHALLOW = 4;
					const int SECOND_FIRST_DEEP = 8;
					int possibilityBits = 0;
					bool manyToOne = false;

					// If only firstRole is unique...
					if (firstRoleIsUnique && !secondRoleIsUnique)
					{
						// Shallow map toward firstRolePlayer.
						possibilityBits |= SECOND_FIRST_SHALLOW;
						manyToOne = true;
					}
					else if (!firstRoleIsUnique && secondRoleIsUnique) // ...only secondRole is unique...
					{
						// Shallow map toward secondRolePlayer.
						possibilityBits |= FIRST_SECOND_SHALLOW;
						manyToOne = true;
					}
					else if (firstRoleIsUnique && secondRoleIsUnique) // ...both roles are unique...
					{
						// If this is a ring fact type...
						if (firstRolePlayer == secondRolePlayer)
						{
							// If only firstRole is mandatory...
							if (firstRoleIsExplicitlyMandatory && !secondRoleIsExplicitlyMandatory)
							{
								// Shallow map toward firstRolePlayer (mandatory role player).
								possibilityBits |= FIRST_SECOND_SHALLOW;
							}
							else if (!firstRoleIsExplicitlyMandatory && secondRoleIsExplicitlyMandatory) // ...only secondRole is mandatory...
							{
								// Shallow map toward secondRolePlayer (mandatory role player).
								possibilityBits |= SECOND_FIRST_SHALLOW;
							}
							else // ...otherwise...
							{
								// Shallow map toward firstRolePlayer.
								possibilityBits |= FIRST_SECOND_SHALLOW;
							}
						}
						else // ...not a ring fact type...
						{
							// These are used to make sure that we never shallowly map towards a preferred identifier.
							bool firstRoleIsUniqueAndPreferred = firstRoleIsUnique && firstRoleUniquenessConstraint.IsPreferred;
							bool secondRoleIsUniqueAndPreferred = secondRoleIsUnique && secondRoleUniquenessConstraint.IsPreferred;

							// If neither role is mandatory...
							if (!firstRoleIsExplicitlyMandatory && !secondRoleIsExplicitlyMandatory)
							{
								// If firstRole is not preferred...
								if (!firstRoleIsUniqueAndPreferred)
								{
									// Shallow map toward firstRolePlayer.
									possibilityBits |= SECOND_FIRST_SHALLOW;
								}

								// If secondRole is not preferred...
								if (!secondRoleIsUniqueAndPreferred)
								{
									// Shallow map toward secondRolePlayer.
									possibilityBits |= FIRST_SECOND_SHALLOW;
								}
							}
							else if (firstRoleIsExplicitlyMandatory && !secondRoleIsExplicitlyMandatory) // ...only firstRole is mandatory...
							{
								// Note that the first role cannot be be preferred if the second role is not mandatory
								// Shallow map toward firstRolePlayer.
								possibilityBits |= SECOND_FIRST_SHALLOW;
#if FALSE
								// UNDONE: This is a much deeper check for 1-1 patterns off of mandatory constraints. Both this and
								// the current much quicker check are meant to limit permutation checks on patterns where numerous
								// 1-1 fact types reference the same optional role player. Both of these systems are extremely fragile
								// to one of the uses of the value being made mandatory, in which case this loop does not apply.
								// We need to find a quicker mechanism for determining when we should allow an absorption towards
								// a fully optional object type, or some other check to eliminate extremely long chains (these can
								// easily consume all memory on a machine).
								bool allowMappingTowardsOptionalRole = true;
								if (null != (mandatory = secondRolePlayer.ImpliedMandatoryConstraint))
								{
									if (!(secondRoleIsUniqueAndPreferred && factType.ImpliedByObjectification != null))
									{
										foreach (Role testRole in mandatory.RoleCollection)
										{
											if (testRole != secondRole && !ShouldIgnoreFactType((testRole.Proxy ?? (RoleBase)testRole).FactType))
											{
												Role oppositeRole;
												if (testRole.SingleRoleAlethicUniquenessConstraint != null &&
													null != (oppositeRole = testRole.OppositeRoleAlwaysResolveProxy as Role) &&
													null != oppositeRole.SingleRoleAlethicUniquenessConstraint &&
													null != (mandatory = oppositeRole.SingleRoleAlethicMandatoryConstraint) &&
													!mandatory.IsImplied)
												{
													// If there are multiple 1-1 mappings towards an object type with
													// an implied mandatory, then don't consider any mappings towards
													// this entity.
													allowMappingTowardsOptionalRole = false;
													break;
												}
											}
										}
									}
								}

								if (allowMappingTowardsOptionalRole)
#endif // FALSE
								if (null == secondRolePlayer.ImpliedMandatoryConstraint ||
									((secondRoleIsUniqueAndPreferred && !secondRolePlayerIsValueType) || factType.ImpliedByObjectification != null))
								{
									// If secondRole is not preferred...
									if (!secondRoleIsUniqueAndPreferred)
									{
										// Shallow map toward secondRolePlayer.
										possibilityBits |= FIRST_SECOND_SHALLOW;
									}

									// Deep map toward secondRolePlayer.
									possibilityBits |= FIRST_SECOND_DEEP;
								}
							}
							else if (!firstRoleIsExplicitlyMandatory && secondRoleIsExplicitlyMandatory) // ...only secondRole is mandatory...
							{
								// Note that the second role cannot be preferred if the first role is not mandatory
								// Shallow map toward secondRolePlayer.
								possibilityBits |= FIRST_SECOND_SHALLOW;

#if FALSE
								// UNDONE: See comments above, duplicate code switching first and second
								bool allowMappingTowardsOptionalRole = true;
								if (null != (mandatory = firstRolePlayer.ImpliedMandatoryConstraint))
								{
									if (!(firstRoleIsUniqueAndPreferred && factType.ImpliedByObjectification != null))
									{
										foreach (Role testRole in mandatory.RoleCollection)
										{
											if (testRole != firstRole && !ShouldIgnoreFactType((testRole.Proxy ?? (RoleBase)testRole).FactType))
											{
												Role oppositeRole;
												if (testRole.SingleRoleAlethicUniquenessConstraint != null &&
													null != (oppositeRole = testRole.OppositeRoleAlwaysResolveProxy as Role) &&
													null != oppositeRole.SingleRoleAlethicUniquenessConstraint &&
													null != (mandatory = oppositeRole.SingleRoleAlethicMandatoryConstraint) &&
													!mandatory.IsImplied)
												{
													// If there are multiple 1-1 mappings towards an object type with
													// an implied mandatory, then don't consider any mappings towards
													// this entity.
													allowMappingTowardsOptionalRole = false;
													break;
												}
											}
										}
									}
								}

								if (allowMappingTowardsOptionalRole)
#endif // FALSE
								if (null == firstRolePlayer.ImpliedMandatoryConstraint ||
									((firstRoleIsUniqueAndPreferred && !firstRolePlayerIsValueType) || factType.ImpliedByObjectification != null))
								{
									// If firstRole is not preferred...
									if (!firstRoleIsUniqueAndPreferred)
									{
										// Shallow map toward firstRolePlayer.
										possibilityBits |= SECOND_FIRST_SHALLOW;
									}

									// Deep map toward firstRolePlayer.
									possibilityBits |= SECOND_FIRST_DEEP;
								}
							}
							else // ...both roles are mandatory...
							{
								// If firstRole is not preferred...
								if (!firstRoleIsUniqueAndPreferred)
								{
									// Shallow map toward firstRolePlayer.
									possibilityBits |= SECOND_FIRST_SHALLOW;
								}

								// If secondRole is not preferred...
								if (!secondRoleIsUniqueAndPreferred)
								{
									// Shallow map toward secondRolePlayer.
									possibilityBits |= FIRST_SECOND_SHALLOW;
								}

								// Possible deep map toward firstRolePlayer and toward secondRolePlayer
								possibilityBits |= FIRST_SECOND_DEEP | SECOND_FIRST_DEEP;
							}
						}
					}
					Debug.Assert(possibilityBits != 0);
					switch (possibilityBits)
					{
						case FIRST_SECOND_SHALLOW:
							(manyToOne ? decidedManyToOneFactTypeMappings : decidedOneToOneFactTypeMappings).Add(factType, new FactTypeMapping(factType, firstRole, secondRole, GetFlags(false, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory)));
							break;
						case SECOND_FIRST_SHALLOW:
							(manyToOne ? decidedManyToOneFactTypeMappings : decidedOneToOneFactTypeMappings).Add(factType, new FactTypeMapping(factType, secondRole, firstRole, GetFlags(false, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory)));
							break;
						case FIRST_SECOND_DEEP:
							(manyToOne ? decidedManyToOneFactTypeMappings : decidedOneToOneFactTypeMappings).Add(factType, new FactTypeMapping(factType, firstRole, secondRole, GetFlags(true, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory)));
							break;
						case SECOND_FIRST_DEEP:
							(manyToOne ? decidedManyToOneFactTypeMappings : decidedOneToOneFactTypeMappings).Add(factType, new FactTypeMapping(factType, secondRole, firstRole, GetFlags(true, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory)));
							break;
						default:
							{
								// UNDONE: I don't see any reason to use a heavy-weight list structure here. The
								// same information could be stored in an UndecidedFactTypeMapping structure that
								// uses a bit field mechanism similar to this block of code. This would allow us
								// to store the factType/firstRole/secondRole once and interpret the contents based
								// on a single bitfield. In the meantime, keep the list as small as possible.
								int countBits = possibilityBits;
								int count = 0;
								while (countBits != 0)
								{
									if (0 != (countBits & 1))
									{
										++count;
									}
									countBits >>= 1;
								}
								FactTypeMappingList potentialMappingList = new FactTypeMappingList(count);
								count = -1;
								if (0 != (possibilityBits & FIRST_SECOND_SHALLOW))
								{
									potentialMappingList.Add(new FactTypeMapping(factType, firstRole, secondRole, GetFlags(false, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory)));
								}
								if (0 != (possibilityBits & SECOND_FIRST_SHALLOW))
								{
									potentialMappingList.Add(new FactTypeMapping(factType, secondRole, firstRole, GetFlags(false, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory)));
								}
								if (0 != (possibilityBits & FIRST_SECOND_DEEP))
								{
									potentialMappingList.Add(new FactTypeMapping(factType, firstRole, secondRole, GetFlags(true, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory)));
								}
								if (0 != (possibilityBits & SECOND_FIRST_DEEP))
								{
									potentialMappingList.Add(new FactTypeMapping(factType, secondRole, firstRole, GetFlags(true, secondRolePlayerIsValueType, secondRoleIsMandatory, secondRoleIsImplicitlyMandatory, firstRolePlayerIsValueType, firstRoleIsMandatory, firstRoleIsImplicitlyMandatory)));
								}
								undecidedOneToOneFactTypeMappings.Add(factType, potentialMappingList);
								break;
							}
					}
				}
			}
		}
예제 #8
0
		/// <summary>
		/// Transforms the data in <see cref="ORMModel"/> into this <see cref="AbstractionModel"/>.
		/// </summary>
		private void TransformORMtoOial()
		{
			ORMModel model = this.ORMModel;
			LinkedElementCollection<FactType> modelFactTypes = model.FactTypeCollection;

			FactTypeMappingDictionary decidedManyToOneFactTypeMappings = new FactTypeMappingDictionary();
			FactTypeMappingDictionary decidedOneToOneFactTypeMappings = new FactTypeMappingDictionary();
			FactTypeMappingListDictionary undecidedOneToOneFactTypeMappings = new FactTypeMappingListDictionary();

			PerformInitialFactTypeMappings(modelFactTypes, decidedManyToOneFactTypeMappings, decidedOneToOneFactTypeMappings, undecidedOneToOneFactTypeMappings);
			FilterFactTypeMappings(decidedManyToOneFactTypeMappings, decidedOneToOneFactTypeMappings, undecidedOneToOneFactTypeMappings);

			FactTypeMappingPermuter permuter = new FactTypeMappingPermuter(decidedManyToOneFactTypeMappings, decidedOneToOneFactTypeMappings, undecidedOneToOneFactTypeMappings);
			FactTypeMappingDictionary decidedFactTypeMappings = permuter.Run();

			GenerateOialModel(decidedFactTypeMappings);
		}
예제 #9
0
                /// <summary>
                /// If the number of undecided elements is unreasonably high,
                /// then apply incrementally more stringent requirements for
                /// deciding fact type mappings until we have a reasonable number.
                /// </summary>
                public void EnsureReasonablePermutations(FactTypeMappingListDictionary allUndecidedMappings, FactTypeMappingDictionary allPredecidedMappings, FactTypeMappingDictionary allDecidedMappings)
                {
                    FactTypeMappingListList undecidedMappings = myUndecidedOneToOneFactTypeMappings;
                    double maxPermutations = CalculateMaxNumberOfPermutations(undecidedMappings);

                    if (maxPermutations > MaxReasonablePermutations)
                    {
                        int undecidedMappingCount = undecidedMappings.Count;
                        Predicate <FactTypeMapping>[] reductionConditions = ReductionConditions;
                        if (reductionConditions == null)
                        {
                            // Note that there is intentionally a lot of duplication in
                            // these routines. An earlier design attempted to call previous
                            // conditions along with later ones, but this resulted in a much
                            // more complicated algorithm and multiple calls. The algorithm
                            // was simplified in exchange for making these condition routines
                            // more complicated.
                            reductionConditions = new Predicate <FactTypeMapping>[] {
                                delegate(FactTypeMapping mapping)
                                {
                                    // If the fact type has a single non-mandatory value type
                                    // then do not map towards the value type.
                                    FactTypeMappingFlags mappingFlags = mapping.Flags;
                                    if ((mappingFlags & (FactTypeMappingFlags.TowardsValueType | FactTypeMappingFlags.FromValueType)) == (FactTypeMappingFlags.TowardsValueType))
                                    {
                                        if (0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleMandatory))
                                        {
                                            return(0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleImpliedMandatory));
                                        }
                                        return(true);
                                    }
                                    return(false);
                                },
                                delegate(FactTypeMapping mapping)
                                {
                                    // If the fact type has an unbalanced mandatory and is not a subtype,
                                    // then map towards the mandatory.
                                    FactTypeMappingFlags mappingFlags = mapping.Flags;
                                    if (FactTypeMappingFlags.FromRoleMandatory == (mappingFlags & (FactTypeMappingFlags.FromRoleMandatory | FactTypeMappingFlags.FromRoleImpliedMandatory)) &&
                                        0 == (mappingFlags & FactTypeMappingFlags.Subtype) &&
                                        FactTypeMappingFlags.TowardsRoleMandatory != (mappingFlags & (FactTypeMappingFlags.TowardsRoleMandatory | FactTypeMappingFlags.TowardsRoleImpliedMandatory)))
                                    {
                                        return(true);
                                    }

                                    // Duplicate previous ValueType check
                                    if ((mappingFlags & (FactTypeMappingFlags.TowardsValueType | FactTypeMappingFlags.FromValueType)) == (FactTypeMappingFlags.TowardsValueType))
                                    {
                                        if (0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleMandatory))
                                        {
                                            return(0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleImpliedMandatory));
                                        }
                                        return(true);
                                    }
                                    return(false);
                                },
                                delegate(FactTypeMapping mapping)
                                {
                                    // Map away from a preferred identifier. This is not a cumulative test, and is ignored for later conditions.
                                    FactTypeMappingFlags mappingFlags = mapping.Flags;
                                    if (0 == (mappingFlags & FactTypeMappingFlags.FromPreferredIdentifier))
                                    {
                                        return(true);
                                    }

                                    // Duplicate unbalanced ValueType and unbalanced mandatory checks
                                    if (FactTypeMappingFlags.FromRoleMandatory == (mappingFlags & (FactTypeMappingFlags.FromRoleMandatory | FactTypeMappingFlags.FromRoleImpliedMandatory)) &&
                                        0 == (mappingFlags & FactTypeMappingFlags.Subtype) &&
                                        FactTypeMappingFlags.TowardsRoleMandatory != (mappingFlags & (FactTypeMappingFlags.TowardsRoleMandatory | FactTypeMappingFlags.TowardsRoleImpliedMandatory)))
                                    {
                                        return(true);
                                    }
                                    if ((mappingFlags & (FactTypeMappingFlags.TowardsValueType | FactTypeMappingFlags.FromValueType)) == (FactTypeMappingFlags.TowardsValueType))
                                    {
                                        if (0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleMandatory))
                                        {
                                            return(0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleImpliedMandatory));
                                        }
                                        return(true);
                                    }
                                    return(false);
                                },
                                delegate(FactTypeMapping mapping)
                                {
                                    // Prefer a shallow mapping.
                                    FactTypeMappingFlags mappingFlags = mapping.Flags;
                                    if (0 != (mappingFlags & FactTypeMappingFlags.DeepMapping))
                                    {
                                        return(true);
                                    }

                                    // Duplicate unbalanced ValueType and unbalanced mandatory checks
                                    if (FactTypeMappingFlags.FromRoleMandatory == (mappingFlags & (FactTypeMappingFlags.FromRoleMandatory | FactTypeMappingFlags.FromRoleImpliedMandatory)) &&
                                        0 == (mappingFlags & FactTypeMappingFlags.Subtype) &&
                                        FactTypeMappingFlags.TowardsRoleMandatory != (mappingFlags & (FactTypeMappingFlags.TowardsRoleMandatory | FactTypeMappingFlags.TowardsRoleImpliedMandatory)))
                                    {
                                        return(true);
                                    }
                                    if ((mappingFlags & (FactTypeMappingFlags.TowardsValueType | FactTypeMappingFlags.FromValueType)) == (FactTypeMappingFlags.TowardsValueType))
                                    {
                                        if (0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleMandatory))
                                        {
                                            return(0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleImpliedMandatory));
                                        }
                                        return(true);
                                    }
                                    return(false);
                                },
                                delegate(FactTypeMapping mapping)
                                {
                                    // If we have too many permutations then just map towards the first role.
                                    // Yes, this is completely arbitrary, but getting anywhere past item 2 on
                                    // this list will be extremely rarely and represents truly pathological cases.

                                    // Perform previous flag-based checks first.
                                    FactTypeMappingFlags mappingFlags = mapping.Flags;
                                    if (0 != (mappingFlags & FactTypeMappingFlags.DeepMapping))
                                    {
                                        return(true);
                                    }
                                    if (FactTypeMappingFlags.FromRoleMandatory == (mappingFlags & (FactTypeMappingFlags.FromRoleMandatory | FactTypeMappingFlags.FromRoleImpliedMandatory)) &&
                                        0 == (mappingFlags & FactTypeMappingFlags.Subtype) &&
                                        FactTypeMappingFlags.TowardsRoleMandatory != (mappingFlags & (FactTypeMappingFlags.TowardsRoleMandatory | FactTypeMappingFlags.TowardsRoleImpliedMandatory)))
                                    {
                                        return(true);
                                    }
                                    if ((mappingFlags & (FactTypeMappingFlags.TowardsValueType | FactTypeMappingFlags.FromValueType)) == (FactTypeMappingFlags.TowardsValueType))
                                    {
                                        if (0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleMandatory))
                                        {
                                            return(0 != (mappingFlags & FactTypeMappingFlags.TowardsRoleImpliedMandatory));
                                        }
                                        return(true);
                                    }
                                    Role role = mapping.TowardsRole;
                                    return(0 != mapping.FactType.RoleCollection.IndexOf((RoleBase)role.Proxy ?? role));
                                },
                            };
                            ReductionConditions = reductionConditions;
                        }
                        FactTypeMappingList decidedMappings = myPredecidedOneToOneFactTypeMappings;
                        for (int maxReduction = 0; maxReduction < reductionConditions.Length; ++maxReduction)
                        {
                            for (int undecidedMappingIndex = undecidedMappingCount - 1; undecidedMappingIndex >= 0; --undecidedMappingIndex)
                            {
                                FactTypeMappingList testMappings = undecidedMappings[undecidedMappingIndex];
                                int testMappingCount             = testMappings.Count;
                                // Note that the max length of this list is four (shallow and deep both directions)
                                FactTypeMapping singleMapping = null;
                                for (int i = 0; i < testMappingCount; ++i)
                                {
                                    FactTypeMapping testMapping = testMappings[i];
                                    if (!reductionConditions[maxReduction](testMapping))
                                    {
                                        // This test mapping is not filtered, allow it
                                        if (singleMapping == null)
                                        {
                                            singleMapping = testMapping;
                                        }
                                        else
                                        {
                                            singleMapping = null;
                                            break;
                                        }
                                    }
                                }
                                if (singleMapping != null)
                                {
                                    decidedMappings.Add(singleMapping);
                                    undecidedMappings.RemoveAt(undecidedMappingIndex);
                                    --undecidedMappingCount;
                                    maxPermutations /= testMappingCount;
                                    FactType factTypeKey = singleMapping.FactType;
                                    allUndecidedMappings.Remove(factTypeKey);
                                    allPredecidedMappings.Add(factTypeKey, singleMapping);
                                    allDecidedMappings.Add(factTypeKey, singleMapping);
                                }
                            }
                            if (maxPermutations <= MaxReasonablePermutations)
                            {
                                break;
                            }
                        }
                    }
                }
예제 #10
0
		/// <summary>
		/// Generages the <see cref="ConceptType"/> objects along with any relationships that they have and adds them to the
		/// model.
		/// </summary>
		/// <param name="factTypeMappings">A dictionary of all the final decided FactTypeMapping objects.</param>
		private void GenerateConceptTypes(FactTypeMappingDictionary factTypeMappings)
		{
			ORMModel model = this.ORMModel;
			LinkedElementCollection<ObjectType> modelObjectTypes = model.ObjectTypeCollection;
			AbstractionModel oialModel = this.AbstractionModel;

			// For each object type in the model...
			foreach (ObjectType objectType in modelObjectTypes)
			{
				if (ShouldIgnoreObjectType(objectType))
				{
					continue;
				}
				// If it should have a conctpt type...
				if (ObjectTypeIsConceptType(objectType, factTypeMappings))
				{
					// Create the ConceptType object.
					PropertyAssignment name = new PropertyAssignment(ConceptType.NameDomainPropertyId, objectType.Name);
					ConceptType conceptType = new ConceptType(Store, name);
					ConceptTypeIsForObjectType conceptTypeIsForObjectType = new ConceptTypeIsForObjectType(conceptType, objectType);

					// Add it to the model.
					oialModel.ConceptTypeCollection.Add(conceptType);

					// If this conceptType is for a ValueType...
					if (objectType.IsValueType)
					{
						InformationTypeFormat valueTypeInformationTypeFormat = InformationTypeFormatIsForValueType.GetInformationTypeFormat(objectType);

						RoleAssignment conceptTypeRole = new RoleAssignment(InformationType.ConceptTypeDomainRoleId, conceptType);
						RoleAssignment informationTypeFormat = new RoleAssignment(InformationType.InformationTypeFormatDomainRoleId, valueTypeInformationTypeFormat);
						RoleAssignment[] roleAssignments = { conceptTypeRole, informationTypeFormat };
						PropertyAssignment isMandatory = new PropertyAssignment(InformationType.IsMandatoryDomainPropertyId, true);
						PropertyAssignment informationTypeNameProperty = new PropertyAssignment(InformationType.NameDomainPropertyId, String.Concat(objectType.Name, "Value"));
						PropertyAssignment[] informationTypePropertyAssignments = { isMandatory, informationTypeNameProperty };

						// ConceptType for conceptType gets an InformationType that references InformationTypeFormat for conceptType.
						InformationType informationType = new InformationType(Store, roleAssignments, informationTypePropertyAssignments);

						PropertyAssignment uniquenessNameProperty = new PropertyAssignment(Uniqueness.NameDomainPropertyId, String.Concat(objectType.Name, "Uniqueness"));
						PropertyAssignment isPreferred = new PropertyAssignment(Uniqueness.IsPreferredDomainPropertyId, true);
						PropertyAssignment[] uniquenessPropertyAssignments = { uniquenessNameProperty, isPreferred };

						// Uniqueness constraint
						Uniqueness uniqueness = new Uniqueness(Store, uniquenessPropertyAssignments);
						UniquenessIncludesConceptTypeChild uniquenessIncludesConceptTypeChild = new UniquenessIncludesConceptTypeChild(uniqueness, informationType);

						conceptType.UniquenessCollection.Add(uniqueness);
					}
				}
			}
		}
예제 #11
0
		private void GenerateFactTypeMappings(FactTypeMappingDictionary factTypeMappings)
		{
			foreach (FactTypeMapping mapping in factTypeMappings.Values)
			{
				// Note that there will currently be no existing maps, but this is
				// likely to change once we do more incremental work. If the FactTypeMapsTowardsRole
				// instance already exists for this FactType, then the following will throw.
				// Any role changes here need to properly update the existing link's mapping
				// pattern properties. This should be done with an OnRolePlayerChanged call
				// (or a rule) inside FactTypeMapsTowardsRole.
				FactTypeMapsTowardsRole.Create(mapping.FactType, mapping.TowardsRole, mapping.MappingDepth);
			}
		}
예제 #12
0
		/// <summary>
		/// Generates the <see cref="Uniqueness"/> objects for the <see cref="AbstractionModel"/>.
		/// </summary>
		/// <param name="factTypeMappings">The decided <see cref="FactTypeMapping"/> objects.</param>
		private void GenerateUniqueness(FactTypeMappingDictionary factTypeMappings)
		{
			// TODO: clean this up.
			AbstractionModel oialModel = this.AbstractionModel;

			// For each concept type in the model...
			foreach (ConceptType conceptType in oialModel.ConceptTypeCollection)
			{
				ObjectType objectType = ConceptTypeIsForObjectType.GetObjectType(conceptType);

				// For each role played by its object type...
				foreach (Role role in objectType.PlayedRoleCollection)
				{
					if (ShouldIgnoreFactType(role.BinarizedFactType))
					{
						continue;
					}

					Role oppositeRole = role.OppositeRoleAlwaysResolveProxy.Role;

					// For each constraint on the opposite role...
					foreach (ConstraintRoleSequence constraintRoleSequence in oppositeRole.ConstraintRoleSequenceCollection)
					{
						UniquenessConstraint uninquenessConstraint = constraintRoleSequence as UniquenessConstraint;

						// If it is a uniqueness constraint...
						if (uninquenessConstraint != null && uninquenessConstraint.Modality == ConstraintModality.Alethic)
						{
							if (UniquenessIsForUniquenessConstraint.GetUniqueness(uninquenessConstraint) != null)
							{
								continue;
							}

							bool hasFactTypeThatShouldBeIgnored = false;
							bool allChildrenMapTowardObjectType = true;
							IList<FactType> factTypes = new List<FactType>();

							foreach (Role childRole in uninquenessConstraint.RoleCollection)
							{
								FactType binarizedFactType = childRole.BinarizedFactType;
								if (ShouldIgnoreFactType(binarizedFactType))
								{
									hasFactTypeThatShouldBeIgnored = true;
									break;
								}
								FactTypeMapping factTypeMapping = factTypeMappings[binarizedFactType];

								if (factTypeMapping.TowardsRole != childRole.OppositeRoleAlwaysResolveProxy.Role)
								{
									allChildrenMapTowardObjectType = false;
									break;
								}
								else
								{
									factTypes.Add(binarizedFactType);
								}
							}
							if (hasFactTypeThatShouldBeIgnored)
							{
								continue;
							}

							if (allChildrenMapTowardObjectType)
							{
								IList<ConceptTypeChild> conceptTypeChildren = new List<ConceptTypeChild>();
								bool skipThisUniquenessConstraint = false;

								foreach (FactType factType in factTypes)
								{
									bool childWasAssimilation = false;
									bool missedChild = true;
									foreach (ConceptTypeChild conceptTypeChild in ConceptTypeChildHasPathFactType.GetConceptTypeChild(factType))
									{
										if (conceptTypeChild.Parent != conceptType)
										{
											// This ConceptTypeChild is of a different ConceptType, so go on to the next ConceptTypeChild.
											continue;
										}
										if (conceptTypeChild is ConceptTypeAssimilatesConceptType)
										{
											childWasAssimilation = true;
											break;
										}

										missedChild = false;
										conceptTypeChildren.Add(conceptTypeChild);
									}

									if (childWasAssimilation)
									{
										skipThisUniquenessConstraint = true;
										break;
									}
									if (missedChild)
									{
										// We couldn't find a ConceptTypeChild for this FactType, so just bail out.
										skipThisUniquenessConstraint = true;
										break;
									}
								}

								if (!skipThisUniquenessConstraint)
								{
									PropertyAssignment name = new PropertyAssignment(Uniqueness.NameDomainPropertyId, uninquenessConstraint.Name);
									PropertyAssignment isPreferred = new PropertyAssignment(Uniqueness.IsPreferredDomainPropertyId, uninquenessConstraint.IsPreferred);
									PropertyAssignment[] propertyAssignments = { name, isPreferred };

									// Create uniquenesss
									Uniqueness uniqueness = new Uniqueness(Store, propertyAssignments);
									uniqueness.ConceptType = conceptType;
									new UniquenessIsForUniquenessConstraint(uniqueness, uninquenessConstraint);

									foreach (ConceptTypeChild conceptTypeChild in conceptTypeChildren)
									{
										UniquenessIncludesConceptTypeChild uniquenessIncludesConceptTypeChild = new UniquenessIncludesConceptTypeChild(uniqueness, conceptTypeChild);
									}
								}
							}
						}
					}
				}
			}
		}
예제 #13
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);
		}
예제 #14
0
			public FactTypeMappingPermuter(FactTypeMappingDictionary predecidedManyToOneFactTypeMappings, FactTypeMappingDictionary predecidedOneToOneFactTypeMappings, FactTypeMappingListDictionary undecidedOneToOneFactTypeMappings)
			{
				myPredecidedManyToOneFactTypeMappings = predecidedManyToOneFactTypeMappings;
				myPredecidedOneToOneFactTypeMappings = predecidedOneToOneFactTypeMappings;
				myUndecidedOneToOneFactTypeMappings = undecidedOneToOneFactTypeMappings;

				myDecidedFactTypeMappings = new FactTypeMappingDictionary(predecidedManyToOneFactTypeMappings.Count + predecidedOneToOneFactTypeMappings.Count + undecidedOneToOneFactTypeMappings.Count);

				foreach (KeyValuePair<FactType, FactTypeMapping> pair in predecidedManyToOneFactTypeMappings)
				{
					myDecidedFactTypeMappings.Add(pair.Key, pair.Value);
				}
				foreach (KeyValuePair<FactType, FactTypeMapping> pair in predecidedOneToOneFactTypeMappings)
				{
					myDecidedFactTypeMappings.Add(pair.Key, pair.Value);
				}
			}
예제 #15
0
				/// <summary>
				/// Apply more stringent criteria to unusually long chains to ensure that
				/// the permutation process will not explode.
				/// </summary>
				private void ReduceChains(FactTypeMappingDictionary allDecidedMappings)
				{
					// Make sure all of the chains are of a size that we can actually permute
					FactTypeMappingDictionary predecidedMappings = myPredecidedOneToOneFactTypeMappings;
					FactTypeMappingListDictionary undecidedMappings = myUndecidedOneToOneFactTypeMappings;
					foreach (Chain chain in myChains)
					{
						chain.EnsureReasonablePermutations(undecidedMappings, predecidedMappings, allDecidedMappings);
					}
				}
예제 #16
0
		/// <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;
		}
예제 #17
0
		/// <summary>
		/// Populates this <see cref="AbstractionModel"/> given the decided <see cref="FactTypeMapping"/> objects.
		/// </summary>
		/// <param name="factTypeMappings">The decided <see cref="FactTypeMapping"/> objects.</param>
		private void GenerateOialModel(FactTypeMappingDictionary factTypeMappings)
		{
			GenerateInformationTypeFormats();
			GenerateConceptTypes(factTypeMappings);
			GenerateConceptTypeChildren(factTypeMappings);
			GenerateFactTypeMappings(factTypeMappings);
			GenerateUniqueness(factTypeMappings);
			GenerateAssociations();
		}
예제 #18
0
		/// <summary>
		/// Determins wheather an <see cref="ObjectType"/> is destined to be a top-level <see cref="ConceptType"/> or not.
		/// </summary>
		/// <param name="objectType">The <see cref="ObjectType"/> to test.</param>
		/// <param name="factTypeMappings">A dictionary of all the final decided <see cref="FactTypeMapping"/> objects.</param>
		/// <returns>Returns true if the <see cref="ObjectType"/> is destined to be a top-level <see cref="ConceptType"/>.</returns>
		private bool ObjectTypeIsTopLevelConceptType(ObjectType objectType, FactTypeMappingDictionary factTypeMappings)
		{
			if (ObjectTypeIsConceptType(objectType, factTypeMappings))
			{
				LinkedElementCollection<Role> roles = ObjectTypePlaysRole.GetPlayedRoleCollection(objectType);

				foreach (Role role in roles)
				{
					FactType factType = role.BinarizedFactType;
					if (ShouldIgnoreFactType(factType))
					{
						continue;
					}
					FactTypeMapping factTypeMapping = factTypeMappings[factType];

					if (factTypeMapping.FromObjectType == objectType && factTypeMapping.MappingDepth == MappingDepth.Deep)
					{
						return false;
					}
				}
				return true;
			}

			return false;
		}
예제 #19
0
		/// <summary>
		/// Generates the <see cref="ConceptTypeChild">concept type children</see> for each
		/// <see cref="ConceptType"/> in the <see cref="AbstractionModel">OIAL model</see>.
		/// </summary>
		/// <param name="factTypeMappings">
		/// The set of all decided <see cref="FactTypeMapping">fact type mappings</see>.
		/// </param>
		private void GenerateConceptTypeChildren(FactTypeMappingDictionary factTypeMappings)
		{
			List<FactType> factTypePath = new List<FactType>();

			foreach (ConceptType conceptType in this.AbstractionModel.ConceptTypeCollection)
			{
				ObjectType objectType = ConceptTypeIsForObjectType.GetObjectType(conceptType);
				bool? conceptTypeHasDeepMappingAway = null;

				// NOTE: We don't need the ShouldIgnoreObjectType filter here, because object
				// types that we want to ignore won't be in the OIAL model in the first place.

				foreach (Role playedRole in objectType.PlayedRoleCollection)
				{
					// NOTE: We don't need the ShouldIgnoreFactType filter here, because fact types that
					// we want to ignore won't be in the set of fact type mappings in the first place.
					FactType playedFactType = playedRole.BinarizedFactType;

					FactTypeMapping factTypeMapping;

					if (factTypeMappings.TryGetValue(playedFactType, out factTypeMapping) &&
						factTypeMapping.TowardsRole == playedRole)
					{
						// The fact type has a mapping and that mapping is towards the role played by
						// this concept type, so we need to generate concept type children for it.
						GenerateConceptTypeChildrenForFactTypeMapping(factTypeMappings, conceptType, ref conceptTypeHasDeepMappingAway, factTypeMapping, factTypePath, true);
					}
				}
			}
		}
예제 #20
0
		/// <summary>
		/// Determins wheather an <see cref="ObjectType"/> should have a <see cref="ConceptType"/> or not.
		/// </summary>
		/// <remarks>
		/// An <see cref="ObjectType"/> should have a <see cref="ConceptType"/> if:
		/// <list>
		/// <item><description>It is independent.</description></item>
		/// <item><description>It is a subtype.</description></item>
		/// <item><description>It has a <see cref="FactTypeMapping"/> towards it for a <see cref="FactType"/> that is not part of its preferred identifier.</description></item>
		/// </list>
		/// </remarks>
		/// <param name="objectType">The <see cref="ObjectType"/> to test.</param>
		/// <param name="factTypeMappings">A dictionary of all the final decided <see cref="FactTypeMapping"/> objects.</param>
		/// <returns>Returns true if the <see cref="ObjectType"/> should have <see cref="ConceptType"/>.</returns>
		private bool ObjectTypeIsConceptType(ObjectType objectType, FactTypeMappingDictionary factTypeMappings)
		{
			// If objectType is independent...
			if (objectType.TreatAsIndependent)
			{
				return true;
			}

			foreach (Role role in ObjectTypePlaysRole.GetPlayedRoleCollection(objectType))
			{
				FactType factType = role.BinarizedFactType;
				if (ShouldIgnoreFactType(factType))
				{
					continue;
				}

				// If it is a subtype fact, we need a concept type. Although the algorithm only calls for this in the case
				// of subtype meta roles, supertype meta roles will always match the patterns below, so we can immediately
				// return true for them as well.
				if (factType is SubtypeFact)
				{
					return true;
				}

				FactTypeMapping factTypeMapping = factTypeMappings[factType];

				// If fact type mapping is toward objectType...
				if (factTypeMapping.TowardsObjectType == objectType)
				{
					bool isPartOfPreferredIdentifier = false;
					foreach (ConstraintRoleSequence constraintRoleSequence in factTypeMapping.FromRole.ConstraintRoleSequenceCollection)
					{
						UniquenessConstraint uninquenessConstraint = constraintRoleSequence as UniquenessConstraint;
						if (uninquenessConstraint != null && uninquenessConstraint.IsPreferred)
						{
							isPartOfPreferredIdentifier = true;
							break;
						}
					}

					if (!isPartOfPreferredIdentifier)
					{
						// This FactType is not part of the preferred identifier.
						return true;
					}
				}
			}

			return false;
		}