コード例 #1
0
        private void ApplyNavigationProperty(ODataNavigationLink navigationLink, ResourceSetWrapper entityResourceSet, ResourceType entityResourceType, ResourceProperty navigationProperty, object entityResource)
        {
            ResourceSetWrapper targetResourceSet = null;

            targetResourceSet = this.GetNavigationPropertyTargetResourceSet(entityResourceSet, entityResourceType, navigationProperty);
            foreach (ODataItem item in navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>())
            {
                ODataEntityReferenceLink entityReferenceLink = item as ODataEntityReferenceLink;
                if (entityReferenceLink != null)
                {
                    this.ApplyEntityReferenceLinkInNavigationProperty(navigationProperty, entityResource, entityReferenceLink);
                }
                else
                {
                    ODataFeed feed = item as ODataFeed;
                    if (feed != null)
                    {
                        this.ApplyFeedInNavigationProperty(navigationProperty, targetResourceSet, entityResource, feed);
                    }
                    else
                    {
                        ODataEntry entry = (ODataEntry)item;
                        this.ApplyEntryInNavigationProperty(navigationProperty, targetResourceSet, entityResource, entry);
                    }
                }
            }
        }
コード例 #2
0
        private void WriteNavigationLink(ODataWriter writer, Lazy <ODataReader> lazyReader, ODataNavigationLink link)
        {
            this.WriteStart(writer, link);
            var expanded = link.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>();

            if (expanded != null)
            {
                var feed = expanded.ExpandedItem as ODataFeed;
                if (feed != null)
                {
                    this.WriteFeed(writer, lazyReader, feed);
                }
                else
                {
                    ODataEntry entry = expanded.ExpandedItem as ODataEntry;
                    if (entry != null || expanded.ExpandedItem == null)
                    {
                        this.WriteEntry(writer, lazyReader, entry);
                    }
                    else
                    {
                        ExceptionUtilities.Assert(expanded.ExpandedItem is ODataEntityReferenceLink, "Content of a nav. link can only be a feed, entry or entity reference link.");
                        writer.WriteEntityReferenceLink((ODataEntityReferenceLink)expanded.ExpandedItem);
                    }
                }
            }

            this.WriteEnd(writer, ODataReaderState.NavigationLinkEnd);
            this.Read(lazyReader);
        }
コード例 #3
0
        private void ApplyNavigationProperty(ODataNavigationLink navigationLink, IEdmNavigationProperty navigationProperty, object entityResource, ODataDeserializerContext readContext)
        {
            ODataNavigationLinkAnnotation navigationLinkAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();

            Contract.Assert(navigationLinkAnnotation != null, "navigationLinkAnnotation != null");
            Contract.Assert(navigationLink.IsCollection.HasValue, "We should know the cardinality of the navigation link by now.");

            foreach (ODataItem childItem in navigationLinkAnnotation)
            {
                ODataEntityReferenceLink entityReferenceLink = childItem as ODataEntityReferenceLink;
                if (entityReferenceLink != null)
                {
                    // ignore links.
                    continue;
                }

                ODataFeed feed = childItem as ODataFeed;
                if (feed != null)
                {
                    ApplyFeedInNavigationProperty(navigationProperty, entityResource, feed, readContext);
                    continue;
                }

                // It must be entry by now.
                ODataEntry entry = (ODataEntry)childItem;
                if (entry != null)
                {
                    ApplyEntryInNavigationProperty(navigationProperty, entityResource, entry, readContext);
                }
            }
        }
        /// <summary>
        /// Writes the navigation link's start element and atom metadata.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        /// <param name="navigationLinkUrlOverride">Url to use for the navigation link. If this is specified the Url property on the <paramref name="navigationLink"/>
        /// will be ignored. If this parameter is null, the Url from the navigation link is used.</param>
        internal void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(!string.IsNullOrEmpty(navigationLink.Name), "The navigation link name was not verified yet.");
            Debug.Assert(navigationLink.Url != null, "The navigation link Url was not verified yet.");
            Debug.Assert(navigationLink.IsCollection.HasValue, "navigationLink.IsCollection.HasValue");

            if (navigationLink.AssociationLinkUrl != null)
            {
                // TODO:Association Link - Add back support for customizing association link element in Atom
                this.WriteAssociationLink(navigationLink.Name, navigationLink.AssociationLinkUrl, null);
            }

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

            string linkRelation = AtomUtils.ComputeODataNavigationLinkRelation(navigationLink);
            string linkType     = AtomUtils.ComputeODataNavigationLinkType(navigationLink);
            string linkTitle    = navigationLink.Name;

            Uri navigationLinkUrl           = navigationLinkUrlOverride ?? navigationLink.Url;
            AtomLinkMetadata linkMetadata   = navigationLink.GetAnnotation <AtomLinkMetadata>();
            AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(linkMetadata, linkRelation, navigationLinkUrl, linkTitle, linkType);

            this.atomEntryMetadataSerializer.WriteAtomLinkAttributes(mergedMetadata, null /* etag */);
        }
コード例 #5
0
        /// <summary>
        /// Creates the materializer link with a feed.
        /// </summary>
        /// <param name="link">The link.</param>
        /// <param name="feed">The feed.</param>
        /// <returns>The materializer link.</returns>
        public static MaterializerNavigationLink CreateLink(ODataNavigationLink link, ODataFeed feed)
        {
            Debug.Assert(link.GetAnnotation <MaterializerNavigationLink>() == null, "there should be no MaterializerNavigationLink annotation on the feed link yet");
            MaterializerNavigationLink materializedNavigationLink = new MaterializerNavigationLink(link, feed);

            link.SetAnnotation <MaterializerNavigationLink>(materializedNavigationLink);
            return(materializedNavigationLink);
        }
コード例 #6
0
        /// <summary>
        /// Applies a navigation link as a navigation property.
        /// </summary>
        /// <param name="navigationLink">The navigation link read from the payload to apply.</param>
        /// <param name="entityResourceSet">The resource set into which the entity belongs to.</param>
        /// <param name="entityResourceType">The type of the entity to apply the properties to.</param>
        /// <param name="navigationProperty">The navigation property which coresponds with the navigation link.</param>
        /// <param name="entityResource">The entity resource to apply the properties to.</param>
        private void ApplyNavigationProperty(
            ODataNavigationLink navigationLink,
            ResourceSetWrapper entityResourceSet,
            ResourceType entityResourceType,
            ResourceProperty navigationProperty,
            object entityResource)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(entityResourceSet != null, "entityResourceSet != null");
            Debug.Assert(entityResourceType != null, "entityResourceType != null");
            Debug.Assert(entityResourceType.ResourceTypeKind == ResourceTypeKind.EntityType, "Only entity types can be specified for entities.");
            Debug.Assert(navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType, "navigationProperty != null && navigationProperty.TypeKind == ResourceTypeKind.EntityType");
            Debug.Assert(navigationLink.Name == navigationProperty.Name, "The navigationProperty must have the same name as the navigationLink to apply.");
            Debug.Assert(entityResource != null, "entityResource != null");

            ResourceSetWrapper targetResourceSet = null;

            // Get the target resource set for the navigation property, this also causes validation of the resource set and thus migth fail.
            // WCF DS Used to do this in ATOM only if the link was expanded, which was a security issue we decided to fix, so now we do it always.
            targetResourceSet = this.GetNavigationPropertyTargetResourceSet(entityResourceSet, entityResourceType, navigationProperty);

            ODataNavigationLinkAnnotation navigationLinkAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();

            Debug.Assert(navigationLinkAnnotation != null, "navigationLinkAnnotation != null");
            Debug.Assert(navigationLinkAnnotation.Count > 0, "Each navigation link must have at least one child in request.");
            Debug.Assert(navigationLink.IsCollection.HasValue, "We should know the cardinality of the navigation link by now.");

            // We have to allow IsCollection=false for ResourceSetReference properties as well.
            Debug.Assert(
                navigationLink.IsCollection == true || (navigationLinkAnnotation.Count == 1),
                "If the navigation link is a singleton, then there must be exactly one child in it and the property must be a singleton as well.");
            Debug.Assert(
                navigationLink.IsCollection == false || (navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference),
                "If the navigation link is a collection, then the property must be a collection as well.");

            // Just loop through the navigation link content
            // Note that if the navigation link is a singleton it must have just one item in it, so it's OK to loop anyway.
            foreach (ODataItem childItem in navigationLinkAnnotation)
            {
                ODataEntityReferenceLink entityReferenceLink = childItem as ODataEntityReferenceLink;
                if (entityReferenceLink != null)
                {
                    this.ApplyEntityReferenceLinkInNavigationProperty(navigationProperty, entityResource, entityReferenceLink);
                    continue;
                }

                ODataFeed feed = childItem as ODataFeed;
                if (feed != null)
                {
                    this.ApplyFeedInNavigationProperty(navigationProperty, targetResourceSet, entityResource, feed);
                    continue;
                }

                // It must be entry by now.
                ODataEntry entry = (ODataEntry)childItem;
                this.ApplyEntryInNavigationProperty(navigationProperty, targetResourceSet, entityResource, entry);
            }
        }
コード例 #7
0
        public static AtomLinkMetadata Atom(this ODataNavigationLink navigationLink)
        {
            ExceptionUtils.CheckArgumentNotNull <ODataNavigationLink>(navigationLink, "navigationLink");
            AtomLinkMetadata annotation = navigationLink.GetAnnotation <AtomLinkMetadata>();

            if (annotation == null)
            {
                annotation = new AtomLinkMetadata();
                navigationLink.SetAnnotation <AtomLinkMetadata>(annotation);
            }
            return(annotation);
        }
コード例 #8
0
        public static AtomLinkMetadata Atom(this ODataNavigationLink navigationLink)
        {
            ExceptionUtils.CheckArgumentNotNull(navigationLink, "navigationLink");

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

            if (linkMetadata == null)
            {
                linkMetadata = new AtomLinkMetadata();
                navigationLink.SetAnnotation(linkMetadata);
            }

            return(linkMetadata);
        }
コード例 #9
0
        /// <summary>
        /// Gets the expanded content of a navigation link.
        /// </summary>
        /// <param name="navigationLink">The <see cref="ODataNavigationLink"/> to get the navigation content for.</param>
        /// <param name="expandedContent">The expanded content (if the method returns null), which can be either
        /// null (null expanded entry), or <see cref="ODataEntry"/> or <see cref="ODataFeed"/>.</param>
        /// <returns>true if the <paramref name="navigationLink"/> is expanded, or false otherwise.</returns>
        public static bool TryGetExpandedContent(this ODataNavigationLink navigationLink, out object expandedContent)
        {
            ExceptionUtilities.CheckArgumentNotNull(navigationLink, "navigationLink");
            var expandedItemAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>();

            if (expandedItemAnnotation != null)
            {
                expandedContent = expandedItemAnnotation.ExpandedItem;
                return(true);
            }
            else
            {
                expandedContent = null;
                return(false);
            }
        }
コード例 #10
0
            /// <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);
            }
コード例 #11
0
        /// <summary>
        /// Writes the navigation link's start element and atom metadata.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        /// <param name="navigationLinkUrlOverride">Url to use for the navigation link. If this is specified the Url property on the <paramref name="navigationLink"/>
        /// will be ignored. If this parameter is null, the Url from the navigation link is used.</param>
        internal void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(!string.IsNullOrEmpty(navigationLink.Name), "The navigation link name was not verified yet.");
            Debug.Assert(navigationLink.Url != null, "The navigation link Url was not verified yet.");
            Debug.Assert(navigationLink.IsCollection.HasValue, "navigationLink.IsCollection.HasValue");

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

            string linkRelation = AtomUtils.ComputeODataNavigationLinkRelation(navigationLink);
            string linkType = AtomUtils.ComputeODataNavigationLinkType(navigationLink);
            string linkTitle = navigationLink.Name;

            Uri navigationLinkUrl = navigationLinkUrlOverride ?? navigationLink.Url;
            AtomLinkMetadata linkMetadata = navigationLink.GetAnnotation<AtomLinkMetadata>();
            AtomLinkMetadata mergedMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(linkMetadata, linkRelation, navigationLinkUrl, linkTitle, linkType);
            this.atomEntryMetadataSerializer.WriteAtomLinkAttributes(mergedMetadata, null /* etag */);
        }
コード例 #12
0
        internal static ODataItem ReadEntryOrFeed(ODataReader odataReader, ODataDeserializerContext readContext)
        {
            ODataItem         topLevelItem = null;
            Stack <ODataItem> itemsStack   = new Stack <ODataItem>();

            while (odataReader.Read())
            {
                switch (odataReader.State)
                {
                case ODataReaderState.EntryStart:
                    ODataEntry           entry           = (ODataEntry)odataReader.Item;
                    ODataEntryAnnotation entryAnnotation = null;
                    if (entry != null)
                    {
                        entryAnnotation = new ODataEntryAnnotation();
                        entry.SetAnnotation(entryAnnotation);
                    }

                    if (itemsStack.Count == 0)
                    {
                        Contract.Assert(entry != null, "The top-level entry can never be null.");
                        topLevelItem = entry;
                    }
                    else
                    {
                        ODataItem parentItem = itemsStack.Peek();
                        ODataFeed parentFeed = parentItem as ODataFeed;
                        if (parentFeed != null)
                        {
                            ODataFeedAnnotation parentFeedAnnotation = parentFeed.GetAnnotation <ODataFeedAnnotation>();
                            Contract.Assert(parentFeedAnnotation != null, "Every feed we added to the stack should have the feed annotation on it.");
                            parentFeedAnnotation.Add(entry);
                        }
                        else
                        {
                            ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)parentItem;
                            ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                            Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                            Contract.Assert(parentNavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child.");
                            Contract.Assert(parentNavigationLinkAnnotation.Count == 0, "Each navigation property can contain only one entry as its direct child.");
                            parentNavigationLinkAnnotation.Add(entry);
                        }
                    }
                    itemsStack.Push(entry);
                    RecurseEnter(readContext);
                    break;

                case ODataReaderState.EntryEnd:
                    Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The entry which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    RecurseLeave(readContext);
                    break;

                case ODataReaderState.NavigationLinkStart:
                    ODataNavigationLink navigationLink = (ODataNavigationLink)odataReader.Item;
                    Contract.Assert(navigationLink != null, "Navigation link should never be null.");

                    navigationLink.SetAnnotation(new ODataNavigationLinkAnnotation());
                    Contract.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item.");
                    {
                        ODataEntry           parentEntry           = (ODataEntry)itemsStack.Peek();
                        ODataEntryAnnotation parentEntryAnnotation = parentEntry.GetAnnotation <ODataEntryAnnotation>();
                        Contract.Assert(parentEntryAnnotation != null, "Every entry we added to the stack should have the entry annotation on it.");
                        parentEntryAnnotation.Add(navigationLink);
                    }

                    itemsStack.Push(navigationLink);
                    RecurseEnter(readContext);
                    break;

                case ODataReaderState.NavigationLinkEnd:
                    Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The navigation link which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    RecurseLeave(readContext);
                    break;

                case ODataReaderState.FeedStart:
                    ODataFeed feed = (ODataFeed)odataReader.Item;
                    Contract.Assert(feed != null, "Feed should never be null.");

                    feed.SetAnnotation(new ODataFeedAnnotation());
                    if (itemsStack.Count > 0)
                    {
                        ODataNavigationLink parentNavigationLink = (ODataNavigationLink)itemsStack.Peek();
                        Contract.Assert(parentNavigationLink != null, "this has to be an inner feed. inner feeds always have a navigation link.");
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        Contract.Assert(parentNavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child.");
                        parentNavigationLinkAnnotation.Add(feed);
                    }
                    else
                    {
                        topLevelItem = feed;
                    }

                    itemsStack.Push(feed);
                    RecurseEnter(readContext);
                    break;

                case ODataReaderState.FeedEnd:
                    Contract.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The feed which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    RecurseLeave(readContext);
                    break;

                case ODataReaderState.EntityReferenceLink:
                    ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)odataReader.Item;
                    Contract.Assert(entityReferenceLink != null, "Entity reference link should never be null.");

                    Contract.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item.");
                    {
                        ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)itemsStack.Peek();
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Contract.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        parentNavigationLinkAnnotation.Add(entityReferenceLink);
                    }

                    break;

                default:
                    Contract.Assert(false, "We should never get here, it means the ODataReader reported a wrong state.");
                    break;
                }
            }

            Contract.Assert(odataReader.State == ODataReaderState.Completed, "We should have consumed all of the input by now.");
            Contract.Assert(topLevelItem != null, "A top level entry or feed should have been read by now.");
            return(topLevelItem);
        }
コード例 #13
0
        internal void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride)
        {
            base.XmlWriter.WriteStartElement("", "link", "http://www.w3.org/2005/Atom");
            string           relation     = AtomUtils.ComputeODataNavigationLinkRelation(navigationLink);
            string           mediaType    = AtomUtils.ComputeODataNavigationLinkType(navigationLink);
            string           name         = navigationLink.Name;
            Uri              href         = navigationLinkUrlOverride ?? navigationLink.Url;
            AtomLinkMetadata linkMetadata = ODataAtomWriterMetadataUtils.MergeLinkMetadata(navigationLink.GetAnnotation <AtomLinkMetadata>(), relation, href, name, mediaType);

            this.atomEntryMetadataSerializer.WriteAtomLinkAttributes(linkMetadata, null);
        }
コード例 #14
0
 public static MaterializerNavigationLink GetLink(ODataNavigationLink link)
 {
     return(link.GetAnnotation <MaterializerNavigationLink>());
 }
コード例 #15
0
        private void Read(Lazy <ODataReader> lazyReader)
        {
            foreach (var state in this.expectedStates)
            {
                lazyReader.Value.Read();
                ExceptionUtilities.Assert(lazyReader.Value.State == state, "Expected %1, Found %2", state, lazyReader.Value.State);
                switch (state)
                {
                case ODataReaderState.FeedStart:
                    if (readItems.Count > 0)
                    {
                        ODataNavigationLink navLink = (ODataNavigationLink)readItems.Peek();
                        var annotation = navLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>();
                        if (annotation == null)
                        {
                            annotation = new ODataNavigationLinkExpandedItemObjectModelAnnotation();
                            navLink.SetAnnotation(annotation);
                        }

                        annotation.ExpandedItem = lazyReader.Value.Item;
                    }

                    readItems.Push(lazyReader.Value.Item);
                    break;

                case ODataReaderState.EntryStart:
                    var currentEntry = (ODataEntry)lazyReader.Value.Item;
                    if (readItems.Count > 0)
                    {
                        ODataFeed feed = readItems.Peek() as ODataFeed;
                        if (feed != null)
                        {
                            var annotation = feed.GetAnnotation <ODataFeedEntriesObjectModelAnnotation>();
                            if (annotation == null)
                            {
                                annotation = new ODataFeedEntriesObjectModelAnnotation();
                                feed.SetAnnotation(annotation);
                            }
                            annotation.Add((ODataEntry)lazyReader.Value.Item);
                        }
                        else
                        {
                            ODataNavigationLink navLink = (ODataNavigationLink)readItems.Peek();
                            var annotation = navLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>();
                            if (annotation == null)
                            {
                                annotation = new ODataNavigationLinkExpandedItemObjectModelAnnotation();
                                navLink.SetAnnotation(annotation);
                            }

                            annotation.ExpandedItem = currentEntry;
                        }
                    }

                    readItems.Push(currentEntry);
                    break;

                case ODataReaderState.NavigationLinkStart:
                    ODataEntry entry = (ODataEntry)readItems.Peek();
                    var        navLinksAnnotation = entry.GetAnnotation <ODataEntryNavigationLinksObjectModelAnnotation>();
                    if (navLinksAnnotation == null)
                    {
                        navLinksAnnotation = new ODataEntryNavigationLinksObjectModelAnnotation();
                        entry.SetAnnotation(navLinksAnnotation);
                    }

                    navLinksAnnotation.Add((ODataNavigationLink)lazyReader.Value.Item, entry.Properties.Count() + navLinksAnnotation.Count);
                    readItems.Push(lazyReader.Value.Item);
                    break;

                case ODataReaderState.EntryEnd:
                case ODataReaderState.FeedEnd:
                case ODataReaderState.NavigationLinkEnd:
                    if (readItems.Count() > 1)
                    {
                        readItems.Pop();
                    }
                    break;
                }
            }

            this.expectedStates.Clear();
        }
コード例 #16
0
        /// <summary>
        /// Reads an entry from the <paramref name="odataReader"/> and all it's children including expanded entries and feeds.
        /// </summary>
        /// <param name="odataReader">The ODataReader to read from.</param>
        /// <param name="topLevelSegmentInfo">The segment info for the top-level entry to read.</param>
        /// <returns>The <see cref="ODataEntry"/> with annotations which store the navigation links and their expanded values.</returns>
        private ODataEntry ReadEntry(ODataReader odataReader, SegmentInfo topLevelSegmentInfo)
        {
            Debug.Assert(odataReader != null, "odataReader != null");
            Debug.Assert(odataReader.State == ODataReaderState.Start, "The ODataReader must not have been used yet.");
            Debug.Assert(topLevelSegmentInfo != null, "topLevelSegmentInfo != null");

            ODataEntry        topLevelEntry = null;
            Stack <ODataItem> itemsStack    = new Stack <ODataItem>();

            while (odataReader.Read())
            {
                // Don't let the item stack grow larger than we can process later. Also lets us to fail and report the recursion depth limit error before ODL does.
                if (itemsStack.Count >= RecursionLimit)
                {
                    throw DataServiceException.CreateDeepRecursion(RecursionLimit);
                }

                switch (odataReader.State)
                {
                case ODataReaderState.EntryStart:
                    ODataEntry           entry           = (ODataEntry)odataReader.Item;
                    ODataEntryAnnotation entryAnnotation = null;
                    if (entry != null)
                    {
                        entryAnnotation = new ODataEntryAnnotation();
                        entry.SetAnnotation(entryAnnotation);
                    }

                    if (itemsStack.Count == 0)
                    {
                        Debug.Assert(entry != null, "The top-level entry can never be null.");
                        topLevelEntry = entry;

                        // For top-level entry, create the entry resource here.
                        // This is needed since the creation of the resource may fail (especially if this is an update in which case
                        // we evaluate the URL query, which may return no results and thus we would fail with 404)
                        // and we need to report that failure rather then potential other failures caused by the properties in the entry in question.
                        this.CreateEntityResource(topLevelSegmentInfo, entry, entryAnnotation, /*topLevel*/ true);
                    }
                    else
                    {
                        ODataItem parentItem = itemsStack.Peek();
                        ODataFeed parentFeed = parentItem as ODataFeed;
                        if (parentFeed != null)
                        {
                            ODataFeedAnnotation parentFeedAnnotation = parentFeed.GetAnnotation <ODataFeedAnnotation>();
                            Debug.Assert(parentFeedAnnotation != null, "Every feed we added to the stack should have the feed annotation on it.");
                            parentFeedAnnotation.Add(entry);
                        }
                        else
                        {
                            ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)parentItem;
                            ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                            Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                            Debug.Assert(parentNavigationLink.IsCollection == false, "Only singleton navigation properties can contain entry as their child.");
                            Debug.Assert(parentNavigationLinkAnnotation.Count == 0, "Each navigation property can contain only one entry as its direct child.");
                            parentNavigationLinkAnnotation.Add(entry);
                        }
                    }

                    itemsStack.Push(entry);
                    break;

                case ODataReaderState.EntryEnd:
                    Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The entry which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    break;

                case ODataReaderState.NavigationLinkStart:
                    ODataNavigationLink navigationLink = (ODataNavigationLink)odataReader.Item;
                    Debug.Assert(navigationLink != null, "Navigation link should never be null.");

                    navigationLink.SetAnnotation(new ODataNavigationLinkAnnotation());
                    Debug.Assert(itemsStack.Count > 0, "Navigation link can't appear as top-level item.");
                    {
                        ODataEntry           parentEntry           = (ODataEntry)itemsStack.Peek();
                        ODataEntryAnnotation parentEntryAnnotation = parentEntry.GetAnnotation <ODataEntryAnnotation>();
                        Debug.Assert(parentEntryAnnotation != null, "Every entry we added to the stack should have the navigation link annotation on it.");
                        parentEntryAnnotation.Add(navigationLink);
                    }

                    itemsStack.Push(navigationLink);
                    break;

                case ODataReaderState.NavigationLinkEnd:
                    Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The navigation link which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    break;

                case ODataReaderState.FeedStart:
                    ODataFeed feed = (ODataFeed)odataReader.Item;
                    Debug.Assert(feed != null, "Feed should never be null.");

                    feed.SetAnnotation(new ODataFeedAnnotation());
                    Debug.Assert(itemsStack.Count > 0, "Since we always start reading entry, we should never get a feed as the top-level item.");
                    {
                        ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)itemsStack.Peek();
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        Debug.Assert(parentNavigationLink.IsCollection == true, "Only collection navigation properties can contain feed as their child.");
                        parentNavigationLinkAnnotation.Add(feed);
                    }

                    itemsStack.Push(feed);
                    break;

                case ODataReaderState.FeedEnd:
                    Debug.Assert(itemsStack.Count > 0 && itemsStack.Peek() == odataReader.Item, "The feed which is ending should be on the top of the items stack.");
                    itemsStack.Pop();
                    break;

                case ODataReaderState.EntityReferenceLink:
                    ODataEntityReferenceLink entityReferenceLink = (ODataEntityReferenceLink)odataReader.Item;
                    Debug.Assert(entityReferenceLink != null, "Entity reference link should never be null.");

                    Debug.Assert(itemsStack.Count > 0, "Entity reference link should never be reported as top-level item.");
                    {
                        ODataNavigationLink           parentNavigationLink           = (ODataNavigationLink)itemsStack.Peek();
                        ODataNavigationLinkAnnotation parentNavigationLinkAnnotation = parentNavigationLink.GetAnnotation <ODataNavigationLinkAnnotation>();
                        Debug.Assert(parentNavigationLinkAnnotation != null, "Every navigation link we added to the stack should have the navigation link annotation on it.");

                        parentNavigationLinkAnnotation.Add(entityReferenceLink);
                    }

                    break;

                default:
                    Debug.Assert(false, "We should never get here, it means the ODataReader reported a wrong state.");
                    break;
                }
            }

            Debug.Assert(odataReader.State == ODataReaderState.Completed, "We should have consumed all of the input by now.");
            Debug.Assert(topLevelEntry != null, "A top level entry should have been read by now.");
            return(topLevelEntry);
        }
コード例 #17
0
        private ODataEntry ReadEntry(ODataReader odataReader, System.Data.Services.SegmentInfo topLevelSegmentInfo)
        {
            ODataEntry        entry = null;
            Stack <ODataItem> stack = new Stack <ODataItem>();

            while (odataReader.Read())
            {
                if (stack.Count >= 100)
                {
                    throw DataServiceException.CreateDeepRecursion(100);
                }
                switch (odataReader.State)
                {
                case ODataReaderState.FeedStart:
                {
                    ODataFeed feed2 = (ODataFeed)odataReader.Item;
                    feed2.SetAnnotation <ODataFeedAnnotation>(new ODataFeedAnnotation());
                    ODataNavigationLink link3 = (ODataNavigationLink)stack.Peek();
                    link3.GetAnnotation <ODataNavigationLinkAnnotation>().Add(feed2);
                    stack.Push(feed2);
                    break;
                }

                case ODataReaderState.FeedEnd:
                    stack.Pop();
                    break;

                case ODataReaderState.EntryStart:
                {
                    ODataEntry           entry2     = (ODataEntry)odataReader.Item;
                    ODataEntryAnnotation annotation = null;
                    if (entry2 != null)
                    {
                        annotation = new ODataEntryAnnotation();
                        entry2.SetAnnotation <ODataEntryAnnotation>(annotation);
                    }
                    if (stack.Count == 0)
                    {
                        entry = entry2;
                        this.CreateEntityResource(topLevelSegmentInfo, entry2, annotation, true);
                    }
                    else
                    {
                        ODataItem item = stack.Peek();
                        ODataFeed feed = item as ODataFeed;
                        if (feed != null)
                        {
                            feed.GetAnnotation <ODataFeedAnnotation>().Add(entry2);
                        }
                        else
                        {
                            ODataNavigationLink link = (ODataNavigationLink)item;
                            link.GetAnnotation <ODataNavigationLinkAnnotation>().Add(entry2);
                        }
                    }
                    stack.Push(entry2);
                    break;
                }

                case ODataReaderState.EntryEnd:
                    stack.Pop();
                    break;

                case ODataReaderState.NavigationLinkStart:
                {
                    ODataNavigationLink link2 = (ODataNavigationLink)odataReader.Item;
                    link2.SetAnnotation <ODataNavigationLinkAnnotation>(new ODataNavigationLinkAnnotation());
                    ODataEntry entry3 = (ODataEntry)stack.Peek();
                    entry3.GetAnnotation <ODataEntryAnnotation>().Add(link2);
                    stack.Push(link2);
                    break;
                }

                case ODataReaderState.NavigationLinkEnd:
                    stack.Pop();
                    break;

                case ODataReaderState.EntityReferenceLink:
                {
                    ODataEntityReferenceLink link4 = (ODataEntityReferenceLink)odataReader.Item;
                    ODataNavigationLink      link5 = (ODataNavigationLink)stack.Peek();
                    link5.GetAnnotation <ODataNavigationLinkAnnotation>().Add(link4);
                    break;
                }
                }
            }
            return(entry);
        }
コード例 #18
0
            /// <summary>
            /// Visits a navigation link item.
            /// </summary>
            /// <param name="navigationLink">The navigation link to visit.</param>
            protected override ODataPayloadElement VisitNavigationLink(ODataNavigationLink navigationLink)
            {
                ExceptionUtilities.CheckArgumentNotNull(navigationLink, "navigationLink");

                ODataPayloadElement navigationPropertyContent = null;

                // check whether there is an entry or feed associated with the link
                var expandedItemAnnotation = navigationLink.GetAnnotation <ODataNavigationLinkExpandedItemObjectModelAnnotation>();

                if (expandedItemAnnotation != null)
                {
                    string navigationLinkUrlString = !this.payloadContainsIdentityMetadata || navigationLink.Url == null ? null : navigationLink.Url.OriginalString;

                    if (expandedItemAnnotation.ExpandedItem is ODataEntry)
                    {
                        navigationPropertyContent = new ExpandedLink(this.Visit((ODataEntry)expandedItemAnnotation.ExpandedItem))
                        {
                            UriString = navigationLinkUrlString
                        };
                    }
                    else if (expandedItemAnnotation.ExpandedItem is ODataFeed)
                    {
                        navigationPropertyContent = new ExpandedLink(this.Visit((ODataFeed)expandedItemAnnotation.ExpandedItem))
                        {
                            UriString = navigationLinkUrlString
                        };
                    }
                    else if (expandedItemAnnotation.ExpandedItem is ODataEntityReferenceLink)
                    {
                        ExceptionUtilities.Assert(!this.response, "Entity reference links in navigation links can only appear in requests.");
                        navigationPropertyContent = this.VisitEntityReferenceLink((ODataEntityReferenceLink)expandedItemAnnotation.ExpandedItem);
                    }
                    else if (expandedItemAnnotation.ExpandedItem is List <ODataItem> )
                    {
                        ExceptionUtilities.Assert(!this.response, "Navigation links with multiple items in content can only appear in requests.");
                        LinkCollection linkCollection = new LinkCollection();
                        foreach (ODataItem item in (List <ODataItem>)expandedItemAnnotation.ExpandedItem)
                        {
                            if (item is ODataFeed)
                            {
                                linkCollection.Add(new ExpandedLink(this.Visit((ODataFeed)item)));
                            }
                            else
                            {
                                ExceptionUtilities.Assert(item is ODataEntityReferenceLink, "Only feed and entity reference links can appear in navigation link content with multiple items.");
                                linkCollection.Add(this.VisitEntityReferenceLink((ODataEntityReferenceLink)item));
                            }
                        }

                        navigationPropertyContent = linkCollection;
                    }
                    else
                    {
                        ExceptionUtilities.Assert(expandedItemAnnotation.ExpandedItem == null, "Only expanded entry, feed or null is allowed.");
                        navigationPropertyContent = new ExpandedLink(new EntityInstance(null, true))
                        {
                            UriString = navigationLinkUrlString
                        };
                    }
                }
                else
                {
                    ExceptionUtilities.Assert(this.response, "Deferred links are only valid in responses.");

                    // this is a deferred link
                    DeferredLink deferredLink = new DeferredLink()
                    {
                        UriString = !this.payloadContainsIdentityMetadata || navigationLink.Url == null ? null : navigationLink.Url.OriginalString,
                    };
                    navigationPropertyContent = deferredLink;
                }

                DeferredLink associationLink = null;

                if (this.payloadContainsIdentityMetadata && navigationLink.AssociationLinkUrl != null)
                {
                    associationLink = new DeferredLink()
                    {
                        UriString = navigationLink.AssociationLinkUrl.OriginalString
                    };
                }

                return(new NavigationPropertyInstance(navigationLink.Name, navigationPropertyContent, associationLink));
            }
コード例 #19
0
 /// <summary>
 /// Visits a navigation link item.
 /// </summary>
 /// <param name="navigationLink">The navigation link to visit.</param>
 protected override void VisitNavigationLink(ODataNavigationLink navigationLink)
 {
     this.VisitAtomMetadata(navigationLink.GetAnnotation <AtomLinkMetadata>());
     base.VisitNavigationLink(navigationLink);
 }