/// <summary> /// Writes the navigation link's start element and atom metadata. /// </summary> /// <param name="navigationLink">The navigation link to write.</param> /// <param name="navigationLinkUrlOverride">Url to use for the navigation link. If this is specified the Url property on the <paramref name="navigationLink"/> /// will be ignored. If this parameter is null, the Url from the navigation link is used.</param> internal void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride) { Debug.Assert(navigationLink != null, "navigationLink != null"); Debug.Assert(!string.IsNullOrEmpty(navigationLink.Name), "The navigation link name was not verified yet."); Debug.Assert(navigationLink.Url != null, "The navigation link Url was not verified yet."); Debug.Assert(navigationLink.IsCollection.HasValue, "navigationLink.IsCollection.HasValue"); if (navigationLink.AssociationLinkUrl != null) { // TODO:Association Link - Add back support for customizing association link element in Atom this.WriteAssociationLink(navigationLink.Name, navigationLink.AssociationLinkUrl, null); } // <atom:link> this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLinkElementName, AtomConstants.AtomNamespace); string linkRelation = AtomUtils.ComputeODataNavigationLinkRelation(navigationLink); string linkType = AtomUtils.ComputeODataNavigationLinkType(navigationLink); string linkTitle = navigationLink.Name; Uri navigationLinkUrl = navigationLinkUrlOverride ?? navigationLink.Url; AtomLinkMetadata linkMetadata = navigationLink.GetAnnotation <AtomLinkMetadata>(); AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(linkMetadata, linkRelation, navigationLinkUrl, linkTitle, linkType); this.atomEntryMetadataSerializer.WriteAtomLinkAttributes(mergedMetadata, null /* etag */); }
/// <summary> /// Write the metadata for an OData association link; makes sure any duplicate of the link's values duplicated in metadata are equal. /// </summary> /// <param name="navigationPropertyName">The name of the navigation property whose association link is being written.</param> /// <param name="associationLinkUrl">The association link url to write.</param> /// <param name="associationLinkMetadata">Atom metadata about this link element. This can be used to customized the link element with additional XML attributes.</param> internal void WriteAssociationLink(string navigationPropertyName, Uri associationLinkUrl, AtomLinkMetadata associationLinkMetadata) { AtomLinkMetadata linkMetadata = associationLinkMetadata; string linkRelation = AtomUtils.ComputeODataAssociationLinkRelation(navigationPropertyName); AtomLinkMetadata mergedLinkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(linkMetadata, linkRelation, associationLinkUrl, navigationPropertyName, MimeConstants.MimeApplicationXml); this.atomEntryMetadataSerializer.WriteAtomLink(mergedLinkMetadata, null /* etag*/); }
/// <summary> /// Writes a stream property to the ATOM payload /// </summary> /// <param name="streamProperty">The stream property to create the payload for.</param> /// <param name="owningType">The <see cref="IEdmEntityType"/> instance for which the stream property defined on.</param> /// <param name="duplicatePropertyNamesChecker">The checker instance for duplicate property names.</param> /// <param name="projectedProperties">Set of projected properties, or null if all properties should be written.</param> internal void WriteStreamProperty( ODataProperty streamProperty, IEdmEntityType owningType, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, ProjectedPropertiesAnnotation projectedProperties) { Debug.Assert(streamProperty != null, "Stream property must not be null."); Debug.Assert(streamProperty.Value != null, "The media resource of the stream property must not be null."); WriterValidationUtils.ValidatePropertyNotNull(streamProperty); string propertyName = streamProperty.Name; if (projectedProperties.ShouldSkipProperty(propertyName)) { return; } WriterValidationUtils.ValidatePropertyName(propertyName); duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(streamProperty); IEdmProperty edmProperty = WriterValidationUtils.ValidatePropertyDefined(streamProperty.Name, owningType); WriterValidationUtils.ValidateStreamReferenceProperty(streamProperty, edmProperty, this.Version, this.WritingResponse); ODataStreamReferenceValue streamReferenceValue = (ODataStreamReferenceValue)streamProperty.Value; WriterValidationUtils.ValidateStreamReferenceValue(streamReferenceValue, false /*isDefaultStream*/); if (owningType != null && owningType.IsOpen && edmProperty == null) { ValidationUtils.ValidateOpenPropertyValue(streamProperty.Name, streamReferenceValue); } AtomStreamReferenceMetadata streamReferenceMetadata = streamReferenceValue.GetAnnotation <AtomStreamReferenceMetadata>(); string contentType = streamReferenceValue.ContentType; string linkTitle = streamProperty.Name; Uri readLink = streamReferenceValue.ReadLink; if (readLink != null) { string readLinkRelation = AtomUtils.ComputeStreamPropertyRelation(streamProperty, false); AtomLinkMetadata readLinkMetadata = streamReferenceMetadata == null ? null : streamReferenceMetadata.SelfLink; AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(readLinkMetadata, readLinkRelation, readLink, linkTitle, contentType); this.atomEntryMetadataSerializer.WriteAtomLink(mergedMetadata, null /* etag */); } Uri editLink = streamReferenceValue.EditLink; if (editLink != null) { string editLinkRelation = AtomUtils.ComputeStreamPropertyRelation(streamProperty, true); AtomLinkMetadata editLinkMetadata = streamReferenceMetadata == null ? null : streamReferenceMetadata.EditLink; AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(editLinkMetadata, editLinkRelation, editLink, linkTitle, contentType); this.atomEntryMetadataSerializer.WriteAtomLink(mergedMetadata, streamReferenceValue.ETag); } }
/// <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> /// Writes a feed link. /// </summary> /// <param name="feed">The feed that contains the link.</param> /// <param name="relation">Relation attribute of the link.</param> /// <param name="href">href attribute of the link.</param> /// <param name="getLinkMetadata">Function to get the AtomLinkMetadata for the feed link.</param> internal void WriteFeedLink(ODataFeed feed, string relation, Uri href, Func <AtomFeedMetadata, AtomLinkMetadata> getLinkMetadata) { AtomFeedMetadata feedMetadata = feed.GetAnnotation <AtomFeedMetadata>(); AtomLinkMetadata mergedLink = ODataAtomWriterMetadataUtils.MergeLinkMetadata( getLinkMetadata(feedMetadata), relation, href, null, /*title*/ null /*mediaType*/); this.atomFeedMetadataSerializer.WriteAtomLink(mergedLink, null); }
/// <summary> /// Writes the self or edit link. /// </summary> /// <param name="link">Uri object for the link.</param> /// <param name="linkMetadata">The atom link metadata for the link to specify title, type, hreflang and length of the link.</param> /// <param name="linkRelation">Relationship value. Either "edit" or "self".</param> private void WriteReadOrEditLink( Uri link, AtomLinkMetadata linkMetadata, string linkRelation) { if (link != null) { AtomLinkMetadata mergedLinkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata( linkMetadata, linkRelation, link, null /* title */, null /* media type */); this.atomEntryMetadataSerializer.WriteAtomLink(mergedLinkMetadata, null /* etag */); } }
/// <summary> /// Writes the edit-media link for an entry. /// </summary> /// <param name="mediaResource">The media resource representing the MR of the entry to write.</param> internal void WriteEntryMediaEditLink(ODataStreamReferenceValue mediaResource) { Debug.Assert(mediaResource != null, "mediaResource != null"); Uri mediaEditLink = mediaResource.EditLink; Debug.Assert(mediaEditLink != null || mediaResource.ETag == null, "The default stream edit link and etag should have been validated by now."); if (mediaEditLink != null) { AtomStreamReferenceMetadata streamReferenceMetadata = mediaResource.GetAnnotation <AtomStreamReferenceMetadata>(); AtomLinkMetadata mediaEditMetadata = streamReferenceMetadata == null ? null : streamReferenceMetadata.EditLink; AtomLinkMetadata mergedLinkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata( mediaEditMetadata, AtomConstants.AtomEditMediaRelationAttributeValue, mediaEditLink, null /* title */, null /* mediaType */); this.atomEntryMetadataSerializer.WriteAtomLink(mergedLinkMetadata, mediaResource.ETag); } }
internal void WriteFeedMetadata(AtomFeedMetadata feedMetadata, ODataFeed feed, string updatedTime, out bool authorWritten) { 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 Uri id = feed == null ? feedMetadata.SourceId : feed.Id; this.WriteElementWithTextContent( AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIdElementName, AtomConstants.AtomNamespace, id == null ? null : UriUtils.UriToString(id)); // <atom:title>text</atom:title> // NOTE: write an empty element if no title is specified since the element is required this.WriteTextConstruct(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace, feedMetadata.Title); if (feedMetadata.Subtitle != null) { // <atom:subtitle>text</atom:subtitle> this.WriteTextConstruct(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomSubtitleElementName, AtomConstants.AtomNamespace, feedMetadata.Subtitle); } // <atom:updated>date</atom:updated> // NOTE: the <updated> element is required and if not specified we use a single 'default/current' date/time for the whole payload. string updated = feedMetadata.Updated.HasValue ? ODataAtomConvert.ToAtomString(feedMetadata.Updated.Value) : updatedTime; this.WriteElementWithTextContent( AtomConstants.AtomNamespacePrefix, AtomConstants.AtomUpdatedElementName, AtomConstants.AtomNamespace, updated); AtomLinkMetadata selfLinkMetadata = feedMetadata.SelfLink; if (selfLinkMetadata != null) { AtomLinkMetadata mergedSelfLinkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata( selfLinkMetadata, AtomConstants.AtomSelfRelationAttributeValue, null /* href */, null /* title */, null /* media type */); this.WriteAtomLink(mergedSelfLinkMetadata, null /*etag*/); } IEnumerable <AtomLinkMetadata> links = feedMetadata.Links; if (links != null) { foreach (AtomLinkMetadata link in links) { // DeltaLink is written from ODataFeed, so it shouldn't be written again from AtomFeedMetadata. if (link.Relation != AtomConstants.AtomDeltaRelationAttributeValue) { // <atom:link>...</atom:link> this.WriteAtomLink(link, null /* etag */); } } } IEnumerable <AtomCategoryMetadata> categories = feedMetadata.Categories; if (categories != null) { foreach (AtomCategoryMetadata category in categories) { // <atom:category term="..." scheme="..." label="..."></atom:category> this.WriteCategory(category); } } Uri logo = feedMetadata.Logo; if (logo != null) { // <atom:logo>Uri</atom:logo> this.WriteElementWithTextContent( AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLogoElementName, AtomConstants.AtomNamespace, this.UriToUrlAttributeValue(logo)); } if (feedMetadata.Rights != null) { // <atom:rights>rights</atom:rights> this.WriteTextConstruct( 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> this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomContributorElementName, AtomConstants.AtomNamespace); this.WritePersonMetadata(contributor); this.XmlWriter.WriteEndElement(); } } AtomGeneratorMetadata generator = feedMetadata.Generator; if (generator != null) { // <atom:generator uri="..." version="...">name</atom:generator> this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomGeneratorElementName, AtomConstants.AtomNamespace); if (generator.Uri != null) { this.XmlWriter.WriteAttributeString(AtomConstants.AtomGeneratorUriAttributeName, this.UriToUrlAttributeValue(generator.Uri)); } if (!string.IsNullOrEmpty(generator.Version)) { this.XmlWriter.WriteAttributeString(AtomConstants.AtomGeneratorVersionAttributeName, generator.Version); } ODataAtomWriterUtils.WriteString(this.XmlWriter, generator.Name); this.XmlWriter.WriteEndElement(); } Uri icon = feedMetadata.Icon; if (icon != null) { // <atom:icon>Uri</atom:icon> this.WriteElementWithTextContent( AtomConstants.AtomNamespacePrefix, AtomConstants.AtomIconElementName, AtomConstants.AtomNamespace, this.UriToUrlAttributeValue(icon)); } IEnumerable <AtomPersonMetadata> authors = feedMetadata.Authors; authorWritten = false; if (authors != null) { foreach (AtomPersonMetadata author in authors) { // <atom:author>author data</atom:author> authorWritten = true; this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomAuthorElementName, AtomConstants.AtomNamespace); this.WritePersonMetadata(author); this.XmlWriter.WriteEndElement(); } } }