Exemplo n.º 1
0
        /// <summary>
        /// Creates the value for the navigation property's link relation attribute.
        /// </summary>
        /// <param name="navigationLink">The link representing the navigation property for which the relation value is created.</param>
        /// <returns>The relation attribute value for the navigation property's link relation.</returns>
        internal static string ComputeODataNavigationLinkRelation(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.Name != null, "navigationLink.Name != null");

            return string.Join("", new string[] { AtomConstants.ODataNavigationPropertiesRelatedLinkRelationPrefix, navigationLink.Name });
        }
        public ODataNavigationLinkTests()
        {
            this.navigationLink = new ODataNavigationLink();

            var entry = new ODataEntry
            {
                TypeName = "ns.DerivedType",
                Properties = new[]
                {
                    new ODataProperty{Name = "Id", Value = 1, SerializationInfo = new ODataPropertySerializationInfo{PropertyKind = ODataPropertyKind.Key}},
                    new ODataProperty{Name = "Name", Value = "Bob", SerializationInfo = new ODataPropertySerializationInfo{PropertyKind = ODataPropertyKind.ETag}}
                }
            };

            var serializationInfo = new ODataFeedAndEntrySerializationInfo { NavigationSourceName = "Set", NavigationSourceEntityTypeName = "ns.BaseType", ExpectedTypeName = "ns.BaseType" };
            var typeContext = ODataFeedAndEntryTypeContext.Create(serializationInfo, null, null, null, EdmCoreModel.Instance, true);
            var metadataContext = new TestMetadataContext();
            var entryMetadataContext = ODataEntryMetadataContext.Create(entry, typeContext, serializationInfo, null, metadataContext, SelectedPropertiesNode.EntireSubtree);
            var metadataBuilder = new ODataConventionalEntityMetadataBuilder(entryMetadataContext, metadataContext, new ODataConventionalUriBuilder(ServiceUri, UrlConvention.CreateWithExplicitValue(false)));
            this.navigationLinkWithFullBuilder = new ODataNavigationLink { Name = "NavProp" };
            this.navigationLinkWithFullBuilder.MetadataBuilder = metadataBuilder;

            this.navigationLinkWithNoOpBuilder = new ODataNavigationLink { Name = "NavProp" };
            this.navigationLinkWithNoOpBuilder.MetadataBuilder = new NoOpEntityMetadataBuilder(entry);

            this.navigationLinkWithNullBuilder = new ODataNavigationLink { Name = "NavProp" };
            this.navigationLinkWithNullBuilder.MetadataBuilder = ODataEntityMetadataBuilder.Null;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="navigationLink">The navigation link.</param>
        /// <param name="navigationProperty">The navigation property for the link, if it's available.</param>
        internal ODataAtomReaderNavigationLinkDescriptor(ODataNavigationLink navigationLink, IEdmNavigationProperty navigationProperty)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");

            this.navigationLink = navigationLink;
            this.navigationProperty = navigationProperty;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="navigationLink">The navigation link.</param>
        /// <param name="navigationProperty">The navigation property for the link, if it's available.</param>
        internal ODataAtomReaderNavigationLinkDescriptor(ODataNavigationLink navigationLink, IEdmNavigationProperty navigationProperty)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(navigationLink != null, "navigationLink != null");

            this.navigationLink = navigationLink;
            this.navigationProperty = navigationProperty;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Creates the value for the navigation property's type attribute.
        /// </summary>
        /// <param name="navigationLink">The link representing the navigation property for which the type value is created.</param>
        /// <returns>The type attribute value for the navigation property.</returns>
        internal static string ComputeODataNavigationLinkType(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.IsCollection.HasValue, "navigationLink.IsCollection.HasValue");

            // "application/atom+xml;type=entry" or type="application/atom+xml;type=feed"
            return navigationLink.IsCollection.Value ? MimeConstants.MimeApplicationAtomXmlTypeFeed : MimeConstants.MimeApplicationAtomXmlTypeEntry;
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates the value for the navigation property's link relation attribute.
        /// </summary>
        /// <param name="navigationLink">The link representing the navigation property for which the relation value is created.</param>
        /// <returns>The relation attribute value for the navigation property's link relation.</returns>
        internal static string ComputeODataNavigationLinkRelation(ODataNavigationLink navigationLink)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.Name != null, "navigationLink.Name != null");

            return string.Join("/", new string[] { AtomConstants.ODataNamespace, AtomConstants.ODataNavigationPropertiesRelatedSegmentName, navigationLink.Name });
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="navigationLink">The navigation link to report.</param>
        /// <param name="navigationProperty">The navigation property for which the link will be reported.</param>
        /// <param name="isExpanded">true if the navigation link is expanded.</param>
        private ODataJsonLightReaderNavigationLinkInfo(ODataNavigationLink navigationLink, IEdmNavigationProperty navigationProperty, bool isExpanded)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationProperty == null || navigationProperty.Name == navigationLink.Name, "The name of the navigation link doesn't match the name of the property.");

            this.navigationLink = navigationLink;
            this.navigationProperty = navigationProperty;
            this.isExpanded = isExpanded;
        }
Exemplo n.º 8
0
        private void AddBoundNavigationPropertyAnnotation(ODataItem item, ODataNavigationLink navigationLink, object boundValue)
        {
            var annotation = item.GetAnnotation <BoundNavigationPropertyAnnotation>();

            if (annotation == null)
            {
                annotation = new BoundNavigationPropertyAnnotation {
                    BoundProperties = new List <Tuple <ODataNavigationLink, object> >()
                };
                item.SetAnnotation(annotation);
            }

            annotation.BoundProperties.Add(new Tuple <ODataNavigationLink, object>(navigationLink, boundValue));
        }
Exemplo n.º 9
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);
        }
Exemplo n.º 10
0
        /// <summary>
        /// Start writing a navigation link with content.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void StartNavigationLinkWithContent(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(!string.IsNullOrEmpty(navigationLink.Name), "The navigation link name should have been verified by now.");

            if (this.jsonLightOutputContext.WritingResponse)
            {
                // Write the navigation link metadata first. The rest is written by the content entry or feed.
                this.jsonLightEntryAndFeedSerializer.WriteNavigationLinkMetadata(navigationLink, this.DuplicatePropertyNamesChecker);
            }
            else
            {
                WriterValidationUtils.ValidateNavigationLinkHasCardinality(navigationLink);
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Start writing a navigation link.
        /// </summary>
        /// <param name="navigationLink">Navigation link to write.</param>
        public override void WriteStart(ODataNavigationLink navigationLink)
        {
            if (this.testConfiguration.Synchronous)
            {
                this.writer.WriteStart(navigationLink);
            }
            else
            {
#if WINDOWS_PHONE
                throw new TaupoNotSupportedException("This test is not supported in asynchronous mode in Silverlight or Windows Phone");
#else
                this.writer.WriteStartAsync(navigationLink).Wait();
#endif
            }
        }
Exemplo n.º 12
0
            protected override void  VisitNavigationLink(ODataNavigationLink navigationLink)
            {
                bool?expectedIsCollectionValue;

                if (this.expectedIsCollectionValues != null && this.expectedIsCollectionValues.TryGetValue(navigationLink.Name, out expectedIsCollectionValue))
                {
                    this.assertionHandler.AreEqual(
                        expectedIsCollectionValue,
                        navigationLink.IsCollection,
                        "Value for IsCollection on NavigationLink '{0}' is unexpected",
                        navigationLink.Name);
                }

                base.VisitNavigationLink(navigationLink);
            }
Exemplo n.º 13
0
 protected override void WriteDeferredNavigationLink(ODataNavigationLink navigationLink)
 {
     if (navigationLink.Url == null)
     {
         throw new ODataException(Strings.ODataWriter_NavigationLinkMustSpecifyUrl);
     }
     this.jsonOutputContext.JsonWriter.WriteName(navigationLink.Name);
     this.jsonOutputContext.JsonWriter.StartObjectScope();
     this.jsonOutputContext.JsonWriter.WriteName("__deferred");
     this.jsonOutputContext.JsonWriter.StartObjectScope();
     this.jsonOutputContext.JsonWriter.WriteName("uri");
     this.jsonOutputContext.JsonWriter.WriteValue(this.jsonEntryAndFeedSerializer.UriToAbsoluteUriString(navigationLink.Url));
     this.jsonOutputContext.JsonWriter.EndObjectScope();
     this.jsonOutputContext.JsonWriter.EndObjectScope();
 }
Exemplo n.º 14
0
 protected override void StartNavigationLinkWithContent(ODataNavigationLink navigationLink)
 {
     this.jsonOutputContext.JsonWriter.WriteName(navigationLink.Name);
     if (!this.jsonOutputContext.WritingResponse)
     {
         if (!navigationLink.IsCollection.HasValue)
         {
             throw new ODataException(Strings.ODataWriterCore_LinkMustSpecifyIsCollection);
         }
         if (navigationLink.IsCollection.Value)
         {
             this.jsonOutputContext.JsonWriter.StartArrayScope();
         }
     }
 }
        private IEnumerable <ODataNavigationLink> CreateNavigationLinks(
            IEnumerable <IEdmNavigationProperty> navigationProperties, EntityInstanceContext entityInstanceContext)
        {
            Contract.Assert(navigationProperties != null);
            Contract.Assert(entityInstanceContext != null);

            foreach (IEdmNavigationProperty navProperty in navigationProperties)
            {
                ODataNavigationLink navigationLink = CreateNavigationLink(navProperty, entityInstanceContext);
                if (navigationLink != null)
                {
                    yield return(navigationLink);
                }
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Creates a navigation link info for an expanded feed link.
        /// </summary>
        /// <param name="navigationLink">The navigation link to report.</param>
        /// <param name="navigationProperty">The navigation property for which the link will be reported.</param>
        /// <param name="expandedFeed">The expanded feed for the navigation link to report.</param>
        /// <returns>The navigation link info created.</returns>
        internal static ODataJsonLightReaderNavigationLinkInfo CreateExpandedFeedLinkInfo(
            ODataNavigationLink navigationLink,
            IEdmNavigationProperty navigationProperty,
            ODataFeed expandedFeed)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.IsCollection == true, "Expanded feeds can only be reported for collection navigation links.");
            Debug.Assert(expandedFeed != null, "expandedFeed != null");

            ODataJsonLightReaderNavigationLinkInfo navigationLinkInfo = new ODataJsonLightReaderNavigationLinkInfo(navigationLink, navigationProperty, /*isExpanded*/ true);

            navigationLinkInfo.expandedFeed = expandedFeed;
            return(navigationLinkInfo);
        }
        /// <summary>
        /// Creates a navigation link info for a collection of entity reference links.
        /// </summary>
        /// <param name="navigationLink">The navigation link to report.</param>
        /// <param name="navigationProperty">The navigation property for which the link will be reported.</param>
        /// <param name="entityReferenceLinks">The entity reference links for the navigation link to report.</param>
        /// <param name="isExpanded">true if the navigation link is expanded.</param>
        /// <returns>The navigation link info created.</returns>
        internal static ODataJsonLightReaderNavigationLinkInfo CreateCollectionEntityReferenceLinksInfo(
            ODataNavigationLink navigationLink,
            IEdmNavigationProperty navigationProperty,
            LinkedList <ODataEntityReferenceLink> entityReferenceLinks,
            bool isExpanded)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.IsCollection == true, "Collection entity reference can only be reported for a collection navigation links.");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");
            Debug.Assert(entityReferenceLinks == null || entityReferenceLinks.Count > 0, "entityReferenceLinks == null || entityReferenceLinks.Count > 0");

            ODataJsonLightReaderNavigationLinkInfo navigationLinkInfo = new ODataJsonLightReaderNavigationLinkInfo(navigationLink, navigationProperty, isExpanded);

            navigationLinkInfo.entityReferenceLinks = entityReferenceLinks;
            return(navigationLinkInfo);
        }
Exemplo n.º 18
0
        /// <summary>
        /// Initializes an ODataNavigationLink instance for the deferred link payload.
        /// </summary>
        /// <param name="payloadElement">The deferred link to process.</param>
        public override void Visit(DeferredLink payloadElement)
        {
            Debug.Assert(this.currentLink != null);
            ODataNavigationLink navigationLink = this.currentLink;

            this.currentLink = null;

            // TODO, ckerer: where do I get the info whether this links is a singleton or collection?
            navigationLink.Url = new Uri(payloadElement.UriString);

            AddLinkMetadata(payloadElement, navigationLink);

            this.writer.WriteStart(navigationLink);
            base.Visit(payloadElement);
            this.writer.WriteEnd();
        }
Exemplo n.º 19
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);
            }
        }
Exemplo n.º 20
0
        public void PropertyGettersAndSettersTest()
        {
            string name         = "ODataNavigationLink";
            Uri    url          = new Uri("http://odatatest.org/");
            bool   isCollection = true;

            ODataNavigationLink navigationLink = new ODataNavigationLink()
            {
                Name         = name,
                Url          = url,
                IsCollection = isCollection,
            };

            this.Assert.AreEqual(name, navigationLink.Name, "Expected equal name values.");
            this.Assert.AreSame(url, navigationLink.Url, "Expected reference equal values for property 'Url'.");
            this.Assert.AreEqual(isCollection, navigationLink.IsCollection, "Expected equal values for property 'IsCollection'");
        }
Exemplo n.º 21
0
        /// <summary>
        /// Finish writing a navigation link with content.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void EndNavigationLinkWithContent(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");

            if (this.verboseJsonOutputContext.WritingResponse)
            {
                // Nothing to do here, the navigation link is represented as a JSON object which is either the feed or entry
            }
            else
            {
                // In request, if the navigation link is a collection we must close the array we've started.
                if (navigationLink.IsCollection.Value)
                {
                    this.verboseJsonOutputContext.JsonWriter.EndArrayScope();
                }
            }
        }
Exemplo n.º 22
0
        public void NavigationLinkValidationTest()
        {
            var testCases = new[] {
                new NavigationLinkValidationTestCase { // null link name is not valid
                    InvalidateLink    = link => link.Name = null,
                    ExpectedException = link => ODataExpectedExceptions.ODataException("ValidationUtils_LinkMustSpecifyName"),
                },
                new NavigationLinkValidationTestCase { // empty link name is not valid
                    InvalidateLink    = link => link.Name = string.Empty,
                    ExpectedException = link => ODataExpectedExceptions.ODataException("ValidationUtils_LinkMustSpecifyName"),
                },
                new NavigationLinkValidationTestCase { // null link Url is not valid
                    InvalidateLink        = link => link.Url = null,
                    ExpectedException     = link => ODataExpectedExceptions.ODataException("WriterValidationUtils_NavigationLinkMustSpecifyUrl", link.Name),
                    SkipTestConfiguration = (testConfiguration) => testConfiguration.Format == ODataFormat.Json || testConfiguration.IsRequest
                },
            };

            var testDescriptors = testCases.Select(testCase =>
            {
                ODataNavigationLink link = ObjectModelUtils.CreateDefaultCollectionLink();
                testCase.InvalidateLink(link);
                return(new PayloadWriterTestDescriptor <ODataItem>(
                           this.Settings,
                           link,
                           testConfiguration => new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                {
                    ExpectedException2 = testCase.ExpectedException(link)
                })
                {
                    SkipTestConfiguration = testCase.SkipTestConfiguration
                });
            });

            // TODO: Fix places where we've lost JsonVerbose coverage to add JsonLight
            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors.PayloadCases(WriterPayloads.NavigationLinkOnlyPayloads),
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurations.Where(tc => tc.Format == ODataFormat.Atom),
                (testDescriptor, testConfiguration) =>
            {
                testConfiguration = testConfiguration.Clone();
                testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);

                TestWriterUtils.WriteAndVerifyODataPayload(testDescriptor.DeferredLinksToEntityReferenceLinksInRequest(testConfiguration), testConfiguration, this.Assert, this.Logger);
            });
        }
Exemplo n.º 23
0
        protected override bool ReadAtNavigationLinkEndImplementation()
        {
            IEdmNavigationProperty property;

            base.PopScope(ODataReaderState.NavigationLinkEnd);
            ODataNavigationLink navigationLink = this.jsonEntryAndFeedDeserializer.ReadEntryContent(this.CurrentEntryState, out property);

            if (navigationLink == null)
            {
                this.ReplaceScope(ODataReaderState.EntryEnd);
            }
            else
            {
                this.StartNavigationLink(navigationLink, property);
            }
            return(true);
        }
Exemplo n.º 24
0
        public void PropertySettersNullTest()
        {
            ODataNavigationLink navigationLink = new ODataNavigationLink()
            {
                Name         = "NewLink",
                Url          = new Uri("http://odata.org"),
                IsCollection = true,
            };

            navigationLink.Name         = null;
            navigationLink.Url          = null;
            navigationLink.IsCollection = null;

            this.Assert.IsNull(navigationLink.Name, "Expected null value for property 'Name'.");
            this.Assert.IsNull(navigationLink.Url, "Expected null value for property 'Url'.");
            this.Assert.IsNull(navigationLink.Url, "Expected null value for property 'IsCollection'.");
        }
Exemplo n.º 25
0
        public void InitTest()
        {
            this.navigationLink = new ODataNavigationLink();

            var entry = new ODataEntry
            {
                TypeName   = "ns.DerivedType",
                Properties = new[]
                {
                    new ODataProperty {
                        Name = "Id", Value = 1, SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.Key
                        }
                    },
                    new ODataProperty {
                        Name = "Name", Value = "Bob", SerializationInfo = new ODataPropertySerializationInfo {
                            PropertyKind = ODataPropertyKind.ETag
                        }
                    }
                }
            };

            var serializationInfo = new ODataFeedAndEntrySerializationInfo {
                NavigationSourceName = "Set", NavigationSourceEntityTypeName = "ns.BaseType", ExpectedTypeName = "ns.BaseType"
            };
            var typeContext          = ODataFeedAndEntryTypeContext.Create(serializationInfo, null, null, null, EdmCoreModel.Instance, true);
            var metadataContext      = new TestMetadataContext();
            var entryMetadataContext = ODataEntryMetadataContext.Create(entry, typeContext, serializationInfo, null, metadataContext, SelectedPropertiesNode.EntireSubtree);
            var metadataBuilder      = new ODataConventionalEntityMetadataBuilder(entryMetadataContext, metadataContext, new ODataConventionalUriBuilder(ServiceUri, UrlConvention.CreateWithExplicitValue(false)));

            this.navigationLinkWithFullBuilder = new ODataNavigationLink {
                Name = "NavProp"
            };
            this.navigationLinkWithFullBuilder.MetadataBuilder = metadataBuilder;

            this.navigationLinkWithNoOpBuilder = new ODataNavigationLink {
                Name = "NavProp"
            };
            this.navigationLinkWithNoOpBuilder.MetadataBuilder = new NoOpEntityMetadataBuilder(entry);

            this.navigationLinkWithNullBuilder = new ODataNavigationLink {
                Name = "NavProp"
            };
            this.navigationLinkWithNullBuilder.MetadataBuilder = ODataEntityMetadataBuilder.Null;
        }
        public void OnNavLinkEndShouldBeFired()
        {
            Person              p    = new Person();
            Address             a    = new Address();
            ODataNavigationLink link = new ODataNavigationLink();
            var wrappedWriter        = this.SetupTestActionExecuted((context, requestPipeline) =>
            {
                requestPipeline.OnNavigationLinkEnding((args) =>
                {
                    args.Source.Should().BeSameAs(p);
                    args.Target.Should().BeSameAs(a);
                    args.Link.Name = "foo";
                });
            });

            wrappedWriter.WriteEnd(link, p, a);
            link.Name.Should().Be("foo");
        }
Exemplo n.º 27
0
        private void WriteEntry(ODataWriter writer, ODataEntry entry)
        {
            writer.WriteStart(entry);
            var annotation = entry.GetAnnotation <ODataEntryNavigationLinksObjectModelAnnotation>();
            ODataNavigationLink navLink = null;

            if (annotation != null)
            {
                for (int i = 0; i < annotation.Count; ++i)
                {
                    bool found = annotation.TryGetNavigationLinkAt(i, out navLink);
                    ExceptionUtilities.Assert(found, "Navigation links should be ordered sequentially for writing");
                    this.WriteNavigationLink(writer, navLink);
                }
            }

            writer.WriteEnd();
        }
Exemplo n.º 28
0
        private async Task <IEnumerable <ODataNavigationLink> > CreateNavigationLinksAsync(
            IEnumerable <IEdmNavigationProperty> navigationProperties, EntityInstanceContext entityInstanceContext)
        {
            Contract.Assert(navigationProperties != null);
            Contract.Assert(entityInstanceContext != null);
            List <ODataNavigationLink> result = new List <ODataNavigationLink>();

            foreach (IEdmNavigationProperty navProperty in navigationProperties)
            {
                ODataNavigationLink navigationLink = await CreateNavigationLinkAsync(navProperty, entityInstanceContext);

                if (navigationLink != null)
                {
                    result.Add(navigationLink);
                }
            }
            return(result);
        }
Exemplo n.º 29
0
        /// <summary>
        /// Writes the navigation link end m:inline and end atom:link elements if there's a parent navigation link.
        /// </summary>
        private void CheckAndWriteParentNavigationLinkEndForInlineElement()
        {
            Debug.Assert(this.State == WriterState.Entry || this.State == WriterState.Feed, "Only entry or feed can be written into a link with inline.");

            ODataNavigationLink parentNavigationLink = this.ParentNavigationLink;

            if (parentNavigationLink != null)
            {
                // We postponed writing the surrounding atom:link and m:inline until now since in request a single navigation link can have
                // multiple items in its content, each of which is written as a standalone atom:link. Thus the EndNavigationLinkWithContent is only called
                // once, but we may need to write multiple atom:link elements.

                // </m:inline>
                this.atomOutputContext.XmlWriter.WriteEndElement();

                // </atom:link>
                this.WriteNavigationLinkEnd();
            }
        }
Exemplo n.º 30
0
        private static MaterializerNavigationLink GetPropertyOrThrow(IEnumerable <ODataNavigationLink> links, string propertyName, string entryIdentity)
        {
            Func <ODataNavigationLink, bool> predicate = null;
            ODataNavigationLink link = null;

            if (links != null)
            {
                if (predicate == null)
                {
                    predicate = p => p.Name == propertyName;
                }
                link = links.Where <ODataNavigationLink>(predicate).FirstOrDefault <ODataNavigationLink>();
            }
            if (link == null)
            {
                throw new InvalidOperationException(System.Data.Services.Client.Strings.AtomMaterializer_PropertyMissing(propertyName, entryIdentity));
            }
            return(MaterializerNavigationLink.GetLink(link));
        }
Exemplo n.º 31
0
        /// <summary>
        /// Adds a navigation link.
        /// </summary>
        /// <param name="link">The link.</param>
        public void AddNavigationLink(ODataNavigationLink link)
        {
            if (this.IsAtomOrTracking)
            {
                this.EntityDescriptor.AddNavigationLink(link.Name, link.Url);
                Uri associationLinkUrl = link.AssociationLinkUrl;
                if (associationLinkUrl != null)
                {
                    this.EntityDescriptor.AddAssociationLink(link.Name, associationLinkUrl);
                }
            }

            if (this.navigationLinks == ODataMaterializer.EmptyLinks)
            {
                this.navigationLinks = new List <ODataNavigationLink>();
            }

            this.navigationLinks.Add(link);
        }
Exemplo n.º 32
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>
        private void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride)
        {
            // IsCollection is required for ATOM
            if (!navigationLink.IsCollection.HasValue)
            {
                throw new ODataException(o.Strings.ODataWriterCore_LinkMustSpecifyIsCollection);
            }

            // Navigation link must specify the Url
            // NOTE: we currently only require a non-null Url for ATOM payloads and non-expanded navigation links in JSON.
            //       There is no place in JSON to write a Url if the navigation link is expanded. We can't change that for v1 and v2; we
            //       might fix the protocol for v3.
            if (navigationLink.Url == null)
            {
                throw new ODataException(o.Strings.ODataWriter_NavigationLinkMustSpecifyUrl);
            }

            this.atomEntryAndFeedSerializer.WriteNavigationLinkStart(navigationLink, navigationLinkUrlOverride);
        }
Exemplo n.º 33
0
        /// <summary>
        /// Start writing an entry.
        /// </summary>
        /// <param name="entry">The entry to write.</param>
        protected override void StartEntry(ODataEntry entry)
        {
            ODataNavigationLink parentNavLink = this.ParentNavigationLink;

            if (parentNavLink != null)
            {
                // Write the property name of an expanded navigation property to start the value.
                this.jsonLightOutputContext.JsonWriter.WriteName(parentNavLink.Name);
            }

            if (entry == null)
            {
                Debug.Assert(
                    parentNavLink != null && !parentNavLink.IsCollection.Value,
                    "when entry == null, it has to be and expanded single entry navigation");

                // this is a null expanded single entry and it is null, so write a JSON null as value.
                this.jsonLightOutputContext.JsonWriter.WriteValue(null);
                return;
            }

            // Write just the object start, nothing else, since we might not have complete information yet
            this.jsonLightOutputContext.JsonWriter.StartObjectScope();

            JsonLightEntryScope entryScope = this.CurrentEntryScope;

            if (this.IsTopLevel)
            {
                // Write odata.metadata
                this.jsonLightEntryAndFeedSerializer.TryWriteEntryMetadataUri(entryScope.GetOrCreateTypeContext(this.jsonLightOutputContext.Model, this.jsonLightOutputContext.WritingResponse));
            }

            // Write the annotation group in responses (if any)
            this.jsonLightEntryAndFeedSerializer.WriteAnnotationGroup(entry);

            // Write the metadata
            this.jsonLightEntryAndFeedSerializer.WriteEntryStartMetadataProperties(entryScope);
            this.jsonLightEntryAndFeedSerializer.WriteEntryMetadataProperties(entryScope);

            // Write custom instance annotations
            this.jsonLightEntryAndFeedSerializer.InstanceAnnotationWriter.WriteInstanceAnnotations(entry.InstanceAnnotations, entryScope.InstanceAnnotationWriteTracker);
        }
Exemplo n.º 34
0
        /// <summary>
        /// Visits a navigation link item.
        /// </summary>
        /// <param name="navigationLink">The navigation link to visit.</param>
        protected virtual void VisitNavigationLink(ODataNavigationLink navigationLink)
        {
            object expandedContent;

            if (navigationLink.TryGetExpandedContent(out expandedContent) && expandedContent != null)
            {
                List <ODataItem> items = expandedContent as List <ODataItem>;
                if (items != null)
                {
                    foreach (ODataItem item in items)
                    {
                        this.Visit(item);
                    }
                }
                else
                {
                    this.Visit(expandedContent);
                }
            }
        }
        /// <summary>
        /// Creates a navigation link info for a singleton entity reference link.
        /// </summary>
        /// <param name="navigationLink">The navigation link to report.</param>
        /// <param name="navigationProperty">The navigation property for which the link will be reported.</param>
        /// <param name="entityReferenceLink">The entity reference link for the navigation link to report.</param>
        /// <param name="isExpanded">true if the navigation link is expanded.</param>
        /// <returns>The navigation link info created.</returns>
        internal static ODataJsonLightReaderNavigationLinkInfo CreateSingletonEntityReferenceLinkInfo(
            ODataNavigationLink navigationLink,
            IEdmNavigationProperty navigationProperty,
            ODataEntityReferenceLink entityReferenceLink,
            bool isExpanded)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.IsCollection == false, "Singleton entity reference can only be reported for a singleton navigation links.");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            ODataJsonLightReaderNavigationLinkInfo navigationLinkInfo = new ODataJsonLightReaderNavigationLinkInfo(navigationLink, navigationProperty, isExpanded);

            if (entityReferenceLink != null)
            {
                navigationLinkInfo.entityReferenceLinks = new LinkedList <ODataEntityReferenceLink>();
                navigationLinkInfo.entityReferenceLinks.AddFirst(entityReferenceLink);
            }

            return(navigationLinkInfo);
        }
Exemplo n.º 36
0
            private ODataNavigationLink ReadNavigationLink()
            {
                MaterializerEntry   entry;
                ODataFeed           feed;
                ODataNavigationLink item = (ODataNavigationLink)this.reader.Item;

                if (this.TryReadFeedOrEntry(false, out feed, out entry))
                {
                    if (feed != null)
                    {
                        MaterializerNavigationLink.CreateLink(item, feed);
                    }
                    else
                    {
                        MaterializerNavigationLink.CreateLink(item, entry);
                    }
                    this.ReadAndExpectState(ODataReaderState.NavigationLinkEnd);
                }
                this.ExpectState(ODataReaderState.NavigationLinkEnd);
                return(item);
            }
Exemplo n.º 37
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 */);
        }
        /// <summary>
        /// Start writing a deferred (non-expanded) navigation link.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void WriteDeferredNavigationLink(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(this.jsonLightOutputContext.WritingResponse, "Deferred links are only supported in response, we should have verified this already.");

            // A deferred navigation link is just the link metadata, no value.
            this.jsonLightEntryAndFeedSerializer.WriteNavigationLinkMetadata(navigationLink, this.DuplicatePropertyNamesChecker);
        }
        /// <summary>
        /// Reads a navigation link in entry element.
        /// </summary>
        /// <param name="entryState">The reader entry state for the entry being read.</param>
        /// <param name="linkRelation">The value of the rel attribute of the link to read, unescaped parsed URI.</param>
        /// <param name="linkHRef">The value of the href attribute of the link to read.</param>
        /// <returns>A descriptor of a navigation link if a navigation link was found; null otherwise.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element atom:link - the start tag of the atom:link element to read.
        /// Post-Condition: XmlNodeType.Element atom:link - the start tag of the atom:link element - the reader doesn't move
        /// </remarks>
        private ODataAtomReaderNavigationLinkDescriptor TryReadNavigationLinkInEntry(
            IODataAtomReaderEntryState entryState,
            string linkRelation,
            string linkHRef)
        {
            Debug.Assert(linkRelation != null, "linkRelation != null");
            this.XmlReader.AssertNotBuffering();
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(
                this.XmlReader.NamespaceURI == AtomConstants.AtomNamespace && this.XmlReader.LocalName == AtomConstants.AtomLinkElementName,
                "The XML reader must be on the atom:link element for this method to work.");

            // We will ignore navigation links with empty property names
            string navigationLinkName = AtomUtils.GetNameFromAtomLinkRelationAttribute(linkRelation, AtomConstants.ODataNavigationPropertiesRelatedLinkRelationPrefix);
            if (string.IsNullOrEmpty(navigationLinkName))
            {
                return null;
            }

            // Lookup the property in metadata
            // Note that we already verified that the navigation link name is not empty.
            IEdmNavigationProperty navigationProperty = ReaderValidationUtils.ValidateNavigationPropertyDefined(navigationLinkName, entryState.EntityType, this.MessageReaderSettings);

            // Navigation link
            ODataNavigationLink navigationLink = new ODataNavigationLink { Name = navigationLinkName };

            // Get the type of the link
            string navigationLinkType = this.XmlReader.GetAttribute(this.AtomTypeAttributeName, this.EmptyNamespace);

            // [Astoria-ODataLib-Integration] Handling of type attribute value on atom:link element.
            // The behavior of ODataLib is:
            // Parse the type as content type
            //   Compare media type names ignoring case (as per spec), compare parameter type names ignoring case
            //   If it's application/atom+xml without type parameter or invalid type parameter - use it as a navigation link without specifying collection/singleton (pending metadata validation)
            //   If it's application/atom+xml with type='feed' - use it as a navigation link assuming it's a collection (pending metadata validation)
            //   If it's application/atom+xml with type='entry' - use it as a navigation link assuming it's a singleton (pending metadata validation)
            //   In any other case - skip this link and treat it as if it's not a navigation link.
            // Note that parsing the type means we may fail if it's not a valid content type.
            // Missing and invalid type attributes are allowed. We will infer the cardinality either from the model or when expanding the link.
            if (!string.IsNullOrEmpty(navigationLinkType))
            {
                // Fast path for most common link types
                bool hasEntryType, hasFeedType;
                bool isExactMatch = AtomUtils.IsExactNavigationLinkTypeMatch(navigationLinkType, out hasEntryType, out hasFeedType);
                if (!isExactMatch)
                {
                    // If the fast path did not work, we have to fully parse the media type.
                    string mediaTypeName, mediaTypeCharset;
                    IList<KeyValuePair<string, string>> contentTypeParameters = HttpUtils.ReadMimeType(navigationLinkType, out mediaTypeName, out mediaTypeCharset);
                    if (!HttpUtils.CompareMediaTypeNames(mediaTypeName, MimeConstants.MimeApplicationAtomXml))
                    {
                        return null;
                    }

                    string typeParameterValue = null;
                    if (contentTypeParameters != null)
                    {
                        for (int contentTypeParameterIndex = 0; contentTypeParameterIndex < contentTypeParameters.Count; contentTypeParameterIndex++)
                        {
                            KeyValuePair<string, string> contentTypeParameter = contentTypeParameters[contentTypeParameterIndex];
                            if (HttpUtils.CompareMediaTypeParameterNames(MimeConstants.MimeTypeParameterName, contentTypeParameter.Key))
                            {
                                typeParameterValue = contentTypeParameter.Value;
                                break;
                            }
                        }
                    }

                    if (typeParameterValue != null)
                    {
                        if (string.Compare(typeParameterValue, MimeConstants.MimeTypeParameterValueEntry, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            hasEntryType = true;
                        }
                        else if (string.Compare(typeParameterValue, MimeConstants.MimeTypeParameterValueFeed, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            hasFeedType = true;
                        }
                    }
                }

                if (hasEntryType)
                {
                    navigationLink.IsCollection = false;
                }
                else if (hasFeedType)
                {
                    navigationLink.IsCollection = true;
                }
            }

            // We allow missing HREF on a link and simply report null.
            if (linkHRef != null)
            {
                navigationLink.Url = this.ProcessUriFromPayload(linkHRef, this.XmlReader.XmlBaseUri);
            }

            this.XmlReader.MoveToElement();

            // Read and store ATOM link metadata (captures extra info like lang, title) if ATOM metadata reading is turned on.
            AtomLinkMetadata atomLinkMetadata = this.EntryMetadataDeserializer.ReadAtomLinkElementInEntryContent(linkRelation, linkHRef);
            if (atomLinkMetadata != null)
            {
                navigationLink.SetAnnotation(atomLinkMetadata);
            }

            return new ODataAtomReaderNavigationLinkDescriptor(navigationLink, navigationProperty);
        }
        /// <summary>
        /// Creates a navigation link info for a singleton entity reference link.
        /// </summary>
        /// <param name="navigationLink">The navigation link to report.</param>
        /// <param name="navigationProperty">The navigation property for which the link will be reported.</param>
        /// <param name="entityReferenceLink">The entity reference link for the navigation link to report.</param>
        /// <param name="isExpanded">true if the navigation link is expanded.</param>
        /// <returns>The navigation link info created.</returns>
        internal static ODataJsonLightReaderNavigationLinkInfo CreateSingletonEntityReferenceLinkInfo(
            ODataNavigationLink navigationLink,
            IEdmNavigationProperty navigationProperty,
            ODataEntityReferenceLink entityReferenceLink,
            bool isExpanded)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.IsCollection == false, "Singleton entity reference can only be reported for a singleton navigation links.");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            ODataJsonLightReaderNavigationLinkInfo navigationLinkInfo = new ODataJsonLightReaderNavigationLinkInfo(navigationLink, navigationProperty, isExpanded);
            if (entityReferenceLink != null)
            {
                navigationLinkInfo.entityReferenceLinks = new LinkedList<ODataEntityReferenceLink>();
                navigationLinkInfo.entityReferenceLinks.AddFirst(entityReferenceLink);
            }

            return navigationLinkInfo;
        }
 /// <summary>
 /// Constructor to create a new JSON Light navigation link scope.
 /// </summary>
 /// <param name="writerState">The writer state for the new scope.</param>
 /// <param name="navLink">The navigation link for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 internal JsonLightNavigationLinkScope(WriterState writerState, ODataNavigationLink navLink, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
     : base(writerState, navLink, navigationSource, entityType, skipWriting, selectedProperties, odataUri)
 {
 }
 /// <summary>
 /// Creates a new JSON Light navigation link scope.
 /// </summary>
 /// <param name="writerState">The writer state for the new scope.</param>
 /// <param name="navLink">The navigation link for the new scope.</param>
 /// <param name="navigationSource">The navigation source we are going to write entities for.</param>
 /// <param name="entityType">The entity type for the entries in the feed to be written (or null if the entity set base type should be used).</param>
 /// <param name="skipWriting">true if the content of the scope to create should not be written.</param>
 /// <param name="selectedProperties">The selected properties of this scope.</param>
 /// <param name="odataUri">The ODataUri info of this scope.</param>
 /// <returns>The newly created JSON Light  navigation link scope.</returns>
 protected override NavigationLinkScope CreateNavigationLinkScope(WriterState writerState, ODataNavigationLink navLink, IEdmNavigationSource navigationSource, IEdmEntityType entityType, bool skipWriting, SelectedPropertiesNode selectedProperties, ODataUri odataUri)
 {
     return new JsonLightNavigationLinkScope(writerState, navLink, navigationSource, entityType, skipWriting, selectedProperties, odataUri);
 }
        /// <summary>
        /// Write an entity reference link.
        /// </summary>
        /// <param name="parentNavigationLink">The parent navigation link which is being written around the entity reference link.</param>
        /// <param name="entityReferenceLink">The entity reference link to write.</param>
        protected override void WriteEntityReferenceInNavigationLinkContent(ODataNavigationLink parentNavigationLink, ODataEntityReferenceLink entityReferenceLink)
        {
            Debug.Assert(parentNavigationLink != null, "parentNavigationLink != null");
            Debug.Assert(entityReferenceLink != null, "entityReferenceLink != null");
            Debug.Assert(!this.jsonLightOutputContext.WritingResponse, "Entity reference links are only supported in request, we should have verified this already.");

            // In JSON Light, we can only write entity reference links at the beginning of a navigation link in requests;
            // once we wrote a feed, entity reference links are not allowed anymore (we require all the entity reference
            // link to come first because of the grouping in the JSON Light wire format).
            JsonLightNavigationLinkScope navigationLinkScope = (JsonLightNavigationLinkScope)this.CurrentScope;
            if (navigationLinkScope.FeedWritten)
            {
                throw new ODataException(OData.Core.Strings.ODataJsonLightWriter_EntityReferenceLinkAfterFeedInRequest);
            }

            if (!navigationLinkScope.EntityReferenceLinkWritten)
            {
                // Write the property annotation for the entity reference link(s)
                this.odataAnnotationWriter.WritePropertyAnnotationName(parentNavigationLink.Name, ODataAnnotationNames.ODataBind);
                Debug.Assert(parentNavigationLink.IsCollection.HasValue, "parentNavigationLink.IsCollection.HasValue");
                if (parentNavigationLink.IsCollection.Value)
                {
                    this.jsonWriter.StartArrayScope();
                }

                navigationLinkScope.EntityReferenceLinkWritten = true;
            }

            Debug.Assert(entityReferenceLink.Url != null, "The entity reference link Url should have been validated by now.");
            this.jsonWriter.WriteValue(this.jsonLightEntryAndFeedSerializer.UriToString(entityReferenceLink.Url));
        }
        /// <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 */);
        }
Exemplo n.º 45
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>
 private void WriteNavigationLinkStart(ODataNavigationLink navigationLink, Uri navigationLinkUrlOverride)
 {
     WriterValidationUtils.ValidateNavigationLinkHasCardinality(navigationLink);
     WriterValidationUtils.ValidateNavigationLinkUrlPresent(navigationLink);
     this.atomEntryAndFeedSerializer.WriteNavigationLinkStart(navigationLink, navigationLinkUrlOverride);
 }
        /// <summary>
        /// Creates a navigation link info for a collection of entity reference links.
        /// </summary>
        /// <param name="navigationLink">The navigation link to report.</param>
        /// <param name="navigationProperty">The navigation property for which the link will be reported.</param>
        /// <param name="entityReferenceLinks">The entity reference links for the navigation link to report.</param>
        /// <param name="isExpanded">true if the navigation link is expanded.</param>
        /// <returns>The navigation link info created.</returns>
        internal static ODataJsonLightReaderNavigationLinkInfo CreateCollectionEntityReferenceLinksInfo(
            ODataNavigationLink navigationLink,
            IEdmNavigationProperty navigationProperty,
            LinkedList<ODataEntityReferenceLink> entityReferenceLinks,
            bool isExpanded)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(navigationLink.IsCollection == true, "Collection entity reference can only be reported for a collection navigation links.");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");
            Debug.Assert(entityReferenceLinks == null || entityReferenceLinks.Count > 0, "entityReferenceLinks == null || entityReferenceLinks.Count > 0");

            ODataJsonLightReaderNavigationLinkInfo navigationLinkInfo = new ODataJsonLightReaderNavigationLinkInfo(navigationLink, navigationProperty, isExpanded);
            navigationLinkInfo.entityReferenceLinks = entityReferenceLinks;
            return navigationLinkInfo;
        }
        /// <summary>
        /// Creates a navigation link info for a projected navigation link that is missing from the payload.
        /// </summary>
        /// <param name="navigationProperty">The navigation property for which the link will be reported.</param>
        /// <returns>The navigation link info created.</returns>
        internal static ODataJsonLightReaderNavigationLinkInfo CreateProjectedNavigationLinkInfo(IEdmNavigationProperty navigationProperty)
        {
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            ODataNavigationLink navigationLink = new ODataNavigationLink { Name = navigationProperty.Name, IsCollection = navigationProperty.Type.IsCollection() };
            ODataJsonLightReaderNavigationLinkInfo navigationLinkInfo = new ODataJsonLightReaderNavigationLinkInfo(navigationLink, navigationProperty, /*isExpanded*/ false);
            return navigationLinkInfo;
        }
        /// <summary>
        /// Reads the information of a deferred link.
        /// </summary>
        /// <param name="entryState">The state of the reader for entry to read.</param>
        /// <param name="navigationPropertyName">The name of the navigation property for which to read the deferred link.</param>
        /// <param name="navigationProperty">The navigation property for which to read the deferred link. This can be null.</param>
        /// <returns>Returns the navigation link info for the deferred navigation link read.</returns>
        /// <remarks>
        /// This method doesn't move the reader.
        /// </remarks>
        private static ODataJsonLightReaderNavigationLinkInfo ReadDeferredNavigationLink(IODataJsonLightReaderEntryState entryState, string navigationPropertyName, IEdmNavigationProperty navigationProperty)
        {
            Debug.Assert(entryState != null, "entryState != null");
            Debug.Assert(!string.IsNullOrEmpty(navigationPropertyName), "!string.IsNullOrEmpty(navigationPropertyName)");
            Debug.Assert(navigationProperty == null || navigationPropertyName == navigationProperty.Name, "navigationProperty == null || navigationPropertyName == navigationProperty.Name");

            ODataNavigationLink navigationLink = new ODataNavigationLink()
            {
                Name = navigationPropertyName,
                IsCollection = navigationProperty == null ? null : (bool?)navigationProperty.Type.IsCollection()
            };

            Dictionary<string, object> propertyAnnotations = entryState.DuplicatePropertyNamesChecker.GetODataPropertyAnnotations(navigationLink.Name);
            if (propertyAnnotations != null)
            {
                foreach (KeyValuePair<string, object> propertyAnnotation in propertyAnnotations)
                {
                    switch (propertyAnnotation.Key)
                    {
                        case ODataAnnotationNames.ODataNavigationLinkUrl:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.navigationLinkUrl annotation should have been parsed as a non-null Uri.");
                            navigationLink.Url = (Uri)propertyAnnotation.Value;
                            break;

                        case ODataAnnotationNames.ODataAssociationLinkUrl:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.associationLinkUrl annotation should have been parsed as a non-null Uri.");
                            navigationLink.AssociationLinkUrl = (Uri)propertyAnnotation.Value;
                            break;

                        default:
                            throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_UnexpectedDeferredLinkPropertyAnnotation(navigationLink.Name, propertyAnnotation.Key));
                    }
                }
            }

            return ODataJsonLightReaderNavigationLinkInfo.CreateDeferredLinkInfo(navigationLink, navigationProperty);
        }
        /// <summary>
        /// Start writing a navigation link with content.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void StartNavigationLinkWithContent(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(!string.IsNullOrEmpty(navigationLink.Name), "The navigation link name should have been verified by now.");

            if (this.jsonLightOutputContext.WritingResponse)
            {
                // Write @odata.context annotation for navigation property
                var containedEntitySet = this.CurrentScope.NavigationSource as IEdmContainedEntitySet;
                if (containedEntitySet != null)
                {
                    ODataContextUrlInfo info = ODataContextUrlInfo.Create(
                                                this.CurrentScope.NavigationSource,
                                                this.CurrentScope.EntityType.FullName(),
                                                containedEntitySet.NavigationProperty.Type.TypeKind() != EdmTypeKind.Collection,
                                                this.CurrentScope.ODataUri);
                    this.jsonLightEntryAndFeedSerializer.WriteNavigationLinkContextUrl(navigationLink, info);
                }

                // Write the navigation link metadata first. The rest is written by the content entry or feed.
                this.jsonLightEntryAndFeedSerializer.WriteNavigationLinkMetadata(navigationLink, this.DuplicatePropertyNamesChecker);
            }
            else
            {
                WriterValidationUtils.ValidateNavigationLinkHasCardinality(navigationLink);
            }
        }
        /// <summary>
        /// Finish writing a navigation link with content.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void EndNavigationLinkWithContent(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");

            if (!this.jsonLightOutputContext.WritingResponse)
            {
                JsonLightNavigationLinkScope navigationLinkScope = (JsonLightNavigationLinkScope)this.CurrentScope;

                // If we wrote entity reference links for a collection navigation property but no 
                // feed afterwards, we have to now close the array of links.
                if (navigationLinkScope.EntityReferenceLinkWritten && !navigationLinkScope.FeedWritten && navigationLink.IsCollection.Value)
                {
                    this.jsonWriter.EndArrayScope();
                }

                // In requests, the navigation link may have multiple entries in multiple feeds in it; if we 
                // wrote at least one feed, close the resulting array here.
                if (navigationLinkScope.FeedWritten)
                {
                    Debug.Assert(navigationLink.IsCollection.Value, "navigationLink.IsCollection.Value");
                    this.jsonWriter.EndArrayScope();
                }
            }
        }
Exemplo n.º 51
0
 protected override void EndNavigationLinkWithContent(ODataNavigationLink navigationLink)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// Reads expanded feed navigation link.
        /// </summary>
        /// <param name="entryState">The state of the reader for entry to read.</param>
        /// <param name="navigationProperty">The navigation property for which to read the expanded link.</param>
        /// <returns>The navigation link info for the expanded link read.</returns>
        /// <remarks>
        /// This method doesn't move the reader.
        /// </remarks>
        private static ODataJsonLightReaderNavigationLinkInfo ReadExpandedFeedNavigationLink(IODataJsonLightReaderEntryState entryState, IEdmNavigationProperty navigationProperty)
        {
            Debug.Assert(entryState != null, "entryState != null");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            ODataNavigationLink navigationLink = new ODataNavigationLink()
            {
                Name = navigationProperty.Name,
                IsCollection = true
            };

            ODataFeed expandedFeed = new ODataFeed();

            Dictionary<string, object> propertyAnnotations = entryState.DuplicatePropertyNamesChecker.GetODataPropertyAnnotations(navigationLink.Name);
            if (propertyAnnotations != null)
            {
                foreach (KeyValuePair<string, object> propertyAnnotation in propertyAnnotations)
                {
                    switch (propertyAnnotation.Key)
                    {
                        case ODataAnnotationNames.ODataNavigationLinkUrl:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.navigationLinkUrl annotation should have been parsed as a non-null Uri.");
                            navigationLink.Url = (Uri)propertyAnnotation.Value;
                            break;

                        case ODataAnnotationNames.ODataAssociationLinkUrl:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.associationLinkUrl annotation should have been parsed as a non-null Uri.");
                            navigationLink.AssociationLinkUrl = (Uri)propertyAnnotation.Value;
                            break;

                        case ODataAnnotationNames.ODataNextLink:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.nextLink annotation should have been parsed as a non-null Uri.");
                            expandedFeed.NextPageLink = (Uri)propertyAnnotation.Value;
                            break;

                        case ODataAnnotationNames.ODataCount:
                            Debug.Assert(propertyAnnotation.Value is long && propertyAnnotation.Value != null, "The odata.count annotation should have been parsed as a non-null long.");
                            expandedFeed.Count = (long?)propertyAnnotation.Value;
                            break;
                        case ODataAnnotationNames.ODataContext:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.context annotation should have been parsed as a non-null Uri.");
                            navigationLink.ContextUrl = (Uri)propertyAnnotation.Value;
                            break;

                        case ODataAnnotationNames.ODataDeltaLink:   // Delta links are not supported on expanded feeds.
                        default:
                            throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_UnexpectedExpandedCollectionNavigationLinkPropertyAnnotation(navigationLink.Name, propertyAnnotation.Key));
                    }
                }
            }

            return ODataJsonLightReaderNavigationLinkInfo.CreateExpandedFeedLinkInfo(navigationLink, navigationProperty, expandedFeed);
        }
        /// <summary>
        /// Reads expanded entry navigation link.
        /// </summary>
        /// <param name="entryState">The state of the reader for entry to read.</param>
        /// <param name="navigationProperty">The navigation property for which to read the expanded link.</param>
        /// <returns>The navigation link info for the expanded link read.</returns>
        /// <remarks>
        /// This method doesn't move the reader.
        /// </remarks>
        private static ODataJsonLightReaderNavigationLinkInfo ReadExpandedEntryNavigationLink(IODataJsonLightReaderEntryState entryState, IEdmNavigationProperty navigationProperty)
        {
            Debug.Assert(entryState != null, "entryState != null");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            ODataNavigationLink navigationLink = new ODataNavigationLink()
            {
                Name = navigationProperty.Name,
                IsCollection = false
            };

            Dictionary<string, object> propertyAnnotations = entryState.DuplicatePropertyNamesChecker.GetODataPropertyAnnotations(navigationLink.Name);
            if (propertyAnnotations != null)
            {
                foreach (KeyValuePair<string, object> propertyAnnotation in propertyAnnotations)
                {
                    switch (propertyAnnotation.Key)
                    {
                        case ODataAnnotationNames.ODataNavigationLinkUrl:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.navigationLinkUrl annotation should have been parsed as a non-null Uri.");
                            navigationLink.Url = (Uri)propertyAnnotation.Value;
                            break;

                        case ODataAnnotationNames.ODataAssociationLinkUrl:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.associationLinkUrl annotation should have been parsed as a non-null Uri.");
                            navigationLink.AssociationLinkUrl = (Uri)propertyAnnotation.Value;
                            break;

                        case ODataAnnotationNames.ODataContext:
                            Debug.Assert(propertyAnnotation.Value is Uri && propertyAnnotation.Value != null, "The odata.context annotation should have been parsed as a non-null Uri.");
                            navigationLink.ContextUrl = (Uri)propertyAnnotation.Value;
                            break;

                        default:
                            throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_UnexpectedExpandedSingletonNavigationLinkPropertyAnnotation(navigationLink.Name, propertyAnnotation.Key));
                    }
                }
            }

            return ODataJsonLightReaderNavigationLinkInfo.CreateExpandedEntryLinkInfo(navigationLink, navigationProperty);
        }
Exemplo n.º 54
0
        /// <summary>
        /// Start writing a navigation link.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void WriteDeferredNavigationLink(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");
            Debug.Assert(this.atomOutputContext.WritingResponse, "Deferred links are only supported in response, we should have verified this already.");

            this.WriteNavigationLinkStart(navigationLink, null);
            this.WriteNavigationLinkEnd();
        }
        /// <summary>
        /// Reads entity reference links for a collection navigation link in request.
        /// </summary>
        /// <param name="entryState">The state of the reader for entry to read.</param>
        /// <param name="navigationProperty">The navigation property for which to read the entity reference links.</param>
        /// <param name="isExpanded">true if the navigation link is expanded.</param>
        /// <returns>The navigation link info for the entity reference links read.</returns>
        /// <remarks>
        /// This method doesn't move the reader.
        /// </remarks>
        private static ODataJsonLightReaderNavigationLinkInfo ReadEntityReferenceLinksForCollectionNavigationLinkInRequest(
            IODataJsonLightReaderEntryState entryState,
            IEdmNavigationProperty navigationProperty,
            bool isExpanded)
        {
            Debug.Assert(entryState != null, "entryState != null");
            Debug.Assert(navigationProperty != null, "navigationProperty != null");

            ODataNavigationLink navigationLink = new ODataNavigationLink()
            {
                Name = navigationProperty.Name,
                IsCollection = true
            };

            Dictionary<string, object> propertyAnnotations = entryState.DuplicatePropertyNamesChecker.GetODataPropertyAnnotations(navigationLink.Name);
            LinkedList<ODataEntityReferenceLink> entityReferenceLinksList = null;
            if (propertyAnnotations != null)
            {
                foreach (KeyValuePair<string, object> propertyAnnotation in propertyAnnotations)
                {
                    switch (propertyAnnotation.Key)
                    {
                        case ODataAnnotationNames.ODataBind:
                            ODataEntityReferenceLink entityReferenceLink = propertyAnnotation.Value as ODataEntityReferenceLink;
                            if (entityReferenceLink != null)
                            {
                                throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_StringValueForCollectionBindPropertyAnnotation(navigationLink.Name, ODataAnnotationNames.ODataBind));
                            }

                            Debug.Assert(
                                propertyAnnotation.Value is LinkedList<ODataEntityReferenceLink> && propertyAnnotation.Value != null,
                                "The value of odata.bind property annotation must be either ODataEntityReferenceLink or List<ODataEntityReferenceLink>");
                            entityReferenceLinksList = (LinkedList<ODataEntityReferenceLink>)propertyAnnotation.Value;
                            break;

                        default:
                            throw new ODataException(ODataErrorStrings.ODataJsonLightEntryAndFeedDeserializer_UnexpectedNavigationLinkInRequestPropertyAnnotation(
                                navigationLink.Name,
                                propertyAnnotation.Key,
                                ODataAnnotationNames.ODataBind));
                    }
                }
            }

            return ODataJsonLightReaderNavigationLinkInfo.CreateCollectionEntityReferenceLinksInfo(navigationLink, navigationProperty, entityReferenceLinksList, isExpanded);
        }
Exemplo n.º 56
0
        /// <summary>
        /// Start writing a navigation link with content.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void StartNavigationLinkWithContent(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");

            // In requests, a navigation link can have multiple items in its content (in the OM view), either entity reference links or expanded entry/feed.
            // For each of these we need to write a separate atom:link element. So we can't write the start of the atom:link element here
            // instead we postpone writing it till the first item in the content.
            // In response, only one item can occur, but for simplicity we will keep the behavior the same as for request and thus postpone writing the atom:link
            // start element as well.
            // Note that the writer core guarantees that this method (and the matching EndNavigationLinkWithContent) is only called for navigation links
            // which actually have some content. The only case where navigation link doesn't have a content is in response, in which case this method won't
            // be called, instead the WriteDeferredNavigationLink is called.
        }
Exemplo n.º 57
0
 protected override void WriteDeferredNavigationLink(ODataNavigationLink navigationLink)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 58
0
        /// <summary>
        /// Finish writing a navigation link with content.
        /// </summary>
        /// <param name="navigationLink">The navigation link to write.</param>
        protected override void EndNavigationLinkWithContent(ODataNavigationLink navigationLink)
        {
            Debug.Assert(navigationLink != null, "navigationLink != null");

            // We do not write the end element for atom:link here, since we need to write it for each item in the content separately.
            // See the detailed description in the StartNavigationLinkWithContent for details.
        }
Exemplo n.º 59
0
 protected override void WriteEntityReferenceInNavigationLinkContent(ODataNavigationLink parentNavigationLink, ODataEntityReferenceLink entityReferenceLink)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 60
0
        /// <summary>
        /// Write an entity reference link.
        /// </summary>
        /// <param name="parentNavigationLink">The parent navigation link which is being written around the entity reference link.</param>
        /// <param name="entityReferenceLink">The entity reference link to write.</param>
        protected override void WriteEntityReferenceInNavigationLinkContent(ODataNavigationLink parentNavigationLink, ODataEntityReferenceLink entityReferenceLink)
        {
            Debug.Assert(parentNavigationLink != null, "parentNavigationLink != null");
            Debug.Assert(entityReferenceLink != null, "entityReferenceLink != null");
            Debug.Assert(entityReferenceLink.Url != null, "We should have already verifies that the Url specified on the entity reference link is not null.");

            this.WriteNavigationLinkStart(parentNavigationLink, entityReferenceLink.Url);
            this.WriteNavigationLinkEnd();
        }