CellNormalizer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / CellNormalizer.cs / 1 / CellNormalizer.cs

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

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

namespace System.Data.Mapping.ViewGeneration { 

    using AttributeSet = Set; 
    using System.Data.Entity; 

    // This class is responsible for normalizing the cells for an extent so 
    // that view generation can occur on the normalized cells.
    // Main task: Converts an extent cells to normalized form with
    // multiconstants along the needed signatures
    // Output: A collection of LeftCellWrappers for the extent. Each wrapper has 
    // the attriutes, the "right" query, and a set of multiconstants X - these
    // multiconstants denote a where clause "variable in X". 
 
    internal class CellNormalizer : InternalBase {
 
        #region Constructors
        // effects: Given an extent and the cells
        // for that extent, creates a CellNormalizer object that is capable
        // of returning the normalized cells and the extent signatures when needed 
        internal CellNormalizer(EntitySetBase extent, IEnumerable extentCells, SchemaContext schemaContext,
                                CqlIdentifiers identifiers, 
                                ConfigViewGenerator config, MemberDomainMap queryDomainMap, 
                                MemberDomainMap updateDomainMap, StorageEntityContainerMapping entityContainerMapping,
                                MetadataWorkspace workspace) { 

            m_extent = extent;
            m_schemaContext = schemaContext;
            m_config = config; 
            m_workspace = workspace;
            m_entityContainerMapping = entityContainerMapping; 
            m_identifiers = identifiers; 

            // Check that the cells that we start out with are ok 
            ValidateCells(extent, extentCells, schemaContext.ViewTarget);

            // create a copy of updateDomainMap so generation of query views later on is not affected
            // it is modified in QueryRewriter.AdjustMemberDomainsForUpdateViews 
            updateDomainMap = updateDomainMap.MakeCopy();
 
            // Create a signature generator that handles all the 
            // multiconstant work and generating the signatures
            MemberDomainMap domainMap = schemaContext.ViewTarget == ViewTarget.QueryView ? queryDomainMap : updateDomainMap; 
            SignatureGenerator signatureGenerator = new SignatureGenerator(extent, m_workspace);
            m_memberMaps = new MemberMaps(schemaContext, signatureGenerator.ProjectedSlotMap,
                                          queryDomainMap, updateDomainMap);
 
            // Create left fragment KB: includes constraints for the extent to be constructed
            FragmentQueryKB leftKB = new FragmentQueryKB(); 
            leftKB.CreateVariableConstraints(extent, domainMap, workspace); 
            m_leftFragmentQP = new FragmentQueryProcessor(leftKB);
            m_rewritingCache = new Dictionary>( 
                FragmentQuery.GetEqualityComparer(m_leftFragmentQP));

            // Now using the signatures, create new cells such that
            // "extent's" query (C or S) is described in terms of multiconstants 
            if(!CreateLeftCellWrappers(extentCells, schemaContext.ViewTarget))
            { 
                return; 
            }
 
            // Create right fragment KB: includes constraints for all extents and association roles of right queries
            FragmentQueryKB rightKB = new FragmentQueryKB();
            MemberDomainMap rightDomainMap = schemaContext.ViewTarget == ViewTarget.QueryView ? updateDomainMap : queryDomainMap;
            foreach (LeftCellWrapper leftCellWrapper in m_cellWrappers) 
            {
                EntitySetBase rightExtent = leftCellWrapper.RightExtent; 
                rightKB.CreateVariableConstraints(rightExtent, rightDomainMap, workspace); 
                rightKB.CreateAssociationConstraints(rightExtent, rightDomainMap, workspace);
            } 
            m_rightFragmentQP = new FragmentQueryProcessor(rightKB);

            // Check for concurrency control tokens
            if (m_schemaContext.ViewTarget == ViewTarget.QueryView) 
            {
                CheckConcurrencyControlTokens(); 
            } 
            // For backward compatibility -
            // order wrappers by increasing domain size, decreasing number of attributes 
            m_cellWrappers.Sort(LeftCellWrapper.Comparer);
        }

        #endregion 

        #region Fields 
        // Configuration variables 
        private ConfigViewGenerator   m_config;
        // Extent for which the cells are being normalized 
        private EntitySetBase       m_extent;
        private SchemaContext         m_schemaContext;
        // Different maps for members
        private MemberMaps            m_memberMaps; 
        private MetadataWorkspace m_workspace;
 
        // The normalized cells that are created 
        private List m_cellWrappers;
        // Implicit constraints between members in queries based on schema. E.g., p.Addr IS NOT NULL <=> p IS OF Customer 
        private FragmentQueryProcessor m_leftFragmentQP;
        // In addition to constraints for each right extent contains constraints due to associations
        private FragmentQueryProcessor m_rightFragmentQP;
        private CqlIdentifiers m_identifiers; 
        // Maps (left) queries to their rewritings in terms of views
        private Dictionary> m_rewritingCache; 
 
        private StorageEntityContainerMapping m_entityContainerMapping;
        #endregion 

        #region Properties

        internal MemberMaps MemberMaps { 
            get {
                return m_memberMaps; 
            } 
        }
 
        // effects: Returns the extent for which the cells have been normalized
        internal EntitySetBase Extent {
            get { return m_extent; }
        } 

        internal SchemaContext SchemaContext 
        { 
            get { return m_schemaContext; }
        } 

        internal ConfigViewGenerator Config
        {
            get { return m_config; } 
        }
 
        internal CqlIdentifiers CqlIdentifiers 
        {
            get { return m_identifiers; } 
        }

        internal MetadataWorkspace Workspace
        { 
            get { return m_workspace; }
        } 
 
        internal FragmentQueryProcessor LeftFragmentQP
        { 
            get { return m_leftFragmentQP; }
        }

        internal FragmentQueryProcessor RightFragmentQP 
        {
            get { return m_rightFragmentQP; } 
        } 

        // effects: Returns all wrappers that were originally relevant for 
        // this extent
        internal List AllWrappersForExtent {
            get {
                return m_cellWrappers; 
            }
        } 
 
        internal StorageEntityContainerMapping EntityContainerMapping
        { 
            get { return m_entityContainerMapping; }
        }
        #endregion
 
        #region Methods
 
        // effects: Returns the cached rewriting of (left) queries in terms of views, if any 
        internal bool TryGetCachedRewriting(FragmentQuery query, out Tile rewriting)
        { 
            return m_rewritingCache.TryGetValue(query, out rewriting);
        }

        // effects: Records the cached rewriting of (left) queries in terms of views 
        internal void SetCachedRewriting(FragmentQuery query, Tile rewriting)
        { 
            m_rewritingCache[query] = rewriting; 
        }
 

        // requires: This method be called for query views only
        // effects: Checks if the concurrency control tokens are mapped for
        // each multiconstant 
        private void CheckConcurrencyControlTokens() {
            // Get the token fields for this extent 
 
            EntityTypeBase extentType = m_extent.ElementType;
            Set tokenMembers = MetadataHelper.GetConcurrencyMembersForTypeHierarchy(extentType, m_workspace); 
            Set tokenPaths = new Set(MemberPath.EqualityComparer);
            foreach (EdmMember tokenMember in tokenMembers) {
                if (tokenMember.DeclaringType.Equals(extentType) == false) {
                    string message = System.Data.Entity.Strings.ViewGen_Concurrency_Derived_Class_2(tokenMember.Name, 
                                                   tokenMember.DeclaringType.Name, m_extent);
                    ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ConcurrencyDerivedClass, message, m_cellWrappers, String.Empty); 
                    ExceptionHelpers.ThrowMappingException(record, m_config); 
                }
                tokenPaths.Add(new MemberPath(m_extent, tokenMember, m_schemaContext.MetadataWorkspace)); 
            }

            if (tokenMembers.Count > 0)
            { 
                foreach (LeftCellWrapper wrapper in m_cellWrappers)
                { 
                    Set conditionMembers = new Set( 
                        wrapper.OnlyInputCell.CQuery.WhereClause.OneOfConstVariables.Select(oneOf => oneOf.Slot.MemberPath),
                        MemberPath.EqualityComparer); 
                    conditionMembers.Intersect(tokenPaths);
                    if (conditionMembers.Count > 0)
                    {
                        // There is a condition on concurrency tokens. Throw an exception. 
                        StringBuilder builder = new StringBuilder();
                        builder.AppendLine(Strings.ViewGen_Concurrency_Invalid_Condition_1( 
                                                         MemberPath.PropertiesToUserString(conditionMembers, false), m_extent.Name)); 
                        ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ConcurrencyTokenHasCondition, builder.ToString(), new LeftCellWrapper[] { wrapper }, String.Empty);
                        ExceptionHelpers.ThrowMappingException(record, m_config); 
                    }
                }
            }
        } 

        // effects: Given an extent and its cells, verifies different 
        // constraints on each cell, e.g., each cell contains mappings for 
        // the keys (isQueryView indicates if the extent is a C side or S
        // side extent). Throws the relevant exception if the validation fails 
        // If there is a user-visible error (i.e., the user made a mistake,
        // throws the real exception for the user)
        private static void ValidateCells(EntitySetBase extent, IEnumerable extentCells, ViewTarget viewTarget) {
            // Validate the cells for the presence of keys 

            foreach (Cell cell in extentCells) { 
                cell.CheckRepInvariant(); 
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget);
                // Determine the extent we are recovering 
                EntitySetBase cellExtent = cellQuery.Extent;
                ExceptionHelpers.CheckAndThrowResArgs(extent.Equals(cellExtent), Strings.ViewGen_InputCells_NotIsolated_1,
                                                      extent.ElementType.Name, cellExtent.ElementType.Name);
 
            }
        } 
 
        // effects: Given the cells for the extent (extentCells) along with
        // the signatures (multiconstants + needed attributes) for this extent, generates 
        // the left cell wrappers for it extent (viewTarget indicates whether
        // the view is for querying or update purposes
        // Modifies m_cellWrappers to contain this list
        private bool CreateLeftCellWrappers(IEnumerable extentCells, 
            ViewTarget viewTarget) {
 
            List extentCellsList = new List(extentCells); 
            List alignedCells = AlignFields(extentCellsList, m_memberMaps.ProjectedSlotMap, viewTarget);
            Debug.Assert(alignedCells.Count == extentCellsList.Count, "Cell counts disagree"); 

            // Go through all the cells and create cell wrappers that can be used for generating the view
            m_cellWrappers = new List();
 
            for (int i = 0; i < alignedCells.Count; i++) {
                Cell alignedCell = alignedCells[i]; 
                CellQuery left = alignedCell.GetLeftQuery(viewTarget); 
                CellQuery right = alignedCell.GetRightQuery(viewTarget);
 
                // Obtain the non-null projected slots into attributes
                AttributeSet attributes = left.GetNonNullSlots();

                BoolExpression fromVariable = BoolExpression.CreateLiteral(new CellIdBoolean(m_identifiers, extentCellsList[i].CellNumber), m_memberMaps.LeftDomainMap); 
                FragmentQuery fragmentQuery = FragmentQuery.Create(fromVariable, left);
                if (viewTarget == ViewTarget.UpdateView) 
                { 
                    fragmentQuery = m_leftFragmentQP.CreateDerivedViewBySelectingConstantAttributes(fragmentQuery) ?? fragmentQuery;
                } 

                LeftCellWrapper leftWrapper = new LeftCellWrapper(m_schemaContext, attributes, fragmentQuery, right, m_memberMaps,
                                                                  extentCellsList[i]);
                m_cellWrappers.Add(leftWrapper); 
            }
            return true; 
        } 

        // effects: Align the fields of each cell in mapping using projectedSlotMap that has a mapping 
        // for each member of this extent to the slot number of that member in the projected slots
        // example:
        //    input:  Proj[A,B,"5"] = Proj[F,"7",G]
        //            Proj[C,B]     = Proj[H,I] 
        //   output:  m_projectedSlotMap: A -> 0, B -> 1, C -> 2
        //            Proj[A,B,null] = Proj[F,"7",null] 
        //            Proj[null,B,C] = Proj[null,I,H] 
        private static List AlignFields(IEnumerable cells, MemberPathMapBase projectedSlotMap,
                                              ViewTarget viewTarget) { 

            List outputCells = new List();

            // Determine the aligned field for each cell 
            // The new cells have ProjectedSlotMap.Count number of fields
            foreach (Cell cell in cells) { 
 
                // If isQueryView is true, we need to consider the C side of
                // the cells; otherwise, we look at the S side. Note that we 
                // CANNOT use cell.LeftQuery since that is determined by
                // cell's isQueryView

                // The query for which we are constructing the extent 
                CellQuery mainQuery = cell.GetLeftQuery(viewTarget);
                CellQuery otherQuery = cell.GetRightQuery(viewTarget); 
 
                CellQuery newMainQuery;
                CellQuery newOtherQuery; 
                // Create both queries where the projected slot map is used
                // to determine the order of the fields of the mainquery (of
                // course, the otherQuery's fields are aligned automatically)
                mainQuery.CreateFieldAlignedCellQueries(otherQuery, projectedSlotMap, 
                                                        out newMainQuery, out newOtherQuery);
 
                Cell outputCell = viewTarget == ViewTarget.QueryView ? 
                    Cell.CreateCS(newMainQuery, newOtherQuery, cell.CellLabel, cell.CellNumber) :
                    Cell.CreateCS(newOtherQuery, newMainQuery, cell.CellLabel, cell.CellNumber); 
                outputCells.Add(outputCell);
            }
            return outputCells;
        } 

        internal bool IsEmpty(CellTreeNode n) 
        { 
            return n.IsEmptyRightFragmentQuery;
        } 

        #endregion

        #region String Methods 
        internal override void ToCompactString(StringBuilder builder) {
            LeftCellWrapper.WrappersToStringBuilder(builder, m_cellWrappers, "Left Celll Wrappers"); 
        } 

        #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.Data.Common.Utils.Boolean;
using System.Data.Mapping.ViewGeneration.Structures;
using System.Collections.Generic;
using System.Text; 
using System.Data.Mapping.ViewGeneration.Validation;
using System.Data.Mapping.ViewGeneration.QueryRewriting; 
using System.Diagnostics; 
using System.Collections.ObjectModel;
using System.Data.Mapping.ViewGeneration.Utils; 
using System.Data.Metadata.Edm;
using System.Linq;

namespace System.Data.Mapping.ViewGeneration { 

    using AttributeSet = Set; 
    using System.Data.Entity; 

    // This class is responsible for normalizing the cells for an extent so 
    // that view generation can occur on the normalized cells.
    // Main task: Converts an extent cells to normalized form with
    // multiconstants along the needed signatures
    // Output: A collection of LeftCellWrappers for the extent. Each wrapper has 
    // the attriutes, the "right" query, and a set of multiconstants X - these
    // multiconstants denote a where clause "variable in X". 
 
    internal class CellNormalizer : InternalBase {
 
        #region Constructors
        // effects: Given an extent and the cells
        // for that extent, creates a CellNormalizer object that is capable
        // of returning the normalized cells and the extent signatures when needed 
        internal CellNormalizer(EntitySetBase extent, IEnumerable extentCells, SchemaContext schemaContext,
                                CqlIdentifiers identifiers, 
                                ConfigViewGenerator config, MemberDomainMap queryDomainMap, 
                                MemberDomainMap updateDomainMap, StorageEntityContainerMapping entityContainerMapping,
                                MetadataWorkspace workspace) { 

            m_extent = extent;
            m_schemaContext = schemaContext;
            m_config = config; 
            m_workspace = workspace;
            m_entityContainerMapping = entityContainerMapping; 
            m_identifiers = identifiers; 

            // Check that the cells that we start out with are ok 
            ValidateCells(extent, extentCells, schemaContext.ViewTarget);

            // create a copy of updateDomainMap so generation of query views later on is not affected
            // it is modified in QueryRewriter.AdjustMemberDomainsForUpdateViews 
            updateDomainMap = updateDomainMap.MakeCopy();
 
            // Create a signature generator that handles all the 
            // multiconstant work and generating the signatures
            MemberDomainMap domainMap = schemaContext.ViewTarget == ViewTarget.QueryView ? queryDomainMap : updateDomainMap; 
            SignatureGenerator signatureGenerator = new SignatureGenerator(extent, m_workspace);
            m_memberMaps = new MemberMaps(schemaContext, signatureGenerator.ProjectedSlotMap,
                                          queryDomainMap, updateDomainMap);
 
            // Create left fragment KB: includes constraints for the extent to be constructed
            FragmentQueryKB leftKB = new FragmentQueryKB(); 
            leftKB.CreateVariableConstraints(extent, domainMap, workspace); 
            m_leftFragmentQP = new FragmentQueryProcessor(leftKB);
            m_rewritingCache = new Dictionary>( 
                FragmentQuery.GetEqualityComparer(m_leftFragmentQP));

            // Now using the signatures, create new cells such that
            // "extent's" query (C or S) is described in terms of multiconstants 
            if(!CreateLeftCellWrappers(extentCells, schemaContext.ViewTarget))
            { 
                return; 
            }
 
            // Create right fragment KB: includes constraints for all extents and association roles of right queries
            FragmentQueryKB rightKB = new FragmentQueryKB();
            MemberDomainMap rightDomainMap = schemaContext.ViewTarget == ViewTarget.QueryView ? updateDomainMap : queryDomainMap;
            foreach (LeftCellWrapper leftCellWrapper in m_cellWrappers) 
            {
                EntitySetBase rightExtent = leftCellWrapper.RightExtent; 
                rightKB.CreateVariableConstraints(rightExtent, rightDomainMap, workspace); 
                rightKB.CreateAssociationConstraints(rightExtent, rightDomainMap, workspace);
            } 
            m_rightFragmentQP = new FragmentQueryProcessor(rightKB);

            // Check for concurrency control tokens
            if (m_schemaContext.ViewTarget == ViewTarget.QueryView) 
            {
                CheckConcurrencyControlTokens(); 
            } 
            // For backward compatibility -
            // order wrappers by increasing domain size, decreasing number of attributes 
            m_cellWrappers.Sort(LeftCellWrapper.Comparer);
        }

        #endregion 

        #region Fields 
        // Configuration variables 
        private ConfigViewGenerator   m_config;
        // Extent for which the cells are being normalized 
        private EntitySetBase       m_extent;
        private SchemaContext         m_schemaContext;
        // Different maps for members
        private MemberMaps            m_memberMaps; 
        private MetadataWorkspace m_workspace;
 
        // The normalized cells that are created 
        private List m_cellWrappers;
        // Implicit constraints between members in queries based on schema. E.g., p.Addr IS NOT NULL <=> p IS OF Customer 
        private FragmentQueryProcessor m_leftFragmentQP;
        // In addition to constraints for each right extent contains constraints due to associations
        private FragmentQueryProcessor m_rightFragmentQP;
        private CqlIdentifiers m_identifiers; 
        // Maps (left) queries to their rewritings in terms of views
        private Dictionary> m_rewritingCache; 
 
        private StorageEntityContainerMapping m_entityContainerMapping;
        #endregion 

        #region Properties

        internal MemberMaps MemberMaps { 
            get {
                return m_memberMaps; 
            } 
        }
 
        // effects: Returns the extent for which the cells have been normalized
        internal EntitySetBase Extent {
            get { return m_extent; }
        } 

        internal SchemaContext SchemaContext 
        { 
            get { return m_schemaContext; }
        } 

        internal ConfigViewGenerator Config
        {
            get { return m_config; } 
        }
 
        internal CqlIdentifiers CqlIdentifiers 
        {
            get { return m_identifiers; } 
        }

        internal MetadataWorkspace Workspace
        { 
            get { return m_workspace; }
        } 
 
        internal FragmentQueryProcessor LeftFragmentQP
        { 
            get { return m_leftFragmentQP; }
        }

        internal FragmentQueryProcessor RightFragmentQP 
        {
            get { return m_rightFragmentQP; } 
        } 

        // effects: Returns all wrappers that were originally relevant for 
        // this extent
        internal List AllWrappersForExtent {
            get {
                return m_cellWrappers; 
            }
        } 
 
        internal StorageEntityContainerMapping EntityContainerMapping
        { 
            get { return m_entityContainerMapping; }
        }
        #endregion
 
        #region Methods
 
        // effects: Returns the cached rewriting of (left) queries in terms of views, if any 
        internal bool TryGetCachedRewriting(FragmentQuery query, out Tile rewriting)
        { 
            return m_rewritingCache.TryGetValue(query, out rewriting);
        }

        // effects: Records the cached rewriting of (left) queries in terms of views 
        internal void SetCachedRewriting(FragmentQuery query, Tile rewriting)
        { 
            m_rewritingCache[query] = rewriting; 
        }
 

        // requires: This method be called for query views only
        // effects: Checks if the concurrency control tokens are mapped for
        // each multiconstant 
        private void CheckConcurrencyControlTokens() {
            // Get the token fields for this extent 
 
            EntityTypeBase extentType = m_extent.ElementType;
            Set tokenMembers = MetadataHelper.GetConcurrencyMembersForTypeHierarchy(extentType, m_workspace); 
            Set tokenPaths = new Set(MemberPath.EqualityComparer);
            foreach (EdmMember tokenMember in tokenMembers) {
                if (tokenMember.DeclaringType.Equals(extentType) == false) {
                    string message = System.Data.Entity.Strings.ViewGen_Concurrency_Derived_Class_2(tokenMember.Name, 
                                                   tokenMember.DeclaringType.Name, m_extent);
                    ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ConcurrencyDerivedClass, message, m_cellWrappers, String.Empty); 
                    ExceptionHelpers.ThrowMappingException(record, m_config); 
                }
                tokenPaths.Add(new MemberPath(m_extent, tokenMember, m_schemaContext.MetadataWorkspace)); 
            }

            if (tokenMembers.Count > 0)
            { 
                foreach (LeftCellWrapper wrapper in m_cellWrappers)
                { 
                    Set conditionMembers = new Set( 
                        wrapper.OnlyInputCell.CQuery.WhereClause.OneOfConstVariables.Select(oneOf => oneOf.Slot.MemberPath),
                        MemberPath.EqualityComparer); 
                    conditionMembers.Intersect(tokenPaths);
                    if (conditionMembers.Count > 0)
                    {
                        // There is a condition on concurrency tokens. Throw an exception. 
                        StringBuilder builder = new StringBuilder();
                        builder.AppendLine(Strings.ViewGen_Concurrency_Invalid_Condition_1( 
                                                         MemberPath.PropertiesToUserString(conditionMembers, false), m_extent.Name)); 
                        ErrorLog.Record record = new ErrorLog.Record(true, ViewGenErrorCode.ConcurrencyTokenHasCondition, builder.ToString(), new LeftCellWrapper[] { wrapper }, String.Empty);
                        ExceptionHelpers.ThrowMappingException(record, m_config); 
                    }
                }
            }
        } 

        // effects: Given an extent and its cells, verifies different 
        // constraints on each cell, e.g., each cell contains mappings for 
        // the keys (isQueryView indicates if the extent is a C side or S
        // side extent). Throws the relevant exception if the validation fails 
        // If there is a user-visible error (i.e., the user made a mistake,
        // throws the real exception for the user)
        private static void ValidateCells(EntitySetBase extent, IEnumerable extentCells, ViewTarget viewTarget) {
            // Validate the cells for the presence of keys 

            foreach (Cell cell in extentCells) { 
                cell.CheckRepInvariant(); 
                CellQuery cellQuery = cell.GetLeftQuery(viewTarget);
                // Determine the extent we are recovering 
                EntitySetBase cellExtent = cellQuery.Extent;
                ExceptionHelpers.CheckAndThrowResArgs(extent.Equals(cellExtent), Strings.ViewGen_InputCells_NotIsolated_1,
                                                      extent.ElementType.Name, cellExtent.ElementType.Name);
 
            }
        } 
 
        // effects: Given the cells for the extent (extentCells) along with
        // the signatures (multiconstants + needed attributes) for this extent, generates 
        // the left cell wrappers for it extent (viewTarget indicates whether
        // the view is for querying or update purposes
        // Modifies m_cellWrappers to contain this list
        private bool CreateLeftCellWrappers(IEnumerable extentCells, 
            ViewTarget viewTarget) {
 
            List extentCellsList = new List(extentCells); 
            List alignedCells = AlignFields(extentCellsList, m_memberMaps.ProjectedSlotMap, viewTarget);
            Debug.Assert(alignedCells.Count == extentCellsList.Count, "Cell counts disagree"); 

            // Go through all the cells and create cell wrappers that can be used for generating the view
            m_cellWrappers = new List();
 
            for (int i = 0; i < alignedCells.Count; i++) {
                Cell alignedCell = alignedCells[i]; 
                CellQuery left = alignedCell.GetLeftQuery(viewTarget); 
                CellQuery right = alignedCell.GetRightQuery(viewTarget);
 
                // Obtain the non-null projected slots into attributes
                AttributeSet attributes = left.GetNonNullSlots();

                BoolExpression fromVariable = BoolExpression.CreateLiteral(new CellIdBoolean(m_identifiers, extentCellsList[i].CellNumber), m_memberMaps.LeftDomainMap); 
                FragmentQuery fragmentQuery = FragmentQuery.Create(fromVariable, left);
                if (viewTarget == ViewTarget.UpdateView) 
                { 
                    fragmentQuery = m_leftFragmentQP.CreateDerivedViewBySelectingConstantAttributes(fragmentQuery) ?? fragmentQuery;
                } 

                LeftCellWrapper leftWrapper = new LeftCellWrapper(m_schemaContext, attributes, fragmentQuery, right, m_memberMaps,
                                                                  extentCellsList[i]);
                m_cellWrappers.Add(leftWrapper); 
            }
            return true; 
        } 

        // effects: Align the fields of each cell in mapping using projectedSlotMap that has a mapping 
        // for each member of this extent to the slot number of that member in the projected slots
        // example:
        //    input:  Proj[A,B,"5"] = Proj[F,"7",G]
        //            Proj[C,B]     = Proj[H,I] 
        //   output:  m_projectedSlotMap: A -> 0, B -> 1, C -> 2
        //            Proj[A,B,null] = Proj[F,"7",null] 
        //            Proj[null,B,C] = Proj[null,I,H] 
        private static List AlignFields(IEnumerable cells, MemberPathMapBase projectedSlotMap,
                                              ViewTarget viewTarget) { 

            List outputCells = new List();

            // Determine the aligned field for each cell 
            // The new cells have ProjectedSlotMap.Count number of fields
            foreach (Cell cell in cells) { 
 
                // If isQueryView is true, we need to consider the C side of
                // the cells; otherwise, we look at the S side. Note that we 
                // CANNOT use cell.LeftQuery since that is determined by
                // cell's isQueryView

                // The query for which we are constructing the extent 
                CellQuery mainQuery = cell.GetLeftQuery(viewTarget);
                CellQuery otherQuery = cell.GetRightQuery(viewTarget); 
 
                CellQuery newMainQuery;
                CellQuery newOtherQuery; 
                // Create both queries where the projected slot map is used
                // to determine the order of the fields of the mainquery (of
                // course, the otherQuery's fields are aligned automatically)
                mainQuery.CreateFieldAlignedCellQueries(otherQuery, projectedSlotMap, 
                                                        out newMainQuery, out newOtherQuery);
 
                Cell outputCell = viewTarget == ViewTarget.QueryView ? 
                    Cell.CreateCS(newMainQuery, newOtherQuery, cell.CellLabel, cell.CellNumber) :
                    Cell.CreateCS(newOtherQuery, newMainQuery, cell.CellLabel, cell.CellNumber); 
                outputCells.Add(outputCell);
            }
            return outputCells;
        } 

        internal bool IsEmpty(CellTreeNode n) 
        { 
            return n.IsEmptyRightFragmentQuery;
        } 

        #endregion

        #region String Methods 
        internal override void ToCompactString(StringBuilder builder) {
            LeftCellWrapper.WrappersToStringBuilder(builder, m_cellWrappers, "Left Celll Wrappers"); 
        } 

        #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