Beispiel #1
0
        /// <summary>
        /// Initialize.
        /// </summary>
        /// <param name="propertyName">The property's name.</param>
        /// <param name="propertyType">The property's primitive type.</param>
        /// <param name="sortedType">The sorted type.</param>
        public JTokenCompare(string propertyName, string propertyType, SortedType sortedType = SortedType.ASC)
        {
            if (string.IsNullOrEmpty(propertyName) || string.IsNullOrEmpty(propertyType))
            {
                throw new ArgumentNullException();
            }

            this.propName   = propertyName;
            this.propType   = propertyType;
            this.sortedType = sortedType;
        }
        /// <summary>
        /// Verify the sequence of two entities.
        /// </summary>
        /// <param name="setOfSortedEntities">The second entity which has been sorted.</param>
        /// <param name="sortedPropName">The property name which will be used to sort the collection of entities.</param>
        /// <param name="sortedPropType">The property type which will be used to sort the collection of entities.</param>
        /// <param name="sortedType">The sorted type (asc or desc).</param>
        /// <returns>Returns the result.</returns>
        private static bool? VerifySortedEntitiesSequence(JObject setOfSortedEntities, string sortedPropName, string sortedPropType, SortedType sortedType)
        {
            if (null == setOfSortedEntities || string.IsNullOrEmpty(sortedPropName) || string.IsNullOrEmpty(sortedPropType))
            {
                return null;
            }

            List<JToken> entities1 = JsonParserHelper.GetEntries(setOfSortedEntities).ToList();
            entities1.Sort(new JTokenCompare(sortedPropName, sortedPropType, sortedType));

            List<JToken> entities2 = JsonParserHelper.GetEntries(setOfSortedEntities).ToList();

            if (entities1.Count == 0 || entities2.Count == 0 || entities1.Count != entities2.Count)
            {
                return null;
            }

            return entities1.SequenceEquals(entities2);
        }
        /// <summary>
        /// Verifies sorting entities order by ascending or descending.
        /// </summary>
        /// <param name="context">The Interop service context.</param>
        /// <param name="sortedType">The sorted type.</param>
        /// <param name="info">Out parameter indicates the extension rule violation information.</param>
        /// <returns>True: The sort validation pass; false: otherwise</returns>
        public static bool? VerifySortEntities(
            ServiceContext context,
            SortedType sortedType,
            out ExtensionRuleViolationInfo info)
        {
            List<JToken> entities1 = null;
            List<JToken> entities2 = new List<JToken>();
            ExtensionRuleResultDetail detail1 = new ExtensionRuleResultDetail();
            string entitySet = string.Empty;
            string navigPropName = string.Empty;
            string sortedPropName = string.Empty;
            string sortedPropType = string.Empty;
            var restrictions = new Dictionary<string, Tuple<List<NormalProperty>, List<NavigProperty>>>();

            if (!AnnotationsHelper.GetExpandRestrictions(context.MetadataDocument, context.VocCapabilities, ref restrictions))
            {
                detail1.ErrorMessage = "Cannot find any appropriate entity-sets which support system query options $expand in the service.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return null;
            }

            foreach (var r in restrictions)
            {
                if (string.IsNullOrEmpty(r.Key) ||
                    null == r.Value.Item1 || !r.Value.Item1.Any() ||
                    null == r.Value.Item2 || !r.Value.Item2.Any())
                {
                    continue;
                }

                bool flag = false;

                foreach (var np in r.Value.Item2)
                {
                    if (NavigationRoughType.CollectionValued == np.NavigationRoughType)
                    {
                        var nEntityTypeShortName = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                        var nEntitySetName = nEntityTypeShortName.MapEntityTypeShortNameToEntitySetName();
                        var funcs = new List<Func<string, string, string, List<NormalProperty>, List<NavigProperty>, bool>>()
                        {
                            AnnotationsHelper.GetFilterRestrictions
                        };
                        List<string> sortedPropTypes = new List<string>()
                        {
                            PrimitiveDataTypes.Binary, PrimitiveDataTypes.Boolean, PrimitiveDataTypes.Byte, PrimitiveDataTypes.Decimal,
                            PrimitiveDataTypes.Double, PrimitiveDataTypes.Guid, PrimitiveDataTypes.Int16, PrimitiveDataTypes.Int32,
                            PrimitiveDataTypes.Int64, PrimitiveDataTypes.SByte, PrimitiveDataTypes.Single, PrimitiveDataTypes.String
                        };
                        var filterRestrictions = nEntitySetName.GetRestrictions(context.MetadataDocument, context.VocCapabilities, funcs, sortedPropTypes);

                        if (!string.IsNullOrEmpty(filterRestrictions.Item1) ||
                            null != filterRestrictions.Item2 || filterRestrictions.Item2.Any() ||
                            null != filterRestrictions.Item3 || filterRestrictions.Item3.Any())
                        {
                            flag = true;
                            entitySet = r.Key;
                            navigPropName = np.NavigationPropertyName;
                            sortedPropName = filterRestrictions.Item2.First().PropertyName;
                            sortedPropType = filterRestrictions.Item2.First().PropertyType;

                            break;
                        }
                    }
                }

                if (flag)
                {
                    break;
                }
            }

            if (string.IsNullOrEmpty(sortedPropName) ||
                string.IsNullOrEmpty(sortedPropType) ||
                string.IsNullOrEmpty(entitySet) ||
                string.IsNullOrEmpty(navigPropName))
            {
                detail1.ErrorMessage = "Cannot find an appropriate entity-set to verify the system query option $orderby.\r\n";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return null;
            }

            string url = string.Format("{0}/{1}?$expand={2}($orderby={3} {4})", context.ServiceBaseUri, entitySet, navigPropName, sortedPropName, sortedType.ToString().ToLower());
            Uri uri = new Uri(url);
            Response resp = WebHelper.Get(uri, Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
            detail1 = new ExtensionRuleResultDetail("", uri.AbsoluteUri, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), resp);

            if (resp != null && resp.StatusCode == HttpStatusCode.OK)
            {
                JObject feed;
                resp.ResponsePayload.TryToJObject(out feed);
                var entities = JsonParserHelper.GetEntries(feed);

                if (null == entities)
                {
                    detail1.ErrorMessage = string.Format("The entity-set '{0}' has no entity in the service.", entitySet);
                    info = new ExtensionRuleViolationInfo(uri, resp.ResponsePayload, detail1);

                    return null;
                }

                foreach (var en in entities)
                {
                    if (null != en[navigPropName] && JTokenType.Array == en[navigPropName].Type)
                    {
                        entities1 = en[navigPropName].ToList();
                        break;
                    }
                }

                entities2.AddRange(entities1);
                entities2.Sort(new JTokenCompare(sortedPropName, sortedPropType, sortedType));
            }
            else
            {
                detail1.ErrorMessage = "The service does not support the system query option '$orderby'.";
                info = new ExtensionRuleViolationInfo(uri, resp.ResponsePayload, detail1);
                return false;
            }

            bool? result = entities1.SequenceEquals(entities2);
            if (result == false)
            {
                detail1.ErrorMessage = string.Format("The service does not support $orderby ({0}) system query options.", sortedType.ToString().ToLower());
            }

            info = new ExtensionRuleViolationInfo(uri, resp.ResponsePayload, detail1);
            return result;
        }
        /// <summary>
        /// Verifies sorting entities order by ascending or descending.
        /// </summary>
        /// <param name="context">The Interop service context.</param>
        /// <param name="sortedType">The sorted type.</param>
        /// <param name="passed">Out parameter indicates validation for sort pass or not</param>
        /// <param name="info">Out parameter indicates the extension rule violation information.</param>
        /// <returns>Returns the HTTP status code of the response.</returns>
        public static HttpStatusCode? VerifySortEntities(ServiceContext context, SortedType sortedType, out bool? passed, out ExtensionRuleViolationInfo info)
        {
            if (SortedType.ASC == sortedType && context.ServiceVerResult.AscSortVerResult != null && context.ServiceVerResult.AscSortVerResult.Passed.HasValue)
            {
                info = context.ServiceVerResult.AscSortVerResult.ViolationInfo;
                passed = context.ServiceVerResult.AscSortVerResult.Passed;
                return context.ServiceVerResult.AscSortVerResult.ResponseStatusCode;
            }
            if (SortedType.DESC == sortedType && context.ServiceVerResult.DescSortVerResult != null && context.ServiceVerResult.DescSortVerResult.Passed.HasValue)
            {
                info = context.ServiceVerResult.DescSortVerResult.ViolationInfo;
                passed = context.ServiceVerResult.DescSortVerResult.Passed;
                return context.ServiceVerResult.DescSortVerResult.ResponseStatusCode;
            }

            passed = null;
            HttpStatusCode? respStatusCode = null;
            ExtensionRuleResultDetail detail1 = new ExtensionRuleResultDetail();
            List<string> sortedPropTypes = new List<string>()
            {
                PrimitiveDataTypes.Binary, PrimitiveDataTypes.Boolean, PrimitiveDataTypes.Byte, PrimitiveDataTypes.Decimal,
                PrimitiveDataTypes.Double, PrimitiveDataTypes.Guid, PrimitiveDataTypes.Int16, PrimitiveDataTypes.Int32,
                PrimitiveDataTypes.Int64, PrimitiveDataTypes.SByte, PrimitiveDataTypes.Single, PrimitiveDataTypes.String
            };

            var restrictions = AnnotationsHelper.GetFilterRestrictions(context.MetadataDocument, context.VocCapabilities, sortedPropTypes);

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

            string entitySet = restrictions.Item1;
            string sortedPropName = restrictions.Item2.First().PropertyName;
            string sortedPropType = restrictions.Item2.First().PropertyType;
            string url = string.Format("{0}/{1}?$orderby={2} {3}", context.ServiceBaseUri, entitySet, sortedPropName, sortedType.ToString().ToLower());
            var resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
            detail1 = new ExtensionRuleResultDetail(string.Empty, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), resp);

            if (resp != null && resp.StatusCode == HttpStatusCode.OK)
            {
                JObject feed;
                resp.ResponsePayload.TryToJObject(out feed);

                if (feed == null || VerifySortedEntitiesSequence(feed, sortedPropName, sortedPropType, sortedType) != true)
                {
                    passed = false;
                    detail1.ErrorMessage = string.Format("The service does not execute an accurate result on the system query option $orderby {0} on individual properties.", sortedType == SortedType.ASC ? "asc" : "desc");
                }
                else
                {
                    passed = true;
                }
            }
            else
            {
                passed = false;
                detail1.ErrorMessage = "The service does not support the system query option '$orderby'.";
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);
            respStatusCode = resp != null ? resp.StatusCode : null;

            if (SortedType.ASC == sortedType)
            {
                context.ServiceVerResult.AscSortVerResult = new ServiceVerificationResult(passed, info, respStatusCode);
            }
            else if (SortedType.DESC == sortedType)
            {
                context.ServiceVerResult.DescSortVerResult = new ServiceVerificationResult(passed, info, respStatusCode);
            }

            return respStatusCode;
        }
 public IntegerCompare(SortedType sortedType)
 {
     this.type = sortedType;
 }