MemberDomainMap.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / MemberDomainMap.cs / 3 / MemberDomainMap.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.Data.Common.Utils; 
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Data.Mapping.ViewGeneration.Utils; 
using System.Data.Metadata.Edm;
using System.Linq; 
 
namespace System.Data.Mapping.ViewGeneration.Structures {
 
    using CellConstantSet = Set;

    // This class keeps track of the domain values of the different members
    // in a schema. E.g., for a discriminator, it keeps track of "P", 
    // "C"; for type of Person, it keeps track of Person, Customer, etc
    // It exposes two concepts -- the domain of a member variable and the 
    // different possible values for that member, e.g., the possible values 
    // could be 3, 4, 5 but the domain could be 3, 4 (domain is always a
    // subset of possibleVales 
    internal class MemberDomainMap : InternalBase {

        #region Constructor
        private MemberDomainMap(Dictionary domainMap, 
                                Dictionary nonConditionDomainMap,
                                MetadataWorkspace workspace) 
        { 
            m_domainMap = domainMap;
            m_workspace = workspace; 
            m_nonConditionDomainMap = nonConditionDomainMap;
        }
        // effects: Creates a map with all the condition member constants
        // from extentCells. viewtarget determines whether the view is an 
        // update or query view
        internal MemberDomainMap(ViewTarget viewTarget, IEnumerable extentCells, MetadataWorkspace workspace, ConfigViewGenerator config, Dictionary> inheritanceGraph) 
        { 
            m_domainMap = new Dictionary(MemberPath.EqualityComparer);
            m_workspace = workspace; 

            Dictionary domainMap = null;
            if (viewTarget == ViewTarget.UpdateView) {
                domainMap = CellConstantDomain.ComputeConstantDomainSetsForSlotsInUpdateViews(extentCells, workspace); 
            } else {
                domainMap = CellConstantDomain.ComputeConstantDomainSetsForSlotsInQueryViews(extentCells, workspace); 
            } 

            foreach (Cell cell in extentCells) { 
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget);
                // Get the atoms from cellQuery and only keep the ones that
                // are condition members
                foreach (OneOfConst condition in cellQuery.GetConjunctsFromWhereClause()) { 
                    // Note: TypeConditions are created using OneOfTypeConst and
                    // scalars are created using OneOfScalarConst 
                    MemberPath memberPath = condition.Slot.MemberPath; 
                    if (m_domainMap.ContainsKey(memberPath)) {
                        continue; 
                    }
                    Debug.Assert(condition is OneOfScalarConst || condition is OneOfTypeConst,
                                 "Unexpected OneOfConst");
 
                    // Take the narrowed domain from domainMap, if any
                    CellConstantSet domainValues; 
                    if (!domainMap.TryGetValue(memberPath, out domainValues)) { 
                        domainValues = CellConstantDomain.CreateDomainSetFromMemberPath(memberPath, m_workspace);
                    } 

                    //Don't count conditions that are satisfied through IsNull=false
                    if (!domainValues.Contains(CellConstant.NotNull))
                    { 
                        //multiple values of condition represent disjunction in conditions (not currently supported)
                        // if there is any condition constant that is NotNull 
                        if(condition.Values.Values.All(conditionConstant => (conditionConstant.Equals(CellConstant.NotNull)) )) 
                        {
                            continue; 
                        }
                        //else there is atleast one condition value that is allowed, continue view generation
                    }
 
                    //IsNull condition on a member that is non nullable is an invalid condition
                    if (domainValues.Count <= 0 || (!domainValues.Contains(CellConstant.Null) && condition.Values.Values.Contains(CellConstant.Null))) 
                    { 
                        string message = System.Data.Entity.Strings.ViewGen_InvalidCondition_0(memberPath.PathToString(false));
                        ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.InvalidCondition, message, cell, String.Empty); 
                        ExceptionHelpers.ThrowMappingException(record, config);
                    }
                    if (memberPath.IsAlwaysDefined(inheritanceGraph) == false)
                    { 
                        domainValues.Add(CellConstant.Undefined);
                    } 
 
                    AddToDomainMap(memberPath, domainValues);
                } 
            }

            // Fill up the domains for the remaining slots as well
            m_nonConditionDomainMap = new Dictionary(MemberPath.EqualityComparer); 
            foreach (Cell cell in extentCells) {
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget); 
                // Get the atoms from cellQuery and only keep the ones that 
                // are condition members
                foreach (JoinTreeSlot slot in cellQuery.GetAllQuerySlots()) { 
                    MemberPath member = slot.MemberPath;
                    if (m_domainMap.ContainsKey(member) == false && m_nonConditionDomainMap.ContainsKey(member) == false) {
                        CellConstantSet memberSet = CellConstantDomain.CreateDomainSetFromMemberPath(member, m_workspace);
                        if (member.IsAlwaysDefined(inheritanceGraph) == false) 
                        { // nonConditionMember may belong to subclass
                            memberSet.Add(CellConstant.Undefined); 
                        } 
                        memberSet = CellConstantDomain.NormalizeDomain(memberSet, memberSet);
                        m_nonConditionDomainMap.Add(member, new CellConstantSetInfo(memberSet, slot)); 
                    }
                }
            }
        } 

        #endregion 
 
        #region Fields
        // Keep track of the actual domain for each member on which we have conditions 
        private Dictionary m_domainMap;
        // Keep track of the actual domain for each member on which we have no conditions
        // CellConstantSet in m_nonConditionDomainMap is really CellConstantSetInfo
        private Dictionary m_nonConditionDomainMap; 
        // Keep track of the different constant values a member could take
        // (but does not necessarily take), e.g., 3, 4 in this map but its 
        // domain could be just 3 
        //private Dictionary m_mergedDomainMap;
        private MetadataWorkspace m_workspace; 
        // members on C-side that are projected, don't have conditions, but the respective S-side members do
        // we need to threat those just as regular members except in validation, where S-side conditions are
        // projected to C-side. For that, KB needs to add the respective constraints involving this members
        // For example: CPerson1.Phone IN {?, NOT(?, NULL)) on C-side. We need to know that 
        // type(CPerson1)=Customer <-> !(CPerson1.Phone IN {?}) for validation of domain constraints
        private Set m_projectedConditionMembers = new Set(); 
 
        // struct to keep track of the constant set for a particular slot
        private class CellConstantSetInfo : CellConstantSet { 
            internal CellConstantSetInfo(Set iconstants, JoinTreeSlot islot) : base(iconstants) {
                slot = islot;
            }
 
            internal JoinTreeSlot slot;
 
            public override string ToString() { 
                return base.ToString();
            } 
        }
        #endregion

        #region Properties 
        internal bool IsProjectedConditionMember(MemberPath memberPath)
        { 
            return m_projectedConditionMembers.Contains(memberPath); 
        }
 
        #endregion

        #region Methods
        // effects: Returns an "open-world" domain, i.e., 
        // one in which not-null constants are used to represent some other value from the domain
        internal MemberDomainMap GetOpenDomain() 
        { 
            var domainMap = m_domainMap.ToDictionary(p => p.Key, p => new Set(p.Value, CellConstant.EqualityComparer));
            AddNegatedConstantsIfNeeded(domainMap); 
            return new MemberDomainMap(domainMap, m_nonConditionDomainMap, m_workspace);
        }

        // effects: Creates a deep copy of MemberDomainMap 
        // nonConditionDomainMap is read-only so it is reused without cloning
        internal MemberDomainMap MakeCopy() 
        { 
            var domainMap = m_domainMap.ToDictionary(p => p.Key, p => new Set(p.Value, CellConstant.EqualityComparer));
            return new MemberDomainMap(domainMap, m_nonConditionDomainMap, m_workspace); 
        }

        // effects: Adds negated constants to the possible set of values if none exists in that set.
        // Needed so that we can handle cases when discriminator in the store as P, C but could have other values 
        // as well.
        internal void AddNegatedConstantsToPossibleValues() { 
            AddNegatedConstantsIfNeeded(m_domainMap); 
        }
 
        private static void AddNegatedConstantsIfNeeded(Dictionary domainMapForMembers) {
            // For the S-side, we always says that NOT(...) is
            // present. For example, if we are told "C", "P", we assume
            // that NOT(C, P) is possibly present in that column 
            foreach (MemberPath path in domainMapForMembers.Keys)
            { 
                CellConstantSet possibleValues = domainMapForMembers[path]; 
                if (MetadataHelper.HasDiscreteDomain(path.EdmType) == false &&
                    path.IsScalarType() && 
                    possibleValues.Any(c => c is NegatedCellConstant) == false)
                {
                    NegatedCellConstant negatedConstant = new NegatedCellConstant(possibleValues);
                    possibleValues.Add(negatedConstant); 
                }
            } 
        } 

        // effects: Shrinks the domain of members whose types can be 
        // enumerated, e.g., booleans and enumerated types. For example,
        // NOT(False, True, Null) for a boolean domain should be removed
        internal void FixEnumerableDomains(ConfigViewGenerator config) {
            // Go through the two maps 

            FixEnumerableDomainsInMap(m_domainMap, config, m_workspace); 
            FixEnumerableDomainsInMap(m_nonConditionDomainMap, config, m_workspace); 
        }
 
        // effects: Fixes the domains of variables in this as specified in FixEnumerableDomains
        private static void FixEnumerableDomainsInMap(Dictionary domainMap, ConfigViewGenerator config,
                                                      MetadataWorkspace workspace) {
            foreach (MemberPath member in domainMap.Keys) { 
                if (MetadataHelper.HasDiscreteDomain(member.EdmType) == false) {
                    continue; 
                } 
                CellConstantSet domain = CellConstantDomain.CreateDomainSetFromMemberPath(member, workspace);
                CellConstantSet extra = domainMap[member].Difference(domain); 
                extra.Remove(CellConstant.Undefined);
                if (extra.Count > 0)
                { // domainMap has extra members -- we should get rid of them
                    if (config.IsNormalTracing) { 
                        Helpers.FormatTraceLine("Changed domain of {0} from {1} - subtract {2}", member, domainMap[member], extra);
                    } 
                    domainMap[member].Subtract(extra); 
                }
            } 
        }

        // requires: this domainMap has been created for the C-side
        // effects: Fixes the mergedDomain map in this by merging entries 
        // available in updateDomainMap
        internal void FixQueryDomainMap(IEnumerable cells, MemberDomainMap updateDomainMap) { 
 
            foreach (Cell cell in cells) {
                CellQuery cQuery = cell.CQuery; 
                CellQuery sQuery = cell.SQuery;
                for (int i = 0; i < cQuery.NumProjectedSlots; i++) {
                    JoinTreeSlot cSlot = cQuery.ProjectedSlotAt(i) as JoinTreeSlot;
                    JoinTreeSlot sSlot = sQuery.ProjectedSlotAt(i) as JoinTreeSlot; 
                    if (cSlot == null || sSlot == null) {
                        continue; 
                    } 
                    // Get the domain for sSlot and merge with cSlot's
                    MemberPath cPath = cSlot.MemberPath; 
                    MemberPath sPath = sSlot.MemberPath;
                    CellConstantSet cSet = GetDomainInternal(cPath);
                    CellConstantSet sSet = updateDomainMap.GetDomainInternal(sPath);
                    // skip NULL because if c-side member is nullable, it's already there, and otherwise can't be taken 
                    // skip negated because negated values are translated in a special way
                    cSet.Unite(sSet.Where(constant => !constant.IsNull() && !(constant is NegatedCellConstant))); 
                    if (updateDomainMap.IsConditionMember(sPath) && !IsConditionMember(cPath)) 
                    {
                        // record this member so KB knows we have to generate constraints for it 
                        m_projectedConditionMembers.Add(cPath);
                    }
                }
            } 
            // Normalize the domains in m_domainMap
            List keys = new List(m_domainMap.Keys); 
            foreach (MemberPath path in keys) { 
                CellConstantSet domain = m_domainMap[path];
                m_domainMap[path] = CellConstantDomain.NormalizeDomain(domain, domain); 
            }

            // Normalize the domains in m_nonConditionDomainMap as well
            keys = new List(m_nonConditionDomainMap.Keys); 
            foreach (MemberPath path in keys) {
                CellConstantSetInfo domain = (CellConstantSetInfo) m_nonConditionDomainMap[path]; 
                CellConstantSet normalizedDomain = CellConstantDomain.NormalizeDomain(domain, domain); 
                CellConstantSetInfo existingInfo = (CellConstantSetInfo)m_nonConditionDomainMap[path];
                m_nonConditionDomainMap[path] = new CellConstantSetInfo(normalizedDomain, existingInfo.slot); 
            }
        }

        internal bool IsConditionMember(MemberPath path) 
        {
            return m_domainMap.ContainsKey(path); 
        } 

        internal IEnumerable ConditionMembers(EntitySetBase extent) 
        {
            foreach (MemberPath path in m_domainMap.Keys)
            {
                if (path.Extent.Equals(extent)) 
                {
                    yield return path; 
                } 
            }
        } 


        internal IEnumerable NonConditionMembers(EntitySetBase extent)
        { 
            foreach (MemberPath path in m_nonConditionDomainMap.Keys)
            { 
                if (path.Extent.Equals(extent)) 
                {
                    yield return path; 
                }
            }
        }
 

        ///  
        /// Adds AllOtherConstants element to the domain set given by MemberPath 
        /// 
        internal void AddSentinel(MemberPath path) 
        {
            CellConstantSet set = GetDomainInternal(path);
            set.Add(CellConstant.AllOtherConstants);
        } 

        ///  
        /// Removes AllOtherConstant element from the domain set given by MemberPath 
        /// 
        internal void RemoveSentinel(MemberPath path) 
        {
            CellConstantSet set = GetDomainInternal(path);
            set.Remove(CellConstant.AllOtherConstants);
        } 

        // requires member exist in this 
        // effects: Returns the possible values/domain for that member 
        internal IEnumerable GetDomain(MemberPath path) {
            return GetDomainInternal(path); 
        }

        private CellConstantSet GetDomainInternal(MemberPath path) {
            CellConstantSet result; 
            bool found = m_domainMap.TryGetValue(path, out result);
            if (!found) { 
                result = m_nonConditionDomainMap[path];  // It better be in this one! 
            }
            return result; 
        }

        // keeps the same set identity for the updated cell constant domain
        internal void UpdateConditionMemberDomain(MemberPath path, IEnumerable domainValues) 
        {
            // update domainMap 
            Set oldDomain = m_domainMap[path]; 
            oldDomain.Clear();
            oldDomain.Unite(domainValues); 
        }

        // effects: For member, adds domainValues as the set of values that
        // member can take. Merges them with any existing values if present 
        private void AddToDomainMap(MemberPath member, IEnumerable domainValues) {
            CellConstantSet possibleValues; 
            if (false == m_domainMap.TryGetValue(member, out possibleValues)) { 
                possibleValues = new CellConstantSet(CellConstant.EqualityComparer);
            } 
            possibleValues.Unite(domainValues);
            // Add the normalized domain to the map so that later uses of the
            // domain are consistent
            m_domainMap[member] = CellConstantDomain.NormalizeDomain(possibleValues, possibleValues); 
        }
 
        internal override void ToCompactString(StringBuilder builder) { 
            foreach (MemberPath memberPath in m_domainMap.Keys) {
                builder.Append('('); 
                memberPath.ToCompactString(builder);
                IEnumerable domain = GetDomain(memberPath);
                builder.Append(": ");
                StringUtil.ToCommaSeparatedStringSorted(builder, domain); 
                builder.Append(") ");
            } 
        } 
        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.Data.Common.Utils; 
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Data.Mapping.ViewGeneration.Utils; 
using System.Data.Metadata.Edm;
using System.Linq; 
 
namespace System.Data.Mapping.ViewGeneration.Structures {
 
    using CellConstantSet = Set;

    // This class keeps track of the domain values of the different members
    // in a schema. E.g., for a discriminator, it keeps track of "P", 
    // "C"; for type of Person, it keeps track of Person, Customer, etc
    // It exposes two concepts -- the domain of a member variable and the 
    // different possible values for that member, e.g., the possible values 
    // could be 3, 4, 5 but the domain could be 3, 4 (domain is always a
    // subset of possibleVales 
    internal class MemberDomainMap : InternalBase {

        #region Constructor
        private MemberDomainMap(Dictionary domainMap, 
                                Dictionary nonConditionDomainMap,
                                MetadataWorkspace workspace) 
        { 
            m_domainMap = domainMap;
            m_workspace = workspace; 
            m_nonConditionDomainMap = nonConditionDomainMap;
        }
        // effects: Creates a map with all the condition member constants
        // from extentCells. viewtarget determines whether the view is an 
        // update or query view
        internal MemberDomainMap(ViewTarget viewTarget, IEnumerable extentCells, MetadataWorkspace workspace, ConfigViewGenerator config, Dictionary> inheritanceGraph) 
        { 
            m_domainMap = new Dictionary(MemberPath.EqualityComparer);
            m_workspace = workspace; 

            Dictionary domainMap = null;
            if (viewTarget == ViewTarget.UpdateView) {
                domainMap = CellConstantDomain.ComputeConstantDomainSetsForSlotsInUpdateViews(extentCells, workspace); 
            } else {
                domainMap = CellConstantDomain.ComputeConstantDomainSetsForSlotsInQueryViews(extentCells, workspace); 
            } 

            foreach (Cell cell in extentCells) { 
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget);
                // Get the atoms from cellQuery and only keep the ones that
                // are condition members
                foreach (OneOfConst condition in cellQuery.GetConjunctsFromWhereClause()) { 
                    // Note: TypeConditions are created using OneOfTypeConst and
                    // scalars are created using OneOfScalarConst 
                    MemberPath memberPath = condition.Slot.MemberPath; 
                    if (m_domainMap.ContainsKey(memberPath)) {
                        continue; 
                    }
                    Debug.Assert(condition is OneOfScalarConst || condition is OneOfTypeConst,
                                 "Unexpected OneOfConst");
 
                    // Take the narrowed domain from domainMap, if any
                    CellConstantSet domainValues; 
                    if (!domainMap.TryGetValue(memberPath, out domainValues)) { 
                        domainValues = CellConstantDomain.CreateDomainSetFromMemberPath(memberPath, m_workspace);
                    } 

                    //Don't count conditions that are satisfied through IsNull=false
                    if (!domainValues.Contains(CellConstant.NotNull))
                    { 
                        //multiple values of condition represent disjunction in conditions (not currently supported)
                        // if there is any condition constant that is NotNull 
                        if(condition.Values.Values.All(conditionConstant => (conditionConstant.Equals(CellConstant.NotNull)) )) 
                        {
                            continue; 
                        }
                        //else there is atleast one condition value that is allowed, continue view generation
                    }
 
                    //IsNull condition on a member that is non nullable is an invalid condition
                    if (domainValues.Count <= 0 || (!domainValues.Contains(CellConstant.Null) && condition.Values.Values.Contains(CellConstant.Null))) 
                    { 
                        string message = System.Data.Entity.Strings.ViewGen_InvalidCondition_0(memberPath.PathToString(false));
                        ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.InvalidCondition, message, cell, String.Empty); 
                        ExceptionHelpers.ThrowMappingException(record, config);
                    }
                    if (memberPath.IsAlwaysDefined(inheritanceGraph) == false)
                    { 
                        domainValues.Add(CellConstant.Undefined);
                    } 
 
                    AddToDomainMap(memberPath, domainValues);
                } 
            }

            // Fill up the domains for the remaining slots as well
            m_nonConditionDomainMap = new Dictionary(MemberPath.EqualityComparer); 
            foreach (Cell cell in extentCells) {
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget); 
                // Get the atoms from cellQuery and only keep the ones that 
                // are condition members
                foreach (JoinTreeSlot slot in cellQuery.GetAllQuerySlots()) { 
                    MemberPath member = slot.MemberPath;
                    if (m_domainMap.ContainsKey(member) == false && m_nonConditionDomainMap.ContainsKey(member) == false) {
                        CellConstantSet memberSet = CellConstantDomain.CreateDomainSetFromMemberPath(member, m_workspace);
                        if (member.IsAlwaysDefined(inheritanceGraph) == false) 
                        { // nonConditionMember may belong to subclass
                            memberSet.Add(CellConstant.Undefined); 
                        } 
                        memberSet = CellConstantDomain.NormalizeDomain(memberSet, memberSet);
                        m_nonConditionDomainMap.Add(member, new CellConstantSetInfo(memberSet, slot)); 
                    }
                }
            }
        } 

        #endregion 
 
        #region Fields
        // Keep track of the actual domain for each member on which we have conditions 
        private Dictionary m_domainMap;
        // Keep track of the actual domain for each member on which we have no conditions
        // CellConstantSet in m_nonConditionDomainMap is really CellConstantSetInfo
        private Dictionary m_nonConditionDomainMap; 
        // Keep track of the different constant values a member could take
        // (but does not necessarily take), e.g., 3, 4 in this map but its 
        // domain could be just 3 
        //private Dictionary m_mergedDomainMap;
        private MetadataWorkspace m_workspace; 
        // members on C-side that are projected, don't have conditions, but the respective S-side members do
        // we need to threat those just as regular members except in validation, where S-side conditions are
        // projected to C-side. For that, KB needs to add the respective constraints involving this members
        // For example: CPerson1.Phone IN {?, NOT(?, NULL)) on C-side. We need to know that 
        // type(CPerson1)=Customer <-> !(CPerson1.Phone IN {?}) for validation of domain constraints
        private Set m_projectedConditionMembers = new Set(); 
 
        // struct to keep track of the constant set for a particular slot
        private class CellConstantSetInfo : CellConstantSet { 
            internal CellConstantSetInfo(Set iconstants, JoinTreeSlot islot) : base(iconstants) {
                slot = islot;
            }
 
            internal JoinTreeSlot slot;
 
            public override string ToString() { 
                return base.ToString();
            } 
        }
        #endregion

        #region Properties 
        internal bool IsProjectedConditionMember(MemberPath memberPath)
        { 
            return m_projectedConditionMembers.Contains(memberPath); 
        }
 
        #endregion

        #region Methods
        // effects: Returns an "open-world" domain, i.e., 
        // one in which not-null constants are used to represent some other value from the domain
        internal MemberDomainMap GetOpenDomain() 
        { 
            var domainMap = m_domainMap.ToDictionary(p => p.Key, p => new Set(p.Value, CellConstant.EqualityComparer));
            AddNegatedConstantsIfNeeded(domainMap); 
            return new MemberDomainMap(domainMap, m_nonConditionDomainMap, m_workspace);
        }

        // effects: Creates a deep copy of MemberDomainMap 
        // nonConditionDomainMap is read-only so it is reused without cloning
        internal MemberDomainMap MakeCopy() 
        { 
            var domainMap = m_domainMap.ToDictionary(p => p.Key, p => new Set(p.Value, CellConstant.EqualityComparer));
            return new MemberDomainMap(domainMap, m_nonConditionDomainMap, m_workspace); 
        }

        // effects: Adds negated constants to the possible set of values if none exists in that set.
        // Needed so that we can handle cases when discriminator in the store as P, C but could have other values 
        // as well.
        internal void AddNegatedConstantsToPossibleValues() { 
            AddNegatedConstantsIfNeeded(m_domainMap); 
        }
 
        private static void AddNegatedConstantsIfNeeded(Dictionary domainMapForMembers) {
            // For the S-side, we always says that NOT(...) is
            // present. For example, if we are told "C", "P", we assume
            // that NOT(C, P) is possibly present in that column 
            foreach (MemberPath path in domainMapForMembers.Keys)
            { 
                CellConstantSet possibleValues = domainMapForMembers[path]; 
                if (MetadataHelper.HasDiscreteDomain(path.EdmType) == false &&
                    path.IsScalarType() && 
                    possibleValues.Any(c => c is NegatedCellConstant) == false)
                {
                    NegatedCellConstant negatedConstant = new NegatedCellConstant(possibleValues);
                    possibleValues.Add(negatedConstant); 
                }
            } 
        } 

        // effects: Shrinks the domain of members whose types can be 
        // enumerated, e.g., booleans and enumerated types. For example,
        // NOT(False, True, Null) for a boolean domain should be removed
        internal void FixEnumerableDomains(ConfigViewGenerator config) {
            // Go through the two maps 

            FixEnumerableDomainsInMap(m_domainMap, config, m_workspace); 
            FixEnumerableDomainsInMap(m_nonConditionDomainMap, config, m_workspace); 
        }
 
        // effects: Fixes the domains of variables in this as specified in FixEnumerableDomains
        private static void FixEnumerableDomainsInMap(Dictionary domainMap, ConfigViewGenerator config,
                                                      MetadataWorkspace workspace) {
            foreach (MemberPath member in domainMap.Keys) { 
                if (MetadataHelper.HasDiscreteDomain(member.EdmType) == false) {
                    continue; 
                } 
                CellConstantSet domain = CellConstantDomain.CreateDomainSetFromMemberPath(member, workspace);
                CellConstantSet extra = domainMap[member].Difference(domain); 
                extra.Remove(CellConstant.Undefined);
                if (extra.Count > 0)
                { // domainMap has extra members -- we should get rid of them
                    if (config.IsNormalTracing) { 
                        Helpers.FormatTraceLine("Changed domain of {0} from {1} - subtract {2}", member, domainMap[member], extra);
                    } 
                    domainMap[member].Subtract(extra); 
                }
            } 
        }

        // requires: this domainMap has been created for the C-side
        // effects: Fixes the mergedDomain map in this by merging entries 
        // available in updateDomainMap
        internal void FixQueryDomainMap(IEnumerable cells, MemberDomainMap updateDomainMap) { 
 
            foreach (Cell cell in cells) {
                CellQuery cQuery = cell.CQuery; 
                CellQuery sQuery = cell.SQuery;
                for (int i = 0; i < cQuery.NumProjectedSlots; i++) {
                    JoinTreeSlot cSlot = cQuery.ProjectedSlotAt(i) as JoinTreeSlot;
                    JoinTreeSlot sSlot = sQuery.ProjectedSlotAt(i) as JoinTreeSlot; 
                    if (cSlot == null || sSlot == null) {
                        continue; 
                    } 
                    // Get the domain for sSlot and merge with cSlot's
                    MemberPath cPath = cSlot.MemberPath; 
                    MemberPath sPath = sSlot.MemberPath;
                    CellConstantSet cSet = GetDomainInternal(cPath);
                    CellConstantSet sSet = updateDomainMap.GetDomainInternal(sPath);
                    // skip NULL because if c-side member is nullable, it's already there, and otherwise can't be taken 
                    // skip negated because negated values are translated in a special way
                    cSet.Unite(sSet.Where(constant => !constant.IsNull() && !(constant is NegatedCellConstant))); 
                    if (updateDomainMap.IsConditionMember(sPath) && !IsConditionMember(cPath)) 
                    {
                        // record this member so KB knows we have to generate constraints for it 
                        m_projectedConditionMembers.Add(cPath);
                    }
                }
            } 
            // Normalize the domains in m_domainMap
            List keys = new List(m_domainMap.Keys); 
            foreach (MemberPath path in keys) { 
                CellConstantSet domain = m_domainMap[path];
                m_domainMap[path] = CellConstantDomain.NormalizeDomain(domain, domain); 
            }

            // Normalize the domains in m_nonConditionDomainMap as well
            keys = new List(m_nonConditionDomainMap.Keys); 
            foreach (MemberPath path in keys) {
                CellConstantSetInfo domain = (CellConstantSetInfo) m_nonConditionDomainMap[path]; 
                CellConstantSet normalizedDomain = CellConstantDomain.NormalizeDomain(domain, domain); 
                CellConstantSetInfo existingInfo = (CellConstantSetInfo)m_nonConditionDomainMap[path];
                m_nonConditionDomainMap[path] = new CellConstantSetInfo(normalizedDomain, existingInfo.slot); 
            }
        }

        internal bool IsConditionMember(MemberPath path) 
        {
            return m_domainMap.ContainsKey(path); 
        } 

        internal IEnumerable ConditionMembers(EntitySetBase extent) 
        {
            foreach (MemberPath path in m_domainMap.Keys)
            {
                if (path.Extent.Equals(extent)) 
                {
                    yield return path; 
                } 
            }
        } 


        internal IEnumerable NonConditionMembers(EntitySetBase extent)
        { 
            foreach (MemberPath path in m_nonConditionDomainMap.Keys)
            { 
                if (path.Extent.Equals(extent)) 
                {
                    yield return path; 
                }
            }
        }
 

        ///  
        /// Adds AllOtherConstants element to the domain set given by MemberPath 
        /// 
        internal void AddSentinel(MemberPath path) 
        {
            CellConstantSet set = GetDomainInternal(path);
            set.Add(CellConstant.AllOtherConstants);
        } 

        ///  
        /// Removes AllOtherConstant element from the domain set given by MemberPath 
        /// 
        internal void RemoveSentinel(MemberPath path) 
        {
            CellConstantSet set = GetDomainInternal(path);
            set.Remove(CellConstant.AllOtherConstants);
        } 

        // requires member exist in this 
        // effects: Returns the possible values/domain for that member 
        internal IEnumerable GetDomain(MemberPath path) {
            return GetDomainInternal(path); 
        }

        private CellConstantSet GetDomainInternal(MemberPath path) {
            CellConstantSet result; 
            bool found = m_domainMap.TryGetValue(path, out result);
            if (!found) { 
                result = m_nonConditionDomainMap[path];  // It better be in this one! 
            }
            return result; 
        }

        // keeps the same set identity for the updated cell constant domain
        internal void UpdateConditionMemberDomain(MemberPath path, IEnumerable domainValues) 
        {
            // update domainMap 
            Set oldDomain = m_domainMap[path]; 
            oldDomain.Clear();
            oldDomain.Unite(domainValues); 
        }

        // effects: For member, adds domainValues as the set of values that
        // member can take. Merges them with any existing values if present 
        private void AddToDomainMap(MemberPath member, IEnumerable domainValues) {
            CellConstantSet possibleValues; 
            if (false == m_domainMap.TryGetValue(member, out possibleValues)) { 
                possibleValues = new CellConstantSet(CellConstant.EqualityComparer);
            } 
            possibleValues.Unite(domainValues);
            // Add the normalized domain to the map so that later uses of the
            // domain are consistent
            m_domainMap[member] = CellConstantDomain.NormalizeDomain(possibleValues, possibleValues); 
        }
 
        internal override void ToCompactString(StringBuilder builder) { 
            foreach (MemberPath memberPath in m_domainMap.Keys) {
                builder.Append('('); 
                memberPath.ToCompactString(builder);
                IEnumerable domain = GetDomain(memberPath);
                builder.Append(": ");
                StringUtil.ToCommaSeparatedStringSorted(builder, domain); 
                builder.Append(") ");
            } 
        } 
        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK