/// <summary> /// Returns the entity set for the given payload element (only for entries and feeds). /// </summary> /// <param name="expectedTypeAnnotation">The expected type annotation.</param> /// <param name="model">The model to get the type from.</param> /// <param name="payloadElement">The payload element to get the expected type for.</param> /// <returns>The expected type for the specified payload element.</returns> private static IEdmEntitySet GetExpectedEntitySet(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model, ODataPayloadElement payloadElement) { ExceptionUtilities.Assert(model != null, "model != null"); ExceptionUtilities.Assert(payloadElement != null, "payloadElement != null"); if (payloadElement.GetAnnotation <IgnoreEntitySetAnnotation>() != null) { // Entity set information is explicitly ignored return(null); } if (expectedTypeAnnotation != null) { if (expectedTypeAnnotation.EdmEntitySet != null) { return(expectedTypeAnnotation.EdmEntitySet); } EntitySet entitySet = expectedTypeAnnotation.EntitySet; if (entitySet != null) { return(model.EntityContainersAcrossModels().Select(m => m.FindEntitySet(entitySet.Name)).FirstOrDefault(s => s != null)); } } EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>(); if (typeAnnotation != null) { var edmEntityType = typeAnnotation.EdmModelType; return(model.EntityContainersAcrossModels().First().EntitySets().SingleOrDefault(es => es.EntityType().FullName() == edmEntityType.FullName())); } return(null); }
/// <summary> /// Returns the type from the entity model type annotation for this payload element. /// </summary> /// <param name="payloadElement">The payload element to return the type for.</param> /// <returns>The type from the annotation or null if none was present.</returns> private static IEdmTypeReference GetEdmTypeFromEntityModelTypeAnnotation(ODataPayloadElement payloadElement) { Debug.Assert(payloadElement != null, "payloadElement != null"); EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>(); return(typeAnnotation == null ? null : typeAnnotation.EdmModelType); }
private void ReplaceExpectedTypeAnnotationIfRootElement(ODataPayloadElement payloadElement) { if (this.payloadElementStack.Count == 2) { var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>(); if (expectedTypeAnnotation != null) { payloadElement.WithContextUri(JsonLightODataPayloadElementExtensions.BuildContextUri(payloadElement.ElementType, JsonLightConstants.DefaultMetadataDocumentUri.OriginalString, expectedTypeAnnotation)); payloadElement.RemoveAnnotations(typeof(ExpectedTypeODataPayloadElementAnnotation)); } } }
/// <summary> /// Gets or adds the expected type annotation. /// </summary> /// <param name="payloadElement">The payload element to get or add the annotation to.</param> /// <returns>The expected type annotation to use.</returns> public static ExpectedTypeODataPayloadElementAnnotation AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement) { Debug.Assert(payloadElement != null, "payloadElement != null"); var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>(); if (expectedTypeAnnotation == null) { expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation(); payloadElement.SetAnnotation(expectedTypeAnnotation); } return(expectedTypeAnnotation); }
/// <summary> /// Gets or adds the expected type annotation. /// </summary> /// <param name="payloadElement">The payload element to get or add the annotation to.</param> /// <returns>The expected type annotation to use.</returns> public static ExpectedTypeODataPayloadElementAnnotation AddExpectedTypeAnnotation(this ODataPayloadElement payloadElement, IEdmType expectedType) { Debug.Assert(payloadElement != null, "payloadElement != null"); var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>(); if (expectedTypeAnnotation == null) { expectedTypeAnnotation = new ExpectedTypeODataPayloadElementAnnotation(); payloadElement.SetAnnotation(expectedTypeAnnotation); } expectedTypeAnnotation.EdmExpectedType = expectedType.ToTypeReference(); return(expectedTypeAnnotation); }
/// <summary> /// Gets the custom content type header for the payload element (if specified). /// </summary> /// <param name="payloadElement">The payload element to get the custom content type header for.</param> /// <returns>The custom content types header or null if none is specified.</returns> public static string GetCustomContentTypeHeader(this ODataPayloadElement payloadElement) { if (payloadElement == null) { return(null); } CustomContentTypeHeaderAnnotation contentTypeAnnotation = payloadElement.GetAnnotation <CustomContentTypeHeaderAnnotation>(); if (contentTypeAnnotation != null) { return(contentTypeAnnotation.ContentType); } BatchBoundaryAnnotation batchBoundaryAnnotation = payloadElement.GetAnnotation <BatchBoundaryAnnotation>(); if (batchBoundaryAnnotation != null) { Debug.Assert(batchBoundaryAnnotation.BatchBoundaryInHeader != null, "If an annotation is found the boundary must not be null."); return(MimeTypes.MultipartMixed + "; boundary=" + batchBoundaryAnnotation.BatchBoundaryInHeader); } return(null); }
/// <summary> /// Annotates the <paramref name="payloadElement"/> with the format version if it's not already annotated. /// </summary> /// <param name="payloadElement">The payload element to annotate.</param> private void AddVersionAnnotation(ODataPayloadElement payloadElement) { PayloadFormatVersionAnnotation versionAnnotation = (PayloadFormatVersionAnnotation)payloadElement.GetAnnotation(typeof(PayloadFormatVersionAnnotation)); if (versionAnnotation == null) { versionAnnotation = new PayloadFormatVersionAnnotation() { Version = this.version, Response = !this.requestPayload, }; payloadElement.AddAnnotation(versionAnnotation); } }
/// <summary> /// Gets the <see cref="EntityType"/> of the specified entry or feed payload element. /// </summary> /// <param name="payloadElement">The payload element to get the entity type for.</param> /// <param name="model">The model to find the entity type in.</param> /// <returns>The <see cref="EntityType"/> of the <paramref name="payloadElement"/>.</returns> public static IEdmEntityType GetPayloadElementEntityType(ODataPayloadElement payloadElement, IEdmModel model) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); ExceptionUtilities.CheckArgumentNotNull(model, "model"); ODataPayloadKind payloadKind = payloadElement.GetPayloadKindFromPayloadElement(); ExceptionUtilities.Assert( payloadKind == ODataPayloadKind.Resource || payloadKind == ODataPayloadKind.ResourceSet, "Can only determine entity type for entry or feed payloads."); EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>(); if (typeAnnotation != null) { var entityDataType = typeAnnotation.EdmModelType; Debug.Assert(entityDataType != null, "entityDataType != null"); return(model.EntityTypes().Single(et => et.FullName() == entityDataType.FullName())); } string entityTypeName; if (payloadKind == ODataPayloadKind.Resource) { EntityInstance entity = payloadElement as EntityInstance; Debug.Assert(entity != null, "entity != null"); entityTypeName = entity.FullTypeName; return(model.EntityTypes().Single(et => et.TestFullName() == entityTypeName)); } else { //if feed has entries figure out type otherwise use first entity type EntitySetInstance feed = payloadElement as EntitySetInstance; Debug.Assert(feed != null, "feed != null"); if (feed.Count > 0) { return(model.EntityTypes().Single(et => et.TestFullName() == ((TypedValue)feed.First()).FullTypeName)); } else { return(model.EntityTypes().First()); } } }
public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName) { bool omitDeclaration = false; SerializationEncodingNameAnnotation encodingNameAnnotation = (SerializationEncodingNameAnnotation)rootElement.GetAnnotation(typeof(SerializationEncodingNameAnnotation)); if (encodingNameAnnotation != null) { encodingName = encodingNameAnnotation.EncodingName; omitDeclaration = encodingNameAnnotation.OmitDeclaration; } var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); XDocument document = new XDocument(this.payloadElementConverter.ConvertToXml(rootElement)); if (!omitDeclaration) { document.Declaration = new XDeclaration("1.0", encoding.WebName, "yes"); } // settings taken from server XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = encoding; settings.OmitXmlDeclaration = omitDeclaration; settings.Indent = true; settings.NewLineHandling = NewLineHandling.Entitize; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (MemoryStream stream = new MemoryStream()) { using (XmlWriter writer = XmlWriter.Create(stream, settings)) { document.Save(writer); writer.Flush(); return stream.ToArray(); } } }
private void ReplaceExpectedTypeAnnotationIfRootElement(ODataPayloadElement payloadElement) { if (this.payloadElementStack.Count == 2) { var expectedTypeAnnotation = payloadElement.GetAnnotation<ExpectedTypeODataPayloadElementAnnotation>(); if (expectedTypeAnnotation != null) { payloadElement.WithContextUri(JsonLightODataPayloadElementExtensions.BuildContextUri(payloadElement.ElementType, JsonLightConstants.DefaultMetadataDocumentUri.OriginalString, expectedTypeAnnotation)); payloadElement.RemoveAnnotations(typeof(ExpectedTypeODataPayloadElementAnnotation)); } } }
/// <summary> /// Constructor /// </summary> /// <param name="model">The model used to resolve the metadata.</param> /// <param name="payloadElement">The payload element to get the reader metadata for.</param> public ReaderMetadata(IEdmModel model, ODataPayloadElement payloadElement) { var expectedTypeAnnotation = payloadElement.GetAnnotation <ExpectedTypeODataPayloadElementAnnotation>(); // NOTE: we don't require a model for the computation of the expected type (since the expected one might be a primitive type). this.expectedType = GetExpectedType(expectedTypeAnnotation, model); // We need a model for all the other expected reader metadata if (model == null) { // If the annotation specified some model dependent data (basically anything but primitive expected type) // and we don't have a model, we wouldn't be able to correctly represent it here (since we need the model to resolve these) // and thus we should not pass in the expected type alone, as that would be changing the intent of the annotation. if (expectedTypeAnnotation != null && (expectedTypeAnnotation.EntitySet != null || expectedTypeAnnotation.EdmEntitySet != null || expectedTypeAnnotation.FunctionImport != null || expectedTypeAnnotation.ProductFunctionImport != null || expectedTypeAnnotation.MemberProperty != null || expectedTypeAnnotation.EdmProperty != null || expectedTypeAnnotation.NavigationProperty != null || expectedTypeAnnotation.EdmNavigationProperty != null || expectedTypeAnnotation.OpenMemberPropertyName != null || expectedTypeAnnotation.OwningType != null || expectedTypeAnnotation.EdmOwningType != null)) { this.expectedType = null; } return; } ODataPayloadElementType elementType = payloadElement.ElementType; switch (elementType) { case ODataPayloadElementType.EntityInstance: // fall through case ODataPayloadElementType.EntitySetInstance: this.entitySet = GetExpectedEntitySet(expectedTypeAnnotation, model, payloadElement); break; case ODataPayloadElementType.DeferredLink: // fall through case ODataPayloadElementType.LinkCollection: this.navigationProperty = GetExpectedNavigationProperty(expectedTypeAnnotation, model); break; case ODataPayloadElementType.PrimitiveMultiValueProperty: // fall through case ODataPayloadElementType.PrimitiveProperty: // fall through case ODataPayloadElementType.ComplexProperty: // fall through case ODataPayloadElementType.ComplexMultiValueProperty: // fall through case ODataPayloadElementType.EmptyCollectionProperty: this.structuralProperty = GetExpectedStructuralProperty(expectedTypeAnnotation, model); this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; case ODataPayloadElementType.ComplexInstanceCollection: // fall through case ODataPayloadElementType.PrimitiveCollection: // fall through case ODataPayloadElementType.EmptyUntypedCollection: this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; case ODataPayloadElementType.ComplexInstance: // NOTE: this is how we model parameter payloads this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; } }
public void EntryPayloadOrderTest() { IEnumerable <PayloadReaderTestDescriptor> testDescriptors = new[] { // Nothing new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity() .XmlRepresentation("<entry></entry>") .PayloadOrderItems("__StartEntry__") }, // Just type name after nav. link - type name should be reported first. new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity("MyType").NavigationProperty("Category", "http://odata.org/Category") .XmlRepresentation( "<entry>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" + "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" + "</entry>") .PayloadOrderItems( "TypeName", "__StartEntry__", "NavigationLink_Category") }, // Type name properties and other things after link - type name and etag should be reported first, the rest after the link new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity("MyType") .ETag("bar") .NavigationProperty("Category", "http://odata.org/Category") .WithSelfLink("http://odata.org") .PrimitiveProperty("Name", "Foo") .XmlRepresentation( "<entry m:etag='bar'>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" + "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" + "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" + "<link rel='self' href='http://odata.org'/>" + "</entry>") .PayloadOrderItems( "TypeName", "ETag", "__StartEntry__", "NavigationLink_Category", "ReadLink", "Property_Name"), // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't SkipTestConfiguration = config => config.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesServer }, // Everything before nav. link new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity("MyType") .ETag("bar") .PrimitiveProperty("Name", "Foo") .NavigationProperty("Category", "http://odata.org/Category") .WithSelfLink("http://odata.org") .OperationDescriptor(new ServiceOperationDescriptor() { IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action" }) .OperationDescriptor(new ServiceOperationDescriptor() { IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function" }) .XmlRepresentation( "<entry m:etag='bar'>" + "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" + "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" + "<link rel='self' href='http://odata.org'/>" + "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" + "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" + "</entry>") .PayloadOrderItems( "TypeName", "ReadLink", "ETag", "Action_/actionMetadata", "Function_/functionMetadata", "Property_Name", "__StartEntry__", "NavigationLink_Category"), // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't SkipTestConfiguration = config => config.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest }, // Everything before nav. link - Server behavior - server ignores most of links new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity("MyType") .ETag("bar") .PrimitiveProperty("Name", "Foo") .NavigationProperty("Category", "http://odata.org/Category") .OperationDescriptor(new ServiceOperationDescriptor() { IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action" }) .OperationDescriptor(new ServiceOperationDescriptor() { IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function" }) .XmlRepresentation( "<entry m:etag='bar'>" + "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" + "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" + "<link rel='self' href='http://odata.org'/>" + "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" + "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" + "</entry>") .PayloadOrderItems( "TypeName", "ETag", "Action_/actionMetadata", "Function_/functionMetadata", "Property_Name", "__StartEntry__", "NavigationLink_Category"), SkipTestConfiguration = config => config.RunBehaviorKind != TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest }, // Everything between nav. links new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity("MyType") .ETag("bar") .NavigationProperty("Order", "http://odata.org/Order") .PrimitiveProperty("Name", "Foo") .NavigationProperty("Category", "http://odata.org/Category") .WithSelfLink("http://odata.org") .OperationDescriptor(new ServiceOperationDescriptor() { IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action" }) .OperationDescriptor(new ServiceOperationDescriptor() { IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function" }) .XmlRepresentation( "<entry m:etag='bar'>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Order' type='application/atom+xml;type=entry' href='http://odata.org/Order'/>" + "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" + "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" + "<link rel='self' href='http://odata.org'/>" + "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" + "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" + "</entry>") .PayloadOrderItems( "TypeName", "ETag", "__StartEntry__", "NavigationLink_Order", "ReadLink", "Action_/actionMetadata", "Function_/functionMetadata", "Property_Name", "NavigationLink_Category"), // [Astoria-ODataLib-Integration] Parsing of URLs on OData recognized places may fail, but Astoria server doesn't SkipTestConfiguration = config => config.RunBehaviorKind == TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest }, // Everything between nav. links - server behavior new PayloadReaderTestDescriptor(this.Settings) { PayloadElement = PayloadBuilder.Entity("MyType") .ETag("bar") .NavigationProperty("Order", "http://odata.org/Order") .PrimitiveProperty("Name", "Foo") .NavigationProperty("Category", "http://odata.org/Category") .OperationDescriptor(new ServiceOperationDescriptor() { IsAction = true, Metadata = "/actionMetadata", Target = "http://odata.org/action" }) .OperationDescriptor(new ServiceOperationDescriptor() { IsFunction = true, Metadata = "/functionMetadata", Target = "http://odata.org/function" }) .XmlRepresentation( "<entry m:etag='bar'>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Order' type='application/atom+xml;type=entry' href='http://odata.org/Order'/>" + "<category term='MyType' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" + "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" + "<link rel='self' href='http://odata.org'/>" + "<m:action metadata='/actionMetadata' target='http://odata.org/action'/>" + "<m:function metadata='/functionMetadata' target='http://odata.org/function'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/relatedlinks/PoliceStation' href='http://odata.org/associationlink' type='application/xml'/>" + "<link rel='http://docs.oasis-open.org/odata/ns/related/Category' type='application/atom+xml;type=entry' href='http://odata.org/Category'/>" + "</entry>") .PayloadOrderItems( "TypeName", "ETag", "__StartEntry__", "NavigationLink_Order", "Action_/actionMetadata", "Function_/functionMetadata", "Property_Name", "NavigationLink_Category"), SkipTestConfiguration = config => config.RunBehaviorKind != TestODataBehaviorKind.WcfDataServicesServer || config.IsRequest }, // EPM //new PayloadReaderTestDescriptor(this.Settings) //{ // PayloadElement = PayloadBuilder.Entity("TestModel.EpmEntity") // .NavigationProperty("Order", "http://odata.org/Order") // .PrimitiveProperty("Name", "Foo") // .NavigationProperty("Orders", "http://odata.org/Orders") // .PrimitiveProperty("Description", "Bart") // .XmlRepresentation( // "<entry>" + // "<link rel='http://docs.oasis-open.org/odata/ns/related/Order' type='application/atom+xml;type=entry' href='http://odata.org/Order'/>" + // "<category term='TestModel.EpmEntity' scheme='http://docs.oasis-open.org/odata/ns/scheme'/>" + // "<content type='application/xml'><m:properties><d:Name>Foo</d:Name></m:properties></content>" + // "<link rel='http://docs.oasis-open.org/odata/ns/related/Orders' type='application/atom+xml;type=feed' href='http://odata.org/Orders'/>" + // "<author><name>Bart</name></author>" + // "</entry>") // .PayloadOrderItems( // "TypeName", // "__StartEntry__", // "NavigationLink_Order", // "Property_Name", // "NavigationLink_Orders", // "Property_Description"), // PayloadModel = model //} }; this.CombinatorialEngineProvider.RunCombinations( testDescriptors, this.ReaderTestConfigurationProvider.AtomFormatConfigurations, TestReaderUtils.ODataBehaviorKinds, (testDescriptor, testConfiguration, behavior) => { // In WCF DS Server mode the reader reports the StartEntry as soon as it finds a type name. // Since the ETag is always on the start element it will be reported in StartEntry as well. if (behavior == TestODataBehaviorKind.WcfDataServicesServer) { ODataPayloadElement element = testDescriptor.PayloadElement.DeepCopy(); PayloadOrderODataPayloadElementAnnotation payloadOrderAnnotation = element.GetAnnotation <PayloadOrderODataPayloadElementAnnotation>(); int startEntryPosition = 0; if (payloadOrderAnnotation.PayloadItems[0] == "TypeName") { startEntryPosition++; } if (payloadOrderAnnotation.PayloadItems.Contains("ETag")) { payloadOrderAnnotation.PayloadItems.Remove("ETag"); payloadOrderAnnotation.PayloadItems.Insert(1, "ETag"); startEntryPosition++; } payloadOrderAnnotation.PayloadItems.Remove("__StartEntry__"); payloadOrderAnnotation.PayloadItems.Insert(startEntryPosition, "__StartEntry__"); testDescriptor = new PayloadReaderTestDescriptor(testDescriptor) { PayloadElement = element }; } // We must remove any payload normalizers since we are now supersensitive to ordering issues in this test. testDescriptor.ExpectedResultNormalizers.Clear(); testDescriptor.RunTest(testConfiguration.CloneAndApplyBehavior(behavior)); }); }
/// <summary> /// Returns annotation of a payload element. /// </summary> /// <typeparam name="T">The type of the annotation to get.</typeparam> /// <param name="payloadElement">The payload element to get the annotation from.</param> /// <returns>The annotation or null if none was found.</returns> public static T GetAnnotation <T>(this ODataPayloadElement payloadElement) where T : ODataPayloadElementAnnotation { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); return((T)payloadElement.GetAnnotation(typeof(T))); }
/// <summary> /// Builds a complex instance from the given payloadElements to represent a parameters payload. /// </summary> /// <param name="payloadElements">Each ODataPayloadElement represents the value for each parameter.</param> /// <param name="model">EdmModel instance.</param> /// <param name="functionImportName">Name of the function import to add to the model.</param> /// <returns></returns> private static ComplexInstance PayloadElementsToParameterPayload(ODataPayloadElement[] payloadElements, EdmModel model, string functionImportName) { EdmOperationImport operationImport = (EdmOperationImport)model.EntityContainer.FindOperationImports(functionImportName).FirstOrDefault(); EdmOperation operation = (EdmOperation)operationImport.Operation; var parameterPayload = new ComplexInstance(null, false); for (int idx = 0; idx < payloadElements.Length; idx++) { ODataPayloadElement p = payloadElements[idx]; string parameterName = "p" + idx; PropertyInstance parameter; IEdmTypeReference entityModelType = p.GetAnnotation <EntityModelTypeAnnotation>().EdmModelType; switch (p.ElementType) { case ODataPayloadElementType.PrimitiveValue: object clrValue = ((PrimitiveValue)p).ClrValue; PrimitiveValue primitiveValue = new PrimitiveValue(clrValue == null ? null : clrValue.GetType().FullName, clrValue); primitiveValue.CopyAnnotation <PrimitiveValue, EntityModelTypeAnnotation>(p); parameter = new PrimitiveProperty(parameterName, primitiveValue); operation.AddParameter(parameterName, MetadataUtils.GetPrimitiveTypeReference(primitiveValue.ClrValue.GetType())); break; case ODataPayloadElementType.ComplexInstance: parameter = new ComplexProperty(parameterName, (ComplexInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.PrimitiveMultiValue: PrimitiveMultiValue primitiveMultiValue = (PrimitiveMultiValue)p; if (primitiveMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { primitiveMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new PrimitiveMultiValueProperty(parameterName, primitiveMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.ComplexMultiValue: ComplexMultiValue complexMultiValue = (ComplexMultiValue)p; if (complexMultiValue.Annotations.OfType <JsonCollectionResultWrapperAnnotation>().SingleOrDefault() == null) { complexMultiValue.Annotations.Add(new JsonCollectionResultWrapperAnnotation(false)); } parameter = new ComplexMultiValueProperty(parameterName, complexMultiValue); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntityInstance: parameter = new NavigationPropertyInstance(parameterName, (EntityInstance)p); operation.AddParameter(parameterName, entityModelType); break; case ODataPayloadElementType.EntitySetInstance: parameter = new NavigationPropertyInstance(parameterName, (EntitySetInstance)p); operation.AddParameter(parameterName, entityModelType); break; default: throw new NotSupportedException("PayloadElementsToParameterPayload() is called on unsupported ODataPayloadElement type: " + p.ElementType); } parameterPayload.Add(parameter); } parameterPayload.ExpectedFunctionImport(operationImport); return(parameterPayload); }
/// <summary> /// Returns the entity set for the given payload element (only for entries and feeds). /// </summary> /// <param name="expectedTypeAnnotation">The expected type annotation.</param> /// <param name="model">The model to get the type from.</param> /// <param name="payloadElement">The payload element to get the expected type for.</param> /// <returns>The expected type for the specified payload element.</returns> private static IEdmEntitySet GetExpectedEntitySet(ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation, IEdmModel model, ODataPayloadElement payloadElement) { ExceptionUtilities.Assert(model != null, "model != null"); ExceptionUtilities.Assert(payloadElement != null, "payloadElement != null"); if (payloadElement.GetAnnotation<IgnoreEntitySetAnnotation>() != null) { // Entity set information is explicitly ignored return null; } if (expectedTypeAnnotation != null) { if (expectedTypeAnnotation.EdmEntitySet != null) { return expectedTypeAnnotation.EdmEntitySet; } EntitySet entitySet = expectedTypeAnnotation.EntitySet; if (entitySet != null) { return model.EntityContainersAcrossModels().Select(m => m.FindEntitySet(entitySet.Name)).FirstOrDefault(s => s != null); } } EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation<EntityModelTypeAnnotation>(); if (typeAnnotation != null) { var edmEntityType = typeAnnotation.EdmModelType; return model.EntityContainersAcrossModels().First().EntitySets().SingleOrDefault(es => es.EntityType().FullName() == edmEntityType.FullName()); } return null; }
/// <summary> /// Constructor /// </summary> /// <param name="model">The model used to resolve the metadata.</param> /// <param name="payloadElement">The payload element to get the reader metadata for.</param> public ReaderMetadata(IEdmModel model, ODataPayloadElement payloadElement) { var expectedTypeAnnotation = payloadElement.GetAnnotation<ExpectedTypeODataPayloadElementAnnotation>(); // NOTE: we don't require a model for the computation of the expected type (since the expected one might be a primitive type). this.expectedType = GetExpectedType(expectedTypeAnnotation, model); // We need a model for all the other expected reader metadata if (model == null) { // If the annotation specified some model dependent data (basically anything but primitive expected type) // and we don't have a model, we wouldn't be able to correctly represent it here (since we need the model to resolve these) // and thus we should not pass in the expected type alone, as that would be changing the intent of the annotation. if (expectedTypeAnnotation != null && (expectedTypeAnnotation.EntitySet != null || expectedTypeAnnotation.EdmEntitySet != null || expectedTypeAnnotation.FunctionImport != null || expectedTypeAnnotation.ProductFunctionImport != null || expectedTypeAnnotation.MemberProperty != null || expectedTypeAnnotation.EdmProperty != null || expectedTypeAnnotation.NavigationProperty != null || expectedTypeAnnotation.EdmNavigationProperty != null || expectedTypeAnnotation.OpenMemberPropertyName != null || expectedTypeAnnotation.OwningType != null || expectedTypeAnnotation.EdmOwningType != null)) { this.expectedType = null; } return; } ODataPayloadElementType elementType = payloadElement.ElementType; switch (elementType) { case ODataPayloadElementType.EntityInstance: // fall through case ODataPayloadElementType.EntitySetInstance: this.entitySet = GetExpectedEntitySet(expectedTypeAnnotation, model, payloadElement); break; case ODataPayloadElementType.DeferredLink: // fall through case ODataPayloadElementType.LinkCollection: this.navigationProperty = GetExpectedNavigationProperty(expectedTypeAnnotation, model); break; case ODataPayloadElementType.PrimitiveMultiValueProperty: // fall through case ODataPayloadElementType.PrimitiveProperty: // fall through case ODataPayloadElementType.ComplexProperty: // fall through case ODataPayloadElementType.ComplexMultiValueProperty: // fall through case ODataPayloadElementType.EmptyCollectionProperty: this.structuralProperty = GetExpectedStructuralProperty(expectedTypeAnnotation, model); this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; case ODataPayloadElementType.ComplexInstanceCollection: // fall through case ODataPayloadElementType.PrimitiveCollection: // fall through case ODataPayloadElementType.EmptyUntypedCollection: this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; case ODataPayloadElementType.ComplexInstance: // NOTE: this is how we model parameter payloads this.functionImport = GetExpectedFunctionImport(expectedTypeAnnotation, model); break; } }
/// <summary> /// Gets the context URI for the specified ODataPayloadElement. /// </summary> /// <param name="payloadElement">The annotated payload element to get the context URI for.</param> /// <returns>The context URI from the annotated payload element or null if no context URI annotation exists.</returns> /// <remarks>If not context URI annotation is found on the <paramref name="payloadElement"/>, this /// method will try to compute the context URI from the expected type annotation. If successful, /// it will cache the computed context URI as annotation on the payload element.</remarks> public static string ContextUri(this ODataPayloadElement payloadElement) { ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement"); JsonLightContextUriAnnotation contextUriAnnotation = (JsonLightContextUriAnnotation)payloadElement.GetAnnotation(typeof(JsonLightContextUriAnnotation)); string contextUri = null; bool cacheContextUri = false; // If an explicit context URI exists, return it if (contextUriAnnotation != null) { contextUri = contextUriAnnotation.ContextUri; } else { // Otherwise construct a context URI from the expected type annotation ExpectedTypeODataPayloadElementAnnotation expectedTypeAnnotation = (ExpectedTypeODataPayloadElementAnnotation)payloadElement.GetAnnotation(typeof(ExpectedTypeODataPayloadElementAnnotation)); if (expectedTypeAnnotation != null) { // Construct a context URI from the exptected type annotation JsonLightMetadataDocumentUriAnnotation metadataDocumentUriAnnotation = (JsonLightMetadataDocumentUriAnnotation)payloadElement.GetAnnotation(typeof(JsonLightMetadataDocumentUriAnnotation)); string metadataDocumentUri = metadataDocumentUriAnnotation == null ? JsonLightConstants.DefaultMetadataDocumentUri.AbsoluteUri : metadataDocumentUriAnnotation.MetadataDocumentUri; string projectionString = null; JsonLightContextUriProjectionAnnotation contextUriProjectionAnnotation = (JsonLightContextUriProjectionAnnotation)payloadElement.GetAnnotation(typeof(JsonLightContextUriProjectionAnnotation)); if (contextUriProjectionAnnotation != null) { // If we have a context URI projection, apply it to the context URI if the context URI does not already have one. projectionString = contextUriProjectionAnnotation.ContextUriProjection; Regex contextUriSelectExpandPattern = new Regex(@"(?:(?<!#Collection))\(.*\)"); // A 'null' projection string means that all properties should be projected. if (projectionString != null) { bool hasProjection = contextUriSelectExpandPattern.IsMatch(projectionString); if (!hasProjection) { // Inject the projection string into the context URI projectionString = JsonLightConstants.ContextUriProjectionStart + projectionString + JsonLightConstants.ContextUriProjectionEnd; } } } contextUri = BuildContextUri(payloadElement.ElementType, metadataDocumentUri, expectedTypeAnnotation, projectionString); cacheContextUri = true; } } // Cache the computed context URI on the payload element (non-comparable annotation) if (cacheContextUri) { payloadElement.WithContextUri(contextUri); payloadElement.RemoveAnnotations(typeof(JsonLightContextUriProjectionAnnotation)); } return(contextUri); }
public byte[] SerializeToBinary(ODataPayloadElement rootElement, string encodingName) { bool omitDeclaration = false; SerializationEncodingNameAnnotation encodingNameAnnotation = (SerializationEncodingNameAnnotation)rootElement.GetAnnotation(typeof(SerializationEncodingNameAnnotation)); if (encodingNameAnnotation != null) { encodingName = encodingNameAnnotation.EncodingName; omitDeclaration = encodingNameAnnotation.OmitDeclaration; } var encoding = HttpUtilities.GetEncodingOrDefault(encodingName); XDocument document = new XDocument(this.payloadElementConverter.ConvertToXml(rootElement)); if (!omitDeclaration) { document.Declaration = new XDeclaration("1.0", encoding.WebName, "yes"); } // settings taken from server XmlWriterSettings settings = new XmlWriterSettings(); settings.Encoding = encoding; settings.OmitXmlDeclaration = omitDeclaration; settings.Indent = true; settings.NewLineHandling = NewLineHandling.Entitize; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (MemoryStream stream = new MemoryStream()) { using (XmlWriter writer = XmlWriter.Create(stream, settings)) { document.Save(writer); writer.Flush(); return(stream.ToArray()); } } }
/// <summary> /// Annotates the <paramref name="payloadElement"/> with the format version if it's not already annotated. /// </summary> /// <param name="payloadElement">The payload element to annotate.</param> private void AddVersionAnnotation(ODataPayloadElement payloadElement) { PayloadFormatVersionAnnotation versionAnnotation = (PayloadFormatVersionAnnotation)payloadElement.GetAnnotation(typeof(PayloadFormatVersionAnnotation)); if (versionAnnotation == null) { versionAnnotation = new PayloadFormatVersionAnnotation() { Version = this.version, Response = !this.requestPayload, }; payloadElement.AddAnnotation(versionAnnotation); } }
/// <summary> /// Determins the payload kind appropriate for the payload element used for this test. /// </summary> /// <param name="payloadElement">The payload element to get the kind for.</param> /// <returns>The payload kind to be used for this test.</returns> public static ODataPayloadKind GetPayloadKindFromPayloadElement(this ODataPayloadElement payloadElement) { if (payloadElement == null) { return(ODataPayloadKind.Unsupported); } switch (payloadElement.ElementType) { case ODataPayloadElementType.NullPropertyInstance: case ODataPayloadElementType.PrimitiveProperty: case ODataPayloadElementType.PrimitiveMultiValueProperty: case ODataPayloadElementType.NamedStreamInstance: case ODataPayloadElementType.NavigationPropertyInstance: return(ODataPayloadKind.Property); case ODataPayloadElementType.ComplexMultiValueProperty: case ODataPayloadElementType.EntitySetInstance: return(ODataPayloadKind.ResourceSet); case ODataPayloadElementType.ComplexProperty: case ODataPayloadElementType.EntityInstance: return(ODataPayloadKind.Resource); case ODataPayloadElementType.PrimitiveCollection: case ODataPayloadElementType.ComplexInstanceCollection: case ODataPayloadElementType.PrimitiveMultiValue: case ODataPayloadElementType.ComplexMultiValue: return(ODataPayloadKind.Collection); case ODataPayloadElementType.ODataErrorPayload: return(ODataPayloadKind.Error); case ODataPayloadElementType.DeferredLink: return(ODataPayloadKind.EntityReferenceLink); case ODataPayloadElementType.LinkCollection: return(ODataPayloadKind.EntityReferenceLinks); case ODataPayloadElementType.ServiceDocumentInstance: return(ODataPayloadKind.ServiceDocument); case ODataPayloadElementType.PrimitiveValue: EntityModelTypeAnnotation typeAnnotation = payloadElement.GetAnnotation <EntityModelTypeAnnotation>(); if (typeAnnotation != null && ((IEdmPrimitiveType)typeAnnotation.EdmModelType.Definition).PrimitiveKind == EdmPrimitiveTypeKind.Binary) { return(ODataPayloadKind.BinaryValue); } return(ODataPayloadKind.Value); case ODataPayloadElementType.BatchRequestPayload: case ODataPayloadElementType.BatchResponsePayload: return(ODataPayloadKind.Batch); case ODataPayloadElementType.ComplexInstance: // TODO: ODataLib test item: Add new ODataPayloadElement for parameters payload return(ODataPayloadKind.Parameter); default: ExceptionUtilities.Assert( false, "Payload element type '{0}' is not yet recognized by GetPayloadKindFromPayloadElement.", payloadElement.ElementType); return(ODataPayloadKind.Unsupported); } }