예제 #1
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;
                            }
                        }
                    }
                }