/// <summary> /// Reads the atom:category element in the entry content. /// </summary> /// <param name="entryState">The reader entry state for the entry being read.</param> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:category) - the atom:category element to read. /// Post-Condition: Any - the node after the atom:category which was read. /// </remarks> internal void ReadAtomCategoryElementInEntryContent(IODataAtomReaderEntryState entryState) { Debug.Assert(entryState != null, "entryState != null"); this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Only atom:category element can be read by this method."); // Read the attributes and create the category metadata regardless if we will need it or not. // We can do this since there's no validation done on any of the values and thus this operation will never fail. // If we then decide we don't need it, we can safely throw it away. if (this.ReadAtomMetadata) { AtomCategoryMetadata categoryMetadata = this.ReadAtomCategoryElement(); // No point in trying to figure out if we will need the category for EPM or not here. // Our EPM syndication reader must handle unneeded categories anyway (if ATOM metadata reading is on) // So instead of burning the cycles to compute if we need it, just store it anyway. entryState.AtomEntryMetadata.AddCategory(categoryMetadata); } else { // Skip the element in any case (we only ever consume attributes on it anyway). this.XmlReader.Skip(); } }
/// <summary> /// Reads an "atom:category" element and returns the data as an <seealso cref="AtomCategoryMetadata"/> object. /// </summary> /// <returns>An <seealso cref="AtomCategoryMetadata"/> object with its properties filled in according to what was found in the XML.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The start of the atom:category element. /// Post-Condition: Any - The next node after the atom:category element. /// </remarks> private AtomCategoryMetadata ReadCategoryElementInCollection() { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert(this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Expected element named 'category'."); Debug.Assert(this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "Element 'category' should be in the atom namespace."); AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata(); while (this.XmlReader.MoveToNextAttribute()) { string attributeValue = this.XmlReader.Value; if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { if (this.XmlReader.LocalNameEquals(this.AtomCategoryTermAttributeName)) { categoryMetadata.Term = attributeValue; } else if (this.XmlReader.LocalNameEquals(this.AtomCategorySchemeAttributeName)) { categoryMetadata.Scheme = attributeValue; } else if (this.XmlReader.LocalNameEquals(this.AtomCategoryLabelAttributeName)) { categoryMetadata.Label = attributeValue; } } } return(categoryMetadata); }
/// <summary> /// Writes the type name category element for the entry. /// </summary> /// <param name="typeName">The type name to write.</param> /// <param name="entryMetadata">The entry metadata if available.</param> internal void WriteEntryTypeName(string typeName, AtomEntryMetadata entryMetadata) { if (typeName != null) { AtomCategoryMetadata mergedCategoryMetadata = ODataAtomWriterMetadataUtils.MergeCategoryMetadata( entryMetadata == null ? null : entryMetadata.CategoryWithTypeName, typeName, AtomConstants.ODataSchemeNamespace); this.atomEntryMetadataSerializer.WriteCategory(mergedCategoryMetadata); } }
/// <summary> /// Reads the atom:category element. /// </summary> /// <returns>The ATOM category metadata read.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:category) - the atom:category element to read. /// Post-Condition: Any - the node after the atom:category which was read. /// </remarks> internal AtomCategoryMetadata ReadAtomCategoryElement() { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Only atom:category element can be read by this method."); AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata(); // Read the attributes while (this.XmlReader.MoveToNextAttribute()) { // Astoria client recognizes attributes in ATOM namespace as well when looking // for category/@scheme and category/@term attributes. // If multiple 'scheme' or 'term' attributes are present the one with non-empty namespace wins. if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { switch (this.XmlReader.LocalName) { case AtomConstants.AtomCategorySchemeAttributeName: categoryMetadata.Scheme = categoryMetadata.Scheme ?? this.XmlReader.Value; break; case AtomConstants.AtomCategoryTermAttributeName: categoryMetadata.Term = categoryMetadata.Term ?? this.XmlReader.Value; break; case AtomConstants.AtomCategoryLabelAttributeName: categoryMetadata.Label = this.XmlReader.Value; break; default: // Ignore all other attributes. break; } } } // Skip the element in any case (we only ever consume attributes on it anyway). this.XmlReader.Skip(); return(categoryMetadata); }
/// <summary> /// Creates a new <see cref="AtomCategoryMetadata"/> instance by merging the given /// <paramref name="categoryMetadata"/> (if any) with the specified <paramref name="term"/> and <paramref name="scheme"/>. /// </summary> /// <param name="categoryMetadata">The metadata to merge with the <paramref name="term"/> and <paramref name="scheme"/>.</param> /// <param name="term">The term to use in the merged metadata.</param> /// <param name="scheme">The scheme to use in the merged metadata.</param> /// <returns>A new <see cref="AtomCategoryMetadata"/> instance created by merging all the arguments.</returns> /// <remarks> /// If the <paramref name="categoryMetadata"/> already holds values for <paramref name="term"/> or <paramref name="scheme"/> /// this method validates that they are the same as the ones specified in the method arguments. /// </remarks> internal static AtomCategoryMetadata MergeCategoryMetadata(AtomCategoryMetadata categoryMetadata, string term, string scheme) { Debug.Assert(term != null, "term != null"); Debug.Assert(scheme != null, "scheme != null"); AtomCategoryMetadata mergedCategoryMetadata = new AtomCategoryMetadata(categoryMetadata); // Set the term. string metadataTerm = mergedCategoryMetadata.Term; if (metadataTerm != null) { // Validate that terms are the same. if (string.CompareOrdinal(term, metadataTerm) != 0) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_CategoryTermsMustMatch(term, metadataTerm)); } } else { mergedCategoryMetadata.Term = term; } // Set the scheme. string metadataScheme = mergedCategoryMetadata.Scheme; if (metadataScheme != null) { // Validate that schemes are the same. if (string.CompareOrdinal(scheme, metadataScheme) != 0) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_CategorySchemesMustMatch(scheme, metadataScheme)); } } else { mergedCategoryMetadata.Scheme = scheme; } return(mergedCategoryMetadata); }
/// <summary> /// Reads an atom:category element in a feed. /// </summary> /// <param name="atomFeedMetadata">The feed metadata to augment.</param> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:category) - the atom:category element to read. /// Post-Condition: Any - the node after the atom:category which was read. /// </remarks> private void ReadCategoryElement(AtomFeedMetadata atomFeedMetadata) { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Only atom:category element can be read by this method."); AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata(); // Read the attributes while (this.XmlReader.MoveToNextAttribute()) { if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { switch (this.XmlReader.LocalName) { case AtomConstants.AtomCategorySchemeAttributeName: categoryMetadata.Scheme = this.XmlReader.Value; break; case AtomConstants.AtomCategoryTermAttributeName: categoryMetadata.Term = this.XmlReader.Value; break; case AtomConstants.AtomCategoryLabelAttributeName: categoryMetadata.Label = this.XmlReader.Value; break; default: // Ignore all other attributes. break; } } } atomFeedMetadata.AddCategory(categoryMetadata); // Skip the rest of the category element. this.XmlReader.Skip(); }
/// <summary> /// Reads the atom:category element. /// </summary> /// <returns>The ATOM category metadata read.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:category) - the atom:category element to read. /// Post-Condition: Any - the node after the atom:category which was read. /// </remarks> internal AtomCategoryMetadata ReadAtomCategoryElement() { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Only atom:category element can be read by this method."); AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata(); // Read the attributes while (this.XmlReader.MoveToNextAttribute()) { if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { switch (this.XmlReader.LocalName) { case AtomConstants.AtomCategorySchemeAttributeName: categoryMetadata.Scheme = categoryMetadata.Scheme ?? this.XmlReader.Value; break; case AtomConstants.AtomCategoryTermAttributeName: categoryMetadata.Term = categoryMetadata.Term ?? this.XmlReader.Value; break; case AtomConstants.AtomCategoryLabelAttributeName: categoryMetadata.Label = this.XmlReader.Value; break; default: // Ignore all other attributes. break; } } } // Skip the element in any case (we only ever consume attributes on it anyway). this.XmlReader.Skip(); return(categoryMetadata); }
private static AtomCategoryMetadata CreateCategoryMetadata(IEnumerable<XmlTreeAnnotation> children) { AtomCategoryMetadata metadata = null; foreach (XmlTreeAnnotation epmTree in children.Where(child => child.IsAttribute)) { if (string.IsNullOrEmpty(epmTree.NamespaceName)) { if (metadata == null) { metadata = new AtomCategoryMetadata(); } string localName = epmTree.LocalName; if (localName == TestAtomConstants.AtomCategoryTermAttributeName) { metadata.Term = epmTree.PropertyValue; } else if (localName == TestAtomConstants.AtomCategorySchemeAttributeName) { metadata.Scheme = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : epmTree.PropertyValue; } else if (localName == TestAtomConstants.AtomCategoryLabelAttributeName) { metadata.Label = epmTree.PropertyValue; } else { throw new NotSupportedException("Unsupported metadata '" + localName + "' found for category."); } } } return metadata; }
/// <summary> /// Creates a new <see cref="AtomCategoryMetadata"/> instance by merging the given /// <paramref name="categoryMetadata"/> (if any) with the specified <paramref name="term"/> and <paramref name="scheme"/>. /// </summary> /// <param name="categoryMetadata">The metadata to merge with the <paramref name="term"/> and <paramref name="scheme"/>.</param> /// <param name="term">The term to use in the merged metadata.</param> /// <param name="scheme">The scheme to use in the merged metadata.</param> /// <returns>A new <see cref="AtomCategoryMetadata"/> instance created by merging all the arguments.</returns> /// <remarks> /// If the <paramref name="categoryMetadata"/> already holds values for <paramref name="term"/> or <paramref name="scheme"/> /// this method validates that they are the same as the ones specified in the method arguments. /// </remarks> internal static AtomCategoryMetadata MergeCategoryMetadata(AtomCategoryMetadata categoryMetadata, string term, string scheme) { Debug.Assert(term != null, "term != null"); Debug.Assert(scheme != null, "scheme != null"); AtomCategoryMetadata mergedCategoryMetadata = new AtomCategoryMetadata(categoryMetadata); // Set the term. string metadataTerm = mergedCategoryMetadata.Term; if (metadataTerm != null) { // Validate that terms are the same. if (string.CompareOrdinal(term, metadataTerm) != 0) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_CategoryTermsMustMatch(term, metadataTerm)); } } else { mergedCategoryMetadata.Term = term; } // Set the scheme. string metadataScheme = mergedCategoryMetadata.Scheme; if (metadataScheme != null) { // Validate that schemes are the same. if (string.CompareOrdinal(scheme, metadataScheme) != 0) { throw new ODataException(Strings.ODataAtomWriterMetadataUtils_CategorySchemesMustMatch(scheme, metadataScheme)); } } else { mergedCategoryMetadata.Scheme = scheme; } return mergedCategoryMetadata; }
/// <summary> /// Reads an "atom:category" element and returns the data as an <seealso cref="AtomCategoryMetadata"/> object. /// </summary> /// <returns>An <seealso cref="AtomCategoryMetadata"/> object with its properties filled in according to what was found in the XML.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The start of the atom:category element. /// Post-Condition: Any - The next node after the atom:category element. /// </remarks> private AtomCategoryMetadata ReadCategoryElementInCollection() { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert(this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Expected element named 'category'."); Debug.Assert(this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "Element 'category' should be in the atom namespace."); AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata(); while (this.XmlReader.MoveToNextAttribute()) { string attributeValue = this.XmlReader.Value; if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { if (this.XmlReader.LocalNameEquals(this.AtomCategoryTermAttributeName)) { categoryMetadata.Term = attributeValue; } else if (this.XmlReader.LocalNameEquals(this.AtomCategorySchemeAttributeName)) { categoryMetadata.Scheme = attributeValue; } else if (this.XmlReader.LocalNameEquals(this.AtomCategoryLabelAttributeName)) { categoryMetadata.Label = attributeValue; } } } return categoryMetadata; }
/// <summary> /// Reads an atom:category element in a feed. /// </summary> /// <param name="atomFeedMetadata">The feed metadata to augment.</param> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:category) - the atom:category element to read. /// Post-Condition: Any - the node after the atom:category which was read. /// </remarks> private void ReadCategoryElement(AtomFeedMetadata atomFeedMetadata) { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Only atom:category element can be read by this method."); AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata(); // Read the attributes while (this.XmlReader.MoveToNextAttribute()) { if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { switch (this.XmlReader.LocalName) { case AtomConstants.AtomCategorySchemeAttributeName: categoryMetadata.Scheme = this.XmlReader.Value; break; case AtomConstants.AtomCategoryTermAttributeName: categoryMetadata.Term = this.XmlReader.Value; break; case AtomConstants.AtomCategoryLabelAttributeName: categoryMetadata.Label = this.XmlReader.Value; break; default: // Ignore all other attributes. break; } } } atomFeedMetadata.AddCategory(categoryMetadata); // Skip the rest of the category element. this.XmlReader.Skip(); }
/// <summary> /// Writes the 'atom:category' element given category metadata. /// </summary> /// <param name="category">The category information to write.</param> internal void WriteCategory(AtomCategoryMetadata category) { Debug.Assert(category != null, "Category must not be null."); this.WriteCategory(AtomConstants.AtomNamespacePrefix, category.Term, category.Scheme, category.Label); }
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> /// Visits an ATOM category metadata. /// </summary> /// <param name="atomCategoryMetadata">The category metadata to visit.</param> protected virtual void VisitAtomCategoryMetadata(AtomCategoryMetadata atomCategoryMetadata) { }
/// <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 category to entry metadata. /// </summary> /// <param name="entryMetadata">The entry metadata to add the category to.</param> /// <param name="categoryMetadata">The category metadata to add.</param> internal static void AddCategory(this AtomEntryMetadata entryMetadata, AtomCategoryMetadata categoryMetadata) { Debug.Assert(entryMetadata != null, "entryMetadata != null"); Debug.Assert(categoryMetadata != null, "categoryMetadata != null"); entryMetadata.Categories = entryMetadata.Categories.ConcatToReadOnlyEnumerable("Categories", categoryMetadata); }
/// <summary> /// Reads the atom:category element. /// </summary> /// <returns>The ATOM category metadata read.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:category) - the atom:category element to read. /// Post-Condition: Any - the node after the atom:category which was read. /// </remarks> internal AtomCategoryMetadata ReadAtomCategoryElement() { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomCategoryElementName, "Only atom:category element can be read by this method."); AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata(); // Read the attributes while (this.XmlReader.MoveToNextAttribute()) { // Astoria client recognizes attributes in ATOM namespace as well when looking // for category/@scheme and category/@term attributes. // If multiple 'scheme' or 'term' attributes are present the one with non-empty namespace wins. if (this.XmlReader.NamespaceEquals(this.EmptyNamespace)) { switch (this.XmlReader.LocalName) { case AtomConstants.AtomCategorySchemeAttributeName: categoryMetadata.Scheme = categoryMetadata.Scheme ?? this.XmlReader.Value; break; case AtomConstants.AtomCategoryTermAttributeName: categoryMetadata.Term = categoryMetadata.Term ?? this.XmlReader.Value; break; case AtomConstants.AtomCategoryLabelAttributeName: categoryMetadata.Label = this.XmlReader.Value; break; default: // Ignore all other attributes. break; } } } // Skip the element in any case (we only ever consume attributes on it anyway). this.XmlReader.Skip(); return categoryMetadata; }
/// <summary> /// Writes the 'atom:category' element given category metadata. /// </summary> /// <param name="category">The category information to write.</param> internal void WriteCategory(AtomCategoryMetadata category) { Debug.Assert(category != null, "Category must not be null."); this.WriteCategory(AtomConstants.AtomNamespacePrefix, category.Term, category.Scheme, category.Label); }