LeftCellWrapper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / LeftCellWrapper.cs / 2 / LeftCellWrapper.cs

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

using System.Collections.Generic; 
using System.Data.Common.Utils;
using System.Text;
using System.Linq;
using System.Diagnostics; 
using System.Collections.ObjectModel;
using System.Data.Metadata.Edm; 
using System.Data.Common.Utils.Boolean; 
using System.Data.Mapping.ViewGeneration.Validation;
using System.Data.Mapping.ViewGeneration.QueryRewriting; 

namespace System.Data.Mapping.ViewGeneration.Structures {

    // This class essentially stores a cell but in a special form. When we 
    // are generating a view for an extent, we denote the extent's side (C or
    // S) as the "left side" and the side being used in the view as the right 
    // side. For example, in query views, the C side is the left side. 
    //
    // Each LeftCellWrapper is a cell of the form: 
    // Project[A1,...,An] (Select[var IN {domain}] (Extent)) = Expr
    // Where
    // - "domain" is a set of multiconstants that correspond to the different
    //   variable values allowed for the cell query 
    // - A1 ... An are denoted by Attributes in this and corresponds to
    //   the list of attributes that are projected 
    // - Extent is the extent for which th view is being generated 
    // - Expr is the expression on the other side to produce the left side of
    //   the cell 
    internal class LeftCellWrapper : InternalBase {

        #region Constructor
        // effects: Creates a LeftCellWrapper of the form: 
        // Project[attrs] (Select[var IN {domain}] (Extent)) = cellquery
        // memberMaps is the set of maps used for producing the query or update views 
        internal LeftCellWrapper(SchemaContext schemaContext, Set attrs, 
                                 FragmentQuery fragmentQuery,
                                 CellQuery cellQuery, MemberMaps memberMaps, IEnumerable inputCells) 
        {
            m_fragmentQuery = fragmentQuery;
            m_rightCellQuery = cellQuery;
            m_attributes = attrs; 
            m_schemaContext = schemaContext;
            m_memberMaps = memberMaps; 
            m_cells = new HashSet(inputCells); 
        }
 
        internal LeftCellWrapper(SchemaContext schemaContext, Set attrs,
                                 FragmentQuery fragmentQuery,
                                 CellQuery cellQuery, MemberMaps memberMaps, Cell inputCell)
            : this(schemaContext, attrs, fragmentQuery, cellQuery, memberMaps, new Cell[] { inputCell }) { } 

        #endregion 
 
        #region Fields
        internal static readonly IEqualityComparer BoolEqualityComparer = new BoolWrapperComparer(); 
        private Set m_attributes;// project: attributes computed by
        // Expr (projected attributes that get set)
        private MemberMaps m_memberMaps;
        private CellQuery m_rightCellQuery; // expression that computes this portion 
        private HashSet m_cells;
        private SchemaContext m_schemaContext; 
        private FragmentQuery m_fragmentQuery; // fragment query corresponding to the left cell query of the cell 

        internal static readonly IComparer Comparer = new LeftCellWrapperComparer(); 
        internal static readonly IComparer OriginalCellIdComparer = new CellIdComparer();
        #endregion

        #region Properties 

        internal FragmentQuery FragmentQuery 
        { 
            get { return m_fragmentQuery; }
        } 

        internal SchemaContext SchemaContext {
            get { return m_schemaContext;}
        } 

        // effects: Returns the projected fields on the left side 
        internal Set Attributes { 
            get { return m_attributes; }
        } 

        // effects: Returns the original cell number from which the wrapper came
        internal string OriginalCellNumberString {
            get { 
                return StringUtil.ToSeparatedString(m_cells.Select(cell => cell.CellNumberAsString), "+", "");
            } 
        } 

        // effects: Returns the right domain map associated with the right query 
        internal MemberDomainMap RightDomainMap {
            get { return m_memberMaps.RightDomainMap; }
        }
 
        [Conditional("DEBUG")]
        internal void AssertHasUniqueCell() { 
            Debug.Assert(m_cells.Count == 1); 
        }
 
        internal IEnumerable Cells
        {
            get { return m_cells; }
        } 

        // requires: There is only one input cell in this 
        // effects: Returns the  input cell provided to view generation as part of the mapping 
        internal Cell OnlyInputCell {
            get { 
                AssertHasUniqueCell();
                return m_cells.First();
            }
        } 

        // effects: Returns the right CellQuery 
        internal CellQuery RightCellQuery { 
            get { return m_rightCellQuery; }
        } 

        // effects: Returns the extent for which the wrapper was built
        internal EntitySetBase LeftExtent {
            get { 
                return m_cells.First().GetLeftQuery(m_schemaContext.ViewTarget).Extent;
            } 
        } 

        // effects: Returns the extent of the right cellquery 
        internal EntitySetBase RightExtent {
            get {
                EntitySetBase result = m_rightCellQuery.Extent;
                Debug.Assert(result != null, "Bad root value in join tree"); 
                return result;
            } 
        } 
        #endregion
 
        #region Methods

        // effects: Yields the input cells in wrappers
        internal static IEnumerable GetInputCellsForWrappers(IEnumerable wrappers) { 
            foreach (LeftCellWrapper wrapper in wrappers) {
                foreach (Cell cell in wrapper.m_cells) 
                { 
                    yield return cell;
                } 
            }
        }

        // requires: RightCellQuery.Extent corresponds to a relationship set 
        // effects: Returns the ends to which the key of the corresponding
        // table (i.e., the left query) maps to in the relationship set. For 
        // example, if RightCellQuery.Extent is OrderOrders and it maps to 
        //  of table SOrders with key oid, this returns the
        // end to which oid is mapped. Similarly, if we have a link table 
        // with the whole key mapped to two ends of the association set, it
        // returns both ends
        private Set GetEndsForTablePrimaryKey() {
            CellQuery rightQuery = RightCellQuery; 
            Set result = new Set(EqualityComparer.Default);
            // Get the key slots for the table (they are in the slotMap) and 
            // check for that slot on the C-side 
            foreach (int keySlot in m_memberMaps.ProjectedSlotMap.KeySlots) {
                JoinTreeSlot slot = (JoinTreeSlot)rightQuery.ProjectedSlotAt(keySlot); 
                MemberPath path = slot.MemberPath;
                // See what end it maps to in the relationSet
                AssociationEndMember endMember = (AssociationEndMember)path.FirstMember;
                Debug.Assert(endMember != null, "Element in path before scalar path is not end property?"); 
                result.Add(endMember);
            } 
            Debug.Assert(result != null, "No end found for keyslots of table?"); 
            return result;
        } 

        // effects: Creates a boolean variable representing the right extent or association end
        internal RoleBoolean CreateRoleBoolean()
        { 
            if (RightExtent is AssociationSet)
            { 
                Set ends = GetEndsForTablePrimaryKey(); 
                if (ends.Count == 1)
                { 
                    AssociationSetEnd setEnd = ((AssociationSet)RightExtent).AssociationSetEnds[ends.First().Name];
                    return new RoleBoolean(setEnd);
                }
            } 
            return new RoleBoolean(RightExtent);
        } 
 
        // effects: Given a set of wrappers, returns a string that contains the list of extents in the
        // rightcellQueries of the wrappers 
        internal static string GetExtentListAsUserString(IEnumerable wrappers) {
            Set extents = new Set(EqualityComparer.Default);
            foreach (LeftCellWrapper wrapper in wrappers) {
                extents.Add(wrapper.RightExtent); 
            }
 
            StringBuilder builder = new StringBuilder(); 
            bool isFirst = true;
            foreach (EntitySetBase extent in extents) { 
                if (isFirst == false) {
                    builder.Append(", ");
                }
                isFirst = false; 
                builder.Append(extent.Name);
            } 
            return builder.ToString(); 
        }
 
        internal override void ToFullString(StringBuilder builder) {
            builder.Append("P[");
            StringUtil.ToSeparatedString(builder, m_attributes, ",");
            builder.Append("] = "); 
            m_rightCellQuery.ToFullString(builder);
        } 
 
        // effects: Modifies stringBuilder to contain the view corresponding
        // to the right cellquery 
        internal override void ToCompactString(StringBuilder stringBuilder) {
            stringBuilder.Append(OriginalCellNumberString);
        }
 
        // effects: Writes m_cellWrappers to builder
        internal static void WrappersToStringBuilder(StringBuilder builder, List wrappers, 
                                                     string header) { 
            builder.AppendLine()
                   .Append(header) 
                   .AppendLine();
            // Sort them according to the original cell number
            LeftCellWrapper[] cellWrappers = wrappers.ToArray();
            Array.Sort(cellWrappers, LeftCellWrapper.OriginalCellIdComparer); 

            foreach (LeftCellWrapper wrapper in cellWrappers) { 
                wrapper.ToCompactString(builder); 
                builder.Append(" = ");
                wrapper.ToFullString(builder); 
                builder.AppendLine();
            }
        }
        #endregion 

        #region Equality Comparer class 
        // This class compares wrappers based on the Right Where Clause and 
        // Extent -- needed for the boolean engine
        private class BoolWrapperComparer : IEqualityComparer { 

            public bool Equals(LeftCellWrapper left, LeftCellWrapper right) {
                // Quick check with references
                if (object.ReferenceEquals(left, right)) { 
                    // Gets the Null and Undefined case as well
                    return true; 
                } 
                // One of them is non-null at least
                if (left == null || right == null) { 
                    return false;
                }
                // Both are non-null at this point
                bool whereClauseEqual = BoolExpression.EqualityComparer.Equals(left.RightCellQuery.WhereClause, 
                                                                               right.RightCellQuery.WhereClause);
 
                return left.RightExtent.Equals(right.RightExtent) && whereClauseEqual; 
            }
 
            public int GetHashCode(LeftCellWrapper wrapper) {
                return BoolExpression.EqualityComparer.GetHashCode(wrapper.RightCellQuery.WhereClause) ^ wrapper.RightExtent.GetHashCode();
            }
        } 
        #endregion
 
        #region Comparer 
        // A class that compares two cell wrappers. Useful for guiding heuristics
        // and to ensure that the largest selection domain (i.e., the number of 
        // multiconstants in "mc in {...}") is first in the list
        private class LeftCellWrapperComparer : IComparer {

            public int Compare(LeftCellWrapper x, LeftCellWrapper y) { 

                // More attributes first -- so that we get most attributes 
                // with very few intersections (when we use the sortings for 
                // that). When we are subtracting, attributes are not important
 
                // Use FragmentQuery's attributes instead of LeftCellWrapper's original attributes in the comparison
                // since the former might have got extended to include all attributes whose value is determined
                // by the WHERE clause (e.g., if we have WHERE ProductName='Camera' we can assume ProductName is projected)
 
                if (x.FragmentQuery.Attributes.Count > y.FragmentQuery.Attributes.Count) {
                    return -1; 
                } else if (x.FragmentQuery.Attributes.Count < y.FragmentQuery.Attributes.Count) { 
                    return 1;
                } 
                // Since the sort may not be stable, we use the original cell number string to break the tie
                return String.CompareOrdinal(x.OriginalCellNumberString, y.OriginalCellNumberString);
            }
        } 

        // A class that compares two cell wrappers based on original cell number 
        internal class CellIdComparer : IComparer { 

            public int Compare(LeftCellWrapper x, LeftCellWrapper y) { 
                return StringComparer.Ordinal.Compare(x.OriginalCellNumberString, y.OriginalCellNumberString);
            }
        }
 
        #endregion
    } 
} 

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

using System.Collections.Generic; 
using System.Data.Common.Utils;
using System.Text;
using System.Linq;
using System.Diagnostics; 
using System.Collections.ObjectModel;
using System.Data.Metadata.Edm; 
using System.Data.Common.Utils.Boolean; 
using System.Data.Mapping.ViewGeneration.Validation;
using System.Data.Mapping.ViewGeneration.QueryRewriting; 

namespace System.Data.Mapping.ViewGeneration.Structures {

    // This class essentially stores a cell but in a special form. When we 
    // are generating a view for an extent, we denote the extent's side (C or
    // S) as the "left side" and the side being used in the view as the right 
    // side. For example, in query views, the C side is the left side. 
    //
    // Each LeftCellWrapper is a cell of the form: 
    // Project[A1,...,An] (Select[var IN {domain}] (Extent)) = Expr
    // Where
    // - "domain" is a set of multiconstants that correspond to the different
    //   variable values allowed for the cell query 
    // - A1 ... An are denoted by Attributes in this and corresponds to
    //   the list of attributes that are projected 
    // - Extent is the extent for which th view is being generated 
    // - Expr is the expression on the other side to produce the left side of
    //   the cell 
    internal class LeftCellWrapper : InternalBase {

        #region Constructor
        // effects: Creates a LeftCellWrapper of the form: 
        // Project[attrs] (Select[var IN {domain}] (Extent)) = cellquery
        // memberMaps is the set of maps used for producing the query or update views 
        internal LeftCellWrapper(SchemaContext schemaContext, Set attrs, 
                                 FragmentQuery fragmentQuery,
                                 CellQuery cellQuery, MemberMaps memberMaps, IEnumerable inputCells) 
        {
            m_fragmentQuery = fragmentQuery;
            m_rightCellQuery = cellQuery;
            m_attributes = attrs; 
            m_schemaContext = schemaContext;
            m_memberMaps = memberMaps; 
            m_cells = new HashSet(inputCells); 
        }
 
        internal LeftCellWrapper(SchemaContext schemaContext, Set attrs,
                                 FragmentQuery fragmentQuery,
                                 CellQuery cellQuery, MemberMaps memberMaps, Cell inputCell)
            : this(schemaContext, attrs, fragmentQuery, cellQuery, memberMaps, new Cell[] { inputCell }) { } 

        #endregion 
 
        #region Fields
        internal static readonly IEqualityComparer BoolEqualityComparer = new BoolWrapperComparer(); 
        private Set m_attributes;// project: attributes computed by
        // Expr (projected attributes that get set)
        private MemberMaps m_memberMaps;
        private CellQuery m_rightCellQuery; // expression that computes this portion 
        private HashSet m_cells;
        private SchemaContext m_schemaContext; 
        private FragmentQuery m_fragmentQuery; // fragment query corresponding to the left cell query of the cell 

        internal static readonly IComparer Comparer = new LeftCellWrapperComparer(); 
        internal static readonly IComparer OriginalCellIdComparer = new CellIdComparer();
        #endregion

        #region Properties 

        internal FragmentQuery FragmentQuery 
        { 
            get { return m_fragmentQuery; }
        } 

        internal SchemaContext SchemaContext {
            get { return m_schemaContext;}
        } 

        // effects: Returns the projected fields on the left side 
        internal Set Attributes { 
            get { return m_attributes; }
        } 

        // effects: Returns the original cell number from which the wrapper came
        internal string OriginalCellNumberString {
            get { 
                return StringUtil.ToSeparatedString(m_cells.Select(cell => cell.CellNumberAsString), "+", "");
            } 
        } 

        // effects: Returns the right domain map associated with the right query 
        internal MemberDomainMap RightDomainMap {
            get { return m_memberMaps.RightDomainMap; }
        }
 
        [Conditional("DEBUG")]
        internal void AssertHasUniqueCell() { 
            Debug.Assert(m_cells.Count == 1); 
        }
 
        internal IEnumerable Cells
        {
            get { return m_cells; }
        } 

        // requires: There is only one input cell in this 
        // effects: Returns the  input cell provided to view generation as part of the mapping 
        internal Cell OnlyInputCell {
            get { 
                AssertHasUniqueCell();
                return m_cells.First();
            }
        } 

        // effects: Returns the right CellQuery 
        internal CellQuery RightCellQuery { 
            get { return m_rightCellQuery; }
        } 

        // effects: Returns the extent for which the wrapper was built
        internal EntitySetBase LeftExtent {
            get { 
                return m_cells.First().GetLeftQuery(m_schemaContext.ViewTarget).Extent;
            } 
        } 

        // effects: Returns the extent of the right cellquery 
        internal EntitySetBase RightExtent {
            get {
                EntitySetBase result = m_rightCellQuery.Extent;
                Debug.Assert(result != null, "Bad root value in join tree"); 
                return result;
            } 
        } 
        #endregion
 
        #region Methods

        // effects: Yields the input cells in wrappers
        internal static IEnumerable GetInputCellsForWrappers(IEnumerable wrappers) { 
            foreach (LeftCellWrapper wrapper in wrappers) {
                foreach (Cell cell in wrapper.m_cells) 
                { 
                    yield return cell;
                } 
            }
        }

        // requires: RightCellQuery.Extent corresponds to a relationship set 
        // effects: Returns the ends to which the key of the corresponding
        // table (i.e., the left query) maps to in the relationship set. For 
        // example, if RightCellQuery.Extent is OrderOrders and it maps to 
        //  of table SOrders with key oid, this returns the
        // end to which oid is mapped. Similarly, if we have a link table 
        // with the whole key mapped to two ends of the association set, it
        // returns both ends
        private Set GetEndsForTablePrimaryKey() {
            CellQuery rightQuery = RightCellQuery; 
            Set result = new Set(EqualityComparer.Default);
            // Get the key slots for the table (they are in the slotMap) and 
            // check for that slot on the C-side 
            foreach (int keySlot in m_memberMaps.ProjectedSlotMap.KeySlots) {
                JoinTreeSlot slot = (JoinTreeSlot)rightQuery.ProjectedSlotAt(keySlot); 
                MemberPath path = slot.MemberPath;
                // See what end it maps to in the relationSet
                AssociationEndMember endMember = (AssociationEndMember)path.FirstMember;
                Debug.Assert(endMember != null, "Element in path before scalar path is not end property?"); 
                result.Add(endMember);
            } 
            Debug.Assert(result != null, "No end found for keyslots of table?"); 
            return result;
        } 

        // effects: Creates a boolean variable representing the right extent or association end
        internal RoleBoolean CreateRoleBoolean()
        { 
            if (RightExtent is AssociationSet)
            { 
                Set ends = GetEndsForTablePrimaryKey(); 
                if (ends.Count == 1)
                { 
                    AssociationSetEnd setEnd = ((AssociationSet)RightExtent).AssociationSetEnds[ends.First().Name];
                    return new RoleBoolean(setEnd);
                }
            } 
            return new RoleBoolean(RightExtent);
        } 
 
        // effects: Given a set of wrappers, returns a string that contains the list of extents in the
        // rightcellQueries of the wrappers 
        internal static string GetExtentListAsUserString(IEnumerable wrappers) {
            Set extents = new Set(EqualityComparer.Default);
            foreach (LeftCellWrapper wrapper in wrappers) {
                extents.Add(wrapper.RightExtent); 
            }
 
            StringBuilder builder = new StringBuilder(); 
            bool isFirst = true;
            foreach (EntitySetBase extent in extents) { 
                if (isFirst == false) {
                    builder.Append(", ");
                }
                isFirst = false; 
                builder.Append(extent.Name);
            } 
            return builder.ToString(); 
        }
 
        internal override void ToFullString(StringBuilder builder) {
            builder.Append("P[");
            StringUtil.ToSeparatedString(builder, m_attributes, ",");
            builder.Append("] = "); 
            m_rightCellQuery.ToFullString(builder);
        } 
 
        // effects: Modifies stringBuilder to contain the view corresponding
        // to the right cellquery 
        internal override void ToCompactString(StringBuilder stringBuilder) {
            stringBuilder.Append(OriginalCellNumberString);
        }
 
        // effects: Writes m_cellWrappers to builder
        internal static void WrappersToStringBuilder(StringBuilder builder, List wrappers, 
                                                     string header) { 
            builder.AppendLine()
                   .Append(header) 
                   .AppendLine();
            // Sort them according to the original cell number
            LeftCellWrapper[] cellWrappers = wrappers.ToArray();
            Array.Sort(cellWrappers, LeftCellWrapper.OriginalCellIdComparer); 

            foreach (LeftCellWrapper wrapper in cellWrappers) { 
                wrapper.ToCompactString(builder); 
                builder.Append(" = ");
                wrapper.ToFullString(builder); 
                builder.AppendLine();
            }
        }
        #endregion 

        #region Equality Comparer class 
        // This class compares wrappers based on the Right Where Clause and 
        // Extent -- needed for the boolean engine
        private class BoolWrapperComparer : IEqualityComparer { 

            public bool Equals(LeftCellWrapper left, LeftCellWrapper right) {
                // Quick check with references
                if (object.ReferenceEquals(left, right)) { 
                    // Gets the Null and Undefined case as well
                    return true; 
                } 
                // One of them is non-null at least
                if (left == null || right == null) { 
                    return false;
                }
                // Both are non-null at this point
                bool whereClauseEqual = BoolExpression.EqualityComparer.Equals(left.RightCellQuery.WhereClause, 
                                                                               right.RightCellQuery.WhereClause);
 
                return left.RightExtent.Equals(right.RightExtent) && whereClauseEqual; 
            }
 
            public int GetHashCode(LeftCellWrapper wrapper) {
                return BoolExpression.EqualityComparer.GetHashCode(wrapper.RightCellQuery.WhereClause) ^ wrapper.RightExtent.GetHashCode();
            }
        } 
        #endregion
 
        #region Comparer 
        // A class that compares two cell wrappers. Useful for guiding heuristics
        // and to ensure that the largest selection domain (i.e., the number of 
        // multiconstants in "mc in {...}") is first in the list
        private class LeftCellWrapperComparer : IComparer {

            public int Compare(LeftCellWrapper x, LeftCellWrapper y) { 

                // More attributes first -- so that we get most attributes 
                // with very few intersections (when we use the sortings for 
                // that). When we are subtracting, attributes are not important
 
                // Use FragmentQuery's attributes instead of LeftCellWrapper's original attributes in the comparison
                // since the former might have got extended to include all attributes whose value is determined
                // by the WHERE clause (e.g., if we have WHERE ProductName='Camera' we can assume ProductName is projected)
 
                if (x.FragmentQuery.Attributes.Count > y.FragmentQuery.Attributes.Count) {
                    return -1; 
                } else if (x.FragmentQuery.Attributes.Count < y.FragmentQuery.Attributes.Count) { 
                    return 1;
                } 
                // Since the sort may not be stable, we use the original cell number string to break the tie
                return String.CompareOrdinal(x.OriginalCellNumberString, y.OriginalCellNumberString);
            }
        } 

        // A class that compares two cell wrappers based on original cell number 
        internal class CellIdComparer : IComparer { 

            public int Compare(LeftCellWrapper x, LeftCellWrapper y) { 
                return StringComparer.Ordinal.Compare(x.OriginalCellNumberString, y.OriginalCellNumberString);
            }
        }
 
        #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