/// <summary>
 /// Compiles single/plural or value for the given term.
 /// </summary>
 /// <param name="block"></param>
 /// <param name="term"></param>
 private static void Compile(Scope block, TermElement term)
 {
     // single/plural?
     if (!string.IsNullOrEmpty(term.Single) && !string.IsNullOrEmpty(term.Multiple))
     {
         // single/plural
         block.AppendLine("return (plural ? {0} : {1});", Compiler.GetLiteral(term.Multiple), Compiler.GetLiteral(term.Single));
     }
     else
     {
         // value
         block.AppendLine("return {0};", Compiler.GetLiteral(term.Value ?? term.Single));
     }
 }
        /// <summary>
        /// Gets the supportive feature information of all the metadata elements.
        /// Note: This method is only used to validate the term with Core.Tag type.
        /// </summary>
        /// <param name="targetShortName">The short name of target element.</param>
        /// <param name="termElement">The term information which will be validated.</param>
        /// <param name="metadataDoc">The metadata document.</param>
        /// <returns>Returns the validation.</returns>
        private static bool? GetSupportiveFeatureInfo(string targetShortName, TermElement termElement, string metadataDoc)
        {
            if (string.IsNullOrEmpty(targetShortName) || null == termElement || !metadataDoc.IsXmlPayload())
            {
                return null;
            }

            var metadata = XElement.Parse(metadataDoc);
            string aliasTermName = string.Format("{0}.{1}", termElement.Alias, termElement.Name);
            string namespaceTermName = string.Format("{0}.{1}", termElement.Namespace, termElement.Name);

            for (int i = 0; i < termElement.AppliesTo.Length; i++)
            {
                // Get the annotation information from target element in metadata. (e.g. EntitySet)
                string xPath = string.Format("//*[local-name()='{0}' and @Name='{1}']/*[local-name()='Annotation'][@Term='{2}' or @Term='{3}']",
                    termElement.AppliesTo[i],
                    targetShortName,
                    aliasTermName,
                    namespaceTermName);
                var annotationElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                if (null != annotationElement)
                {
                    return null != annotationElement.Attribute("Bool") ?
                        Convert.ToBoolean(annotationElement.Attribute("Bool").Value) :
                        Convert.ToBoolean(termElement.DefaultValue);
                }
                else
                {
                    xPath = string.Format("//*[local-name()='{0}' and @Name='{1}']", termElement.AppliesTo[i], targetShortName);
                    var entitySetElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                    if (null != entitySetElement)
                    {
                        var localAliasNamespace = MetadataHelper.GetAliasAndNamespace(entitySetElement);

                        // Get the annotation information from Annotations element in metadata.
                        xPath = string.Format(
                            "//*[local-name()='Annotations'][@Target='{0}' or @Target='{1}' or @Target='{2}']/*[local-name()='Annotation'][@Term='{3}' or @Term='{4}']",
                            targetShortName,
                            string.Format("{0}.{1}", localAliasNamespace.Alias, targetShortName),
                            string.Format("{0}.{1}", localAliasNamespace.Namespace, targetShortName),
                            aliasTermName,
                            namespaceTermName);
                        annotationElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                        if (null != annotationElement)
                        {
                            return null != annotationElement.Attribute("Bool") ?
                                Convert.ToBoolean(annotationElement.Attribute("Bool").Value) :
                                Convert.ToBoolean(termElement.DefaultValue);
                        }
                    }
                }
            }

            return Convert.ToBoolean(termElement.DefaultValue);
        }
        /// <summary>
        /// Gets the supportive feature information of all the metadata elements.
        /// Note: This method is only used to validate all the terms with enumeration type.
        /// </summary>
        /// <param name="targetShortName">The short name of target element.</param>
        /// <param name="termElement">The term information which will be validated.</param>
        /// <param name="enumTypeElement">The enumeration type template.</param>
        /// <param name="metadataDoc">The metadata document.</param>
        /// <returns>Returns the validation.</returns>
        public static List<KeyValuePair<string, int>> GetSupportiveFeatureInfo(string targetShortName, TermElement termElement, EnumTypeElement enumTypeElement, string metadataDoc)
        {
            if (string.IsNullOrEmpty(targetShortName) || null == termElement || null == enumTypeElement || !metadataDoc.IsXmlPayload())
            {
                return null;
            }

            var metadata = XElement.Parse(metadataDoc);
            string aliasTermName = string.Format("{0}.{1}", termElement.Alias, termElement.Name);
            string namespaceTermName = string.Format("{0}.{1}", termElement.Namespace, termElement.Name);
            List<KeyValuePair<string, int>> result = new List<KeyValuePair<string, int>>();

            for (int i = 0; i < termElement.AppliesTo.Length; i++)
            {
                // Get the annotation information from target element in metadata. (e.g. EntitySet)
                string xPath = string.Format("//*[local-name()='{0}' and @Name='{1}']/*[local-name()='Annotation'][@Term='{2}' or @Term='{3}']/*[local-name()='EnumMember']",
                    termElement.AppliesTo[i],
                    targetShortName,
                    aliasTermName,
                    namespaceTermName);
                var enumMemberElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                if (null != enumMemberElement)
                {
                    string[] enumMembers = enumMemberElement.Value.Split(' ');

                    foreach (var enumMember in enumMembers)
                    {
                        foreach (var m in enumTypeElement.Members)
                        {
                            if (enumMember.Contains(m.Key))
                            {
                                result.Add(new KeyValuePair<string, int>(m.Key, m.Value));
                            }
                        }
                    }
                }
                else
                {
                    xPath = string.Format("//*[local-name()='{0}' and @Name='{1}']", termElement.AppliesTo[i], targetShortName);
                    var entitySetElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                    if (null != entitySetElement)
                    {
                        var localAliasNamespace = MetadataHelper.GetAliasAndNamespace(entitySetElement);

                        // Get the annotation information from Annotations element in metadata.
                        xPath = string.Format(
                            "//*[local-name()='Annotations'][@Target='{0}' or @Target='{1}' or @Target='{2}']/*[local-name()='Annotation'][@Term='{3}' or @Term='{4}']/*[local-name()='EnumMember']",
                            targetShortName,
                            string.Format("{0}.{1}", localAliasNamespace.Alias, targetShortName),
                            string.Format("{0}.{1}", localAliasNamespace.Namespace, targetShortName),
                            aliasTermName,
                            namespaceTermName);
                        enumMemberElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                        if (null != enumMemberElement)
                        {
                            string[] enumMembers = enumMemberElement.Value.Split(' ');

                            foreach (var enumMember in enumMembers)
                            {
                                foreach (var m in enumTypeElement.Members)
                                {
                                    if (enumMember.Contains(m.Key))
                                    {
                                        result.Add(new KeyValuePair<string, int>(m.Key, m.Value));
                                    }
                                }
                            }
                        }
                    }
                }

                if (result.Any())
                {
                    return result;
                }
            }

            return result;
        }
        /// <summary>
        /// Gets the supportive feature information of all the metadata elements.
        /// Note: This method is only used to validate all the terms with complex type.
        /// </summary>
        /// <param name="targetShortName">The short name of target element.</param>
        /// <param name="termElement">The term information which will be validated.</param>
        /// <param name="complexTypeElement">The complex type template.</param>
        /// <param name="metadataDoc">The metadata document.</param>
        /// <returns>Returns the validation.</returns>
        public static ODataComplexType GetSupportiveFeatureInfo(string targetShortName, TermElement termElement, ComplexTypeElement complexTypeElement, string metadataDoc)
        {
            if (string.IsNullOrEmpty(targetShortName) || null == termElement || null == complexTypeElement || !metadataDoc.IsXmlPayload())
            {
                return null;
            }

            ODataComplexType complexType = new ODataComplexType(complexTypeElement.Name);
            var metadata = XElement.Parse(metadataDoc);
            string aliasTermName = string.Format("{0}.{1}", termElement.Alias, termElement.Name);
            string namespaceTermName = string.Format("{0}.{1}", termElement.Namespace, termElement.Name);

            for (int i = 0; i < termElement.AppliesTo.Length; i++)
            {
                #region Gets the inside annotation.
                // Gets the specified annotation which is defined in entity-set element.
                string xPath = string.Format("//*[local-name()='{0}' and @Name='{1}']/*[local-name()='Annotation'][@Term='{2}' or @Term='{3}']",
                        termElement.AppliesTo[i],
                        targetShortName,
                        aliasTermName,
                        namespaceTermName);
                var annotationInside = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);
                #endregion

                #region Gets the outside annotation.
                // Gets the specified annotation which is defined in annotations element.
                XElement annotationOutside = null;
                xPath = string.Format("//*[local-name()='{0}' and @Name='{1}']", termElement.AppliesTo[i], targetShortName);
                var entitySetElement = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);

                if (null != entitySetElement)
                {
                    var localAliasNamespace = MetadataHelper.GetAliasAndNamespace(entitySetElement);

                    xPath = string.Format("//*[local-name()='Annotations'][@Target='{0}' or @Target='{1}' or @Target='{2}']/*[local-name()='Annotation'][@Term='{3}' or @Term='{4}']",
                        targetShortName,
                        string.Format("{0}.{1}", localAliasNamespace.Alias, targetShortName),
                        string.Format("{0}.{1}", localAliasNamespace.Namespace, targetShortName),
                        aliasTermName,
                        namespaceTermName);
                    annotationOutside = metadata.XPathSelectElement(xPath, ODataNamespaceManager.Instance);
                }
                #endregion

                if (null != annotationInside)
                {
                    // Get the annotation information from target element in metadata. (e.g. EntitySet)
                    xPath = ".//*[local-name()='PropertyValue']";
                    var propertyValueElements = annotationInside.XPathSelectElements(xPath, ODataNamespaceManager.Instance);

                    if (null != propertyValueElements && 0 != propertyValueElements.Count())
                    {
                        foreach (var pV in propertyValueElements)
                        {
                            complexType.AddProperty(ODataProperty.Parse(pV, complexTypeElement));
                        }
                    }
                }

                if (null != annotationOutside)
                {
                    // Get the annotation information from Annotations element in metadata.
                    var propertyValueElements = annotationOutside.XPathSelectElements(xPath, ODataNamespaceManager.Instance);

                    if (null != propertyValueElements)
                    {
                        foreach (var pV in propertyValueElements)
                        {
                            complexType.AddProperty(ODataProperty.Parse(pV, complexTypeElement));
                        }
                    }
                }

                if (complexType.GetProperties().Any())
                {
                    return complexType;
                }
            }

            foreach (var prop in complexTypeElement.Properties)
            {
                if (null != prop.DefaultValue && prop.Type.StartsWith("Edm."))
                {
                    complexType.AddProperty(new ODataProperty(prop.Name, prop.DefaultValue, prop.Type));
                }
            }

            return complexType;
        }