/// <summary> /// Visits a stream reference value item. /// </summary> /// <param name="streamReferenceValue">The stream reference value item to visit.</param> /// <returns>An ODataPayloadElement representing the stream reference value.</returns> protected override ODataPayloadElement VisitStreamReferenceValue(ODataStreamReferenceValue streamReferenceValue) { ExceptionUtilities.CheckArgumentNotNull(streamReferenceValue, "streamReferenceValue"); NamedStreamInstance namedStreamInstance = (NamedStreamInstance)base.VisitStreamReferenceValue(streamReferenceValue); AtomStreamReferenceMetadata streamMetadata = streamReferenceValue.GetAnnotation <AtomStreamReferenceMetadata>(); if (streamMetadata != null) { if (streamMetadata.EditLink != null) { AtomLinkMetadata editMetadata = streamMetadata.EditLink; namedStreamInstance.AtomNamedStreamLink(editMetadata.Href == null ? null : editMetadata.Href.OriginalString, editMetadata.Relation, editMetadata.MediaType, editMetadata.HrefLang, editMetadata.Title, ToString(editMetadata.Length)); } if (streamMetadata.SelfLink != null) { AtomLinkMetadata selfMetadata = streamMetadata.SelfLink; namedStreamInstance.AtomNamedStreamLink(selfMetadata.Href == null ? null : selfMetadata.Href.OriginalString, selfMetadata.Relation, selfMetadata.MediaType, selfMetadata.HrefLang, selfMetadata.Title, ToString(selfMetadata.Length)); } } return(namedStreamInstance); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(NamedStreamInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); ExceptionUtilities.CheckObjectNotNull(this.currentXElement, "Current XElement is not defined"); if (payloadElement.SourceLink != null) { XElement sourceLinkElement = CreateAtomLinkElement( this.currentXElement, ODataConstants.DataServicesMediaResourceNamespaceName + payloadElement.Name, payloadElement.SourceLink, payloadElement.SourceLinkContentType); PostProcessXElement(payloadElement, sourceLinkElement); } if (payloadElement.EditLink != null) { XElement editLinkElement = CreateAtomLinkElement( this.currentXElement, ODataConstants.DataServicesMediaResourceEditNamespaceName + payloadElement.Name, payloadElement.EditLink, payloadElement.EditLinkContentType, payloadElement.ETag); PostProcessXElement(payloadElement, editLinkElement); } }
/// <summary> /// Annotates the named stream with atom:link values for the 'source' link. /// </summary> /// <param name="namedStream">The named stream to annotate.</param> /// <param name="href">The value of the atom:link's href property</param> /// <param name="type">The value of the atom:link's type property</param> /// <param name="hrefLang">The optional value of the atom:link's hrefLang property</param> /// <param name="title">The optional value of the atom:link's title property</param> /// <param name="length">The optional value of the atom:link's length property</param> /// <returns>The named stream with the annotations applied.</returns> public static NamedStreamInstance AtomNamedStreamSourceLink(this NamedStreamInstance namedStream, string href, string type, string hrefLang = null, string title = null, string length = null) { ExceptionUtilities.CheckArgumentNotNull(namedStream, "namedStream"); string relation = TestAtomConstants.ODataStreamPropertyMediaResourceRelatedLinkRelationPrefix + namedStream.Name; return(namedStream.AtomNamedStreamLink(href, relation, type, hrefLang, title, length)); }
/// <summary> /// Visits a property item. /// </summary> /// <param name="property">The property to visit.</param> protected override ODataPayloadElement VisitProperty(ODataProperty property) { ExceptionUtilities.CheckArgumentNotNull(property, "property"); object value = property.Value; if (value == null) { return(new PrimitiveProperty() { Name = property.Name, Value = new PrimitiveValue(null, null) }); } else { ODataComplexValue complexValue = value as ODataComplexValue; if (complexValue != null) { return(new ComplexProperty(property.Name, (ComplexInstance)this.Visit(complexValue))); } else { ODataCollectionValue collectionValue = value as ODataCollectionValue; if (collectionValue != null) { ODataPayloadElementCollection collection = (ODataPayloadElementCollection)this.Visit(collectionValue); ComplexMultiValue complexCollection = collection as ComplexMultiValue; if (complexCollection != null) { return(new ComplexMultiValueProperty(property.Name, complexCollection)); } else { return(new PrimitiveMultiValueProperty(property.Name, (PrimitiveMultiValue)collection)); } } else { ODataStreamReferenceValue streamReferenceValue = value as ODataStreamReferenceValue; if (streamReferenceValue != null) { NamedStreamInstance namedStream = (NamedStreamInstance)this.Visit(streamReferenceValue); namedStream.Name = property.Name; return(namedStream); } else { return(new PrimitiveProperty() { Name = property.Name, Value = (PrimitiveValue)this.Visit(value) }); } } } } }
/// <summary> /// Visits the children of the given payload element and replaces it with a copy if any child changes /// </summary> /// <param name="payloadElement">The payload element to potentially replace</param> /// <returns>The original element or a copy to replace it with</returns> public virtual ODataPayloadElement Visit(NamedStreamInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); if (this.alwaysReplace) { return(payloadElement.ReplaceWith <NamedStreamInstance>(new NamedStreamInstance() { Name = payloadElement.Name, EditLink = payloadElement.EditLink, EditLinkContentType = payloadElement.EditLinkContentType, ETag = payloadElement.ETag, SourceLink = payloadElement.SourceLink, SourceLinkContentType = payloadElement.SourceLinkContentType })); } return(payloadElement); }
/// <summary> /// Generates all interesting reader payloads for the given <paramref name="streamReferencePayload"/>. /// </summary> /// <param name="streamReferencePayload">The stream reference value payload to use in the generated payloads.</param> /// <returns>All interesting reader payloads for the given <paramref name="streamReferencePayload"/>.</returns> /// <remarks> /// This method assumes that the <paramref name="streamReferencePayload"/> represents a single stream reference value (named stream). /// It will return the stream reference value as part of different entity payloads. /// </remarks> private IEnumerable <T> GenerateNamedStreamPayloads <T>(T streamReferencePayload) where T : PayloadTestDescriptor { this.Assert.IsNotNull(streamReferencePayload, "streamReferencePayload != null"); this.Assert.IsNotNull(streamReferencePayload.PayloadElement, "streamReferencePayload.PayloadElement != null"); NamedStreamInstance namedStreamInstance = streamReferencePayload.PayloadElement as NamedStreamInstance; this.Assert.IsNotNull(namedStreamInstance, "namedStreamInstance != null"); // return the named stream as the only property in an entity (not counting the required key property) yield return(streamReferencePayload.InEntity()); // return the named stream with some properties before and after it yield return(streamReferencePayload.InEntity(2, 2)); // return the named stream with many properties before and after it yield return(streamReferencePayload.InEntity(15, 15)); }
/// <summary> /// Computes the XmlTreeAnnotation for a stream property from the <see cref="NamedStreamAtomLinkMetadataAnnotation"/>. /// </summary> /// <param name="streampProperty">The stream property to compute the Xml annotation for.</param> /// <param name="relation">The relation of the link we are converting</param> /// <returns>The <see cref="XmlTreeAnnotation"/> for the link with the specified <paramref name="relation"/>.</returns> private XmlTreeAnnotation GetStreamPropertyLinkXmlTreeAnnotation(NamedStreamInstance streampProperty, string relation) { // Look it up again since it was created above. NamedStreamAtomLinkMetadataAnnotation linkAnnotation = streampProperty.Annotations.OfType <NamedStreamAtomLinkMetadataAnnotation>().SingleOrDefault(a => a.Relation == relation); if (linkAnnotation == null) { return(null); } List <XmlTreeAnnotation> attributes = new List <XmlTreeAnnotation>(); if (linkAnnotation.Href != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkHrefAttributeName, linkAnnotation.Href)); } if (linkAnnotation.HrefLang != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkHrefLangAttributeName, linkAnnotation.HrefLang)); } if (linkAnnotation.Length != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkLengthAttributeName, linkAnnotation.Length)); } if (linkAnnotation.Relation != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkRelationAttributeName, linkAnnotation.Relation)); } if (linkAnnotation.Title != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkTitleAttributeName, linkAnnotation.Title)); } if (linkAnnotation.Type != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkTypeAttributeName, linkAnnotation.Type)); } return(XmlTreeAnnotation.Atom(TestAtomConstants.AtomLinkElementName, null, attributes.ToArray())); }
/// <summary> /// Normalizes named stream specific atom metadata. /// </summary> /// <param name="payloadElement">The payload element to normalize.</param> public override void Visit(NamedStreamInstance payloadElement) { // Edit Link string editRelationValue = TestAtomConstants.ODataStreamPropertyEditMediaRelatedLinkRelationPrefix + payloadElement.Name; NamedStreamAtomLinkMetadataAnnotation editLinkAnnotation = payloadElement.Annotations.OfType <NamedStreamAtomLinkMetadataAnnotation>().SingleOrDefault(a => a.Relation == editRelationValue); NormalizeNamedStreamLinkValue( payloadElement, editLinkAnnotation, (annotation) => annotation.Href, (annotation, value) => annotation.Href = value, (namedStream) => namedStream.EditLink, (namedStream, value) => namedStream.EditLink = value); NormalizeNamedStreamLinkValue( payloadElement, editLinkAnnotation, (annotation) => annotation.Type, (annotation, value) => annotation.Type = value, (namedStream) => namedStream.EditLinkContentType, (namedStream, value) => namedStream.EditLinkContentType = value); // Source Link string sourceRelationValue = TestAtomConstants.ODataStreamPropertyMediaResourceRelatedLinkRelationPrefix + payloadElement.Name; NamedStreamAtomLinkMetadataAnnotation sourceLinkAnnotation = payloadElement.Annotations.OfType <NamedStreamAtomLinkMetadataAnnotation>().SingleOrDefault(a => a.Relation == sourceRelationValue); NormalizeNamedStreamLinkValue( payloadElement, sourceLinkAnnotation, (annotation) => annotation.Href, (annotation, value) => annotation.Href = value, (namedStream) => namedStream.SourceLink, (namedStream, value) => namedStream.SourceLink = value); NormalizeNamedStreamLinkValue( payloadElement, sourceLinkAnnotation, (annotation) => annotation.Type, (annotation, value) => annotation.Type = value, (namedStream) => namedStream.SourceLinkContentType, (namedStream, value) => namedStream.SourceLinkContentType = value); base.Visit(payloadElement); }
/// <summary> /// Visits a payload element whose root is a NamedStreamProperty. this will validate the content types and etags /// </summary> /// <param name="expected">The root node of payload element being visited.</param> public void Visit(NamedStreamInstance expected) { ExceptionUtilities.CheckArgumentNotNull(expected, "expected"); var observed = this.GetNextObservedElement <NamedStreamInstance>(); using (this.Assert.WithMessage("Named stream '{0}' did not match expectation", expected.Name)) { this.Assert.AreEqual(expected.Name, observed.Name, "Stream name did not match expectation"); if (this.comparingJsonLightResponse && expected.EditLink == null) { this.Assert.IsNotNull(observed.EditLink, "Conventional template evaluation should compute the EditLink."); } else { this.Assert.AreEqual(expected.EditLink, observed.EditLink, "Edit link did not match expectation"); } if (this.comparingJsonLightResponse && (expected.EditLinkContentType != null || expected.SourceLinkContentType != null)) { this.Assert.IsNotNull(observed.EditLinkContentType, "Conventional template evaluation should compute the edit link content type."); this.Assert.IsNotNull(observed.SourceLinkContentType, "Conventional template evaluation should compute the source link content type."); } else { this.Assert.AreEqual(expected.EditLinkContentType, observed.EditLinkContentType, "Edit link content type did not match expectation"); this.Assert.AreEqual(expected.SourceLinkContentType, observed.SourceLinkContentType, "Source link content type did not match expectation"); } this.Assert.AreEqual(expected.ETag, observed.ETag, "ETag did not match expectation"); if (this.comparingJsonLightResponse && expected.SourceLink == null) { this.Assert.IsNotNull(observed.SourceLink, "Conventional template evaluation should compute the SourceLink."); } else { this.Assert.AreEqual(expected.SourceLink, observed.SourceLink, "Source link did not match expectation"); } this.CompareAnnotations(expected.Annotations, observed.Annotations); } }
/// <summary> /// Annotates the named stream with atom:link values. /// </summary> /// <param name="namedStream">The named stream to annotate.</param> /// <param name="href">The value of the atom:link's href property</param> /// <param name="rel">The value of the atom:link's rel property</param> /// <param name="type">The value of the atom:link's type property</param> /// <param name="hrefLang">The optional value of the atom:link's hrefLang property</param> /// <param name="title">The optional value of the atom:link's title property</param> /// <param name="length">The optional value of the atom:link's length property</param> /// <returns>The named stream with the annotations applied.</returns> public static NamedStreamInstance AtomNamedStreamLink(this NamedStreamInstance namedStream, string href, string rel, string type, string hrefLang = null, string title = null, string length = null) { ExceptionUtilities.CheckArgumentNotNull(namedStream, "namedStream"); // The Test OM representation for Named Streams does not allow individual annotation of the two links that it represents. // Thus, we special case Named Streams, and apply two annotations to represent ATOM link metadata - one for serialization and one for comparison. // This annotation will replace the standard serialization of the NamedStreamInstance with the link XElement. var xmlAnnotation = namedStream.Annotations.OfType <XmlPayloadElementRepresentationAnnotation>().SingleOrDefault(); if (xmlAnnotation == null) { xmlAnnotation = new XmlPayloadElementRepresentationAnnotation { XmlNodes = new XNode[0] }; namedStream.AddAnnotation(xmlAnnotation); } XElement linkElement = new XElement(TestAtomConstants.AtomXNamespace.GetName(TestAtomConstants.AtomLinkElementName)); AddXAttribute(linkElement, TestAtomConstants.AtomLinkHrefAttributeName, href); AddXAttribute(linkElement, TestAtomConstants.AtomLinkRelationAttributeName, rel); AddXAttribute(linkElement, TestAtomConstants.AtomLinkTypeAttributeName, type); AddXAttribute(linkElement, TestAtomConstants.AtomLinkHrefLangAttributeName, hrefLang); AddXAttribute(linkElement, TestAtomConstants.AtomLinkTitleAttributeName, title); AddXAttribute(linkElement, TestAtomConstants.AtomLinkLengthAttributeName, length); xmlAnnotation.XmlNodes = xmlAnnotation.XmlNodes.Union(new[] { linkElement }).ToArray(); // This annotation captures the link metadata values for comparison with test result. namedStream.AddAnnotation( new NamedStreamAtomLinkMetadataAnnotation { Href = href, HrefLang = hrefLang, Length = length, Relation = rel, Title = title, Type = type, }); return(namedStream); }
/// <summary> /// Creates a new ODataStreamReferenceValue for the named stream and initializes it. /// </summary> /// <param name="payloadElement">The named stream to process.</param> public override void Visit(NamedStreamInstance payloadElement) { var odataNamedStream = new ODataStreamReferenceValue() { ETag = payloadElement.ETag, ContentType = payloadElement.EditLink == null ? payloadElement.SourceLinkContentType : payloadElement.EditLinkContentType, ReadLink = payloadElement.SourceLink == null ? null : new Uri(payloadElement.SourceLink), EditLink = payloadElement.EditLink == null ? null : new Uri(payloadElement.EditLink), }; var odataNamedStreamProperty = new ODataProperty() { Name = payloadElement.Name, Value = odataNamedStream }; this.currentProperties.Add(odataNamedStreamProperty); base.Visit(payloadElement); }
private bool TryGetNamedStream(JsonObject jsonObject, out ODataPayloadElement elem) { if (jsonObject.Properties.Count() == 1 && jsonObject.Properties.Single().Name == MediaResourceFieldName) { JsonProperty namedStreamProperty = jsonObject.Properties.Single(); NamedStreamInstance nsi = new NamedStreamInstance(namedStreamProperty.Name); JsonObject streamJsonObject = (JsonObject)namedStreamProperty.Value; var editLink = streamJsonObject.Properties.SingleOrDefault(a => a.Name.Equals(EditMediaFieldName)); if (editLink != null) { nsi.EditLink = (string)((JsonPrimitiveValue)editLink.Value).Value; } var sourceLink = streamJsonObject.Properties.SingleOrDefault(a => a.Name.Equals(MediaSrcFieldName)); if (sourceLink != null) { nsi.SourceLink = (string)((JsonPrimitiveValue)sourceLink.Value).Value; } var etag = streamJsonObject.Properties.SingleOrDefault(a => a.Name.Equals(MediaETagFieldName)); if (etag != null) { nsi.ETag = (string)((JsonPrimitiveValue)etag.Value).Value; } var contentType = streamJsonObject.Properties.SingleOrDefault(a => a.Name.Equals(ContentTypeFieldName)); if (contentType != null) { nsi.SourceLinkContentType = nsi.EditLinkContentType = (string)((JsonPrimitiveValue)contentType.Value).Value; } elem = nsi; return(true); } elem = null; return(false); }
/// <summary> /// Normalizes an named stream's Atom link property value between a NamedStreamAtomLinkMetadataAnnotation and another property. /// </summary> /// <param name="namedStream">The named stream to normalize.</param> /// <param name="annotation">The annotation to use for normalizing.</param> /// <param name="getAnnotationValue">Function for retrieving the annotation value for the link property.</param> /// <param name="setAnnotationValue">Delegate for setting the annotation value for the link property.</param> /// <param name="getPropertyValue">Function for retrieving the property value for the link property.</param> /// <param name="setPropertyValue">Delegate for setting the property value for the link property.</param> private void NormalizeNamedStreamLinkValue( NamedStreamInstance namedStream, NamedStreamAtomLinkMetadataAnnotation annotation, Func <NamedStreamAtomLinkMetadataAnnotation, string> getAnnotationValue, Action <NamedStreamAtomLinkMetadataAnnotation, string> setAnnotationValue, Func <NamedStreamInstance, string> getPropertyValue, Action <NamedStreamInstance, string> setPropertyValue) { string propertyValue = getPropertyValue(namedStream); if (propertyValue != null) { if (annotation != null) { string annotationValue = getAnnotationValue(annotation); if (annotationValue == null) { setAnnotationValue(annotation, propertyValue); } else { ExceptionUtilities.Assert(propertyValue == annotationValue, "Link '" + annotation.Relation + "' has different values : Property=" + propertyValue + ", Annotation=" + annotationValue); } } else { var newAnnotation = new NamedStreamAtomLinkMetadataAnnotation { Relation = annotation.Relation }; setAnnotationValue(newAnnotation, propertyValue); namedStream.Add(newAnnotation); } } else if (annotation != null) { setPropertyValue(namedStream, getAnnotationValue(annotation)); } }
/// <summary> /// Creates a new ODataStreamReferenceValue for the named stream and initializes it. /// </summary> /// <param name="payloadElement">The named stream to process.</param> public override void Visit(NamedStreamInstance payloadElement) { var odataNamedStream = new ODataStreamReferenceValue() { ETag = payloadElement.ETag, ContentType = payloadElement.EditLink == null ? payloadElement.SourceLinkContentType : payloadElement.EditLinkContentType, ReadLink = payloadElement.SourceLink == null ? null : new Uri(payloadElement.SourceLink), EditLink = payloadElement.EditLink == null ? null : new Uri(payloadElement.EditLink), }; var odataNamedStreamProperty = new ODataProperty() { Name = payloadElement.Name, Value = odataNamedStream }; var parent = this.items.Peek(); if (parent != null) { var entry = parent as ODataResource; if (entry != null) { var properties = (List <ODataProperty>)entry.Properties; properties.Add(odataNamedStreamProperty); } var complex = parent as ODataComplexValue; if (complex != null) { var properties = (List <ODataProperty>)complex.Properties; properties.Add(odataNamedStreamProperty); } } base.Visit(payloadElement); }
private IEnumerable <NamedStreamInstance> DeserializeNamedStreamProperties(IEnumerable <XElement> links) { // This is a bit complex, but the goal here is to take all the edit and source links for named streams // and produce representations without leaving any information out. So, if duplicate edit or source links // with the same name are present, we want to represent them *somehow* so that later verification can fail. // However, edit/source links with the same name should be combined based on the order in which they appear. // The algorithm for this is as follows: // Gather all source and edit links // For each link: // determine if it is an edit or source link // if there is not an un-matched source/edit link with the same name: // create a new instance and add it to the list of un-matched edit/source links // else // remove the link for the list of un-matched links, and update its properties // // find any media links and convert them into named stream properties var mediaLinks = links .Select(link => link.Attribute(Rel)) .Where(rel => rel != null) .Where(rel => rel.Value.StartsWith(ODataConstants.DataServicesMediaResourceEditNamespaceName, StringComparison.Ordinal) || rel.Value.StartsWith(ODataConstants.DataServicesMediaResourceNamespaceName, StringComparison.Ordinal)) .Select(rel => rel.Parent) .ToList(); // go through the links, generating named-stream-instances or updating instances created on earlier passes // when source/edit links can be combined List <NamedStreamInstance> results = new List <NamedStreamInstance>(mediaLinks.Count); var unmatchedEditLinks = new List <NamedStreamInstance>(); var unmatchedSourceLinks = new List <NamedStreamInstance>(); foreach (var mediaLink in mediaLinks) { var rel = mediaLink.Attribute(Rel).Value; string name; bool isEdit; List <NamedStreamInstance> possibleMatches; List <NamedStreamInstance> unmatchedList; // edit links should be matched with source links, and vice versa if (rel.StartsWith(ODataConstants.DataServicesMediaResourceEditNamespaceName, StringComparison.Ordinal)) { isEdit = true; name = rel.Substring(ODataConstants.DataServicesMediaResourceEditNamespaceName.Length); possibleMatches = unmatchedSourceLinks; unmatchedList = unmatchedEditLinks; } else { ExceptionUtilities.Assert(rel.StartsWith(ODataConstants.DataServicesMediaResourceNamespaceName, StringComparison.Ordinal), "Unexpected rel: {0}", rel); isEdit = false; name = rel.Substring(ODataConstants.DataServicesMediaResourceNamespaceName.Length); possibleMatches = unmatchedEditLinks; unmatchedList = unmatchedSourceLinks; } var namedStreamInstance = possibleMatches.FirstOrDefault(n => n.Name == name); if (namedStreamInstance == null) { namedStreamInstance = new NamedStreamInstance(name); results.Add(namedStreamInstance); unmatchedList.Add(namedStreamInstance); } else { possibleMatches.Remove(namedStreamInstance); } // get the media link href var href = mediaLink.Attribute(Href); if (href != null) { if (isEdit) { namedStreamInstance.EditLink = href.Value; } else { namedStreamInstance.SourceLink = href.Value; } } // get the media link type var type = mediaLink.Attribute(Type); if (type != null) { if (isEdit) { namedStreamInstance.EditLinkContentType = type.Value; } else { namedStreamInstance.SourceLinkContentType = type.Value; } } // get the media link etag var etag = mediaLink.Attribute(MetadataETag); if (etag != null) { namedStreamInstance.ETag = etag.Value; } } return(results); }
/// <summary> /// Visits an entry item. /// </summary> /// <param name="entry">The entry to visit.</param> protected override ODataPayloadElement VisitEntry(ODataResource entry) { ExceptionUtilities.CheckArgumentNotNull(entry, "entry"); EntityInstance entity = new EntityInstance(entry.TypeName, false); if (this.payloadContainsIdentityMetadata) { entity.Id = entry.Id == null ? null : entry.Id.OriginalString; if (entry.ReadLink != null) { entity.WithSelfLink(entry.ReadLink.OriginalString); } if (entry.EditLink != null) { entity.WithEditLink(entry.EditLink.OriginalString); } } if (this.payloadContainsEtagPropertiesForType(entry.TypeName)) { entity.ETag = entry.ETag; } ODataStreamReferenceValue mediaResource = entry.MediaResource; if (mediaResource != null) { entity = entity.AsMediaLinkEntry(); NamedStreamInstance namedStreamInstance = (NamedStreamInstance)this.Visit(mediaResource); entity.StreamETag = namedStreamInstance.ETag; entity.StreamSourceLink = namedStreamInstance.SourceLink; entity.StreamEditLink = namedStreamInstance.EditLink; entity.StreamContentType = namedStreamInstance.SourceLinkContentType ?? namedStreamInstance.EditLinkContentType; foreach (var namedStreamAtomLinkMetadataAnnotation in namedStreamInstance.Annotations.OfType <NamedStreamAtomLinkMetadataAnnotation>()) { entity.AddAnnotation(namedStreamAtomLinkMetadataAnnotation); } } // convert properties and navigation links entry.ProcessPropertiesPreservingPayloadOrder( property => entity.Add((PropertyInstance)this.Visit(property)), navigationLink => entity.Add((PropertyInstance)this.Visit(navigationLink))); var actions = entry.Actions; if (actions != null) { foreach (var operation in actions) { var serviceOperationDescriptor = this.Visit(operation) as ServiceOperationDescriptor; entity.Add(serviceOperationDescriptor); } } var functions = entry.Functions; if (functions != null) { foreach (var operation in functions) { var serviceOperationDescriptor = this.Visit(operation) as ServiceOperationDescriptor; entity.Add(serviceOperationDescriptor); } } this.ConvertSerializationTypeNameAnnotation(entry, entity); return(entity); }
/// <summary> /// Visits a payload element whose root is a NamedStreamProperty. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(NamedStreamInstance payloadElement) { throw new TaupoNotSupportedException("Json serialization does not allow element of type: " + payloadElement.ElementType.ToString()); }
/// <summary> /// Visits the payload element and determines the version of it /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(NamedStreamInstance payloadElement) { this.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4); }
public void EntryReadingBaseUriTest() { EdmModel model = (EdmModel)Microsoft.Test.OData.Utils.Metadata.TestModels.BuildTestModel(); model.Fixup(); Action <EntityInstance, Uri, ReaderTestConfiguration>[] setUriActions = new Action <EntityInstance, Uri, ReaderTestConfiguration>[] { // Setting the read link of an entry (instance, uri, testConfig) => { instance.SetAnnotation(new SelfLinkAnnotation(UriToString(uri))); }, // Setting the edit link of an entry (instance, uri, testConfig) => { instance.WithEditLink(UriToString(uri)); }, // Setting the navigation link of an entry (instance, uri, testConfig) => { NavigationPropertyInstance navProperty = instance.GetProperty("CityHall") as NavigationPropertyInstance; this.Assert.IsNotNull(navProperty, "Did not find expected navigation property 'CityHall'."); DeferredLink deferredLink = navProperty.Value as DeferredLink; this.Assert.IsNotNull(deferredLink, "Did not find expected deferred link."); deferredLink.UriString = UriToString(uri); }, // Setting the association link of an entry (instance, uri, testConfig) => { NavigationPropertyInstance navProperty = instance.GetProperty("CityHall") as NavigationPropertyInstance; this.Assert.IsNotNull(navProperty, "Did not find expected navigation property 'CityHall'."); DeferredLink deferredLink = navProperty.AssociationLink as DeferredLink; this.Assert.IsNotNull(deferredLink, "Did not find expected assocation link."); deferredLink.UriString = UriToString(uri); }, // Setting the read link of a stream property (instance, uri, testConfig) => { NamedStreamInstance namedStream = instance.GetProperty("Skyline") as NamedStreamInstance; this.Assert.IsNotNull(namedStream, "Did not find expected stream property 'Skyline'."); namedStream.SourceLink = UriToString(uri); }, // Setting the edit link of a stream property (instance, uri, testConfig) => { NamedStreamInstance namedStream = instance.GetProperty("Skyline") as NamedStreamInstance; this.Assert.IsNotNull(namedStream, "Did not find expected stream property 'Skyline'."); namedStream.EditLink = UriToString(uri); }, // Setting the read link of the default stream (instance, uri, testConfig) => { instance.StreamSourceLink = UriToString(uri); }, // Setting the edit link of the default stream (instance, uri, testConfig) => { instance.StreamEditLink = UriToString(uri); }, // TODO: add tests for operation links (not yet supported in the test infrastructure). }; EntityInstance entry = PayloadBuilder.Entity("TestModel.CityWithMapType") .PrimitiveProperty("Id", 1) .Property(PayloadBuilder.NavigationProperty("CityHall", /*url*/ "http://odata.org/dummy", /*associationUrl*/ "http://odata.org/dummy").IsCollection(true)) .StreamProperty("Skyline", "http://odata.org./dummy") .AsMediaLinkEntry() .StreamSourceLink("http://odata.org/dummy"); this.CombinatorialEngineProvider.RunCombinations( payloadUris, baseUriValues, resolvers, setUriActions, this.ReaderTestConfigurationProvider.AtomFormatConfigurations, (payloadUri, baseUriValue, resolver, setUriAction, testConfiguration) => { this.CombinatorialEngineProvider.RunCombinations( new bool[] { false, true }, runInBatch => { this.RunBaseUriReadingTest(entry, setUriAction, model, payloadUri, baseUriValue, resolver, testConfiguration, runInBatch); }); }); }
/// <summary> /// Creates a new ODataStreamReferenceValue for the named stream and initializes it. /// </summary> /// <param name="payloadElement">The named stream to process.</param> public override void Visit(NamedStreamInstance payloadElement) { var odataNamedStream = new ODataStreamReferenceValue() { ETag = payloadElement.ETag, ContentType = payloadElement.EditLink == null ? payloadElement.SourceLinkContentType : payloadElement.EditLinkContentType, ReadLink = payloadElement.SourceLink == null ? null : new Uri(payloadElement.SourceLink), EditLink = payloadElement.EditLink == null ? null : new Uri(payloadElement.EditLink), }; var odataNamedStreamProperty = new ODataProperty() { Name = payloadElement.Name, Value = odataNamedStream }; this.currentProperties.Add(odataNamedStreamProperty); base.Visit(payloadElement); }
/// <summary> /// Removes ATOM link metadata annotations from a <see cref="NamedStreamInstance"/>. /// </summary> /// <param name="payloadElement">The named stream instance to visit.</param> public override void Visit(NamedStreamInstance payloadElement) { payloadElement.RemoveAnnotations(typeof(NamedStreamAtomLinkMetadataAnnotation)); base.Visit(payloadElement); }
/// <summary> /// Removes ATOM link metadata annotations from a <see cref="NamedStreamInstance"/>. /// </summary> /// <param name="payloadElement">The named stream instance to visit.</param> public override void Visit(NamedStreamInstance payloadElement) { payloadElement.RemoveAnnotations(typeof(NamedStreamAtomLinkMetadataAnnotation)); base.Visit(payloadElement); }
private IEnumerable<NamedStreamInstance> DeserializeNamedStreamProperties(IEnumerable<XElement> links) { // This is a bit complex, but the goal here is to take all the edit and source links for named streams // and produce representations without leaving any information out. So, if duplicate edit or source links // with the same name are present, we want to represent them *somehow* so that later verification can fail. // However, edit/source links with the same name should be combined based on the order in which they appear. // The algorithm for this is as follows: // Gather all source and edit links // For each link: // determine if it is an edit or source link // if there is not an un-matched source/edit link with the same name: // create a new instance and add it to the list of un-matched edit/source links // else // remove the link for the list of un-matched links, and update its properties // // find any media links and convert them into named stream properties var mediaLinks = links .Select(link => link.Attribute(Rel)) .Where(rel => rel != null) .Where(rel => rel.Value.StartsWith(ODataConstants.DataServicesMediaResourceEditNamespaceName, StringComparison.Ordinal) || rel.Value.StartsWith(ODataConstants.DataServicesMediaResourceNamespaceName, StringComparison.Ordinal)) .Select(rel => rel.Parent) .ToList(); // go through the links, generating named-stream-instances or updating instances created on earlier passes // when source/edit links can be combined List<NamedStreamInstance> results = new List<NamedStreamInstance>(mediaLinks.Count); var unmatchedEditLinks = new List<NamedStreamInstance>(); var unmatchedSourceLinks = new List<NamedStreamInstance>(); foreach (var mediaLink in mediaLinks) { var rel = mediaLink.Attribute(Rel).Value; string name; bool isEdit; List<NamedStreamInstance> possibleMatches; List<NamedStreamInstance> unmatchedList; // edit links should be matched with source links, and vice versa if (rel.StartsWith(ODataConstants.DataServicesMediaResourceEditNamespaceName, StringComparison.Ordinal)) { isEdit = true; name = rel.Substring(ODataConstants.DataServicesMediaResourceEditNamespaceName.Length); possibleMatches = unmatchedSourceLinks; unmatchedList = unmatchedEditLinks; } else { ExceptionUtilities.Assert(rel.StartsWith(ODataConstants.DataServicesMediaResourceNamespaceName, StringComparison.Ordinal), "Unexpected rel: {0}", rel); isEdit = false; name = rel.Substring(ODataConstants.DataServicesMediaResourceNamespaceName.Length); possibleMatches = unmatchedEditLinks; unmatchedList = unmatchedSourceLinks; } var namedStreamInstance = possibleMatches.FirstOrDefault(n => n.Name == name); if (namedStreamInstance == null) { namedStreamInstance = new NamedStreamInstance(name); results.Add(namedStreamInstance); unmatchedList.Add(namedStreamInstance); } else { possibleMatches.Remove(namedStreamInstance); } // get the media link href var href = mediaLink.Attribute(Href); if (href != null) { if (isEdit) { namedStreamInstance.EditLink = href.Value; } else { namedStreamInstance.SourceLink = href.Value; } } // get the media link type var type = mediaLink.Attribute(Type); if (type != null) { if (isEdit) { namedStreamInstance.EditLinkContentType = type.Value; } else { namedStreamInstance.SourceLinkContentType = type.Value; } } // get the media link etag var etag = mediaLink.Attribute(MetadataETag); if (etag != null) { namedStreamInstance.ETag = etag.Value; } } return results; }
/// <summary> /// Visits the payload element and determines the version of it /// </summary> /// <param name="payloadElement">The payload element to visit</param> public override void Visit(NamedStreamInstance payloadElement) { this.IncreaseVersionIfRequired(DataServiceProtocolVersion.V4); }
/// <summary> /// Computes the XmlTreeAnnotation for a stream property from the <see cref="NamedStreamAtomLinkMetadataAnnotation"/>. /// </summary> /// <param name="streampProperty">The stream property to compute the Xml annotation for.</param> /// <param name="relation">The relation of the link we are converting</param> /// <returns>The <see cref="XmlTreeAnnotation"/> for the link with the specified <paramref name="relation"/>.</returns> private XmlTreeAnnotation GetStreamPropertyLinkXmlTreeAnnotation(NamedStreamInstance streampProperty, string relation) { // Look it up again since it was created above. NamedStreamAtomLinkMetadataAnnotation linkAnnotation = streampProperty.Annotations.OfType<NamedStreamAtomLinkMetadataAnnotation>().SingleOrDefault(a => a.Relation == relation); if (linkAnnotation == null) { return null; } List<XmlTreeAnnotation> attributes = new List<XmlTreeAnnotation>(); if (linkAnnotation.Href != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkHrefAttributeName, linkAnnotation.Href)); } if (linkAnnotation.HrefLang != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkHrefLangAttributeName, linkAnnotation.HrefLang)); } if (linkAnnotation.Length != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkLengthAttributeName, linkAnnotation.Length)); } if (linkAnnotation.Relation != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkRelationAttributeName, linkAnnotation.Relation)); } if (linkAnnotation.Title != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkTitleAttributeName, linkAnnotation.Title)); } if (linkAnnotation.Type != null) { attributes.Add(XmlTreeAnnotation.AtomAttribute(TestAtomConstants.AtomLinkTypeAttributeName, linkAnnotation.Type)); } return XmlTreeAnnotation.Atom(TestAtomConstants.AtomLinkElementName, null, attributes.ToArray()); }
/// <summary> /// Creates a new ODataStreamReferenceValue for the named stream and initializes it. /// </summary> /// <param name="payloadElement">The named stream to process.</param> public override void Visit(NamedStreamInstance payloadElement) { var odataNamedStream = new ODataStreamReferenceValue() { ETag = payloadElement.ETag, ContentType = payloadElement.EditLink == null ? payloadElement.SourceLinkContentType : payloadElement.EditLinkContentType, ReadLink = payloadElement.SourceLink == null ? null : new Uri(payloadElement.SourceLink), EditLink = payloadElement.EditLink == null ? null : new Uri(payloadElement.EditLink), }; var odataNamedStreamProperty = new ODataProperty() { Name = payloadElement.Name, Value = odataNamedStream }; var parent = this.items.Peek(); if (parent != null) { var entry = parent as ODataEntry; if (entry != null) { var properties = (List<ODataProperty>)entry.Properties; properties.Add(odataNamedStreamProperty); } var complex = parent as ODataComplexValue; if (complex != null) { var properties = (List<ODataProperty>)complex.Properties; properties.Add(odataNamedStreamProperty); } } base.Visit(payloadElement); }
/// <summary> /// Visits the payload element /// </summary> /// <param name="payloadElement">The payload element to visit</param> public virtual void Visit(NamedStreamInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); }
/// <summary> /// Asserts that two payload elements are equal. /// </summary> /// <param name="expected">The expected element</param> /// <param name="observed">The actual, observed element</param> public void Compare(ODataPayloadElement expected, ODataPayloadElement observed) { if (expected == null) { this.Assert.IsNull(observed, "Observed element must be null"); return; } this.Assert.AreEqual(expected.ElementType, observed.ElementType, "Element types are not equal."); this.Assert.AreEqual(expected.Annotations.Count, observed.Annotations.Count, "Annotation counts are not equal"); Compare(expected.Annotations, observed.Annotations); switch (expected.ElementType) { case ODataPayloadElementType.EntitySetInstance: EntitySetInstance expectedSet = expected as EntitySetInstance; EntitySetInstance observedSet = observed as EntitySetInstance; this.Assert.AreEqual(expectedSet.NextLink, observedSet.NextLink, "Next links are not equal"); this.Assert.AreEqual(expectedSet.InlineCount, observedSet.InlineCount, "Inline counts are not equal"); this.Assert.AreEqual(expectedSet.Count, observedSet.Count, "Entity counts are not equal"); for (int i = 0; i < expectedSet.Count; i++) { Compare(expectedSet[i], observedSet[i]); } break; case ODataPayloadElementType.EntityInstance: EntityInstance expectedEntity = expected as EntityInstance; EntityInstance observedEntity = observed as EntityInstance; this.Assert.AreEqual(expectedEntity.Id, observedEntity.Id, "Entity IDs are not equal"); this.Assert.AreEqual(expectedEntity.ETag, observedEntity.ETag, "ETags are not equal"); this.Assert.AreEqual(expectedEntity.IsNull, observedEntity.IsNull, "IsNull flags are not equal"); this.Assert.AreEqual(expectedEntity.FullTypeName, observedEntity.FullTypeName, "FullTypeNames are not equal"); this.Assert.AreEqual(expectedEntity.StreamContentType, observedEntity.StreamContentType, "Stream content types are not equal"); this.Assert.AreEqual(expectedEntity.StreamEditLink, observedEntity.StreamEditLink, "Stream edit links are not equal"); this.Assert.AreEqual(expectedEntity.StreamETag, observedEntity.StreamETag, "Stream ETags are not equal"); this.Assert.AreEqual(expectedEntity.StreamSourceLink, observedEntity.StreamSourceLink, "Stream source links are not equal"); this.Assert.AreEqual(expectedEntity.Properties.Count(), observedEntity.Properties.Count(), "Property counts are not equal"); for (int i = 0; i < expectedEntity.Properties.Count(); i++) { Compare(expectedEntity.Properties.ElementAt(i), observedEntity.Properties.ElementAt(i)); } break; case ODataPayloadElementType.ComplexInstance: ComplexInstance expectedCI = expected as ComplexInstance; ComplexInstance observedCI = observed as ComplexInstance; this.Assert.AreEqual(expectedCI.IsNull, observedCI.IsNull, "IsNull flags are not equal"); this.Assert.AreEqual(expectedCI.FullTypeName, observedCI.FullTypeName, "Full type names are not equal"); this.Assert.AreEqual(expectedCI.Properties.Count(), observedCI.Properties.Count(), "Property counts are not equal"); for (int i = 0; i < expectedCI.Properties.Count(); i++) { Compare(expectedCI.Properties.ElementAt(i), observedCI.Properties.ElementAt(i)); } break; case ODataPayloadElementType.NamedStreamInstance: NamedStreamInstance expectedNsi = expected as NamedStreamInstance; NamedStreamInstance observedNsi = observed as NamedStreamInstance; this.Assert.AreEqual(expectedNsi.Name, observedNsi.Name, "Stream names are not equal"); this.Assert.AreEqual(expectedNsi.ETag, observedNsi.ETag, "Stream ETags are not equal"); this.Assert.AreEqual(expectedNsi.EditLink, observedNsi.EditLink, "Edit links are not equal"); this.Assert.AreEqual(expectedNsi.EditLinkContentType, observedNsi.EditLinkContentType, "Edit link content types are not equal"); this.Assert.AreEqual(expectedNsi.SourceLink, observedNsi.SourceLink, "Source links are not equal"); this.Assert.AreEqual(expectedNsi.SourceLinkContentType, observedNsi.SourceLinkContentType, "Source links content types are not equal"); break; case ODataPayloadElementType.NavigationPropertyInstance: NavigationPropertyInstance expectedNav = expected as NavigationPropertyInstance; NavigationPropertyInstance observedNav = observed as NavigationPropertyInstance; Assert.AreEqual(expectedNav.Name, observedNav.Name, "Navigation property names are not equal"); Compare(expectedNav.AssociationLink, observedNav.AssociationLink); Compare(expectedNav.Value, observedNav.Value); break; case ODataPayloadElementType.ComplexProperty: ComplexProperty expectedCP = expected as ComplexProperty; ComplexProperty observedCP = observed as ComplexProperty; this.Assert.AreEqual(expectedCP.Name, observedCP.Name, "Complex property names are not equal"); Compare(expectedCP.Value, observedCP.Value); break; case ODataPayloadElementType.PrimitiveProperty: PrimitiveProperty expectedProperty = expected as PrimitiveProperty; PrimitiveProperty observedProperty = observed as PrimitiveProperty; this.Assert.AreEqual(expectedProperty.Name, observedProperty.Name, "Primitive property names are not equal"); Compare(expectedProperty.Value, observedProperty.Value); break; case ODataPayloadElementType.PrimitiveValue: PrimitiveValue expectedValue = expected as PrimitiveValue; PrimitiveValue observedValue = observed as PrimitiveValue; this.Assert.AreEqual(expectedValue.IsNull, observedValue.IsNull, "IsNull flags are not equal"); if (expectedValue.FullTypeName != null) { if (expectedValue.FullTypeName.Equals("Edm.String")) { this.Assert.IsTrue(string.IsNullOrEmpty(observedValue.FullTypeName) || observedValue.FullTypeName.Equals("Edm.String"), "FullTypeName should be null or Edm.String"); } else { this.Assert.AreEqual(expectedValue.FullTypeName, observedValue.FullTypeName, "Full type names are not equal"); } } else { this.Assert.IsNull(observedValue.FullTypeName, "observed full type name should be null"); } this.Assert.AreEqual(expectedValue.ClrValue, observedValue.ClrValue, "Clr values are not equal"); break; case ODataPayloadElementType.DeferredLink: DeferredLink expectedLink = expected as DeferredLink; DeferredLink observedLink = observed as DeferredLink; this.Assert.AreEqual(expectedLink.UriString, observedLink.UriString, "Uris are not equal"); break; case ODataPayloadElementType.ExpandedLink: ExpandedLink expectedExpand = expected as ExpandedLink; ExpandedLink observedExpand = observed as ExpandedLink; Compare(expectedExpand.ExpandedElement, observedExpand.ExpandedElement); break; case ODataPayloadElementType.LinkCollection: LinkCollection expectedLinks = expected as LinkCollection; LinkCollection observedLinks = observed as LinkCollection; this.Assert.AreEqual(expectedLinks.Count, observedLinks.Count, "Link counts are not equal"); this.Assert.AreEqual(expectedLinks.InlineCount, observedLinks.InlineCount, "Link inline counts are not equal"); for (int i = 0; i < expectedLinks.Count; i++) { Compare(expectedLinks[i], observedLinks[i]); } break; case ODataPayloadElementType.PrimitiveMultiValueProperty: var expectedPrimitiveCollectionProperty = expected as PrimitiveMultiValueProperty; var observedPrimitiveCollectionProperty = observed as PrimitiveMultiValueProperty; this.Assert.AreEqual(expectedPrimitiveCollectionProperty.Name, observedPrimitiveCollectionProperty.Name, "Property names are not equal"); this.Assert.AreEqual(expectedPrimitiveCollectionProperty.Value.FullTypeName, observedPrimitiveCollectionProperty.Value.FullTypeName, "Full type names are not equal"); this.Assert.AreEqual(expectedPrimitiveCollectionProperty.Value.Count, observedPrimitiveCollectionProperty.Value.Count, "Collection counts are not equal"); for (int i = 0; i < expectedPrimitiveCollectionProperty.Value.Count; i++) { Compare(expectedPrimitiveCollectionProperty.Value[i], observedPrimitiveCollectionProperty.Value[i]); } break; case ODataPayloadElementType.ComplexMultiValueProperty: var expectedComplexCollectionProperty = expected as ComplexMultiValueProperty; var observedComplexCollectionProperty = observed as ComplexMultiValueProperty; this.Assert.AreEqual(expectedComplexCollectionProperty.Name, observedComplexCollectionProperty.Name, "Property names are not equal"); this.Assert.AreEqual(expectedComplexCollectionProperty.Value.FullTypeName, observedComplexCollectionProperty.Value.FullTypeName, "Full type names are not equal"); this.Assert.AreEqual(expectedComplexCollectionProperty.Value.Count, observedComplexCollectionProperty.Value.Count, "Collection counts are not equal"); for (int i = 0; i < expectedComplexCollectionProperty.Value.Count; i++) { Compare(expectedComplexCollectionProperty.Value[i], observedComplexCollectionProperty.Value[i]); } break; case ODataPayloadElementType.PrimitiveCollection: var expectedPrimitiveCollection = expected as PrimitiveCollection; var observedPrimitiveCollection = observed as PrimitiveCollection; this.Assert.AreEqual(expectedPrimitiveCollection.Count, observedPrimitiveCollection.Count, "Collection counts are not equal"); for (int i = 0; i < expectedPrimitiveCollection.Count; i++) { Compare(expectedPrimitiveCollection[i], observedPrimitiveCollection[i]); } break; case ODataPayloadElementType.ComplexInstanceCollection: var expectedComplexCollection = expected as ComplexInstanceCollection; var observedComplexCollection = observed as ComplexInstanceCollection; this.Assert.AreEqual(expectedComplexCollection.Count, observedComplexCollection.Count, "Collection counts are not equal"); for (int i = 0; i < expectedComplexCollection.Count; i++) { Compare(expectedComplexCollection[i], observedComplexCollection[i]); } break; case ODataPayloadElementType.NullPropertyInstance: case ODataPayloadElementType.EmptyUntypedCollection: break; default: this.Assert.Fail("Case " + expected.ElementType + " unhandled"); break; } }
/// <summary> /// Creates a set of interesting entity instances along with metadata. /// </summary> /// <param name="settings">The test descriptor settings to use.</param> /// <param name="model">If non-null, the method creates complex types for the complex values and adds them to the model.</param> /// <param name="withTypeNames">true if the payloads should specify type names.</param> /// <returns>List of test descriptors with interesting entity instances as payload.</returns> public static IEnumerable <PayloadTestDescriptor> CreateEntityInstanceTestDescriptors( EdmModel model, bool withTypeNames) { IEnumerable <PrimitiveValue> primitiveValues = TestValues.CreatePrimitiveValuesWithMetadata(fullSet: false); IEnumerable <ComplexInstance> complexValues = TestValues.CreateComplexValues(model, withTypeNames, fullSet: false); IEnumerable <NamedStreamInstance> streamReferenceValues = TestValues.CreateStreamReferenceValues(fullSet: false); IEnumerable <PrimitiveMultiValue> primitiveMultiValues = TestValues.CreatePrimitiveCollections(withTypeNames, fullSet: false); IEnumerable <ComplexMultiValue> complexMultiValues = TestValues.CreateComplexCollections(model, withTypeNames, fullSet: false); IEnumerable <NavigationPropertyInstance> navigationProperties = TestValues.CreateDeferredNavigationLinks(); // NOTE we have to copy the EntityModelTypeAnnotation on the primitive value to the NullPropertyInstance for null values since the // NullPropertyInstance does not expose a value. We will later copy it back to the value we generate for the null property. IEnumerable <PropertyInstance> primitiveProperties = primitiveValues.Select((pv, ix) => PayloadBuilder.Property("PrimitiveProperty" + ix, pv).CopyAnnotation <PropertyInstance, EntityModelTypeAnnotation>(pv)); IEnumerable <PropertyInstance> complexProperties = complexValues.Select((cv, ix) => PayloadBuilder.Property("ComplexProperty" + ix, cv)); IEnumerable <PropertyInstance> primitiveMultiValueProperties = primitiveMultiValues.Select((pmv, ix) => PayloadBuilder.Property("PrimitiveMultiValueProperty" + ix, pmv)); IEnumerable <PropertyInstance> complexMultiValueProperties = complexMultiValues.Select((cmv, ix) => PayloadBuilder.Property("ComplexMultiValueProperty" + ix, cmv)); PropertyInstance[][] propertyMatrix = new PropertyInstance[6][]; propertyMatrix[0] = primitiveProperties.ToArray(); propertyMatrix[1] = complexProperties.ToArray(); propertyMatrix[2] = streamReferenceValues.ToArray(); propertyMatrix[3] = primitiveMultiValueProperties.ToArray(); propertyMatrix[4] = complexMultiValueProperties.ToArray(); propertyMatrix[5] = navigationProperties.ToArray(); IEnumerable <PropertyInstance[]> propertyCombinations = propertyMatrix.ColumnCombinations(0, 1, 6); int count = 0; foreach (PropertyInstance[] propertyCombination in propertyCombinations) { // build the entity type, add it to the model EdmEntityType generatedEntityType = null; string typeName = "PGEntityType" + count; EdmEntityContainer container = null; EdmEntitySet entitySet = null; if (model != null) { // generate a new type with the auto-generated name, check that no type with this name exists and add the default key property to it. Debug.Assert(model.FindDeclaredType(typeName) == null, "Entity type '" + typeName + "' already exists."); generatedEntityType = new EdmEntityType("TestModel", typeName); generatedEntityType.AddKeys(generatedEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32)); model.AddElement(generatedEntityType); container = model.EntityContainer as EdmEntityContainer; if (container == null) { container = new EdmEntityContainer("TestModel", "DefaultNamespace"); model.AddElement(container); } entitySet = container.AddEntitySet(typeName, generatedEntityType); } EntityInstance entityInstance = PayloadBuilder.Entity("TestModel." + typeName) .Property("Id", PayloadBuilder.PrimitiveValue(count).WithTypeAnnotation(EdmCoreModel.Instance.GetInt32(false))); for (int i = 0; i < propertyCombination.Length; ++i) { PropertyInstance currentProperty = propertyCombination[i]; entityInstance.Add(currentProperty); if (model != null) { if (entitySet == null) { entitySet = container.FindEntitySet(typeName) as EdmEntitySet; } switch (currentProperty.ElementType) { case ODataPayloadElementType.ComplexProperty: ComplexProperty complexProperty = (ComplexProperty)currentProperty; generatedEntityType.AddStructuralProperty(complexProperty.Name, complexProperty.Value.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType); break; case ODataPayloadElementType.PrimitiveProperty: PrimitiveProperty primitiveProperty = (PrimitiveProperty)currentProperty; if (primitiveProperty.Value == null) { generatedEntityType.AddStructuralProperty( primitiveProperty.Name, PayloadBuilder.PrimitiveValueType(null)); } else { generatedEntityType.AddStructuralProperty(primitiveProperty.Name, primitiveProperty.Value.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType); } break; case ODataPayloadElementType.NamedStreamInstance: NamedStreamInstance streamProperty = (NamedStreamInstance)currentProperty; generatedEntityType.AddStructuralProperty(streamProperty.Name, EdmPrimitiveTypeKind.Stream); break; case ODataPayloadElementType.EmptyCollectionProperty: throw new NotImplementedException(); case ODataPayloadElementType.NavigationPropertyInstance: NavigationPropertyInstance navigationProperty = (NavigationPropertyInstance)currentProperty; var navProperty = generatedEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo() { ContainsTarget = false, Name = navigationProperty.Name, Target = generatedEntityType, TargetMultiplicity = EdmMultiplicity.One }); entitySet.AddNavigationTarget(navProperty, entitySet); break; case ODataPayloadElementType.ComplexMultiValueProperty: ComplexMultiValueProperty complexMultiValueProperty = (ComplexMultiValueProperty)currentProperty; generatedEntityType.AddStructuralProperty(complexMultiValueProperty.Name, complexMultiValueProperty.Value.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType); break; case ODataPayloadElementType.PrimitiveMultiValueProperty: PrimitiveMultiValueProperty primitiveMultiValueProperty = (PrimitiveMultiValueProperty)currentProperty; generatedEntityType.AddStructuralProperty(primitiveMultiValueProperty.Name, primitiveMultiValueProperty.Value.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType); break; default: throw new NotSupportedException("Unsupported element type found : " + propertyCombination[i].ElementType); } } } if (generatedEntityType != null) { entityInstance.AddAnnotation(new EntityModelTypeAnnotation(generatedEntityType.ToTypeReference(true))); } yield return(new PayloadTestDescriptor() { PayloadElement = entityInstance, PayloadEdmModel = model }); count++; } }
/// <summary> /// Converts the given name/value pair into a property element. /// And infers the type of property from the converted value. /// </summary> /// <param name="jsonProperty">the property value</param> /// <returns>the converted property</returns> private PropertyInstance ConvertProperty(JsonProperty jsonProperty) { if (jsonProperty.Value.JsonType == JsonValueType.JsonPrimitiveValue && ((JsonPrimitiveValue)jsonProperty.Value).Value == null) { return(new NullPropertyInstance() { Name = jsonProperty.Name }); } else { ODataPayloadElement elem = this.ConvertValue(jsonProperty.Value); ExceptionUtilities.CheckObjectNotNull(elem, "Converted property value was null"); if (elem.ElementType == ODataPayloadElementType.PrimitiveValue) { return(new PrimitiveProperty(jsonProperty.Name, (PrimitiveValue)elem)); } else if (elem.ElementType == ODataPayloadElementType.ComplexInstance) { return(new ComplexProperty(jsonProperty.Name, (ComplexInstance)elem)); } else if (elem.ElementType == ODataPayloadElementType.EntityInstance) { return(new NavigationPropertyInstance(jsonProperty.Name, new ExpandedLink(elem))); } else if (elem.ElementType == ODataPayloadElementType.DeferredLink) { DeferredLink deferredLink = (DeferredLink)elem; return(new NavigationPropertyInstance(jsonProperty.Name, deferredLink)); } else if (elem.ElementType == ODataPayloadElementType.EntitySetInstance) { return(new NavigationPropertyInstance(jsonProperty.Name, elem)); } else if (elem.ElementType == ODataPayloadElementType.ComplexMultiValue) { ComplexMultiValue complexMultiValue = (ComplexMultiValue)elem; return(new ComplexMultiValueProperty(jsonProperty.Name, complexMultiValue)); } else if (elem.ElementType == ODataPayloadElementType.PrimitiveMultiValue) { PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)elem; return(new PrimitiveMultiValueProperty(jsonProperty.Name, primitiveMultiValue)); } else if (elem.ElementType == ODataPayloadElementType.ComplexInstanceCollection) { ComplexInstanceCollection complexCollection = (ComplexInstanceCollection)elem; return(new ComplexMultiValueProperty(jsonProperty.Name, new ComplexMultiValue(null, false, complexCollection.ToArray()))); } else if (elem.ElementType == ODataPayloadElementType.PrimitiveCollection) { PrimitiveCollection primitiveCollection = (PrimitiveCollection)elem; return(new PrimitiveMultiValueProperty(jsonProperty.Name, new PrimitiveMultiValue(null, false, primitiveCollection.ToArray()))); } else if (elem.ElementType == ODataPayloadElementType.NamedStreamInstance) { NamedStreamInstance nsi = (NamedStreamInstance)elem; nsi.Name = jsonProperty.Name; return(nsi); } else { ExceptionUtilities.Assert(elem.ElementType == ODataPayloadElementType.EmptyUntypedCollection, "Do not know how to handle element of type" + elem.ElementType); return(new EmptyCollectionProperty(jsonProperty.Name, (EmptyUntypedCollection)elem)); } } }
/// <summary> /// Visits a payload element whose root is a NamedStreamProperty. /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(NamedStreamInstance payloadElement) { throw new TaupoNotSupportedException("Json serialization does not allow element of type: " + payloadElement.ElementType.ToString()); }
/// <summary> /// Visits a payload element whose root is a NamedStreamProperty. this will validate the content types and etags /// </summary> /// <param name="payloadElement">The root node of payload element being visited.</param> public void Visit(NamedStreamInstance payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); var current = this.expectedValueStack.Peek(); var queryStreamValue = current as AstoriaQueryStreamValue; ExceptionUtilities.CheckObjectNotNull(queryStreamValue, "Value was not a stream. Value was: '{0}'", current.ToString()); using (this.parent.Assert.WithMessage("Named stream '{0}' did not match expectation", payloadElement.Name)) { this.CompareStreamETag(queryStreamValue, payloadElement.ETag); if (this.parent.ExpectedPayloadOptions.HasFlag(ODataPayloadOptions.IncludeSelfOrEditLink)) { this.parent.Assert.IsFalse(payloadElement.EditLink == null && payloadElement.SourceLink == null, "At least one link (self/edit) should be present in the response payload"); } if (payloadElement.EditLink != null) { this.CompareUri(queryStreamValue.EditLink, payloadElement.EditLink, "Edit link did not match"); this.parent.Assert.AreEqual(queryStreamValue.ContentType, payloadElement.EditLinkContentType, "Edit link content-type did not match"); } if (payloadElement.SourceLink != null) { if (!this.parent.ExpectedPayloadOptions.HasFlag(ODataPayloadOptions.ConventionallyProducedNamedStreamSelfLink)) { this.CompareUri(queryStreamValue.SelfLink, payloadElement.SourceLink, "Self link did not match"); this.parent.Assert.AreEqual(queryStreamValue.ContentType, payloadElement.SourceLinkContentType, "Self link content-type did not match"); } } } }