You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			592 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			592 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | //--------------------------------------------------------------------- | ||
|  | // <copyright file="Helper.cs" company="Microsoft"> | ||
|  | //      Copyright (c) Microsoft Corporation.  All rights reserved. | ||
|  | // </copyright> | ||
|  | // | ||
|  | // @owner       [....] | ||
|  | // @backupOwner [....] | ||
|  | //--------------------------------------------------------------------- | ||
|  | 
 | ||
|  | namespace System.Data.Metadata.Edm | ||
|  | { | ||
|  |     using System.Collections; | ||
|  |     using System.Collections.Generic; | ||
|  |     using System.Diagnostics; | ||
|  |     using System.Linq; | ||
|  |     using System.Text; | ||
|  |     using System.Xml; | ||
|  |     using System.Xml.XPath; | ||
|  | 
 | ||
|  |     /// <summary> | ||
|  |     /// Helper Class for EDM Metadata - this class contains all the helper methods | ||
|  |     /// which only accesses public methods/properties. The other partial class contains all  | ||
|  |     /// helper methods which just uses internal methods/properties. The reason why we  | ||
|  |     /// did this for allowing view gen to happen at compile time - all the helper | ||
|  |     /// methods that view gen or mapping uses are in this class. Rest of the | ||
|  |     /// methods are in this class | ||
|  |     /// </summary> | ||
|  |     internal static partial class Helper | ||
|  |     { | ||
|  |         #region Fields | ||
|  |         internal static readonly EdmMember[] EmptyArrayEdmProperty = new EdmMember[0]; | ||
|  | 
 | ||
|  |         #endregion | ||
|  | 
 | ||
|  |         #region Methods | ||
|  |         /// <summary> | ||
|  |         /// The method wraps the GetAttribute method on XPathNavigator. | ||
|  |         /// The problem with using the method directly is that the  | ||
|  |         /// Get Attribute method does not differentiate the absence of an attribute and | ||
|  |         /// having an attribute with Empty string value. In both cases the value returned is an empty string. | ||
|  |         /// So in case of optional attributes, it becomes hard to distinguish the case whether the  | ||
|  |         /// xml contains the attribute with empty string or doesn't contain the attribute | ||
|  |         /// This method will return null if the attribute is not present and otherwise will return the | ||
|  |         /// attribute value. | ||
|  |         /// </summary> | ||
|  |         /// <param name="nav"></param> | ||
|  |         /// <param name="attributeName">name of the attribute</param> | ||
|  |         /// <returns></returns> | ||
|  |         static internal string GetAttributeValue(XPathNavigator nav,  | ||
|  |                                                  string attributeName) | ||
|  |         { | ||
|  |             //Clone the navigator so that there wont be any sideeffects on the passed in Navigator | ||
|  |             nav = nav.Clone(); | ||
|  |             string attributeValue = null; | ||
|  |             if (nav.MoveToAttribute(attributeName, string.Empty)) | ||
|  |             { | ||
|  |                 attributeValue = nav.Value; | ||
|  |             } | ||
|  |             return attributeValue; | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// The method returns typed attribute value of the specified xml attribute. | ||
|  |         /// The method does not do any specific casting but uses the methods on XPathNavigator. | ||
|  |         /// </summary> | ||
|  |         /// <param name="nav"></param> | ||
|  |         /// <param name="attributeName"></param> | ||
|  |         /// <param name="clrType"></param> | ||
|  |         /// <returns></returns> | ||
|  |         internal static object GetTypedAttributeValue(XPathNavigator nav,  | ||
|  |                                                      string attributeName, | ||
|  |                                                      Type clrType)  | ||
|  |         { | ||
|  |             //Clone the navigator so that there wont be any sideeffects on the passed in Navigator | ||
|  |             nav = nav.Clone(); | ||
|  |             object attributeValue = null; | ||
|  |             if (nav.MoveToAttribute(attributeName, string.Empty)) | ||
|  |             { | ||
|  |                 attributeValue = nav.ValueAs(clrType); | ||
|  |             } | ||
|  |             return attributeValue; | ||
|  |         } | ||
|  |          | ||
|  |         /// <summary> | ||
|  |         /// Searches for Facet Description with the name specified.  | ||
|  |         /// </summary> | ||
|  |         /// <param name="facetCollection">Collection of facet description</param> | ||
|  |         /// <param name="facetName">name of the facet</param> | ||
|  |         /// <returns></returns> | ||
|  |         internal static FacetDescription GetFacet(IEnumerable<FacetDescription> facetCollection, string facetName) | ||
|  |         { | ||
|  |             foreach (FacetDescription facetDescription in facetCollection) | ||
|  |             { | ||
|  |                 if (facetDescription.FacetName == facetName) | ||
|  |                 { | ||
|  |                     return facetDescription; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         // requires: firstType is not null | ||
|  |         // effects: Returns true iff firstType is assignable from secondType | ||
|  |         internal static bool IsAssignableFrom(EdmType firstType, EdmType secondType) | ||
|  |         { | ||
|  |             Debug.Assert(firstType != null, "firstType should not be not null"); | ||
|  |             if (secondType == null) | ||
|  |             { | ||
|  |                 return false; | ||
|  |             } | ||
|  |             return firstType.Equals(secondType) || IsSubtypeOf(secondType, firstType); | ||
|  |         } | ||
|  | 
 | ||
|  |         // requires: firstType is not null | ||
|  |         // effects: if otherType is among the base types, return true,  | ||
|  |         // otherwise returns false. | ||
|  |         // when othertype is same as the current type, return false. | ||
|  |         internal static bool IsSubtypeOf(EdmType firstType, EdmType secondType) | ||
|  |         { | ||
|  |             Debug.Assert(firstType != null, "firstType should not be not null"); | ||
|  |             if (secondType == null) | ||
|  |             { | ||
|  |                 return false; | ||
|  |             } | ||
|  | 
 | ||
|  |             // walk up my type hierarchy list | ||
|  |             for (EdmType t = firstType.BaseType; t != null; t = t.BaseType) | ||
|  |             { | ||
|  |                 if (t == secondType) | ||
|  |                     return true; | ||
|  |             } | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static IList GetAllStructuralMembers(EdmType edmType) | ||
|  |         { | ||
|  |             switch (edmType.BuiltInTypeKind) | ||
|  |             { | ||
|  |                 case BuiltInTypeKind.AssociationType: | ||
|  |                     return ((AssociationType)edmType).AssociationEndMembers; | ||
|  |                 case BuiltInTypeKind.ComplexType: | ||
|  |                     return ((ComplexType)edmType).Properties; | ||
|  |                 case BuiltInTypeKind.EntityType: | ||
|  |                     return ((EntityType)edmType).Properties; | ||
|  |                 case BuiltInTypeKind.RowType: | ||
|  |                     return ((RowType)edmType).Properties; | ||
|  |                 default: | ||
|  |                     return EmptyArrayEdmProperty; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static AssociationEndMember GetEndThatShouldBeMappedToKey(AssociationType associationType) | ||
|  |         { | ||
|  |             //For 1:* and 1:0..1 associations, the end other than 1 i.e. either * or 0..1 ends need to be  | ||
|  |             //mapped to key columns | ||
|  |             if (associationType.AssociationEndMembers.Any( it => | ||
|  |                 it.RelationshipMultiplicity.Equals(RelationshipMultiplicity.One))) | ||
|  |             { | ||
|  |                 { | ||
|  |                     return associationType.AssociationEndMembers.SingleOrDefault(it => | ||
|  |                         ((it.RelationshipMultiplicity.Equals(RelationshipMultiplicity.Many)) | ||
|  |                          || (it.RelationshipMultiplicity.Equals(RelationshipMultiplicity.ZeroOrOne)))); | ||
|  |                 } | ||
|  |             } | ||
|  |             //For 0..1:* associations, * end must be mapped to key. | ||
|  |             else if (associationType.AssociationEndMembers.Any(it =>  | ||
|  |                 (it.RelationshipMultiplicity.Equals(RelationshipMultiplicity.ZeroOrOne)))) | ||
|  |             { | ||
|  |                 { | ||
|  |                     return associationType.AssociationEndMembers.SingleOrDefault(it => | ||
|  |                         ((it.RelationshipMultiplicity.Equals(RelationshipMultiplicity.Many)))); | ||
|  |                 } | ||
|  |             }                 | ||
|  |             return null; | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Creates a single comma delimited string given a list of strings | ||
|  |         /// </summary> | ||
|  |         /// <param name="stringList"></param> | ||
|  |         /// <returns></returns> | ||
|  |         internal static String GetCommaDelimitedString(IEnumerable<string> stringList) | ||
|  |         { | ||
|  |             Debug.Assert(stringList != null , "Expecting a non null list"); | ||
|  |             StringBuilder sb = new StringBuilder(); | ||
|  |             bool first = true; | ||
|  |             foreach (string part in stringList) | ||
|  |             { | ||
|  |                 if (!first) | ||
|  |                 { | ||
|  |                     sb.Append(", "); | ||
|  |                 } | ||
|  |                 else | ||
|  |                 { | ||
|  |                     first = false; | ||
|  |                 } | ||
|  |                  | ||
|  |                 sb.Append(part); | ||
|  |             } | ||
|  |             return sb.ToString(); | ||
|  |         } | ||
|  | 
 | ||
|  |          | ||
|  |         // effects: concatenates all given enumerations | ||
|  |         internal static IEnumerable<T> Concat<T>(params IEnumerable<T>[] sources) | ||
|  |         { | ||
|  |             foreach (IEnumerable<T> source in sources) | ||
|  |             { | ||
|  |                 if (null != source) | ||
|  |                 { | ||
|  |                     foreach (T element in source) | ||
|  |                     { | ||
|  |                         yield return element; | ||
|  |                     } | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static void DisposeXmlReaders(IEnumerable<XmlReader> xmlReaders) | ||
|  |         { | ||
|  |             Debug.Assert(xmlReaders != null); | ||
|  | 
 | ||
|  |             foreach (XmlReader xmlReader in xmlReaders) | ||
|  |             { | ||
|  |                 ((IDisposable)xmlReader).Dispose(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         #region IsXXXType Methods | ||
|  |         internal static bool IsStructuralType(EdmType type) | ||
|  |         { | ||
|  |             return (IsComplexType(type) || IsEntityType(type) || IsRelationshipType(type) || IsRowType(type)); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsCollectionType(GlobalItem item) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.CollectionType == item.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsEntityType(EdmType type) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.EntityType == type.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsComplexType(EdmType type) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.ComplexType == type.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsPrimitiveType(EdmType type) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.PrimitiveType == type.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsRefType(GlobalItem item) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.RefType == item.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsRowType(GlobalItem item) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.RowType == item.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsAssociationType(EdmType type) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.AssociationType == type.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsRelationshipType(EdmType type) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.AssociationType == type.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsEdmProperty(EdmMember member) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.EdmProperty == member.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsRelationshipEndMember(EdmMember member) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.AssociationEndMember == member.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsAssociationEndMember(EdmMember member) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.AssociationEndMember == member.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsNavigationProperty(EdmMember member) | ||
|  |         { | ||
|  |             return (BuiltInTypeKind.NavigationProperty == member.BuiltInTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsEntityTypeBase(EdmType edmType) | ||
|  |         { | ||
|  |             return Helper.IsEntityType(edmType) || | ||
|  |                    Helper.IsRelationshipType(edmType); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsTransientType(EdmType edmType) | ||
|  |         { | ||
|  |             return Helper.IsCollectionType(edmType) || | ||
|  |                    Helper.IsRefType(edmType) || | ||
|  |                    Helper.IsRowType(edmType); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsEntitySet(EntitySetBase entitySetBase) | ||
|  |         { | ||
|  |             return BuiltInTypeKind.EntitySet == entitySetBase.BuiltInTypeKind; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsRelationshipSet(EntitySetBase entitySetBase) | ||
|  |         { | ||
|  |             return BuiltInTypeKind.AssociationSet == entitySetBase.BuiltInTypeKind; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsEntityContainer(GlobalItem item) | ||
|  |         { | ||
|  |             return BuiltInTypeKind.EntityContainer == item.BuiltInTypeKind; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsEdmFunction(GlobalItem item) | ||
|  |         { | ||
|  |             return BuiltInTypeKind.EdmFunction == item.BuiltInTypeKind; | ||
|  |         } | ||
|  |                 | ||
|  |         internal static string GetFileNameFromUri(Uri uri) | ||
|  |         { | ||
|  |             if ( uri == null ) | ||
|  |                 throw new ArgumentNullException("uri"); | ||
|  |             if ( uri.IsFile ) | ||
|  |                 return uri.LocalPath; | ||
|  | 
 | ||
|  |             if ( uri.IsAbsoluteUri ) | ||
|  |                 return uri.AbsolutePath; | ||
|  | 
 | ||
|  |             throw new ArgumentException(System.Data.Entity.Strings.UnacceptableUri(uri),"uri"); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsEnumType(EdmType edmType) | ||
|  |         { | ||
|  |             Debug.Assert(edmType != null, "edmType != null"); | ||
|  |             return BuiltInTypeKind.EnumType == edmType.BuiltInTypeKind; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsUnboundedFacetValue(Facet facet) | ||
|  |         { | ||
|  |             return object.ReferenceEquals(facet.Value, EdmConstants.UnboundedValue); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsVariableFacetValue(Facet facet) | ||
|  |         { | ||
|  |             return object.ReferenceEquals(facet.Value, EdmConstants.VariableValue); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsScalarType(EdmType edmType) | ||
|  |         { | ||
|  |             return IsEnumType(edmType) || IsPrimitiveType(edmType); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsSpatialType(PrimitiveType type) | ||
|  |         { | ||
|  |             return IsGeographicType(type) || IsGeometricType(type); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsSpatialType(EdmType type, out bool isGeographic) | ||
|  |         { | ||
|  |             PrimitiveType pt = type as PrimitiveType; | ||
|  |             if (pt == null) | ||
|  |             { | ||
|  |                 isGeographic = false; | ||
|  |                 return false; | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 isGeographic = IsGeographicType(pt); | ||
|  |                 return isGeographic || IsGeometricType(pt); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsGeographicType(PrimitiveType type) | ||
|  |         { | ||
|  |             return IsGeographicTypeKind(type.PrimitiveTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool AreSameSpatialUnionType(PrimitiveType firstType, PrimitiveType secondType) | ||
|  |         { | ||
|  |             // for the purposes of type checking all geographic types should be treated as if they were the Geography union type. | ||
|  |             if (Helper.IsGeographicTypeKind(firstType.PrimitiveTypeKind) && Helper.IsGeographicTypeKind(secondType.PrimitiveTypeKind)) | ||
|  |             { | ||
|  |                 return true; | ||
|  |             } | ||
|  | 
 | ||
|  |             // for the purposes of type checking all geometric types should be treated as if they were the Geometry union type. | ||
|  |             if (Helper.IsGeometricTypeKind(firstType.PrimitiveTypeKind) && Helper.IsGeometricTypeKind(secondType.PrimitiveTypeKind)) | ||
|  |             { | ||
|  |                 return true; | ||
|  |             } | ||
|  | 
 | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsGeographicTypeKind(PrimitiveTypeKind kind) | ||
|  |         { | ||
|  |             return kind == PrimitiveTypeKind.Geography || IsStrongGeographicTypeKind(kind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsGeometricType(PrimitiveType type) | ||
|  |         { | ||
|  |             return IsGeometricTypeKind(type.PrimitiveTypeKind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsGeometricTypeKind(PrimitiveTypeKind kind) | ||
|  |         { | ||
|  |             return kind == PrimitiveTypeKind.Geometry || IsStrongGeometricTypeKind(kind); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsStrongSpatialTypeKind(PrimitiveTypeKind kind) | ||
|  |         { | ||
|  |             return IsStrongGeometricTypeKind(kind) || IsStrongGeographicTypeKind(kind); | ||
|  |         } | ||
|  | 
 | ||
|  |         static bool IsStrongGeometricTypeKind(PrimitiveTypeKind kind) | ||
|  |         { | ||
|  |             return kind >= PrimitiveTypeKind.GeometryPoint && kind <= PrimitiveTypeKind.GeometryCollection; | ||
|  |         } | ||
|  | 
 | ||
|  |         static bool IsStrongGeographicTypeKind(PrimitiveTypeKind kind) | ||
|  |         { | ||
|  |             return kind >= PrimitiveTypeKind.GeographyPoint && kind <= PrimitiveTypeKind.GeographyCollection; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsSpatialType(TypeUsage type) | ||
|  |         { | ||
|  |             return (type.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType && IsSpatialType((PrimitiveType)type.EdmType)); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static bool IsSpatialType(TypeUsage type, out PrimitiveTypeKind spatialType) | ||
|  |         { | ||
|  |             if (type.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType) | ||
|  |             { | ||
|  |                 PrimitiveType primitiveType = (PrimitiveType)type.EdmType; | ||
|  |                 if (IsGeographicTypeKind(primitiveType.PrimitiveTypeKind) || IsGeometricTypeKind(primitiveType.PrimitiveTypeKind)) | ||
|  |                 { | ||
|  |                     spatialType = primitiveType.PrimitiveTypeKind; | ||
|  |                     return true; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             spatialType = default(PrimitiveTypeKind); | ||
|  |             return false; | ||
|  |         } | ||
|  | 
 | ||
|  |         #endregion /// IsXXXType region | ||
|  | 
 | ||
|  |         /// <remarks>Performance of Enum.ToString() is slow and we use this value in building Identity</remarks> | ||
|  |         internal static string ToString(System.Data.ParameterDirection value) | ||
|  |         { | ||
|  |             switch (value) | ||
|  |             { | ||
|  |                 case ParameterDirection.Input: | ||
|  |                     return "Input"; | ||
|  |                 case ParameterDirection.Output: | ||
|  |                     return "Output"; | ||
|  |                 case ParameterDirection.InputOutput: | ||
|  |                     return "InputOutput"; | ||
|  |                 case ParameterDirection.ReturnValue: | ||
|  |                     return "ReturnValue"; | ||
|  |                 default: | ||
|  |                     Debug.Assert(false, "which ParameterDirection.ToString() is missing?"); | ||
|  |                     return value.ToString(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <remarks>Performance of Enum.ToString() is slow and we use this value in building Identity</remarks> | ||
|  |         internal static string ToString(System.Data.Metadata.Edm.ParameterMode value) | ||
|  |         { | ||
|  |             switch (value) | ||
|  |             { | ||
|  |                 case ParameterMode.In: | ||
|  |                     return EdmConstants.In; | ||
|  |                 case ParameterMode.Out: | ||
|  |                     return EdmConstants.Out; | ||
|  |                 case ParameterMode.InOut: | ||
|  |                     return EdmConstants.InOut; | ||
|  |                 case ParameterMode.ReturnValue: | ||
|  |                     return "ReturnValue"; | ||
|  |                 default: | ||
|  |                     Debug.Assert(false, "which ParameterMode.ToString() is missing?"); | ||
|  |                     return value.ToString(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Verifies whether the given <paramref name="typeKind"/> is a valid underlying type for an enumeration type. | ||
|  |         /// </summary> | ||
|  |         /// <param name="typeKind"> | ||
|  |         /// <see cref="PrimitiveTypeKind"/> to verifiy. | ||
|  |         /// </param> | ||
|  |         /// <returns> | ||
|  |         /// <c>true</c> if the <paramref name="typeKind"/> is a valid underlying type for an enumeration type. Otherwise <c>false</c>. | ||
|  |         /// </returns> | ||
|  |         internal static bool IsSupportedEnumUnderlyingType(PrimitiveTypeKind typeKind) | ||
|  |         { | ||
|  |             return typeKind == PrimitiveTypeKind.Byte || | ||
|  |                    typeKind == PrimitiveTypeKind.SByte || | ||
|  |                    typeKind == PrimitiveTypeKind.Int16 || | ||
|  |                    typeKind == PrimitiveTypeKind.Int32 || | ||
|  |                    typeKind == PrimitiveTypeKind.Int64; | ||
|  |         } | ||
|  | 
 | ||
|  |         private static readonly Dictionary<PrimitiveTypeKind, long[]> _enumUnderlyingTypeRanges = | ||
|  |             new Dictionary<PrimitiveTypeKind, long[]> | ||
|  |             { | ||
|  |                 { PrimitiveTypeKind.Byte,  new long[] { Byte.MinValue,  Byte.MaxValue  } }, | ||
|  |                 { PrimitiveTypeKind.SByte, new long[] { SByte.MinValue, SByte.MaxValue } }, | ||
|  |                 { PrimitiveTypeKind.Int16, new long[] { Int16.MinValue, Int16.MaxValue } }, | ||
|  |                 { PrimitiveTypeKind.Int32, new long[] { Int32.MinValue, Int32.MaxValue } }, | ||
|  |                 { PrimitiveTypeKind.Int64, new long[] { Int64.MinValue, Int64.MaxValue } }, | ||
|  |             }; | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Verifies whether a value of a member of an enumeration type is in range according to underlying type of the enumeration type. | ||
|  |         /// </summary> | ||
|  |         /// <param name="underlyingTypeKind">Underlying type of the enumeration type.</param> | ||
|  |         /// <param name="value">Value to check.</param> | ||
|  |         /// <returns> | ||
|  |         /// <c>true</c> if the <paramref name="value"/> is in range of the <paramref name="underlyingTypeKind"/>. <c>false</c> otherwise. | ||
|  |         /// </returns> | ||
|  |         internal static bool IsEnumMemberValueInRange(PrimitiveTypeKind underlyingTypeKind, long value) | ||
|  |         { | ||
|  |             Debug.Assert(IsSupportedEnumUnderlyingType(underlyingTypeKind), "Unsupported underlying type."); | ||
|  | 
 | ||
|  |             return value >= _enumUnderlyingTypeRanges[underlyingTypeKind][0] && value <= _enumUnderlyingTypeRanges[underlyingTypeKind][1]; | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Checks whether the <paramref name="type"/> is enum type and if this is the case returns its underlying type. Otherwise  | ||
|  |         /// returns <paramref name="type"/> after casting it to PrimitiveType. | ||
|  |         /// </summary> | ||
|  |         /// <param name="type">Type to convert to primitive type.</param> | ||
|  |         /// <returns>Underlying type if <paramref name="type"/> is enumeration type. Otherwise <paramref name="type"/> itself.</returns> | ||
|  |         /// <remarks>This method should be called only for primitive or enumeration types.</remarks> | ||
|  |         internal static PrimitiveType AsPrimitive(EdmType type) | ||
|  |         { | ||
|  |             Debug.Assert(type != null, "type != null"); | ||
|  |             Debug.Assert(IsScalarType(type), "This method must not be called for types that are neither primitive nor enums."); | ||
|  | 
 | ||
|  |             return Helper.IsEnumType(type) ? | ||
|  |                 GetUnderlyingEdmTypeForEnumType(type) :  | ||
|  |                 (PrimitiveType)type; | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Returns underlying EDM type of a given enum <paramref name="type"/>. | ||
|  |         /// </summary> | ||
|  |         /// <param name="type">Enum type whose underlying EDM type needs to be returned. Must not be null.</param> | ||
|  |         /// <returns>The underlying EDM type of a given enum <paramref name="type"/>.</returns> | ||
|  |         internal static PrimitiveType GetUnderlyingEdmTypeForEnumType(EdmType type) | ||
|  |         { | ||
|  |             Debug.Assert(type != null, "type != null"); | ||
|  |             Debug.Assert(IsEnumType(type), "This method can be called only for enums."); | ||
|  | 
 | ||
|  |             return ((EnumType)type).UnderlyingType; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static PrimitiveType GetSpatialNormalizedPrimitiveType(EdmType type) | ||
|  |         { | ||
|  |             Debug.Assert(type != null, "type != null"); | ||
|  |             Debug.Assert(IsPrimitiveType(type), "This method can be called only for enums."); | ||
|  |             PrimitiveType primitiveType = (PrimitiveType)type; | ||
|  | 
 | ||
|  |             if (IsGeographicType(primitiveType) && primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Geography) | ||
|  |             { | ||
|  |                 return PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Geography); | ||
|  |             } | ||
|  |             else if (IsGeometricType(primitiveType) && primitiveType.PrimitiveTypeKind != PrimitiveTypeKind.Geometry) | ||
|  |             { | ||
|  |                 return PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Geometry); | ||
|  |             } | ||
|  |             else  | ||
|  |             { | ||
|  |                 return primitiveType; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         #endregion | ||
|  |     } | ||
|  | } |