/// <summary> /// Adds a new contributor to entry metadata. /// </summary> /// <param name="entryMetadata">The entry metadata to add the contributor to.</param> /// <param name="contributorMetadata">The contributor metadata to add.</param> internal static void AddContributor(this AtomEntryMetadata entryMetadata, AtomPersonMetadata contributorMetadata) { Debug.Assert(entryMetadata != null, "entryMetadata != null"); Debug.Assert(contributorMetadata != null, "contributorMetadata != null"); entryMetadata.Contributors = entryMetadata.Contributors.ConcatToReadOnlyEnumerable("Contributors", contributorMetadata); }
/// <summary> /// Adds a new author to entry metadata. /// </summary> /// <param name="entryMetadata">The entry metadata to add the author to.</param> /// <param name="authorMetadata">The author metadata to add.</param> internal static void AddAuthor(this AtomEntryMetadata entryMetadata, AtomPersonMetadata authorMetadata) { Debug.Assert(entryMetadata != null, "entryMetadata != null"); Debug.Assert(authorMetadata != null, "authorMetadata != null"); entryMetadata.Authors = entryMetadata.Authors.ConcatToReadOnlyEnumerable("Authors", authorMetadata); }
/// <summary> /// Writes the specified start/end tags and the specified person metadata as content /// </summary> /// <param name="personMetadata">The person metadata to write.</param> internal void WritePersonMetadata(AtomPersonMetadata personMetadata) { Debug.Assert(personMetadata != null, "Person metadata must not be null."); // <atom:name>name of person</atom:name> // NOTE: write an empty element if no name is specified because the element is required. this.WriteElementWithTextContent( AtomConstants.AtomNamespacePrefix, AtomConstants.AtomPersonNameElementName, AtomConstants.AtomNamespace, personMetadata.Name); string uriString = personMetadata.UriFromEpm; if (uriString != null) { Debug.Assert( personMetadata.Uri == null, "If the internal UriFromEpm was used, then the Uri property must be left null. The merge between custom and EPM is probably wrong."); } else { Uri uri = personMetadata.Uri; if (uri != null) { uriString = this.UriToUrlAttributeValue(uri); } } if (uriString != null) { this.WriteElementWithTextContent( AtomConstants.AtomNamespacePrefix, AtomConstants.AtomPersonUriElementName, AtomConstants.AtomNamespace, uriString); } string email = personMetadata.Email; if (email != null) { this.WriteElementWithTextContent( AtomConstants.AtomNamespacePrefix, AtomConstants.AtomPersonEmailElementName, AtomConstants.AtomNamespace, email); } }
/// <summary> /// Visits an ATOM person metadata. /// </summary> /// <param name="atomPersonMetadata">The person metadata to visit.</param> protected override void VisitAtomPersonMetadata(AtomPersonMetadata atomPersonMetadata) { this.ValidateUri(atomPersonMetadata.Uri); base.VisitAtomPersonMetadata(atomPersonMetadata); }
/// <summary> /// Reads a person (author/contributor) element. /// </summary> /// <returns>The person metadata object with the read values.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:contributor/atom:author) - the atom:author/atom:contributor element to read. /// Post-Condition: Any - the node after the atom:author/atom:contributor element which was read. /// </remarks> protected AtomPersonMetadata ReadAtomPersonConstruct() { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( (this.XmlReader.LocalName == AtomConstants.AtomAuthorElementName || this.XmlReader.LocalName == AtomConstants.AtomContributorElementName) && this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "Only atom:author or atom:contributor elements can be read by this method."); AtomPersonMetadata personMetadata = new AtomPersonMetadata(); if (!this.XmlReader.IsEmptyElement) { // Move to the first child this.XmlReader.Read(); do { switch (this.XmlReader.NodeType) { case XmlNodeType.EndElement: // End of the atom:author/atom:contributor element continue; case XmlNodeType.Element: if (this.XmlReader.NamespaceEquals(this.AtomNamespace)) { if (this.ReadAtomMetadata) { switch (this.XmlReader.LocalName) { case AtomConstants.AtomPersonNameElementName: personMetadata.Name = this.ReadElementStringValue(); continue; case AtomConstants.AtomPersonUriElementName: // NOTE: get the base URI here before we read the content as string; reading the content as string will move the // reader to the end element and thus we lose the xml:base definition on the element. Uri xmlBaseUri = this.XmlReader.XmlBaseUri; string textValue = this.ReadElementStringValue(); if (this.ReadAtomMetadata) { personMetadata.Uri = this.ProcessUriFromPayload(textValue, xmlBaseUri); } continue; case AtomConstants.AtomPersonEmailElementName: personMetadata.Email = this.ReadElementStringValue(); continue; default: break; } } } break; default: break; } // Skip everything we haven't read yet. this.XmlReader.Skip(); } while (this.XmlReader.NodeType != XmlNodeType.EndElement); } // Read over the end element or the empty start element. this.AssertXmlCondition(true, XmlNodeType.EndElement); Debug.Assert( (this.XmlReader.LocalName == AtomConstants.AtomAuthorElementName || this.XmlReader.LocalName == AtomConstants.AtomContributorElementName) && this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "Only atom:author or atom:contributor elements can be read by this method."); this.XmlReader.Read(); return personMetadata; }
private static AtomPersonMetadata CreateAuthorMetadata(IEnumerable<XmlTreeAnnotation> children) { AtomPersonMetadata metadata = null; foreach (XmlTreeAnnotation epmTree in children) { if (epmTree.NamespaceName == TestAtomConstants.AtomNamespace) { if (metadata == null) { metadata = new AtomPersonMetadata(); } string localName = epmTree.LocalName; if (localName == TestAtomConstants.AtomPersonNameElementName) { Debug.Assert(!epmTree.IsAttribute); metadata.Name = epmTree.PropertyValue; } else if (localName == TestAtomConstants.AtomPersonUriElementName) { Debug.Assert(!epmTree.IsAttribute); metadata.Uri = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue); } else if (localName == TestAtomConstants.AtomPersonEmailElementName) { Debug.Assert(!epmTree.IsAttribute); metadata.Email = epmTree.PropertyValue; } } } return metadata; }
/// <summary> /// Reads a person (author/contributor) element. /// </summary> /// <returns>The person metadata object with the read values.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element (atom:contributor/atom:author) - the atom:author/atom:contributor element to read. /// Post-Condition: Any - the node after the atom:author/atom:contributor element which was read. /// </remarks> protected AtomPersonMetadata ReadAtomPersonConstruct() { this.AssertXmlCondition(XmlNodeType.Element); Debug.Assert( (this.XmlReader.LocalName == AtomConstants.AtomAuthorElementName || this.XmlReader.LocalName == AtomConstants.AtomContributorElementName) && this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "Only atom:author or atom:contributor elements can be read by this method."); AtomPersonMetadata personMetadata = new AtomPersonMetadata(); if (!this.XmlReader.IsEmptyElement) { // Move to the first child this.XmlReader.Read(); do { switch (this.XmlReader.NodeType) { case XmlNodeType.EndElement: // End of the atom:author/atom:contributor element continue; case XmlNodeType.Element: if (this.XmlReader.NamespaceEquals(this.AtomNamespace)) { if (this.ReadAtomMetadata) { switch (this.XmlReader.LocalName) { case AtomConstants.AtomPersonNameElementName: personMetadata.Name = this.ReadElementStringValue(); continue; case AtomConstants.AtomPersonUriElementName: // NOTE: get the base URI here before we read the content as string; reading the content as string will move the // reader to the end element and thus we lose the xml:base definition on the element. Uri xmlBaseUri = this.XmlReader.XmlBaseUri; string textValue = this.ReadElementStringValue(); if (this.ReadAtomMetadata) { personMetadata.Uri = this.ProcessUriFromPayload(textValue, xmlBaseUri); } continue; case AtomConstants.AtomPersonEmailElementName: personMetadata.Email = this.ReadElementStringValue(); continue; default: break; } } } break; default: break; } // Skip everything we haven't read yet. this.XmlReader.Skip(); }while (this.XmlReader.NodeType != XmlNodeType.EndElement); } // Read over the end element or the empty start element. this.AssertXmlCondition(true, XmlNodeType.EndElement); Debug.Assert( (this.XmlReader.LocalName == AtomConstants.AtomAuthorElementName || this.XmlReader.LocalName == AtomConstants.AtomContributorElementName) && this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace, "Only atom:author or atom:contributor elements can be read by this method."); this.XmlReader.Read(); return(personMetadata); }
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 person metadata. /// </summary> /// <param name="atomPersonMetadata">The person metadata to visit.</param> protected virtual void VisitAtomPersonMetadata(AtomPersonMetadata atomPersonMetadata) { }
/// <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); }
/// <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); }