Beispiel #1
0
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            XmlRewriteElementAnnotation annotation = new XmlRewriteElementAnnotation()
            {
                RewriteFunction = (node) =>
                {
                    XNode foundNode   = null;
                    var   currentNode = node.FirstNode;
                    if (node.Nodes().Count() > 1)
                    {
                        while (currentNode != null && foundNode == null)
                        {
                            var element = (XElement)currentNode;
                            if (element.Name.LocalName.Equals("id"))
                            {
                                foundNode = currentNode;
                                currentNode.Remove();
                            }
                            currentNode = currentNode.NextNode;
                        }

                        if (foundNode != null)
                        {
                            node.FirstNode.AddBeforeSelf(foundNode);
                        }
                    }

                    return(node);
                }
            };

            payloadElement.Add(annotation);
            base.Visit(payloadElement);
        }
Beispiel #2
0
        /// <summary>
        /// Visits an entity set instance: creates a new ODataFeed instance, calls ODataWriter.WriteStart()
        /// before visiting the entries and then calls ODataWriter.WriteEnd()
        /// </summary>
        /// <param name="payloadElement">The entity set instance to write.</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            // create an ODataFeed and write it
            ODataFeed feed = new ODataFeed()
            {
                // NOTE: the required Id is set when processing the annotations in AddFeedMetadata()
                Count             = payloadElement.InlineCount,
                SerializationInfo = new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceEntityTypeName = "Null",
                    NavigationSourceName           = "MySet",
                    ExpectedTypeName = "Null"
                }
            };

            if (payloadElement.NextLink != null)
            {
                feed.NextPageLink = new Uri(payloadElement.NextLink);
            }

            AddFeedMetadata(payloadElement, feed);

            this.writer.WriteStart(feed);
            base.Visit(payloadElement);
            this.writer.WriteEnd();
        }
Beispiel #3
0
        public void TaupoTopLevelFeedTest()
        {
            EntitySetInstance entitySet = new EntitySetInstance(PayloadGenerator.GenerateAtomPayloads().First())
                .WithDefaultAtomFeedAnnotations();

            this.CombinatorialEngineProvider.RunCombinations(
                new[] { entitySet },
                this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent,
                (testCase, testConfiguration) =>
                {
                    testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                    this.WriteAndVerifyODataPayloadElement(testCase, testConfiguration);
                });

            // The ID annotation is added for JSON as even though JSON has no way to represent the ID ODataLib requires it.
            entitySet = new EntitySetInstance(PayloadGenerator.GenerateJsonPayloads().ToArray()).WithDefaultAtomIDAnnotation();

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            //this.CombinatorialEngineProvider.RunCombinations(
            //    new[] { entitySet },
            //    this.WriterTestConfigurationProvider.JsonLightFormatConfigurationsWithIndent,
            //    (testCase, testConfiguration) =>
            //    {
            //        this.WriteAndVerifyODataPayloadElement(testCase, testConfiguration);
            //    });
        }
Beispiel #4
0
            /// <summary>
            /// Visits a feed item.
            /// </summary>
            /// <param name="feed">The feed to visit.</param>
            protected override ODataPayloadElement VisitFeed(ODataResourceSet resourceCollection)
            {
                ExceptionUtilities.CheckArgumentNotNull(resourceCollection, "feed");

                EntitySetInstance entitySet = new EntitySetInstance()
                {
                    InlineCount = resourceCollection.Count,
                    NextLink    = resourceCollection.NextPageLink == null ? null : resourceCollection.NextPageLink.OriginalString
                };

                if (resourceCollection.Id != null)
                {
                    entitySet.AtomId(UriUtils.UriToString(resourceCollection.Id));
                }

                // now check for the entries annotation on the feed
                IEnumerable <ODataResource> entries = resourceCollection.Entries();

                if (entries != null)
                {
                    foreach (ODataResource entry in entries)
                    {
                        entitySet.Add(this.Visit(entry));
                    }
                }

                return(entitySet);
            }
            private void Recurse(EntitySetInstance payloadElement)
            {
                if (payloadElement.Count == 0)
                {
                    return;
                }

                var currentValue = this.queryValueStack.Peek() as QueryCollectionValue;

                ExceptionUtilities.CheckObjectNotNull(currentValue, "Current value was not a collection");

                ExceptionUtilities.Assert(payloadElement.Count == currentValue.Elements.Count, "Number of elements did not match");

                for (int i = 0; i < payloadElement.Count; i++)
                {
                    try
                    {
                        this.queryValueStack.Push(currentValue.Elements[i]);
                        this.Recurse(payloadElement[i]);
                    }
                    finally
                    {
                        this.queryValueStack.Pop();
                    }
                }
            }
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            base.Visit(payloadElement);

            // Inject an empty $select projection for top-level feeds (if no projection exists)
            this.InjectEmptyContextUriProjection(payloadElement);
        }
Beispiel #7
0
        /// <summary>
        /// Annotates the feed with atom:logo values.
        /// </summary>
        /// <param name="feed">The feed to annotate.</param>
        /// <param name="uri">The value of the atom:logo element.</param>
        /// <returns>The feed with the annotation applied.</returns>
        public static EntitySetInstance AtomLogo(this EntitySetInstance feed, string uri)
        {
            ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

            feed.AddAnnotation(XmlTreeAnnotation.Atom(TestAtomConstants.AtomLogoElementName, uri));
            return(feed);
        }
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            base.Visit(payloadElement);

            // Inject an empty $select projection for top-level feeds (if no projection exists)
            this.InjectEmptyContextUriProjection(payloadElement);
        }
Beispiel #9
0
        public void FeedReadingNullUriTest()
        {
            EdmModel model = (EdmModel)Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel();

            model.Fixup();

            EntitySetInstance feed = PayloadBuilder.EntitySet();

            feed.NextLink = null;

            // Run only in version >= 2 since next links are only supported since v2 and not allowed in requests
            this.CombinatorialEngineProvider.RunCombinations(
                baseUriValues,
                this.ReaderTestConfigurationProvider.AtomFormatConfigurations.Where(tc => !tc.IsRequest),
                (baseUriValue, testConfiguration) =>
            {
                // The next link should always be null independently of whether a base URI is specified or not
                NullUriValueTestCase <EntitySetInstance> testCase = new NullUriValueTestCase <EntitySetInstance>
                {
                    SetNullUriAction     = (instance, uri, testConfig) => instance.NextLink = null,
                    SetExpectedUriAction = null         // will use SetNullUriAction instead
                };

                this.RunNullUriReadingTest(feed, testCase, model, baseUriValue, testConfiguration);
            });
        }
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            ExceptionUtilities.CheckObjectNotNull(this.currentXElement, "Current XElement is not defined");

            XElement feed = CreateAtomElement(this.currentXElement, "feed");

            if (payloadElement.InlineCount.HasValue)
            {
                XElement countElement = CreateMetadataElement(feed, "count");
                countElement.Value = payloadElement.InlineCount.Value.ToString(CultureInfo.InvariantCulture);
            }

            foreach (EntityInstance entity in payloadElement)
            {
                this.VisitPayloadElement(entity, feed);
            }

            if (payloadElement.NextLink != null)
            {
                CreateAtomLinkElement(feed, "next", payloadElement.NextLink);
            }

            PostProcessXElement(payloadElement, feed);
        }
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            XmlRewriteElementAnnotation annotation = new XmlRewriteElementAnnotation()
            {
                RewriteFunction = (node) =>
                    {
                        XNode foundNode = null;
                        var currentNode = node.FirstNode;
                        if (node.Nodes().Count() > 1)
                        {
                            while (currentNode != null && foundNode == null)
                            {
                                var element = (XElement)currentNode;
                                if (element.Name.LocalName.Equals("id"))
                                {
                                    foundNode = currentNode;
                                    currentNode.Remove();
                                }
                                currentNode = currentNode.NextNode;
                            }

                            if (foundNode != null)
                            {
                                node.FirstNode.AddBeforeSelf(foundNode);
                            }
                        }

                        return node;
                    }
            };

            payloadElement.Add(annotation);
            base.Visit(payloadElement);
        }
        /// <summary>
        /// Visits an entity set instance: creates a new ODataFeed instance, calls ODataWriter.WriteStart()
        /// before visiting the entries and then calls ODataWriter.WriteEnd()
        /// </summary>
        /// <param name="payloadElement">The entity set instance to write.</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            // create an ODataFeed and write it
            ODataFeed feed = new ODataFeed()
            {
                // NOTE: the required Id is set when processing the annotations in AddFeedMetadata()
                Count = payloadElement.InlineCount,
                SerializationInfo = new ODataFeedAndEntrySerializationInfo()
                {
                    NavigationSourceEntityTypeName = "Null",
                    NavigationSourceName = "MySet",
                    ExpectedTypeName = "Null"
                }
            };

            if (payloadElement.NextLink != null)
            {
                feed.NextPageLink = new Uri(payloadElement.NextLink);
            }

            AddFeedMetadata(payloadElement, feed);

            this.writer.WriteStart(feed);
            base.Visit(payloadElement);
            this.writer.WriteEnd();
        }
Beispiel #13
0
        public void TaupoTopLevelFeedTest()
        {
            EntitySetInstance entitySet = new EntitySetInstance(PayloadGenerator.GenerateAtomPayloads().First())
                                          .WithDefaultAtomFeedAnnotations();

            this.CombinatorialEngineProvider.RunCombinations(
                new[] { entitySet },
                this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent,
                (testCase, testConfiguration) =>
            {
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                this.WriteAndVerifyODataPayloadElement(testCase, testConfiguration);
            });

            // The ID annotation is added for JSON as even though JSON has no way to represent the ID ODataLib requires it.
            entitySet = new EntitySetInstance(PayloadGenerator.GenerateJsonPayloads().ToArray()).WithDefaultAtomIDAnnotation();

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            //this.CombinatorialEngineProvider.RunCombinations(
            //    new[] { entitySet },
            //    this.WriterTestConfigurationProvider.JsonLightFormatConfigurationsWithIndent,
            //    (testCase, testConfiguration) =>
            //    {
            //        this.WriteAndVerifyODataPayloadElement(testCase, testConfiguration);
            //    });
        }
        /// <summary>
        /// Visits an entity set instance: creates a new ODataFeed instance, calls ODataWriter.WriteStart()
        /// before visiting the entries and then calls ODataWriter.WriteEnd()
        /// </summary>
        /// <param name="payloadElement">The entity set instance to write.</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            // create an ODataFeed and write it
            ODataFeed feed = new ODataFeed()
            {
                // NOTE: the required Id is set when processing the annotations in AddFeedMetadata()
                Count = payloadElement.InlineCount,
                SerializationInfo = new ODataFeedAndEntrySerializationInfo() {
                    NavigationSourceEntityTypeName = "Null",
                    NavigationSourceName = "MySet",
                    ExpectedTypeName = "Null"
                }
            };

            var idAnnotation = payloadElement.Annotations.Where(a => 
                {
                    var annotation = a as XmlTreeAnnotation;
                    if (annotation != null)
                        return annotation.LocalName.Equals("id");
                    return false;
                }).SingleOrDefault();
            
            if (idAnnotation != null)
            {
                feed.Id = new Uri((idAnnotation as XmlTreeAnnotation).PropertyValue, UriKind.Absolute);
            }

            if (payloadElement.NextLink != null)
            {
                feed.NextPageLink = new Uri(payloadElement.NextLink);
            }

            AddFeedMetadata(payloadElement, feed);

            if (this.items.Count > 0 && this.items.Peek() is ODataNavigationLink)
            {
                var currentLink = this.items.Peek() as ODataNavigationLink;
                ExceptionUtilities.CheckObjectNotNull(currentLink, "Feed can only exist at top level or inside a navigation link");
                currentLink.SetAnnotation(new ODataNavigationLinkExpandedItemObjectModelAnnotation() { ExpandedItem = feed });
            }

            try
            {
                items.Push(feed);
                base.Visit(payloadElement);
            }
            finally
            {
                feed = (ODataFeed)items.Pop();
            }

            // If we are at the top level push this to items to make it the result.
            if (this.items.Count == 0)
            {
                this.items.Push(feed);
            }
        }
        /// <summary>
        /// Sets the expected base entity type for the top-level entity set.
        /// </summary>
        /// <param name="entitySetInstance">The entity set instance to set the expected set for.</param>
        /// <param name="entitySet">The entity set the entities belong to.</param>
        /// <param name="baseEntityType">The base entity type to set as the expected base entity type.</param>
        /// <returns>The <paramref name="entitySetInstance"/> after its expected type was set.</returns>
        public static EntitySetInstance ExpectedEntityType(this EntitySetInstance entitySetInstance, EntitySet entitySet, EntityDataType baseEntityType)
        {
            ExceptionUtilities.CheckArgumentNotNull(entitySetInstance, "entitySetInstance");
            ExpectedTypeODataPayloadElementAnnotation annotation = AddExpectedTypeAnnotation(entitySetInstance);
            EntityDataType entityType = baseEntityType ?? (entitySet == null ? null : DataTypes.EntityType.WithDefinition(entitySet.EntityType));

            annotation.ExpectedType = entityType;
            annotation.EntitySet    = entitySet;
            return(entitySetInstance);
        }
        /// <summary>
        /// Sets the expected base entity type for the top-level entity set.
        /// </summary>
        /// <param name="entitySetInstance">The entity set instance to set the expected set for.</param>
        /// <param name="entitySet">The entity set the entities belong to.</param>
        /// <param name="baseEntityType">The base entity type to set as the expected base entity type.</param>
        /// <returns>The <paramref name="entitySetInstance"/> after its expected type was set.</returns>
        public static EntitySetInstance ExpectedEntityType(this EntitySetInstance entitySetInstance, IEdmTypeReference baseEntityType, IEdmEntitySet entitySet = null)
        {
            ExceptionUtilities.CheckArgumentNotNull(entitySetInstance, "entitySetInstance");
            ExpectedTypeODataPayloadElementAnnotation annotation = ODataPayloadElementExtensions.AddExpectedTypeAnnotation(entitySetInstance);
            var entityType = baseEntityType ?? (entitySet == null ? null : entitySet.EntityType().ToTypeReference());

            annotation.EdmExpectedType = entityType;
            annotation.EdmEntitySet    = entitySet;
            return(entitySetInstance);
        }
        private void AddFeedEPMAnnotations(XElement feedXElement, EntitySetInstance entitySetInstance)
        {
            // get all the properties mapped to atom-specific locations
            // note that this is driven off what is found, not what is expected based on metadata

            // Id
            foreach (var id in feedXElement.Elements(AtomId))
            {
                this.AddEpmTree(entitySetInstance, id);
            }

            // Title
            foreach (var title in feedXElement.Elements(AtomTitle))
            {
                this.AddEpmTree(entitySetInstance, title);
            }

            // Summary
            foreach (var summary in feedXElement.Elements(AtomSummary))
            {
                this.AddEpmTree(entitySetInstance, summary);
            }

            // Rights
            foreach (var rights in feedXElement.Elements(AtomRights))
            {
                this.AddEpmTree(entitySetInstance, rights);
            }

            // Published
            foreach (var published in feedXElement.Elements(AtomPublished))
            {
                this.AddEpmTree(entitySetInstance, published);
            }

            // Updated
            foreach (var updated in feedXElement.Elements(AtomUpdated))
            {
                this.AddEpmTree(entitySetInstance, updated);
            }

            // Author
            foreach (var author in feedXElement.Elements(AtomAuthor))
            {
                // will recurse automatically
                this.AddEpmTree(entitySetInstance, author);
            }

            // Contributor
            foreach (var contributor in feedXElement.Elements(AtomContributor))
            {
                // will recurse automatically
                this.AddEpmTree(entitySetInstance, contributor);
            }
        }
Beispiel #18
0
        /// <summary>
        /// Annotates the feed with atom:generator values.
        /// </summary>
        /// <param name="feed">The feed to annotate.</param>
        /// <param name="name">The value of the atom:generator element.</param>
        /// <param name="uri">The value of the atom:generator's URI property.</param>
        /// <param name="version">The value of the atom:generator's version property.</param>
        /// <returns>The feed with the annotation applied.</returns>
        public static EntitySetInstance AtomGenerator(this EntitySetInstance feed, string name, string uri, string version)
        {
            ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

            var generatorAttributes = CreateAtomAttributes(
                new KeyValuePair <string, string>(TestAtomConstants.AtomGeneratorUriAttributeName, uri),
                new KeyValuePair <string, string>(TestAtomConstants.AtomGeneratorVersionAttributeName, version));

            feed.AddAnnotation(XmlTreeAnnotation.Atom(TestAtomConstants.AtomGeneratorElementName, name, generatorAttributes));
            return(feed);
        }
        /// <summary>
        /// Visits a payload element whose root is an EntitySetInstance.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override ODataPayloadElement Visit(EntitySetInstance payloadElement)
        {
            EntitySetInstance entitySetInstance = (EntitySetInstance)base.Visit(payloadElement);

            foreach (EntityInstance instance in entitySetInstance)
            {
                instance.Accept(this);
            }

            return(entitySetInstance);
        }
Beispiel #20
0
        /// <summary>
        /// Visits the entity set and removes the title and entity set annotations
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            var annotation = payloadElement.Annotations.Where(a => a is TitleAnnotation).SingleOrDefault();
            payloadElement.Annotations.Remove(annotation);
            annotation = payloadElement.Annotations.Where(a => a is EntitySetAnnotation).SingleOrDefault();
            payloadElement.Annotations.Remove(annotation);

            base.Visit(payloadElement);
        }
Beispiel #21
0
 /// <summary>
 /// Visits the payload element
 /// </summary>
 /// <param name="payloadElement">The payload element to visit</param>
 public override void Visit(EntitySetInstance payloadElement)
 {
     ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
     var hasID = payloadElement.Annotations.Where(a => a is XmlTreeAnnotation && (a as XmlTreeAnnotation).LocalName == TestAtomConstants.AtomIdElementName).SingleOrDefault();
     if (hasID == null)
     {
         payloadElement.AtomId("urn:FeedID");
     }
     
     base.Visit(payloadElement);
 }
Beispiel #22
0
        /// <summary>
        /// Visits a payload element whose root is an EntitySetInstance.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            base.Visit(payloadElement);

            // Entity set instances (Feeds) use different format in JSON for V2 (and higher) payloads in responses
            // so we need to add an annotation marking it with the right version so that the serializer will use the
            // V2 format.
            if (!this.requestPayload)
            {
                this.AddVersionAnnotation(payloadElement);
            }
        }
Beispiel #23
0
        /// <summary>
        /// Visits the entity set and removes the title and entity set annotations
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            var annotation = payloadElement.Annotations.Where(a => a is TitleAnnotation).SingleOrDefault();

            payloadElement.Annotations.Remove(annotation);
            annotation = payloadElement.Annotations.Where(a => a is EntitySetAnnotation).SingleOrDefault();
            payloadElement.Annotations.Remove(annotation);

            base.Visit(payloadElement);
        }
Beispiel #24
0
            /// <summary>
            /// Visits a payload element whose root is a EntitySetInstance.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(EntitySetInstance payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
                this.isRootElement = false;
                this.writer.StartArrayScope();
                for (int i = 0; i < payloadElement.Count(); i++)
                {
                    payloadElement[i].Accept(this);
                }

                this.writer.EndScope();
            }
Beispiel #25
0
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var hasID = payloadElement.Annotations.Where(a => a is XmlTreeAnnotation && (a as XmlTreeAnnotation).LocalName == TestAtomConstants.AtomIdElementName).SingleOrDefault();

            if (hasID == null)
            {
                payloadElement.AtomId("urn:FeedID");
            }

            base.Visit(payloadElement);
        }
Beispiel #26
0
        /// <summary>
        /// Visits payloadElement to add default annotations and remove certain ones.
        /// Then Visits its properties to replace properties with null values with NullProperty Instances.
        /// This is required in comparison because the Test Deserialiser converts properties that are null to NullProperty Instnaces.
        /// Also removes the annotations added by the Replacing Visitor and removes MultiValue properties if found
        /// </summary>
        /// <param name="payloadElement">the payload to potentially replace</param>
        /// <returns>The original or a copy if it has changed</returns>
        public override ODataPayloadElement Visit(EntitySetInstance payloadElement)
        {
            FixEpmAnnotationsUris(payloadElement.Annotations);
            EntitySetInstance entitySetInstance = (EntitySetInstance)base.Visit(payloadElement);

            // This has to happen last
            ReplaceAnnotationRemover replaceAnnotationRemover = new ReplaceAnnotationRemover();

            replaceAnnotationRemover.Visit(entitySetInstance);

            return(entitySetInstance);
        }
Beispiel #27
0
        private static void AddFeedMetadata(EntitySetInstance payloadElement, ODataFeed feed)
        {
            AtomFeedMetadata metadata = CreateFeedMetadata(payloadElement.Annotations.OfType <XmlTreeAnnotation>(), feed);

            // Fix up metadata for baselining
            metadata = metadata.Fixup();

            if (metadata != null)
            {
                feed.SetAnnotation <AtomFeedMetadata>(metadata);
            }
        }
Beispiel #28
0
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            var idAnnotation = payloadElement.Annotations
                .Where(a => a is XmlTreeAnnotation && ((XmlTreeAnnotation)a).LocalName == TestAtomConstants.AtomIdElementName).SingleOrDefault();
            if (idAnnotation != null)
            {
                payloadElement.Annotations.Remove(idAnnotation);
            }
            
            base.Visit(payloadElement);
        }
            /// <summary>
            /// Visits a payload element whose root is an EntitySetInstance.
            /// </summary>
            /// <param name="expected">The root node of payload element being visited.</param>
            public void Visit(EntitySetInstance expected)
            {
                ExceptionUtilities.CheckArgumentNotNull(expected, "expected");
                var observed = this.GetNextObservedElement <EntitySetInstance>();

                using (this.Assert.WithMessage("Entity set instance did not match expectation"))
                {
                    this.Assert.AreEqual(expected.NextLink, observed.NextLink, "Next link did not match expectation");
                    this.Assert.AreEqual(expected.InlineCount, observed.InlineCount, "Inline count did not match expectation");

                    this.CompareCollection(expected, observed);
                }
            }
Beispiel #30
0
        /// <summary>
        /// Builds an instance of QueryCollectionValue from an entity set instance.
        /// </summary>
        /// <param name="entitySetInstance">The entity set instance.</param>
        /// <param name="elementType">The QueryEntityType of its element.</param>
        /// <param name="xmlBaseAnnotations">The xml base annotations from parent elements, if any</param>
        /// <returns>The converted QueryCollectionValue of entity set instance.</returns>
        private QueryCollectionValue BuildFromEntitySetInstance(EntitySetInstance entitySetInstance, QueryEntityType elementType, IEnumerable <XmlBaseAnnotation> xmlBaseAnnotations)
        {
            ExceptionUtilities.CheckArgumentNotNull(elementType, "elementType");
            var entities = new List <QueryStructuralValue>();

            foreach (var entityInstance in entitySetInstance)
            {
                var value = this.BuildFromEntityInstance(entityInstance, elementType, xmlBaseAnnotations.Concat(entityInstance.Annotations.OfType <XmlBaseAnnotation>()));
                entities.Add(value);
            }

            return(QueryCollectionValue.Create(elementType, entities.ToArray()));
        }
        /// <summary>
        /// Converts the ComplexMultiValue into an EntitySetInstance based on if the base returns a set of EntityInstances
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(ComplexMultiValue payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var replaced = (ComplexMultiValue)base.Visit(payloadElement);
            ExceptionUtilities.CheckObjectNotNull(replaced, "ComplexMultiValue Expected");
            if (replaced.All(e => e.ElementType == ODataPayloadElementType.EntityInstance) && replaced.Count > 0)
            {
                var entitySet = new EntitySetInstance(replaced.Cast<EntityInstance>().ToArray());
                return replaced.ReplaceWith(entitySet);
            }

            return replaced;
        }
Beispiel #32
0
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            var idAnnotation = payloadElement.Annotations
                               .Where(a => a is XmlTreeAnnotation && ((XmlTreeAnnotation)a).LocalName == TestAtomConstants.AtomIdElementName).SingleOrDefault();

            if (idAnnotation != null)
            {
                payloadElement.Annotations.Remove(idAnnotation);
            }

            base.Visit(payloadElement);
        }
        /// <summary>
        /// Converts the ComplexMultiValue into an EntitySetInstance based on if the base returns a set of EntityInstances
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(ComplexMultiValue payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var replaced = (ComplexMultiValue)base.Visit(payloadElement);

            ExceptionUtilities.CheckObjectNotNull(replaced, "ComplexMultiValue Expected");
            if (replaced.All(e => e.ElementType == ODataPayloadElementType.EntityInstance) && replaced.Count > 0)
            {
                var entitySet = new EntitySetInstance(replaced.Cast <EntityInstance>().ToArray());
                return(replaced.ReplaceWith(entitySet));
            }

            return(replaced);
        }
        /// <summary>
        /// Deserializes the given element, which is assumed to be an atom feed, into an entity set
        /// </summary>
        /// <param name="feed">An atom feed xml element</param>
        /// <returns>The deserialized entity set</returns>
        private EntitySetInstance DeserializeEntitySet(XElement feed)
        {
            ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

            EntitySetInstance entitySet = new EntitySetInstance();

            AddXmlBaseAnnotation(entitySet, feed);

            // set title
            XElement title = feed.Element(AtomTitle);

            if (title != null)
            {
                entitySet.Annotations.Add(new TitleAnnotation(title.Value));
            }

            // read the count, if present
            XElement count = feed.Element(MetadataCount);

            if (count != null)
            {
                entitySet.InlineCount = long.Parse(count.Value, CultureInfo.InvariantCulture);
            }

            // read the next link, if present
            XElement nextLink = feed.Elements(AtomLink)
                                .Select(l => l.Attribute(Rel))
                                .Where(rel => rel != null)
                                .Where(rel => rel.Value == RelNext)
                                .Select(rel => rel.Parent)
                                .SingleOrDefault();

            if (nextLink != null)
            {
                XAttribute href = nextLink.Attribute(Href);
                if (href != null)
                {
                    entitySet.NextLink = href.Value;
                }
            }

            // deserialize and add each entry
            foreach (XElement entry in feed.Elements(AtomEntry))
            {
                entitySet.Add(this.DeserializeEntity(entry));
            }

            this.AddFeedEPMAnnotations(feed, entitySet);
            return(entitySet);
        }
Beispiel #35
0
        /// <summary>
        /// Annotates the entry with atom:source values.
        /// </summary>
        /// <param name="entry">The entry to annotate.</param>
        /// <param name="sourceFeed">The feed containing metadata to copy.</param>
        /// <returns>The entry with the annotation applied.</returns>
        public static EntityInstance AtomSource(this EntityInstance entry, EntitySetInstance sourceFeed)
        {
            ExceptionUtilities.CheckArgumentNotNull(entry, "entry");
            ExceptionUtilities.CheckArgumentNotNull(sourceFeed, "sourceFeed");

            var sourceAnnotations = sourceFeed.Annotations.OfType <XmlTreeAnnotation>();

            entry.AddAnnotation(
                XmlTreeAnnotation.Atom(
                    TestAtomConstants.AtomSourceElementName,
                    null,
                    sourceAnnotations.Select(a => (XmlTreeAnnotation)a.Clone()).ToArray()));

            return(entry);
        }
            /// <summary>
            /// Visits a feed item.
            /// </summary>
            /// <param name="feed">The feed item to visit.</param>
            /// <returns>An ODataPayloadElement representing the feed.</returns>
            protected override ODataPayloadElement VisitFeed(ODataFeed feed)
            {
                ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

                EntitySetInstance entitySet = (EntitySetInstance)base.VisitFeed(feed);

                var atomMetadata = feed.GetAnnotation <AtomFeedMetadata>();

                if (atomMetadata != null)
                {
                    ConvertAtomFeedMetadata(atomMetadata, entitySet);
                }

                return(entitySet);
            }
Beispiel #37
0
        /// <summary>
        /// Build QueryValue from action response payload
        /// </summary>
        /// <param name="payload">response payload element</param>
        /// <param name="queryType">query type to build</param>
        /// <returns>query value that represents the payload</returns>
        private QueryValue BuildQueryValueForActionResponse(ODataPayloadElement payload, QueryType queryType)
        {
            EntitySetInstance           entitySetInstance           = payload as EntitySetInstance;
            PrimitiveProperty           primitiveProperty           = payload as PrimitiveProperty;
            ComplexProperty             complexProperty             = payload as ComplexProperty;
            PrimitiveMultiValueProperty primitiveMultiValueProperty = payload as PrimitiveMultiValueProperty;
            ComplexMultiValueProperty   complexMultiValueProperty   = payload as ComplexMultiValueProperty;
            PrimitiveCollection         primitiveCollection         = payload as PrimitiveCollection;
            ComplexInstanceCollection   complexInstanceCollection   = payload as ComplexInstanceCollection;

            if (entitySetInstance != null)
            {
                var xmlBaseAnnotations = payload.Annotations.OfType <XmlBaseAnnotation>();
                var collectionType     = this.currentExpression.ExpressionType as QueryCollectionType;
                ExceptionUtilities.CheckObjectNotNull(collectionType, "Cannot cast expression type to QueryCollectionType.");
                var elementType = collectionType.ElementType as QueryEntityType;
                return(this.BuildFromEntitySetInstance(entitySetInstance, elementType, xmlBaseAnnotations));
            }
            else if (primitiveProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(primitiveProperty.Value, queryType));
            }
            else if (complexProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(complexProperty.Value, queryType));
            }
            else if (primitiveMultiValueProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(primitiveMultiValueProperty.Value, queryType));
            }
            else if (complexMultiValueProperty != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(complexMultiValueProperty.Value, queryType));
            }
            else if (primitiveCollection != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(primitiveCollection, queryType));
            }
            else if (complexInstanceCollection != null)
            {
                return(this.PayloadElementToQueryValueConverter.Convert(complexInstanceCollection, queryType));
            }
            else
            {
                ExceptionUtilities.CheckArgumentNotNull(payload as EntityInstance, "Unexpected response payload type: " + payload.ElementType + ".");
                return(this.PayloadElementToQueryValueConverter.Convert(payload, queryType));
            }
        }
Beispiel #38
0
        /// <summary>
        /// Visits the children of the given payload element and replaces it with a copy if any child changes
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public virtual ODataPayloadElement Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var replaced = this.VisitCollection(payloadElement);

            if (!this.ShouldReplace(replaced, payloadElement))
            {
                return(payloadElement);
            }

            var replacedCollection = payloadElement.ReplaceWith(new EntitySetInstance(replaced.ToArray()));

            replacedCollection.InlineCount = payloadElement.InlineCount;
            replacedCollection.NextLink    = payloadElement.NextLink;
            return(replacedCollection);
        }
Beispiel #39
0
        /// <summary>
        /// Visits the payload element and annotates it with metadata
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var entitySet = this.MetadataStack.Peek() as EntitySet;

            ExceptionUtilities.CheckObjectNotNull(entitySet, "Expected entity set, got '{0}'", this.MetadataStack.Peek());

            payloadElement.AddAnnotationIfNotExist(new EntitySetAnnotation()
            {
                EntitySet = entitySet
            });
            foreach (var element in payloadElement)
            {
                this.Recurse(element);
            }
        }
        /// <summary>
        /// Visits the payload element
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            XmlTreeAnnotation updated = XmlTreeAnnotation.Atom(TestAtomConstants.AtomUpdatedElementName, "2013-08-13T01:03:16.7800000");
            updated.SetValueEqualityFunc((obj1, obj2) =>
            {
                return true;
            });
            payloadElement.Annotations.Add(updated);
            payloadElement.Add(XmlTreeAnnotation.Atom("title", null));
            
            //If a feed is empty it must have an author
            bool feedEmpty = payloadElement.Count == 0;
            if (feedEmpty)
            {
                XmlTreeAnnotation author = XmlTreeAnnotation.Atom(TestAtomConstants.AtomAuthorElementName,
                  null, XmlTreeAnnotation.Atom(TestAtomConstants.AtomAuthorNameElementName, null));
                payloadElement.Annotations.Add(author);
            }

            base.Visit(payloadElement);
        }
        /// <summary>
        /// Replaces the empty collection property with a more specific type
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(EmptyUntypedCollection payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var expectedTypeAnnotatation = payloadElement.Annotations.OfType<ExpectedPayloadElementTypeAnnotation>().SingleOrDefault();
            if (expectedTypeAnnotatation != null && expectedTypeAnnotatation.ExpectedType == ODataPayloadElementType.LinkCollection)
            {
                var linkCollection = new LinkCollection();
                linkCollection.InlineCount = payloadElement.InlineCount;
                linkCollection.NextLink = payloadElement.NextLink;
                return payloadElement.ReplaceWith(linkCollection);
            }

            var entitySetAnnotation = payloadElement.Annotations.OfType<EntitySetAnnotation>().SingleOrDefault();
            if (entitySetAnnotation != null)
            {
                var entitySet = new EntitySetInstance();
                entitySet.InlineCount = payloadElement.InlineCount;
                entitySet.NextLink = payloadElement.NextLink;
                return payloadElement.ReplaceWith(entitySet);
            }

            var functionAnnotation = payloadElement.Annotations.OfType<FunctionAnnotation>().SingleOrDefault();
            if (functionAnnotation != null && expectedTypeAnnotatation != null)
            {
                if (expectedTypeAnnotatation.ExpectedType == ODataPayloadElementType.ComplexInstanceCollection)
                {
                    return payloadElement.ReplaceWith(new ComplexInstanceCollection());
                }

                if (expectedTypeAnnotatation.ExpectedType == ODataPayloadElementType.PrimitiveCollection)
                {
                    return payloadElement.ReplaceWith(new PrimitiveCollection());
                }
            }

            return base.Visit(payloadElement);
        }
            /// <summary>
            /// Converts the Object Model representation of Atom metadata for entries into appropriate PayloadElement annotations
            /// </summary>
            /// <param name="entryMetadata">the Atom entry metadata, in Object Model representation, to convert</param>
            /// <param name="entry">the EntityInstance to annotate</param>
            private static void ConvertAtomEntryMetadata(AtomEntryMetadata entryMetadata, EntityInstance entry)
            {
                ExceptionUtilities.CheckArgumentNotNull(entryMetadata, "entryMetadata");
                ExceptionUtilities.CheckArgumentNotNull(entry, "entry");

                foreach (var author in entryMetadata.Authors)
                {
                    entry.AtomAuthor(author.Name, author.Uri == null ? null : author.Uri.OriginalString, author.Email);
                }

                foreach (var category in entryMetadata.Categories)
                {
                    entry.AtomCategory(category.Term, category.Scheme, category.Label);
                }

                foreach (var contributor in entryMetadata.Contributors)
                {
                    entry.AtomContributor(contributor.Name, contributor.Uri == null? null : contributor.Uri.OriginalString, contributor.Email);
                }

                if (entryMetadata.EditLink != null)
                {
                    AtomLinkMetadata editLink = entryMetadata.EditLink;
                    entry.AtomEditLink(editLink.Href == null ? null : editLink.Href.OriginalString, editLink.MediaType, editLink.HrefLang, editLink.Title, ToString(editLink.Length));
                }

                foreach (var link in entryMetadata.Links)
                {
                    entry.AtomLink(link.Href == null ? null : link.Href.OriginalString, link.Relation, link.MediaType, link.HrefLang, link.Title, ToString(link.Length));
                }

                if (entryMetadata.Published.HasValue)
                {
                    entry.AtomPublished(ToString(entryMetadata.Published));
                }

                if (entryMetadata.Rights != null)
                {
                    entry.AtomRights(entryMetadata.Rights.Text, ToString(entryMetadata.Rights.Kind));
                }

                if (entryMetadata.SelfLink != null)
                {
                    AtomLinkMetadata selfLink = entryMetadata.SelfLink;
                    entry.AtomSelfLink(selfLink.Href == null ? null : selfLink.Href.OriginalString, selfLink.MediaType, selfLink.HrefLang, selfLink.Title, ToString(selfLink.Length));
                }

                if (entryMetadata.CategoryWithTypeName != null)
                {
                    AtomCategoryMetadata categoryWithTypeName = entryMetadata.CategoryWithTypeName;
                    entry.AtomCategoryWithTypeName(categoryWithTypeName.Term, categoryWithTypeName.Label);
                }

                if (entryMetadata.Source != null)
                {
                    EntitySetInstance tempSourceFeed = new EntitySetInstance();
                    ConvertAtomFeedMetadata(entryMetadata.Source, tempSourceFeed);
                    entry.AtomSource(tempSourceFeed);
                }

                if (entryMetadata.Summary != null)
                {
                    entry.AtomSummary(entryMetadata.Summary.Text, ToString(entryMetadata.Summary.Kind));
                }

                if (entryMetadata.Title != null)
                {
                    entry.AtomTitle(entryMetadata.Title.Text, ToString(entryMetadata.Title.Kind));
                }

                if (entryMetadata.Updated.HasValue)
                {
                    entry.AtomUpdated(ToString(entryMetadata.Updated));
                }
            }
            private void GenerateAndCompareNextLink(EntitySetInstance payloadElement, int expectedPageSize)
            {
                var currentPageValues = this.queryValueStack.Peek() as QueryCollectionValue;
                ExceptionUtilities.CheckObjectNotNull(currentPageValues, "Current value was not a collection");
                var lastEntityValue = currentPageValues.Elements.Cast<QueryStructuralValue>().Last();

                // build the expected next link and the message to used based on whether we are in an expanded feed or top-level feed
                string expectedNextLink = null;
                if (this.navigationStack.Count == 0)
                {
                    expectedNextLink = this.parent.ExpectedNextLinkGenerator.GenerateNextLink(this.requestUri, expectedPageSize, lastEntityValue);
                }
                else
                {
                    expectedNextLink = this.parent.ExpectedNextLinkGenerator.GenerateExpandedNextLink(this.entityStack.Peek(), this.navigationStack.Peek(), lastEntityValue);
                }

                var xmlBaseSegments = this.xmlBaseStack.Reverse().Select(x => x.Value);
                var expected = UriHelpers.CreateAbsoluteLink(expectedNextLink, xmlBaseSegments);

                this.parent.AssertHandler.AreEqual(expected.OriginalString, payloadElement.NextLink, "Next link did not match expectation");
            }
            private void Recurse(EntitySetInstance payloadElement)
            {
                if (payloadElement.Count == 0)
                {
                    return;
                }

                var currentValue = this.queryValueStack.Peek() as QueryCollectionValue;
                ExceptionUtilities.CheckObjectNotNull(currentValue, "Current value was not a collection");

                ExceptionUtilities.Assert(payloadElement.Count == currentValue.Elements.Count, "Number of elements did not match");

                for (int i = 0; i < payloadElement.Count; i++)
                {
                    try
                    {
                        this.queryValueStack.Push(currentValue.Elements[i]);
                        this.Recurse(payloadElement[i]);
                    }
                    finally
                    {
                        this.queryValueStack.Pop();
                    }
                }
            }
        /// <summary>
        /// Visits the payload element and annotates it with metadata
        /// </summary>
        /// <param name="payloadElement">The payload element to visit</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
            var entitySet = this.MetadataStack.Peek() as EntitySet;
            ExceptionUtilities.CheckObjectNotNull(entitySet, "Expected entity set, got '{0}'", this.MetadataStack.Peek());

            payloadElement.AddAnnotationIfNotExist(new EntitySetAnnotation() { EntitySet = entitySet });
            foreach (var element in payloadElement)
            {
                this.Recurse(element);
            }
        }
        /// <summary>
        /// Visits a payload element whose root is an EntitySetInstance.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            base.Visit(payloadElement);

            // Entity set instances (Feeds) use different format in JSON for V2 (and higher) payloads in responses
            // so we need to add an annotation marking it with the right version so that the serializer will use the
            // V2 format.
            if (!this.requestPayload)
            {
                this.AddVersionAnnotation(payloadElement);
            }
        }
        /// <summary>
        /// Deserializes the given element, which is assumed to be an atom feed, into an entity set
        /// </summary>
        /// <param name="feed">An atom feed xml element</param>
        /// <returns>The deserialized entity set</returns>
        private EntitySetInstance DeserializeEntitySet(XElement feed)
        {
            ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

            EntitySetInstance entitySet = new EntitySetInstance();

            AddXmlBaseAnnotation(entitySet, feed);

            // set title
            XElement title = feed.Element(AtomTitle);
            if (title != null)
            {
                entitySet.Annotations.Add(new TitleAnnotation(title.Value));
            }

            // read the count, if present
            XElement count = feed.Element(MetadataCount);
            if (count != null)
            {
                entitySet.InlineCount = long.Parse(count.Value, CultureInfo.InvariantCulture);
            }

            // read the next link, if present
            XElement nextLink = feed.Elements(AtomLink)
                .Select(l => l.Attribute(Rel))
                .Where(rel => rel != null)
                .Where(rel => rel.Value == RelNext)
                .Select(rel => rel.Parent)
                .SingleOrDefault();
            if (nextLink != null)
            {
                XAttribute href = nextLink.Attribute(Href);
                if (href != null)
                {
                    entitySet.NextLink = href.Value;
                }
            }

            // deserialize and add each entry
            foreach (XElement entry in feed.Elements(AtomEntry))
            {
                entitySet.Add(this.DeserializeEntity(entry));
            }

            this.AddFeedEPMAnnotations(feed, entitySet);
            return entitySet;
        }
            /// <summary>
            /// verification method to verify entity collection without verifying order.
            /// </summary>
            /// <param name="payloadElement">entity set instance</param>
            /// <param name="value">expected collection value</param>
            private void CompareUnsortedCollection(EntitySetInstance payloadElement, QueryCollectionValue value)
            {
                for (int i = 0; i < payloadElement.Count; i++)
                {
                    var actual = payloadElement[i];
                    ExceptionUtilities.CheckObjectNotNull(actual, "Element at position {0} was unexpectedly null", i);

                    bool match = false;
                    foreach (var expected in value.Elements)
                    {
                        var ex = this.RecurseAndCatch(actual, expected);
                        if (ex == null)
                        {
                            match = true;
                            break;
                        }
                    }

                    this.parent.Assert.IsTrue(match, "Element at position {0} did not match any expected value", i + 1);
                }
            }
        private void AddFeedEPMAnnotations(XElement feedXElement, EntitySetInstance entitySetInstance)
        {
            // get all the properties mapped to atom-specific locations
            // note that this is driven off what is found, not what is expected based on metadata

            // Id
            foreach (var id in feedXElement.Elements(AtomId))
            {
                this.AddEpmTree(entitySetInstance, id);
            }

            // Title
            foreach (var title in feedXElement.Elements(AtomTitle))
            {
                this.AddEpmTree(entitySetInstance, title);
            }

            // Summary
            foreach (var summary in feedXElement.Elements(AtomSummary))
            {
                this.AddEpmTree(entitySetInstance, summary);
            }

            // Rights
            foreach (var rights in feedXElement.Elements(AtomRights))
            {
                this.AddEpmTree(entitySetInstance, rights);
            }

            // Published
            foreach (var published in feedXElement.Elements(AtomPublished))
            {
                this.AddEpmTree(entitySetInstance, published);
            }

            // Updated
            foreach (var updated in feedXElement.Elements(AtomUpdated))
            {
                this.AddEpmTree(entitySetInstance, updated);
            }

            // Author
            foreach (var author in feedXElement.Elements(AtomAuthor))
            {
                // will recurse automatically
                this.AddEpmTree(entitySetInstance, author);
            }

            // Contributor
            foreach (var contributor in feedXElement.Elements(AtomContributor))
            {
                // will recurse automatically
                this.AddEpmTree(entitySetInstance, contributor);
            }
        }
        /// <summary>
        /// Visits a payload element whose root is a EntitySetInstance.
        /// </summary>
        /// <param name="payloadElement">The root node of the payload element being visited.</param>
        public override void Visit(EntitySetInstance payloadElement)
        {
            base.Visit(payloadElement);

            if (payloadElement.GetAnnotation<JsonLightContextUriAnnotation>() == null)
            {
                var typeAnnotation = payloadElement.Annotations.OfType<ExpectedTypeODataPayloadElementAnnotation>().SingleOrDefault();
                if (typeAnnotation == null && this.payloadElementStack.Count == 1)
                {
                    var annotation = payloadElement.GetAnnotation<EntityModelTypeAnnotation>();
                    if (annotation != null)
                    {
                        if (this.testDescriptor.PayloadEdmModel != null && annotation.EdmModelType != null)
                        {
                            var edmEntityType = annotation.EdmModelType;
                            var edmEntitySet = FindEntitySet(this.testDescriptor.PayloadEdmModel, edmEntityType.Definition as IEdmSchemaType);
                            payloadElement.ExpectedEntityType(edmEntityType, edmEntitySet);
                        }
                    }
                }
            }
        }
 /// <summary>
 /// verification method to verify entity collection with predictable order.
 /// </summary>
 /// <param name="payloadElement">entity set instance</param>
 /// <param name="value">expected collection value</param>
 private void CompareSortedCollection(EntitySetInstance payloadElement, QueryCollectionValue value)
 {
     for (int i = 0; i < value.Elements.Count; i++)
     {
         this.RecurseWithMessage(payloadElement[i], value.Elements[i], "Element at position {0} did not match expectation", i + 1);
     }
 }
 /// <summary>
 /// Visits the payload element
 /// </summary>
 /// <param name="payloadElement">The payload element to visit</param>
 public override void Visit(EntitySetInstance payloadElement)
 {
     ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
     this.IncreaseVersionIfNonNull(payloadElement.NextLink, DataServiceProtocolVersion.V4);
     base.Visit(payloadElement);
 }
            /// <summary>
            /// Visits a payload element whose root is a EntitySetInstance.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(EntitySetInstance payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
                this.isRootElement = false;
                this.writer.StartArrayScope();
                for (int i = 0; i < payloadElement.Count(); i++)
                {
                    payloadElement[i].Accept(this);
                }

                this.writer.EndScope();
            }
            /// <summary>
            /// Visits a payload element whose root is an EntitySetInstance.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(EntitySetInstance payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

                var current = this.expectedValueStack.Peek();
                var value = current as QueryCollectionValue;
                ExceptionUtilities.CheckObjectNotNull(value, "Value was not a collection. Value was: '{0}'", current.ToString());
                var entityType = value.Type.ElementType as QueryEntityType;
                ExceptionUtilities.CheckObjectNotNull(entityType, "Value was not a collection of entities. Value was: '{0}'", current.ToString());

                this.parent.Assert.AreEqual(value.Elements.Count, payloadElement.Count, "Entity set count did not match expectation");

                // apply different verification methods based on whether order is predictable.
                if (value.IsSorted)
                {
                    this.CompareSortedCollection(payloadElement, value);
                }
                else
                {
                    this.CompareUnsortedCollection(payloadElement, value);
                }

                // next-link verification now performed by seperate component. See NextLinkResponseVerifier.
            }
            /// <summary>
            /// Visits the payload element
            /// </summary>
            /// <param name="payloadElement">The payload element to visit</param>
            public override void Visit(EntitySetInstance payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

                var entitySetAnnotation = payloadElement.Annotations.OfType<EntitySetAnnotation>().SingleOrDefault();
                ExceptionUtilities.CheckObjectNotNull(entitySetAnnotation, "Could not find entity-set annotation on payload element");

                bool expectNextLink = false;
                var expectedPageSize = entitySetAnnotation.EntitySet.GetEffectivePageSize();
                if (expectedPageSize.HasValue)
                {
                    // note that the check that the number of elements is less-than-or-equal-to page size happens below
                    expectNextLink = payloadElement.Count == expectedPageSize.Value;
                }

                string message;
                if (this.navigationStack.Count == 0)
                {
                    message = "In root feed";

                    // if the service can tell from the uri that no paging is needed, there will be no next link
                    if (expectNextLink && this.requestUri.Top.HasValue)
                    {
                        expectNextLink &= this.requestUri.Top.Value > expectedPageSize.Value;
                    }
                }
                else
                {
                    message = "In expanded feed";
                }

                using (this.parent.AssertHandler.WithMessage(message))
                {
                    if (expectedPageSize.HasValue)
                    {
                        // verify number of elements. This is also validated based on query expectations in another verifier,
                        // but its cheap and easy to cover here as well to cover our bases.
                        this.parent.AssertHandler.IsTrue(
                            payloadElement.Count <= expectedPageSize.Value,
                            "Number of elements ({0}) exceeds page size ({1}).",
                            payloadElement.Count,
                            expectedPageSize.Value);
                    }

                    if (!expectNextLink)
                    {
                        this.parent.AssertHandler.IsNull(payloadElement.NextLink, "Next link unexpectedly non-null");
                    }
                    else
                    {
                        this.parent.AssertHandler.IsNotNull(payloadElement.NextLink, "Next link unexpectedly null");

                        // only validate the next link if the protocol is implemented based on the expected conventions
                        if (this.payloadOptions.HasFlag(ODataPayloadOptions.UseConventionBasedLinks))
                        {
                            this.GenerateAndCompareNextLink(payloadElement, expectedPageSize.Value);
                        }
                    }

                    this.Recurse(payloadElement);
                }
            }
        private static void AddFeedMetadata(EntitySetInstance payloadElement, ODataFeed feed)
        {
            AtomFeedMetadata metadata = CreateFeedMetadata(payloadElement.Annotations.OfType<XmlTreeAnnotation>(), feed);

            // Fix up metadata for baselining
            metadata = metadata.Fixup();

            if (metadata != null)
            {
                feed.SetAnnotation<AtomFeedMetadata>(metadata);
            }
        }
            /// <summary>
            /// Converts the Object Model representation of Atom metadata for feeds into appropriate PayloadElement annotations
            /// </summary>
            /// <param name="feedMetadata">the Atom feed metadata, in Object Model representation, to convert</param>
            /// <param name="feed">the EntitySetInstance to annotate</param>
            private static void ConvertAtomFeedMetadata(AtomFeedMetadata feedMetadata, EntitySetInstance feed)
            {
                ExceptionUtilities.CheckArgumentNotNull(feedMetadata, "feedMetadata");
                ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

                foreach (var author in feedMetadata.Authors)
                {
                    feed.AtomAuthor(author.Name, author.Uri == null ? null : author.Uri.OriginalString, author.Email);
                }

                foreach (var category in feedMetadata.Categories)
                {
                    feed.AtomCategory(category.Term, category.Scheme, category.Label);
                }

                foreach (var contributor in feedMetadata.Contributors)
                {
                    feed.AtomContributor(contributor.Name, contributor.Uri == null ? null : contributor.Uri.OriginalString, contributor.Email);
                }

                if (feedMetadata.Generator != null)
                {
                    feed.AtomGenerator(feedMetadata.Generator.Name, feedMetadata.Generator.Uri == null ? null : feedMetadata.Generator.Uri.OriginalString, feedMetadata.Generator.Version);
                }

                if (feedMetadata.Icon != null)
                {
                    feed.AtomIcon(feedMetadata.Icon.OriginalString);
                }

                foreach (var link in feedMetadata.Links)
                {
                    string linkLength = link.Length.HasValue ? link.Length.Value.ToString() : null;
                    feed.AtomLink(link.Href == null ? null : link.Href.OriginalString, link.Relation, link.MediaType, link.HrefLang, link.Title, linkLength);
                }

                if (feedMetadata.Logo != null)
                {
                    feed.AtomLogo(feedMetadata.Logo.OriginalString);
                }

                if (feedMetadata.Rights != null)
                {
                    feed.AtomRights(feedMetadata.Rights.Text, ToString(feedMetadata.Rights.Kind));
                }

                if (feedMetadata.SelfLink != null)
                {
                    AtomLinkMetadata selfLink = feedMetadata.SelfLink;
                    ExceptionUtilities.Assert(selfLink.Relation == TestAtomConstants.AtomSelfRelationAttributeValue, "The self link ATOM metadata must have the rel set to 'self'.");
                    string selfLinkLength = selfLink.Length.HasValue ? selfLink.Length.Value.ToString() : null;
                    feed.AtomSelfLink(selfLink.Href == null ? null : selfLink.Href.OriginalString, selfLink.MediaType, selfLink.HrefLang, selfLink.Title, selfLinkLength);
                }

                if (feedMetadata.NextPageLink != null)
                {
                    AtomLinkMetadata nextPageLink = feedMetadata.NextPageLink;
                    ExceptionUtilities.Assert(nextPageLink.Relation == TestAtomConstants.AtomNextRelationAttributeValue, "The next page link ATOM metadata must have the rel set to 'next'.");
                    string nextPageLinkLength = nextPageLink.Length.HasValue ? nextPageLink.Length.Value.ToString() : null;
                    feed.AtomNextPageLink(nextPageLink.Href == null ? null : nextPageLink.Href.OriginalString, nextPageLink.MediaType, nextPageLink.HrefLang, nextPageLink.Title, nextPageLinkLength);
                }

                if (feedMetadata.SourceId != null)
                {
                    // This should only occur when the metadata comes from the source element of an entry
                    // and we are annotating a temporary feed instance
                    feed.AtomId(UriUtils.UriToString(feedMetadata.SourceId));
                }

                if (feedMetadata.Subtitle != null)
                {
                    feed.AtomSubtitle(feedMetadata.Subtitle.Text, ToString(feedMetadata.Subtitle.Kind));
                }

                if (feedMetadata.Title != null)
                {
                    feed.AtomTitle(feedMetadata.Title.Text, ToString(feedMetadata.Title.Kind));
                }

                if (feedMetadata.Updated.HasValue)
                {
                    feed.AtomUpdated(ToString(feedMetadata.Updated));
                }
            }
 /// <summary>
 /// Visit the EntitySetInstance to remove annotations.
 /// </summary>
 /// <param name="payloadElement">payloadElement to visit</param>
 public override void Visit(EntitySetInstance payloadElement)
 {
     payloadElement.Annotations.Clear();
     base.Visit(payloadElement);
 }
Beispiel #59
0
        public void ODataFeedWriterErrorTests()
        {
            var feed = new EntitySetInstance(
                new EntityInstance("TestModel.Type1", false)
                {
                    Properties = new List<PropertyInstance>()
                    {
                        new PrimitiveProperty("StringProp", "Edm.String", "hello"),
                        new PrimitiveProperty("IntProp", "Edm.Int32", 5)
                    }
                },
                new EntityInstance("TestModel.Type2", false)
                {
                    Properties = new List<PropertyInstance>()
                    {
                        new PrimitiveProperty("GuidProp", "Edm.Guid", Guid.NewGuid()),
                        new PrimitiveProperty("BooleanProp", "Edm.Boolean", true)
                    }
                }
            ).WithDefaultAtomIDAnnotation();
            
            List<PayloadWriterTestDescriptor<ODataPayloadElement>> testDescriptors = new List<PayloadWriterTestDescriptor<ODataPayloadElement>>()
            {
                // Skipping json because there is a fixup in the PayloadWriterTestDescriptor that will add the ID.
                // Write feed without ID.
                new PayloadWriterTestDescriptor<ODataPayloadElement>(this.Settings, (ODataPayloadElement)null)
                {
                    PayloadElement = new EntitySetInstance(),
                    SkipTestConfiguration = (tc) => tc.Format == ODataFormat.Json,
                    ExpectedResultCallback = (tc) => new PayloadWriterTestExpectedResults(this.ExpectedResultSettings)
                    {
                        ExpectedException2 = ODataExpectedExceptions.ODataException("ODataAtomWriter_FeedsMustHaveNonEmptyId")
                    }
                },
                // Write feed with inline count on a request.
                new PayloadWriterTestDescriptor<ODataPayloadElement>(this.Settings, (ODataPayloadElement)null)
                {
                    PayloadElement = new EntitySetInstance(){ InlineCount = 0 }.WithDefaultAtomIDAnnotation(),
                    SkipTestConfiguration = (tc) => !tc.IsRequest,
                    ExpectedResultCallback = (tc) => new PayloadWriterTestExpectedResults(this.ExpectedResultSettings)
                    {
                        ExpectedException2 = ODataExpectedExceptions.ODataException("ODataWriterCore_QueryCountInRequest")
                    }
                },
                // Write feed with next link on a request.
                new PayloadWriterTestDescriptor<ODataPayloadElement>(this.Settings, (ODataPayloadElement)null)
                {
                    PayloadElement = new EntitySetInstance(){ NextLink = "http://www.odata.org"}.WithDefaultAtomIDAnnotation(),
                    SkipTestConfiguration = (tc) => !tc.IsRequest,
                    ExpectedResultCallback = (tc) => new PayloadWriterTestExpectedResults(this.ExpectedResultSettings)
                    {
                        ExpectedException2 = ODataExpectedExceptions.ODataException("WriterValidationUtils_NextPageLinkInRequest")
                    }
                },
                // TODO: Add appropriate exception and enable the test when this is bug is fixed.
                // new PayloadWriterTestDescriptor<ODataPayloadElement>(this.Settings, feed)
                // {
                //    ExpectedResultCallback = (tc) => new PayloadWriterTestExpectedResults(this.ExpectedResultSettings)
                //    {
                //        ExpectedException2 = 
                //    }
                // },
            };

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfig) =>
                {
                    testConfig = testConfig.Clone();
                    testConfig.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                    testDescriptor.RunTest(testConfig, this.Logger);
                });
        }