/// <summary>
        /// Verifies the extension rule.
        /// </summary>
        /// <param name="context">The Interop service context</param>
        /// <param name="info">out parameter to return violation information when rule does not pass</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;
            List <string> expectedTypes = new List <string>()
            {
                "Edm.String", "Edm.Int32", "Edm.Int16", "Edm.Single", "Edm.Double", "Edm.Boolean", "Edm.DateTimeOffset", "Edm.Guid"
            };
            ExtensionRuleResultDetail detail1 = new ExtensionRuleResultDetail(this.Name);

            var restrictions = AnnotationsHelper.GetRestrictions(
                context.MetadataDocument,
                context.VocCapabilities,
                new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
            {
                AnnotationsHelper.GetExpandRestrictions, AnnotationsHelper.GetFilterRestrictions
            },
                null,
                NavigationRoughType.CollectionValued);

            if (string.IsNullOrEmpty(restrictions.Item1) ||
                null == restrictions.Item2 || !restrictions.Item2.Any() ||
                null == restrictions.Item3 || !restrictions.Item3.Any())
            {
                detail1.ErrorMessage = "Cannot find an appropriate entity-set which supports $expand, $filter system query options in the service.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            string entitySet     = restrictions.Item1;
            string navigPropName = string.Empty;
            string navigPropType = string.Empty;

            foreach (var np in restrictions.Item3)
            {
                if (NavigationRoughType.CollectionValued == np.NavigationRoughType)
                {
                    navigPropName = np.NavigationPropertyName;
                    navigPropType = np.NavigationPropertyType;
                }
            }

            string entityType = navigPropType.RemoveCollectionFlag().GetLastSegment();
            var    tmp        = MetadataHelper.GetPropertiesWithSpecifiedTypeFromEntityType(entityType, context.MetadataDocument, expectedTypes);

            if (null == tmp && !tmp.Any())
            {
                detail1.ErrorMessage = "Cannot find an appropriate primitive properties of entity type in the service.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            var    str = tmp.First().Split(',');
            string primitivePropertyName = str[0];
            string primitivePropertyType = str[1];

            if (string.IsNullOrEmpty(entitySet))
            {
                detail1.ErrorMessage = "Cannot find an appropriate entity-set which supports $expand system query option.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            if (string.IsNullOrEmpty(navigPropName) || string.IsNullOrEmpty(navigPropType))
            {
                detail1.ErrorMessage = "Cannot get expanded entities because cannot get collection type of navigation property from metadata";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            if (string.IsNullOrEmpty(primitivePropertyName) || string.IsNullOrEmpty(primitivePropertyType))
            {
                detail1.ErrorMessage = "Cannot get an appropriate primitive property from navigation properties.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            Uri uri      = new Uri(string.Format("{0}/{1}?$expand={2}", context.ServiceBaseUri, entitySet, navigPropName));
            var response = WebHelper.Get(uri, Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            if (HttpStatusCode.OK != response.StatusCode)
            {
                passed = false;
                detail1.ErrorMessage = JsonParserHelper.GetErrorMessage(response.ResponsePayload);
                info = new ExtensionRuleViolationInfo(uri, response.ResponsePayload, detail1);

                return(passed);
            }

            JObject feed;

            response.ResponsePayload.TryToJObject(out feed);

            if (feed != null && JTokenType.Object == feed.Type)
            {
                var entities  = JsonParserHelper.GetEntries(feed);
                var navigProp = entities[0][navigPropName] as JArray;

                if (navigProp != null && navigProp.Count != 0)
                {
                    string propVal    = navigProp[0][primitivePropertyName].ToString();
                    string compareVal = propVal;

                    if (primitivePropertyType.Equals("Edm.String"))
                    {
                        compareVal = "'" + propVal + "'";
                    }

                    string url  = string.Format("{0}/{1}?$expand={2}($filter={3} eq {4})", context.ServiceBaseUri, entitySet, navigPropName, primitivePropertyName, compareVal);
                    var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                    detail1 = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), resp);

                    if (resp.StatusCode == HttpStatusCode.OK)
                    {
                        JObject jObj;
                        resp.ResponsePayload.TryToJObject(out jObj);

                        if (jObj != null && JTokenType.Object == jObj.Type)
                        {
                            var entries = JsonParserHelper.GetEntries(jObj).ToList();

                            foreach (var entry in entries)
                            {
                                if (entry[navigPropName] != null && ((JArray)entry[navigPropName]).Count == 0)
                                {
                                    continue;
                                }
                                else if (entry[navigPropName] != null && ((JArray)entry[navigPropName]).Count > 0)
                                {
                                    var temp = entry[navigPropName].ToList()
                                               .FindAll(en => propVal == en[primitivePropertyName].ToString())
                                               .Select(en => en);

                                    if (entry[navigPropName].ToList().Count == temp.Count())
                                    {
                                        passed = true;
                                    }
                                    else
                                    {
                                        passed = false;
                                        detail1.ErrorMessage = string.Format("The service does not execute an accurate result on system query option '$filter' (Actual Value: {0}, Expected Value: {1}).", entry[navigPropName].ToList().Count, temp.Count());
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        passed = false;
                        detail1.ErrorMessage = "The service does not support system query option '$filter' on expanded entities.";
                    }
                }
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);
            return(passed);
        }