/// <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); } }
/// <summary> /// Write an empty author element that has the required name element /// </summary> /// <param name="writer">The Xml writer to write to.</param> private static void WriteEmptyAuthor(XmlWriter writer) { // <atom:author> writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomAuthorElementName, AtomConstants.AtomNamespace); // <atom:Name></atom:Name> ODataAtomWriterUtils.WriteEmptyElement(writer, AtomConstants.AtomNamespacePrefix, AtomConstants.AtomAuthorNameElementName, AtomConstants.AtomNamespace); // </atom:author> writer.WriteEndElement(); }
/// <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(); } } }