/// <summary> /// Adds a new author to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the author to.</param> /// <param name="authorMetadata">The author metadata to add.</param> internal static void AddAuthor(this AtomFeedMetadata feedMetadata, AtomPersonMetadata authorMetadata) { Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(authorMetadata != null, "authorMetadata != null"); feedMetadata.Authors = feedMetadata.Authors.ConcatToReadOnlyEnumerable("Authors", authorMetadata); }
/// <summary> /// Adds a new category to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the category to.</param> /// <param name="categoryMetadata">The category metadata to add.</param> internal static void AddCategory(this AtomFeedMetadata feedMetadata, AtomCategoryMetadata categoryMetadata) { Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(categoryMetadata != null, "categoryMetadata != null"); feedMetadata.Categories = feedMetadata.Categories.ConcatToReadOnlyEnumerable("Categories", categoryMetadata); }
/// <summary> /// Adds a new contributor to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the contributor to.</param> /// <param name="contributorMetadata">The author metadata to add.</param> internal static void AddContributor(this AtomFeedMetadata feedMetadata, AtomPersonMetadata contributorMetadata) { Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(contributorMetadata != null, "contributorMetadata != null"); feedMetadata.Contributors = feedMetadata.Contributors.ConcatToReadOnlyEnumerable("Contributors", contributorMetadata); }
private void CreateTestDescriptorsAndRunTests(FeedMetadataTestCase[] testCases, Func <PayloadWriterTestDescriptor <ODataItem>, IEnumerable <PayloadWriterTestDescriptor <ODataItem> > > payloads) { // Convert test cases to test descriptions IEnumerable <Func <ODataFeed> > feedCreators = new Func <ODataFeed>[] { () => ObjectModelUtils.CreateDefaultFeed(), () => ObjectModelUtils.CreateDefaultFeedWithAtomMetadata(), }; var testDescriptors = testCases.SelectMany(testCase => feedCreators.Select(feedCreator => { ODataFeed feed = feedCreator(); AtomFeedMetadata metadata = feed.Atom(); this.Assert.IsNotNull(metadata, "Expected default feed metadata on a default feed."); testCase.CustomizeMetadata(metadata); ODataItem[] payloadItems = testCase.CustomizePayload == null ? new ODataItem[] { feed } : testCase.CustomizePayload(feed); return(new PayloadWriterTestDescriptor <ODataItem>(this.Settings, payloadItems, testConfiguration => { if (testCase.SkipTestConfiguration != null && testCase.SkipTestConfiguration(testConfiguration)) { return null; } return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = testCase.Xml, FragmentExtractor = testCase.Extractor, ExpectedException2 = testCase.ExpectedException }; })); })); this.CombinatorialEngineProvider.RunCombinations(testDescriptors.PayloadCases(WriterPayloads.TopLevelValuePayload), this.WriterTestConfigurationProvider.AtomFormatConfigurations, (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
/// <summary> /// Adds a new link to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the link to.</param> /// <param name="linkMetadata">The link metadata to add.</param> internal static void AddLink(this AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata) { Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(linkMetadata != null, "linkMetadata != null"); feedMetadata.Links = feedMetadata.Links.ConcatToReadOnlyEnumerable("Ref", linkMetadata); }
/// <summary> /// Write the ATOM metadata for a feed /// </summary> /// <param name="writer">The Xml writer to write to.</param> /// <param name="baseUri">The base Uri of the document or null if none was specified.</param> /// <param name="feed">The feed for which to write the metadata.</param> internal static void WriteFeedMetadata(XmlWriter writer, Uri baseUri, ODataFeed feed) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(writer != null, "writer != null"); Debug.Assert(feed != null, "feed != null"); AtomFeedMetadata feedMetadata = feed.GetAnnotation <AtomFeedMetadata>(); if (feedMetadata == null) { // create the required metadata elements with default values. // <atom:id>idValue</atom:id> Debug.Assert(!string.IsNullOrEmpty(feed.Id), "The feed Id should have been validated by now."); ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIdElementName, AtomConstants.AtomNamespace, feed.Id); // <atom:title></atom:title> ODataAtomWriterUtils.WriteEmptyElement(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace); // <atom:updated>dateTimeOffset</atom:updated> ODataAtomWriterUtils.WriteElementWithTextContent(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(DateTimeOffset.UtcNow)); } else { WriteFeedMetadata(writer, baseUri, feedMetadata, feed); } }
public void CreateODataFeed_Sets_FeedSelfLink() { // Arrange var feedInstance = new object[0]; ODataSerializerContext writeContext = new ODataSerializerContext { EntitySet = _customerSet, Model = _model, Request = new HttpRequestMessage() }; writeContext.Url = new UrlHelper(writeContext.Request); ODataFeedSerializer serializer = new ODataFeedSerializer(new DefaultODataSerializerProvider()); Uri feedSelfLink = new Uri("http://feed_self_link/"); EntitySetLinkBuilderAnnotation linkBuilder = new MockEntitySetLinkBuilderAnnotation { FeedSelfLinkBuilder = (context) => { Assert.Equal(_customerSet, context.EntitySet); Assert.Equal(feedInstance, context.FeedInstance); Assert.Equal(writeContext.Request, context.Request); Assert.Equal(writeContext.Url, context.Url); return(feedSelfLink); } }; _model.SetEntitySetLinkBuilder(_customerSet, linkBuilder); // Act ODataFeed feed = serializer.CreateODataFeed(feedInstance, _customersType, writeContext); // Assert AtomFeedMetadata feedMetadata = feed.GetAnnotation <AtomFeedMetadata>(); Assert.Equal(feedSelfLink, feedMetadata.SelfLink.Href); Assert.Equal("self", feedMetadata.SelfLink.Relation); }
internal static void AddLinkToFeedMetadata(AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata) { if (object.ReferenceEquals(feedMetadata.Links, EmptyLinksList)) { feedMetadata.Links = new ReadOnlyEnumerable <AtomLinkMetadata>(); } ReaderUtils.GetSourceListOfEnumerable <AtomLinkMetadata>(feedMetadata.Links, "Links").Add(linkMetadata); }
internal static void AddContributorToFeedMetadata(AtomFeedMetadata feedMetadata, AtomPersonMetadata contributorMetadata) { if (object.ReferenceEquals(feedMetadata.Contributors, EmptyPersonsList)) { feedMetadata.Contributors = new ReadOnlyEnumerable <AtomPersonMetadata>(); } ReaderUtils.GetSourceListOfEnumerable <AtomPersonMetadata>(feedMetadata.Contributors, "Contributors").Add(contributorMetadata); }
internal static void AddCategoryToFeedMetadata(AtomFeedMetadata feedMetadata, AtomCategoryMetadata categoryMetadata) { if (object.ReferenceEquals(feedMetadata.Categories, EmptyCategoriesList)) { feedMetadata.Categories = new ReadOnlyEnumerable <AtomCategoryMetadata>(); } ReaderUtils.GetSourceListOfEnumerable <AtomCategoryMetadata>(feedMetadata.Categories, "Categories").Add(categoryMetadata); }
/// <summary> /// Adds a new link to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the link to.</param> /// <param name="linkMetadata">The link metadata to add.</param> internal static void AddLink(this AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(linkMetadata != null, "linkMetadata != null"); feedMetadata.Links = feedMetadata.Links.ConcatToReadOnlyEnumerable("Links", linkMetadata); }
/// <summary> /// Visits an ATOM feed metadata. /// </summary> /// <param name="atomFeedMetadata">The feed metadata to visit.</param> protected override void VisitAtomFeedMetadata(AtomFeedMetadata atomFeedMetadata) { this.ValidateEnumerable <AtomPersonMetadata>(atomFeedMetadata.Authors, "AtomFeedMetadata.Authors"); this.ValidateEnumerable <AtomCategoryMetadata>(atomFeedMetadata.Categories, "AtomFeedMetadata.Categories"); this.ValidateEnumerable <AtomPersonMetadata>(atomFeedMetadata.Contributors, "AtomFeedMetadata.Contributors"); this.ValidateEnumerable <AtomLinkMetadata>(atomFeedMetadata.Links, "AtomFeedMetadata.Links"); base.VisitAtomFeedMetadata(atomFeedMetadata); }
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> /// Adds a new contributor to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the contributor to.</param> /// <param name="contributorMetadata">The author metadata to add.</param> internal static void AddContributorToFeedMetadata(AtomFeedMetadata feedMetadata, AtomPersonMetadata contributorMetadata) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(contributorMetadata != null, "contributorMetadata != null"); if (object.ReferenceEquals(feedMetadata.Contributors, EmptyPersonsList)) { feedMetadata.Contributors = new ReadOnlyEnumerable <AtomPersonMetadata>(); } ReaderUtils.GetSourceListOfEnumerable(feedMetadata.Contributors, "Contributors").Add(contributorMetadata); }
/// <summary> /// Adds a new link to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the link to.</param> /// <param name="linkMetadata">The link metadata to add.</param> internal static void AddLinkToFeedMetadata(AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(linkMetadata != null, "linkMetadata != null"); if (object.ReferenceEquals(feedMetadata.Links, EmptyLinksList)) { feedMetadata.Links = new ReadOnlyEnumerable <AtomLinkMetadata>(); } ReaderUtils.GetSourceListOfEnumerable(feedMetadata.Links, "Links").Add(linkMetadata); }
/// <summary> /// Adds a new category to feed metadata. /// </summary> /// <param name="feedMetadata">The feed metadata to add the category to.</param> /// <param name="categoryMetadata">The category metadata to add.</param> internal static void AddCategoryToFeedMetadata(AtomFeedMetadata feedMetadata, AtomCategoryMetadata categoryMetadata) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(feedMetadata != null, "feedMetadata != null"); Debug.Assert(categoryMetadata != null, "categoryMetadata != null"); if (object.ReferenceEquals(feedMetadata.Categories, EmptyCategoriesList)) { feedMetadata.Categories = new ReadOnlyEnumerable <AtomCategoryMetadata>(); } ReaderUtils.GetSourceListOfEnumerable(feedMetadata.Categories, "Categories").Add(categoryMetadata); }
/// <summary> /// Visits an ATOM feed metadata. /// </summary> /// <param name="atomFeedMetadata">The feed metadata to visit.</param> protected virtual void VisitAtomFeedMetadata(AtomFeedMetadata atomFeedMetadata) { IEnumerable <AtomPersonMetadata> authors = atomFeedMetadata.Authors; if (authors != null) { foreach (AtomPersonMetadata author in authors) { this.VisitAtomMetadata(author); } } IEnumerable <AtomCategoryMetadata> categories = atomFeedMetadata.Categories; if (categories != null) { foreach (AtomCategoryMetadata category in categories) { this.VisitAtomMetadata(category); } } IEnumerable <AtomPersonMetadata> contributors = atomFeedMetadata.Contributors; if (contributors != null) { foreach (AtomPersonMetadata contributor in contributors) { this.VisitAtomMetadata(contributor); } } this.VisitAtomMetadata(atomFeedMetadata.Generator); IEnumerable <AtomLinkMetadata> links = atomFeedMetadata.Links; if (links != null) { foreach (AtomLinkMetadata link in links) { this.VisitAtomMetadata(link); } } this.VisitAtomMetadata(atomFeedMetadata.Rights); this.VisitAtomMetadata(atomFeedMetadata.SelfLink); this.VisitAtomMetadata(atomFeedMetadata.Subtitle); this.VisitAtomMetadata(atomFeedMetadata.Title); }
/// <summary> /// Fixup AtomFeedMetadata to fix hte baselne issue for Atom Feed payload generator /// </summary> /// <param name="metadata">the AtomFeedMetadata</param> /// <returns>fix-up AtomFeedMetadata</returns> public static AtomFeedMetadata Fixup(this AtomFeedMetadata metadata) { if (metadata == null) { return(new AtomFeedMetadata() { Updated = DateTimeOffset.MaxValue }); } if (metadata.Updated == null) { metadata.Updated = DateTimeOffset.MaxValue; } return(metadata); }
/// <summary> /// Visits an ATOM feed metadata. /// </summary> /// <param name="atomFeedMetadata">The feed metadata to visit.</param> protected override void VisitAtomFeedMetadata(AtomFeedMetadata atomFeedMetadata) { this.ValidateUri(atomFeedMetadata.Icon); this.ValidateUri(atomFeedMetadata.Logo); base.VisitAtomFeedMetadata(atomFeedMetadata); }
/// <summary> /// Writes the feed element for the atom payload. /// </summary> /// <param name="expanded">Expanded properties for the result.</param> /// <param name="elements">Collection of entries in the feed element.</param> /// <param name="expectedType">ExpectedType of the elements in the collection.</param> /// <param name="title">Title of the feed element.</param> /// <param name="getRelativeUri">Callback to get the relative uri of the feed.</param> /// <param name="getAbsoluteUri">Callback to get the absolute uri of the feed.</param> /// <param name="topLevel">True if the feed is the top level feed, otherwise false for the inner expanded feed.</param> private void WriteFeedElements( IExpandedResult expanded, QueryResultInfo elements, ResourceType expectedType, string title, Func <Uri> getRelativeUri, Func <Uri> getAbsoluteUri, bool topLevel) { Debug.Assert(elements != null, "elements != null"); Debug.Assert(expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType, "expectedType != null && expectedType.ResourceTypeKind == ResourceTypeKind.EntityType"); Debug.Assert(!string.IsNullOrEmpty(title), "!string.IsNullOrEmpty(title)"); ODataFeed feed = new ODataFeed(); feed.SetSerializationInfo(new ODataFeedAndEntrySerializationInfo { NavigationSourceName = this.CurrentContainer.Name, NavigationSourceEntityTypeName = this.CurrentContainer.ResourceType.FullName, ExpectedTypeName = expectedType.FullName }); // Write the other elements for the feed this.PayloadMetadataPropertyManager.SetId(feed, () => getAbsoluteUri()); #pragma warning disable 618 if (this.contentFormat == ODataFormat.Atom) #pragma warning restore 618 { // Create the atom feed metadata and set the self link and title value. AtomFeedMetadata feedMetadata = new AtomFeedMetadata(); feed.SetAnnotation(feedMetadata); feedMetadata.Title = new AtomTextConstruct { Text = title }; feedMetadata.SelfLink = new AtomLinkMetadata { Href = getRelativeUri(), Title = title }; } // support for $count // in ATOM we write it at the beginning (we always have) // in JSON for backward compatiblity reasons we write it at the end, so we must not fill it here. if (topLevel && this.RequestDescription.CountOption == RequestQueryCountOption.CountQuery) { feed.Count = this.RequestDescription.CountValue; } var feedArgs = elements.GetDataServiceODataWriterFeedArgs(feed, this.Service.OperationContext); this.dataServicesODataWriter.WriteStart(feedArgs); object lastObject = null; IExpandedResult lastExpandedSkipToken = null; while (elements.HasMoved) { object o = elements.Current; IExpandedResult skipToken = this.GetSkipToken(expanded); if (o != null) { IExpandedResult expandedO = o as IExpandedResult; if (expandedO != null) { expanded = expandedO; o = GetExpandedElement(expanded); skipToken = this.GetSkipToken(expanded); } this.WriteEntry(expanded, o, true /*resourceInstanceInFeed*/, expectedType); } elements.MoveNext(); lastObject = o; lastExpandedSkipToken = skipToken; } // After looping through the objects in the sequence, decide if we need to write the next // page link and if yes, write it by invoking the delegate if (this.NeedNextPageLink(elements)) { this.PayloadMetadataPropertyManager.SetNextPageLink( feed, this.AbsoluteServiceUri, this.GetNextLinkUri(lastObject, lastExpandedSkipToken, getAbsoluteUri())); } this.dataServicesODataWriter.WriteEnd(feedArgs); #if ASTORIA_FF_CALLBACKS this.Service.InternalOnWriteFeed(feed); #endif }
public void PayloadOrderTest() { ODataFeedAndEntrySerializationInfo info = new ODataFeedAndEntrySerializationInfo() { NavigationSourceEntityTypeName = "Null", NavigationSourceName = "MySet", ExpectedTypeName = "Null" }; AtomFeedMetadata defaultAtomFeedMetadata = new AtomFeedMetadata() { Authors = new[] { new AtomPersonMetadata { Name = "Bart" } }, Updated = ObjectModelUtils.DefaultEntryUpdatedDateTime }; IEnumerable <PayloadOrderTestCase> testCases = new[] { new PayloadOrderTestCase { DebugDescription = "Just ID", Feed = new ODataFeed() { Id = new Uri("http://MyFeedId"), SerializationInfo = info } .WithAnnotation(defaultAtomFeedMetadata), Xml = string.Join( "$(NL)", "<feed xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <id>http://MyFeedId</id>", " <title />", " <updated>2010-10-12T17:13:00Z</updated>", " <author>", " <name>Bart</name>", " </author>{0}", "</feed>"), }, new PayloadOrderTestCase { DebugDescription = "Just ID, and another ID at the end, the one from the starts is used", Feed = new ODataFeed() { SerializationInfo = info } .WithAnnotation(new WriteFeedCallbacksAnnotation { BeforeWriteStartCallback = (feed) => { feed.Id = new Uri("http://MyFeedId"); }, BeforeWriteEndCallback = (feed) => { feed.Id = new Uri("http://AnotherFeedId"); } }) .WithAnnotation(defaultAtomFeedMetadata), Xml = string.Join( "$(NL)", "<feed xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <id>http://MyFeedId</id>", " <title />", " <updated>2010-10-12T17:13:00Z</updated>", " <author>", " <name>Bart</name>", " </author>{0}", "</feed>"), }, new PayloadOrderTestCase { DebugDescription = "ID and no author metadata and no entities, the default author should be written.", Feed = new ODataFeed() { Id = new Uri("http://MyFeedId"), SerializationInfo = info } .WithAnnotation(new AtomFeedMetadata { Updated = ObjectModelUtils.DefaultEntryUpdatedDateTime }), Xml = string.Join( "$(NL)", "<feed xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <id>http://MyFeedId</id>", " <title />", " <updated>2010-10-12T17:13:00Z</updated>{0}", " <author>", " <name />", " </author>", "</feed>"), NoEntitiesOnly = true }, new PayloadOrderTestCase { DebugDescription = "ID and no author metadata but with entities, no author is written.", Feed = new ODataFeed() { Id = new Uri("http://MyFeedId"), SerializationInfo = info } .WithAnnotation(new AtomFeedMetadata { Updated = ObjectModelUtils.DefaultEntryUpdatedDateTime }), Xml = string.Join( "$(NL)", "<feed xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <id>http://MyFeedId</id>", " <title />", " <updated>2010-10-12T17:13:00Z</updated>{0}", "</feed>"), WithEntitiesOnly = true }, new PayloadOrderTestCase { DebugDescription = "ID, count at the end - the count is ignored", Feed = new ODataFeed() { Id = new Uri("http://MyFeedId"), SerializationInfo = info } .WithAnnotation(new WriteFeedCallbacksAnnotation { BeforeWriteStartCallback = (feed) => { feed.Count = null; }, BeforeWriteEndCallback = (feed) => { feed.Count = 42; } }) .WithAnnotation(defaultAtomFeedMetadata), Xml = string.Join( "$(NL)", "<feed xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <id>http://MyFeedId</id>", " <title />", " <updated>2010-10-12T17:13:00Z</updated>", " <author>", " <name>Bart</name>", " </author>{0}", "</feed>"), }, new PayloadOrderTestCase { DebugDescription = "ID, count and next link", Feed = new ODataFeed() { Id = new Uri("http://MyFeedId"), Count = 42, NextPageLink = new Uri("http://odata.org/nextlink"), SerializationInfo = info } .WithAnnotation(defaultAtomFeedMetadata), Xml = string.Join( "$(NL)", "<feed xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <count xmlns=\"http://docs.oasis-open.org/odata/ns/metadata\">42</count>", " <id>http://MyFeedId</id>", " <title />", " <updated>2010-10-12T17:13:00Z</updated>", " <author>", " <name>Bart</name>", " </author>{0}", " <link rel=\"next\" href=\"http://odata.org/nextlink\" />", "</feed>"), }, new PayloadOrderTestCase { DebugDescription = "ID, count and next link and some ATOM metadata, metadata goes before entries but author is the last of them.", Feed = new ODataFeed() { Id = new Uri("http://MyFeedId"), Count = 42, NextPageLink = new Uri("http://odata.org/nextlink"), SerializationInfo = info } .WithAnnotation(new AtomFeedMetadata() { Authors = new[] { new AtomPersonMetadata { Name = "Bart" } }, Updated = ObjectModelUtils.DefaultEntryUpdatedDateTime, Logo = new Uri("http://odata.org/logo") }), Xml = string.Join( "$(NL)", "<feed xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <count xmlns=\"http://docs.oasis-open.org/odata/ns/metadata\">42</count>", " <id>http://MyFeedId</id>", " <title />", " <updated>2010-10-12T17:13:00Z</updated>", " <logo>http://odata.org/logo</logo>", " <author>", " <name>Bart</name>", " </author>{0}", " <link rel=\"next\" href=\"http://odata.org/nextlink\" />", "</feed>"), }, }; IEnumerable <PayloadWriterTestDescriptor <ODataItem> > testDescriptors = testCases.Where(testCase => !testCase.WithEntitiesOnly).Select(testCase => new PayloadWriterTestDescriptor <ODataItem>( this.Settings, new ODataItem[] { testCase.Feed }, tc => new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = string.Format(CultureInfo.InvariantCulture, testCase.Xml, string.Empty), FragmentExtractor = (element) => element }) { DebugDescription = testCase.DebugDescription, }); testDescriptors = testDescriptors.Concat(testCases.Where(testCase => !testCase.NoEntitiesOnly).Select(testCase => new PayloadWriterTestDescriptor <ODataItem>( this.Settings, new ODataItem[] { testCase.Feed, new ODataEntry { } .WithAnnotation(new AtomEntryMetadata { Updated = ObjectModelUtils.DefaultEntryUpdatedDateTime }), }, tc => new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = string.Format(CultureInfo.InvariantCulture, testCase.Xml, string.Join( "$(NL)", "<entry xmlns=\"" + TestAtomConstants.AtomNamespace + "\">", " <id />", " <title />", " <updated>2010-10-12T17:13:00Z</updated>", " <author>", " <name />", " </author>", " <content type=\"application/xml\" />", "</entry>")), FragmentExtractor = (element) => element }) { DebugDescription = testCase.DebugDescription + "- with entry", })); this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.WriterTestConfigurationProvider.AtomFormatConfigurationsWithIndent .Where(tc => !tc.IsRequest), (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
public void GeneratorMetadataWriterTest() { string testName = "Test generator"; string testUri = "http://odata.org/generator"; string testVersion = "3.0"; var testCases = new[] { new { Generator = new AtomGeneratorMetadata() { Name = testName, Uri = new Uri(testUri), Version = testVersion }, Xml = @"<generator uri=""" + testUri + @""" version=""" + testVersion + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testName + @"</generator>", ExpectedException = (string)null }, new { Generator = new AtomGeneratorMetadata() { Name = testName, Uri = null, Version = null }, Xml = @"<generator xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testName + @"</generator>", ExpectedException = (string)null }, new { Generator = new AtomGeneratorMetadata() { Name = string.Empty, Uri = null, Version = null }, Xml = @"<generator xmlns=""" + TestAtomConstants.AtomNamespace + @"""></generator>", ExpectedException = (string)null }, new { Generator = new AtomGeneratorMetadata() { Name = null, Uri = null, Version = null }, Xml = @"<generator xmlns=""" + TestAtomConstants.AtomNamespace + @""" />", ExpectedException = (string)null }, new { Generator = new AtomGeneratorMetadata() { Name = "\n\t ", Uri = null, Version = null }, Xml = @"<generator xml:space=""preserve"" xmlns=""" + TestAtomConstants.AtomNamespace + "\">\n\t </generator>", ExpectedException = (string)null }, }; Func <XElement, XElement> fragmentExtractor = (e) => e.Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomGeneratorElementName); // Convert test cases to test descriptions var testDescriptors = testCases.Select(testCase => { ODataFeed feed = ObjectModelUtils.CreateDefaultFeedWithAtomMetadata(); AtomFeedMetadata metadata = feed.Atom(); this.Assert.IsNotNull(metadata, "Expected default feed metadata on a default feed."); metadata.Generator = testCase.Generator; return(new PayloadWriterTestDescriptor <ODataItem>(this.Settings, feed, testConfiguration => new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = testCase.Xml, ExpectedODataExceptionMessage = testCase.ExpectedException, FragmentExtractor = fragmentExtractor, PreserveWhitespace = true })); }); this.CombinatorialEngineProvider.RunCombinations( testDescriptors.PayloadCases(WriterPayloads.FeedPayloads), this.WriterTestConfigurationProvider.AtomFormatConfigurations, (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
public void EntryMetadataWriterTest() { const string testPublished = "2010-10-20T20:10:00Z"; AtomTextConstruct testRights = new AtomTextConstruct { Text = "Copyright Data Fx team." }; AtomTextConstruct testSummary = new AtomTextConstruct { Text = "Test summary." }; AtomTextConstruct testTitle = new AtomTextConstruct { Text = "Test title" }; const string testUpdated = "2010-11-01T00:04:00Z"; const string testIcon = "http://odata.org/icon"; const string testSourceId = "http://odata.org/id/random"; const string testLogo = "http://odata.org/logo"; AtomTextConstruct testSubtitle = new AtomTextConstruct { Text = "Test subtitle." }; const string testAuthorName = "Test Author 1"; const string testAuthorEmail = "*****@*****.**"; const string testAuthorUri = "http://odata.org/authors/1"; var testAuthors = new AtomPersonMetadata[] { new AtomPersonMetadata() { Email = testAuthorEmail, Name = testAuthorName, Uri = new Uri(testAuthorUri) } }; var testAuthors2 = new AtomPersonMetadata[0]; const string testCategoryTerm = "Test category 1 term"; const string testCategoryLabel = "Test category 1 label"; const string testCategoryScheme = "http://odata.org/categories/1"; var testCategories = new AtomCategoryMetadata[] { new AtomCategoryMetadata() { Term = testCategoryTerm, Label = testCategoryLabel, Scheme = testCategoryScheme } }; const string testContributorName = "Test Contributor 1"; const string testContributorEmail = "*****@*****.**"; const string testContributorUri = "http://odata.org/contributors/1"; var testContributors = new AtomPersonMetadata[] { new AtomPersonMetadata() { Email = testContributorEmail, Name = testContributorName, Uri = new Uri(testContributorUri) } }; const string testGeneratorName = "Test generator"; const string testGeneratorUri = "http://odata.org/generator"; const string testGeneratorVersion = "3.0"; var testGenerator = new AtomGeneratorMetadata() { Name = testGeneratorName, Uri = new Uri(testGeneratorUri), Version = testGeneratorVersion }; const string testLinkRelation = "http://odata.org/links/1"; const string testLinkTitle = "Test link 1"; const string testLinkHref = "http://odata.org/links/1"; const string testLinkHrefLang = "de-AT"; int? testLinkLength = 999; const string testLinkMediaType = "image/png"; var testLinks = new AtomLinkMetadata[] { new AtomLinkMetadata() { Relation = testLinkRelation, Title = testLinkTitle, Href = new Uri(testLinkHref), HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType } }; AtomFeedMetadata testSource = new AtomFeedMetadata() { Authors = testAuthors, Categories = testCategories, Contributors = testContributors, Generator = testGenerator, Icon = new Uri(testIcon), SourceId = new Uri(testSourceId), Links = testLinks, Logo = new Uri(testLogo), Rights = testRights, Subtitle = testSubtitle, Title = testTitle, Updated = DateTimeOffset.Parse(testUpdated) }; Func <string, Func <XElement, XElement> > fragmentExtractor = (localName) => (e) => e.Element(TestAtomConstants.AtomXNamespace + localName); // TODO, ckerer: specify an Id via metadata if the entry does not specify one; we first have to decide what rules // we want to apply to merging of metadata and ODataLib OM data. var testCases = new[] { new { // specify an author via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Authors = testAuthors), Xml = string.Join( "$(NL)", @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">", @" <name>" + testAuthorName + @"</name>", @" <uri>" + testAuthorUri + @"</uri>", @" <email>" + testAuthorEmail + @"</email>", @"</author>"), Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName) }, new { // specify an empty author array via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Authors = testAuthors2), Xml = string.Join( "$(NL)", @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">", @" <name />", @"</author>"), Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName) }, new { // specify no authors via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Authors = null), Xml = string.Join( "$(NL)", @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">", @"$(Indent)<name />", @"</author>"), Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName) }, new { // specify a category via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Categories = testCategories), Xml = @"<category term=""" + testCategoryTerm + @""" scheme=""" + testCategoryScheme + @""" label=""" + testCategoryLabel + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""" />", Extractor = fragmentExtractor(TestAtomConstants.AtomCategoryElementName) }, new { // specify a contributor via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Contributors = testContributors), Xml = string.Join( "$(NL)", @"<contributor xmlns=""" + TestAtomConstants.AtomNamespace + @""">", @" <name>" + testContributorName + @"</name>", @" <uri>" + testContributorUri + @"</uri>", @" <email>" + testContributorEmail + @"</email>", @"</contributor>"), Extractor = fragmentExtractor(TestAtomConstants.AtomContributorElementName) }, new { // specify a link via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Links = testLinks), Xml = @"<link rel=""" + testLinkRelation + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>", Extractor = new Func <XElement, XElement>( (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName) .Where(l => l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName).Value != TestAtomConstants.AtomSelfRelationAttributeValue) .Single()) }, new { // specify a published date via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Published = DateTimeOffset.Parse(testPublished)), Xml = @"<published xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testPublished + @"</published>", Extractor = fragmentExtractor(TestAtomConstants.AtomPublishedElementName) }, new { // specify rights via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Rights = testRights), Xml = @"<rights type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testRights.Text + @"</rights>", Extractor = fragmentExtractor(TestAtomConstants.AtomRightsElementName) }, new { // specify a source via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Source = testSource), Xml = string.Join( "$(NL)", @"<source xmlns=""" + TestAtomConstants.AtomNamespace + @""">", @" <id>" + testSourceId + "</id>", @" <title type=""text"">" + testTitle.Text + @"</title>", @" <subtitle type=""text"">" + testSubtitle.Text + @"</subtitle>", @" <updated>" + testUpdated + @"</updated>", @" <link rel=""" + testLinkRelation + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""/>", @" <category term=""" + testCategoryTerm + @""" scheme=""" + testCategoryScheme + @""" label=""" + testCategoryLabel + @""" />", @" <logo>" + testLogo + @"</logo>", @" <rights type=""text"">" + testRights.Text + @"</rights>", @" <contributor>", @" <name>" + testContributorName + @"</name>", @" <uri>" + testContributorUri + @"</uri>", @" <email>" + testContributorEmail + @"</email>", @" </contributor>", @" <generator uri=""" + testGeneratorUri + @""" version=""" + testGeneratorVersion + @""">" + testGeneratorName + @"</generator>", @" <icon>" + testIcon + @"</icon>", @" <author>", @" <name>" + testAuthorName + @"</name>", @" <uri>" + testAuthorUri + @"</uri>", @" <email>" + testAuthorEmail + @"</email>", @" </author>", @"</source>"), Extractor = fragmentExtractor(TestAtomConstants.AtomSourceElementName) }, new { // specify default feed metadata as source CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Source = new AtomFeedMetadata()), Xml = string.Join( "$(NL)", @"<source xmlns=""" + TestAtomConstants.AtomNamespace + @""">", @" <id />", @" <title />", @" <updated />", @"</source>"), Extractor = new Func <XElement, XElement>(result => { var source = fragmentExtractor(TestAtomConstants.AtomSourceElementName)(result); // Remove the value of updates as it can't be reliably predicted source.Element(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomUpdatedElementName).Nodes().Remove(); return(source); }) }, new { // specify a summary via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Summary = testSummary), Xml = @"<summary type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testSummary.Text + @"</summary>", Extractor = fragmentExtractor(TestAtomConstants.AtomSummaryElementName) }, new { // specify a title via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Title = testTitle), Xml = @"<title type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testTitle.Text + @"</title>", Extractor = fragmentExtractor(TestAtomConstants.AtomTitleElementName) }, new { // specify an updated date via metadata CustomizeMetadata = new Action <AtomEntryMetadata>(metadata => metadata.Updated = DateTimeOffset.Parse(testUpdated)), Xml = @"<updated xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testUpdated + @"</updated>", Extractor = fragmentExtractor(TestAtomConstants.AtomUpdatedElementName) }, }; // Convert test cases to test descriptions IEnumerable <Func <ODataEntry> > entryCreators = new Func <ODataEntry>[] { () => ObjectModelUtils.CreateDefaultEntry(), () => ObjectModelUtils.CreateDefaultEntryWithAtomMetadata(), }; var testDescriptors = testCases.SelectMany(testCase => entryCreators.Select(entryCreator => { ODataEntry entry = entryCreator(); AtomEntryMetadata metadata = entry.Atom(); this.Assert.IsNotNull(metadata, "Expected default entry metadata on a default entry."); testCase.CustomizeMetadata(metadata); return(new PayloadWriterTestDescriptor <ODataItem>(this.Settings, entry, testConfiguration => new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings) { Xml = testCase.Xml, FragmentExtractor = testCase.Extractor })); })); this.CombinatorialEngineProvider.RunCombinations( testDescriptors.PayloadCases(WriterPayloads.EntryPayloads), this.WriterTestConfigurationProvider.AtomFormatConfigurations, (testDescriptor, testConfiguration) => { testConfiguration = testConfiguration.Clone(); testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor, testConfiguration, this.Assert, this.Logger); }); }
/// <summary> /// Write the given feed metadata in atom format /// </summary> /// <param name="writer">The Xml writer to write to.</param> /// <param name="baseUri">The base Uri of the document or null if none was specified.</param> /// <param name="feedMetadata">The metadata to write.</param> /// <param name="feed">The feed for which to write the meadata or null if it is the metadata of an atom:source element.</param> private static void WriteFeedMetadata(XmlWriter writer, Uri baseUri, AtomFeedMetadata feedMetadata, ODataFeed feed) { Debug.Assert(writer != null, "writer != null"); Debug.Assert(feedMetadata != null, "Feed metadata must not be null!"); // <atom:id>text</atom:id> // NOTE: this is the Id of the feed. For a regular feed this is stored on the feed itself; // if used in the context of an <atom:source> element it is stored in metadata Debug.Assert(feed == null || !string.IsNullOrEmpty(feed.Id), "The feed Id should have been validated by now."); string id = feed == null ? feedMetadata.SourceId : feed.Id; ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIdElementName, AtomConstants.AtomNamespace, id); // <atom:title>text</atom:title> // NOTE: write an empty element if no title is specified since the element is required ODataAtomWriterMetadataUtils.WriteTextConstruct(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace, feedMetadata.Title); if (feedMetadata.Subtitle != null) { // <atom:subtitle>text</atom:subtitle> ODataAtomWriterMetadataUtils.WriteTextConstruct(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomSubtitleElementName, AtomConstants.AtomNamespace, feedMetadata.Subtitle); } // <atom:updated>date</atom:updated> // NOTE: the <updated> element is required and if not specified the best we can do is to create a default // one with the current date/time. DateTimeOffset updated = feedMetadata.Updated.HasValue ? feedMetadata.Updated.Value : DateTimeOffset.UtcNow; ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(updated)); IEnumerable<AtomPersonMetadata> authors = feedMetadata.Authors; if (authors != null) { foreach (AtomPersonMetadata author in authors) { // <atom:author>author data</atom:author> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomAuthorElementName, AtomConstants.AtomNamespace); WritePersonMetadata(writer, baseUri, author); writer.WriteEndElement(); } } IEnumerable<AtomLinkMetadata> links = feedMetadata.Links; if (links != null) { foreach (AtomLinkMetadata link in links) { // <atom:link>...</atom:link> WriteAtomLinkMetadata(writer, baseUri, link); } } IEnumerable<AtomCategoryMetadata> categories = feedMetadata.Categories; if (categories != null) { foreach (AtomCategoryMetadata category in categories) { // <atom:category term="..." scheme="..." label="..."></atom:category> WriteCategory(writer, category); } } Uri logo = feedMetadata.Logo; if (logo != null) { // <atom:logo>Uri</atom:logo> ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLogoElementName, AtomConstants.AtomNamespace, AtomUtils.ToUrlAttributeValue(logo, baseUri)); } if (feedMetadata.Rights != null) { // <atom:rights>rights</atom:rights> ODataAtomWriterMetadataUtils.WriteTextConstruct( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomRightsElementName, AtomConstants.AtomNamespace, feedMetadata.Rights); } IEnumerable<AtomPersonMetadata> contributors = feedMetadata.Contributors; if (contributors != null) { foreach (AtomPersonMetadata contributor in contributors) { // <atom:contributor>contributor data</atom:contributor> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomContributorElementName, AtomConstants.AtomNamespace); WritePersonMetadata(writer, baseUri, contributor); writer.WriteEndElement(); } } AtomGeneratorMetadata generator = feedMetadata.Generator; if (generator != null) { // <atom:generator uri="..." version="...">name</atom:generator> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomGeneratorElementName, AtomConstants.AtomNamespace); if (generator.Uri != null) { writer.WriteAttributeString(AtomConstants.AtomGeneratorUriAttributeName, AtomUtils.ToUrlAttributeValue(generator.Uri, baseUri)); } if (!string.IsNullOrEmpty(generator.Version)) { writer.WriteAttributeString(AtomConstants.AtomGeneratorVersionAttributeName, generator.Version); } writer.WriteString(generator.Name); writer.WriteEndElement(); } Uri icon = feedMetadata.Icon; if (icon != null) { // <atom:icon>Uri</atom:icon> ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIconElementName, AtomConstants.AtomNamespace, AtomUtils.ToUrlAttributeValue(icon, baseUri)); } }
private static AtomFeedMetadata CreateFeedMetadata(IEnumerable <XmlTreeAnnotation> children, ODataFeed feed) { AtomFeedMetadata metadata = null; foreach (XmlTreeAnnotation epmTree in children) { if (epmTree.NamespaceName == TestAtomConstants.AtomNamespace) { if (metadata == null) { metadata = new AtomFeedMetadata(); } string localName = epmTree.LocalName; if (localName == TestAtomConstants.AtomAuthorElementName) { AtomPersonMetadata author = CreateAuthorMetadata(epmTree.Children); List <AtomPersonMetadata> authors; if (metadata.Authors == null) { authors = new List <AtomPersonMetadata>(); metadata.Authors = authors; } else { authors = (List <AtomPersonMetadata>)metadata.Authors; } authors.Add(author); } else if (localName == TestAtomConstants.AtomCategoryElementName) { AtomCategoryMetadata category = CreateCategoryMetadata(epmTree.Children); List <AtomCategoryMetadata> categories; if (metadata.Categories == null) { categories = new List <AtomCategoryMetadata>(); metadata.Categories = categories; } else { categories = (List <AtomCategoryMetadata>)metadata.Categories; } categories.Add(category); } else if (localName == TestAtomConstants.AtomContributorElementName) { AtomPersonMetadata contributor = CreateAuthorMetadata(epmTree.Children); List <AtomPersonMetadata> contributors; if (metadata.Contributors == null) { contributors = new List <AtomPersonMetadata>(); metadata.Contributors = contributors; } else { contributors = (List <AtomPersonMetadata>)metadata.Contributors; } contributors.Add(contributor); } else if (localName == TestAtomConstants.AtomGeneratorElementName) { metadata.Generator = CreateGeneratorMetadata(epmTree); } else if (localName == TestAtomConstants.AtomIconElementName) { metadata.Icon = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue); } else if (localName == TestAtomConstants.AtomIdElementName) { Debug.Assert(!epmTree.IsAttribute); Uri id = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue, UriKind.Absolute); if (feed == null) { // we are creating the metadata for an entry's 'source' metadata; // we don't have a feed to store the Id on so it has to go into metadata metadata.SourceId = id; } else { feed.Id = id; } } else if (localName == TestAtomConstants.AtomLinkElementName) { AtomLinkMetadata link = CreateLinkMetadata(epmTree.Children); List <AtomLinkMetadata> links; if (metadata.Links == null) { links = new List <AtomLinkMetadata>(); metadata.Links = links; } else { links = (List <AtomLinkMetadata>)metadata.Contributors; } links.Add(link); } else if (localName == TestAtomConstants.AtomLogoElementName) { metadata.Logo = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue); } else if (localName == TestAtomConstants.AtomRightsElementName) { AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children); metadata.Rights = new AtomTextConstruct { Kind = atomConstructKind, Text = epmTree.PropertyValue }; } else if (localName == TestAtomConstants.AtomSubtitleElementName) { AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children); metadata.Subtitle = new AtomTextConstruct { Kind = atomConstructKind, Text = epmTree.PropertyValue }; } else if (localName == TestAtomConstants.AtomTitleElementName) { AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children); metadata.Title = new AtomTextConstruct { Kind = atomConstructKind, Text = epmTree.PropertyValue }; } else if (localName == TestAtomConstants.AtomUpdatedElementName) { Debug.Assert(!epmTree.IsAttribute); metadata.Updated = string.IsNullOrEmpty(epmTree.PropertyValue) ? (DateTimeOffset?)null : DateTimeOffset.Parse(epmTree.PropertyValue); } else { throw new NotSupportedException("Unsupported atom metadata found!"); } } } return(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> /// Write the ATOM metadata for an entry /// </summary> /// <param name="writer">The Xml writer to write to.</param> /// <param name="baseUri">The base Uri of the document or null if none was specified.</param> /// <param name="entry">The entry for which to write the metadata.</param> /// <param name="epmEntryMetadata">The ATOM metadata for the entry which came from EPM.</param> internal static void WriteEntryMetadata(XmlWriter writer, Uri baseUri, ODataEntry entry, AtomEntryMetadata epmEntryMetadata) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(writer != null, "writer != null"); // TODO, ckerer: implement the rule around authors (an entry has to have an author directly or in the <entry:source> unless the feed has an author). // currently we make all entries have an author. AtomEntryMetadata customEntryMetadata = entry.GetAnnotation <AtomEntryMetadata>(); AtomEntryMetadata entryMetadata = ODataAtomWriterMetadataEpmMergeUtils.MergeCustomAndEpmEntryMetadata(customEntryMetadata, epmEntryMetadata); if (entryMetadata == null) { // write all required metadata elements with default content // <atom:title></atom:title> ODataAtomWriterUtils.WriteEmptyElement(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace); // <atom:updated>dateTimeOffset</atom:updated> // NOTE: the <updated> element is required and if not specified the best we can do is to create a default // one with the current date/time. ODataAtomWriterUtils.WriteElementWithTextContent(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(DateTimeOffset.UtcNow)); WriteEmptyAuthor(writer); } else { // <atom:title>text</atom:title> // NOTE: writes an empty element even if no title was specified since the title is required ODataAtomWriterMetadataUtils.WriteTextConstruct(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace, entryMetadata.Title); AtomTextConstruct summary = entryMetadata.Summary; if (summary != null) { // <atom:summary>text</atom:summary> ODataAtomWriterMetadataUtils.WriteTextConstruct(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomSummaryElementName, AtomConstants.AtomNamespace, summary); } DateTimeOffset?published = entryMetadata.Published; if (published.HasValue) { // <atom:published>dateTimeOffset</atom:published> ODataAtomWriterUtils.WriteElementWithTextContent(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomPublishedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(published.Value)); } // <atom:updated>date</atom:updated> // NOTE: the <updated> element is required and if not specified the best we can do is to create a default // one with the current date/time. DateTimeOffset updated = entryMetadata.Updated.HasValue ? entryMetadata.Updated.Value : DateTimeOffset.UtcNow; ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(updated)); bool wroteAuthor = false; IEnumerable <AtomPersonMetadata> authors = entryMetadata.Authors; if (authors != null) { foreach (AtomPersonMetadata author in authors) { if (author == null) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_AuthorMetadataMustNotContainNull); } // <atom:author>author data</atom:author> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomAuthorElementName, AtomConstants.AtomNamespace); WritePersonMetadata(writer, baseUri, author); writer.WriteEndElement(); wroteAuthor = true; } } if (!wroteAuthor) { // write empty authors since they are required WriteEmptyAuthor(writer); } IEnumerable <AtomPersonMetadata> contributors = entryMetadata.Contributors; if (contributors != null) { foreach (AtomPersonMetadata contributor in contributors) { if (contributor == null) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_ContributorMetadataMustNotContainNull); } // <atom:contributor>contributor data</atom:contributor> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomContributorElementName, AtomConstants.AtomNamespace); WritePersonMetadata(writer, baseUri, contributor); writer.WriteEndElement(); } } IEnumerable <AtomLinkMetadata> links = entryMetadata.Links; if (links != null) { foreach (AtomLinkMetadata link in links) { if (link == null) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_LinkMetadataMustNotContainNull); } // <atom:link>...</atom:link> WriteAtomLinkMetadata(writer, baseUri, link); } } IEnumerable <AtomCategoryMetadata> categories = entryMetadata.Categories; if (categories != null) { foreach (AtomCategoryMetadata category in categories) { if (category == null) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_CategoryMetadataMustNotContainNull); } // <atom:category term="..." scheme="..." label="..."></atom:category> WriteCategory(writer, category); } } if (entryMetadata.Rights != null) { // <atom:rights>rights</atom:rights> ODataAtomWriterMetadataUtils.WriteTextConstruct(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomRightsElementName, AtomConstants.AtomNamespace, entryMetadata.Rights); } Uri icon = entryMetadata.Icon; if (icon != null) { // <atom:icon>Uri</atom:icon> ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIconElementName, AtomConstants.AtomNamespace, AtomUtils.ToUrlAttributeValue(icon, baseUri)); } AtomFeedMetadata source = entryMetadata.Source; if (source != null) { // <atom:source> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomSourceElementName, AtomConstants.AtomNamespace); WriteFeedMetadata(writer, baseUri, source, null); // </atom:source> writer.WriteEndElement(); } } }
/// <summary> /// Write the given feed metadata in atom format /// </summary> /// <param name="writer">The Xml writer to write to.</param> /// <param name="baseUri">The base Uri of the document or null if none was specified.</param> /// <param name="feedMetadata">The metadata to write.</param> /// <param name="feed">The feed for which to write the meadata or null if it is the metadata of an atom:source element.</param> private static void WriteFeedMetadata(XmlWriter writer, Uri baseUri, AtomFeedMetadata feedMetadata, ODataFeed feed) { Debug.Assert(writer != null, "writer != null"); Debug.Assert(feedMetadata != null, "Feed metadata must not be null!"); // <atom:id>text</atom:id> // NOTE: this is the Id of the feed. For a regular feed this is stored on the feed itself; // if used in the context of an <atom:source> element it is stored in metadata Debug.Assert(feed == null || !string.IsNullOrEmpty(feed.Id), "The feed Id should have been validated by now."); string id = feed == null ? feedMetadata.SourceId : feed.Id; ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIdElementName, AtomConstants.AtomNamespace, id); // <atom:title>text</atom:title> // NOTE: write an empty element if no title is specified since the element is required ODataAtomWriterMetadataUtils.WriteTextConstruct(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace, feedMetadata.Title); if (feedMetadata.Subtitle != null) { // <atom:subtitle>text</atom:subtitle> ODataAtomWriterMetadataUtils.WriteTextConstruct(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomSubtitleElementName, AtomConstants.AtomNamespace, feedMetadata.Subtitle); } // <atom:updated>date</atom:updated> // NOTE: the <updated> element is required and if not specified the best we can do is to create a default // one with the current date/time. DateTimeOffset updated = feedMetadata.Updated.HasValue ? feedMetadata.Updated.Value : DateTimeOffset.UtcNow; ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, ODataAtomConvert.ToString(updated)); IEnumerable <AtomPersonMetadata> authors = feedMetadata.Authors; if (authors != null) { foreach (AtomPersonMetadata author in authors) { // <atom:author>author data</atom:author> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomAuthorElementName, AtomConstants.AtomNamespace); WritePersonMetadata(writer, baseUri, author); writer.WriteEndElement(); } } IEnumerable <AtomLinkMetadata> links = feedMetadata.Links; if (links != null) { foreach (AtomLinkMetadata link in links) { // <atom:link>...</atom:link> WriteAtomLinkMetadata(writer, baseUri, link); } } IEnumerable <AtomCategoryMetadata> categories = feedMetadata.Categories; if (categories != null) { foreach (AtomCategoryMetadata category in categories) { // <atom:category term="..." scheme="..." label="..."></atom:category> WriteCategory(writer, category); } } Uri logo = feedMetadata.Logo; if (logo != null) { // <atom:logo>Uri</atom:logo> ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLogoElementName, AtomConstants.AtomNamespace, AtomUtils.ToUrlAttributeValue(logo, baseUri)); } if (feedMetadata.Rights != null) { // <atom:rights>rights</atom:rights> ODataAtomWriterMetadataUtils.WriteTextConstruct( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomRightsElementName, AtomConstants.AtomNamespace, feedMetadata.Rights); } IEnumerable <AtomPersonMetadata> contributors = feedMetadata.Contributors; if (contributors != null) { foreach (AtomPersonMetadata contributor in contributors) { // <atom:contributor>contributor data</atom:contributor> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomContributorElementName, AtomConstants.AtomNamespace); WritePersonMetadata(writer, baseUri, contributor); writer.WriteEndElement(); } } AtomGeneratorMetadata generator = feedMetadata.Generator; if (generator != null) { // <atom:generator uri="..." version="...">name</atom:generator> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomGeneratorElementName, AtomConstants.AtomNamespace); if (generator.Uri != null) { writer.WriteAttributeString(AtomConstants.AtomGeneratorUriAttributeName, AtomUtils.ToUrlAttributeValue(generator.Uri, baseUri)); } if (!string.IsNullOrEmpty(generator.Version)) { writer.WriteAttributeString(AtomConstants.AtomGeneratorVersionAttributeName, generator.Version); } writer.WriteString(generator.Name); writer.WriteEndElement(); } Uri icon = feedMetadata.Icon; if (icon != null) { // <atom:icon>Uri</atom:icon> ODataAtomWriterUtils.WriteElementWithTextContent( writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIconElementName, AtomConstants.AtomNamespace, AtomUtils.ToUrlAttributeValue(icon, baseUri)); } }
private void WriteFeedElements(IExpandedResult expanded, IEnumerator elements, ResourceType expectedType, string title, Uri relativeUri, Uri absoluteUri, bool hasMoved, bool topLevel) { ODataFeed feed = new ODataFeed { Id = absoluteUri.AbsoluteUri }; AtomFeedMetadata annotation = new AtomFeedMetadata(); feed.SetAnnotation <AtomFeedMetadata>(annotation); AtomTextConstruct construct = new AtomTextConstruct { Text = title }; annotation.Title = construct; AtomLinkMetadata metadata2 = new AtomLinkMetadata { Href = relativeUri, Title = title }; annotation.SelfLink = metadata2; bool flag = false; if (topLevel && (base.RequestDescription.CountOption == RequestQueryCountOption.Inline)) { flag = this.contentFormat == ODataFormat.VerboseJson; if (!flag) { feed.Count = new long?(base.RequestDescription.CountValue); } } this.odataWriter.WriteStart(feed); try { object lastObject = null; IExpandedResult skipTokenExpandedResult = null; while (hasMoved) { object current = elements.Current; IExpandedResult skipToken = base.GetSkipToken(expanded); if (current != null) { IExpandedResult result3 = current as IExpandedResult; if (result3 != null) { expanded = result3; current = Serializer.GetExpandedElement(expanded); skipToken = base.GetSkipToken(expanded); } this.WriteEntry(expanded, current, true, expectedType); } hasMoved = elements.MoveNext(); lastObject = current; skipTokenExpandedResult = skipToken; } if (flag) { feed.Count = new long?(base.RequestDescription.CountValue); } if (base.NeedNextPageLink(elements)) { feed.NextPageLink = base.GetNextLinkUri(lastObject, skipTokenExpandedResult, absoluteUri); } } finally { if (!topLevel) { WebUtil.Dispose(elements); } } this.odataWriter.WriteEnd(); }
/// <summary> /// Visits an ATOM metadata object. /// </summary> /// <param name="atomMetadata"></param> protected virtual void VisitAtomMetadata(object atomMetadata) { if (atomMetadata == null) { return; } AtomCategoryMetadata atomCategoryMetadata = atomMetadata as AtomCategoryMetadata; if (atomCategoryMetadata != null) { this.VisitAtomCategoryMetadata(atomCategoryMetadata); return; } AtomEntryMetadata atomEntryMetadata = atomMetadata as AtomEntryMetadata; if (atomEntryMetadata != null) { this.VisitAtomEntryMetadata(atomEntryMetadata); return; } AtomFeedMetadata atomFeedMetadata = atomMetadata as AtomFeedMetadata; if (atomFeedMetadata != null) { this.VisitAtomFeedMetadata(atomFeedMetadata); return; } AtomGeneratorMetadata atomGeneratorMetadata = atomMetadata as AtomGeneratorMetadata; if (atomGeneratorMetadata != null) { this.VisitAtomGeneratorMetadata(atomGeneratorMetadata); return; } AtomLinkMetadata atomLinkMetadata = atomMetadata as AtomLinkMetadata; if (atomLinkMetadata != null) { this.VisitAtomLinkMetadata(atomLinkMetadata); return; } AtomPersonMetadata atomPersonMetadata = atomMetadata as AtomPersonMetadata; if (atomPersonMetadata != null) { this.VisitAtomPersonMetadata(atomPersonMetadata); return; } AtomResourceCollectionMetadata atomResourceCollectionMetadata = atomMetadata as AtomResourceCollectionMetadata; if (atomResourceCollectionMetadata != null) { this.VisitAtomResourceCollectionMetadata(atomResourceCollectionMetadata); return; } AtomStreamReferenceMetadata atomStreamReferenceMetadata = atomMetadata as AtomStreamReferenceMetadata; if (atomStreamReferenceMetadata != null) { this.VisitAtomStreamReferenceMetadata(atomStreamReferenceMetadata); return; } AtomTextConstruct atomTextConstruct = atomMetadata as AtomTextConstruct; if (atomTextConstruct != null) { this.VisitAtomTextConstruct(atomTextConstruct); return; } AtomWorkspaceMetadata atomWorkspaceMetadata = atomMetadata as AtomWorkspaceMetadata; if (atomWorkspaceMetadata != null) { this.VisitAtomWorkspaceMetadata(atomWorkspaceMetadata); return; } AtomCategoriesMetadata atomCategoriesMetadata = atomMetadata as AtomCategoriesMetadata; if (atomCategoriesMetadata != null) { this.VisitAtomCategoriesMetadata(atomCategoriesMetadata); return; } ExceptionUtilities.Assert(false, "Unrecognized ATOM metadata object {0} of type {1}.", atomMetadata.ToString(), atomMetadata.GetType().ToString()); }