private static string CreateDateTimeStringValue(object propertyValue, ODataWriterBehavior writerBehavior)
        {
            Debug.Assert(
                writerBehavior.FormatBehaviorKind == ODataBehaviorKind.WcfDataServicesClient,
                "CreateDateTimeStringValue should only be used in WCF DS client mode.");

            if (propertyValue == null)
            {
                propertyValue = DateTimeOffset.Now;
            }

            if (propertyValue is DateTime)
            {
                // DateTimeOffset takes care of DateTimes of Unspecified kind so we won't end up
                // with datetime without timezone info mapped to atom:updated or atom:published element.
                propertyValue = new DateTimeOffset((DateTime)propertyValue);
            }

            // For DateTimeOffset values we need to use the ATOM format when translating them
            // to strings since the value will be used in ATOM metadata.
            if (propertyValue is DateTimeOffset)
            {
                return(ODataAtomConvert.ToAtomString((DateTimeOffset)propertyValue));
            }

            return(EpmWriterUtils.GetPropertyValueAsText(propertyValue));
        }
Example #2
0
 internal ODataAtomWriter(ODataAtomOutputContext atomOutputContext, bool writingFeed) : base(atomOutputContext, writingFeed)
 {
     this.updatedTime       = ODataAtomConvert.ToAtomString(DateTimeOffset.UtcNow);
     this.atomOutputContext = atomOutputContext;
     if (this.atomOutputContext.MessageWriterSettings.WriterBehavior.StartEntryXmlCustomizationCallback != null)
     {
         this.atomOutputContext.InitializeWriterCustomization();
     }
     this.atomEntryAndFeedSerializer = new ODataAtomEntryAndFeedSerializer(this.atomOutputContext);
 }
 private static string CreateDateTimeStringValue(object propertyValue, ODataWriterBehavior writerBehavior)
 {
     if (propertyValue == null)
     {
         propertyValue = DateTimeOffset.Now;
     }
     if (propertyValue is DateTime)
     {
         propertyValue = new DateTimeOffset((DateTime)propertyValue);
     }
     if (propertyValue is DateTimeOffset)
     {
         return(ODataAtomConvert.ToAtomString((DateTimeOffset)propertyValue));
     }
     return(EpmWriterUtils.GetPropertyValueAsText(propertyValue));
 }
        internal static AtomEntryMetadata MergeCustomAndEpmEntryMetadata(AtomEntryMetadata customEntryMetadata, AtomEntryMetadata epmEntryMetadata, ODataWriterBehavior writerBehavior)
        {
            AtomEntryMetadata metadata;

            if ((customEntryMetadata != null) && (writerBehavior.FormatBehaviorKind == ODataBehaviorKind.WcfDataServicesClient))
            {
                if (customEntryMetadata.Updated.HasValue)
                {
                    customEntryMetadata.UpdatedString = ODataAtomConvert.ToAtomString(customEntryMetadata.Updated.Value);
                }
                if (customEntryMetadata.Published.HasValue)
                {
                    customEntryMetadata.PublishedString = ODataAtomConvert.ToAtomString(customEntryMetadata.Published.Value);
                }
            }
            if (TryMergeIfNull <AtomEntryMetadata>(customEntryMetadata, epmEntryMetadata, out metadata))
            {
                return(metadata);
            }
            epmEntryMetadata.Title   = MergeAtomTextValue(customEntryMetadata.Title, epmEntryMetadata.Title, "Title");
            epmEntryMetadata.Summary = MergeAtomTextValue(customEntryMetadata.Summary, epmEntryMetadata.Summary, "Summary");
            epmEntryMetadata.Rights  = MergeAtomTextValue(customEntryMetadata.Rights, epmEntryMetadata.Rights, "Rights");
            if (writerBehavior.FormatBehaviorKind == ODataBehaviorKind.WcfDataServicesClient)
            {
                epmEntryMetadata.PublishedString = MergeTextValue(customEntryMetadata.PublishedString, epmEntryMetadata.PublishedString, "PublishedString");
                epmEntryMetadata.UpdatedString   = MergeTextValue(customEntryMetadata.UpdatedString, epmEntryMetadata.UpdatedString, "UpdatedString");
            }
            else
            {
                epmEntryMetadata.Published = MergeDateTimeValue(customEntryMetadata.Published, epmEntryMetadata.Published, "Published");
                epmEntryMetadata.Updated   = MergeDateTimeValue(customEntryMetadata.Updated, epmEntryMetadata.Updated, "Updated");
            }
            epmEntryMetadata.Authors      = MergeSyndicationMapping <AtomPersonMetadata>(customEntryMetadata.Authors, epmEntryMetadata.Authors);
            epmEntryMetadata.Contributors = MergeSyndicationMapping <AtomPersonMetadata>(customEntryMetadata.Contributors, epmEntryMetadata.Contributors);
            epmEntryMetadata.Categories   = MergeSyndicationMapping <AtomCategoryMetadata>(customEntryMetadata.Categories, epmEntryMetadata.Categories);
            epmEntryMetadata.Links        = MergeSyndicationMapping <AtomLinkMetadata>(customEntryMetadata.Links, epmEntryMetadata.Links);
            epmEntryMetadata.Source       = customEntryMetadata.Source;
            return(epmEntryMetadata);
        }
Example #5
0
        internal void WriteEntryMetadata(AtomEntryMetadata entryMetadata, AtomEntryMetadata epmEntryMetadata, string updatedTime)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(!string.IsNullOrEmpty(updatedTime), "!string.IsNullOrEmpty(updatedTime)");
#if DEBUG
            DateTimeOffset tempDateTimeOffset;
            Debug.Assert(DateTimeOffset.TryParse(updatedTime, out tempDateTimeOffset), "DateTimeOffset.TryParse(updatedTime, out tempDateTimeOffset)");
#endif

            // TODO: 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 mergedEntryMetadata = ODataAtomWriterMetadataEpmMergeUtils.MergeCustomAndEpmEntryMetadata(entryMetadata, epmEntryMetadata, this.MessageWriterSettings.WriterBehavior);
            if (mergedEntryMetadata == null)
            {
                // write all required metadata elements with default content

                // <atom:title></atom:title>
                this.WriteEmptyElement(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomTitleElementName,
                    AtomConstants.AtomNamespace);

                // <atom:updated>dateTimeOffset</atom:updated>
                // NOTE: the <updated> element is required and if not specified we use a single 'default/current' date/time for the whole payload.
                this.WriteElementWithTextContent(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomUpdatedElementName,
                    AtomConstants.AtomNamespace,
                    updatedTime);

                this.WriteEmptyAuthor();
            }
            else
            {
                // <atom:title>text</atom:title>
                // NOTE: writes an empty element even if no title was specified since the title is required
                this.WriteTextConstruct(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomTitleElementName, AtomConstants.AtomNamespace, mergedEntryMetadata.Title);

                AtomTextConstruct summary = mergedEntryMetadata.Summary;
                if (summary != null)
                {
                    // <atom:summary>text</atom:summary>
                    this.WriteTextConstruct(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomSummaryElementName, AtomConstants.AtomNamespace, summary);
                }

                string published = this.UseClientFormatBehavior
                    ? mergedEntryMetadata.PublishedString
                    : mergedEntryMetadata.Published.HasValue
                        ? ODataAtomConvert.ToAtomString(mergedEntryMetadata.Published.Value)
                        : null;
                if (published != null)
                {
                    // <atom:published>dateTimeOffset</atom:published>
                    this.WriteElementWithTextContent(
                        AtomConstants.AtomNamespacePrefix,
                        AtomConstants.AtomPublishedElementName,
                        AtomConstants.AtomNamespace,
                        published);
                }

                // <atom:updated>date</atom:updated>
                string updated = this.UseClientFormatBehavior
                    ? mergedEntryMetadata.UpdatedString
                    : mergedEntryMetadata.Updated.HasValue
                        ? ODataAtomConvert.ToAtomString(mergedEntryMetadata.Updated.Value)
                        : null;

                // NOTE: the <updated> element is required and if not specified we use a single 'default/current' date/time for the whole payload.
                updated = updated ?? updatedTime;
                this.WriteElementWithTextContent(
                    AtomConstants.AtomNamespacePrefix,
                    AtomConstants.AtomUpdatedElementName,
                    AtomConstants.AtomNamespace,
                    updated);

                bool wroteAuthor = false;
                IEnumerable <AtomPersonMetadata> authors = mergedEntryMetadata.Authors;
                if (authors != null)
                {
                    foreach (AtomPersonMetadata author in authors)
                    {
                        if (author == null)
                        {
                            throw new ODataException(ODataErrorStrings.ODataAtomWriterMetadataUtils_AuthorMetadataMustNotContainNull);
                        }

                        // <atom:author>author data</atom:author>
                        this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomAuthorElementName, AtomConstants.AtomNamespace);
                        this.WritePersonMetadata(author);
                        this.XmlWriter.WriteEndElement();
                        wroteAuthor = true;
                    }
                }

                if (!wroteAuthor)
                {
                    // write empty authors since they are required
                    this.WriteEmptyAuthor();
                }

                IEnumerable <AtomPersonMetadata> contributors = mergedEntryMetadata.Contributors;
                if (contributors != null)
                {
                    foreach (AtomPersonMetadata contributor in contributors)
                    {
                        if (contributor == null)
                        {
                            throw new ODataException(ODataErrorStrings.ODataAtomWriterMetadataUtils_ContributorMetadataMustNotContainNull);
                        }

                        // <atom:contributor>contributor data</atom:contributor>
                        this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomContributorElementName, AtomConstants.AtomNamespace);
                        this.WritePersonMetadata(contributor);
                        this.XmlWriter.WriteEndElement();
                    }
                }

                IEnumerable <AtomLinkMetadata> links = mergedEntryMetadata.Links;
                if (links != null)
                {
                    foreach (AtomLinkMetadata link in links)
                    {
                        if (link == null)
                        {
                            throw new ODataException(ODataErrorStrings.ODataAtomWriterMetadataUtils_LinkMetadataMustNotContainNull);
                        }

                        // <atom:link>...</atom:link>
                        this.WriteAtomLink(link, null /*edit-link-etag*/);
                    }
                }

                IEnumerable <AtomCategoryMetadata> categories = mergedEntryMetadata.Categories;
                if (categories != null)
                {
                    foreach (AtomCategoryMetadata category in categories)
                    {
                        if (category == null)
                        {
                            throw new ODataException(ODataErrorStrings.ODataAtomWriterMetadataUtils_CategoryMetadataMustNotContainNull);
                        }

                        // <atom:category term="..." scheme="..." label="..."></atom:category>
                        this.WriteCategory(category);
                    }
                }

                if (mergedEntryMetadata.Rights != null)
                {
                    // <atom:rights>rights</atom:rights>
                    this.WriteTextConstruct(
                        AtomConstants.AtomNamespacePrefix,
                        AtomConstants.AtomRightsElementName,
                        AtomConstants.AtomNamespace,
                        mergedEntryMetadata.Rights);
                }

                AtomFeedMetadata source = mergedEntryMetadata.Source;
                if (source != null)
                {
                    // <atom:source>
                    this.XmlWriter.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomSourceElementName, AtomConstants.AtomNamespace);

                    bool authorWritten;
                    this.SourceMetadataSerializer.WriteFeedMetadata(source, null /* feed */, updatedTime, out authorWritten);

                    // </atom:source>
                    this.XmlWriter.WriteEndElement();
                }
            }
        }
        internal void WriteFeedMetadata(AtomFeedMetadata feedMetadata, ODataFeed feed, string updatedTime, out bool authorWritten)
        {
            DebugUtils.CheckNoExternalCallers();
            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;

            this.WriteElementWithTextContent(
                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
            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();
                }
            }
        }
        internal void WriteFeedMetadata(AtomFeedMetadata feedMetadata, ODataFeed feed, string updatedTime, out bool authorWritten)
        {
            string textContent = (feed == null) ? feedMetadata.SourceId : feed.Id;

            base.WriteElementWithTextContent("", "id", "http://www.w3.org/2005/Atom", textContent);
            base.WriteTextConstruct("", "title", "http://www.w3.org/2005/Atom", feedMetadata.Title);
            if (feedMetadata.Subtitle != null)
            {
                base.WriteTextConstruct("", "subtitle", "http://www.w3.org/2005/Atom", feedMetadata.Subtitle);
            }
            string str2 = feedMetadata.Updated.HasValue ? ODataAtomConvert.ToAtomString(feedMetadata.Updated.Value) : updatedTime;

            base.WriteElementWithTextContent("", "updated", "http://www.w3.org/2005/Atom", str2);
            AtomLinkMetadata selfLink = feedMetadata.SelfLink;

            if (selfLink != null)
            {
                AtomLinkMetadata linkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(selfLink, "self", null, null, null);
                base.WriteAtomLink(linkMetadata, null);
            }
            IEnumerable <AtomLinkMetadata> links = feedMetadata.Links;

            if (links != null)
            {
                foreach (AtomLinkMetadata metadata3 in links)
                {
                    base.WriteAtomLink(metadata3, null);
                }
            }
            IEnumerable <AtomCategoryMetadata> categories = feedMetadata.Categories;

            if (categories != null)
            {
                foreach (AtomCategoryMetadata metadata4 in categories)
                {
                    base.WriteCategory(metadata4);
                }
            }
            Uri logo = feedMetadata.Logo;

            if (logo != null)
            {
                base.WriteElementWithTextContent("", "logo", "http://www.w3.org/2005/Atom", base.UriToUrlAttributeValue(logo));
            }
            if (feedMetadata.Rights != null)
            {
                base.WriteTextConstruct("", "rights", "http://www.w3.org/2005/Atom", feedMetadata.Rights);
            }
            IEnumerable <AtomPersonMetadata> contributors = feedMetadata.Contributors;

            if (contributors != null)
            {
                foreach (AtomPersonMetadata metadata5 in contributors)
                {
                    base.XmlWriter.WriteStartElement("", "contributor", "http://www.w3.org/2005/Atom");
                    base.WritePersonMetadata(metadata5);
                    base.XmlWriter.WriteEndElement();
                }
            }
            AtomGeneratorMetadata generator = feedMetadata.Generator;

            if (generator != null)
            {
                base.XmlWriter.WriteStartElement("", "generator", "http://www.w3.org/2005/Atom");
                if (generator.Uri != null)
                {
                    base.XmlWriter.WriteAttributeString("uri", base.UriToUrlAttributeValue(generator.Uri));
                }
                if (!string.IsNullOrEmpty(generator.Version))
                {
                    base.XmlWriter.WriteAttributeString("version", generator.Version);
                }
                ODataAtomWriterUtils.WriteString(base.XmlWriter, generator.Name);
                base.XmlWriter.WriteEndElement();
            }
            Uri icon = feedMetadata.Icon;

            if (icon != null)
            {
                base.WriteElementWithTextContent("", "icon", "http://www.w3.org/2005/Atom", base.UriToUrlAttributeValue(icon));
            }
            IEnumerable <AtomPersonMetadata> authors = feedMetadata.Authors;

            authorWritten = false;
            if (authors != null)
            {
                foreach (AtomPersonMetadata metadata7 in authors)
                {
                    authorWritten = true;
                    base.XmlWriter.WriteStartElement("", "author", "http://www.w3.org/2005/Atom");
                    base.WritePersonMetadata(metadata7);
                    base.XmlWriter.WriteEndElement();
                }
            }
        }
Example #8
0
        /// <summary>
        /// Merges custom and EPM ATOM metadata.
        /// </summary>
        /// <param name="customEntryMetadata">The custom ATOM metadata, or null if there were no custom ATOM metadata.</param>
        /// <param name="epmEntryMetadata">The EPM ATOM metadata, or null if there are no EPM mappings to syndication targets.</param>
        /// <param name="writerBehavior">The <see cref="ODataWriterBehavior"/> instance configuring the writer.</param>
        /// <returns>The merged ATOM metadata to write to the output.</returns>
        /// <remarks>The merge means that if one of the sides has null, the other is used, otherwise if both are non-null
        /// we verify that the values are the same, otherwise we throw.</remarks>
        internal static AtomEntryMetadata MergeCustomAndEpmEntryMetadata(AtomEntryMetadata customEntryMetadata, AtomEntryMetadata epmEntryMetadata, ODataWriterBehavior writerBehavior)
        {
            DebugUtils.CheckNoExternalCallers();

            if (customEntryMetadata != null && writerBehavior.FormatBehaviorKind == ODataBehaviorKind.WcfDataServicesClient)
            {
                // ODataLib supports specifying ATOM metadata for entries even in the WCF DS client mode;
                // WCF DS itself will never do this but ODataLib clients using this mode might. We have
                // to convert potential Published and Updated values to the internal string properties
                // used in WCF DS client mode.
                if (customEntryMetadata.Updated.HasValue)
                {
                    customEntryMetadata.UpdatedString = ODataAtomConvert.ToAtomString(customEntryMetadata.Updated.Value);
                }

                if (customEntryMetadata.Published.HasValue)
                {
                    customEntryMetadata.PublishedString = ODataAtomConvert.ToAtomString(customEntryMetadata.Published.Value);
                }
            }

            AtomEntryMetadata simpleMergeResult;

            if (TryMergeIfNull(customEntryMetadata, epmEntryMetadata, out simpleMergeResult))
            {
                return(simpleMergeResult);
            }

            // We will be modifying the EPM metadata adding the custom into it
            // The reason is that with EPM we can be sure that the enumerations are of type List (since they were created like that) and thus
            // we can safely add items into those without reallocating the collections.

            // Merge Title
            epmEntryMetadata.Title = MergeAtomTextValue(customEntryMetadata.Title, epmEntryMetadata.Title, "Title");

            // Merge Summary
            epmEntryMetadata.Summary = MergeAtomTextValue(customEntryMetadata.Summary, epmEntryMetadata.Summary, "Summary");

            // Merge Rights
            epmEntryMetadata.Rights = MergeAtomTextValue(customEntryMetadata.Rights, epmEntryMetadata.Rights, "Rights");

            if (writerBehavior.FormatBehaviorKind == ODataBehaviorKind.WcfDataServicesClient)
            {
                // Merge PublishedString
                epmEntryMetadata.PublishedString = MergeTextValue(customEntryMetadata.PublishedString, epmEntryMetadata.PublishedString, "PublishedString");

                // Merge UpdatedString
                epmEntryMetadata.UpdatedString = MergeTextValue(customEntryMetadata.UpdatedString, epmEntryMetadata.UpdatedString, "UpdatedString");
            }
            else
            {
                // Merge Published
                epmEntryMetadata.Published = MergeDateTimeValue(customEntryMetadata.Published, epmEntryMetadata.Published, "Published");

                // Merge Updated
                epmEntryMetadata.Updated = MergeDateTimeValue(customEntryMetadata.Updated, epmEntryMetadata.Updated, "Updated");
            }

            // Merge authors
            epmEntryMetadata.Authors = MergeSyndicationMapping <AtomPersonMetadata>(customEntryMetadata.Authors, epmEntryMetadata.Authors);

            // Merge contributors
            epmEntryMetadata.Contributors = MergeSyndicationMapping <AtomPersonMetadata>(customEntryMetadata.Contributors, epmEntryMetadata.Contributors);

            // Merge Categories
            epmEntryMetadata.Categories = MergeSyndicationMapping <AtomCategoryMetadata>(customEntryMetadata.Categories, epmEntryMetadata.Categories);

            // Merge Links
            epmEntryMetadata.Links = MergeSyndicationMapping <AtomLinkMetadata>(customEntryMetadata.Links, epmEntryMetadata.Links);

            // Source
            // Copy the source element over from custom metadata since EPM doesn't use it yet.
            Debug.Assert(epmEntryMetadata.Source == null, "Once EPM actually writes to source element, implement the merge with custom metadata here.");
            epmEntryMetadata.Source = customEntryMetadata.Source;

            return(epmEntryMetadata);
        }
        /// <summary>
        /// Write the metadata attributes of a link in ATOM format
        /// </summary>
        /// <param name="relation">The value for the 'rel' attribute.</param>
        /// <param name="href">The value for the 'href' attribute.</param>
        /// <param name="hrefLang">The value for the 'hreflang' attribute.</param>
        /// <param name="title">The value for the 'title' attribute.</param>
        /// <param name="mediaType">The value for the 'type' attribute.</param>
        /// <param name="length">The value for the 'length' attribute.</param>
        private void WriteAtomLinkMetadataAttributes(string relation, string href, string hrefLang, string title, string mediaType, int?length)
        {
            // rel="..."
            if (relation != null)
            {
                this.XmlWriter.WriteAttributeString(AtomConstants.AtomLinkRelationAttributeName, relation);
            }

            // type="..."
            if (mediaType != null)
            {
                this.XmlWriter.WriteAttributeString(AtomConstants.AtomLinkTypeAttributeName, mediaType);
            }

            // title="..."
            if (title != null)
            {
                this.XmlWriter.WriteAttributeString(AtomConstants.AtomLinkTitleAttributeName, title);
            }

            // href="..."
            if (href == null)
            {
                throw new ODataException(o.Strings.ODataAtomWriterMetadataUtils_LinkMustSpecifyHref);
            }

            this.XmlWriter.WriteAttributeString(AtomConstants.AtomHRefAttributeName, href);

            // hreflang="..."
            if (hrefLang != null)
            {
                this.XmlWriter.WriteAttributeString(AtomConstants.AtomLinkHrefLangAttributeName, hrefLang);
            }

            // length="..."
            if (length.HasValue)
            {
                this.XmlWriter.WriteAttributeString(AtomConstants.AtomLinkLengthAttributeName, ODataAtomConvert.ToString(length.Value));
            }
        }
        internal void WriteEntryMetadata(AtomEntryMetadata entryMetadata, AtomEntryMetadata epmEntryMetadata, string updatedTime)
        {
            AtomEntryMetadata metadata = ODataAtomWriterMetadataEpmMergeUtils.MergeCustomAndEpmEntryMetadata(entryMetadata, epmEntryMetadata, base.MessageWriterSettings.WriterBehavior);

            if (metadata == null)
            {
                base.WriteEmptyElement("", "title", "http://www.w3.org/2005/Atom");
                base.WriteElementWithTextContent("", "updated", "http://www.w3.org/2005/Atom", updatedTime);
                base.WriteEmptyAuthor();
            }
            else
            {
                base.WriteTextConstruct("", "title", "http://www.w3.org/2005/Atom", metadata.Title);
                AtomTextConstruct summary = metadata.Summary;
                if (summary != null)
                {
                    base.WriteTextConstruct("", "summary", "http://www.w3.org/2005/Atom", summary);
                }
                string textContent = base.UseClientFormatBehavior ? metadata.PublishedString : (metadata.Published.HasValue ? ODataAtomConvert.ToAtomString(metadata.Published.Value) : null);
                if (textContent != null)
                {
                    base.WriteElementWithTextContent("", "published", "http://www.w3.org/2005/Atom", textContent);
                }
                string str2 = base.UseClientFormatBehavior ? metadata.UpdatedString : (metadata.Updated.HasValue ? ODataAtomConvert.ToAtomString(metadata.Updated.Value) : null);
                str2 = str2 ?? updatedTime;
                base.WriteElementWithTextContent("", "updated", "http://www.w3.org/2005/Atom", str2);
                bool flag = false;
                IEnumerable <AtomPersonMetadata> authors = metadata.Authors;
                if (authors != null)
                {
                    foreach (AtomPersonMetadata metadata2 in authors)
                    {
                        if (metadata2 == null)
                        {
                            throw new ODataException(Strings.ODataAtomWriterMetadataUtils_AuthorMetadataMustNotContainNull);
                        }
                        base.XmlWriter.WriteStartElement("", "author", "http://www.w3.org/2005/Atom");
                        base.WritePersonMetadata(metadata2);
                        base.XmlWriter.WriteEndElement();
                        flag = true;
                    }
                }
                if (!flag)
                {
                    base.WriteEmptyAuthor();
                }
                IEnumerable <AtomPersonMetadata> contributors = metadata.Contributors;
                if (contributors != null)
                {
                    foreach (AtomPersonMetadata metadata3 in contributors)
                    {
                        if (metadata3 == null)
                        {
                            throw new ODataException(Strings.ODataAtomWriterMetadataUtils_ContributorMetadataMustNotContainNull);
                        }
                        base.XmlWriter.WriteStartElement("", "contributor", "http://www.w3.org/2005/Atom");
                        base.WritePersonMetadata(metadata3);
                        base.XmlWriter.WriteEndElement();
                    }
                }
                IEnumerable <AtomLinkMetadata> links = metadata.Links;
                if (links != null)
                {
                    foreach (AtomLinkMetadata metadata4 in links)
                    {
                        if (metadata4 == null)
                        {
                            throw new ODataException(Strings.ODataAtomWriterMetadataUtils_LinkMetadataMustNotContainNull);
                        }
                        base.WriteAtomLink(metadata4, null);
                    }
                }
                IEnumerable <AtomCategoryMetadata> categories = metadata.Categories;
                if (categories != null)
                {
                    foreach (AtomCategoryMetadata metadata5 in categories)
                    {
                        if (metadata5 == null)
                        {
                            throw new ODataException(Strings.ODataAtomWriterMetadataUtils_CategoryMetadataMustNotContainNull);
                        }
                        base.WriteCategory(metadata5);
                    }
                }
                if (metadata.Rights != null)
                {
                    base.WriteTextConstruct("", "rights", "http://www.w3.org/2005/Atom", metadata.Rights);
                }
                AtomFeedMetadata source = metadata.Source;
                if (source != null)
                {
                    bool flag2;
                    base.XmlWriter.WriteStartElement("", "source", "http://www.w3.org/2005/Atom");
                    this.SourceMetadataSerializer.WriteFeedMetadata(source, null, updatedTime, out flag2);
                    base.XmlWriter.WriteEndElement();
                }
            }
        }