/// <summary>
        /// Get all the properties from EntityType element in metadata.
        /// </summary>
        /// <param name="metadata">The whole metadata data.</param>
        /// <param name="entityTypeShortName">The short name of entity type.</param>
        /// <param name="mpType">The matching property type.</param>
        /// <returns>Returns all the properties of an entity.</returns>
        public static List<XElement> GetAllPropertiesOfEntity(string metadata, string entityTypeShortName, MatchPropertyType mpType)
        {
            if (metadata == null || metadata == string.Empty || entityTypeShortName == null || entityTypeShortName == string.Empty)
            {
                return null;
            }

            string xpath1 = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']", entityTypeShortName);
            string xpath2 = string.Empty;
            XElement md = XElement.Parse(metadata);
            var entity = md.XPathSelectElement(xpath1, ODataNamespaceManager.Instance);

            if (entity != null)
            {
                string baseTypeFullName = entity.Attribute(@"BaseType") != null ? entity.Attribute(@"BaseType").Value : string.Empty;
                string ns = entity.Parent.Attribute("Namespace").Value;
                string baseTypeShortName =
                    baseTypeFullName.Contains(@".") ?
                    baseTypeFullName.Remove(0, ns.Length + 1) :
                    baseTypeFullName;

                switch (mpType)
                {
                    default:
                    case MatchPropertyType.Normal:
                        xpath1 = @"./*[local-name()='Property']";
                        xpath2 = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='Property']", baseTypeShortName);
                        break;
                    case MatchPropertyType.Navigations:
                        xpath1 = @"./*[local-name()='NavigationProperty']";
                        xpath2 = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='NavigationProperty']", baseTypeShortName);
                        break;
                    case MatchPropertyType.All:
                        xpath1 = @"./*[local-name()='Property' or local-name()='NavigationProperty']";
                        xpath2 = string.Format(@"//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='Property' or local-name()='NavigationProperty']", baseTypeShortName);
                        break;
                }

                var currentEntityProps = entity.XPathSelectElements(xpath1, ODataNamespaceManager.Instance);
                var baseEntityProps = baseTypeFullName != string.Empty ? md.XPathSelectElements(xpath2, ODataNamespaceManager.Instance) : null;

                return baseEntityProps != null ? baseEntityProps.Concat(currentEntityProps).ToList() : currentEntityProps.ToList();
            }
            else
            {
                return new List<XElement>();
            }
        }
        /// <summary>
        /// Get property names of a EntityType or ComplexType.
        /// </summary>
        /// <param name="metadata">The metadata document.</param>
        /// <param name="@namespace">The namespace of the StructuredType.</param>
        /// <param name="complexName">The short name of the StructuredType.</param>
        /// <param name="mpType">The property type to get.</param>
        /// <returns>The dictionay of property name and its type.</returns>
        public static List<string> GetAllPropertiesNamesOfStructuredType(string metadata, string @namespace, string complexName, MatchPropertyType mpType)
        {
            if (string.IsNullOrEmpty(metadata) || string.IsNullOrEmpty(complexName) || string.IsNullOrEmpty(@namespace))
            {
                return null;
            }

            string basePath = @"./*[local-name()='DataServices']/*[local-name()='Schema' and (@Namespace='{0}' or @Alias='{1}')]";

            string xpath = string.Format(basePath, @namespace, @namespace) + string.Format(@"/*[@Name='{0}']", complexName);

            XElement md = XElement.Parse(metadata);
            XElement structuredType = md.XPathSelectElement(xpath, ODataNamespaceManager.Instance);
            List<string> propertiesNames = new List<string>();

            // Get base type name and namespace.
            if (structuredType != null)
            {
                string baseTypeName = string.Empty;
                string baseTypeNs = string.Empty;
                if (!string.IsNullOrEmpty(structuredType.GetAttributeValue(@"BaseType")))
                {
                    string fullname = structuredType.GetAttributeValue(@"BaseType");
                    int dotIndex = structuredType.GetAttributeValue(@"BaseType").LastIndexOf('.');
                    if (dotIndex != -1 && dotIndex != 0 && dotIndex != fullname.Length - 1)
                    {
                        baseTypeNs = fullname.Substring(0, dotIndex);
                        baseTypeName = fullname.Substring(dotIndex + 1);
                    }
                }

                // Get the XPath for properties.
                string currentTypePath;
                string baseTypePath = string.Empty;
                switch (mpType)
                {
                    case MatchPropertyType.All:
                        currentTypePath = @"./*[local-name()='Property' or local-name()='NavigationProperty']";
                        if (string.IsNullOrEmpty(baseTypeName)) { break; }
                        baseTypePath = string.Format(basePath, baseTypeNs, baseTypeNs)
                            + string.Format(@"/*[local-name()='{0}' and @Name='{1}']/*[local-name()='Property' or local-name()='NavigationProperty']", structuredType.Name, baseTypeName);
                        break;
                    case MatchPropertyType.Navigations:
                        currentTypePath = @"./*[local-name()='NavigationProperty']";
                        if (string.IsNullOrEmpty(baseTypeName)) { break; }
                        baseTypePath = string.Format(basePath, baseTypeNs, baseTypeNs)
                            + string.Format(@"/*[local-name()='{0}' and @Name='{1}']/*[local-name()='NavigationProperty']", structuredType.Name, baseTypeName);
                        break;
                    case MatchPropertyType.Normal:
                        currentTypePath = @"./*[local-name()='Property']";
                        if (string.IsNullOrEmpty(baseTypeName)) { break; }
                        baseTypePath = string.Format(basePath, baseTypeNs, baseTypeNs)
                            + string.Format(@"/*[local-name()='{0}' and @Name='{1}']/*[local-name()='Property']", structuredType.Name, baseTypeName);
                        break;
                    default:
                        return null;
                }

                IEnumerable<XElement> currentComplexTypeProperties = structuredType.XPathSelectElements(currentTypePath, ODataNamespaceManager.Instance);
                IEnumerable<XElement> baseComplexTypeProperties = string.IsNullOrEmpty(baseTypeName) ? null : md.XPathSelectElements(baseTypePath, ODataNamespaceManager.Instance);
                IEnumerable<XElement> total = baseComplexTypeProperties != null ? currentComplexTypeProperties.Concat(baseComplexTypeProperties) : currentComplexTypeProperties;

                foreach (XElement xe in total)
                {
                    propertiesNames.Add(xe.GetAttributeValue("Name"));
                }
            }

            return propertiesNames;
        }