public Chain()
 {
     myObjectTypes = new List <ObjectType>();
     myPredecidedManyToOneFactTypeMappings = new FactTypeMappingList();
     myPredecidedOneToOneFactTypeMappings  = new FactTypeMappingList();
     myUndecidedOneToOneFactTypeMappings   = new FactTypeMappingListList();
     myPossiblePermutations = new List <Permutation>();
     mySmallestPermutationsInTermsOfConceptTypes = new List <Permutation>();
 }
Beispiel #2
0
			/// <summary>
			/// Permutes the <see cref="FactTypeMapping"/>s, recursively.
			/// </summary>
			/// <param name="permutations">The collection containing <see cref="Permutation"/>s that have already been calculated, and to which newly calculated <see cref="Permutation"/>s are added.</param>
			/// <param name="undecidedMappings">The list of potential <see cref="FactTypeMapping"/>s for each <see cref="FactType"/> that need to be permuted.</param>
			/// <param name="decidedMappings">The <see cref="FactTypeMapping"/>s that have already been decided for this branch of the permutation. Should initially be empty.</param>
			/// <param name="deeplyMappedObjectTypes"><see cref="ObjectType"/>s that already have some deep <see cref="FactTypeMapping"/> away from them.</param>
			/// <param name="currentPosition">The index into <paramref name="undecidedMappings"/> that should be processed.</param>
			private static void PermuteFactTypeMappings(IList<Permutation> permutations, FactTypeMappingListList undecidedMappings, FactTypeMappingList decidedMappings, Dictionary<ObjectType, object> deeplyMappedObjectTypes, int currentPosition)
			{
				int nextPosition = currentPosition + 1;
				bool isLastUndecided = (nextPosition == undecidedMappings.Count);
				foreach (FactTypeMapping potentialMapping in undecidedMappings[currentPosition])
				{
					if (potentialMapping.MappingDepth == MappingDepth.Deep && deeplyMappedObjectTypes.ContainsKey(potentialMapping.FromObjectType))
					{
						// We already have a deep mapping away from this object type, so we can skip this potential mapping (which would result in an illegal permutation).
						continue;
					}

					// Put this potential mapping onto the stack of decided mappings.
					decidedMappings.Add(potentialMapping);

					if (isLastUndecided)
					{
						// This is the end of the list of undecided fact types, so we can create a permutation.
						permutations.Add(new Permutation(new FactTypeMappingList(decidedMappings)));
					}
					else
					{
						if (potentialMapping.MappingDepth == MappingDepth.Deep)
						{
							// This is a deep mapping, so add the from object type to the set of deeply mapped object types.
							deeplyMappedObjectTypes[potentialMapping.FromObjectType] = null;
						}

						// Go on to the potential mappings for the next undecided fact type.
						PermuteFactTypeMappings(permutations, undecidedMappings, decidedMappings, deeplyMappedObjectTypes, nextPosition);

						if (potentialMapping.MappingDepth == MappingDepth.Deep)
						{
							// Remove the from object type from the set of deeply mapped object types.
							deeplyMappedObjectTypes.Remove(potentialMapping.FromObjectType);
						}
					}

					// Pop this potential mapping off the stack of decided mappings so that we can go on to the next potential mapping.
					decidedMappings.RemoveAt(decidedMappings.Count - 1);
				}
			}
Beispiel #3
0
			/// <summary>
			/// Returns the maximum number of <see cref="Permutation"/>s that could result for the specified set of undecided <see cref="FactTypeMapping"/>s.
			/// </summary>
			private static double CalculateMaxNumberOfPermutations(FactTypeMappingListList undecidedMappings)
			{
				double maxPermutations = 1;
				foreach (FactTypeMappingList mappingList in undecidedMappings)
				{
					maxPermutations *= mappingList.Count;
				}
				return maxPermutations;
			}
                /// <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;
                            }
                        }
                    }
                }