Exemple #1
0
        private ODataStreamReferenceValue GetMediaResource(object element, ResourceType entityResourceType, string title, Uri relativeUri)
        {
            ODataStreamReferenceValue value2 = null;

            if (entityResourceType.IsMediaLinkEntry)
            {
                string str;
                Uri    uri;
                string str2;
                base.Service.StreamProvider.GetStreamDescription(element, null, base.Service.OperationContext, out str, out uri, out str2);
                Uri uri2 = RequestUriProcessor.AppendEscapedSegment(relativeUri, "$value");
                value2 = new ODataStreamReferenceValue {
                    EditLink    = uri2,
                    ContentType = str2,
                    ReadLink    = uri ?? uri2
                };
                AtomStreamReferenceMetadata metadata2 = new AtomStreamReferenceMetadata();
                AtomLinkMetadata            metadata3 = new AtomLinkMetadata {
                    Title = title
                };
                metadata2.EditLink = metadata3;
                AtomStreamReferenceMetadata annotation = metadata2;
                value2.SetAnnotation <AtomStreamReferenceMetadata>(annotation);
                if (!string.IsNullOrEmpty(str))
                {
                    value2.ETag = str;
                }
            }
            return(value2);
        }
        /// <summary>
        /// Adds a new link to entry metadata.
        /// </summary>
        /// <param name="entryMetadata">The entry metadata to add the link to.</param>
        /// <param name="linkMetadata">The link metadata to add.</param>
        internal static void AddLink(this AtomEntryMetadata entryMetadata, AtomLinkMetadata linkMetadata)
        {
            Debug.Assert(entryMetadata != null, "entryMetadata != null");
            Debug.Assert(linkMetadata != null, "linkMetadata != null");

            entryMetadata.Links = entryMetadata.Links.ConcatToReadOnlyEnumerable("Ref", linkMetadata);
        }
        /// <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="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 association link.</param>
        /// <param name="associationLink">The association link for which to write the metadata.</param>
        internal static void WriteODataAssociationLinkMetadata(XmlWriter writer, Uri baseUri, ODataEntry entry, ODataAssociationLink associationLink)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(entry != null, "entry != null");
            Debug.Assert(associationLink != null, "link != null");
            Debug.Assert(!string.IsNullOrEmpty(associationLink.Name), "The link name was not verified yet.");
            Debug.Assert(associationLink.Url != null, "The link Url was not verified yet.");

            string linkRelation = AtomUtils.ComputeODataAssociationLinkRelation(associationLink);
            string linkHref     = AtomUtils.ToUrlAttributeValue(associationLink.Url, baseUri);
            string linkHrefLang = null;
            string linkType     = MimeConstants.MimeApplicationXml;
            string linkTitle    = associationLink.Name;
            int?   linkLength   = null;

            AtomLinkMetadata  linkMetadata  = null;
            AtomEntryMetadata entryMetadata = entry.Atom();

            if (entryMetadata != null)
            {
                // TODO: Determine the link metadata from the entry
            }

            if (linkMetadata != null)
            {
                Uri metadataHref = linkMetadata.Href;
                if (metadataHref != null)
                {
                    string metadataHrefString = AtomUtils.ToUrlAttributeValue(metadataHref, baseUri);
                    if (metadataHrefString != linkHref)
                    {
                        throw new ODataException(Strings.ODataAtomWriter_LinkMetadataHrefMustBeEqualWithLinkUrl(metadataHrefString, linkHref));
                    }
                }

                string metadataRelation = linkMetadata.Relation;
                if (metadataRelation != null && metadataRelation != linkRelation)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataRelationMustBeEqualWithComputedRelation(metadataRelation, linkRelation));
                }

                string metadataType = linkMetadata.MediaType;
                if (metadataType != null && metadataType != linkType)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataMediaTypeMustBeEqualWithComputedType(metadataRelation, linkType));
                }

                string metadataTitle = linkMetadata.Title;
                if (metadataTitle != null && metadataTitle != linkTitle)
                {
                    throw new ODataException(Strings.ODataAtomWriter_LinkMetadataTitleMustBeEqualWithLinkName(metadataTitle, linkTitle));
                }

                linkHrefLang = linkMetadata.HrefLang;
                linkLength   = linkMetadata.Length;
            }

            WriteAtomLinkMetadataAttributes(writer, linkRelation, linkHref, linkHrefLang, linkTitle, linkType, linkLength);
        }
        /// <summary>
        /// Adds a new link to feed metadata.
        /// </summary>
        /// <param name="feedMetadata">The feed metadata to add the link to.</param>
        /// <param name="linkMetadata">The link metadata to add.</param>
        internal static void AddLink(this AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata)
        {
            Debug.Assert(feedMetadata != null, "feedMetadata != null");
            Debug.Assert(linkMetadata != null, "linkMetadata != null");

            feedMetadata.Links = feedMetadata.Links.ConcatToReadOnlyEnumerable("Ref", linkMetadata);
        }
            /// <summary>
            /// Visits a stream reference value item.
            /// </summary>
            /// <param name="streamReferenceValue">The stream reference value item to visit.</param>
            /// <returns>An ODataPayloadElement representing the stream reference value.</returns>
            protected override ODataPayloadElement VisitStreamReferenceValue(ODataStreamReferenceValue streamReferenceValue)
            {
                ExceptionUtilities.CheckArgumentNotNull(streamReferenceValue, "streamReferenceValue");

                NamedStreamInstance namedStreamInstance = (NamedStreamInstance)base.VisitStreamReferenceValue(streamReferenceValue);

                AtomStreamReferenceMetadata streamMetadata = streamReferenceValue.GetAnnotation <AtomStreamReferenceMetadata>();

                if (streamMetadata != null)
                {
                    if (streamMetadata.EditLink != null)
                    {
                        AtomLinkMetadata editMetadata = streamMetadata.EditLink;
                        namedStreamInstance.AtomNamedStreamLink(editMetadata.Href == null ? null : editMetadata.Href.OriginalString, editMetadata.Relation, editMetadata.MediaType, editMetadata.HrefLang, editMetadata.Title, ToString(editMetadata.Length));
                    }

                    if (streamMetadata.SelfLink != null)
                    {
                        AtomLinkMetadata selfMetadata = streamMetadata.SelfLink;
                        namedStreamInstance.AtomNamedStreamLink(selfMetadata.Href == null ? null : selfMetadata.Href.OriginalString, selfMetadata.Relation, selfMetadata.MediaType, selfMetadata.HrefLang, selfMetadata.Title, ToString(selfMetadata.Length));
                    }
                }

                return(namedStreamInstance);
            }
 internal static void AddLinkToFeedMetadata(AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata)
 {
     if (object.ReferenceEquals(feedMetadata.Links, EmptyLinksList))
     {
         feedMetadata.Links = new ReadOnlyEnumerable <AtomLinkMetadata>();
     }
     ReaderUtils.GetSourceListOfEnumerable <AtomLinkMetadata>(feedMetadata.Links, "Links").Add(linkMetadata);
 }
Exemple #7
0
        /// <summary>
        /// Adds a new link to feed metadata.
        /// </summary>
        /// <param name="feedMetadata">The feed metadata to add the link to.</param>
        /// <param name="linkMetadata">The link metadata to add.</param>
        internal static void AddLink(this AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(feedMetadata != null, "feedMetadata != null");
            Debug.Assert(linkMetadata != null, "linkMetadata != null");

            feedMetadata.Links = feedMetadata.Links.ConcatToReadOnlyEnumerable("Links", linkMetadata);
        }
Exemple #8
0
        private static void AddLinkMetadata(DeferredLink payloadElement, ODataNavigationLink link)
        {
            AtomLinkMetadata metadata = CreateLinkMetadata(payloadElement.Annotations.OfType <XmlTreeAnnotation>());

            if (metadata != null)
            {
                link.SetAnnotation <AtomLinkMetadata>(metadata);
            }
        }
            /// <summary>
            /// Converts the Object Model representation of Atom link metadata into appropriate annotations for a link ODataPayloadElement.
            /// </summary>
            /// <param name="linkMetadata">The Atom link metadata, in Object Model representation, to convert.</param>
            /// <param name="payloadElement">The payload element to annotate.</param>
            private static void ConvertAtomLinkMetadata(AtomLinkMetadata linkMetadata, ODataPayloadElement payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(linkMetadata, "linkMetadata");
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "link");

                string lengthValue = linkMetadata.Length.HasValue ? linkMetadata.Length.Value.ToString() : null;

                payloadElement.AtomLink(linkMetadata.Href == null ? null : linkMetadata.Href.OriginalString, linkMetadata.Relation, linkMetadata.MediaType, linkMetadata.HrefLang, linkMetadata.Title, lengthValue);
            }
Exemple #10
0
        private void WriteEntry(IExpandedResult expanded, object element, bool resourceInstanceInFeed, ResourceType expectedType)
        {
            Uri uri;
            Func <ProjectionNode, bool> predicate = null;

            base.IncrementSegmentResultCount();
            ODataEntry        entry      = new ODataEntry();
            AtomEntryMetadata annotation = new AtomEntryMetadata();

            entry.SetAnnotation <AtomEntryMetadata>(annotation);
            string       name = expectedType.Name;
            ResourceType actualResourceType = WebUtil.GetNonPrimitiveResourceType(base.Provider, element);

            if (actualResourceType.ResourceTypeKind != ResourceTypeKind.EntityType)
            {
                throw new DataServiceException(500, System.Data.Services.Strings.BadProvider_InconsistentEntityOrComplexTypeUsage(actualResourceType.FullName));
            }
            Uri absoluteUri = Serializer.GetIdAndEditLink(element, actualResourceType, base.Provider, base.CurrentContainer, base.AbsoluteServiceUri, out uri);
            Uri relativeUri = new Uri(absoluteUri.AbsoluteUri.Substring(base.AbsoluteServiceUri.AbsoluteUri.Length), UriKind.Relative);

            entry.MediaResource = this.GetMediaResource(element, actualResourceType, name, relativeUri);
            entry.TypeName      = actualResourceType.FullName;
            entry.Id            = uri.AbsoluteUri;
            entry.EditLink      = relativeUri;
            AtomLinkMetadata metadata2 = new AtomLinkMetadata {
                Title = name
            };

            annotation.EditLink = metadata2;
            string eTagValue = base.GetETagValue(element, actualResourceType);

            if (eTagValue != null)
            {
                entry.ETag = eTagValue;
            }
            IEnumerable <ProjectionNode> projections = base.GetProjections();

            if (projections != null)
            {
                if (predicate == null)
                {
                    predicate = projectionNode => projectionNode.TargetResourceType.IsAssignableFrom(actualResourceType);
                }
                projections = projections.Where <ProjectionNode>(predicate);
                entry.SetAnnotation <ProjectedPropertiesAnnotation>(new ProjectedPropertiesAnnotation(from p in projections select p.PropertyName));
            }
            entry.AssociationLinks = this.GetEntityAssociationLinks(actualResourceType, relativeUri, projections);
            this.PopulateODataOperations(element, resourceInstanceInFeed, entry, actualResourceType);
            this.odataWriter.WriteStart(entry);
            this.WriteNavigationProperties(expanded, element, resourceInstanceInFeed, actualResourceType, absoluteUri, relativeUri, projections);
            entry.Properties = this.GetEntityProperties(element, actualResourceType, relativeUri, projections);
            this.odataWriter.WriteEnd();
        }
Exemple #11
0
        private static AtomLinkMetadata CreateLinkMetadata(IEnumerable <XmlTreeAnnotation> children)
        {
            AtomLinkMetadata metadata    = new AtomLinkMetadata();
            bool             initialized = false;

            foreach (XmlTreeAnnotation epmTree in children.Where(child => child.IsAttribute))
            {
                string localName = epmTree.LocalName;
                if (localName == TestAtomConstants.AtomLinkHrefAttributeName)
                {
                    Debug.Assert(epmTree.IsAttribute);
                    metadata.Href = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue);
                    initialized   = true;
                }
                else if (localName == TestAtomConstants.AtomLinkHrefLangAttributeName)
                {
                    Debug.Assert(epmTree.IsAttribute);
                    metadata.HrefLang = epmTree.PropertyValue;
                    initialized       = true;
                }
                else if (localName == TestAtomConstants.AtomLinkLengthAttributeName)
                {
                    Debug.Assert(epmTree.IsAttribute);
                    metadata.Length = string.IsNullOrEmpty(epmTree.PropertyValue) ? (int?)null : int.Parse(epmTree.PropertyValue);
                    initialized     = true;
                }
                else if (localName == TestAtomConstants.AtomLinkRelationAttributeName)
                {
                    Debug.Assert(epmTree.IsAttribute);
                    metadata.Relation = epmTree.PropertyValue;
                    initialized       = true;
                }
                else if (localName == TestAtomConstants.AtomLinkTitleAttributeName)
                {
                    Debug.Assert(epmTree.IsAttribute);
                    metadata.Title = epmTree.PropertyValue;
                    initialized    = true;
                }
                else if (localName == TestAtomConstants.AtomLinkTypeAttributeName)
                {
                    Debug.Assert(epmTree.IsAttribute);
                    metadata.MediaType = epmTree.PropertyValue;
                    initialized        = true;
                }
                else
                {
                    throw new NotSupportedException("Unsupported metadata '" + localName + "' found for a link.");
                }
            }

            return(initialized ? metadata : null);
        }
        /// <summary>
        /// Adds a new link to feed metadata.
        /// </summary>
        /// <param name="feedMetadata">The feed metadata to add the link to.</param>
        /// <param name="linkMetadata">The link metadata to add.</param>
        internal static void AddLinkToFeedMetadata(AtomFeedMetadata feedMetadata, AtomLinkMetadata linkMetadata)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(feedMetadata != null, "feedMetadata != null");
            Debug.Assert(linkMetadata != null, "linkMetadata != null");

            if (object.ReferenceEquals(feedMetadata.Links, EmptyLinksList))
            {
                feedMetadata.Links = new ReadOnlyEnumerable <AtomLinkMetadata>();
            }

            ReaderUtils.GetSourceListOfEnumerable(feedMetadata.Links, "Links").Add(linkMetadata);
        }
            /// <summary>
            /// Visits an entity reference links item.
            /// </summary>
            /// <param name="entityReferenceLinks">The entity reference links item to visit.</param>
            /// <returns>An ODataPayloadElement representing the entity reference links.</returns>
            protected override ODataPayloadElement VisitEntityReferenceLinks(ODataEntityReferenceLinks entityReferenceLinks)
            {
                ExceptionUtilities.CheckArgumentNotNull(entityReferenceLinks, "entityReferenceLinks");

                LinkCollection linkCollection = (LinkCollection)base.VisitEntityReferenceLinks(entityReferenceLinks);

                AtomLinkMetadata atomMetadata = entityReferenceLinks.GetAnnotation <AtomLinkMetadata>();

                if (atomMetadata != null)
                {
                    ConvertAtomLinkMetadata(atomMetadata, linkCollection);
                }

                return(linkCollection);
            }
        /// <summary>
        /// Write the metadata of a link in ATOM format
        /// </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="linkMetadata">The link metadata to write.</param>
        internal static void WriteAtomLinkMetadata(XmlWriter writer, Uri baseUri, AtomLinkMetadata linkMetadata)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(linkMetadata != null, "Link metadata must not be null.");

            // <atom:link ... >
            writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLinkElementName, AtomConstants.AtomNamespace);

            string linkHref = linkMetadata.Href == null ? null : AtomUtils.ToUrlAttributeValue(linkMetadata.Href, baseUri);

            WriteAtomLinkMetadataAttributes(writer, linkMetadata.Relation, linkHref, linkMetadata.HrefLang, linkMetadata.Title, linkMetadata.MediaType, linkMetadata.Length);

            // </atom:link>
            writer.WriteEndElement();
        }
            /// <summary>
            /// Converts the Object Model representation of Atom link metadata into appropriate annotations for a payload element representing a link.
            /// </summary>
            /// <param name="linkMetadata">The Atom link metadata, in Object Model representation, to convert.</param>
            /// <param name="linkPayloadElement">The link payload element to annotate.</param>
            /// <remarks>This method is only for use with payload elements that represent links, as it will skip over the root link annotation.</remarks>
            private static void ConvertAtomLinkChildrenMetadata(AtomLinkMetadata linkMetadata, ODataPayloadElement linkPayloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(linkMetadata, "linkMetadata");
                ExceptionUtilities.CheckArgumentNotNull(linkPayloadElement, "linkPayloadElement");

                // Since the payload element already represents a link, we annotate a temporary element
                // and copy the "children" annotations onto the actual payload element.
                var tempPayloadElement = new EntityInstance();

                ExceptionUtilities.Assert(!tempPayloadElement.Annotations.OfType <XmlTreeAnnotation>().Any(), "Payload element should not have XmlTreeAnnotations after construction");
                ConvertAtomLinkMetadata(linkMetadata, tempPayloadElement);

                XmlTreeAnnotation linkAnnotation = tempPayloadElement.Annotations.OfType <XmlTreeAnnotation>().Single();

                foreach (XmlTreeAnnotation childAnnotation in linkAnnotation.Children)
                {
                    linkPayloadElement.AddAnnotation(childAnnotation);
                }
            }
            /// <summary>
            /// Visits a navigation link item.
            /// </summary>
            /// <param name="navigationLink">The navigation link to visit.</param>
            /// <returns>An ODataPayloadElement representing the navigation link.</returns>
            protected override ODataPayloadElement VisitNavigationLink(ODataNavigationLink navigationLink)
            {
                ExceptionUtilities.CheckArgumentNotNull(navigationLink, "navigationLink");

                NavigationPropertyInstance navigationProperty = (NavigationPropertyInstance)base.VisitNavigationLink(navigationLink);

                // In ATOM even deferred links may know if they point to collection or singleton.
                // So add the content type annotation to them (through it IsCollection) so that comparison is precise.
                DeferredLink deferredLink = navigationProperty.Value as DeferredLink;

                if (deferredLink != null && navigationLink.IsCollection.HasValue)
                {
                    deferredLink.IsCollection(navigationLink.IsCollection.Value);
                }

                AtomLinkMetadata atomMetadata = navigationLink.GetAnnotation <AtomLinkMetadata>();

                if (atomMetadata != null && deferredLink != null)
                {
                    ConvertAtomLinkChildrenMetadata(atomMetadata, navigationProperty.Value);
                }

                return(navigationProperty);
            }
Exemple #17
0
        public void NavigationLinkMetadataWriterTest()
        {
            string testRelation          = "http://docs.oasis-open.org/odata/ns/related/SampleLinkName";
            string testIncorrectRelation = "http://odata.org/relation/1";
            string testTitle             = "SampleLinkName";
            string testIncorrectTitle    = "Test link 1";
            string testHref               = "http://odata.org/link";
            string testIncorrectHref      = "http://odata.org/links/1";
            string testHrefLang           = "de-AT";
            int?   testLength             = 999;
            string testMediaType          = "application/atom+xml;type=feed";
            string testIncorrectMediaType = "image/png";

            var testCases = new[]
            {
                new
                {
                    CustomizeLink = new Action <ODataNavigationLink>(
                        (link) =>
                    {
                        AtomLinkMetadata metadata = link.Atom();
                        metadata.Relation         = testRelation;
                        metadata.Title            = testTitle;
                        metadata.Href             = new Uri(testHref);
                        metadata.HrefLang         = testHrefLang;
                        metadata.Length           = testLength;
                        metadata.MediaType        = testMediaType;
                        link.Url = metadata.Href;
                    }),
                    Xml = @"<link rel=""" + testRelation + @""" type = """ + testMediaType + @""" title=""" + testTitle + @""" href=""" + testHref + @""" hreflang=""" + testHrefLang + @""" length=""" + testLength.Value + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @""" />",
                    ExpectedException = (ExpectedException)null
                },
                new
                {
                    CustomizeLink = new Action <ODataNavigationLink>(
                        (link) =>
                    {
                        AtomLinkMetadata metadata = link.Atom();
                        metadata.Relation         = testRelation;
                        metadata.Title            = testTitle;
                        metadata.Href             = new Uri(testIncorrectHref);
                        metadata.HrefLang         = testHrefLang;
                        metadata.Length           = testLength;
                        metadata.MediaType        = testMediaType;
                    }),
                    Xml = (string)null,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkHrefsMustMatch", "http://odata.org/link", "http://odata.org/links/1"),
                },
                new
                {
                    CustomizeLink = new Action <ODataNavigationLink>(
                        (link) =>
                    {
                        AtomLinkMetadata metadata = link.Atom();
                        metadata.Relation         = testIncorrectRelation;
                        metadata.Title            = testTitle;
                        metadata.Href             = new Uri(testHref);
                        metadata.HrefLang         = testHrefLang;
                        metadata.Length           = testLength;
                        metadata.MediaType        = testMediaType;
                    }),
                    Xml = (string)null,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkRelationsMustMatch", "http://docs.oasis-open.org/odata/ns/related/SampleLinkName", "http://odata.org/relation/1"),
                },
                new
                {
                    CustomizeLink = new Action <ODataNavigationLink>(
                        (link) =>
                    {
                        AtomLinkMetadata metadata = link.Atom();
                        metadata.Relation         = testRelation;
                        metadata.Title            = testTitle;
                        metadata.Href             = new Uri(testHref);
                        metadata.HrefLang         = testHrefLang;
                        metadata.Length           = testLength;
                        metadata.MediaType        = testIncorrectMediaType;
                    }),
                    Xml = (string)null,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkMediaTypesMustMatch", "application/atom+xml;type=feed", "image/png"),
                },
                new
                {
                    CustomizeLink = new Action <ODataNavigationLink>(
                        (link) =>
                    {
                        AtomLinkMetadata metadata = link.Atom();
                        metadata.Relation         = testRelation;
                        metadata.Title            = testIncorrectTitle;
                        metadata.Href             = new Uri(testHref);
                        metadata.HrefLang         = testHrefLang;
                        metadata.Length           = testLength;
                        metadata.MediaType        = testMediaType;
                    }),
                    Xml = (string)null,
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkTitlesMustMatch", "SampleLinkName", "Test link 1"),
                },
                new
                {
                    CustomizeLink = new Action <ODataNavigationLink>(
                        (link) =>
                    {
                        AtomLinkMetadata metadata = link.Atom();
                        metadata.Relation         = testRelation;
                        metadata.Title            = null;
                        metadata.Href             = new Uri(testHref);
                        metadata.HrefLang         = null;
                        metadata.Length           = null;
                        metadata.MediaType        = null;
                    }),
                    Xml = @"<link rel=""" + testRelation + @""" type = """ + testMediaType + @""" title=""" + testTitle + @""" href=""" + testHref + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""" />",
                    ExpectedException = (ExpectedException)null
                },
            };

            Func <XElement, XElement> fragmentExtractor = (e) => e;

            // Convert test cases to test descriptions
            Func <ODataNavigationLink>[] linkCreators = new Func <ODataNavigationLink>[]
            {
                () => ObjectModelUtils.CreateDefaultCollectionLink(),
                () => { var link = ObjectModelUtils.CreateDefaultCollectionLink(); link.SetAnnotation(new AtomLinkMetadata()); return(link); }
            };
            var testDescriptors = testCases.SelectMany(testCase =>
                                                       linkCreators.Select(linkCreator =>
            {
                ODataNavigationLink link = linkCreator();
                testCase.CustomizeLink(link);
                return(new PayloadWriterTestDescriptor <ODataItem>(this.Settings, link, testConfiguration =>
                                                                   new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                {
                    Xml = testCase.Xml, ExpectedException2 = testCase.ExpectedException, FragmentExtractor = fragmentExtractor
                }));
            }));

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.NavigationLinkPayloads),
                this.WriterTestConfigurationProvider.AtomFormatConfigurations,
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor.DeferredLinksToEntityReferenceLinksInRequest(testConfiguration), testConfiguration, this.Assert, this.Logger);
            });
        }
        /// <summary>
        /// Writes the syndication part of EPM for an entry into ATOM metadata OM.
        /// </summary>
        /// <param name="epmTargetTree">The EPM target tree to use.</param>
        /// <param name="epmValueCache">The entry properties value cache to use to access the properties.</param>
        /// <param name="resourceType">The resource type of the entry.</param>
        /// <param name="metadata">The metadata provider to use.</param>
        /// <param name="version">The version of OData protocol to use.</param>
        /// <returns>The ATOM metadata OM with the EPM values populated.</returns>
        internal static AtomEntryMetadata WriteEntryEpm(
            EpmTargetTree epmTargetTree, 
            EntryPropertiesValueCache epmValueCache, 
            ResourceType resourceType,
            DataServiceMetadataProviderWrapper metadata,
            ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(epmTargetTree != null, "epmTargetTree != null");
            Debug.Assert(epmValueCache != null, "epmValueCache != null");
            Debug.Assert(resourceType != null, "For any EPM to exist the metadata must be available.");

            // If there are no syndication mappings, just return null.
            EpmTargetPathSegment syndicationRootSegment = epmTargetTree.SyndicationRoot;
            Debug.Assert(syndicationRootSegment != null, "EPM Target tree must always have syndication root.");
            if (syndicationRootSegment.SubSegments.Count == 0)
            {
                return null;
            }

            AtomEntryMetadata entryMetadata = new AtomEntryMetadata();

            foreach (EpmTargetPathSegment targetSegment in syndicationRootSegment.SubSegments)
            {
                if (targetSegment.IsMultiValueProperty)
                {
                    Debug.Assert(
                        targetSegment.EpmInfo != null && targetSegment.EpmInfo.Attribute != null,
                        "MultiValue property target segment must have EpmInfo and the Epm Attribute.");
                    
                    ODataVersionChecker.CheckMultiValueProperties(version, targetSegment.EpmInfo.Attribute.SourcePath);

                    // WriteMultiValueEpm(entry, targetSegment, epmValueCache);
                    throw new NotImplementedException();
                }
                else if (targetSegment.HasContent)
                {
                    EntityPropertyMappingInfo epmInfo = targetSegment.EpmInfo;
                    Debug.Assert(
                        epmInfo != null && epmInfo.Attribute != null, 
                        "If the segment has content it must have EpmInfo which in turn must have the Epm attribute");

                    bool nullOnParentProperty;
                    object propertyValue = epmInfo.ReadEntryPropertyValue(epmValueCache, resourceType, metadata, out nullOnParentProperty);
                    string textPropertyValue = EpmWriterUtils.GetPropertyValueAsText(propertyValue);

                    switch (epmInfo.Attribute.TargetSyndicationItem)
                    {
                        case SyndicationItemProperty.Updated:
                            entryMetadata.Updated = CreateDateTimeValue(propertyValue, SyndicationItemProperty.Updated, version);
                            break;
                        case SyndicationItemProperty.Published:
                            entryMetadata.Published = CreateDateTimeValue(propertyValue, SyndicationItemProperty.Published, version);
                            break;
                        case SyndicationItemProperty.Rights:
                            entryMetadata.Rights = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                            break;
                        case SyndicationItemProperty.Summary:
                            entryMetadata.Summary = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                            break;
                        case SyndicationItemProperty.Title:
                            entryMetadata.Title = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                            break;
                        default:
                            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.EpmSyndicationWriter_WriteEntryEpm_ContentTarget));
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomAuthorElementName)
                {
                    AtomPersonMetadata authorMetadata = WritePersonEpm(targetSegment, epmValueCache, resourceType, metadata);

                    Debug.Assert(entryMetadata.Authors == null, "Found two mappings to author, that is invalid.");
                    if (authorMetadata != null)
                    {
                        entryMetadata.Authors = CreateSinglePersonList(authorMetadata);
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomContributorElementName)
                {
                    AtomPersonMetadata contributorMetadata = WritePersonEpm(targetSegment, epmValueCache, resourceType, metadata);

                    Debug.Assert(entryMetadata.Contributors == null, "Found two mappings to contributor, that is invalid.");
                    if (contributorMetadata != null)
                    {
                        entryMetadata.Contributors = CreateSinglePersonList(contributorMetadata);
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomLinkElementName)
                {
                    AtomLinkMetadata linkMetadata = new AtomLinkMetadata();
                    //// WriteLinkEpm(entry, targetSegment, epmValueCache);

                    Debug.Assert(targetSegment.CriteriaValue != null, "Mapping to link must be conditional.");
                    linkMetadata.Relation = targetSegment.CriteriaValue;
                    List<AtomLinkMetadata> links;
                    if (entryMetadata.Links == null)
                    {
                        links = new List<AtomLinkMetadata>();
                        entryMetadata.Links = links;
                    }
                    else
                    {
                        links = entryMetadata.Links as List<AtomLinkMetadata>;
                        Debug.Assert(links != null, "AtomEntryMetadata.Links must be of type List<AtomLinkMetadata> since we create it like that.");
                    }

                    links.Add(linkMetadata);

                    throw new NotImplementedException();
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomCategoryElementName)
                {
                    AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata();
                    //// WriteCategoryEpm(entry, targetSegment, epmValueCache)

                    Debug.Assert(targetSegment.CriteriaValue != null, "Mapping to category must be conditional.");
                    categoryMetadata.Scheme = targetSegment.CriteriaValue;
                    List<AtomCategoryMetadata> categories;
                    if (entryMetadata.Categories == null)
                    {
                        categories = new List<AtomCategoryMetadata>();
                        entryMetadata.Categories = categories;
                    }
                    else
                    {
                        categories = entryMetadata.Links as List<AtomCategoryMetadata>;
                        Debug.Assert(categories != null, "AtomEntryMetadata.Categories must be of type List<AtomCategoryMetadata> since we create it like that.");
                    }

                    categories.Add(categoryMetadata);

                    throw new NotImplementedException();
                }
                else
                {
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.EpmSyndicationWriter_WriteEntryEpm_TargetSegment));
                }
            }

            return entryMetadata;
        }
Exemple #19
0
        private static AtomFeedMetadata CreateFeedMetadata(IEnumerable <XmlTreeAnnotation> children, ODataFeed feed)
        {
            AtomFeedMetadata metadata = null;

            foreach (XmlTreeAnnotation epmTree in children)
            {
                if (epmTree.NamespaceName == TestAtomConstants.AtomNamespace)
                {
                    if (metadata == null)
                    {
                        metadata = new AtomFeedMetadata();
                    }

                    string localName = epmTree.LocalName;
                    if (localName == TestAtomConstants.AtomAuthorElementName)
                    {
                        AtomPersonMetadata author = CreateAuthorMetadata(epmTree.Children);

                        List <AtomPersonMetadata> authors;
                        if (metadata.Authors == null)
                        {
                            authors          = new List <AtomPersonMetadata>();
                            metadata.Authors = authors;
                        }
                        else
                        {
                            authors = (List <AtomPersonMetadata>)metadata.Authors;
                        }
                        authors.Add(author);
                    }
                    else if (localName == TestAtomConstants.AtomCategoryElementName)
                    {
                        AtomCategoryMetadata category = CreateCategoryMetadata(epmTree.Children);

                        List <AtomCategoryMetadata> categories;
                        if (metadata.Categories == null)
                        {
                            categories          = new List <AtomCategoryMetadata>();
                            metadata.Categories = categories;
                        }
                        else
                        {
                            categories = (List <AtomCategoryMetadata>)metadata.Categories;
                        }
                        categories.Add(category);
                    }
                    else if (localName == TestAtomConstants.AtomContributorElementName)
                    {
                        AtomPersonMetadata contributor = CreateAuthorMetadata(epmTree.Children);

                        List <AtomPersonMetadata> contributors;
                        if (metadata.Contributors == null)
                        {
                            contributors          = new List <AtomPersonMetadata>();
                            metadata.Contributors = contributors;
                        }
                        else
                        {
                            contributors = (List <AtomPersonMetadata>)metadata.Contributors;
                        }
                        contributors.Add(contributor);
                    }
                    else if (localName == TestAtomConstants.AtomGeneratorElementName)
                    {
                        metadata.Generator = CreateGeneratorMetadata(epmTree);
                    }
                    else if (localName == TestAtomConstants.AtomIconElementName)
                    {
                        metadata.Icon = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue);
                    }
                    else if (localName == TestAtomConstants.AtomIdElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        Uri id = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue, UriKind.Absolute);
                        if (feed == null)
                        {
                            // we are creating the metadata for an entry's 'source' metadata;
                            // we don't have a feed to store the Id on so it has to go into metadata
                            metadata.SourceId = id;
                        }
                        else
                        {
                            feed.Id = id;
                        }
                    }
                    else if (localName == TestAtomConstants.AtomLinkElementName)
                    {
                        AtomLinkMetadata link = CreateLinkMetadata(epmTree.Children);

                        List <AtomLinkMetadata> links;
                        if (metadata.Links == null)
                        {
                            links          = new List <AtomLinkMetadata>();
                            metadata.Links = links;
                        }
                        else
                        {
                            links = (List <AtomLinkMetadata>)metadata.Contributors;
                        }
                        links.Add(link);
                    }
                    else if (localName == TestAtomConstants.AtomLogoElementName)
                    {
                        metadata.Logo = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue);
                    }
                    else if (localName == TestAtomConstants.AtomRightsElementName)
                    {
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Rights = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomSubtitleElementName)
                    {
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Subtitle = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomTitleElementName)
                    {
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Title = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomUpdatedElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        metadata.Updated = string.IsNullOrEmpty(epmTree.PropertyValue) ? (DateTimeOffset?)null : DateTimeOffset.Parse(epmTree.PropertyValue);
                    }
                    else
                    {
                        throw new NotSupportedException("Unsupported atom metadata found!");
                    }
                }
            }

            return(metadata);
        }
        public void FeedMetadataWriterTest()
        {
            AtomTextConstruct testRights = new AtomTextConstruct {
                Text = "Copyright Data Fx team."
            };
            AtomTextConstruct testTitle = new AtomTextConstruct {
                Text = "Test title"
            };
            AtomTextConstruct testSubtitle = new AtomTextConstruct {
                Text = "Test subtitle"
            };
            const string testUpdated = "2010-11-01T00:04:00Z";
            const string testIcon    = "http://odata.org/icon";
            const string testLogo    = "http://odata.org/logo";

            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)
                }
            };

            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
                }
            };

            var selfLink = new AtomLinkMetadata()
            {
                Relation  = TestAtomConstants.AtomSelfRelationAttributeValue,
                Title     = testLinkTitle,
                Href      = new Uri(testLinkHref),
                HrefLang  = testLinkHrefLang,
                Length    = testLinkLength,
                MediaType = testLinkMediaType
            };

            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 FeedMetadataTestCase[] {
                new FeedMetadataTestCase { // specify an icon via metadata
                    CustomizeMetadata = metadata => metadata.Icon = new Uri(testIcon),
                    Xml       = @"<icon xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testIcon + @"</icon>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomIconElementName)
                },
                new FeedMetadataTestCase { // specify a logo via metadata
                    CustomizeMetadata = metadata => metadata.Logo = new Uri(testLogo),
                    Xml       = @"<logo xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testLogo + @"</logo>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomLogoElementName)
                },
                new FeedMetadataTestCase { // specify rights via metadata
                    CustomizeMetadata = metadata => metadata.Rights = testRights,
                    Xml       = @"<rights type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testRights.Text + @"</rights>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomRightsElementName)
                },
                new FeedMetadataTestCase { // specify a subtitle via metadata
                    CustomizeMetadata = metadata => metadata.Subtitle = testSubtitle,
                    Xml       = @"<subtitle type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testSubtitle.Text + @"</subtitle>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomSubtitleElementName)
                },
                new FeedMetadataTestCase { // specify a title via metadata
                    CustomizeMetadata = metadata => metadata.Title = testTitle,
                    Xml       = @"<title type=""text"" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testTitle.Text + @"</title>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomTitleElementName)
                },
                new FeedMetadataTestCase { // specify an updated date via metadata
                    CustomizeMetadata = metadata => metadata.Updated = DateTimeOffset.Parse(testUpdated),
                    Xml       = @"<updated xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testUpdated + @"</updated>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomUpdatedElementName)
                },
                new FeedMetadataTestCase { // no author specified, the default author with empty name is written
                    CustomizeMetadata = metadata => metadata.Authors = null,
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name />",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new FeedMetadataTestCase { // specify an author via metadata
                    CustomizeMetadata = 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 FeedMetadataTestCase { // no author specified but some entries written, no author should be written
                    CustomizeMetadata = metadata => metadata.Authors = null,
                    CustomizePayload  = feed => new ODataItem[] { feed, ObjectModelUtils.CreateDefaultEntry() },
                    Xml       = "<authors />",
                    Extractor = result => new XElement("authors", fragmentExtractor(TestAtomConstants.AtomAuthorElementName)(result))
                },
                new FeedMetadataTestCase { // specify an author via metadata and some entries (the author should be written anyway)
                    CustomizeMetadata = metadata => metadata.Authors = testAuthors,
                    CustomizePayload  = feed => new ODataItem[] { feed, ObjectModelUtils.CreateDefaultEntry() },
                    Xml = string.Join(
                        "$(NL)",
                        @"<author xmlns=""" + TestAtomConstants.AtomNamespace + @""">",
                        @"  <name>" + testAuthorName + @"</name>",
                        @"  <uri>" + testAuthorUri + @"</uri>",
                        @"  <email>" + testAuthorEmail + @"</email>",
                        @"</author>"),
                    Extractor = fragmentExtractor(TestAtomConstants.AtomAuthorElementName)
                },
                new FeedMetadataTestCase { // specify a category via metadata
                    CustomizeMetadata = metadata => metadata.Categories = testCategories,
                    Xml       = @"<category term=""" + testCategoryTerm + @""" scheme=""" + testCategoryScheme + @""" label=""" + testCategoryLabel + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""" />",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomCategoryElementName)
                },
                new FeedMetadataTestCase { // specify a contributor via metadata
                    CustomizeMetadata = 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 FeedMetadataTestCase { // specify a generator via metadata
                    CustomizeMetadata = metadata => metadata.Generator = testGenerator,
                    Xml       = @"<generator uri=""" + testGeneratorUri + @""" version=""" + testGeneratorVersion + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @""">" + testGeneratorName + @"</generator>",
                    Extractor = fragmentExtractor(TestAtomConstants.AtomGeneratorElementName)
                },
                new FeedMetadataTestCase { // specify a link via metadata
                    CustomizeMetadata = metadata => metadata.Links = testLinks,
                    Xml       = @"<link rel=""" + testLinkRelation + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .Single()
                },
                new FeedMetadataTestCase { // no self link specified
                    CustomizeMetadata = metadata => metadata.SelfLink = null,
                    Xml       = @"<selflink/>",
                    Extractor = (e) => new XElement("selflink",
                                                    e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                                    .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomSelfRelationAttributeValue))
                },
                new FeedMetadataTestCase { // Some self link specified
                    CustomizeMetadata = metadata => metadata.SelfLink = selfLink,
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomSelfRelationAttributeValue + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomSelfRelationAttributeValue)
                },
                new FeedMetadataTestCase { // Non-self relation
                    CustomizeMetadata = metadata => metadata.SelfLink = new AtomLinkMetadata {
                        Relation = "SelF", Href = new Uri(testLinkHref)
                    },
                    ExpectedException = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkRelationsMustMatch", "self", "SelF"),
                },
                new FeedMetadataTestCase { // no next link on either OM or metadata specified
                    CustomizeMetadata = metadata => metadata.NextPageLink = null,
                    Xml       = @"<nextlink/>",
                    Extractor = (e) => new XElement("nextlink",
                                                    e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                                    .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue)),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // the next link is only specified on metadata - nothing is written
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Relation = "next", Href = new Uri(testLinkHref)
                    },
                    Xml       = @"<nextlink/>",
                    Extractor = (e) => new XElement("nextlink",
                                                    e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                                    .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue)),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified only on the OM
                    CustomizeMetadata = metadata => metadata.NextPageLink = null,
                    CustomizePayload  = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomNextRelationAttributeValue + @""" href=""" + testLinkHref + @""" xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - no conflicts
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomNextRelationAttributeValue + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - no conflicts cause values are identical
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Relation = TestAtomConstants.AtomNextRelationAttributeValue, Href = new Uri(testLinkHref), Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    Xml       = @"<link rel=""" + TestAtomConstants.AtomNextRelationAttributeValue + @""" type = """ + testLinkMediaType + @""" title=""" + testLinkTitle + @""" href=""" + testLinkHref + @""" hreflang=""" + testLinkHrefLang + @""" length=""" + testLinkLength + @"""  xmlns=""" + TestAtomConstants.AtomNamespace + @"""/>",
                    Extractor = (e) => e.Elements(TestAtomConstants.AtomXNamespace + TestAtomConstants.AtomLinkElementName)
                                .SingleOrDefault(l => (string)l.Attribute(TestAtomConstants.AtomLinkRelationAttributeName) == TestAtomConstants.AtomNextRelationAttributeValue),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - conflict on relation
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Relation = "Next", Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload      = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    ExpectedException     = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkRelationsMustMatch", "next", "Next"),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
                new FeedMetadataTestCase { // Next link specified both on OM and on metadata - conflict on href
                    CustomizeMetadata = metadata => metadata.NextPageLink = new AtomLinkMetadata {
                        Href = new Uri("http://odata.org/different"), Title = testLinkTitle, HrefLang = testLinkHrefLang, Length = testLinkLength, MediaType = testLinkMediaType
                    },
                    CustomizePayload      = feed => { feed.NextPageLink = new Uri(testLinkHref); return(new ODataItem[] { feed }); },
                    ExpectedException     = ODataExpectedExceptions.ODataException("ODataAtomWriterMetadataUtils_LinkHrefsMustMatch", testLinkHref, "http://odata.org/different"),
                    SkipTestConfiguration = tc => tc.IsRequest
                },
            };

            this.CreateTestDescriptorsAndRunTests(testCases, WriterPayloads.FeedPayloads);
        }
        /// <summary>
        /// Writes the syndication part of EPM for an entry into ATOM metadata OM.
        /// </summary>
        /// <param name="epmTargetTree">The EPM target tree to use.</param>
        /// <param name="epmValueCache">The entry properties value cache to use to access the properties.</param>
        /// <param name="resourceType">The resource type of the entry.</param>
        /// <param name="metadata">The metadata provider to use.</param>
        /// <param name="version">The version of OData protocol to use.</param>
        /// <returns>The ATOM metadata OM with the EPM values populated.</returns>
        internal static AtomEntryMetadata WriteEntryEpm(
            EpmTargetTree epmTargetTree,
            EntryPropertiesValueCache epmValueCache,
            ResourceType resourceType,
            DataServiceMetadataProviderWrapper metadata,
            ODataVersion version)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(epmTargetTree != null, "epmTargetTree != null");
            Debug.Assert(epmValueCache != null, "epmValueCache != null");
            Debug.Assert(resourceType != null, "For any EPM to exist the metadata must be available.");

            // If there are no syndication mappings, just return null.
            EpmTargetPathSegment syndicationRootSegment = epmTargetTree.SyndicationRoot;

            Debug.Assert(syndicationRootSegment != null, "EPM Target tree must always have syndication root.");
            if (syndicationRootSegment.SubSegments.Count == 0)
            {
                return(null);
            }

            AtomEntryMetadata entryMetadata = new AtomEntryMetadata();

            foreach (EpmTargetPathSegment targetSegment in syndicationRootSegment.SubSegments)
            {
                if (targetSegment.IsMultiValueProperty)
                {
                    Debug.Assert(
                        targetSegment.EpmInfo != null && targetSegment.EpmInfo.Attribute != null,
                        "MultiValue property target segment must have EpmInfo and the Epm Attribute.");

                    ODataVersionChecker.CheckMultiValueProperties(version, targetSegment.EpmInfo.Attribute.SourcePath);

                    // WriteMultiValueEpm(entry, targetSegment, epmValueCache);
                    throw new NotImplementedException();
                }
                else if (targetSegment.HasContent)
                {
                    EntityPropertyMappingInfo epmInfo = targetSegment.EpmInfo;
                    Debug.Assert(
                        epmInfo != null && epmInfo.Attribute != null,
                        "If the segment has content it must have EpmInfo which in turn must have the Epm attribute");

                    bool   nullOnParentProperty;
                    object propertyValue     = epmInfo.ReadEntryPropertyValue(epmValueCache, resourceType, metadata, out nullOnParentProperty);
                    string textPropertyValue = EpmWriterUtils.GetPropertyValueAsText(propertyValue);

                    switch (epmInfo.Attribute.TargetSyndicationItem)
                    {
                    case SyndicationItemProperty.Updated:
                        entryMetadata.Updated = CreateDateTimeValue(propertyValue, SyndicationItemProperty.Updated, version);
                        break;

                    case SyndicationItemProperty.Published:
                        entryMetadata.Published = CreateDateTimeValue(propertyValue, SyndicationItemProperty.Published, version);
                        break;

                    case SyndicationItemProperty.Rights:
                        entryMetadata.Rights = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                        break;

                    case SyndicationItemProperty.Summary:
                        entryMetadata.Summary = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                        break;

                    case SyndicationItemProperty.Title:
                        entryMetadata.Title = CreateAtomTextConstruct(textPropertyValue, epmInfo.Attribute.TargetTextContentKind, version);
                        break;

                    default:
                        throw new ODataException(Strings.General_InternalError(InternalErrorCodes.EpmSyndicationWriter_WriteEntryEpm_ContentTarget));
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomAuthorElementName)
                {
                    AtomPersonMetadata authorMetadata = WritePersonEpm(targetSegment, epmValueCache, resourceType, metadata);

                    Debug.Assert(entryMetadata.Authors == null, "Found two mappings to author, that is invalid.");
                    if (authorMetadata != null)
                    {
                        entryMetadata.Authors = CreateSinglePersonList(authorMetadata);
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomContributorElementName)
                {
                    AtomPersonMetadata contributorMetadata = WritePersonEpm(targetSegment, epmValueCache, resourceType, metadata);

                    Debug.Assert(entryMetadata.Contributors == null, "Found two mappings to contributor, that is invalid.");
                    if (contributorMetadata != null)
                    {
                        entryMetadata.Contributors = CreateSinglePersonList(contributorMetadata);
                    }
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomLinkElementName)
                {
                    AtomLinkMetadata linkMetadata = new AtomLinkMetadata();
                    //// WriteLinkEpm(entry, targetSegment, epmValueCache);

                    Debug.Assert(targetSegment.CriteriaValue != null, "Mapping to link must be conditional.");
                    linkMetadata.Relation = targetSegment.CriteriaValue;
                    List <AtomLinkMetadata> links;
                    if (entryMetadata.Links == null)
                    {
                        links = new List <AtomLinkMetadata>();
                        entryMetadata.Links = links;
                    }
                    else
                    {
                        links = entryMetadata.Links as List <AtomLinkMetadata>;
                        Debug.Assert(links != null, "AtomEntryMetadata.Links must be of type List<AtomLinkMetadata> since we create it like that.");
                    }

                    links.Add(linkMetadata);

                    throw new NotImplementedException();
                }
                else if (targetSegment.SegmentName == AtomConstants.AtomCategoryElementName)
                {
                    AtomCategoryMetadata categoryMetadata = new AtomCategoryMetadata();
                    //// WriteCategoryEpm(entry, targetSegment, epmValueCache)

                    Debug.Assert(targetSegment.CriteriaValue != null, "Mapping to category must be conditional.");
                    categoryMetadata.Scheme = targetSegment.CriteriaValue;
                    List <AtomCategoryMetadata> categories;
                    if (entryMetadata.Categories == null)
                    {
                        categories = new List <AtomCategoryMetadata>();
                        entryMetadata.Categories = categories;
                    }
                    else
                    {
                        categories = entryMetadata.Links as List <AtomCategoryMetadata>;
                        Debug.Assert(categories != null, "AtomEntryMetadata.Categories must be of type List<AtomCategoryMetadata> since we create it like that.");
                    }

                    categories.Add(categoryMetadata);

                    throw new NotImplementedException();
                }
                else
                {
                    throw new ODataException(Strings.General_InternalError(InternalErrorCodes.EpmSyndicationWriter_WriteEntryEpm_TargetSegment));
                }
            }

            return(entryMetadata);
        }
Exemple #22
0
        private static void AddEntryMetadata(EntityInstance payloadElement, ODataEntry entry)
        {
            AtomEntryMetadata metadata = null;

            foreach (XmlTreeAnnotation epmTree in payloadElement.Annotations.OfType <XmlTreeAnnotation>())
            {
                if (epmTree.NamespaceName == TestAtomConstants.AtomNamespace)
                {
                    if (metadata == null)
                    {
                        metadata = new AtomEntryMetadata();
                    }

                    string localName = epmTree.LocalName;
                    if (localName == TestAtomConstants.AtomAuthorElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomPersonMetadata author = CreateAuthorMetadata(epmTree.Children);

                        List <AtomPersonMetadata> authors;
                        if (metadata.Authors == null)
                        {
                            authors          = new List <AtomPersonMetadata>();
                            metadata.Authors = authors;
                        }
                        else
                        {
                            authors = (List <AtomPersonMetadata>)metadata.Authors;
                        }
                        authors.Add(author);
                    }
                    else if (localName == TestAtomConstants.AtomCategoryElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomCategoryMetadata category = CreateCategoryMetadata(epmTree.Children);

                        List <AtomCategoryMetadata> categories;
                        if (metadata.Categories == null)
                        {
                            categories          = new List <AtomCategoryMetadata>();
                            metadata.Categories = categories;
                        }
                        else
                        {
                            categories = (List <AtomCategoryMetadata>)metadata.Categories;
                        }
                        categories.Add(category);
                    }
                    else if (localName == TestAtomConstants.AtomContributorElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomPersonMetadata contributor = CreateAuthorMetadata(epmTree.Children);

                        List <AtomPersonMetadata> contributors;
                        if (metadata.Contributors == null)
                        {
                            contributors          = new List <AtomPersonMetadata>();
                            metadata.Contributors = contributors;
                        }
                        else
                        {
                            contributors = (List <AtomPersonMetadata>)metadata.Contributors;
                        }
                        contributors.Add(contributor);
                    }
                    else if (localName == TestAtomConstants.AtomIdElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        entry.Id = string.IsNullOrEmpty(epmTree.PropertyValue) ? null : new Uri(epmTree.PropertyValue);
                    }
                    else if (localName == TestAtomConstants.AtomLinkElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomLinkMetadata link = CreateLinkMetadata(epmTree.Children);

                        List <AtomLinkMetadata> links;
                        if (metadata.Links == null)
                        {
                            links          = new List <AtomLinkMetadata>();
                            metadata.Links = links;
                        }
                        else
                        {
                            links = (List <AtomLinkMetadata>)metadata.Links;
                        }
                        links.Add(link);
                    }
                    else if (localName == TestAtomConstants.AtomPublishedElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        metadata.Published = string.IsNullOrEmpty(epmTree.PropertyValue) ? (DateTimeOffset?)null : DateTimeOffset.Parse(epmTree.PropertyValue);
                    }
                    else if (localName == TestAtomConstants.AtomRightsElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Rights = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomSourceElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        metadata.Source = CreateFeedMetadata(epmTree.Children, null);
                    }
                    else if (localName == TestAtomConstants.AtomSummaryElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Summary = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomTitleElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        AtomTextConstructKind atomConstructKind = GetAtomConstructKind(epmTree.Children);
                        metadata.Title = new AtomTextConstruct {
                            Kind = atomConstructKind, Text = epmTree.PropertyValue
                        };
                    }
                    else if (localName == TestAtomConstants.AtomUpdatedElementName)
                    {
                        Debug.Assert(!epmTree.IsAttribute);
                        metadata.Updated = string.IsNullOrEmpty(epmTree.PropertyValue) ? (DateTimeOffset?)null : DateTimeOffset.Parse(epmTree.PropertyValue);
                    }
                    else
                    {
                        throw new NotSupportedException("Unsupported atom metadata '" + localName + "' found for entry!");
                    }
                }
            }

            // Fix up metadata for baselining
            metadata = metadata.Fixup();

            if (metadata != null)
            {
                entry.SetAnnotation <AtomEntryMetadata>(metadata);
            }
        }
            /// <summary>
            /// Converts the Object Model representation of Atom metadata for entries into appropriate PayloadElement annotations
            /// </summary>
            /// <param name="entryMetadata">the Atom entry metadata, in Object Model representation, to convert</param>
            /// <param name="entry">the EntityInstance to annotate</param>
            private static void ConvertAtomEntryMetadata(AtomEntryMetadata entryMetadata, EntityInstance entry)
            {
                ExceptionUtilities.CheckArgumentNotNull(entryMetadata, "entryMetadata");
                ExceptionUtilities.CheckArgumentNotNull(entry, "entry");

                foreach (var author in entryMetadata.Authors)
                {
                    entry.AtomAuthor(author.Name, author.Uri == null ? null : author.Uri.OriginalString, author.Email);
                }

                foreach (var category in entryMetadata.Categories)
                {
                    entry.AtomCategory(category.Term, category.Scheme, category.Label);
                }

                foreach (var contributor in entryMetadata.Contributors)
                {
                    entry.AtomContributor(contributor.Name, contributor.Uri == null? null : contributor.Uri.OriginalString, contributor.Email);
                }

                if (entryMetadata.EditLink != null)
                {
                    AtomLinkMetadata editLink = entryMetadata.EditLink;
                    entry.AtomEditLink(editLink.Href == null ? null : editLink.Href.OriginalString, editLink.MediaType, editLink.HrefLang, editLink.Title, ToString(editLink.Length));
                }

                foreach (var link in entryMetadata.Links)
                {
                    entry.AtomLink(link.Href == null ? null : link.Href.OriginalString, link.Relation, link.MediaType, link.HrefLang, link.Title, ToString(link.Length));
                }

                if (entryMetadata.Published.HasValue)
                {
                    entry.AtomPublished(ToString(entryMetadata.Published));
                }

                if (entryMetadata.Rights != null)
                {
                    entry.AtomRights(entryMetadata.Rights.Text, ToString(entryMetadata.Rights.Kind));
                }

                if (entryMetadata.SelfLink != null)
                {
                    AtomLinkMetadata selfLink = entryMetadata.SelfLink;
                    entry.AtomSelfLink(selfLink.Href == null ? null : selfLink.Href.OriginalString, selfLink.MediaType, selfLink.HrefLang, selfLink.Title, ToString(selfLink.Length));
                }

                if (entryMetadata.CategoryWithTypeName != null)
                {
                    AtomCategoryMetadata categoryWithTypeName = entryMetadata.CategoryWithTypeName;
                    entry.AtomCategoryWithTypeName(categoryWithTypeName.Term, categoryWithTypeName.Label);
                }

                if (entryMetadata.Source != null)
                {
                    EntitySetInstance tempSourceFeed = new EntitySetInstance();
                    ConvertAtomFeedMetadata(entryMetadata.Source, tempSourceFeed);
                    entry.AtomSource(tempSourceFeed);
                }

                if (entryMetadata.Summary != null)
                {
                    entry.AtomSummary(entryMetadata.Summary.Text, ToString(entryMetadata.Summary.Kind));
                }

                if (entryMetadata.Title != null)
                {
                    entry.AtomTitle(entryMetadata.Title.Text, ToString(entryMetadata.Title.Kind));
                }

                if (entryMetadata.Updated.HasValue)
                {
                    entry.AtomUpdated(ToString(entryMetadata.Updated));
                }
            }
 /// <summary>
 /// Visits an ATOM link metadata.
 /// </summary>
 /// <param name="atomLinkMetadata">The link metadata to visit.</param>
 protected virtual void VisitAtomLinkMetadata(AtomLinkMetadata atomLinkMetadata)
 {
 }
        /// <summary>
        /// Visits an ATOM metadata object.
        /// </summary>
        /// <param name="atomMetadata"></param>
        protected virtual void VisitAtomMetadata(object atomMetadata)
        {
            if (atomMetadata == null)
            {
                return;
            }

            AtomCategoryMetadata atomCategoryMetadata = atomMetadata as AtomCategoryMetadata;

            if (atomCategoryMetadata != null)
            {
                this.VisitAtomCategoryMetadata(atomCategoryMetadata);
                return;
            }

            AtomEntryMetadata atomEntryMetadata = atomMetadata as AtomEntryMetadata;

            if (atomEntryMetadata != null)
            {
                this.VisitAtomEntryMetadata(atomEntryMetadata);
                return;
            }

            AtomFeedMetadata atomFeedMetadata = atomMetadata as AtomFeedMetadata;

            if (atomFeedMetadata != null)
            {
                this.VisitAtomFeedMetadata(atomFeedMetadata);
                return;
            }

            AtomGeneratorMetadata atomGeneratorMetadata = atomMetadata as AtomGeneratorMetadata;

            if (atomGeneratorMetadata != null)
            {
                this.VisitAtomGeneratorMetadata(atomGeneratorMetadata);
                return;
            }

            AtomLinkMetadata atomLinkMetadata = atomMetadata as AtomLinkMetadata;

            if (atomLinkMetadata != null)
            {
                this.VisitAtomLinkMetadata(atomLinkMetadata);
                return;
            }

            AtomPersonMetadata atomPersonMetadata = atomMetadata as AtomPersonMetadata;

            if (atomPersonMetadata != null)
            {
                this.VisitAtomPersonMetadata(atomPersonMetadata);
                return;
            }

            AtomResourceCollectionMetadata atomResourceCollectionMetadata = atomMetadata as AtomResourceCollectionMetadata;

            if (atomResourceCollectionMetadata != null)
            {
                this.VisitAtomResourceCollectionMetadata(atomResourceCollectionMetadata);
                return;
            }

            AtomStreamReferenceMetadata atomStreamReferenceMetadata = atomMetadata as AtomStreamReferenceMetadata;

            if (atomStreamReferenceMetadata != null)
            {
                this.VisitAtomStreamReferenceMetadata(atomStreamReferenceMetadata);
                return;
            }

            AtomTextConstruct atomTextConstruct = atomMetadata as AtomTextConstruct;

            if (atomTextConstruct != null)
            {
                this.VisitAtomTextConstruct(atomTextConstruct);
                return;
            }

            AtomWorkspaceMetadata atomWorkspaceMetadata = atomMetadata as AtomWorkspaceMetadata;

            if (atomWorkspaceMetadata != null)
            {
                this.VisitAtomWorkspaceMetadata(atomWorkspaceMetadata);
                return;
            }

            AtomCategoriesMetadata atomCategoriesMetadata = atomMetadata as AtomCategoriesMetadata;

            if (atomCategoriesMetadata != null)
            {
                this.VisitAtomCategoriesMetadata(atomCategoriesMetadata);
                return;
            }

            ExceptionUtilities.Assert(false, "Unrecognized ATOM metadata object {0} of type {1}.", atomMetadata.ToString(), atomMetadata.GetType().ToString());
        }
        /// <summary>
        /// Write the metadata of a link in ATOM format
        /// </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="linkMetadata">The link metadata to write.</param>
        internal static void WriteAtomLinkMetadata(XmlWriter writer, Uri baseUri, AtomLinkMetadata linkMetadata)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(writer != null, "writer != null");
            Debug.Assert(linkMetadata != null, "Link metadata must not be null.");

            // <atom:link ... >
            writer.WriteStartElement(AtomConstants.AtomNamespacePrefix, AtomConstants.AtomLinkElementName, AtomConstants.AtomNamespace);

            string linkHref = linkMetadata.Href == null ? null : AtomUtils.ToUrlAttributeValue(linkMetadata.Href, baseUri);
            WriteAtomLinkMetadataAttributes(writer, linkMetadata.Relation, linkHref, linkMetadata.HrefLang, linkMetadata.Title, linkMetadata.MediaType, linkMetadata.Length);

            // </atom:link>
            writer.WriteEndElement();
        }
            /// <summary>
            /// Converts the Object Model representation of Atom metadata for feeds into appropriate PayloadElement annotations
            /// </summary>
            /// <param name="feedMetadata">the Atom feed metadata, in Object Model representation, to convert</param>
            /// <param name="feed">the EntitySetInstance to annotate</param>
            private static void ConvertAtomFeedMetadata(AtomFeedMetadata feedMetadata, EntitySetInstance feed)
            {
                ExceptionUtilities.CheckArgumentNotNull(feedMetadata, "feedMetadata");
                ExceptionUtilities.CheckArgumentNotNull(feed, "feed");

                foreach (var author in feedMetadata.Authors)
                {
                    feed.AtomAuthor(author.Name, author.Uri == null ? null : author.Uri.OriginalString, author.Email);
                }

                foreach (var category in feedMetadata.Categories)
                {
                    feed.AtomCategory(category.Term, category.Scheme, category.Label);
                }

                foreach (var contributor in feedMetadata.Contributors)
                {
                    feed.AtomContributor(contributor.Name, contributor.Uri == null ? null : contributor.Uri.OriginalString, contributor.Email);
                }

                if (feedMetadata.Generator != null)
                {
                    feed.AtomGenerator(feedMetadata.Generator.Name, feedMetadata.Generator.Uri == null ? null : feedMetadata.Generator.Uri.OriginalString, feedMetadata.Generator.Version);
                }

                if (feedMetadata.Icon != null)
                {
                    feed.AtomIcon(feedMetadata.Icon.OriginalString);
                }

                foreach (var link in feedMetadata.Links)
                {
                    string linkLength = link.Length.HasValue ? link.Length.Value.ToString() : null;
                    feed.AtomLink(link.Href == null ? null : link.Href.OriginalString, link.Relation, link.MediaType, link.HrefLang, link.Title, linkLength);
                }

                if (feedMetadata.Logo != null)
                {
                    feed.AtomLogo(feedMetadata.Logo.OriginalString);
                }

                if (feedMetadata.Rights != null)
                {
                    feed.AtomRights(feedMetadata.Rights.Text, ToString(feedMetadata.Rights.Kind));
                }

                if (feedMetadata.SelfLink != null)
                {
                    AtomLinkMetadata selfLink = feedMetadata.SelfLink;
                    ExceptionUtilities.Assert(selfLink.Relation == TestAtomConstants.AtomSelfRelationAttributeValue, "The self link ATOM metadata must have the rel set to 'self'.");
                    string selfLinkLength = selfLink.Length.HasValue ? selfLink.Length.Value.ToString() : null;
                    feed.AtomSelfLink(selfLink.Href == null ? null : selfLink.Href.OriginalString, selfLink.MediaType, selfLink.HrefLang, selfLink.Title, selfLinkLength);
                }

                if (feedMetadata.NextPageLink != null)
                {
                    AtomLinkMetadata nextPageLink = feedMetadata.NextPageLink;
                    ExceptionUtilities.Assert(nextPageLink.Relation == TestAtomConstants.AtomNextRelationAttributeValue, "The next page link ATOM metadata must have the rel set to 'next'.");
                    string nextPageLinkLength = nextPageLink.Length.HasValue ? nextPageLink.Length.Value.ToString() : null;
                    feed.AtomNextPageLink(nextPageLink.Href == null ? null : nextPageLink.Href.OriginalString, nextPageLink.MediaType, nextPageLink.HrefLang, nextPageLink.Title, nextPageLinkLength);
                }

                if (feedMetadata.SourceId != null)
                {
                    // This should only occur when the metadata comes from the source element of an entry
                    // and we are annotating a temporary feed instance
                    feed.AtomId(UriUtils.UriToString(feedMetadata.SourceId));
                }

                if (feedMetadata.Subtitle != null)
                {
                    feed.AtomSubtitle(feedMetadata.Subtitle.Text, ToString(feedMetadata.Subtitle.Kind));
                }

                if (feedMetadata.Title != null)
                {
                    feed.AtomTitle(feedMetadata.Title.Text, ToString(feedMetadata.Title.Kind));
                }

                if (feedMetadata.Updated.HasValue)
                {
                    feed.AtomUpdated(ToString(feedMetadata.Updated));
                }
            }
Exemple #28
0
        private void WriteFeedElements(IExpandedResult expanded, IEnumerator elements, ResourceType expectedType, string title, Uri relativeUri, Uri absoluteUri, bool hasMoved, bool topLevel)
        {
            ODataFeed feed = new ODataFeed {
                Id = absoluteUri.AbsoluteUri
            };
            AtomFeedMetadata annotation = new AtomFeedMetadata();

            feed.SetAnnotation <AtomFeedMetadata>(annotation);
            AtomTextConstruct construct = new AtomTextConstruct {
                Text = title
            };

            annotation.Title = construct;
            AtomLinkMetadata metadata2 = new AtomLinkMetadata {
                Href  = relativeUri,
                Title = title
            };

            annotation.SelfLink = metadata2;
            bool flag = false;

            if (topLevel && (base.RequestDescription.CountOption == RequestQueryCountOption.Inline))
            {
                flag = this.contentFormat == ODataFormat.VerboseJson;
                if (!flag)
                {
                    feed.Count = new long?(base.RequestDescription.CountValue);
                }
            }
            this.odataWriter.WriteStart(feed);
            try
            {
                object          lastObject = null;
                IExpandedResult skipTokenExpandedResult = null;
                while (hasMoved)
                {
                    object          current   = elements.Current;
                    IExpandedResult skipToken = base.GetSkipToken(expanded);
                    if (current != null)
                    {
                        IExpandedResult result3 = current as IExpandedResult;
                        if (result3 != null)
                        {
                            expanded  = result3;
                            current   = Serializer.GetExpandedElement(expanded);
                            skipToken = base.GetSkipToken(expanded);
                        }
                        this.WriteEntry(expanded, current, true, expectedType);
                    }
                    hasMoved   = elements.MoveNext();
                    lastObject = current;
                    skipTokenExpandedResult = skipToken;
                }
                if (flag)
                {
                    feed.Count = new long?(base.RequestDescription.CountValue);
                }
                if (base.NeedNextPageLink(elements))
                {
                    feed.NextPageLink = base.GetNextLinkUri(lastObject, skipTokenExpandedResult, absoluteUri);
                }
            }
            finally
            {
                if (!topLevel)
                {
                    WebUtil.Dispose(elements);
                }
            }
            this.odataWriter.WriteEnd();
        }
Exemple #29
0
 /// <summary>
 /// Visits an ATOM link metadata.
 /// </summary>
 /// <param name="atomLinkMetadata">The link metadata to visit.</param>
 protected override void VisitAtomLinkMetadata(AtomLinkMetadata atomLinkMetadata)
 {
     this.ValidateUri(atomLinkMetadata.Href);
     base.VisitAtomLinkMetadata(atomLinkMetadata);
 }
        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);
            });
        }