Span.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Objects / Span.cs / 1305376 / Span.cs

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

using System; 
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data; 
using System.Data.Common;
using System.Data.Metadata; 
using System.Data.Metadata.Edm; 
using System.Data.Objects.DataClasses;
using System.Diagnostics; 
using System.Reflection;
using System.Text.RegularExpressions;
using System.Text;
using System.Data.Objects.Internal; 

namespace System.Data.Objects 
{ 
    /// 
    /// A collection of paths to determine which entities are spanned into a query. 
    /// 
    internal sealed class Span
    {
        private List _spanList; 
        private string _cacheKey;
 
        internal Span() 
        {
            _spanList = new List(); 
        }

        /// 
        /// The list of paths that should be spanned into the query 
        /// 
        internal List SpanList 
        { 
            get { return _spanList; }
        } 

        /// 
        /// Checks whether relationship span needs to be performed. Currently this is only when the query is
        /// not using MergeOption.NoTracking. 
        /// 
        ///  
        /// True if the query needs a relationship span rewrite 
        internal static bool RequiresRelationshipSpan(MergeOption mergeOption)
        { 
            return (mergeOption != MergeOption.NoTracking);
        }

        ///  
        /// Includes the specified span path in the specified span instance and returns the updated span instance.
        /// If  is null, a new span instance is constructed and returned that contains 
        /// the specified include path. 
        /// 
        /// The span instance to which the include path should be added. May be null 
        /// The include path to add
        /// A non-null span instance that contains the specified include path in addition to any paths ut already contained
        internal static Span IncludeIn(Span spanToIncludeIn, string pathToInclude)
        { 
            if (null == spanToIncludeIn)
            { 
                spanToIncludeIn = new Span(); 
            }
 
            spanToIncludeIn.Include(pathToInclude);
            return spanToIncludeIn;
        }
 
        /// 
        /// Returns a span instance that is the union of the two specified span instances. 
        /// If  and  are both null, 
        /// then null is returned.
        /// If  or  is null, but the remaining argument is non-null, 
        /// then the non-null argument is returned.
        /// If neither  nor  are null, a new span instance is returned
        /// that contains the merged span paths from both.
        ///  
        /// The first span instance from which to include span paths; may be null
        /// The second span instance from which to include span paths; may be null 
        /// A span instance representing the union of the two arguments; may be null if both arguments are null 
        internal static Span CopyUnion(Span span1, Span span2)
        { 
            if (null == span1)
            {
                return span2;
            } 

            if (null == span2) 
            { 
                return span1;
            } 

            Span retSpan = span1.Clone();
            foreach (SpanPath path in span2.SpanList)
            { 
                retSpan.AddSpanPath(path);
            } 
 
            return retSpan;
        } 

        internal string GetCacheKey()
        {
            if (null == _cacheKey) 
            {
                if (_spanList.Count > 0) 
                { 
                    // If there is only a single Include path with a single property,
                    // then simply use the property name as the cache key rather than 
                    // creating any new strings.
                    if (_spanList.Count == 1 &&
                       _spanList[0].Navigations.Count == 1)
                    { 
                        _cacheKey = _spanList[0].Navigations[0];
                    } 
                    else 
                    {
                        StringBuilder keyBuilder = new StringBuilder(); 
                        for (int pathIdx = 0; pathIdx < _spanList.Count; pathIdx++)
                        {
                            if (pathIdx > 0)
                            { 
                                keyBuilder.Append(";");
                            } 
 
                            SpanPath thisPath = _spanList[pathIdx];
                            keyBuilder.Append(thisPath.Navigations[0]); 
                            for (int propIdx = 1; propIdx < thisPath.Navigations.Count; propIdx++)
                            {
                                keyBuilder.Append(".");
                                keyBuilder.Append(thisPath.Navigations[propIdx]); 
                            }
                        } 
 
                        _cacheKey = keyBuilder.ToString();
                    } 
                }
            }

            return _cacheKey; 
        }
 
        ///  
        /// Adds a path to span into the query.
        ///  
        /// The path to span
        public void Include(string path)
        {
            EntityUtil.CheckStringArgument(path, "path"); 

            SpanPath spanPath = new SpanPath(ParsePath(path)); 
            AddSpanPath(spanPath); 
            _cacheKey = null;
        } 

        /// 
        /// Creates a new Span with the same SpanPaths as this Span
        ///  
        /// 
        internal Span Clone() 
        { 
            Span newSpan = new Span();
            newSpan.SpanList.AddRange(_spanList); 
            newSpan._cacheKey = this._cacheKey;

            return newSpan;
        } 

        ///  
        /// Adds the path if it does not already exist 
        /// 
        ///  
        internal void AddSpanPath(SpanPath spanPath)
        {
            if (ValidateSpanPath(spanPath))
            { 
                RemoveExistingSubPaths(spanPath);
                _spanList.Add(spanPath); 
            } 
        }
 
        /// 
        /// Returns true if the path can be added
        /// 
        ///  
        private bool ValidateSpanPath(SpanPath spanPath)
        { 
 
            // Check for dupliacte entries
            for (int i = 0; i < _spanList.Count; i++) 
            {
                // make sure spanPath is not a sub-path of anything already in the list
                if (spanPath.IsSubPath(_spanList[i]))
                { 
                    return false;
                } 
            } 
            return true;
        } 

        private void RemoveExistingSubPaths(SpanPath spanPath)
        {
            List toDelete = new List(); 
            for (int i = 0; i < _spanList.Count; i++)
            { 
                // make sure spanPath is not a sub-path of anything already in the list 
                if (_spanList[i].IsSubPath(spanPath))
                { 
                    toDelete.Add(_spanList[i]);
                }
            }
 
            foreach (SpanPath path in toDelete)
            { 
                _spanList.Remove(path); 
            }
        } 

        /// 
        /// Storage for a span path
        /// Currently this includes the list of navigation properties 
        /// 
        internal class SpanPath 
        { 
            public readonly List Navigations;
 
            public SpanPath(List navigations)
            {
                Navigations = navigations;
            } 

            public bool IsSubPath(SpanPath rhs) 
            { 
                // this is a subpath of rhs if it has fewer paths, and all the path element values are equal
                if (Navigations.Count > rhs.Navigations.Count) 
                {
                    return false;
                }
 
                for (int i = 0; i < Navigations.Count; i++)
                { 
                    if (!Navigations[i].Equals(rhs.Navigations[i], StringComparison.OrdinalIgnoreCase)) 
                    {
                        return false; 
                    }
                }

                return true; 
            }
        } 
 

        private static List ParsePath(string path) 
        {
            List navigations = new List();

            string[] parts = System.Data.Common.MultipartIdentifier.ParseMultipartIdentifier(path, "[", "]", '.', 8, true, "Include", false); 

            for (int i = parts.Length - 1; i >= 0; i--) 
            { 
                if (parts[i] != null)
                { 
                    if (parts[i].Length == 0)
                    {
                        throw EntityUtil.SpanPathSyntaxError();
                    } 
                    navigations.Add(parts[i]);
                } 
            } 

            Debug.Assert(navigations.Count > 0, "Empty path found"); 

            if(navigations.Count > 1)
            {
                navigations.Reverse(); 
            }
 
            return navigations; 
        }
    } 
}

// 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