private void AddAnnotation(object sender, RoutedEventArgs e)
        {
            // add annotation based on button's tag value.
            Button button     = (Button)sender;
            string actionName = button.Tag as string;

            if (this.document != null && this.document.NativePage != null && this.document.Page != null)
            {
                if (actionName == "star")
                {
                    Annotation starAnnotation = new RubberStampAnnotation(new Boundary(10, 400, 50, 440),
                                                                          AnnotationFlags.Default);
                    FixedContent fixedContent = new FixedContent("ap01", new Boundary(0, 0, 40, 40));
                    fixedContent.Content.AppendImage("star", 0, 0, 40, 40);
                    starAnnotation.Appearance.Normal = fixedContent;
                    this.document.NativePage.Annotations.Add(starAnnotation);

                    this.document.PageViewModel.Annotations.Add(new StarAnnotationViewModel(starAnnotation,
                                                                                            this.document.Page));
                }
                else if (actionName == "smile")
                {
                    Annotation starAnnotation = new RubberStampAnnotation(new Boundary(60, 400, 100, 440),
                                                                          AnnotationFlags.Default);
                    FixedContent fixedContent = new FixedContent("ap01", new Boundary(0, 0, 40, 40));
                    fixedContent.Content.AppendImage("smile", 0, 0, 40, 40);
                    starAnnotation.Appearance.Normal = fixedContent;
                    this.document.NativePage.Annotations.Add(starAnnotation);

                    this.document.PageViewModel.Annotations.Add(new SmileAnnotationViewModel(starAnnotation,
                                                                                             this.document.Page));
                }
                else if (actionName == "text")
                {
                    FreeTextAnnotation textAnnotation = new FreeTextAnnotation(new Boundary(60, 400, 260, 500));

                    string sampleText = "sample text";

                    textAnnotation.Appearance.Normal = AnnotationsHelper.CreateNormalAppearance(sampleText, 200, 100);

                    // set properties affecting default appearance to be used as fallback
                    textAnnotation.FontSize     = 12;
                    textAnnotation.BorderEffect = new AnnotationBorderEffect(AnnotationBorderEffectStyle.NoEffect, 0);
                    textAnnotation.Contents     = sampleText;
                    // text and border color
                    textAnnotation.TextColor = RgbColors.White.Components;
                    // set  background here if needed
                    textAnnotation.Color = RgbColors.Green.Components;

                    this.document.NativePage.Annotations.Add(textAnnotation);

                    this.document.PageViewModel.Annotations.Add(new TextAnnotationViewModel(textAnnotation,
                                                                                            this.document.Page));
                }
            }
        }
Example #2
0
        /// <summary>
        /// Get specified count of entities from first feed of service document.
        /// </summary>
        /// <param name="context">The service document context.</param>
        /// <returns>Returns an entity URLs's list.</returns>
        public static bool GetBatchSupportedEntityUrls(out KeyValuePair <string, IEnumerable <string> > entityUrls)
        {
            entityUrls = new KeyValuePair <string, IEnumerable <string> >();
            var           svcStatus = ServiceStatus.GetInstance();
            List <string> vocDocs   = new List <string>()
            {
                TermDocuments.GetInstance().VocCapabilitiesDoc
            };
            var payloadFormat = svcStatus.ServiceDocument.GetFormatFromPayload();
            var batchSupportedEntitySetUrls  = new List <string>();
            var batchSupportedEntitySetNames = AnnotationsHelper.SelectEntitySetSupportBatch(svcStatus.MetadataDocument, vocDocs);

            batchSupportedEntitySetNames.ForEach(temp => { batchSupportedEntitySetUrls.Add(temp.MapEntitySetNameToEntitySetURL()); });
            var entitySetUrls = ContextHelper.GetFeeds(svcStatus.ServiceDocument, payloadFormat).ToArray();

            if (entitySetUrls.Any())
            {
                string entitySetUrl = string.Empty;
                foreach (var setUrl in entitySetUrls)
                {
                    try
                    {
                        string entityTypeShortName = setUrl.MapEntitySetURLToEntityTypeShortName();
                        if (batchSupportedEntitySetUrls.Contains(setUrl) && !entityTypeShortName.IsMediaType())
                        {
                            entitySetUrl = setUrl;
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                        string test = ex.Message;
                    }
                }

                if (string.IsNullOrEmpty(entitySetUrl))
                {
                    return(false);
                }

                string   url      = string.Format("{0}/{1}?$top=1", svcStatus.RootURL.TrimEnd('/'), entitySetUrl);
                Response response = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, svcStatus.DefaultHeaders);
                payloadFormat = response.ResponsePayload.GetFormatFromPayload();
                var payloadType = ContextHelper.GetPayloadType(response.ResponsePayload, payloadFormat, response.ResponseHeaders);
                if (payloadType == RuleEngine.PayloadType.Feed)
                {
                    entityUrls = new KeyValuePair <string, IEnumerable <string> >(entitySetUrl, ContextHelper.GetEntries(response.ResponsePayload, payloadFormat));

                    return(true);
                }
            }

            return(false);
        }
Example #3
0
        private void OnHostShutdownTriggered()
        {
            log.Info("Hosting shutdown has been initiated. Timeout = {HostingShutdownTimeout}.", totalTimeout);

            if (sendAnnotation)
            {
                AnnotationsHelper.ReportStopping(identity, instanceMetrics);
            }

            hostShutdownBudget.Start();

            ShutdownBeaconAsync().ContinueWith(_ => appShutdown.Initiate(hostShutdownBudget.Remaining));
        }
Example #4
0
        public void checkJavaAttributesDeserialization()
        {
            if (File.Exists(expectedSpringMvcAttributeXmlFile) == false)
            {
                File.Delete(expectedSpringMvcAttributeXmlFile);
                AnnotationsHelper.executeJythonScript(testSpringMvcClassFile);
            }
            Assert.That(File.Exists(expectedSpringMvcAttributeXmlFile), "expectedSpringMvcAttributeXmlFile file did not exist: {0}", expectedSpringMvcAttributeXmlFile);
            var javaAttributeMappings = Serialize.getDeSerializedObjectFromXmlFile(expectedSpringMvcAttributeXmlFile, typeof(JavaAttributeMappings));

            Assert.That(javaAttributeMappings != null, "javaAttributeMappings was null");
            Assert.That(checkThatDeSerializedObjectMatchesXmlFile(expectedSpringMvcAttributeXmlFile, javaAttributeMappings), "checkThatDeSerializedObjectMatchesXmlFile failed");
            DI.log.info("All ok");
        }
Example #5
0
        /*private void handleDrop(DragEventArgs e)
         * {
         *  O2Thread.mtaThread(
         *      ()=>
         *  {
         *      var fileOrFolder = Dnd.tryToGetFileOrDirectoryFromDroppedObject(e);
         *
         *      if (false == loadCirDataFile(fileOrFolder))
         *          // if (false == loadReferenceFindings(fileOrFolder))
         *          loadFileOrFolder(fileOrFolder);
         *  });
         * }*/

        private void handleDropOnDropControl(object oObject, bool processJarFiles, bool deleteTempFiles)
        {
            var workingOnTaskFormName = "Running Spring MVC (Annotations) Analysis Engine";

            O2AscxGUI.workingOnTaskForm_open(workingOnTaskFormName);

            O2Thread.mtaThread(
                () =>
            {
                Processes.Sleep(500);
                try
                {
                    O2AscxGUI.workingOnTaskForm_setText(workingOnTaskFormName, "Prepare files for Analysis (unzip zip, jars, etc..)");
                    var pythonStringTargetFileOrFolder = AnnotationsHelper.getPythonStringTargetFileOrFolder(oObject.ToString(), processJarFiles);
                    //var tempFolder = DI.config.getTempFolderInTempDirectory("unzipedDroppedZip");
                    O2AscxGUI.workingOnTaskForm_setText(workingOnTaskFormName, "Converting files (using Jyhton)");
                    var tempFolderForAnnotationsXmlFiles = AnnotationsHelper.createAnnotationsXmlFilesFromJavaClassFileOrFolder(pythonStringTargetFileOrFolder);
                    var javaXmlFilesToProcess            = AnnotationsHelper.calculateFilesToProcess(oObject.ToString(), tempFolderForAnnotationsXmlFiles);
                    O2AscxGUI.workingOnTaskForm_setText(workingOnTaskFormName, "Creating CirData");
                    var cirData = createCirData(javaXmlFilesToProcess);
                    O2AscxGUI.workingOnTaskForm_setText(workingOnTaskFormName, "Mapping Spring Mvc Controllers");

                    var springMvcControllers = createSpringMvcControlersObjectsFromXmlFiles(javaXmlFilesToProcess);

                    springMvcMappings.loadMappedControllers(cirData, springMvcControllers);
                    //showSpringMvcControllers(springMvcControllers);
                    if (deleteTempFiles)
                    {
                        Files.deleteFolder(tempFolderForAnnotationsXmlFiles, true);
                        Files.deleteFolder(pythonStringTargetFileOrFolder, true);
                    }
                    else
                    {
                        DI.log.info(
                            "Temp files were not deleted:   \n    tempFolderForAnnotationsXmlFiles:{0}\n    pythonStringTargetFileOrFolder:{1} ",
                            tempFolderForAnnotationsXmlFiles, pythonStringTargetFileOrFolder);
                    }
                    O2AscxGUI.workingOnTaskForm_close(workingOnTaskFormName);
                }
                catch (Exception ex)
                {
                    DI.log.error("in handleDropOnDropControl: {0}", ex.Message);
                }
            });
        }
Example #6
0
        [Test]  // the errors that will appear in the logs are because we are not loading the CIR data file, for example "getTreeNodeWithAutoWiredObject, loaded cirData did not contained signature :org.springframework.samples.petclinic.web.EditOwnerForm.setupForm(int;org.springframework.ui.Model):java.lang.String"
        public void viewSpringMvcControllersObjectOnGui()
        {
            if (false == File.Exists(expectedSpringMvcAttributeXmlFile))
            {
                AnnotationsHelper.executeJythonScript(testSpringMvcClassFile);
            }
            // create controllers
            var springMvcControllers = LoadSpringMvcData.createSpringMvcControllersFromXmlAttributeFile(expectedSpringMvcAttributeXmlFile);
            // create Gui
            var viewSpringMvcControllerName = "ascx_CreateSpringMvcMappings";

            O2AscxGUI.openAscxAsForm(typeof(ascx_SpringMvcMappings), viewSpringMvcControllerName);
            var springMvcMappings = (ascx_SpringMvcMappings)O2AscxGUI.getAscx(viewSpringMvcControllerName);

            // load controllers on gui
            springMvcMappings.showSpringMvcControllers(springMvcControllers);
            O2AscxGUI.close();
            //viewSpringMvcController
        }
Example #7
0
        private async Task <VostokApplicationRunResult> RunApplicationAsync()
        {
            log.Info("Running application.");
            ChangeStateTo(VostokApplicationState.Running);

            try
            {
                if (settings.SendAnnotations)
                {
                    AnnotationsHelper.ReportInitialized(environment.ApplicationIdentity, environment.Metrics.Instance);
                }

                return(await RunPhaseAsync(false).ConfigureAwait(false));
            }
            catch (Exception error)
            {
                log.Error(error, "Unhandled exception has occurred while running the application.");
                return(ReturnResult(VostokApplicationState.CrashedDuringRunning, error));
            }
        }
Example #8
0
        public void convertClassFileInto()
        {
            // check that target class and Annotation.py exists
            Assert.That(File.Exists(testSpringMvcClassFile), "could not find test class to for test: {0}", testSpringMvcClassFile);
            Assert.That(File.Exists(AnnotationsHelper.jythonAnnotationScript), "could not find Annotations.py file {0}", AnnotationsHelper.jythonAnnotationScript);

            // exsure expectedSpringMvcAttributeXmlFile is not there
            if (File.Exists(expectedSpringMvcAttributeXmlFile))
            {
                File.Delete(expectedSpringMvcAttributeXmlFile);
            }
            Assert.That(false == File.Exists(expectedSpringMvcAttributeXmlFile), "(at this stage) expected file should not exist: {0}", expectedSpringMvcAttributeXmlFile);

            // convert class file
            var executionResult = AnnotationsHelper.executeJythonScript(testSpringMvcClassFile);

            DI.log.debug("Execution Result: {0}", executionResult);

            Assert.That(File.Exists(expectedSpringMvcAttributeXmlFile), "expected file did not exist: {0}", expectedSpringMvcAttributeXmlFile);
        }
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var expandRestrictions           = AnnotationsHelper.GetExpandRestrictions(context.MetadataDocument, context.VocCapabilities);

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

                return(passed);
            }

            string entitySet = expandRestrictions.Item1;
            string navigProp = expandRestrictions.Item3.First().NavigationPropertyName;
            string url       = string.Format("{0}/{1}", context.ServiceBaseUri, entitySet);
            var    resp      = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            if (null == resp || HttpStatusCode.OK != resp.StatusCode)
            {
                detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                info = new ExtensionRuleViolationInfo(new Uri(url), resp.ResponsePayload, detail);

                return(passed);
            }

            JObject feed;

            resp.ResponsePayload.TryToJObject(out feed);
            var entities = JsonParserHelper.GetEntries(feed);

            if (null == entities || 0 == entities.Count)
            {
                detail.ErrorMessage = string.Format("The entity-set {0} has no entity.", entitySet);
                info = new ExtensionRuleViolationInfo(new Uri(url), resp.ResponsePayload, detail);

                return(passed);
            }

            var    entity    = entities.First;
            string entityURL = null != entity[Constants.V4OdataId] ? entity[Constants.V4OdataId].ToString() : string.Empty;

            if (string.IsNullOrEmpty(entityURL))
            {
                detail.ErrorMessage = "Cannot find the annotation @odata.id in the current entity.";
                info = new ExtensionRuleViolationInfo(new Uri(url), resp.ResponsePayload, detail);

                return(passed);
            }

            url    = string.Format("{0}?$expand={1}/$ref", entityURL, navigProp);
            resp   = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
            detail = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), resp);

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

                if (entry != null && JTokenType.Object == entry.Type)
                {
                    entity = entry[navigProp].First;
                    url    = entity[Constants.V4OdataId].ToString();
                    resp   = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                    if (resp.StatusCode == HttpStatusCode.OK)
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        detail.ErrorMessage = "The service does not execute an accurate result, because the value of the annotation '@odata.id' is a bad link.";
                    }
                }
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not support the '$ref' segment for expanded properties.";
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
Example #10
0
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var filterRestrictions           = AnnotationsHelper.GetFilterRestrictions(context.MetadataDocument, context.VocCapabilities);

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

                return(passed);
            }

            string entitySet         = filterRestrictions.Item1;
            string primitivePropName = filterRestrictions.Item2.First().PropertyName;
            string primitivePropType = filterRestrictions.Item2.First().PropertyType;

            string url  = string.Format("{0}/{1}", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet);
            var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            if (null == resp || HttpStatusCode.OK != resp.StatusCode)
            {
                detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            JObject feed;

            resp.ResponsePayload.TryToJObject(out feed);

            if (feed != null && JTokenType.Object == feed.Type)
            {
                var    entities = JsonParserHelper.GetEntries(feed);
                string propVal  = "Edm.String" == primitivePropType?string.Format("'{0}'", entities[0][primitivePropName].ToString()) : entities[0][primitivePropName].ToString();

                //var req = WebRequest.Create(string.Format("{0}?$filter={1} eq @test1&@test1={2}", url, primitivePropName, propVal)) as HttpWebRequest;;
                //resp = WebHelper.Get(req, RuleEngineSetting.Instance().DefaultMaximumPayloadSize); //REPLACE HEADER

                string requri = string.Format("{0}?$filter={1} eq @test1&@test1={2}", url, primitivePropName, propVal);
                resp   = WebHelper.Get(requri, null, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                detail = new ExtensionRuleResultDetail(this.Name, requri, "GET", string.Empty, resp);

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

                    if (feed1 != null && JTokenType.Object == feed1.Type)
                    {
                        var entities1 = JsonParserHelper.GetEntries(feed1).ToList();
                        var temp      = entities1.FindAll(en => propVal == en[primitivePropName].ToString()).Select(en => en);

                        if (entities1.Count() == temp.Count())
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = "The service does not execute an accurate result on aliases in $filter expressions.";
                        }
                    }
                }
                else
                {
                    passed = false;
                    detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                }
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var restrictions = new Dictionary <string, Tuple <List <NormalProperty>, List <NavigProperty> > >();

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

                return(passed);
            }

            if (!AnnotationsHelper.IsSuitableNavigationProperty(NavigationRoughType.CollectionValued, ref restrictions))
            {
                detail.ErrorMessage = "Cannot find any collection-valued navigation properties in any entity-sets which supports $expand system query options.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string entitySet = string.Empty;
            string navigProp = string.Empty;

            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;
                }

                entitySet = r.Key;

                foreach (var np in r.Value.Item2)
                {
                    navigProp = np.NavigationPropertyName;
                    string nEntityTypeShortName = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                    var    rest = AnnotationsHelper.GetCountRestrictions(context.MetadataDocument, context.VocCapabilities);

                    if (string.IsNullOrEmpty(rest.Item1) ||
                        null == rest.Item2 || !rest.Item2.Any() ||
                        null == rest.Item3 || !rest.Item3.Any())
                    {
                        continue;
                    }

                    break;
                }

                break;
            }

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

                return(passed);
            }

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

                return(passed);
            }

            string   url  = string.Format("{0}/{1}?$expand={2}($count=true)", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet, navigProp);
            Uri      uri  = new Uri(url);
            Response resp = WebHelper.Get(uri, Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            detail                    = new ExtensionRuleResultDetail(this.Name, uri.AbsoluteUri, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), resp);
            detail.URI                = url;
            detail.ResponsePayload    = resp.ResponsePayload;
            detail.ResponseHeaders    = resp.ResponseHeaders;
            detail.HTTPMethod         = "GET";
            detail.ResponseStatusCode = resp.StatusCode.ToString();
            if (resp != null && resp.StatusCode == HttpStatusCode.OK)
            {
                JObject feed;
                resp.ResponsePayload.TryToJObject(out feed);

                if (null == feed)
                {
                    detail.ErrorMessage = "Cannot find any entity-sets in the service.\r\n";
                    info = new ExtensionRuleViolationInfo(uri, resp.ResponsePayload, detail);

                    return(passed);
                }

                JObject entry    = null;
                var     entities = JsonParserHelper.GetEntries(feed);

                foreach (var e in entities)
                {
                    if (null != e[navigProp] && JTokenType.Array == e[navigProp].Type)
                    {
                        entry = e as JObject;
                        break;
                    }
                }

                if (null == entry)
                {
                    detail.ErrorMessage = "Cannot find an appropriate entity which contains at least one collection-valued navigation property.\r\n";
                    info = new ExtensionRuleViolationInfo(uri, resp.ResponsePayload, detail);

                    return(passed);
                }


                if (null != entry && JTokenType.Object == entry.Type)
                {
                    JArray jArr         = entry[navigProp] as JArray;
                    int    actualAmount = 0;
                    JsonParserHelper.GetEntitiesNumFromCollectionValuedNavigProp(entry[Constants.V4OdataId].ToString(), entry, navigProp, context.RequestHeaders, ref actualAmount);

                    if (null != entry[navigProp + Constants.V4OdataCount] && actualAmount == (int)entry[navigProp + Constants.V4OdataCount])
                    {
                        passed = true;
                    }
                    else
                    {
                        passed = false;
                        detail.ErrorMessage = "The service does not execute an accurate result on the system query option '$count' for expanded properties.";
                    }
                }
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not support the system query option '$count' for expanded properties.";
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <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 <ExtensionRuleResultDetail> details = new List <ExtensionRuleResultDetail>();
            ExtensionRuleResultDetail        detail1 = new ExtensionRuleResultDetail(this.Name);
            Tuple <string, List <NormalProperty>, List <NavigProperty> > filterRestrictions = null;

            try
            {
                filterRestrictions = AnnotationsHelper.GetFilterRestrictions(context.MetadataDocument, context.VocCapabilities);
            }
            catch
            {
                detail1.ErrorMessage = "The Metadata is malformed.  Cannot determine the entity-set that supports $filter";
                info   = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);
                passed = false;
                return(passed);
            }


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

                return(passed);
            }

            string entitySet         = filterRestrictions.Item1;
            string primitivePropName = filterRestrictions.Item2.First().PropertyName;
            string primitivePropType = filterRestrictions.Item2.First().PropertyType;

            string url  = string.Format("{0}/{1}", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet);
            var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            if (null == resp || HttpStatusCode.OK != resp.StatusCode)
            {
                detail1.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            JObject feed;

            resp.ResponsePayload.TryToJObject(out feed);

            if (feed != null && JTokenType.Object == feed.Type)
            {
                var    entities = JsonParserHelper.GetEntries(feed);
                string propVal  = entities[0][primitivePropName].ToString();

                #region Equal operation on filter.
                bool?  isEqualOpValidation = null;
                string pattern             = "Edm.String" == primitivePropType ? "{0}/{1}?$filter={2} eq '{3}'" : "{0}/{1}?$filter={2} eq {3}";
                url     = string.Format(pattern, context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet, primitivePropName, propVal);
                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 feed1;
                    resp.ResponsePayload.TryToJObject(out feed1);

                    if (feed1 != null && JTokenType.Object == feed1.Type)
                    {
                        var entities1 = JsonParserHelper.GetEntries(feed1).ToList();
                        var temp      = entities1.FindAll(en => propVal == en[primitivePropName].ToString()).Select(en => en);

                        if (entities1.Count() == temp.Count())
                        {
                            isEqualOpValidation = true;
                        }
                        else
                        {
                            isEqualOpValidation  = false;
                            detail1.ErrorMessage = "The service does not execute an accurate result with system query option $filter eq.";
                            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                            return(isEqualOpValidation);
                        }
                    }
                }
                else
                {
                    passed = false;
                    detail1.ErrorMessage = "Request failed with system query option $filter eq.";
                    info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                    return(passed);
                }
                #endregion

                #region NotEqual operation on filter.
                bool?isNotEqualOpValidation = null;
                pattern = "Edm.String" == primitivePropType ? "{0}/{1}?$filter={2} ne '{3}'" : "{0}/{1}?$filter={2} ne {3}";
                url     = string.Format(pattern, context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet, primitivePropName, propVal);
                resp    = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                ExtensionRuleResultDetail detail2 = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), resp);

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

                    if (feed2 != null && JTokenType.Object == feed2.Type)
                    {
                        var entities2 = JsonParserHelper.GetEntries(feed2).ToList();
                        var temp      = entities2.FindAll(en => propVal != en[primitivePropName].ToString()).Select(en => en);

                        if (entities2.Count() == temp.Count())
                        {
                            isNotEqualOpValidation = true;
                        }
                        else
                        {
                            isNotEqualOpValidation = false;
                            detail2.ErrorMessage   = "The service does not execute an accurate result with system query option $filter ne.";
                        }
                    }
                }
                else
                {
                    passed = false;
                    detail2.ErrorMessage = "Request failed with system query option $filter ne.";
                }
                #endregion

                if (true == isEqualOpValidation && true == isNotEqualOpValidation)
                {
                    passed = true;
                }

                details.Add(detail2);
            }

            details.Insert(0, detail1);
            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, details);

            return(passed);
        }
        /// <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> vocDocs = new List <string>()
            {
                context.VocCapabilities, context.VocCore, context.VocMeasures
            };
            List <string> expectedTypes = new List <string>()
            {
                "Edm.String", "Edm.Int32", "Edm.Int16", "Edm.Single", "Edm.Double", "Edm.Boolean", "Edm.DateTimeOffset", "Edm.Guid"
            };
            List <ExtensionRuleResultDetail> details = new List <ExtensionRuleResultDetail>();
            ExtensionRuleResultDetail        detail  = new ExtensionRuleResultDetail(this.Name);

            var restrictions = new Dictionary <string, Tuple <List <NormalProperty>, List <NavigProperty> > >();

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

                return(passed);
            }

            if (!AnnotationsHelper.IsSuitableNavigationProperty(NavigationRoughType.CollectionValued, ref restrictions))
            {
                detail.ErrorMessage = "Cannot find any collection-valued navigation properties in any entity-sets which supports $expand system query options.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string entitySet             = string.Empty;
            string navigPropName         = string.Empty;
            string primitivePropertyName = string.Empty;
            string primitivePropertyType = string.Empty;

            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;
                }

                foreach (var np in r.Value.Item2)
                {
                    string nEntityTypeShortName = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                    string nEntitySetName       = nEntityTypeShortName.MapEntityTypeShortNameToEntitySetName();
                    var    funcs = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                    {
                        AnnotationsHelper.GetFilterRestrictions
                    };
                    var rest = nEntitySetName.GetRestrictions(context.MetadataDocument, context.VocCapabilities, funcs, expectedTypes);

                    if (string.IsNullOrEmpty(rest.Item1) ||
                        null == rest.Item2 || !rest.Item2.Any() ||
                        null == rest.Item3 || !rest.Item3.Any())
                    {
                        continue;
                    }

                    navigPropName         = np.NavigationPropertyName;
                    primitivePropertyName = rest.Item2.First().PropertyName;
                    primitivePropertyType = rest.Item2.First().PropertyType;

                    break;
                }

                entitySet = r.Key;

                break;
            }

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

                return(passed);
            }

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

                return(passed);
            }

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

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

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

                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.OriginalString.TrimEnd('/'), entitySet, navigPropName, primitivePropertyName, compareVal);
                    var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                    detail = 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;
                                        detail.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;
                        detail.ErrorMessage = string.Format("The service does not support system query option '$filter' on expanded entities.");
                    }
                }
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
Example #14
0
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);

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

            if (string.IsNullOrEmpty(restrictions.Item1) ||
                null == restrictions.Item2 || !restrictions.Item2.Any() ||
                null == restrictions.Item3 || !restrictions.Item3.Any())
            {
                detail.ErrorMessage = "Cannot find an entity-container or any entity-sets which support the change tracking function.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string url = string.Format("{0}/{1}", context.ServiceBaseUri, restrictions.Item1);
            List <KeyValuePair <string, string> > requestHeaders = new List <KeyValuePair <string, string> >();

            foreach (KeyValuePair <string, string> kvp in context.RequestHeaders)
            {
                requestHeaders.Add(new KeyValuePair <string, string>(kvp.Key, kvp.Value));
            }

            // Add odata.track-changes preference in request header.
            KeyValuePair <string, string> prefer = new KeyValuePair <string, string>("Prefer", "odata.track-changes");

            requestHeaders.Add(prefer);
            Response response = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, requestHeaders);

            detail = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.V4AcceptHeaderJsonFullMetadata, requestHeaders), response);

            if (response != null && !string.IsNullOrEmpty(response.ResponseHeaders))
            {
                string preferHeader = response.ResponseHeaders.GetHeaderValue("Preference-Applied");

                if (string.IsNullOrEmpty(preferHeader))
                {
                    passed = false;
                    detail.ErrorMessage = "The response header returned by the service does not contain 'odata.track-changes', when request with the header 'Prefer:odata.track-changes'.";
                }
                else if (preferHeader.Contains("odata.track-changes"))
                {
                    passed = true;
                }
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not support Delta change tracking.";
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
Example #15
0
        /// <summary>
        /// Verifies the service implementation feature.
        /// </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 the service implementation feature passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);

            info   = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            detail = info.Details[0];

            List <string> supportedPropertyTypes = new List <string> {
                PrimitiveDataTypes.Int16, PrimitiveDataTypes.Int32, PrimitiveDataTypes.Int64,
                PrimitiveDataTypes.Decimal, PrimitiveDataTypes.Double
            };

            var filterRestrictions = AnnotationsHelper.GetFilterRestrictionsWithoutNavi(context.MetadataDocument, context.VocCapabilities, supportedPropertyTypes);

            if (string.IsNullOrEmpty(filterRestrictions.Item1) ||
                null == filterRestrictions.Item2 || !filterRestrictions.Item2.Any())
            {
                detail.ErrorMessage = "Cannot find an appropriate entity-set which supports Greater Than system query options in the service.";

                return(passed);
            }

            string entitySet         = filterRestrictions.Item1;
            string primitivePropName = filterRestrictions.Item2.First().PropertyName;

            string url  = string.Format("{0}/{1}", context.ServiceBaseUri, entitySet);
            var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            if (null == resp || HttpStatusCode.OK != resp.StatusCode)
            {
                detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);

                return(passed);
            }

            JObject feed;

            resp.ResponsePayload.TryToJObject(out feed);

            if (feed == null || JTokenType.Object != feed.Type)
            {
                detail.ErrorMessage = "The service does not return a valid response for system query option";
                return(passed);
            }

            var   entities = JsonParserHelper.GetEntries(feed);
            Int64 propVal  = entities[0].Value <Int64>(primitivePropName) - 1;

            string pattern = "{0}/{1}?$filter={2} gt {3}";

            url  = string.Format(pattern, context.ServiceBaseUri, entitySet, primitivePropName, propVal);
            resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            detail.URI                = url;
            detail.HTTPMethod         = "GET";
            detail.RequestHeaders     = StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders);
            detail.ResponseStatusCode = resp != null && resp.StatusCode.HasValue ? resp.StatusCode.Value.ToString() : "";
            detail.ResponseHeaders    = string.IsNullOrEmpty(resp.ResponseHeaders) ? "" : resp.ResponseHeaders;
            detail.ResponsePayload    = string.IsNullOrEmpty(resp.ResponsePayload) ? "" : resp.ResponsePayload;


            if (resp.StatusCode != HttpStatusCode.OK)
            {
                passed = false;
                detail.ErrorMessage = "Request failed with system query option $filter gt.";
                return(passed);
            }

            JObject feed2;

            resp.ResponsePayload.TryToJObject(out feed2);

            if (feed2 == null || JTokenType.Object != feed2.Type)
            {
                passed = false;
                detail.ErrorMessage = "The service does not return a valid response for system query option $filter gt.";
                return(passed);
            }

            var entities2 = JsonParserHelper.GetEntries(feed2).ToList();
            var temp      = entities2.FindAll(en => en.Value <Int64>(primitivePropName) > propVal).Select(en => en);

            if (entities2.Count() == temp.Count())
            {
                passed = true;
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not execute an accurate result with system query option $filter gt.";
            }

            return(passed);
        }
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var countRestrictions            = AnnotationsHelper.GetCountRestrictions(context.MetadataDocument, context.VocCapabilities);

            if (string.IsNullOrEmpty(countRestrictions.Item1))
            {
                detail.ErrorMessage = "Cannot find an entity-set which supports $count system query options.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string   entitySet           = countRestrictions.Item1;
            bool     isNextLinkPropExist = false;
            Int64    totalCount          = 0;
            string   url  = string.Format("{0}/{1}?$count=true", context.ServiceBaseUri.AbsoluteUri.TrimEnd('/'), entitySet);
            Response resp = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            detail = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.V4AcceptHeaderJsonFullMetadata, context.RequestHeaders), resp);

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

                if (feed[Constants.V4OdataCount] != null)
                {
                    totalCount = Convert.ToInt64(feed[Constants.V4OdataCount].Value <string>().StripOffDoubleQuotes());

                    if (entries.Count == totalCount)
                    {
                        passed = true;
                    }
                    else if (entries.Count < totalCount)
                    {
                        var jProps = feed.Children();

                        foreach (JProperty jProp in jProps)
                        {
                            if (jProp.Name == Constants.V4OdataNextLink)
                            {
                                isNextLinkPropExist = true;
                                break;
                            }
                        }

                        if (isNextLinkPropExist)
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = string.Format("The feed has {0} entities totally, but it only display {1} entities and there is no NextLink annotation.", totalCount, entries.Count);
                        }
                    }
                    else
                    {
                        passed = null;
                        detail.ErrorMessage = string.Format("The response of feed {0} has only one page, so can not test partial results.", entitySet);
                    }
                }
                else
                {
                    passed = null;
                    detail.ErrorMessage = string.Format("The response of feed {0} does not have \"@Odata.count\" annotation so it cannot get the total count of entities.", entitySet);
                }
            }
            else
            {
                passed = null;
                detail.ErrorMessage = "Cannot get response from above URI.";
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var filterRestrictions           = AnnotationsHelper.GetFilterRestrictions(context.MetadataDocument, context.VocCapabilities);

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

                return(passed);
            }

            string entitySet         = filterRestrictions.Item1;
            string primitivePropName = filterRestrictions.Item2.First().PropertyName;
            string primitivePropType = filterRestrictions.Item2.First().PropertyType;

            string url  = string.Format("{0}/{1}", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet);
            var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            if (null == resp || HttpStatusCode.OK != resp.StatusCode)
            {
                detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            JObject feed;

            resp.ResponsePayload.TryToJObject(out feed);

            if (feed != null && JTokenType.Object == feed.Type)
            {
                var    entities = JsonParserHelper.GetEntries(feed);
                string propVal  = "Edm.String" == primitivePropType?string.Format("{0}", entities[0][primitivePropName].ToString()) : entities[0][primitivePropName].ToString();

                #region Equal operation on filter.
                url    = string.Format("{0}?$filter={1} eq '{2}'", url, primitivePropName, propVal);
                resp   = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                detail = 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();
                        var temp    = entries.FindAll(en => propVal == en[primitivePropName].ToString()).Select(en => en);

                        if (entries.Count() == temp.Count())
                        {
                            passed = true;
                        }
                        else
                        {
                            passed = false;
                            detail.ErrorMessage = string.Format("The actual result of filter operation is {0}, and the expected result of filter operation is {1}", entities.Count, temp.Count());
                        }
                    }
                }
                else if (resp.StatusCode == HttpStatusCode.NotImplemented)
                {
                    passed = true;
                }
                else
                {
                    passed = false;
                    detail.ErrorMessage = String.Format(JsonParserHelper.GetErrorMessage(resp.ResponsePayload));
                }
                #endregion
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var restrictions = AnnotationsHelper.GetExpandRestrictions(context.MetadataDocument, context.VocCapabilities);

            if (string.IsNullOrEmpty(restrictions.Item1) ||
                null == restrictions.Item3 || !restrictions.Item3.Any())
            {
                detail.ErrorMessage = "Cannot find any appropriate entity-sets which supports $expand system query options.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            // Set a expected level number as 2, and store it in the parameter expectedLevel.
            int    expectedLevels      = 2;
            string entitySetName       = restrictions.Item1;
            string entityTypeShortName = entitySetName.MapEntitySetNameToEntityTypeShortName();

            string[] navigPropNames = MetadataHelper.GetNavigPropNamesRecurseByLevels(entityTypeShortName, context.MetadataDocument, expectedLevels);
            string   url            = string.Format("{0}/{1}?$expand=*($levels={2})", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySetName, expectedLevels);
            var      resp           = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

            detail = new ExtensionRuleResultDetail(this.Name, url, "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 || !entities.Any())
                {
                    detail.ErrorMessage = string.Format("Cannot find any entities from the entity-set '{0}'", entitySetName);
                    info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                    return(passed);
                }

                bool    isFirstLevelEmpty = false;
                int     levelsCounter     = 0;
                JObject entry             = null;

                foreach (var en in entities)
                {
                    levelsCounter     = 0;
                    entry             = en as JObject;
                    isFirstLevelEmpty = false;
                    for (int i = 0; i < expectedLevels; i++)
                    {
                        if (entry != null && JTokenType.Object == entry.Type)
                        {
                            var navigPropVal = entry[navigPropNames[i]];

                            if (navigPropVal != null)
                            {
                                levelsCounter++;
                                entry = navigPropVal.Type == JTokenType.Array ? navigPropVal.First as JObject : navigPropVal as JObject;
                                if (entry == null)
                                {
                                    isFirstLevelEmpty = true;
                                    break;
                                }
                            }
                        }
                    }

                    if (expectedLevels == levelsCounter)
                    {
                        passed = true;
                    }
                    else if (!(levelsCounter < expectedLevels && isFirstLevelEmpty)) // If not no data
                    {
                        passed = false;
                        detail.ErrorMessage = "The service does not execute an accurate result on the system query option '$levels' for expanded properties.";

                        break;
                    }
                }
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not support the system query option '$levels' for expanded properties.";
            }

            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            return(passed);
        }
        /// <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 <ExtensionRuleResultDetail> details = new List <ExtensionRuleResultDetail>();
            ExtensionRuleResultDetail        detail1 = new ExtensionRuleResultDetail(this.Name);
            ExtensionRuleResultDetail        detail2 = new ExtensionRuleResultDetail(this.Name);
            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 supports $expand system query options.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            if (!AnnotationsHelper.IsSuitableNavigationProperty(NavigationRoughType.CollectionValued, ref restrictions))
            {
                detail1.ErrorMessage = "Cannot find any collection-valued navigation properties in any entity-sets which supports $expand system query options.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            string entitySet     = string.Empty;
            string navigPropName = string.Empty;

            #region Verify the system query $top.

            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;
                }

                foreach (var np in r.Value.Item2)
                {
                    string nEntityTypeShortName = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                    string nEntitySetName       = nEntityTypeShortName.MapEntityTypeShortNameToEntitySetName();

                    if (false == nEntitySetName.IsEntitySetSupportTopQuery(context.MetadataDocument, new List <string>()
                    {
                        context.VocCapabilities
                    }))
                    {
                        continue;
                    }

                    navigPropName = np.NavigationPropertyName;
                    break;
                }

                entitySet = r.Key;
                break;
            }

            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))
            {
                detail1.ErrorMessage = "Cannot find any collection-valued navigation properties which support system query options $top.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            bool?  isTopQueryValidation = null;
            string url      = string.Format("{0}/{1}?$expand={2}($top=1)", context.ServiceBaseUri, entitySet, navigPropName);
            var    response = 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), response);

            if (response.StatusCode == HttpStatusCode.OK)
            {
                JObject feed;
                response.ResponsePayload.TryToJObject(out feed);

                if (feed != null && JTokenType.Object == feed.Type)
                {
                    var entities = JsonParserHelper.GetEntries(feed);

                    foreach (var entity in entities)
                    {
                        if (entity[navigPropName] != null)
                        {
                            if (JTokenType.Array == entity[navigPropName].Type && ((JArray)entity[navigPropName]).Count <= 1)
                            {
                                isTopQueryValidation = true;
                            }
                            else
                            {
                                passed = false;
                                detail1.ErrorMessage = "The service does not execute an accurate result on the system query option '$top' for expanded properties.";
                                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                                return(passed);
                            }
                        }
                    }
                }
            }
            else
            {
                passed = false;
                detail1.ErrorMessage = "The service does not support the system query option '$top' for expanded properties.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            #endregion

            #region Verify the system query $skip.

            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;
                }

                foreach (var np in r.Value.Item2)
                {
                    string nEntityTypeShortName = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                    string nEntitySetName       = nEntityTypeShortName.MapEntityTypeShortNameToEntitySetName();

                    if (false == nEntitySetName.IsEntitySetSupportSkipQuery(context.MetadataDocument, new List <string>()
                    {
                        context.VocCapabilities
                    }))
                    {
                        continue;
                    }

                    navigPropName = np.NavigationPropertyName;
                    break;
                }

                entitySet = r.Key;
                break;
            }

            if (string.IsNullOrEmpty(entitySet))
            {
                detail2.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))
            {
                detail2.ErrorMessage = "Cannot find any collection-valued navigation properties which support system query options $skip.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            bool?isSkipQueryValidation = null;
            url      = string.Format("{0}/{1}?$expand={2}($skip=1)", context.ServiceBaseUri, entitySet, navigPropName);
            response = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
            detail2  = new ExtensionRuleResultDetail(this.Name, url, "GET", StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders), response);

            if (response.StatusCode == HttpStatusCode.OK)
            {
                JObject feed;
                response.ResponsePayload.TryToJObject(out feed);

                if (feed != null && JTokenType.Object == feed.Type)
                {
                    var entities = JsonParserHelper.GetEntries(feed);

                    foreach (var entity in entities)
                    {
                        if (entity[navigPropName] != null)
                        {
                            int actualAmount = 0;
                            JsonParserHelper.GetEntitiesNumFromCollectionValuedNavigProp(context.DestinationBasePath, (JObject)entity, navigPropName, context.RequestHeaders, ref actualAmount);

                            if (JTokenType.Array == entity[navigPropName].Type && ((JArray)entity[navigPropName]).Count <= actualAmount)// TODO: This should be justified by total count
                            {
                                isSkipQueryValidation = true;
                            }
                            else
                            {
                                isSkipQueryValidation = false;
                                detail2.ErrorMessage  = "The service does not execute an accurate result on the system query option '$skip' for expanded properties.";
                                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                                return(isSkipQueryValidation);
                            }
                        }
                    }
                }
            }
            else
            {
                passed = false;
                detail2.ErrorMessage = "The service does not support the system query option '$skip' for expanded properties.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail1);

                return(passed);
            }

            #endregion

            if (isTopQueryValidation == true && isSkipQueryValidation == true)
            {
                passed = true;
            }

            details.Add(detail1);
            details.Add(detail2);
            info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, details);

            return(passed);
        }
Example #20
0
        /// <summary>
        /// Verifies the service implementation feature.
        /// </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 the service implementation feature passes; false otherwise</returns>
        public override bool?Verify(ServiceContext context, out ExtensionRuleViolationInfo info)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            bool?passed = null;

            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);

            info   = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);
            detail = info.Details[0];

            List <string> supportedPropertyTypes = new List <string>();

            #region Using ge and le as the single condition

            supportedPropertyTypes.Clear();
            supportedPropertyTypes.AddRange(new List <string> {
                PrimitiveDataTypes.Int16, PrimitiveDataTypes.Int32, PrimitiveDataTypes.Int64,
                PrimitiveDataTypes.Decimal, PrimitiveDataTypes.Double
            });

            var filterRestrictions = AnnotationsHelper.GetFilterRestrictionsWithoutNavi(context.MetadataDocument, context.VocCapabilities, supportedPropertyTypes);

            if (string.IsNullOrEmpty(filterRestrictions.Item1) ||
                null == filterRestrictions.Item2 || !filterRestrictions.Item2.Any())
            {
                detail.ErrorMessage = "Cannot find an appropriate entity-set which supports $filter system query options in the service.";
            }
            else
            {
                string entitySet         = filterRestrictions.Item1;
                string primitivePropName = filterRestrictions.Item2.First().PropertyName;
                string primitivePropType = filterRestrictions.Item2.First().PropertyType;

                string url  = string.Format("{0}/{1}", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet);
                var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                detail.URI                = url;
                detail.ResponsePayload    = resp.ResponsePayload;
                detail.ResponseHeaders    = resp.ResponseHeaders;
                detail.HTTPMethod         = "GET";
                detail.ResponseStatusCode = resp.StatusCode.ToString();

                if (null == resp || HttpStatusCode.OK != resp.StatusCode)
                {
                    passed = false;
                    detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                }
                else
                {
                    JObject feed;
                    resp.ResponsePayload.TryToJObject(out feed);

                    if (feed == null || JTokenType.Object != feed.Type)
                    {
                        passed = false;
                        detail.ErrorMessage = "The service does not return a valid response for system query option";
                    }
                    else
                    {
                        var entities = JsonParserHelper.GetEntries(feed);

                        Int64?propVal = null;
                        for (int n = 0; n < entities.Count; n++)
                        {
                            //if (entities[0].Value != null)
                            {
                                try
                                {
                                    propVal = entities[0].Value <Int64>(primitivePropName) - 1;
                                    break;
                                }
                                catch
                                {
                                }
                            }
                        }

                        if (propVal == null)
                        {
                            detail.ErrorMessage = "Unable to find a suitable property to test.  They have all returned NULL.  Require a Int64 with data";

                            passed = false;
                            return(passed);
                        }

                        //Int64 propVal = entities[0][primitivePropName].Value<Int64>();

                        string pattern = "{0}/{1}?$filter=not {2} eq {3}";
                        url  = string.Format(pattern, context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet, primitivePropName, propVal);
                        resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                        detail.URI                = url;
                        detail.HTTPMethod         = "GET";
                        detail.RequestHeaders     = StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders);
                        detail.ResponseStatusCode = resp != null && resp.StatusCode.HasValue ? resp.StatusCode.Value.ToString() : "";
                        detail.ResponseHeaders    = string.IsNullOrEmpty(resp.ResponseHeaders) ? "" : resp.ResponseHeaders;
                        detail.ResponsePayload    = string.IsNullOrEmpty(resp.ResponsePayload) ? "" : resp.ResponsePayload;

                        if (resp.StatusCode != HttpStatusCode.OK)
                        {
                            passed = false;
                            detail.ErrorMessage = "Request failed with system query option $filter not.";
                        }
                        else
                        {
                            JObject feed1;
                            resp.ResponsePayload.TryToJObject(out feed1);

                            if (feed1 == null || JTokenType.Object != feed1.Type)
                            {
                                passed = false;
                                detail.ErrorMessage = "The service does not return a valid response for system query option $filter not.";
                            }
                            else
                            {
                                var entities1 = JsonParserHelper.GetEntries(feed1).ToList();
                                var temp      = entities1.FindAll(en => (en[primitivePropName].Value <Int64>() == propVal)).Select(en => en);

                                if (temp.Count() == 0)
                                {
                                    passed = true;
                                }
                                else
                                {
                                    passed = false;
                                    detail.ErrorMessage = "The service does not execute an accurate result with system query option $filter not.";
                                }
                            }
                        }
                    }
                }
            }

            #endregion Using ge and le as the single condition

            if (passed.HasValue && passed.Value)
            {
                return(passed);
            }

            #region Using startswith and endswith as the single condition

            supportedPropertyTypes.Clear();
            supportedPropertyTypes.Add(PrimitiveDataTypes.String);

            filterRestrictions = AnnotationsHelper.GetFilterRestrictionsWithoutNavi(context.MetadataDocument, context.VocCapabilities, supportedPropertyTypes);

            if (string.IsNullOrEmpty(filterRestrictions.Item1) ||
                null == filterRestrictions.Item2 || !filterRestrictions.Item2.Any())
            {
                detail.ErrorMessage = "Cannot find an appropriate entity-set which supports $filter system query options in the service.";
            }
            else
            {
                string entitySet         = filterRestrictions.Item1;
                string primitivePropName = filterRestrictions.Item2.First().PropertyName;
                string primitivePropType = filterRestrictions.Item2.First().PropertyType;

                string url  = string.Format("{0}/{1}", context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet);
                var    resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
                detail.URI                = url;
                detail.ResponsePayload    = resp.ResponsePayload;
                detail.ResponseHeaders    = resp.ResponseHeaders;
                detail.HTTPMethod         = "GET";
                detail.ResponseStatusCode = resp.StatusCode.ToString();

                if (null == resp || HttpStatusCode.OK != resp.StatusCode)
                {
                    passed = false;
                    detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                }
                else
                {
                    JObject feed;
                    resp.ResponsePayload.TryToJObject(out feed);

                    if (feed == null || JTokenType.Object != feed.Type)
                    {
                        passed = false;
                        detail.ErrorMessage = "The service does not return a valid response for system query option";
                    }
                    else
                    {
                        var    entities = JsonParserHelper.GetEntries(feed);
                        string propVal  = entities[0][primitivePropName].Value <string>();

                        string pattern = "{0}/{1}?$filter=not endswith({2},'{3}')";
                        url  = string.Format(pattern, context.ServiceBaseUri.OriginalString.TrimEnd('/'), entitySet, primitivePropName, propVal);
                        resp = WebHelper.Get(new Uri(url), Constants.AcceptHeaderJson, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);

                        detail.URI                = url;
                        detail.HTTPMethod         = "GET";
                        detail.RequestHeaders     = StringHelper.MergeHeaders(Constants.AcceptHeaderJson, context.RequestHeaders);
                        detail.ResponseStatusCode = resp != null && resp.StatusCode.HasValue ? resp.StatusCode.Value.ToString() : "";
                        detail.ResponseHeaders    = string.IsNullOrEmpty(resp.ResponseHeaders) ? "" : resp.ResponseHeaders;
                        detail.ResponsePayload    = string.IsNullOrEmpty(resp.ResponsePayload) ? "" : resp.ResponsePayload;

                        if (resp.StatusCode != HttpStatusCode.OK)
                        {
                            passed = false;
                            detail.ErrorMessage = "Request failed with system query option $filter not.";
                        }
                        else
                        {
                            JObject feed1;
                            resp.ResponsePayload.TryToJObject(out feed1);

                            if (feed1 == null || JTokenType.Object != feed1.Type)
                            {
                                passed = false;
                                detail.ErrorMessage = "The service does not return a valid response for system query option $filter not.";
                            }
                            else
                            {
                                var entities1 = JsonParserHelper.GetEntries(feed1).ToList();
                                var temp      = entities1.FindAll(en => en[primitivePropName].Value <string>().EndsWith(propVal)).Select(en => en);

                                if (temp.Count() == 0)
                                {
                                    passed = true;
                                }
                                else
                                {
                                    passed = false;
                                    detail.ErrorMessage = "The service does not execute an accurate result with system query option $filter not.";
                                }
                            }
                        }
                    }
                }
            }

            #endregion Using ge and le as the single condition

            return(passed);
        }
        /// <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;
            ExtensionRuleResultDetail detail = new ExtensionRuleResultDetail(this.Name);
            var restrictions = new Dictionary <string, Tuple <List <NormalProperty>, List <NavigProperty> > >();

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

                return(passed);
            }

            if (!AnnotationsHelper.IsSuitableNavigationProperty(NavigationRoughType.CollectionValued, ref restrictions))
            {
                detail.ErrorMessage = "Cannot find any collection-valued navigation properties in any entity-sets which supports $expand system query options.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string entitySet             = string.Empty;
            string navigPropName         = string.Empty;
            string primitivePropertyName = string.Empty;

            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;
                }

                foreach (var np in r.Value.Item2)
                {
                    string nEntityType = np.NavigationPropertyType.RemoveCollectionFlag().GetLastSegment();
                    var    funcs       = new List <Func <string, string, string, List <NormalProperty>, List <NavigProperty>, bool> >()
                    {
                        AnnotationsHelper.GetFilterRestrictions
                    };
                    var expectedTypes = new List <string>()
                    {
                        "Edm.String"
                    };
                    var props = MetadataHelper.GetNormalProperties(context.MetadataDocument, nEntityType);

                    if (null == props || !props.Any())
                    {
                        continue;
                    }

                    var targetProps = props.Where(p => expectedTypes.Contains(p.PropertyType)).Select(p => p);

                    if (!targetProps.Any())
                    {
                        continue;
                    }

                    navigPropName         = np.NavigationPropertyName;
                    primitivePropertyName = targetProps.First().PropertyName;

                    break;
                }

                entitySet = r.Key;

                if (!string.IsNullOrEmpty(navigPropName) && !string.IsNullOrEmpty(primitivePropertyName))
                {
                    break;
                }
            }

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

                return(passed);
            }

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

                return(passed);
            }

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

                return(passed);
            }

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

            if (null == resp || HttpStatusCode.OK != resp.StatusCode)
            {
                detail.ErrorMessage = JsonParserHelper.GetErrorMessage(resp.ResponsePayload);
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            JObject feed;

            resp.ResponsePayload.TryToJObject(out feed);
            var entities = JsonParserHelper.GetEntries(feed);

            if (null == entities || !entities.Any())
            {
                detail.ErrorMessage = string.Format("Cannot find any entities from the entity-set '{0}'", entitySet);
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            string searchVal = string.Empty;

            foreach (var en in entities)
            {
                if (null != en[navigPropName] || JTokenType.Array == en[navigPropName].Type || en[navigPropName].Any())
                {
                    if (JTokenType.Object != en[navigPropName].First.Type)
                    {
                        break;
                    }

                    var nEntity = en[navigPropName].First as JObject;
                    searchVal = nEntity[primitivePropertyName].ToString().Contains(" ") ?
                                string.Format("\"{0}\"", nEntity[primitivePropertyName].ToString()) :
                                nEntity[primitivePropertyName].ToString();

                    if (!string.IsNullOrEmpty(searchVal))
                    {
                        break;
                    }
                }
            }

            if (string.IsNullOrEmpty(searchVal))
            {
                detail.ErrorMessage = "Cannot find any appropriate search values in the expanded entities.";
                info = new ExtensionRuleViolationInfo(context.Destination, context.ResponsePayload, detail);

                return(passed);
            }

            url    = string.Format("{0}/{1}?$expand={2}($search={3})", context.ServiceBaseUri, entitySet, navigPropName, searchVal);
            resp   = WebHelper.Get(new Uri(url), Constants.V4AcceptHeaderJsonFullMetadata, RuleEngineSetting.Instance().DefaultMaximumPayloadSize, context.RequestHeaders);
            detail = new ExtensionRuleResultDetail(this.Name, url, "GET", String.Empty, resp);

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

                if (null != feed && JTokenType.Object == feed.Type)
                {
                    entities = JsonParserHelper.GetEntries(feed);

                    foreach (var e in entities)
                    {
                        var navigEntities = e[navigPropName].ToList();

                        if (null == navigEntities || !navigEntities.Any())
                        {
                            continue;
                        }

                        foreach (var ne in navigEntities)
                        {
                            passed = null;

                            if (searchVal.StripOffDoubleQuotes() == ne[primitivePropertyName].ToString())
                            {
                                passed = true;
                            }

                            if (passed == null)
                            {
                                passed = false;
                                detail.ErrorMessage = "The service does not execute an accurate result on the system query option '$search' for expanded properties.";
                            }
                        }

                        if (passed == false)
                        {
                            break;
                        }
                    }

                    if (null == passed)
                    {
                        detail.ErrorMessage = "Cannot find any appropriate data to verify this rule.";
                    }
                }
                else
                {
                    detail.ErrorMessage = "The service does not return an correct response payload.";
                }
            }
            else
            {
                passed = false;
                detail.ErrorMessage = "The service does not support the system query option '$search' for expanded properties.";
            }

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