EpmContentSerializer.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 / DataWeb / Server / System / Data / Services / Epm / EpmContentSerializer.cs / 1305376 / EpmContentSerializer.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
// Class used for serializing EntityPropertyMappingAttribute content.
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Common
{
#region Namespaces 
    using System.Collections.Generic;
    using System.Data.Services.Internal; 
    using System.Data.Services.Providers; 
    using System.Data.Services.Serializers;
    using System.Diagnostics; 
    using System.Linq;
    using System.ServiceModel.Syndication;
#endregion
 
    /// 
    /// Publically visible interface of the Content serializer, acts as container for both Custom and Syndication content serializers 
    ///  
    internal sealed class EpmContentSerializer : IDisposable
    { 
        ///  for which this serializer works
        private readonly ResourceType resourceType;

        ///  
        /// Syndication specific content serializer
        ///  
        private readonly EpmSyndicationContentSerializer epmSyndicationSerializer; 

        ///  
        /// Custom content serializer
        /// 
        private readonly EpmCustomContentSerializer epmCustomSerializer;
 
        /// 
        /// Target syndication item to which we add serialized content 
        ///  
        private SyndicationItem targetItem;
 
        /// Collection of null valued properties for this current serialization
        private EpmNullValuedPropertyTree nullValuedProperties;

        ///  
        /// Constructor creates contained serializers
        ///  
        /// Resource type being serialized 
        /// Instance of 
        /// SyndicationItem to which content will be added 
        /// Data Service provider used for rights verification.
        internal EpmContentSerializer(ResourceType resourceType, Object value, SyndicationItem targetItem, DataServiceProviderWrapper provider)
        {
            this.resourceType = resourceType; 
            this.targetItem = targetItem;
            this.nullValuedProperties = new EpmNullValuedPropertyTree(provider, value); 
 
            if (this.NeedEpmSerialization)
            { 
                this.epmSyndicationSerializer = new EpmSyndicationContentSerializer(this.resourceType.EpmTargetTree, value, targetItem, this.nullValuedProperties);
                this.epmCustomSerializer = new EpmCustomContentSerializer(this.resourceType.EpmTargetTree, value, targetItem, this.nullValuedProperties, provider);
            }
        } 

        /// Does this type have any entity property mappings at all 
        private bool NeedEpmSerialization 
        {
            get 
            {
                Debug.Assert(this.resourceType != null, "Must have a valid ResourceType");
                return this.resourceType.HasEntityPropertyMappings;
            } 
        }
 
        ///  
        /// Cleansup visitor specific state of the target tree
        ///  
        public void Dispose()
        {
            if (this.NeedEpmSerialization)
            { 
                Debug.Assert(this.epmSyndicationSerializer != null, "ResourceType with mapping implies a valid syndication content serializer");
                this.epmSyndicationSerializer.Dispose(); 
                Debug.Assert(this.epmCustomSerializer != null, "ResourceType with mapping implies a valid custom content serializer"); 
                this.epmCustomSerializer.Dispose();
            } 
        }

        /// Delegates to each of custom and syndication serializers for serializing content
        /// Content in which to write null valued properties 
        /// Data Service provider used for rights verification.
        internal void Serialize(DictionaryContent content, DataServiceProviderWrapper provider) 
        { 
            if (this.NeedEpmSerialization)
            { 
                Debug.Assert(this.epmSyndicationSerializer != null, "ResourceType with mapping implies a valid syndication content serializer");
                this.epmSyndicationSerializer.Serialize(provider);
                Debug.Assert(this.epmCustomSerializer != null, "ResourceType with mapping implies a valid custom content serializer");
                this.epmCustomSerializer.Serialize(provider); 

                this.nullValuedProperties.AddNullValuesToContent(content); 
            } 
            else
            { 
                Debug.Assert(this.targetItem != null, "Must always have target content item");
                this.targetItem.Authors.Add(new SyndicationPerson(null, String.Empty, null));
            }
        } 

        /// Tree representing null valued properties for an instance 
        internal sealed class EpmNullValuedPropertyTree 
        {
            /// Root of the tree 
            private EpmNullValuedPropertyNode root;

            /// Provider wrapper instance
            private DataServiceProviderWrapper provider; 

            /// Object whose properties we will read 
            private object element; 

            /// Constructor that creates the root of the tree 
            /// Provider wrapper instance
            /// Object whose properties we will read
            internal EpmNullValuedPropertyTree(DataServiceProviderWrapper provider, object element)
            { 
                this.root = new EpmNullValuedPropertyNode { Name = null };
                this.provider = provider; 
                this.element = element; 
            }
 
            /// Adds a property to the null valued collection
            /// EpmInfo containing the property information such as path
            internal void Add(EntityPropertyMappingInfo epmInfo)
            { 
                Debug.Assert(epmInfo != null, "epmInfo != null");
                EpmNullValuedPropertyNode current = this.root; 
                ResourceType currentType = epmInfo.DefiningType; 
                object currentValue = this.element;
 
                // We are here because the epm path points to a null value. If the path is multiple level deep, we need to
                // know the first level the null value begins and we don't need to serialize deeper than that.
                // To serialize the complex properties correctly in the case they are not already in content, we also need
                // to find the type for each segment from root to the first segment that has the null property value. 
                foreach (var segment in epmInfo.Attribute.SourcePath.Split('/'))
                { 
                    EpmNullValuedPropertyNode child = current.Children.FirstOrDefault(c => c.Name == segment); 
                    if (child != null)
                    { 
                        // The current segment is already added to the tree, reuse it.
                        current = child;
                        currentValue = child.Element;
                        currentType = child.ResourceType; 
                    }
                    else 
                    { 
                        EpmNullValuedPropertyNode newNode = new EpmNullValuedPropertyNode { Name = segment };
                        Debug.Assert(currentType != null, "currentType != null"); 
                        ResourceProperty property = currentType.TryResolvePropertyName(segment);

                        Debug.Assert(currentValue != null, "currentValue != null");
                        ProjectedWrapper projectedValue = currentValue as ProjectedWrapper; 
                        if (projectedValue == null)
                        { 
                            if (property != null) 
                            {
                                currentValue = this.provider.GetPropertyValue(currentValue, property, currentType); 
                                currentValue = currentValue == DBNull.Value ? null : currentValue;
                                currentType = property.ResourceType;
                            }
                            else 
                            {
                                // Handle open property... 
                                currentValue = this.provider.GetOpenPropertyValue(currentValue, segment); 
                                currentValue = currentValue == DBNull.Value ? null : currentValue;
                                if (currentValue != null) 
                                {
                                    // Get the type from the instance.
                                    currentType = this.provider.GetResourceType(currentValue);
                                } 
                                else
                                { 
                                    // We have a null open property at hand, we don't know its type. 
                                    // Default the type to string so that we will omit the type name
                                    // and just write out null. i.e.  
                                    currentType = ResourceType.PrimitiveStringResourceType;
                                }
                            }
                        } 
                        else
                        { 
                            currentValue = projectedValue.GetProjectedPropertyValue(segment); 
                            currentValue = currentValue == DBNull.Value ? null : currentValue;
 
                            if (property != null)
                            {
                                currentType = property.ResourceType;
                            } 
                            else
                            { 
                                // Handle open property... 
                                if (currentValue == null)
                                { 
                                    // We have a null open property at hand, we don't know its type.
                                    // Default the type to string so that we will omit the type name
                                    // and just write out null. i.e. 
                                    currentType = ResourceType.PrimitiveStringResourceType; 
                                }
                                else 
                                { 
                                    projectedValue = currentValue as ProjectedWrapper;
                                    if (projectedValue != null) 
                                    {
                                        // Get the type from the project wrapper.
                                        currentType = this.provider.TryResolveResourceType(projectedValue.ResourceTypeName);
                                    } 
                                    else
                                    { 
                                        // Get the type from the instance. 
                                        currentType = this.provider.GetResourceType(currentValue);
                                    } 
                                }
                            }
                        }
 
                        Debug.Assert(currentType != null, "currentType != null");
                        Debug.Assert(currentValue != DBNull.Value, "currentValue != DBNull.Value -- we have converted DBNull to null"); 
                        newNode.ResourceType = currentType; 
                        newNode.Element = currentValue;
                        current.Children.Add(newNode); 
                        current = newNode;
                    }

                    if (current.Element == null) 
                    {
                        // If the current element is null, we don't need to go further since that is the obvious reason 
                        // that the children properties are null. 
                        break;
                    } 
                }
            }

            /// Adds the null valued properties to the content section 
            /// Content to which null properties are to be added
            internal void AddNullValuesToContent(DictionaryContent content) 
            { 
                this.AddNullValuesToContent(this.root, content);
            } 

            /// Adds the null valued properties to the content section of a syndication entry
            /// Current root node
            /// Current collection to which property is to be added 
            private void AddNullValuesToContent(EpmNullValuedPropertyNode currentRoot, DictionaryContent currentContent)
            { 
                foreach (EpmNullValuedPropertyNode node in currentRoot.Children) 
                {
                    bool found; 
                    DictionaryContent c = currentContent.Lookup(node.Name, out found);

                    Debug.Assert(node.ResourceType != null, "node.ResourceType != null");
                    switch (node.ResourceType.ResourceTypeKind) 
                    {
                        case ResourceTypeKind.ComplexType: 
                            if (!found) 
                            {
                                // If a complex property is not found in content, it is either not being projected 
                                // or all of its properties are mapped and all of them have KeepInContent=false
                                Debug.Assert(c == null, "when look up not found, c should be null.");
                                if (node.Element != null)
                                { 
                                    Debug.Assert(node.Children.Count > 0, "If the property represented by the current node is not null, there must be children nodes.");
 
                                    // The complex property is not null, but some of its descendant properties are null. 
                                    // We need to serialize the type name of the complex property.
                                    c = new DictionaryContent(); 
                                    currentContent.Add(node.Name, node.ResourceType.FullName, c);
                                }
                                else
                                { 
                                    Debug.Assert(node.Children.Count == 0, "If the property represented by the current node is not null, there must not be any children node.");
 
                                    // The complex property is null, we write out m:null='true'. 
                                    currentContent.AddNull(node.ResourceType.FullName, node.Name);
                                } 
                            }

                            if (c != null)
                            { 
                                // Only add the children properties if the complex property is not null.
                                this.AddNullValuesToContent(node, c); 
                            } 

                            break; 

                        case ResourceTypeKind.Primitive:
                            Debug.Assert(c == null, "DictionaryContent not expected for primitive properties.");
                            Debug.Assert(node.Element == null, "node.Element == null"); 
                            if (!found)
                            { 
                                currentContent.AddNull(node.ResourceType.FullName, node.Name); 
                            }
 
                            // if found, use the value in currentContent, we don't need to do anything here.
                            break;

                        case ResourceTypeKind.EntityType: 
                            Debug.Assert(false, "We cannot map navigation properties with friendly feeds.");
                            break; 
                    } 
                }
            } 

            /// 
            /// Representation for a node in the 
            ///  
            private sealed class EpmNullValuedPropertyNode
            { 
                /// Children of current node 
                private List children;
 
                /// Name of the property
                internal String Name
                {
                    get; 
                    set;
                } 
 
                /// ResourceType corresponding to the node
                internal ResourceType ResourceType 
                {
                    get;
                    set;
                } 

                /// Object whose element we will read 
                internal object Element 
                {
                    get; 
                    set;
                }

                /// Lazily creates the children collection and returns the collection 
                internal ICollection Children
                { 
                    get 
                    {
                        if (this.children == null) 
                        {
                            this.children = new List();
                        }
 
                        return this.children;
                    } 
                } 
            }
        } 
    }
}

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