/// <summary>
        /// Verify the code rule
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater to return violation information when rule fail</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            var     edmxHelper = new EdmxHelper(XElement.Parse(context.MetadataDocument));
            var     segments   = ResourcePathHelper.GetPathSegments(context);
            UriType uriType;
            var     target = edmxHelper.GetTargetType(segments, out uriType);

            // to check this rule only when returned resource is collection of ComplexType
            if (uriType == UriType.URI11)
            {
                JObject jo      = JObject.Parse(context.ResponsePayload);
                var     version = JsonParserHelper.GetPayloadODataVersion(jo);

                string     jSchema = JsonSchemaHelper.WrapJsonSchema(coreSchema, version);
                TestResult testResult;
                passed = JsonParserHelper.ValidateJson(jSchema, context.ResponsePayload, out testResult);
                if (passed.HasValue && !passed.Value)
                {
                    info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, testResult != null ? testResult.LineNumberInError : -1);
                }
            }

            return(passed);
        }
        /// <summary>
        /// Verify the rule
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater to return violation information when rule fail</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            var    qs      = HttpUtility.ParseQueryString(context.Destination.Query);
            string qExpand = qs["$expand"];

            if (!string.IsNullOrEmpty(qExpand))
            {
                JObject jo      = JObject.Parse(context.ResponsePayload);
                var     version = JsonParserHelper.GetPayloadODataVersion(jo);

                var        edmxHelper = new EdmxHelper(XElement.Parse(context.MetadataDocument));
                EntityType et;
                edmxHelper.TryGetItem(context.EntityTypeFullName, out et);

                var branches = ResourcePathHelper.GetBranchedSegments(qExpand);
                foreach (var paths in branches)
                {
                    var    navStack           = ODataUriAnalyzer.GetNavigationStack(et, paths).ToArray();
                    bool[] targetIsCollection = (from n in navStack select n.RelationshipMultiplicity == RelationshipMultiplicity.Many).ToArray();

                    // to verify each single entity type expanded along the navigation path to have proper properties
                    TestResult result = null;
                    for (int i = 0; i < paths.Length; i++)
                    {
                        string jSchema = null;

                        if (!targetIsCollection[i])
                        {
                            var    etShort = navStack[i].GetEntityType().FullName.GetLastSegment();
                            string jsET    = JsonSchemaHelper.GetSchemaForEntityType(etShort, context.MetadataDocument);
                            string jsCore  = string.Format(@"""{0}"" : {1}", paths[i], jsET);
                            jSchema = JsonSchemaHelper.GetJsonSchema(paths, i, version, jsCore, targetIsCollection);

                            passed = JsonParserHelper.ValidateJson(jSchema, context.ResponsePayload, out result);
                            if (!passed.Value)
                            {
                                break;
                            }
                        }
                    }

                    if (!passed.Value)
                    {
                        info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, result != null ? result.LineNumberInError : -1);
                        break;
                    }
                }
            }

            return(passed);
        }
        /// <summary>
        /// Verify the rule
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater to return violation information when rule fail</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            var    qs        = HttpUtility.ParseQueryString(context.Destination.Query);
            string qExpand   = qs["$expand"];
            var    branches  = ResourcePathHelper.GetBranchedSegments(qExpand);
            var    brHeaders = from br in branches select br.FirstOrDefault();

            // to get collection of navigatio properties which is not expanded
            List <string> navProps = new List <string>();
            XElement      meta     = XElement.Parse(context.MetadataDocument);
            const string  fmtXPathToTypeProperty = "//*[local-name()='Schema' and @Namespace='{0}']/*[local-name()='EntityType' and @Name='{1}']/*[local-name()='NavigationProperty' and @Name]";
            string        xpath = string.Format(fmtXPathToTypeProperty, ResourcePathHelper.GetNamespaceName(context.EntityTypeFullName), ResourcePathHelper.GetBaseName(context.EntityTypeFullName));
            var           nodes = meta.XPathSelectElements(xpath);

            foreach (var n in nodes)
            {
                var name = ResourcePathHelper.GetBaseName(n.Attribute("Name").Value);
                if (!brHeaders.Any(x => x.Equals(name, StringComparison.Ordinal)))
                {
                    navProps.Add(name);
                }
            }

            if (navProps.Count() > 0)
            {
                JObject jo      = JObject.Parse(context.ResponsePayload);
                var     version = JsonParserHelper.GetPayloadODataVersion(jo);

                var    propSchemas    = navProps.Select(x => string.Format(fmtCore, x));
                string coreProperties = string.Join("\r\n,", propSchemas);
                string CoreObject     = string.Format(fmtObj, coreProperties);
                string jSchema        = JsonSchemaHelper.WrapJsonSchema(CoreObject, version);

                TestResult result;
                passed = JsonParserHelper.ValidateJson(jSchema, context.ResponsePayload, out result);
                if (!passed.HasValue)
                {
                    info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, result != null ? result.LineNumberInError : -1);
                }
            }

            return(passed);
        }
        /// <summary>
        /// Verify the rule
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out parameter to return violation information when rule fail</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            // if __metadata.etag property is there, ensure its value equals to ETag header value
            var  entry       = JsonParserHelper.GetResponseObject(context);
            var  etag        = entry.GetPropertyOfChild("__metadata", "etag");
            bool etagInPlace = etag != null;

            if (etagInPlace)
            {
                var etagInHeader             = context.ResponseHttpHeaders.GetHeaderValue("ETag").Trim();
                var etagLiteral              = StringHelper.ToLiteral(etagInHeader);
                RuleEngine.TestResult result = null;

                ODataVersion version = JsonParserHelper.GetPayloadODataVersion(entry);
                switch (version)
                {
                case ODataVersion.V1:
                    string schemaV1 = string.Format(EntryCore2009.schemaFormat_v1, etagLiteral);
                    passed = JsonParserHelper.ValidateJson(schemaV1, context.ResponsePayload, out result);
                    break;

                case ODataVersion.V2:
                    string schemaV2 = string.Format(EntryCore2009.schemaFormat_v2, etagLiteral);
                    passed = JsonParserHelper.ValidateJson(schemaV2, context.ResponsePayload, out result);
                    break;

                default:
                    passed = false;
                    break;
                }

                if (!passed.Value)
                {
                    info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, result != null ? result.LineNumberInError : -1);
                }
            }

            return(passed);
        }
        /// <summary>
        /// Verify the code rule
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater to return violation information when rule fail</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            var     edmxHelper = new EdmxHelper(XElement.Parse(context.MetadataDocument));
            var     segments   = ResourcePathHelper.GetPathSegments(context);
            UriType uriType;
            var     target = edmxHelper.GetTargetType(segments, out uriType);

            // to check this rule only when returned resource is a ComplexType
            if (uriType == UriType.URI3 || uriType == UriType.URI12)
            {
                JObject jo      = JObject.Parse(context.ResponsePayload);
                var     version = JsonParserHelper.GetPayloadODataVersion(jo);

                ComplexType ct      = (uriType == UriType.URI12) ? (ComplexType)target : (ComplexType)((EdmProperty)target).TypeUsage.EdmType;
                var         props   = from p in ct.Properties select p.Name;
                var         jsProps = props.Select(x => string.Format(@"""{0}"" : {{""required"" : false }}", x));
                string      jsCore  = string.Format(fmtCoreSchema, ct.Name, string.Join(",", jsProps.ToArray()));
                string      jSchema = JsonSchemaHelper.WrapJsonSchema(jsCore, version);
                TestResult  result;
                passed = JsonParserHelper.ValidateJson(jSchema, context.ResponsePayload, out result);
                if (passed.HasValue && !passed.Value)
                {
                    info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, result != null ? result.LineNumberInError : -1);
                }
            }

            return(passed);
        }
        /// <summary>
        /// Verify the code rule
        /// </summary>
        /// <param name="context">Service context</param>
        /// <param name="info">out paramater to return violation information when rule fail</param>
        /// <returns>true if rule passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            info = null;

            // for each entry within the collection (feed)
            // to check its __metadata.etag value (if existent) is the same as ETag header in the single entry response that would have been requested
            JObject feed;

            context.ResponsePayload.TryToJObject(out feed);
            ODataVersion version    = JsonParserHelper.GetPayloadODataVersion(feed);
            var          entries    = JsonParserHelper.GetEntries(feed);
            int          indexEntry = 0;
            int          count      = entries.Count;

            foreach (JObject e in entries)
            {
                var  etag        = e.GetPropertyOfElement("__metadata", "etag");
                bool etagInPlace = etag != null;
                if (etagInPlace)
                {
                    var targetSingleEntry = e.GetPropertyOfElement("__metadata", "uri");
                    // get the ETag header value for the entry
                    var etagInSingleEntry = WebResponseHelper.GetETagOfEntry(targetSingleEntry, Constants.AcceptHeaderAtom);

                    JSconSchemaBuilder builder;
                    if (version == ODataVersion.V2)
                    {
                        builder = new JSconSchemaBuilder(jschemaV2Header, jschemaV2Tail);
                    }
                    else
                    {
                        builder = new JSconSchemaBuilder(jschemaV1Header, jschemaV1Tail);
                    }

                    for (int i = 0; i < indexEntry; i++)
                    {
                        builder.AddItem("{},");
                    }

                    var    etagLiteral = StringHelper.ToLiteral(etagInSingleEntry);
                    string entryCore   = string.Format(entryCoreFormat, etagLiteral);
                    builder.AddItem(entryCore);

                    for (int i = indexEntry + 1; i < count; i++)
                    {
                        builder.AddItem(",{}");
                    }

                    var jSchema = builder.GetProduct();
                    RuleEngine.TestResult result = null;
                    passed = JsonParserHelper.ValidateJson(jSchema, context.ResponsePayload, out result);
                    if (!passed.Value)
                    {
                        info = new ExtensionRuleViolationInfo(this.ErrorMessage, context.Destination, context.ResponsePayload, result != null ? result.LineNumberInError : -1);
                        break;
                    }
                }

                indexEntry++;
            }

            return(passed);
        }