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

					myPredecidedManyToOneFactTypeMappings = predecidedManyToOneFactTypeMappings;
					myPredecidedOneToOneFactTypeMappings = predecidedOneToOneFactTypeMappings;
					myUndecidedOneToOneFactTypeMappings = undecidedOneToOneFactTypeMappings;
				}
Example #2
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;
		}
Example #3
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;
		}
Example #4
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);
			}
		}
Example #5
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);
		}
Example #6
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;
							}
					}
				}
			}
		}
Example #7
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);
		}
Example #8
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);
				}
			}
                /// <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;
                            }
                        }
                    }
                }