diff --git a/src/Microsoft.OData.Core/ODataMetadataJsonOutputContext.cs b/src/Microsoft.OData.Core/ODataMetadataJsonOutputContext.cs
index f5370f058a..235fdca4d9 100644
--- a/src/Microsoft.OData.Core/ODataMetadataJsonOutputContext.cs
+++ b/src/Microsoft.OData.Core/ODataMetadataJsonOutputContext.cs
@@ -89,16 +89,12 @@ internal Task FlushAsync()
///
/// A task representing the asynchronous operation of writing the metadata document.
/// It is the responsibility of this method to flush the output before the task finishes.
- internal override Task WriteMetadataDocumentAsync()
+ internal override async Task WriteMetadataDocumentAsync()
{
this.AssertAsynchronous();
- return TaskUtils.GetTaskForSynchronousOperationReturningTask(
- () =>
- {
- this.WriteMetadataDocumentImplementation();
- return this.FlushAsync();
- });
+ await this.WriteMetadataDocumentImplementationAsync().ConfigureAwait(false);
+ await this.FlushAsync().ConfigureAwait(false);
}
///
@@ -259,6 +255,28 @@ private void WriteMetadataDocumentImplementation()
}
}
+ private async Task WriteMetadataDocumentImplementationAsync()
+ {
+ var writerSettings = new CsdlJsonWriterSettings
+ {
+ IsIeee754Compatible = MessageWriterSettings.IsIeee754Compatible,
+ };
+
+ var (success, errors) = await CsdlWriter.TryWriteCsdlAsync(this.Model, this.jsonWriter, writerSettings).ConfigureAwait(false);
+ if (!success)
+ {
+ Debug.Assert(errors != null, "errors != null");
+
+ StringBuilder builder = new StringBuilder();
+ foreach (EdmError error in errors)
+ {
+ builder.AppendLine(error.ToString());
+ }
+
+ throw new ODataException(Strings.ODataMetadataOutputContext_ErrorWritingMetadata(builder.ToString()));
+ }
+ }
+
private async Task DisposeOutputStreamAsync()
{
await this.asynchronousOutputStream.FlushAsync().ConfigureAwait(false);
diff --git a/src/Microsoft.OData.Core/ODataMetadataOutputContext.cs b/src/Microsoft.OData.Core/ODataMetadataOutputContext.cs
index f0fc2a2d46..f63cae5b7a 100644
--- a/src/Microsoft.OData.Core/ODataMetadataOutputContext.cs
+++ b/src/Microsoft.OData.Core/ODataMetadataOutputContext.cs
@@ -118,16 +118,12 @@ internal override Task WriteInStreamErrorAsync(ODataError error, bool includeDeb
///
/// A task representing the asynchronous operation of writing the metadata document.
/// It is the responsibility of this method to flush the output before the task finishes.
- internal override Task WriteMetadataDocumentAsync()
+ internal override async Task WriteMetadataDocumentAsync()
{
this.AssertAsynchronous();
- return TaskUtils.GetTaskForSynchronousOperationReturningTask(
- () =>
- {
- this.WriteMetadataDocumentImplementation();
- return this.FlushAsync();
- });
+ await this.WriteMetadataDocumentImplementationAsync().ConfigureAwait(false);
+ await this.FlushAsync().ConfigureAwait(false);
}
///
@@ -289,5 +285,29 @@ private void WriteMetadataDocumentImplementation()
throw new ODataException(Strings.ODataMetadataOutputContext_ErrorWritingMetadata(builder.ToString()));
}
}
+
+ private async Task WriteMetadataDocumentImplementationAsync()
+ {
+ CsdlXmlWriterSettings writerSettings = new CsdlXmlWriterSettings();
+
+ if (this.MessageWriterSettings.LibraryCompatibility.HasFlag(ODataLibraryCompatibility.UseLegacyVariableCasing))
+ {
+ writerSettings.LibraryCompatibility |= EdmLibraryCompatibility.UseLegacyVariableCasing;
+ }
+
+ var (success, errors) = await CsdlWriter.TryWriteCsdlAsync(this.Model, this.xmlWriter, CsdlTarget.OData, writerSettings).ConfigureAwait(false);
+ if (!success)
+ {
+ Debug.Assert(errors != null, "errors != null");
+
+ StringBuilder builder = new StringBuilder();
+ foreach (EdmError error in errors)
+ {
+ builder.AppendLine(error.ToString());
+ }
+
+ throw new ODataException(Strings.ODataMetadataOutputContext_ErrorWritingMetadata(builder.ToString()));
+ }
+ }
}
}
diff --git a/src/Microsoft.OData.Edm/Csdl/CsdlJsonWriter.cs b/src/Microsoft.OData.Edm/Csdl/CsdlJsonWriter.cs
index d176cee09c..b72221194c 100644
--- a/src/Microsoft.OData.Edm/Csdl/CsdlJsonWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/CsdlJsonWriter.cs
@@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
+using System.Threading.Tasks;
using Microsoft.OData.Edm.Csdl.Serialization;
namespace Microsoft.OData.Edm.Csdl
@@ -39,7 +40,7 @@ public CsdlJsonWriter(IEdmModel model, Utf8JsonWriter jsonWriter, CsdlJsonWriter
}
///
- /// Write the JSON CSDL.
+ /// Writes the JSON CSDL.
///
protected override void WriteCsdl()
{
@@ -49,13 +50,30 @@ protected override void WriteCsdl()
WriteReferenceElements();
// It also MAY contain members for schemas.
- WriteSchemata();
+ WriteSchemas();
WriteCsdlEnd();
}
///
- /// CSDL JSON Document Object
+ /// Asynchronously Writes the JSON CSDL.
+ ///
+ /// Task that represents the asynchronous operation.
+ protected override async Task WriteCsdlAsync()
+ {
+ await WriteCsdlStartAsync().ConfigureAwait(false);
+
+ // The CSDL JSON Document object MAY contain the member $Reference to reference other CSDL documents.
+ await WriteReferenceElementsAsync().ConfigureAwait(false);
+
+ // It also MAY contain members for schemas.
+ await WriteSchemasAsync().ConfigureAwait(false);
+
+ await WriteCsdlEndAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes CSDL JSON Document Object
///
private void WriteCsdlStart()
{
@@ -73,7 +91,28 @@ private void WriteCsdlStart()
}
///
- /// $Reference Object
+ /// Asynchronously Writes CSDL JSON Document Object
+ ///
+ /// A task that represents the asynchronous operation
+ private Task WriteCsdlStartAsync()
+ {
+ // A CSDL JSON document consists of a single JSON object.
+ this.jsonWriter.WriteStartObject();
+
+ // This document object MUST contain the member $Version.
+ this.jsonWriter.WriteRequiredProperty("$Version", GetVersionString(edmxVersion));
+
+ // If the CSDL JSON document is the metadata document of an OData service, the document object MUST contain the member $EntityContainer.
+ if (model.EntityContainer != null)
+ {
+ this.jsonWriter.WriteRequiredProperty("$EntityContainer", model.EntityContainer.FullName());
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes $Reference Object
///
private void WriteReferenceElements()
{
@@ -84,9 +123,20 @@ EdmModelReferenceElementsJsonVisitor visitor
}
///
- /// Schema Object.
+ /// Asynchronously writes $Reference Object.
///
- private void WriteSchemata()
+ /// A task that represents the asynchronous operation
+ private Task WriteReferenceElementsAsync()
+ {
+ var visitor = new EdmModelReferenceElementsJsonVisitor(this.model, this.jsonWriter, this.edmxVersion);
+
+ return visitor.VisitEdmReferencesAsync(this.model);
+ }
+
+ ///
+ /// Writes Schema Object.
+ ///
+ private void WriteSchemas()
{
// A schema is represented as a member of the document object whose name is the schema namespace.
// Its value is an object that MAY contain the members $Alias and $Annotations.
@@ -100,6 +150,24 @@ private void WriteSchemata()
}
}
+ ///
+ /// Asynchronously Writes Schema Object
+ ///
+ /// A task that represents the asynchronous operation
+ private async Task WriteSchemasAsync()
+ {
+ // A schema is represented as a member of the document object whose name is the schema namespace.
+ // Its value is an object that MAY contain the members $Alias and $Annotations.
+ EdmModelCsdlSerializationVisitor visitor;
+ Version edmVersion = this.model.GetEdmVersion() ?? EdmConstants.EdmVersionLatest;
+ foreach (EdmSchema schema in this.schemas)
+ {
+ EdmModelCsdlSchemaWriter writer = new EdmModelCsdlSchemaJsonWriter(model, jsonWriter, edmVersion, settings);
+ visitor = new EdmModelCsdlSerializationVisitor(this.model, writer);
+ await visitor.VisitEdmSchemaAsync(schema, this.model.GetNamespacePrefixMappings()).ConfigureAwait(false);
+ }
+ }
+
private void WriteCsdlEnd()
{
// End of the CSDL JSON document.
@@ -107,6 +175,18 @@ private void WriteCsdlEnd()
this.jsonWriter.Flush();
}
+
+ ///
+ /// Write the end of the CSDL JSON document asynchronously.
+ ///
+ /// A task that flushing the JSON writer (jsonWriter) asynchronously.
+ private Task WriteCsdlEndAsync()
+ {
+ // End of the CSDL JSON document.
+ this.jsonWriter.WriteEndObject();
+
+ return this.jsonWriter.FlushAsync();
+ }
}
}
#endif
\ No newline at end of file
diff --git a/src/Microsoft.OData.Edm/Csdl/CsdlWriter.cs b/src/Microsoft.OData.Edm/Csdl/CsdlWriter.cs
index 4490eae04b..ed7eb2069e 100644
--- a/src/Microsoft.OData.Edm/Csdl/CsdlWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/CsdlWriter.cs
@@ -8,8 +8,12 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Text;
+
#if NETCOREAPP
using System.Text.Json;
+using System.Threading.Tasks;
+
#endif
using System.Xml;
@@ -56,6 +60,17 @@ public static bool TryWriteCsdl(IEdmModel model, Utf8JsonWriter writer, out IEnu
return TryWriteCsdl(model, writer, CsdlJsonWriterSettings.Default, out errors);
}
+ ///
+ /// Asynchronously Outputs a CSDL JSON artifact to the provided .
+ ///
+ /// The Edm model to be written.
+ /// JSON writer the generated CSDL will be written to.
+ /// A Task with a tuple with a value indicating whether serialization was successful and EdmError if any
+ public static Task<(bool, IEnumerable)> TryWriteCsdlAsync(IEdmModel model, Utf8JsonWriter writer)
+ {
+ return TryWriteCsdlAsync(model, writer, CsdlJsonWriterSettings.Default);
+ }
+
///
/// Outputs a CSDL JSON artifact to the provided using the settings.
///
@@ -82,6 +97,31 @@ public static bool TryWriteCsdl(IEdmModel model, Utf8JsonWriter writer, CsdlJson
errors = Enumerable.Empty();
return true;
}
+
+ ///
+ /// Asynchronously Outputs a CSDL JSON artifact to the provided using the settings.
+ ///
+ /// The Edm model to be written.
+ /// JSON writer the generated CSDL will be written to.
+ /// The CSDL writer settings.
+ /// A Task with tuple with a value indicating whether serialization was successful and EdmError if any
+ public static async Task<(bool, IEnumerable)> TryWriteCsdlAsync(IEdmModel model, Utf8JsonWriter writer, CsdlJsonWriterSettings settings)
+ {
+ EdmUtil.CheckArgumentNull(model, nameof(model));
+ EdmUtil.CheckArgumentNull(writer, nameof(writer));
+ EdmUtil.CheckArgumentNull(settings, nameof(settings));
+
+ Version edmxVersion;
+ if (!VerifyAndGetVersion(model, out edmxVersion, out IEnumerable errors))
+ {
+ return (false, errors);
+ }
+
+ CsdlWriter csdlWriter = new CsdlJsonWriter(model, writer, settings, edmxVersion);
+ await csdlWriter.WriteCsdlAsync().ConfigureAwait(false);
+
+ return (true, Enumerable.Empty());
+ }
#endif
///
@@ -97,6 +137,17 @@ public static bool TryWriteCsdl(IEdmModel model, XmlWriter writer, CsdlTarget ta
return TryWriteCsdl(model, writer, target, new CsdlXmlWriterSettings(), out errors);
}
+ ///
+ /// Asynchronously Outputs a CSDL XML artifact to the provided .
+ ///
+ /// The Edm model to be written.
+ /// Xmlwriter the generated CSDL will be written to.
+ /// A task with tuple with a value indicating whether serialization was successful and EdmError if any
+ public static Task<(bool, IEnumerable)> TryWriteCsdlAsync(IEdmModel model, XmlWriter writer, CsdlTarget target)
+ {
+ return TryWriteCsdlAsync(model, writer, target, new CsdlXmlWriterSettings());
+ }
+
///
/// Outputs a CSDL XML artifact to the provided .
///
@@ -124,6 +175,31 @@ public static bool TryWriteCsdl(IEdmModel model, XmlWriter writer, CsdlTarget ta
return true;
}
+ ///
+ /// Asynchronously Outputs a CSDL XML artifact to the provided .
+ ///
+ /// Model to be written.
+ /// XmlWriter the generated CSDL will be written to.
+ /// Target implementation of the CSDL being generated.
+ /// The CSDL xml writer settings.
+ /// A task with a value indicating whether serialization was successful.
+ public static async Task<(bool, IEnumerable)> TryWriteCsdlAsync(IEdmModel model, XmlWriter writer, CsdlTarget target, CsdlXmlWriterSettings writerSettings)
+ {
+ EdmUtil.CheckArgumentNull(model, "model");
+ EdmUtil.CheckArgumentNull(writer, "writer");
+
+ Version edmxVersion;
+ if (!VerifyAndGetVersion(model, out edmxVersion, out IEnumerable errors))
+ {
+ return (false, errors);
+ }
+
+ CsdlWriter csdlWriter = new CsdlXmlWriter(model, writer, edmxVersion, target, writerSettings);
+ await csdlWriter.WriteCsdlAsync().ConfigureAwait(false);
+
+ return (true, Enumerable.Empty());
+ }
+
///
/// Write CSDL output.
///
@@ -132,6 +208,15 @@ protected virtual void WriteCsdl()
// nothing here
}
+ ///
+ /// Asynchronously Writes CSDL output.
+ ///
+ /// Task represents an asynchronous operation that may or may not return a result.
+ protected virtual Task WriteCsdlAsync()
+ {
+ return Task.CompletedTask;
+ }
+
///
/// Gets the string form of the EdmVersion.
/// Note that Version 4.01 needs two digits of minor version precision.
diff --git a/src/Microsoft.OData.Edm/Csdl/CsdlXmlWriter.cs b/src/Microsoft.OData.Edm/Csdl/CsdlXmlWriter.cs
index 755dff0825..5a5dcbdf18 100644
--- a/src/Microsoft.OData.Edm/Csdl/CsdlXmlWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/CsdlXmlWriter.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Threading.Tasks;
using System.Xml;
using Microsoft.OData.Edm.Csdl.Serialization;
@@ -73,6 +74,25 @@ protected override void WriteCsdl()
}
}
+ ///
+ /// Asynchronously write the CSDL XML.
+ ///
+ ///
+ protected override async Task WriteCsdlAsync()
+ {
+ switch (this.target)
+ {
+ case CsdlTarget.EntityFramework:
+ await this.WriteEFCsdlAsync().ConfigureAwait(false);
+ break;
+ case CsdlTarget.OData:
+ await this.WriteODataCsdlAsync().ConfigureAwait(false);
+ break;
+ default:
+ throw new InvalidOperationException(Strings.UnknownEnumVal_CsdlTarget(this.target.ToString()));
+ }
+ }
+
private void WriteODataCsdl()
{
this.WriteEdmxElement();
@@ -84,6 +104,17 @@ private void WriteODataCsdl()
this.writer.Flush();
}
+ private async Task WriteODataCsdlAsync()
+ {
+ await this.WriteEdmxElementAsync().ConfigureAwait(false);
+ await this.WriteReferenceElementsAsync().ConfigureAwait(false);
+ await this.WriteDataServicesElementAsync().ConfigureAwait(false);
+ await this.WriteSchemasAsync().ConfigureAwait(false);
+ await this.EndElementAsync().ConfigureAwait(false); //
+ await this.EndElementAsync().ConfigureAwait(false); //
+ await this.writer.FlushAsync().ConfigureAwait(false);
+ }
+
private void WriteEFCsdl()
{
this.WriteEdmxElement();
@@ -96,22 +127,54 @@ private void WriteEFCsdl()
this.writer.Flush();
}
+ private async Task WriteEFCsdlAsync()
+ {
+ await this.WriteEdmxElementAsync().ConfigureAwait(false);
+ await this.WriteRuntimeElementAsync().ConfigureAwait(false);
+ await this.WriteConceptualModelsElementAsync().ConfigureAwait(false);
+ await this.WriteSchemasAsync().ConfigureAwait(false);
+ await this.EndElementAsync().ConfigureAwait(false); //
+ await this.EndElementAsync().ConfigureAwait(false); //
+ await this.EndElementAsync().ConfigureAwait(false); //
+ await this.writer.FlushAsync().ConfigureAwait(false);
+ }
+
private void WriteEdmxElement()
{
this.writer.WriteStartElement(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_Edmx, this.edmxNamespace);
this.writer.WriteAttributeString(CsdlConstants.Attribute_Version, GetVersionString(this.edmxVersion));
}
+ private async Task WriteEdmxElementAsync()
+ {
+ await this.writer.WriteStartElementAsync(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_Edmx, this.edmxNamespace).ConfigureAwait(false);
+ await this.writer.WriteAttributeStringAsync(null, CsdlConstants.Attribute_Version, null, GetVersionString(this.edmxVersion)).ConfigureAwait(false);
+ }
+
private void WriteRuntimeElement()
{
this.writer.WriteStartElement(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_Runtime, this.edmxNamespace);
}
+ private Task WriteRuntimeElementAsync()
+ {
+ return this.writer.WriteStartElementAsync(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_Runtime, this.edmxNamespace);
+ }
+
private void WriteConceptualModelsElement()
{
this.writer.WriteStartElement(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_ConceptualModels, this.edmxNamespace);
}
+ ///
+ /// Asynchronously write the ConceptualModels element.
+ ///
+ /// The task represents the asynchronous operation.
+ private Task WriteConceptualModelsElementAsync()
+ {
+ return this.writer.WriteStartElementAsync(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_ConceptualModels, this.edmxNamespace);
+ }
+
private void WriteReferenceElements()
{
EdmModelReferenceElementsXmlVisitor visitor;
@@ -141,11 +204,45 @@ private void WriteReferenceElements()
}
}
+ private async Task WriteReferenceElementsAsync()
+ {
+ EdmModelReferenceElementsXmlVisitor visitor;
+ IEnumerable references = model.GetEdmReferences();
+ if (references != null)
+ {
+ foreach (IEdmReference reference in references)
+ {
+ //loop through the includes and set the namespace alias
+ if (reference.Includes != null)
+ {
+ foreach (IEdmInclude include in reference.Includes)
+ {
+ if (include.Alias != null)
+ {
+ model.SetNamespaceAlias(include.Namespace, include.Alias);
+ }
+ }
+ }
+ }
+
+ foreach (IEdmReference edmReference in references)
+ {
+ visitor = new EdmModelReferenceElementsXmlVisitor(this.model, this.writer, this.edmxVersion, this.writerSettings);
+ await visitor.VisitEdmReferencesAsync(this.model, edmReference).ConfigureAwait(false);
+ }
+ }
+ }
+
private void WriteDataServicesElement()
{
this.writer.WriteStartElement(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_DataServices, this.edmxNamespace);
}
+ private Task WriteDataServicesElementAsync()
+ {
+ return this.writer.WriteStartElementAsync(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_DataServices, this.edmxNamespace);
+ }
+
private void WriteSchemas()
{
// TODO: for referenced model - write alias as is, instead of writing its namespace.
@@ -159,9 +256,27 @@ private void WriteSchemas()
}
}
+ private async Task WriteSchemasAsync()
+ {
+ // TODO: for referenced model - write alias as is, instead of writing its namespace.
+ EdmModelCsdlSerializationVisitor visitor;
+ Version edmVersion = this.model.GetEdmVersion() ?? EdmConstants.EdmVersionLatest;
+ foreach (EdmSchema schema in this.schemas)
+ {
+ var schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, this.writer, edmVersion, this.writerSettings);
+ visitor = new EdmModelCsdlSerializationVisitor(this.model, schemaWriter);
+ await visitor.VisitEdmSchemaAsync(schema, this.model.GetNamespacePrefixMappings()).ConfigureAwait(false);
+ }
+ }
+
private void EndElement()
{
this.writer.WriteEndElement();
}
+
+ private Task EndElementAsync()
+ {
+ return this.writer.WriteEndElementAsync();
+ }
}
}
diff --git a/src/Microsoft.OData.Edm/Csdl/SchemaWriter.cs b/src/Microsoft.OData.Edm/Csdl/SchemaWriter.cs
index d72cda014c..0b52d86a93 100644
--- a/src/Microsoft.OData.Edm/Csdl/SchemaWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/SchemaWriter.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using System.Xml;
using Microsoft.OData.Edm.Csdl.Serialization;
using Microsoft.OData.Edm.Validation;
@@ -30,6 +31,17 @@ public static bool TryWriteSchema(this IEdmModel model, XmlWriter writer, out IE
return TryWriteSchema(model, x => writer, true, out errors);
}
+ ///
+ /// Asynchronously Outputs a Schema artifact to the provided writer.
+ ///
+ /// Model to be written.
+ /// XmlWriter the generated Schema will be written to.
+ /// A task represents a Tuple with value indicating whether serialization was successful and Errors that prevented successful serialization, or no errors if serialization was successful.
+ public static Task<(bool, IEnumerable)> TryWriteSchemaAsync(this IEdmModel model, XmlWriter writer)
+ {
+ return TryWriteSchemaAsync(model, x => writer, true);
+ }
+
///
/// Outputs Schema artifacts to the provided writers.
///
@@ -42,6 +54,17 @@ public static bool TryWriteSchema(this IEdmModel model, Func
return TryWriteSchema(model, writerProvider, false, out errors);
}
+ ///
+ /// Asynchronously Outputs Schema artifacts to the provided writers.
+ ///
+ /// Model to be written.
+ /// A delegate that takes in a Schema namespace name and returns an XmlWriter to write the Schema to.
+ /// A task represents a Tuple with value indicating whether serialization was successful and Errors that prevented successful serialization, or no errors if serialization was successful.
+ public static Task<(bool, IEnumerable)> TryWriteSchemaAsync(this IEdmModel model, Func writerProvider)
+ {
+ return TryWriteSchemaAsync(model, writerProvider, false);
+ }
+
internal static bool TryWriteSchema(IEdmModel model, Func writerProvider, bool singleFileExpected, out IEnumerable errors)
{
EdmUtil.CheckArgumentNull(model, "model");
@@ -72,6 +95,36 @@ internal static bool TryWriteSchema(IEdmModel model, Func wri
return true;
}
+ internal static async Task<(bool, IEnumerable)> TryWriteSchemaAsync(IEdmModel model, Func writerProvider, bool singleFileExpected)
+ {
+ EdmUtil.CheckArgumentNull(model, "model");
+ EdmUtil.CheckArgumentNull(writerProvider, "writerProvider");
+
+ IEnumerable errors = model.GetSerializationErrors();
+ if (errors.FirstOrDefault() != null)
+ {
+ return (false, errors);
+ }
+
+ IEnumerable schemas = new EdmModelSchemaSeparationSerializationVisitor(model).GetSchemas();
+ if (schemas.Count() > 1 && singleFileExpected)
+ {
+ errors = new EdmError[] { new EdmError(new CsdlLocation(0, 0), EdmErrorCode.SingleFileExpected, Edm.Strings.Serializer_SingleFileExpected) };
+ return (false, errors);
+ }
+
+ if (!schemas.Any())
+ {
+ errors = new EdmError[] { new EdmError(new CsdlLocation(0, 0), EdmErrorCode.NoSchemasProduced, Edm.Strings.Serializer_NoSchemasProduced) };
+ return (false, errors);
+ }
+
+ await WriteSchemasAsync(model, schemas, writerProvider).ConfigureAwait(false);
+
+ errors = Enumerable.Empty();
+ return (true, errors);
+ }
+
internal static void WriteSchemas(IEdmModel model, IEnumerable schemas, Func writerProvider)
{
EdmModelCsdlSerializationVisitor visitor;
@@ -87,5 +140,21 @@ internal static void WriteSchemas(IEdmModel model, IEnumerable schema
}
}
}
+
+ internal static async Task WriteSchemasAsync(IEdmModel model, IEnumerable schemas, Func writerProvider)
+ {
+ EdmModelCsdlSerializationVisitor visitor;
+ Version edmVersion = model.GetEdmVersion() ?? EdmConstants.EdmVersionDefault;
+ foreach (EdmSchema schema in schemas)
+ {
+ XmlWriter writer = writerProvider(schema.Namespace);
+ if (writer != null)
+ {
+ var schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, writer, edmVersion, new CsdlXmlWriterSettings());
+ visitor = new EdmModelCsdlSerializationVisitor(model, schemaWriter);
+ await visitor.VisitEdmSchemaAsync(schema, model.GetNamespacePrefixMappings()).ConfigureAwait(false);
+ }
+ }
+ }
}
}
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs
index f66c2b2040..d31034fa04 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs
@@ -12,6 +12,7 @@
using System.Linq;
using System.Text;
using System.Text.Json;
+using System.Threading.Tasks;
using Microsoft.OData.Edm.Csdl.CsdlSemantics;
using Microsoft.OData.Edm.Csdl.Parsing.Ast;
using Microsoft.OData.Edm.Vocabularies;
@@ -56,6 +57,10 @@ internal EdmModelCsdlSchemaJsonWriter(IEdmModel model, Utf8JsonWriter writer, Ve
this.settings = settings;
}
+ ///
+ /// Writes Reference Element Header.
+ ///
+ /// The Edm Reference.
internal override void WriteReferenceElementHeader(IEdmReference reference)
{
// The name of the pair is a URI for the referenced document.
@@ -65,11 +70,47 @@ internal override void WriteReferenceElementHeader(IEdmReference reference)
this.jsonWriter.WriteStartObject();
}
+ ///
+ /// Asynchronously Writes Reference Element Header.
+ ///
+ /// The Edm Reference.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteReferenceElementHeaderAsync(IEdmReference reference)
+ {
+ // The name of the pair is a URI for the referenced document.
+ this.jsonWriter.WritePropertyName(reference.Uri.OriginalString);
+
+ // The value of each member is a reference object.
+ this.jsonWriter.WriteStartObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Reference Element End.
+ ///
+ /// The Edm Reference element.
internal override void WriteReferenceElementEnd(IEdmReference reference)
{
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes Reference Element End.
+ ///
+ /// The Edm Reference element.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteReferenceElementEndAsync(IEdmReference reference)
+ {
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Include Element Header.
+ ///
+ /// The Edm Include information.
internal override void WritIncludeElementHeader(IEdmInclude include)
{
// Array items are objects.
@@ -82,11 +123,46 @@ internal override void WritIncludeElementHeader(IEdmInclude include)
this.jsonWriter.WriteOptionalProperty("$Alias", include.Alias);
}
+ ///
+ /// Asynchronously Writes Include Element Header.
+ ///
+ /// The Edm Include information.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WritIncludeElementHeaderAsync(IEdmInclude include)
+ {
+ // Array items are objects.
+ this.jsonWriter.WriteStartObject();
+
+ // MUST contain the member $Namespace
+ this.jsonWriter.WriteRequiredProperty("$Namespace", include.Namespace);
+
+ // MAY contain the member $Alias
+ this.jsonWriter.WriteOptionalProperty("$Alias", include.Alias);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Include Element End.
+ ///
+ /// The Edm Include information.
internal override void WriteIncludeElementEnd(IEdmInclude include)
{
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes Include Element End.
+ ///
+ /// The Edm Include information.
+ /// Task representing asynchronous
+ internal override Task WriteIncludeElementEndAsync(IEdmInclude include)
+ {
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Term Object header
///
@@ -135,6 +211,51 @@ internal override void WriteTermElementHeader(IEdmTerm term, bool inlineType)
// These members are processed in ProcessFacets().
}
+ ///
+ /// Asynchronously Writes Term Object header.
+ ///
+ /// The Edm Term
+ /// Is inline type or not.
+ internal override async Task WriteTermElementHeaderAsync(IEdmTerm term, bool inlineType)
+ {
+ // A term is represented as a member of the schema object whose name is the unqualified name of the term.
+ this.jsonWriter.WritePropertyName(term.Name);
+
+ // whose value is an object.
+ this.jsonWriter.WriteStartObject();
+
+ // The term object MUST contain the member $Kind with a string value of Term.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_Term);
+
+ // It MAY contain the members $Type, $Collection.
+ if (inlineType && term.Type is not null)
+ {
+ await WriteTypeReferenceAsync(term.Type).ConfigureAwait(false);
+ }
+
+ // A term MAY specialize another term in scope by specifying it as its base term.
+ // The value of $BaseTerm is the qualified name of the base term. So far, it's not supported.
+
+ // It MAY contain the members $AppliesTo.
+ // The value of $AppliesTo is an array whose items are strings containing symbolic values from a table
+ // that identify model elements the term is intended to be applied to.
+ if (term.AppliesTo is not null)
+ {
+ string[] appliesTo = term.AppliesTo.Split(',');
+ this.jsonWriter.WritePropertyName("$AppliesTo");
+ this.jsonWriter.WriteStartArray();
+ foreach (var applyTo in appliesTo)
+ {
+ this.jsonWriter.WriteStringValue(applyTo);
+ }
+ this.jsonWriter.WriteEndArray();
+ }
+
+ // It MAY contain the members $DefaultValue.
+ // The value of $DefaultValue is the type-specific JSON representation of the default value of the term
+ this.jsonWriter.WriteOptionalProperty("$DefaultValue", term.DefaultValue);
+ }
+
///
/// Write Entity Type object
///
@@ -163,6 +284,37 @@ internal override void WriteEntityTypeElementHeader(IEdmEntityType entityType)
this.jsonWriter.WriteOptionalProperty("$HasStream", entityType.HasStream, CsdlConstants.Default_HasStream);
}
+ ///
+ /// Asynchronously Writes Entity Type object.
+ ///
+ /// The Edm entity type.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteEntityTypeElementHeaderAsync(IEdmEntityType entityType)
+ {
+ // An entity type is represented as a member of the schema object whose name is the unqualified name of the entity type
+ this.jsonWriter.WritePropertyName(entityType.Name);
+
+ // whose value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The entity type object MUST contain the member $Kind with a string value of EntityType.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_EntityType);
+
+ // It MAY contain the members $BaseType
+ this.jsonWriter.WriteOptionalProperty("$BaseType", entityType.BaseEntityType(), this.TypeDefinitionAsJson);
+
+ // It MAY contain the members $Abstract, The value of $Abstract is one of the Boolean literals true or false. Absence of the member means false.
+ this.jsonWriter.WriteOptionalProperty("$Abstract", entityType.IsAbstract, CsdlConstants.Default_Abstract);
+
+ // It MAY contain the members $OpenType, The value of $OpenType is one of the Boolean literals true or false. Absence of the member means false.
+ this.jsonWriter.WriteOptionalProperty("$OpenType", entityType.IsOpen, CsdlConstants.Default_OpenType);
+
+ // It MAY contain the members $HasStream, The value of $HasStream is one of the Boolean literals true or false. Absence of the member means false
+ this.jsonWriter.WriteOptionalProperty("$HasStream", entityType.HasStream, CsdlConstants.Default_HasStream);
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Complex Type Object
///
@@ -188,6 +340,34 @@ internal override void WriteComplexTypeElementHeader(IEdmComplexType complexType
this.jsonWriter.WriteOptionalProperty("$OpenType", complexType.IsOpen, CsdlConstants.Default_OpenType);
}
+ ///
+ /// Asynchronously Writes Complex Type Object.
+ ///
+ /// The Edm complex type.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteComplexTypeElementHeaderAsync(IEdmComplexType complexType)
+ {
+ // A complex type is represented as a member of the schema object whose name is the unqualified name of the complex type
+ this.jsonWriter.WritePropertyName(complexType.Name);
+
+ // whose value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The complex type object MUST contain the member $Kind with a string value of ComplexType.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_ComplexType);
+
+ // It MAY contain the members $BaseType
+ this.jsonWriter.WriteOptionalProperty("$BaseType", complexType.BaseComplexType(), this.TypeDefinitionAsJson);
+
+ // It MAY contain the members $Abstract, The value of $Abstract is one of the Boolean literals true or false. Absence of the member means false.
+ this.jsonWriter.WriteOptionalProperty("$Abstract", complexType.IsAbstract, CsdlConstants.Default_Abstract);
+
+ // It MAY contain the members $OpenType, The value of $OpenType is one of the Boolean literals true or false. Absence of the member means false.
+ this.jsonWriter.WriteOptionalProperty("$OpenType", complexType.IsOpen, CsdlConstants.Default_OpenType);
+
+ return Task.CompletedTask;
+ }
+
///
/// Write $Key
///
@@ -200,10 +380,25 @@ internal override void WriteDeclaredKeyPropertiesElementHeader()
this.jsonWriter.WriteStartArray();
}
+ ///
+ /// Asynchronously Writes $Key.
+ ///
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteDeclaredKeyPropertiesElementHeaderAsync()
+ {
+ // The value of $Key is an array with one item per key property.
+ this.jsonWriter.WritePropertyName("$Key");
+
+ // Its value is an array.
+ this.jsonWriter.WriteStartArray();
+
+ return Task.CompletedTask;
+ }
+
///
/// Write the Key property
///
- ///
+ /// The Edm Structural Property.
internal override void WritePropertyRefElement(IEdmStructuralProperty property)
{
// Key properties without a key alias are represented as strings containing the property name.
@@ -212,6 +407,20 @@ internal override void WritePropertyRefElement(IEdmStructuralProperty property)
this.jsonWriter.WriteStringValue(property.Name);
}
+ ///
+ /// Asynchronously Writes the Key property.
+ ///
+ /// The Edm Structural Property.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WritePropertyRefElementAsync(IEdmStructuralProperty property)
+ {
+ // Key properties without a key alias are represented as strings containing the property name.
+ // Key properties with a key alias are represented as objects with one member whose name is the key alias and whose value is a string containing the path to the property.
+ this.jsonWriter.WriteStringValue(property.Name);
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Navigation Property Object
///
@@ -248,6 +457,47 @@ internal override void WriteNavigationPropertyElementHeader(IEdmNavigationProper
this.jsonWriter.WriteOptionalProperty("$ContainsTarget", property.ContainsTarget, CsdlConstants.Default_ContainsTarget);
}
+ ///
+ /// Asynchronously Writes Navigation Property Object.
+ ///
+ /// The Edm navigation property.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteNavigationPropertyElementHeaderAsync(IEdmNavigationProperty property)
+ {
+ // Navigation properties are represented as members of the object representing a structured type. The member name is the property name.
+ this.jsonWriter.WritePropertyName(property.Name);
+
+ // the member value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The navigation property object MUST contain the member $Kind with a string value of NavigationProperty.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_NavigationProperty);
+
+ // It MUST contain the member $Type (because the navigation property type never be Edm.String)
+ // It MAY contain the members $Collection.
+ await WriteTypeReferenceAsync(property.Type).ConfigureAwait(false);
+
+ // It MAY contain the members $Partner.
+ // A navigation property of an entity type MAY specify a partner navigation property. Navigation properties of complex types MUST NOT specify a partner.
+ // So far, it doesn't support to set the path.
+ if (property.Partner != null)
+ {
+ IEdmPathExpression pathExpression = property.GetPartnerPath();
+ if (pathExpression != null)
+ {
+ this.jsonWriter.WriteRequiredProperty("$Partner", property.GetPartnerPath().Path);
+ }
+ }
+
+ // It MAY contain the members $Collection, $Nullable, $Partner, $ContainsTarget
+ // The value of $ContainsTarget is one of the Boolean literals true or false. Absence of the member means false.
+ this.jsonWriter.WriteOptionalProperty("$ContainsTarget", property.ContainsTarget, CsdlConstants.Default_ContainsTarget);
+ }
+
+ ///
+ /// Writes Referential Constraint Begin.
+ ///
+ /// The Edm Referential Constraint.
internal override void WriteReferentialConstraintBegin(IEdmReferentialConstraint referentialConstraint)
{
// The value of $ReferentialConstraint is an object with one member per referential constraint.
@@ -256,6 +506,25 @@ internal override void WriteReferentialConstraintBegin(IEdmReferentialConstraint
this.jsonWriter.WriteStartObject();
}
+ ///
+ /// Asynchronously Writes Referential Constraint Begin.
+ ///
+ /// The Edm Referential Constraint.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteReferentialConstraintBeginAsync(IEdmReferentialConstraint referentialConstraint)
+ {
+ // The value of $ReferentialConstraint is an object with one member per referential constraint.
+ this.jsonWriter.WritePropertyName("$ReferentialConstraint");
+
+ this.jsonWriter.WriteStartObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Referential Constraint End.
+ ///
+ /// The Edm Referential Constraint.
internal override void WriteReferentialConstraintEnd(IEdmReferentialConstraint referentialConstraint)
{
// It also MAY contain annotations. These are prefixed with the path of the dependent property of the annotated referential constraint.
@@ -264,6 +533,25 @@ internal override void WriteReferentialConstraintEnd(IEdmReferentialConstraint r
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes Referential Constraint End.
+ ///
+ /// The Edm Referential Constraint.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteReferentialConstraintEndAsync(IEdmReferentialConstraint referentialConstraint)
+ {
+ // It also MAY contain annotations. These are prefixed with the path of the dependent property of the annotated referential constraint.
+ // So far, it's not supported.
+
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Referential Constraint Pair.
+ ///
+ /// The Edm Referential Constraint Property Pair.
internal override void WriteReferentialConstraintPair(EdmReferentialConstraintPropertyPair pair)
{
// One member per referential constraint
@@ -274,6 +562,27 @@ internal override void WriteReferentialConstraintPair(EdmReferentialConstraintPr
this.jsonWriter.WriteStringValue(pair.PrincipalProperty.Name); // It should be the path, so far it's not supported.
}
+ ///
+ /// Asynchronously Writes Referential Constraint Pair.
+ ///
+ /// The Edm Referential Constraint Property Pair.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteReferentialConstraintPairAsync(EdmReferentialConstraintPropertyPair pair)
+ {
+ // One member per referential constraint
+ // The member name is the path to the dependent property, this path is relative to the structured type declaring the navigation property.
+ this.jsonWriter.WritePropertyName(pair.DependentProperty.Name); // It should be the path, so far, it's not supported.
+
+ // The member value is a string containing the path to the principal property,
+ this.jsonWriter.WriteStringValue(pair.PrincipalProperty.Name); // It should be the path, so far it's not supported.
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Navigation OnDelete Action Element.
+ ///
+ /// The Edm OnDelete Action.
internal override void WriteNavigationOnDeleteActionElement(EdmOnDeleteAction operationAction)
{
// $OnDelete
@@ -285,6 +594,24 @@ internal override void WriteNavigationOnDeleteActionElement(EdmOnDeleteAction op
// Annotations for $OnDelete are prefixed with $OnDelete. So far, it's not supported now.
}
+ ///
+ /// Asynchronously Writes Navigation OnDelete Action Element.
+ ///
+ /// The Edm OnDelete Action.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteNavigationOnDeleteActionElementAsync(EdmOnDeleteAction operationAction)
+ {
+ // $OnDelete
+ this.jsonWriter.WritePropertyName("$OnDelete");
+
+ // The value of $OnDelete is a string with one of the values Cascade, None, SetNull, or SetDefault.
+ this.jsonWriter.WriteStringValue(operationAction.ToString());
+
+ // Annotations for $OnDelete are prefixed with $OnDelete. So far, it's not supported now.
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Schema Object
///
@@ -304,15 +631,50 @@ internal override void WriteSchemaElementHeader(EdmSchema schema, string alias,
}
///
- /// Write $Annotations : {
+ /// Asynchronously Writes Schema Object.
///
- /// The total out of line annotations.
- internal override void WriteOutOfLineAnnotationsBegin(IEnumerable>> outOfLineAnnotations)
+ /// The Schema
+ /// The alias
+ /// The namespace prefix mapping. It's used in XML, Not apply for JSON.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteSchemaElementHeaderAsync(EdmSchema schema, string alias, IEnumerable> mappings)
{
- // The value of $Annotations is an object with one member per annotation target.
- this.jsonWriter.WritePropertyName("$Annotations");
- this.jsonWriter.WriteStartObject();
- }
+ // A schema is represented as a member of the document object whose name is the schema namespace.
+ this.jsonWriter.WritePropertyName(schema.Namespace);
+
+ // Its value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // It MAY contain the members $Alias
+ this.jsonWriter.WriteOptionalProperty("$Alias", alias);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Write $Annotations : {
+ ///
+ /// The total out of line annotations.
+ internal override void WriteOutOfLineAnnotationsBegin(IEnumerable>> outOfLineAnnotations)
+ {
+ // The value of $Annotations is an object with one member per annotation target.
+ this.jsonWriter.WritePropertyName("$Annotations");
+ this.jsonWriter.WriteStartObject();
+ }
+
+ ///
+ /// Asynchronously Writes $Annotations Begin : {
+ ///
+ /// The total out of line annotations.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteOutOfLineAnnotationsBeginAsync(IEnumerable>> outOfLineAnnotations)
+ {
+ // The value of $Annotations is an object with one member per annotation target.
+ this.jsonWriter.WritePropertyName("$Annotations");
+ this.jsonWriter.WriteStartObject();
+
+ return Task.CompletedTask;
+ }
///
/// Write Annotations with External Targeting.
@@ -325,6 +687,20 @@ internal override void WriteAnnotationsElementHeader(KeyValuePair
+ /// Asynchronously Writes Annotations with External Targeting.
+ ///
+ /// The annotation.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteAnnotationsElementHeaderAsync(KeyValuePair> annotationsForTarget)
+ {
+ // The member name is a path identifying the annotation target, the member value is an object containing annotations for that target.
+ this.jsonWriter.WritePropertyName(annotationsForTarget.Key);
+ this.jsonWriter.WriteStartObject();
+
+ return Task.CompletedTask;
+ }
+
///
/// Write $Annotations End: }
///
@@ -334,6 +710,18 @@ internal override void WriteOutOfLineAnnotationsEnd(IEnumerable
+ /// Asynchronously Writes $Annotations End: }
+ ///
+ /// The total out of line annotations.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteOutOfLineAnnotationsEndAsync(IEnumerable>> outOfLineAnnotations)
+ {
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
///
/// Write structural property object.
///
@@ -361,6 +749,34 @@ internal override void WriteStructuralPropertyElementHeader(IEdmStructuralProper
this.jsonWriter.WriteOptionalProperty("$DefaultValue", property.DefaultValueString);
}
+ ///
+ /// Asynchronously Writes structural property object.
+ ///
+ /// The Edm structural property.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteStructuralPropertyElementHeaderAsync(IEdmStructuralProperty property, bool inlineType)
+ {
+ // Structural properties are represented as members of the object representing a structured type. The member name is the property name.
+ this.jsonWriter.WritePropertyName(property.Name);
+
+ // The member value is an object.
+ this.jsonWriter.WriteStartObject();
+
+ // The property object MAY contain the member $Kind with a string value of Property. This member SHOULD be omitted to reduce document size.
+ // So, we omit the $Kind for property.
+
+ // It MAY contain the member $Type & $Collection
+ if (inlineType)
+ {
+ await WriteTypeReferenceAsync(property.Type).ConfigureAwait(false);
+ }
+
+ // The value of $DefaultValue is the type-specific JSON representation of the default value of the property.
+ // So far, it only includes the string format.
+ this.jsonWriter.WriteOptionalProperty("$DefaultValue", property.DefaultValueString);
+ }
+
///
/// Write enumeration type object header
///
@@ -389,6 +805,37 @@ internal override void WriteEnumTypeElementHeader(IEdmEnumType enumType)
this.isInEnumTypeWriting = true;
}
+ ///
+ /// Asynchronously Writes enumeration type object header
+ ///
+ /// The given enumeration type.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteEnumTypeElementHeaderAsync(IEdmEnumType enumType)
+ {
+ // An enumeration type is represented as a member of the schema object whose name is the unqualified name of the enumeration type
+ this.jsonWriter.WritePropertyName(enumType.Name);
+
+ // whose value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The enumeration type object MUST contain the member $Kind with a string value of EnumType.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_EnumType);
+
+ // An enumeration type MAY specify one of Edm.Byte, Edm.SByte, Edm.Int16, Edm.Int32, or Edm.Int64 as its underlying type.
+ // If not explicitly specified, Edm.Int32 is used as the underlying type.
+ if (enumType.UnderlyingType.PrimitiveKind != EdmPrimitiveTypeKind.Int32)
+ {
+ this.jsonWriter.WriteRequiredProperty("$UnderlyingType", enumType.UnderlyingType, this.TypeDefinitionAsJson);
+ }
+
+ // The value of $IsFlags is one of the Boolean literals true or false. Absence of the member means false.
+ this.jsonWriter.WriteOptionalProperty("$IsFlags", enumType.IsFlags, CsdlConstants.Default_IsFlags);
+
+ this.isInEnumTypeWriting = true;
+
+ return Task.CompletedTask;
+ }
+
///
/// Write enumeration type object end
///
@@ -399,6 +846,17 @@ internal override void WriteEnumTypeElementEnd(IEdmEnumType enumType)
this.isInEnumTypeWriting = false;
}
+ ///
+ /// Asynchronously Writes enumeration type object end
+ ///
+ /// The given enumeration type.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteEnumTypeElementEndAsync(IEdmEnumType enumType)
+ {
+ await WriteEndElementAsync().ConfigureAwait(false);
+ this.isInEnumTypeWriting = false;
+ }
+
///
/// Write Enumeration Member Object start
///
@@ -411,6 +869,21 @@ internal override void WriteEnumMemberElementHeader(IEdmEnumMember member)
this.jsonWriter.WriteRequiredProperty(member.Name, member.Value.Value);
}
+ ///
+ /// Asynchronously Writes Enumeration Member Object start
+ ///
+ /// The Edm Enum member.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteEnumMemberElementHeaderAsync(IEdmEnumMember member)
+ {
+ // Enumeration type members are represented as JSON object members.
+ // Member name is the enumeration member name.
+ // member value is the enumeration member value
+ this.jsonWriter.WriteRequiredProperty(member.Name, member.Value.Value);
+
+ return Task.CompletedTask;
+ }
+
///
/// 7.2.1 Nullable, A Boolean value specifying whether a value is required for the property.
///
@@ -421,6 +894,23 @@ internal override void WriteNullableAttribute(IEdmTypeReference reference)
this.jsonWriter.WriteOptionalProperty("$Nullable", reference.IsNullable, defaultValue: false);
}
+ ///
+ /// Asynchronously Writes Nullable, A Boolean value specifying whether a value is required for the property.
+ ///
+ /// The Edm type reference.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteNullableAttributeAsync(IEdmTypeReference reference)
+ {
+ // The value of $Nullable is one of the Boolean literals true or false. Absence of the member means false.
+ this.jsonWriter.WriteOptionalProperty("$Nullable", reference.IsNullable, defaultValue: false);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Type Definition Attributes.
+ ///
+ /// The Edm Type Definition Reference.
internal override void WriteTypeDefinitionAttributes(IEdmTypeDefinitionReference reference)
{
IEdmTypeReference actualTypeReference = reference.AsActualTypeReference();
@@ -447,6 +937,41 @@ internal override void WriteTypeDefinitionAttributes(IEdmTypeDefinitionReference
}
}
+ ///
+ /// Asynchronously Writes Type Definition Attributes.
+ ///
+ /// The Edm Type Definition Reference.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteTypeDefinitionAttributesAsync(IEdmTypeDefinitionReference reference)
+ {
+ IEdmTypeReference actualTypeReference = reference.AsActualTypeReference();
+
+ if (actualTypeReference.IsBinary())
+ {
+ await this.WriteBinaryTypeAttributesAsync(actualTypeReference.AsBinary()).ConfigureAwait(false);
+ }
+ else if (actualTypeReference.IsString())
+ {
+ await this.WriteStringTypeAttributesAsync(actualTypeReference.AsString()).ConfigureAwait(false);
+ }
+ else if (actualTypeReference.IsTemporal())
+ {
+ await this.WriteTemporalTypeAttributesAsync(actualTypeReference.AsTemporal()).ConfigureAwait(false);
+ }
+ else if (actualTypeReference.IsDecimal())
+ {
+ await this.WriteDecimalTypeAttributesAsync(actualTypeReference.AsDecimal()).ConfigureAwait(false);
+ }
+ else if (actualTypeReference.IsSpatial())
+ {
+ await this.WriteSpatialTypeAttributesAsync(actualTypeReference.AsSpatial()).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Binary Type Attributes.
+ ///
+ /// The Edm Binary Type Reference
internal override void WriteBinaryTypeAttributes(IEdmBinaryTypeReference reference)
{
// CSDL XML defines a symbolic value max that is only allowed in OData 4.0 responses.
@@ -455,6 +980,25 @@ internal override void WriteBinaryTypeAttributes(IEdmBinaryTypeReference referen
this.jsonWriter.WriteOptionalProperty("$MaxLength", reference.MaxLength);
}
+ ///
+ /// Asynchronously Writes Binary Type Attributes.
+ ///
+ /// The Edm Binary Type Reference
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteBinaryTypeAttributesAsync(IEdmBinaryTypeReference reference)
+ {
+ // CSDL XML defines a symbolic value max that is only allowed in OData 4.0 responses.
+ // This symbolic value is not allowed in CDSL JSON documents at all.
+ // So, 'IsUnbounded' is skipped in CSDL JSON.
+ this.jsonWriter.WriteOptionalProperty("$MaxLength", reference.MaxLength);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes DecimalType Attributes.
+ ///
+ /// The Edm Decimal Type Reference.
internal override void WriteDecimalTypeAttributes(IEdmDecimalTypeReference reference)
{
// The value of $Precision is a number. Absence of $Precision means arbitrary precision.
@@ -466,6 +1010,28 @@ internal override void WriteDecimalTypeAttributes(IEdmDecimalTypeReference refer
this.jsonWriter.WriteOptionalProperty("$Scale", reference.Scale);
}
+ ///
+ /// Asynchronously Writes Decimal Type Attributes.
+ ///
+ /// The Edm Decimal Type Reference.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteDecimalTypeAttributesAsync(IEdmDecimalTypeReference reference)
+ {
+ // The value of $Precision is a number. Absence of $Precision means arbitrary precision.
+ this.jsonWriter.WriteOptionalProperty("$Precision", reference.Precision);
+
+ // The value of $Scale is a number or a string with one of the symbolic values floating or variable.
+ // TODO: the symbolic values floating or variable is not supported now.
+ // Absence of $Scale means variable.
+ this.jsonWriter.WriteOptionalProperty("$Scale", reference.Scale);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Spatial Type Attributes. $SRID
+ ///
+ /// The Edm Spatial Type Reference.
internal override void WriteSpatialTypeAttributes(IEdmSpatialTypeReference reference)
{
// The value of $SRID is a string containing a number or the symbolic value variable
@@ -482,6 +1048,33 @@ internal override void WriteSpatialTypeAttributes(IEdmSpatialTypeReference refer
}
}
+ ///
+ /// Asynchronously Writes Spatial Type Attributes. $SRID
+ ///
+ /// The Edm Spatial Type Reference.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteSpatialTypeAttributesAsync(IEdmSpatialTypeReference reference)
+ {
+ // The value of $SRID is a string containing a number or the symbolic value variable
+ // The value of the SRID facet MUST be a non-negative integer or the special value variable.
+ // TODO: the special value variable is not supported now.
+ // If no value is specified, the facet defaults to 0 for Geometry types or 4326 for Geography types.
+ if (reference.IsGeography())
+ {
+ this.jsonWriter.WriteOptionalProperty("$SRID", reference.SpatialReferenceIdentifier, CsdlConstants.Default_SpatialGeographySrid);
+ }
+ else if (reference.IsGeometry())
+ {
+ this.jsonWriter.WriteOptionalProperty("$SRID", reference.SpatialReferenceIdentifier, CsdlConstants.Default_SpatialGeometrySrid);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes String Type Attributes. $MaxLength, $Unicode
+ ///
+ /// The Edm String Type Reference.
internal override void WriteStringTypeAttributes(IEdmStringTypeReference reference)
{
// CSDL XML defines a symbolic value max that is only allowed in OData 4.0 responses.
@@ -492,12 +1085,50 @@ internal override void WriteStringTypeAttributes(IEdmStringTypeReference referen
this.jsonWriter.WriteOptionalProperty("$Unicode", reference.IsUnicode, CsdlConstants.Default_IsUnicode);
}
+ ///
+ /// Asynchronously Writes String Type Attributes. $MaxLength, $Unicode
+ ///
+ /// The Edm String Type Reference.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteStringTypeAttributesAsync(IEdmStringTypeReference reference)
+ {
+ // CSDL XML defines a symbolic value max that is only allowed in OData 4.0 responses.
+ // This symbolic value is not allowed in CDSL JSON documents at all.
+ this.jsonWriter.WriteOptionalProperty("$MaxLength", reference.MaxLength);
+
+ // The value of $Unicode is one of the Boolean literals true or false.Absence of the member means true.
+ this.jsonWriter.WriteOptionalProperty("$Unicode", reference.IsUnicode, CsdlConstants.Default_IsUnicode);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Temporal Type Attributes. $Precision
+ ///
+ /// The Edm Temporal Type Reference.
internal override void WriteTemporalTypeAttributes(IEdmTemporalTypeReference reference)
{
// The value of $Precision is a number. Absence of $Precision means arbitrary precision.
this.jsonWriter.WriteOptionalProperty("$Precision", reference.Precision);
}
+ ///
+ /// Asynchronously Writes Temporal Type Attributes. $Precision
+ ///
+ /// The Edm Temporal Type Reference.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteTemporalTypeAttributesAsync(IEdmTemporalTypeReference reference)
+ {
+ // The value of $Precision is a number. Absence of $Precision means arbitrary precision.
+ this.jsonWriter.WriteOptionalProperty("$Precision", reference.Precision);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Annotation String Attribute.
+ ///
+ /// The Edm Direct Value Annotation.
internal override void WriteAnnotationStringAttribute(IEdmDirectValueAnnotation annotation)
{
var edmValue = (IEdmPrimitiveValue)annotation.Value;
@@ -507,6 +1138,25 @@ internal override void WriteAnnotationStringAttribute(IEdmDirectValueAnnotation
}
}
+ ///
+ /// Asynchronously Writes Annotation String Attribute.
+ ///
+ /// The Edm Direct Value Annotation.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteAnnotationStringAttributeAsync(IEdmDirectValueAnnotation annotation)
+ {
+ if ((IEdmPrimitiveValue)annotation.Value is not null)
+ {
+ this.jsonWriter.WriteRequiredProperty(annotation.Name, EdmValueWriter.PrimitiveValueAsXml((IEdmPrimitiveValue)annotation.Value));
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Annotation String Element.
+ ///
+ /// The Edm Direct Value Annotation.
internal override void WriteAnnotationStringElement(IEdmDirectValueAnnotation annotation)
{
var edmValue = (IEdmPrimitiveValue)annotation.Value;
@@ -516,6 +1166,27 @@ internal override void WriteAnnotationStringElement(IEdmDirectValueAnnotation an
}
}
+ ///
+ /// Asynchronously Writes Annotation String Element.
+ ///
+ /// The Edm Direct Value Annotation.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteAnnotationStringElementAsync(IEdmDirectValueAnnotation annotation)
+ {
+ var edmValue = (IEdmPrimitiveValue)annotation.Value;
+ if (edmValue != null)
+ {
+ this.jsonWriter.WriteStringValue(((IEdmStringValue)edmValue).Value);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Schema Operations Header.
+ ///
+ ///
+ /// The Key/Value Pair Operation. An operation is represented as a member of the schema object whose name is the unqualified name of the operation.
internal override void WriteSchemaOperationsHeader(KeyValuePair> operation)
{
// An operation is represented as a member of the schema object whose name is the unqualified name of the operation.
@@ -525,12 +1196,51 @@ internal override void WriteSchemaOperationsHeader(KeyValuePair(KeyValuePair> operation)
+ ///
+ /// Asynchronously Writes Schema Operations Header.
+ ///
+ ///
+ /// The Key/Value Pair Operation. An operation is represented as a member of the schema object whose name is the unqualified name of the operation.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteSchemaOperationsHeaderAsync(KeyValuePair> operation)
{
- this.jsonWriter.WriteEndArray();
+ // An operation is represented as a member of the schema object whose name is the unqualified name of the operation.
+ this.jsonWriter.WritePropertyName(operation.Key);
+
+ // Whose value is an array
+ this.jsonWriter.WriteStartArray();
+
+ return Task.CompletedTask;
}
- internal override void WriteActionElementHeader(IEdmAction action)
+ ///
+ /// Writes Schema Operations End.
+ ///
+ ///
+ /// The Key/Value Pair Operation. An operation is represented as a member of the schema object whose name is the unqualified name of the operation.
+ internal override void WriteSchemaOperationsEnd(KeyValuePair> operation)
+ {
+ this.jsonWriter.WriteEndArray();
+ }
+
+ ///
+ /// Asynchronously Writes Schema Operations End.
+ ///
+ ///
+ /// The Key/Value Pair Operation. An operation is represented as a member of the schema object whose name is the unqualified name of the operation.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteSchemaOperationsEndAsync(KeyValuePair> operation)
+ {
+ this.jsonWriter.WriteEndArray();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Action Element Header. $Kind
+ ///
+ /// The Edm Action.
+ internal override void WriteActionElementHeader(IEdmAction action)
{
this.jsonWriter.WriteStartObject();
@@ -540,6 +1250,25 @@ internal override void WriteActionElementHeader(IEdmAction action)
this.WriteOperationElementAttributes(action);
}
+ ///
+ /// Asynchronously Writes Action Element Header. $Kind
+ ///
+ /// The Edm Action.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteActionElementHeaderAsync(IEdmAction action)
+ {
+ this.jsonWriter.WriteStartObject();
+
+ // The action overload object MUST contain the member $Kind with a string value of Action.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_Action);
+
+ await this.WriteOperationElementAttributesAsync(action).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes Function Element Header. $Kind, $IsComposable
+ ///
+ /// The Edm Function.
internal override void WriteFunctionElementHeader(IEdmFunction function)
{
this.jsonWriter.WriteStartObject();
@@ -555,6 +1284,30 @@ internal override void WriteFunctionElementHeader(IEdmFunction function)
}
}
+ ///
+ /// Asynchronously Writes Function Element Header. $Kind, $IsComposable
+ ///
+ /// The Edm Function.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteFunctionElementHeaderAsync(IEdmFunction function)
+ {
+ this.jsonWriter.WriteStartObject();
+
+ // The action overload object MUST contain the member $Kind with a string value of Action.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_Function);
+
+ await this.WriteOperationElementAttributesAsync(function).ConfigureAwait(false);
+
+ if (function.IsComposable)
+ {
+ this.jsonWriter.WriteRequiredProperty("$IsComposable", true);
+ }
+ }
+
+ ///
+ /// Writes Operation Element Attributes. $IsBound, $EntitySetPath
+ ///
+ /// The Edm Operation.
internal override void WriteOperationElementAttributes(IEdmOperation operation)
{
if (operation.IsBound)
@@ -568,6 +1321,30 @@ internal override void WriteOperationElementAttributes(IEdmOperation operation)
}
}
+ ///
+ /// Asynchronously Writes Operation Element Attributes. $IsBound, $EntitySetPath
+ ///
+ /// The Edm Operation.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteOperationElementAttributesAsync(IEdmOperation operation)
+ {
+ if (operation.IsBound)
+ {
+ this.jsonWriter.WriteRequiredProperty("$IsBound", true);
+ }
+
+ if (operation.EntitySetPath != null)
+ {
+ this.jsonWriter.WriteRequiredProperty("$EntitySetPath", operation.EntitySetPath.Path);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Operation Parameters Begin. $Parameter
+ ///
+ /// The Edm Operation parameters.
internal override void WriteOperationParametersBegin(IEnumerable parameters)
{
if (parameters != null && parameters.Any())
@@ -577,6 +1354,26 @@ internal override void WriteOperationParametersBegin(IEnumerable
+ /// Asynchronously Writes Operation Parameters Begin. $Parameter
+ ///
+ /// The Edm Operation parameters.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteOperationParametersBeginAsync(IEnumerable parameters)
+ {
+ if (parameters != null && parameters.Any())
+ {
+ this.jsonWriter.WritePropertyName("$Parameter");
+ this.jsonWriter.WriteStartArray();
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Operation Parameters End.
+ ///
+ /// The Edm Operation parameters.
internal override void WriteOperationParametersEnd(IEnumerable parameters)
{
if (parameters != null && parameters.Any())
@@ -585,6 +1382,25 @@ internal override void WriteOperationParametersEnd(IEnumerable
+ /// Asynchronously Writes Operation Parameters End.
+ ///
+ /// The Edm Operation parameters.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteOperationParametersEndAsync(IEnumerable parameters)
+ {
+ if (parameters != null && parameters.Any())
+ {
+ this.jsonWriter.WriteEndArray();
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Return Type Element Header. $ReturnType
+ ///
+ /// The Edm Operation Return.
internal override void WriteReturnTypeElementHeader(IEdmOperationReturn operationReturn)
{
// $ReturnType
@@ -594,11 +1410,41 @@ internal override void WriteReturnTypeElementHeader(IEdmOperationReturn operatio
this.jsonWriter.WriteStartObject();
}
+ ///
+ /// Asynchronously Writes Return Type Element Header. $ReturnType
+ ///
+ /// The Edm Operation Return.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteReturnTypeElementHeaderAsync(IEdmOperationReturn operationReturn)
+ {
+ // $ReturnType
+ this.jsonWriter.WritePropertyName("$ReturnType");
+
+ // The value of $ReturnType is an object.
+ this.jsonWriter.WriteStartObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Type Attribute
+ ///
+ /// The Edm Type Reference.
internal override void WriteTypeAttribute(IEdmTypeReference typeReference)
{
WriteTypeReference(typeReference);
}
+ ///
+ /// Asynchronously Writes Type Attribute
+ ///
+ /// The Edm Type Reference.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteTypeAttributeAsync(IEdmTypeReference typeReference)
+ {
+ return WriteTypeReferenceAsync(typeReference);
+ }
+
///
/// Write Entity Container Object
///
@@ -624,6 +1470,34 @@ internal override void WriteEntityContainerElementHeader(IEdmEntityContainer con
}
}
+ ///
+ /// Asynchronously Writes Entity Container Element Header.
+ ///
+ /// The Edm Entity Container.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteEntityContainerElementHeaderAsync(IEdmEntityContainer container)
+ {
+ // An entity container is represented as a member of the schema object whose name is the unqualified name of the entity container
+ this.jsonWriter.WritePropertyName(container.Name);
+
+ // whose value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The entity container object MUST contain the member $Kind with a string value of EntityContainer.
+ // Be caution: Example 33 has the $Kind, but no other words.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_EntityContainer);
+
+ // The entity container object MAY contain the member $Extends, so far it only supports in Csdl Semantics.
+ CsdlSemanticsEntityContainer tmp = container as CsdlSemanticsEntityContainer;
+ CsdlEntityContainer csdlContainer;
+ if (tmp != null && (csdlContainer = tmp.Element as CsdlEntityContainer) != null)
+ {
+ this.jsonWriter.WriteOptionalProperty("$Extends", csdlContainer.Extends);
+ }
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Entity Set object
///
@@ -646,6 +1520,31 @@ internal override void WriteEntitySetElementHeader(IEdmEntitySet entitySet)
this.jsonWriter.WriteOptionalProperty("$IncludeInServiceDocument", entitySet.IncludeInServiceDocument, true);
}
+ ///
+ /// Asynchronously Writes Entity Set object.
+ ///
+ /// The Edm Entity Set.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteEntitySetElementHeaderAsync(IEdmEntitySet entitySet)
+ {
+ // An entity set is represented as a member of the entity container object whose name is the name of the entity set
+ this.jsonWriter.WritePropertyName(entitySet.Name);
+
+ // whose value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The entity set object MUST contain the members $Collection, it's value as true
+ this.jsonWriter.WriteRequiredProperty("$Collection", true);
+
+ // The entity set object MUST contain the member $Type whose string value is the qualified name of an entity type.
+ this.jsonWriter.WriteRequiredProperty("$Type", entitySet.EntityType.FullName());
+
+ // It MAY contain the members $IncludeInServiceDocument. Absence of the member means true.
+ this.jsonWriter.WriteOptionalProperty("$IncludeInServiceDocument", entitySet.IncludeInServiceDocument, true);
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Singleton object
///
@@ -665,6 +1564,28 @@ internal override void WriteSingletonElementHeader(IEdmSingleton singleton)
// So far, IEdmSingleton doesn't have the property defined, so skip it now.
}
+ ///
+ /// Asynchronously Writes Singleton Object.
+ ///
+ /// The Edm singleton.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteSingletonElementHeaderAsync(IEdmSingleton singleton)
+ {
+ // A singleton is represented as a member of the entity container object whose name is the name of the singleton
+ this.jsonWriter.WritePropertyName(singleton.Name);
+
+ // whose value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The singleton object MUST contain the member $Type whose string value is the qualified name of an entity type.
+ this.jsonWriter.WriteRequiredProperty("$Type", singleton.EntityType.FullName());
+
+ // The singleton object MAY contain the member $Nullable. In OData 4.0 responses this member MUST NOT be specified.
+ // So far, IEdmSingleton doesn't have the property defined, so skip it now.
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Action Import Object
///
@@ -687,6 +1608,29 @@ internal override void WriteActionImportElementHeader(IEdmActionImport actionImp
this.WriteOperationImportAttributes(actionImport, CsdlConstants.Attribute_Action);
}
+ ///
+ /// Asynchronously Writes Action Import Object.
+ ///
+ /// The Edm action import.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteActionImportElementHeaderAsync(IEdmActionImport actionImport)
+ {
+ // An action import is represented as a member of the entity container object whose name is the name of the action import.
+ this.jsonWriter.WritePropertyName(actionImport.Name);
+
+ // whose value is an object
+ this.jsonWriter.WriteStartObject();
+
+ // The action import object MUST contain the member $Kind with a string value of ActionImport, and the member $Action.
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_ActionImport);
+
+ // The action import object MUST contain the member $Action. The value of $Action is a string containing the qualified name of an unbound action.
+ this.jsonWriter.WriteRequiredProperty("$Action", actionImport.Operation.FullName());
+
+ // The action import object MAY contain the member $EntitySet.
+ await this.WriteOperationImportAttributesAsync(actionImport, CsdlConstants.Attribute_Action).ConfigureAwait(false);
+ }
+
///
/// Write Function Import Object
///
@@ -715,6 +1659,40 @@ internal override void WriteFunctionImportElementHeader(IEdmFunctionImport funct
}
}
+ ///
+ /// Asynchronously Writes Function Import Object.
+ ///
+ /// The Edm function import.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteFunctionImportElementHeaderAsync(IEdmFunctionImport functionImport)
+ {
+ // A function import is represented as a member of the entity container object whose name is the name of the function import
+ this.jsonWriter.WritePropertyName(functionImport.Name);
+
+ // whose value is an object.
+ this.jsonWriter.WriteStartObject();
+
+ // The function import object MUST contain the member $Kind with a string value of FunctionImport
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_FunctionImport);
+
+ // The function import object MUST contain the member $Function.
+ this.jsonWriter.WriteRequiredProperty("$Function", functionImport.Operation.FullName());
+
+ // The function import object MAY contain the member $EntitySet.
+ await this.WriteOperationImportAttributesAsync(functionImport, CsdlConstants.Attribute_Function).ConfigureAwait(false);
+
+ // The value of $IncludeInServiceDocument is one of the Boolean literals true or false. Absence of the member means false.
+ if (functionImport.IncludeInServiceDocument)
+ {
+ this.jsonWriter.WriteRequiredProperty("$IncludeInServiceDocument", functionImport.IncludeInServiceDocument);
+ }
+ }
+
+ ///
+ /// Writes Operation Parameter Object.
+ ///
+ /// The Edm Operation parameter.
+ /// Is line type or not.
internal override void WriteOperationParameterElementHeader(IEdmOperationParameter parameter, bool inlineType)
{
this.jsonWriter.WriteStartObject();
@@ -728,6 +1706,30 @@ internal override void WriteOperationParameterElementHeader(IEdmOperationParamet
}
}
+ ///
+ /// Asynchronously Writes Operation Parameter Object.
+ ///
+ /// The Edm Operation parameter.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteOperationParameterElementHeaderAsync(IEdmOperationParameter parameter, bool inlineType)
+ {
+ this.jsonWriter.WriteStartObject();
+
+ // A parameter object MUST contain the member $Name
+ this.jsonWriter.WriteRequiredProperty("$Name", parameter.Name);
+
+ if (inlineType)
+ {
+ await WriteTypeReferenceAsync(parameter.Type).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Type Reference.
+ ///
+ /// The Edm Type Reference.
+ /// The Default Type name. Set to "Edm.String" by default.
internal void WriteTypeReference(IEdmTypeReference type, string defaultTypeName = "Edm.String")
{
IEdmTypeReference elementType = type;
@@ -748,6 +1750,38 @@ internal void WriteTypeReference(IEdmTypeReference type, string defaultTypeName
}
}
+ ///
+ /// Asynchronously Writes Type Reference.
+ ///
+ /// The Edm Type Reference.
+ /// The Default Type name. Set to "Edm.String" by default.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal Task WriteTypeReferenceAsync(IEdmTypeReference type, string defaultTypeName = "Edm.String")
+ {
+ IEdmTypeReference elementType = type;
+ if (type.IsCollection())
+ {
+ this.jsonWriter.WriteRequiredProperty("$Collection", true);
+
+ IEdmCollectionTypeReference collectionReference = type.AsCollection();
+ elementType = collectionReference.ElementType();
+ }
+
+ // Absence of the $Type member means the type is Edm.String.
+ // Does it mean to omit the type for Collection(Edm.String)? No, $Collection is used to identify whether it's collection of not.
+ if (elementType.FullName() != defaultTypeName)
+ {
+ string typeName = this.SerializationName((IEdmSchemaElement)elementType.Definition);
+ this.jsonWriter.WriteRequiredProperty("$Type", typeName);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Operation Parameter End Element.
+ ///
+ /// The Edm Operation Parameter.
internal override void WriteOperationParameterEndElement(IEdmOperationParameter parameter)
{
IEdmOptionalParameter optionalParameter = parameter as IEdmOptionalParameter;
@@ -775,10 +1809,62 @@ internal override void WriteOperationParameterEndElement(IEdmOperationParameter
this.WriteEndElement();
}
- internal override void WriteCollectionTypeElementHeader(IEdmCollectionType collectionType, bool inlineType)
+ ///
+ /// Asynchronously Writes Operation Parameter End Element.
+ ///
+ /// The Edm Operation Parameter.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteOperationParameterEndElementAsync(IEdmOperationParameter parameter)
{
+ IEdmOptionalParameter optionalParameter = parameter as IEdmOptionalParameter;
+ if (optionalParameter != null && !(optionalParameter.VocabularyAnnotations(this.Model).Any(a => a.Term == CoreVocabularyModel.OptionalParameterTerm)))
+ {
+ string defaultValue = optionalParameter.DefaultValueString;
+ EdmRecordExpression optionalValue = new EdmRecordExpression();
+
+ await this.WriteVocabularyAnnotationElementHeaderAsync(new EdmVocabularyAnnotation(parameter, CoreVocabularyModel.OptionalParameterTerm, optionalValue), false).ConfigureAwait(false);
+
+ if (!string.IsNullOrEmpty(defaultValue))
+ {
+ var property = new EdmPropertyConstructor(CsdlConstants.Attribute_DefaultValue, new EdmStringConstant(defaultValue));
+ await this.WriteRecordExpressionElementHeaderAsync(optionalValue).ConfigureAwait(false);
+ await this.WritePropertyValueElementHeaderAsync(property, true).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+ else
+ {
+ this.jsonWriter.WriteStartObject();
+ this.jsonWriter.WriteEndObject();
+ }
+ }
+
+ await this.WriteEndElementAsync().ConfigureAwait(false);
}
+ ///
+ /// Writes Collection Type Element Header.
+ ///
+ /// The Edm Collection Type.
+ /// Is line type or not.
+ internal override void WriteCollectionTypeElementHeader(IEdmCollectionType collectionType, bool inlineType)
+ {
+ }
+
+ ///
+ /// Asynchronously Writes Collection Type Element Header.
+ ///
+ /// The Edm Collection Type.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteCollectionTypeElementHeaderAsync(IEdmCollectionType collectionType, bool inlineType)
+ {
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Inline Expression.
+ ///
+ /// The Edm Expression.
internal override void WriteInlineExpression(IEdmExpression expression)
{
IEdmPathExpression pathExpression = expression as IEdmPathExpression;
@@ -835,6 +1921,57 @@ internal override void WriteInlineExpression(IEdmExpression expression)
}
}
+ ///
+ /// Asynchronously Writes Inline Expression.
+ ///
+ /// The Edm Expression.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteInlineExpressionAsync(IEdmExpression expression)
+ {
+ IEdmPathExpression pathExpression = expression as IEdmPathExpression;
+ switch (expression.ExpressionKind)
+ {
+ case EdmExpressionKind.BinaryConstant:
+ return WriteBinaryConstantExpressionElementAsync((IEdmBinaryConstantExpression)expression);
+ case EdmExpressionKind.BooleanConstant:
+ return WriteBooleanConstantExpressionElementAsync((IEdmBooleanConstantExpression)expression);
+ case EdmExpressionKind.DateTimeOffsetConstant:
+ return WriteDateTimeOffsetConstantExpressionElementAsync((IEdmDateTimeOffsetConstantExpression)expression);
+ case EdmExpressionKind.DecimalConstant:
+ return WriteDecimalConstantExpressionElementAsync((IEdmDecimalConstantExpression)expression);
+ case EdmExpressionKind.FloatingConstant:
+ return WriteFloatingConstantExpressionElementAsync((IEdmFloatingConstantExpression)expression);
+ case EdmExpressionKind.GuidConstant:
+ return WriteGuidConstantExpressionElementAsync((IEdmGuidConstantExpression)expression);
+ case EdmExpressionKind.IntegerConstant:
+ return WriteIntegerConstantExpressionElementAsync((IEdmIntegerConstantExpression)expression);
+ case EdmExpressionKind.Path:
+ return WritePathExpressionElementAsync(pathExpression);
+ case EdmExpressionKind.PropertyPath:
+ return WritePropertyPathExpressionElementAsync(pathExpression);
+ case EdmExpressionKind.NavigationPropertyPath:
+ return WriteNavigationPropertyPathExpressionElementAsync(pathExpression);
+ case EdmExpressionKind.AnnotationPath:
+ return WriteAnnotationPathExpressionElementAsync(pathExpression);
+ case EdmExpressionKind.StringConstant:
+ return WriteStringConstantExpressionElementAsync((IEdmStringConstantExpression)expression);
+ case EdmExpressionKind.DurationConstant:
+ return WriteDurationConstantExpressionElementAsync((IEdmDurationConstantExpression)expression);
+ case EdmExpressionKind.DateConstant:
+ return WriteDateConstantExpressionElementAsync((IEdmDateConstantExpression)expression);
+ case EdmExpressionKind.TimeOfDayConstant:
+ return WriteTimeOfDayConstantExpressionElementAsync((IEdmTimeOfDayConstantExpression)expression);
+ default:
+ Debug.Assert(false, "Attempted to inline an expression that was not one of the expected inlineable types.");
+ return Task.CompletedTask;
+ }
+ }
+
+ ///
+ /// Writes Vocabulary Annotation Header.
+ ///
+ /// The Edm Vocabulary Annotation.
+ /// Is line type or not.
internal override void WriteVocabularyAnnotationElementHeader(IEdmVocabularyAnnotation annotation, bool isInline)
{
this.jsonWriter.WritePropertyName(AnnotationToString(annotation));
@@ -846,11 +1983,49 @@ internal override void WriteVocabularyAnnotationElementHeader(IEdmVocabularyAnno
}
}
+ ///
+ /// Asynchronously Writes Vocabulary Annotation Header.
+ ///
+ /// The Edm Vocabulary Annotation.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteVocabularyAnnotationElementHeaderAsync(IEdmVocabularyAnnotation annotation, bool isInline)
+ {
+ this.jsonWriter.WritePropertyName(AnnotationToString(annotation));
+
+ if (isInline)
+ {
+ // In JSON, we always write the annotation value.
+ await this.WriteInlineExpressionAsync(annotation.Value).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Vocabulary Annotation End.
+ ///
+ /// The Edm Vocabulary Annotation.
+ /// Is line type or not.
internal override void WriteVocabularyAnnotationElementEnd(IEdmVocabularyAnnotation annotation, bool isInline)
{
// nothing here
}
+ ///
+ /// Asynchronously Writes Vocabulary Annotation End.
+ ///
+ /// The Edm Vocabulary Annotation.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteVocabularyAnnotationElementEndAsync(IEdmVocabularyAnnotation annotation, bool isInline)
+ {
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Property Value Header.
+ ///
+ /// The Edm Property Constructor.
+ /// Is line type or not.
internal override void WritePropertyValueElementHeader(IEdmPropertyConstructor value, bool isInline)
{
this.jsonWriter.WritePropertyName(value.Name);
@@ -861,6 +2036,26 @@ internal override void WritePropertyValueElementHeader(IEdmPropertyConstructor v
}
}
+ ///
+ /// Asynchronously Writes Property Value Header.
+ ///
+ /// The Edm Property Constructor.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritePropertyValueElementHeaderAsync(IEdmPropertyConstructor value, bool isInline)
+ {
+ this.jsonWriter.WritePropertyName(value.Name);
+
+ if (isInline)
+ {
+ await this.WriteInlineExpressionAsync(value.Value).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Record Expression Header.
+ ///
+ /// The Edm Record Expression.
internal override void WriteRecordExpressionElementHeader(IEdmRecordExpression expression)
{
// Record expressions are represented as objects with one member per property value expression.
@@ -874,6 +2069,31 @@ internal override void WriteRecordExpressionElementHeader(IEdmRecordExpression e
// It MAY contain annotations for itself. It's not supported now.
}
+ ///
+ /// Asynchronously Writes Record Expression Header.
+ ///
+ /// The Edm Record Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteRecordExpressionElementHeaderAsync(IEdmRecordExpression expression)
+ {
+ // Record expressions are represented as objects with one member per property value expression.
+ this.jsonWriter.WriteStartObject();
+
+ if (expression.DeclaredType is not null)
+ {
+ // The type of a record expression is represented as the @type control information.
+ this.jsonWriter.WriteRequiredProperty("@type", expression.DeclaredType.FullName());
+ }
+ // It MAY contain annotations for itself. It's not supported now.
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Property Constructor Header.
+ ///
+ /// The Edm Property Constructor.
+ /// Is line type or not.
internal override void WritePropertyConstructorElementHeader(IEdmPropertyConstructor constructor, bool isInline)
{
// The member name is the property name, and the member value is the property value expression.
@@ -887,29 +2107,117 @@ internal override void WritePropertyConstructorElementHeader(IEdmPropertyConstru
// Annotations for record members are prefixed with the member name. It's not supported now.
}
+ ///
+ /// Asynchronously Writes Property Constructor Header.
+ ///
+ /// The Edm Property Constructor.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritePropertyConstructorElementHeaderAsync(IEdmPropertyConstructor constructor, bool isInline)
+ {
+ // The member name is the property name, and the member value is the property value expression.
+ this.jsonWriter.WritePropertyName(constructor.Name);
+
+ if (isInline)
+ {
+ await this.WriteInlineExpressionAsync(constructor.Value).ConfigureAwait(false);
+ }
+
+ // Annotations for record members are prefixed with the member name. It's not supported now.
+ }
+
+ ///
+ /// Writes Property Constructor End.
+ ///
+ /// The Edm Property Constructor.
internal override void WritePropertyConstructorElementEnd(IEdmPropertyConstructor constructor)
{
// nothing here.
}
+ ///
+ /// Asynchronously Writes Property Constructor End.
+ ///
+ /// The Edm Property Constructor.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WritePropertyConstructorElementEndAsync(IEdmPropertyConstructor constructor)
+ {
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes String Constant Expression.
+ ///
+ /// The Edm String Constant Expression.
internal override void WriteStringConstantExpressionElement(IEdmStringConstantExpression expression)
{
// String expressions are represented as a JSON string.
this.jsonWriter.WriteStringValue(expression.Value);
}
+ ///
+ /// Asynchronously Writes String Constant Expression.
+ ///
+ /// The Edm String Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteStringConstantExpressionElementAsync(IEdmStringConstantExpression expression)
+ {
+ // String expressions are represented as a JSON string.
+ this.jsonWriter.WriteStringValue(expression.Value);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Binary Constant Expression.
+ ///
+ /// The Edm String Constant Expression.
internal override void WriteBinaryConstantExpressionElement(IEdmBinaryConstantExpression expression)
{
// Binary expressions are represented as a string containing the base64url-encoded binary value.
this.jsonWriter.WriteStringValue(BinaryToString(expression));
}
+ ///
+ /// Asynchronously Writes Binary Constant Expression.
+ ///
+ /// The Edm String Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteBinaryConstantExpressionElementAsync(IEdmBinaryConstantExpression expression)
+ {
+ // Binary expressions are represented as a string containing the base64url-encoded binary value.
+ this.jsonWriter.WriteStringValue(BinaryToString(expression));
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Boolean Constant Expression.
+ ///
+ /// The Edm Boolean Constant Expression.
internal override void WriteBooleanConstantExpressionElement(IEdmBooleanConstantExpression expression)
{
// Boolean expressions are represented as the literals true or false.
this.jsonWriter.WriteBooleanValue(expression.Value);
}
+ ///
+ /// Asynchronously Writes Boolean Constant Expression.
+ ///
+ /// The Edm Boolean Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteBooleanConstantExpressionElementAsync(IEdmBooleanConstantExpression expression)
+ {
+ // Boolean expressions are represented as the literals true or false.
+ this.jsonWriter.WriteBooleanValue(expression.Value);
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Null Constant Expression.
+ ///
+ /// The Edm Null Constant Expression.
internal override void WriteNullConstantExpressionElement(IEdmNullExpression expression)
{
// Null expressions that do not contain annotations are represented as the literal null.
@@ -919,24 +2227,95 @@ internal override void WriteNullConstantExpressionElement(IEdmNullExpression exp
// So far, it's not supported.
}
+ ///
+ /// Asynchronously Writes Null Constant Expression.
+ ///
+ /// The Edm Null Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteNullConstantExpressionElementAsync(IEdmNullExpression expression)
+ {
+ // Null expressions that do not contain annotations are represented as the literal null.
+ this.jsonWriter.WriteNullValue();
+
+ // Null expression containing annotations are represented as an object with a member $Null whose value is the literal null.
+ // So far, it's not supported.
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Date Constant Expression.
+ ///
+ /// The Edm Date Constant Expression.
internal override void WriteDateConstantExpressionElement(IEdmDateConstantExpression expression)
{
// Date expressions are represented as a string containing the date value.
this.jsonWriter.WriteStringValue(expression.Value.ToString());
}
+ ///
+ /// Asynchronously Writes Date Constant Expression.
+ ///
+ /// The Edm Date Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteDateConstantExpressionElementAsync(IEdmDateConstantExpression expression)
+ {
+ // Date expressions are represented as a string containing the date value.
+ this.jsonWriter.WriteStringValue(expression.Value.ToString());
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Datetime Offset Constant Expression.
+ ///
+ /// The Edm DateTimeOffset Constant Expression.
internal override void WriteDateTimeOffsetConstantExpressionElement(IEdmDateTimeOffsetConstantExpression expression)
{
// Datetimestamp expressions are represented as a string containing the timestamp value.
this.jsonWriter.WriteStringValue(EdmValueWriter.DateTimeOffsetAsXml(expression.Value));
}
+ ///
+ /// Asynchronously Writes Datetime Offset Constant Expression.
+ ///
+ /// The Edm DateTimeOffset Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteDateTimeOffsetConstantExpressionElementAsync(IEdmDateTimeOffsetConstantExpression expression)
+ {
+ // Datetimestamp expressions are represented as a string containing the timestamp value.
+ this.jsonWriter.WriteStringValue(EdmValueWriter.DateTimeOffsetAsXml(expression.Value));
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Duration Constant Expression.
+ ///
+ /// The Edm Duration Constant Expression.
internal override void WriteDurationConstantExpressionElement(IEdmDurationConstantExpression expression)
{
// Duration expressions are represented as a string containing the duration value.
this.jsonWriter.WriteStringValue(EdmValueWriter.DurationAsXml(expression.Value));
}
+ ///
+ /// Asynchronously Writes Duration Constant Expression.
+ ///
+ /// The Edm Duration Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteDurationConstantExpressionElementAsync(IEdmDurationConstantExpression expression)
+ {
+ // Duration expressions are represented as a string containing the duration value.
+ this.jsonWriter.WriteStringValue(EdmValueWriter.DurationAsXml(expression.Value));
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Decimal Constant Expression.
+ ///
+ /// The Edm Decimal Constant Expression.
internal override void WriteDecimalConstantExpressionElement(IEdmDecimalConstantExpression expression)
{
// Decimal expressions are represented as either a number or a string.
@@ -951,6 +2330,31 @@ internal override void WriteDecimalConstantExpressionElement(IEdmDecimalConstant
}
}
+ ///
+ /// Asynchronously Writes Decimal Constant Expression.
+ ///
+ /// The Edm Decimal Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteDecimalConstantExpressionElementAsync(IEdmDecimalConstantExpression expression)
+ {
+ // Decimal expressions are represented as either a number or a string.
+ // The special values INF, -INF, or NaN are represented as strings. so far, that's not supported.
+ if (this.settings.IsIeee754Compatible)
+ {
+ this.jsonWriter.WriteStringValue(expression.Value.ToString(CultureInfo.InvariantCulture));
+ }
+ else
+ {
+ this.jsonWriter.WriteNumberValue(expression.Value);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Floating Constant Expression.
+ ///
+ /// The Edm Floating Constant Expression.
internal override void WriteFloatingConstantExpressionElement(IEdmFloatingConstantExpression expression)
{
// Ut8JsonWriter can't write the Infinity double,
@@ -973,6 +2377,39 @@ internal override void WriteFloatingConstantExpressionElement(IEdmFloatingConsta
}
}
+ ///
+ /// Asynchronously Writes Floating Constant Expression.
+ ///
+ /// The Edm Floating Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteFloatingConstantExpressionElementAsync(IEdmFloatingConstantExpression expression)
+ {
+ // Ut8JsonWriter can't write the Infinity double,
+ // it throws ".NET number values such as positive and negative infinity cannot be written as valid JSON."
+ if (double.IsNegativeInfinity(expression.Value))
+ {
+ this.jsonWriter.WriteStringValue("-INF");
+ }
+ else if (double.IsPositiveInfinity(expression.Value))
+ {
+ this.jsonWriter.WriteStringValue("INF");
+ }
+ else if (double.IsNaN(expression.Value))
+ {
+ this.jsonWriter.WriteStringValue("NaN");
+ }
+ else
+ {
+ this.jsonWriter.WriteNumberValue(expression.Value);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Function Application Header.
+ ///
+ /// The Edm Apply Expression.
internal override void WriteFunctionApplicationElementHeader(IEdmApplyExpression expression)
{
// Apply expressions are represented as an object.
@@ -985,6 +2422,29 @@ internal override void WriteFunctionApplicationElementHeader(IEdmApplyExpression
this.jsonWriter.WriteStartArray();
}
+ ///
+ /// Asynchronously Writes Function Application Header.
+ ///
+ /// The Edm Apply Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteFunctionApplicationElementHeaderAsync(IEdmApplyExpression expression)
+ {
+ // Apply expressions are represented as an object.
+ this.jsonWriter.WriteStartObject();
+
+ // a member $Apply
+ this.jsonWriter.WritePropertyName("$Apply");
+
+ // whose value is an array of annotation expressions.
+ this.jsonWriter.WriteStartArray();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Function Application End.
+ ///
+ /// The Edm Apply Expression.
internal override void WriteFunctionApplicationElementEnd(IEdmApplyExpression expression)
{
// End of $Apply
@@ -997,12 +2457,52 @@ internal override void WriteFunctionApplicationElementEnd(IEdmApplyExpression ex
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes Function Application End.
+ ///
+ /// The Edm Apply Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteFunctionApplicationElementEndAsync(IEdmApplyExpression expression)
+ {
+ // End of $Apply
+ this.jsonWriter.WriteEndArray();
+
+ // a member $Function whose value is a string containing the qualified name of the client-side function to be applied
+ this.jsonWriter.WriteRequiredProperty("$Function", expression.AppliedFunction.FullName());
+
+ // End of Annotation Value.
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Guid Constant Expression.
+ ///
+ /// The Edm Guid Constant Expression.
internal override void WriteGuidConstantExpressionElement(IEdmGuidConstantExpression expression)
{
// Guid expressions are represented as a string containing the guid value.
this.jsonWriter.WriteStringValue(EdmValueWriter.GuidAsXml(expression.Value));
}
+ ///
+ /// Asynchronously Writes Guid Constant Expression.
+ ///
+ /// The Edm Guid Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteGuidConstantExpressionElementAsync(IEdmGuidConstantExpression expression)
+ {
+ // Guid expressions are represented as a string containing the guid value.
+ this.jsonWriter.WriteStringValue(EdmValueWriter.GuidAsXml(expression.Value));
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Integer Constant Expression.
+ ///
+ /// The Edm Integer Constant Expression.
internal override void WriteIntegerConstantExpressionElement(IEdmIntegerConstantExpression expression)
{
// Integer expressions are represented as a numbers or strings depending on the media type parameter IEEE754Compatible.
@@ -1016,6 +2516,30 @@ internal override void WriteIntegerConstantExpressionElement(IEdmIntegerConstant
}
}
+ ///
+ /// Asynchronously Writes Integer Constant Expression.
+ ///
+ /// The Edm Integer Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteIntegerConstantExpressionElementAsync(IEdmIntegerConstantExpression expression)
+ {
+ // Integer expressions are represented as a numbers or strings depending on the media type parameter IEEE754Compatible.
+ if (this.settings.IsIeee754Compatible)
+ {
+ this.jsonWriter.WriteStringValue(expression.Value.ToString(CultureInfo.InvariantCulture));
+ }
+ else
+ {
+ this.jsonWriter.WriteNumberValue(expression.Value);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Path Expression.
+ ///
+ /// The Edm Path Expression.
internal override void WritePathExpressionElement(IEdmPathExpression expression)
{
// We consider base Path expression is a value path, not same as NavigationPropertyPath, we don't have a value path.
@@ -1025,24 +2549,95 @@ internal override void WritePathExpressionElement(IEdmPathExpression expression)
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes Path Expression.
+ ///
+ /// The Edm Path Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WritePathExpressionElementAsync(IEdmPathExpression expression)
+ {
+ // We consider base Path expression is a value path, not same as NavigationPropertyPath, we don't have a value path.
+ // Path expressions are represented as an object with a single member $Path whose value is a string containing a path.
+ this.jsonWriter.WriteStartObject();
+ this.jsonWriter.WriteRequiredProperty("$Path", PathAsXml(expression.PathSegments));
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Property Path Expression.
+ ///
+ /// The Edm Path Expression.
internal override void WritePropertyPathExpressionElement(IEdmPathExpression expression)
{
// Navigation property path expressions are represented as a string containing a path.
this.jsonWriter.WriteStringValue(PathAsXml(expression.PathSegments));
}
+ ///
+ /// Asynchronously Writes Property Path Expression.
+ ///
+ /// The Edm Path Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WritePropertyPathExpressionElementAsync(IEdmPathExpression expression)
+ {
+ // Navigation property path expressions are represented as a string containing a path.
+ this.jsonWriter.WriteStringValue(PathAsXml(expression.PathSegments));
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Navigation Property Path Expression.
+ ///
+ /// The Edm Path Expression.
internal override void WriteNavigationPropertyPathExpressionElement(IEdmPathExpression expression)
{
// Property path expressions are represented as a string containing a path.
this.jsonWriter.WriteStringValue(PathAsXml(expression.PathSegments));
}
- internal override void WriteAnnotationPathExpressionElement(IEdmPathExpression expression)
+ ///
+ /// Asynchronously Writes Navigation Property Path Expression.
+ ///
+ /// The Edm Path Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteNavigationPropertyPathExpressionElementAsync(IEdmPathExpression expression)
+ {
+ // Property path expressions are represented as a string containing a path.
+ this.jsonWriter.WriteStringValue(PathAsXml(expression.PathSegments));
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Annotation Path Expression.
+ ///
+ /// The Edm Path Expression.
+ internal override void WriteAnnotationPathExpressionElement(IEdmPathExpression expression)
+ {
+ // Annotation path expressions are represented as a string containing a path.
+ this.jsonWriter.WriteStringValue(PathAsXml(expression.PathSegments));
+ }
+
+ ///
+ /// Asynchronously Writes Annotation Path Expression.
+ ///
+ /// The Edm Path Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteAnnotationPathExpressionElementAsync(IEdmPathExpression expression)
{
// Annotation path expressions are represented as a string containing a path.
this.jsonWriter.WriteStringValue(PathAsXml(expression.PathSegments));
+
+ return Task.CompletedTask;
}
+ ///
+ /// Writes 'If' Expression Header.
+ ///
+ /// The If Expression.
internal override void WriteIfExpressionElementHeader(IEdmIfExpression expression)
{
// Is-of expressions are represented as an object
@@ -1055,6 +2650,29 @@ internal override void WriteIfExpressionElementHeader(IEdmIfExpression expressio
this.jsonWriter.WriteStartArray();
}
+ ///
+ /// Asynchronously Writes 'If' Expression Header.
+ ///
+ /// The If Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteIfExpressionElementHeaderAsync(IEdmIfExpression expression)
+ {
+ // Is-of expressions are represented as an object
+ this.jsonWriter.WriteStartObject();
+
+ // Conditional expressions are represented as an object with a member $If
+ this.jsonWriter.WritePropertyName("$If");
+
+ // whose value is an array of two or three annotation expressions
+ this.jsonWriter.WriteStartArray();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes 'If' Expression End.
+ ///
+ /// The Edm If Expression.
internal override void WriteIfExpressionElementEnd(IEdmIfExpression expression)
{
this.jsonWriter.WriteEndArray();
@@ -1062,16 +2680,66 @@ internal override void WriteIfExpressionElementEnd(IEdmIfExpression expression)
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes 'If' Expression End.
+ ///
+ /// The Edm If Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteIfExpressionElementEndAsync(IEdmIfExpression expression)
+ {
+ this.jsonWriter.WriteEndArray();
+
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Collection Expression Header.
+ ///
+ /// The Edm Collection Expression.
internal override void WriteCollectionExpressionElementHeader(IEdmCollectionExpression expression)
{
this.jsonWriter.WriteStartArray();
}
+ ///
+ /// Asynchronously Writes Collection Expression Header.
+ ///
+ /// The Edm Collection Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteCollectionExpressionElementHeaderAsync(IEdmCollectionExpression expression)
+ {
+ this.jsonWriter.WriteStartArray();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Collection Expression End.
+ ///
+ /// The Edm Collection Expression.
internal override void WriteCollectionExpressionElementEnd(IEdmCollectionExpression expression)
{
this.jsonWriter.WriteEndArray();
}
+ ///
+ /// Asynchronously Writes Collection Expression End.
+ ///
+ /// The Edm Collection Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteCollectionExpressionElementEndAsync(IEdmCollectionExpression expression)
+ {
+ this.jsonWriter.WriteEndArray();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Labeled Header.
+ ///
+ /// The Edm Labeled Expression.
internal override void WriteLabeledElementHeader(IEdmLabeledExpression labeledElement)
{
// Labeled element expressions are represented as an object with a member $LabeledElement whose value is an annotation expression.
@@ -1084,6 +2752,29 @@ internal override void WriteLabeledElementHeader(IEdmLabeledExpression labeledEl
this.jsonWriter.WritePropertyName("$LabeledElement");
}
+ ///
+ /// Asynchronously Writes Labeled Header.
+ ///
+ /// The Edm Labeled Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteLabeledElementHeaderAsync(IEdmLabeledExpression labeledElement)
+ {
+ // Labeled element expressions are represented as an object with a member $LabeledElement whose value is an annotation expression.
+ this.jsonWriter.WriteStartObject();
+
+ // a member $Name whose value is a string containing the labeled element’s name
+ this.jsonWriter.WriteRequiredProperty("$Name", labeledElement.Name);
+
+ // an object with a member $LabeledElement
+ this.jsonWriter.WritePropertyName("$LabeledElement");
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Write Labeled Expression Reference.
+ ///
+ /// The Edm Labeled Expression Reference.
internal override void WriteLabeledExpressionReferenceExpression(IEdmLabeledExpressionReferenceExpression labeledExpressionReference)
{
// Labeled element reference expressions are represented as an object
@@ -1101,12 +2792,58 @@ internal override void WriteLabeledExpressionReferenceExpression(IEdmLabeledExpr
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes Labeled Expression Reference.
+ ///
+ /// The Edm Labeled Expression Reference.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteLabeledExpressionReferenceExpressionAsync(IEdmLabeledExpressionReferenceExpression labeledExpressionReference)
+ {
+ // Labeled element reference expressions are represented as an object
+ this.jsonWriter.WriteStartObject();
+
+ // with a member $LabeledElementReference
+ this.jsonWriter.WritePropertyName("$LabeledElementReference");
+
+ // Whose value is a string containing an qualified name.
+ // Here's the problem that we don't have the namespace for the labeled expression,
+ // Even though we can get the namespace from the up-level schema, we can't query it here.
+ // So, leave it using the name.
+ this.jsonWriter.WriteStringValue(labeledExpressionReference.ReferencedLabeledExpression.Name);
+
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Write Time Of Day Constant Expression.
+ ///
+ /// The Edm TimeOfDay Constant Expression.
internal override void WriteTimeOfDayConstantExpressionElement(IEdmTimeOfDayConstantExpression expression)
{
// Time-of-day expressions are represented as a string containing the time-of-day value.
this.jsonWriter.WriteStringValue(EdmValueWriter.TimeOfDayAsXml(expression.Value));
}
+ ///
+ /// Asynchronously Writes Time Of Day Constant Expression.
+ ///
+ /// The Edm TimeOfDay Constant Expression.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteTimeOfDayConstantExpressionElementAsync(IEdmTimeOfDayConstantExpression expression)
+ {
+ // Time-of-day expressions are represented as a string containing the time-of-day value.
+ this.jsonWriter.WriteStringValue(EdmValueWriter.TimeOfDayAsXml(expression.Value));
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Is Type Expression Header.
+ ///
+ /// The Edm IsOf Type Expression.
+ /// Is line type or not.
internal override void WriteIsTypeExpressionElementHeader(IEdmIsTypeExpression expression, bool inlineType)
{
// Is-of expressions are represented as an object
@@ -1117,6 +2854,29 @@ internal override void WriteIsTypeExpressionElementHeader(IEdmIsTypeExpression e
this.jsonWriter.WritePropertyName("$IsOf");
}
+ ///
+ /// Asynchronously Writes Is Type Expression Header.
+ ///
+ /// The Edm IsOf Type Expression.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteIsTypeExpressionElementHeaderAsync(IEdmIsTypeExpression expression, bool inlineType)
+ {
+ // Is-of expressions are represented as an object
+ this.jsonWriter.WriteStartObject();
+
+ // a member $IsOf whose value is an annotation expression
+ // fix it using $IsOf, not using $IsType
+ this.jsonWriter.WritePropertyName("$IsOf");
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Write 'Is Of' Expression Type.
+ ///
+ /// The Edm IsOf Type Expression.
+ /// Is line type or not.
internal override void WriteIsOfExpressionType(IEdmIsTypeExpression expression, bool inlineType)
{
if (inlineType)
@@ -1125,11 +2885,28 @@ internal override void WriteIsOfExpressionType(IEdmIsTypeExpression expression,
}
}
+ ///
+ /// Asynchronously Writes 'Is Of' Expression Type.
+ ///
+ /// The Edm IsOf Type Expression.
+ /// Is line type or not.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteIsOfExpressionTypeAsync(IEdmIsTypeExpression expression, bool inlineType)
+ {
+ if (inlineType)
+ {
+ return WriteTypeReferenceAsync(expression.Type, "None");
+ }
+
+ return Task.CompletedTask;
+ }
+
///
/// Cast
///
/// The cast expression
/// Is inline type.
+ /// Task represents an asynchronous operation that may or may not return a result.
internal override void WriteCastExpressionElementHeader(IEdmCastExpression expression, bool inlineType)
{
// Cast expressions are represented as an object with a member $Cast whose value is an annotation expression,
@@ -1138,11 +2915,45 @@ internal override void WriteCastExpressionElementHeader(IEdmCastExpression expre
this.jsonWriter.WritePropertyName("$Cast");
}
+ ///
+ /// Asynchronously Writes Cast Expression Header.
+ ///
+ /// The cast expression
+ /// Is inline type.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteCastExpressionElementHeaderAsync(IEdmCastExpression expression, bool inlineType)
+ {
+ // Cast expressions are represented as an object with a member $Cast whose value is an annotation expression,
+ this.jsonWriter.WriteStartObject();
+
+ this.jsonWriter.WritePropertyName("$Cast");
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Cast Expression End.
+ ///
+ /// The Edm cast expression
+ /// Is inline type.
internal override void WriteCastExpressionElementEnd(IEdmCastExpression expression, bool inlineType)
{
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes Cast Expression End.
+ ///
+ /// The Edm cast expression
+ /// Is inline type.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteCastExpressionElementEndAsync(IEdmCastExpression expression, bool inlineType)
+ {
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
internal override void WriteCastExpressionType(IEdmCastExpression expression, bool inlineType)
{
if (inlineType)
@@ -1151,6 +2962,22 @@ internal override void WriteCastExpressionType(IEdmCastExpression expression, bo
}
}
+ ///
+ /// Asynchronously Writes Cast Expression Type.
+ ///
+ /// The Edm cast expression
+ /// Is inline type.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteCastExpressionTypeAsync(IEdmCastExpression expression, bool inlineType)
+ {
+ if (inlineType)
+ {
+ return WriteTypeReferenceAsync(expression.Type, "None");
+ }
+
+ return Task.CompletedTask;
+ }
+
///
/// Enumeration Member Expression
///
@@ -1161,6 +2988,18 @@ internal override void WriteEnumMemberExpressionElement(IEdmEnumMemberExpression
this.jsonWriter.WriteStringValue(EnumMemberExpressionAsJson(expression.EnumMembers));
}
+ ///
+ /// Asynchronously Enumeration Member Expression
+ ///
+ /// The Edm Enumeration member expression.
+ internal override Task WriteEnumMemberExpressionElementAsync(IEdmEnumMemberExpression expression)
+ {
+ // Enumeration member expressions are represented as a string containing the numeric or symbolic enumeration value.
+ this.jsonWriter.WriteStringValue(EnumMemberExpressionAsJson(expression.EnumMembers));
+
+ return Task.CompletedTask;
+ }
+
///
/// Write Type Definition Object
///
@@ -1180,6 +3019,28 @@ internal override void WriteTypeDefinitionElementHeader(IEdmTypeDefinition typeD
this.jsonWriter.WriteRequiredProperty("$UnderlyingType", typeDefinition.UnderlyingType, TypeDefinitionAsJson);
}
+ ///
+ /// Asynchronously Writes Type Definition Object
+ ///
+ /// The Edm type definition.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteTypeDefinitionElementHeaderAsync(IEdmTypeDefinition typeDefinition)
+ {
+ // A type definition is represented as a member of the schema object whose name is the unqualified name of the type definition
+ this.jsonWriter.WritePropertyName(typeDefinition.Name);
+
+ // whose value is an object.
+ this.jsonWriter.WriteStartObject();
+
+ // The type definition object MUST contain the member $Kind with a string value of TypeDefinition
+ this.jsonWriter.WriteRequiredProperty("$Kind", CsdlConstants.Element_TypeDefinition);
+
+ // The type definition object MUST contain he member $UnderlyingType.
+ this.jsonWriter.WriteRequiredProperty("$UnderlyingType", typeDefinition.UnderlyingType, TypeDefinitionAsJson);
+
+ return Task.CompletedTask;
+ }
+
///
/// Start $NavigationPropertyBinding
///
@@ -1193,6 +3054,22 @@ internal override void WriteNavigationPropertyBindingsBegin(IEnumerable
+ /// Asynchronously Writes Navigation Property Bindings Begin $NavigationPropertyBinding
+ ///
+ /// The collection the bindings.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteNavigationPropertyBindingsBeginAsync(IEnumerable bindings)
+ {
+ // It MAY contain the member $NavigationPropertyBinding
+ this.jsonWriter.WritePropertyName("$NavigationPropertyBinding");
+
+ // whose value is an object.
+ this.jsonWriter.WriteStartObject();
+
+ return Task.CompletedTask;
+ }
+
///
/// End $NavigationPropertyBinding
///
@@ -1202,10 +3079,22 @@ internal override void WriteNavigationPropertyBindingsEnd(IEnumerable
+ /// Asynchronously Writes Navigation Property Bindings End $NavigationPropertyBinding
+ ///
+ /// The collection the bindings.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteNavigationPropertyBindingsEndAsync(IEnumerable bindings)
+ {
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
///
/// Write the navigation property binding member in $NavigationPropertyBinding object.
///
- ///
+ /// The Edm Navigation Property binding.
internal override void WriteNavigationPropertyBinding(IEdmNavigationPropertyBinding binding)
{
// whose name is the navigation property binding path.
@@ -1223,16 +3112,73 @@ internal override void WriteNavigationPropertyBinding(IEdmNavigationPropertyBind
}
}
+ ///
+ /// Asynchronously Writes the navigation property binding member in $NavigationPropertyBinding object.
+ ///
+ /// The Edm Navigation Property binding.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteNavigationPropertyBindingAsync(IEdmNavigationPropertyBinding binding)
+ {
+ // whose name is the navigation property binding path.
+ this.jsonWriter.WritePropertyName(binding.Path.Path);
+
+ // whose value is a string containing the navigation property binding target.
+ if (binding.Target is IEdmContainedEntitySet containedEntitySet)
+ {
+ this.jsonWriter.WriteStringValue(containedEntitySet.Path.Path);
+ }
+ else
+ {
+ this.jsonWriter.WriteStringValue(binding.Target.Name);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes End Element.
+ ///
internal override void WriteEndElement()
{
this.jsonWriter.WriteEndObject();
}
+ ///
+ /// Asynchronously Writes End Element.
+ ///
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteEndElementAsync()
+ {
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Array End Element.
+ ///
internal override void WriteArrayEndElement()
{
this.jsonWriter.WriteEndArray();
}
+ ///
+ /// Asynchronously Writes Array End Element.
+ ///
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteArrayEndElementAsync()
+ {
+ this.jsonWriter.WriteEndArray();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Operation Import Attributes.
+ ///
+ /// The Edm Operation import.
+ /// Operation Attribute name.
+ ///
internal override void WriteOperationImportAttributes(IEdmOperationImport operationImport, string operationAttributeName)
{
if (operationImport.EntitySet != null)
@@ -1249,6 +3195,30 @@ internal override void WriteOperationImportAttributes(IEdmOperationImport operat
}
}
+ ///
+ /// Asynchronously Writes Operation Import Attributes.
+ ///
+ /// The Edm Operation import.
+ /// Operation Attribute name.
+ ///
+ /// Task represents an asynchronous operation that may or may not return a result.
+ internal override Task WriteOperationImportAttributesAsync(IEdmOperationImport operationImport, string operationAttributeName)
+ {
+ if (operationImport.EntitySet is not null)
+ {
+ if (operationImport.EntitySet is IEdmPathExpression pathExpression)
+ {
+ this.jsonWriter.WriteRequiredProperty("$EntitySet", pathExpression.PathSegments, PathAsXml);
+ }
+ else
+ {
+ throw new InvalidOperationException(Strings.EdmModel_Validator_Semantic_OperationImportEntitySetExpressionIsInvalid(operationImport.Name));
+ }
+ }
+
+ return Task.CompletedTask;
+ }
+
private static string BinaryToString(IEdmBinaryConstantExpression binary)
{
// whose value is a string containing the base64url-encoded binary value.
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs
index a299e6a77e..6cc8bad6fd 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.OData.Edm.Vocabularies;
namespace Microsoft.OData.Edm.Csdl.Serialization
@@ -47,227 +48,372 @@ internal EdmModelCsdlSchemaWriter(IEdmModel model, Version edmVersion)
public VersioningDictionary NamespaceAliasMappings { get; }
internal abstract void WriteReferenceElementHeader(IEdmReference reference);
+ internal abstract Task WriteReferenceElementHeaderAsync(IEdmReference reference);
internal abstract void WriteReferenceElementEnd(IEdmReference reference);
+ internal abstract Task WriteReferenceElementEndAsync(IEdmReference reference);
internal abstract void WritIncludeElementHeader(IEdmInclude include);
+ internal abstract Task WritIncludeElementHeaderAsync(IEdmInclude include);
internal abstract void WriteIncludeElementEnd(IEdmInclude include);
+ internal abstract Task WriteIncludeElementEndAsync(IEdmInclude include);
internal abstract void WriteTermElementHeader(IEdmTerm term, bool inlineType);
+ internal abstract Task WriteTermElementHeaderAsync(IEdmTerm term, bool inlineType);
internal abstract void WriteComplexTypeElementHeader(IEdmComplexType complexType);
+ internal abstract Task WriteComplexTypeElementHeaderAsync(IEdmComplexType complexType);
internal abstract void WriteEntityTypeElementHeader(IEdmEntityType entityType);
+ internal abstract Task WriteEntityTypeElementHeaderAsync(IEdmEntityType entityType);
internal abstract void WriteEnumTypeElementHeader(IEdmEnumType enumType);
+ internal abstract Task WriteEnumTypeElementHeaderAsync(IEdmEnumType enumType);
internal abstract void WriteEnumTypeElementEnd(IEdmEnumType enumType);
+ internal abstract Task WriteEnumTypeElementEndAsync(IEdmEnumType enumType);
internal abstract void WriteEntityContainerElementHeader(IEdmEntityContainer container);
+ internal abstract Task WriteEntityContainerElementHeaderAsync(IEdmEntityContainer container);
internal abstract void WriteEntitySetElementHeader(IEdmEntitySet entitySet);
+ internal abstract Task WriteEntitySetElementHeaderAsync(IEdmEntitySet entitySet);
internal abstract void WriteSingletonElementHeader(IEdmSingleton singleton);
+ internal abstract Task WriteSingletonElementHeaderAsync(IEdmSingleton singleton);
internal abstract void WriteDeclaredKeyPropertiesElementHeader();
+ internal abstract Task WriteDeclaredKeyPropertiesElementHeaderAsync();
internal abstract void WritePropertyRefElement(IEdmStructuralProperty property);
+ internal abstract Task WritePropertyRefElementAsync(IEdmStructuralProperty property);
internal abstract void WriteNavigationPropertyElementHeader(IEdmNavigationProperty property);
+ internal abstract Task WriteNavigationPropertyElementHeaderAsync(IEdmNavigationProperty property);
internal abstract void WriteNavigationOnDeleteActionElement(EdmOnDeleteAction operationAction);
+ internal abstract Task WriteNavigationOnDeleteActionElementAsync(EdmOnDeleteAction operationAction);
internal abstract void WriteSchemaElementHeader(EdmSchema schema, string alias, IEnumerable> mappings);
+ internal abstract Task WriteSchemaElementHeaderAsync(EdmSchema schema, string alias, IEnumerable> mappings);
internal abstract void WriteAnnotationsElementHeader(KeyValuePair> annotationsForTarget);
+ internal abstract Task WriteAnnotationsElementHeaderAsync(KeyValuePair> annotationsForTarget);
internal virtual void WriteOutOfLineAnnotationsBegin(IEnumerable>> outOfLineAnnotations)
{
// nothing here
}
+ internal virtual Task WriteOutOfLineAnnotationsBeginAsync(IEnumerable>> outOfLineAnnotations)
+ {
+ return Task.CompletedTask;
+ }
+
internal virtual void WriteOutOfLineAnnotationsEnd(IEnumerable>> outOfLineAnnotations)
{
// nothing here
}
+ internal virtual Task WriteOutOfLineAnnotationsEndAsync(IEnumerable>> outOfLineAnnotations)
+ {
+ return Task.CompletedTask;
+ }
+
internal abstract void WriteStructuralPropertyElementHeader(IEdmStructuralProperty property, bool inlineType);
+ internal abstract Task WriteStructuralPropertyElementHeaderAsync(IEdmStructuralProperty property, bool inlineType);
internal abstract void WriteEnumMemberElementHeader(IEdmEnumMember member);
+ internal abstract Task WriteEnumMemberElementHeaderAsync(IEdmEnumMember member);
internal virtual void WriteEnumMemberElementEnd(IEdmEnumMember member)
{
// Nothing here
}
+ internal virtual Task WriteEnumMemberElementEndAsync(IEdmEnumMember member)
+ {
+ return Task.CompletedTask;
+ }
+
internal abstract void WriteNavigationPropertyBinding(IEdmNavigationPropertyBinding binding);
+ internal abstract Task WriteNavigationPropertyBindingAsync(IEdmNavigationPropertyBinding binding);
internal virtual void WriteNavigationPropertyBindingsBegin(IEnumerable bindings)
{
// Nothing here
}
+ internal virtual Task WriteNavigationPropertyBindingsBeginAsync(IEnumerable bindings)
+ {
+ return Task.CompletedTask;
+ }
+
internal virtual void WriteNavigationPropertyBindingsEnd(IEnumerable bindings)
{
// Nothing here
}
+ internal virtual Task WriteNavigationPropertyBindingsEndAsync(IEnumerable bindings)
+ {
+ return Task.CompletedTask;
+ }
+
internal abstract void WriteNullableAttribute(IEdmTypeReference reference);
+ internal abstract Task WriteNullableAttributeAsync(IEdmTypeReference reference);
internal abstract void WriteTypeDefinitionAttributes(IEdmTypeDefinitionReference reference);
+ internal abstract Task WriteTypeDefinitionAttributesAsync(IEdmTypeDefinitionReference reference);
internal abstract void WriteBinaryTypeAttributes(IEdmBinaryTypeReference reference);
+ internal abstract Task WriteBinaryTypeAttributesAsync(IEdmBinaryTypeReference reference);
internal abstract void WriteDecimalTypeAttributes(IEdmDecimalTypeReference reference);
+ internal abstract Task WriteDecimalTypeAttributesAsync(IEdmDecimalTypeReference reference);
internal abstract void WriteSpatialTypeAttributes(IEdmSpatialTypeReference reference);
+ internal abstract Task WriteSpatialTypeAttributesAsync(IEdmSpatialTypeReference reference);
internal abstract void WriteStringTypeAttributes(IEdmStringTypeReference reference);
+ internal abstract Task WriteStringTypeAttributesAsync(IEdmStringTypeReference reference);
internal abstract void WriteTemporalTypeAttributes(IEdmTemporalTypeReference reference);
+ internal abstract Task WriteTemporalTypeAttributesAsync(IEdmTemporalTypeReference reference);
internal virtual void WriteReferentialConstraintBegin(IEdmReferentialConstraint referentialConstraint)
{
// nothing here
}
+ internal virtual Task WriteReferentialConstraintBeginAsync(IEdmReferentialConstraint referentialConstraint)
+ {
+ return Task.CompletedTask;
+ }
+
internal virtual void WriteReferentialConstraintEnd(IEdmReferentialConstraint referentialConstraint)
{
// nothing here
}
+ internal virtual Task WriteReferentialConstraintEndAsync(IEdmReferentialConstraint referentialConstraint)
+ {
+ return Task.CompletedTask;
+ }
+
internal abstract void WriteReferentialConstraintPair(EdmReferentialConstraintPropertyPair pair);
+ internal abstract Task WriteReferentialConstraintPairAsync(EdmReferentialConstraintPropertyPair pair);
internal abstract void WriteAnnotationStringAttribute(IEdmDirectValueAnnotation annotation);
+ internal abstract Task WriteAnnotationStringAttributeAsync(IEdmDirectValueAnnotation annotation);
internal abstract void WriteAnnotationStringElement(IEdmDirectValueAnnotation annotation);
+ internal abstract Task WriteAnnotationStringElementAsync(IEdmDirectValueAnnotation annotation);
internal abstract void WriteActionElementHeader(IEdmAction action);
+ internal abstract Task WriteActionElementHeaderAsync(IEdmAction action);
internal abstract void WriteFunctionElementHeader(IEdmFunction function);
+ internal abstract Task WriteFunctionElementHeaderAsync(IEdmFunction function);
internal abstract void WriteReturnTypeElementHeader(IEdmOperationReturn operationReturn);
+ internal abstract Task WriteReturnTypeElementHeaderAsync(IEdmOperationReturn operationReturn);
internal abstract void WriteTypeAttribute(IEdmTypeReference typeReference);
+ internal abstract Task WriteTypeAttributeAsync(IEdmTypeReference typeReference);
internal abstract void WriteActionImportElementHeader(IEdmActionImport actionImport);
+ internal abstract Task WriteActionImportElementHeaderAsync(IEdmActionImport actionImport);
internal abstract void WriteFunctionImportElementHeader(IEdmFunctionImport functionImport);
+ internal abstract Task WriteFunctionImportElementHeaderAsync(IEdmFunctionImport functionImport);
internal abstract void WriteOperationParameterElementHeader(IEdmOperationParameter parameter, bool inlineType);
+ internal abstract Task WriteOperationParameterElementHeaderAsync(IEdmOperationParameter parameter, bool inlineType);
internal abstract void WriteOperationParameterEndElement(IEdmOperationParameter parameter);
+ internal abstract Task WriteOperationParameterEndElementAsync(IEdmOperationParameter parameter);
internal abstract void WriteCollectionTypeElementHeader(IEdmCollectionType collectionType, bool inlineType);
+ internal abstract Task WriteCollectionTypeElementHeaderAsync(IEdmCollectionType collectionType, bool inlineType);
internal abstract void WriteInlineExpression(IEdmExpression expression);
+ internal abstract Task WriteInlineExpressionAsync(IEdmExpression expression);
internal abstract void WriteVocabularyAnnotationElementHeader(IEdmVocabularyAnnotation annotation, bool isInline);
+ internal abstract Task WriteVocabularyAnnotationElementHeaderAsync(IEdmVocabularyAnnotation annotation, bool isInline);
internal abstract void WriteVocabularyAnnotationElementEnd(IEdmVocabularyAnnotation annotation, bool isInline);
+ internal abstract Task WriteVocabularyAnnotationElementEndAsync(IEdmVocabularyAnnotation annotation, bool isInline);
internal abstract void WritePropertyValueElementHeader(IEdmPropertyConstructor value, bool isInline);
+ internal abstract Task WritePropertyValueElementHeaderAsync(IEdmPropertyConstructor value, bool isInline);
internal abstract void WriteRecordExpressionElementHeader(IEdmRecordExpression expression);
+ internal abstract Task WriteRecordExpressionElementHeaderAsync(IEdmRecordExpression expression);
internal abstract void WritePropertyConstructorElementHeader(IEdmPropertyConstructor constructor, bool isInline);
+ internal abstract Task WritePropertyConstructorElementHeaderAsync(IEdmPropertyConstructor constructor, bool isInline);
internal abstract void WritePropertyConstructorElementEnd(IEdmPropertyConstructor constructor);
+ internal abstract Task WritePropertyConstructorElementEndAsync(IEdmPropertyConstructor constructor);
internal abstract void WriteStringConstantExpressionElement(IEdmStringConstantExpression expression);
+ internal abstract Task WriteStringConstantExpressionElementAsync(IEdmStringConstantExpression expression);
internal abstract void WriteBinaryConstantExpressionElement(IEdmBinaryConstantExpression expression);
+ internal abstract Task WriteBinaryConstantExpressionElementAsync(IEdmBinaryConstantExpression expression);
internal abstract void WriteBooleanConstantExpressionElement(IEdmBooleanConstantExpression expression);
+ internal abstract Task WriteBooleanConstantExpressionElementAsync(IEdmBooleanConstantExpression expression);
internal abstract void WriteNullConstantExpressionElement(IEdmNullExpression expression);
+ internal abstract Task WriteNullConstantExpressionElementAsync(IEdmNullExpression expression);
internal abstract void WriteDateConstantExpressionElement(IEdmDateConstantExpression expression);
+ internal abstract Task WriteDateConstantExpressionElementAsync(IEdmDateConstantExpression expression);
internal virtual void WriteSchemaOperationsHeader(KeyValuePair> operations)
{
// nothing here
}
+ internal virtual Task WriteSchemaOperationsHeaderAsync(KeyValuePair> operations)
+ {
+ return Task.CompletedTask;
+ }
+
internal virtual void WriteSchemaOperationsEnd(KeyValuePair> operation)
{
// nothing here
}
+ internal virtual Task WriteSchemaOperationsEndAsync(KeyValuePair> operation)
+ {
+ return Task.CompletedTask;
+ }
+
internal virtual void WriteOperationParametersBegin(IEnumerable parameters)
{
// nothing here
}
+ internal virtual Task WriteOperationParametersBeginAsync(IEnumerable parameters)
+ {
+ return Task.CompletedTask;
+ }
+
internal virtual void WriteOperationParametersEnd(IEnumerable parameters)
{
// nothing here
}
+ internal virtual Task WriteOperationParametersEndAsync(IEnumerable parameters)
+ {
+ return Task.CompletedTask;
+ }
+
internal abstract void WriteDateTimeOffsetConstantExpressionElement(IEdmDateTimeOffsetConstantExpression expression);
+ internal abstract Task WriteDateTimeOffsetConstantExpressionElementAsync(IEdmDateTimeOffsetConstantExpression expression);
internal abstract void WriteDurationConstantExpressionElement(IEdmDurationConstantExpression expression);
+ internal abstract Task WriteDurationConstantExpressionElementAsync(IEdmDurationConstantExpression expression);
internal abstract void WriteDecimalConstantExpressionElement(IEdmDecimalConstantExpression expression);
+ internal abstract Task WriteDecimalConstantExpressionElementAsync(IEdmDecimalConstantExpression expression);
internal abstract void WriteFloatingConstantExpressionElement(IEdmFloatingConstantExpression expression);
+ internal abstract Task WriteFloatingConstantExpressionElementAsync(IEdmFloatingConstantExpression expression);
internal abstract void WriteFunctionApplicationElementHeader(IEdmApplyExpression expression);
+ internal abstract Task WriteFunctionApplicationElementHeaderAsync(IEdmApplyExpression expression);
internal abstract void WriteFunctionApplicationElementEnd(IEdmApplyExpression expression);
+ internal abstract Task WriteFunctionApplicationElementEndAsync(IEdmApplyExpression expression);
internal abstract void WriteGuidConstantExpressionElement(IEdmGuidConstantExpression expression);
+ internal abstract Task WriteGuidConstantExpressionElementAsync(IEdmGuidConstantExpression expression);
internal abstract void WriteIntegerConstantExpressionElement(IEdmIntegerConstantExpression expression);
+ internal abstract Task WriteIntegerConstantExpressionElementAsync(IEdmIntegerConstantExpression expression);
internal abstract void WritePathExpressionElement(IEdmPathExpression expression);
+ internal abstract Task WritePathExpressionElementAsync(IEdmPathExpression expression);
internal abstract void WriteAnnotationPathExpressionElement(IEdmPathExpression expression);
+ internal abstract Task WriteAnnotationPathExpressionElementAsync(IEdmPathExpression expression);
internal abstract void WritePropertyPathExpressionElement(IEdmPathExpression expression);
+ internal abstract Task WritePropertyPathExpressionElementAsync(IEdmPathExpression expression);
internal abstract void WriteNavigationPropertyPathExpressionElement(IEdmPathExpression expression);
+ internal abstract Task WriteNavigationPropertyPathExpressionElementAsync(IEdmPathExpression expression);
internal abstract void WriteIfExpressionElementHeader(IEdmIfExpression expression);
+ internal abstract Task WriteIfExpressionElementHeaderAsync(IEdmIfExpression expression);
internal abstract void WriteIfExpressionElementEnd(IEdmIfExpression expression);
+ internal abstract Task WriteIfExpressionElementEndAsync(IEdmIfExpression expression);
internal abstract void WriteCollectionExpressionElementHeader(IEdmCollectionExpression expression);
+ internal abstract Task WriteCollectionExpressionElementHeaderAsync(IEdmCollectionExpression expression);
internal abstract void WriteCollectionExpressionElementEnd(IEdmCollectionExpression expression);
+ internal abstract Task WriteCollectionExpressionElementEndAsync(IEdmCollectionExpression expression);
internal abstract void WriteLabeledElementHeader(IEdmLabeledExpression labeledElement);
+ internal abstract Task WriteLabeledElementHeaderAsync(IEdmLabeledExpression labeledElement);
internal abstract void WriteLabeledExpressionReferenceExpression(IEdmLabeledExpressionReferenceExpression labeledExpressionReference);
+ internal abstract Task WriteLabeledExpressionReferenceExpressionAsync(IEdmLabeledExpressionReferenceExpression labeledExpressionReference);
internal abstract void WriteTimeOfDayConstantExpressionElement(IEdmTimeOfDayConstantExpression expression);
+ internal abstract Task WriteTimeOfDayConstantExpressionElementAsync(IEdmTimeOfDayConstantExpression expression);
internal abstract void WriteIsTypeExpressionElementHeader(IEdmIsTypeExpression expression, bool inlineType);
+ internal abstract Task WriteIsTypeExpressionElementHeaderAsync(IEdmIsTypeExpression expression, bool inlineType);
internal virtual void WriteIsOfExpressionType(IEdmIsTypeExpression expression, bool inlineType)
{
// nothing here
}
+ internal virtual Task WriteIsOfExpressionTypeAsync(IEdmIsTypeExpression expression, bool inlineType)
+ {
+ return Task.CompletedTask;
+ }
+
internal abstract void WriteCastExpressionElementHeader(IEdmCastExpression expression, bool inlineType);
+ internal abstract Task WriteCastExpressionElementHeaderAsync(IEdmCastExpression expression, bool inlineType);
internal abstract void WriteCastExpressionElementEnd(IEdmCastExpression expression, bool inlineType);
+ internal abstract Task WriteCastExpressionElementEndAsync(IEdmCastExpression expression, bool inlineType);
internal virtual void WriteCastExpressionType(IEdmCastExpression expression, bool inlineType)
{
// nothing here
}
+ internal virtual Task WriteCastExpressionTypeAsync(IEdmCastExpression expression, bool inlineType)
+ {
+ return Task.CompletedTask;
+ }
+
internal abstract void WriteEnumMemberExpressionElement(IEdmEnumMemberExpression expression);
+ internal abstract Task WriteEnumMemberExpressionElementAsync(IEdmEnumMemberExpression expression);
internal abstract void WriteTypeDefinitionElementHeader(IEdmTypeDefinition typeDefinition);
+ internal abstract Task WriteTypeDefinitionElementHeaderAsync(IEdmTypeDefinition typeDefinition);
internal abstract void WriteEndElement();
+ internal abstract Task WriteEndElementAsync();
internal abstract void WriteArrayEndElement();
+ internal abstract Task WriteArrayEndElementAsync();
internal abstract void WriteOperationElementAttributes(IEdmOperation operation);
+ internal abstract Task WriteOperationElementAttributesAsync(IEdmOperation operation);
internal abstract void WriteOperationImportAttributes(IEdmOperationImport operationImport, string operationAttributeName);
+ internal abstract Task WriteOperationImportAttributesAsync(IEdmOperationImport operationImport, string operationAttributeName);
internal static string PathAsXml(IEnumerable path)
{
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs
index bf3a9bfc15..2b758d80e4 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs
@@ -9,6 +9,7 @@
using System.Diagnostics;
using System.Globalization;
using System.Linq;
+using System.Threading.Tasks;
using System.Xml;
using Microsoft.OData.Edm.Csdl.CsdlSemantics;
using Microsoft.OData.Edm.Csdl.Parsing.Ast;
@@ -37,6 +38,10 @@ internal EdmModelCsdlSchemaXmlWriter(IEdmModel model, XmlWriter xmlWriter, Versi
this.writerSettings = csdlXmlWriterSettings;
}
+ ///
+ /// Writes Reference element header.
+ ///
+ /// edmx:reference element
internal override void WriteReferenceElementHeader(IEdmReference reference)
{
// e.g.
@@ -44,11 +49,41 @@ internal override void WriteReferenceElementHeader(IEdmReference reference)
this.WriteRequiredAttribute(CsdlConstants.Attribute_Uri, reference.Uri, EdmValueWriter.UriAsXml);
}
+ ///
+ /// Asynchronously writes Reference element header.
+ ///
+ /// edmx:reference element
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteReferenceElementHeaderAsync(IEdmReference reference)
+ {
+ // e.g.
+ await this.xmlWriter.WriteStartElementAsync(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_Reference, this.edmxNamespace).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Uri, reference.Uri, EdmValueWriter.UriAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the reference element end.
+ ///
+ /// edmx:reference element
internal override void WriteReferenceElementEnd(IEdmReference reference)
{
this.xmlWriter.WriteEndElement();
}
+ ///
+ /// Asynchronously writes the reference element end.
+ ///
+ /// edmx:reference element
+ /// Task represents an asynchronous operation.
+ internal override Task WriteReferenceElementEndAsync(IEdmReference reference)
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes the Include element header.
+ ///
+ /// The Edm Include information.
internal override void WritIncludeElementHeader(IEdmInclude include)
{
// e.g.
@@ -57,11 +92,42 @@ internal override void WritIncludeElementHeader(IEdmInclude include)
this.WriteRequiredAttribute(CsdlConstants.Attribute_Alias, include.Alias, EdmValueWriter.StringAsXml);
}
+ ///
+ /// Asynchronously writes the Include element header.
+ ///
+ /// The Edm Include information.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritIncludeElementHeaderAsync(IEdmInclude include)
+ {
+ // e.g.
+ await this.xmlWriter.WriteStartElementAsync(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_Include, this.edmxNamespace).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Namespace, include.Namespace, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Alias, include.Alias, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the IncludeAnnotations end.
+ ///
+ /// The Edm Include information.
internal override void WriteIncludeElementEnd(IEdmInclude include)
{
this.xmlWriter.WriteEndElement();
}
+ ///
+ /// Asynchronously writes the IncludeAnnotations end.
+ ///
+ /// The Edm Include information.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteIncludeElementEndAsync(IEdmInclude include)
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes the IncludeAnnotations element.
+ ///
+ /// The Edm Include annotations.
internal void WriteIncludeAnnotationsElement(IEdmIncludeAnnotations includeAnnotations)
{
// e.g.
@@ -72,6 +138,26 @@ internal void WriteIncludeAnnotationsElement(IEdmIncludeAnnotations includeAnnot
this.xmlWriter.WriteEndElement();
}
+ ///
+ /// Asynchronously writes the IncludeAnnotations element.
+ ///
+ /// The Edm Include annotations.
+ /// Task represents an asynchronous operation.
+ internal async Task WriteIncludeAnnotationsElementAsync(IEdmIncludeAnnotations includeAnnotations)
+ {
+ // e.g.
+ await this.xmlWriter.WriteStartElementAsync(CsdlConstants.Prefix_Edmx, CsdlConstants.Element_IncludeAnnotations, this.edmxNamespace).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_TermNamespace, includeAnnotations.TermNamespace, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Qualifier, includeAnnotations.Qualifier, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_TargetNamespace, includeAnnotations.TargetNamespace, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.xmlWriter.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes Term element header.
+ ///
+ /// The Edm term.
+ /// Is inline type or not.
internal override void WriteTermElementHeader(IEdmTerm term, bool inlineType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Term);
@@ -85,6 +171,28 @@ internal override void WriteTermElementHeader(IEdmTerm term, bool inlineType)
this.WriteOptionalAttribute(CsdlConstants.Attribute_AppliesTo, term.AppliesTo, EdmValueWriter.StringAsXml);
}
+ ///
+ /// Asynchronously writes Term element header.
+ ///
+ /// The Edm term.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteTermElementHeaderAsync(IEdmTerm term, bool inlineType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Term, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, term.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (inlineType && term.Type is not null)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, term.Type, this.TypeReferenceAsXml).ConfigureAwait(false);
+ }
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_DefaultValue, term.DefaultValue, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_AppliesTo, term.AppliesTo, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the ComplexType element header.
+ ///
+ /// The Edm Complex type.
internal override void WriteComplexTypeElementHeader(IEdmComplexType complexType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_ComplexType);
@@ -94,6 +202,24 @@ internal override void WriteComplexTypeElementHeader(IEdmComplexType complexType
this.WriteOptionalAttribute(CsdlConstants.Attribute_OpenType, complexType.IsOpen, CsdlConstants.Default_OpenType, EdmValueWriter.BooleanAsXml);
}
+ ///
+ /// Asynchronously writes the ComplexType element header.
+ ///
+ /// The Edm Complex type.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteComplexTypeElementHeaderAsync(IEdmComplexType complexType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_ComplexType, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, complexType.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_BaseType, complexType.BaseComplexType(), this.TypeDefinitionAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Abstract, complexType.IsAbstract, CsdlConstants.Default_Abstract, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_OpenType, complexType.IsOpen, CsdlConstants.Default_OpenType, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the EnumType element header.
+ ///
+ /// The Edm enumaration type.
internal override void WriteEnumTypeElementHeader(IEdmEnumType enumType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_EnumType);
@@ -106,11 +232,46 @@ internal override void WriteEnumTypeElementHeader(IEdmEnumType enumType)
this.WriteOptionalAttribute(CsdlConstants.Attribute_IsFlags, enumType.IsFlags, CsdlConstants.Default_IsFlags, EdmValueWriter.BooleanAsXml);
}
+ ///
+ /// Asynchronously writes the EnumType element header.
+ ///
+ /// The Edm enumaration type.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteEnumTypeElementHeaderAsync(IEdmEnumType enumType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_EnumType, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, enumType.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (enumType.UnderlyingType.PrimitiveKind != EdmPrimitiveTypeKind.Int32)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_UnderlyingType, enumType.UnderlyingType, this.TypeDefinitionAsXml).ConfigureAwait(false);
+ }
+
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_IsFlags, enumType.IsFlags, CsdlConstants.Default_IsFlags, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the EnumContainer element end.
+ ///
+ /// The Edm enumaration type.
internal override void WriteEnumTypeElementEnd(IEdmEnumType enumType)
{
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes the EnumContainer element end.
+ ///
+ /// The Edm enumaration type.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteEnumTypeElementEndAsync(IEdmEnumType enumType)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes the EntityContainer element header.
+ ///
+ /// The Edm Entity container.
internal override void WriteEntityContainerElementHeader(IEdmEntityContainer container)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_EntityContainer);
@@ -123,6 +284,25 @@ internal override void WriteEntityContainerElementHeader(IEdmEntityContainer con
}
}
+ ///
+ /// Asynchronously writes the EntityContainer element header.
+ ///
+ /// The Edm Entity container.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteEntityContainerElementHeaderAsync(IEdmEntityContainer container)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_EntityContainer, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, container.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (container is CsdlSemanticsEntityContainer tmp && tmp.Element is CsdlEntityContainer csdlContainer)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Extends, csdlContainer.Extends, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes the EntitySet element header.
+ ///
+ /// The Edm Entity set.
internal override void WriteEntitySetElementHeader(IEdmEntitySet entitySet)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_EntitySet);
@@ -130,6 +310,22 @@ internal override void WriteEntitySetElementHeader(IEdmEntitySet entitySet)
this.WriteRequiredAttribute(CsdlConstants.Attribute_EntityType, entitySet.EntityType.FullName(), EdmValueWriter.StringAsXml);
}
+ ///
+ /// Asynchronously writes the EntitySet element header.
+ ///
+ /// The Edm Entity set.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteEntitySetElementHeaderAsync(IEdmEntitySet entitySet)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_EntitySet, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, entitySet.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_EntityType, entitySet.EntityType.FullName(), EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the Singleton element header.
+ ///
+ /// The Edm singleton.
internal override void WriteSingletonElementHeader(IEdmSingleton singleton)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Singleton);
@@ -137,6 +333,22 @@ internal override void WriteSingletonElementHeader(IEdmSingleton singleton)
this.WriteRequiredAttribute(CsdlConstants.Attribute_Type, singleton.EntityType.FullName(), EdmValueWriter.StringAsXml);
}
+ ///
+ /// Asynchronously writes the Singleton element header.
+ ///
+ /// The Edm singleton.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteSingletonElementHeaderAsync(IEdmSingleton singleton)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Singleton, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, singleton.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, singleton.EntityType.FullName(), EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the EntityType element header.
+ ///
+ /// The Edm entity type.
internal override void WriteEntityTypeElementHeader(IEdmEntityType entityType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_EntityType);
@@ -150,11 +362,45 @@ internal override void WriteEntityTypeElementHeader(IEdmEntityType entityType)
this.WriteOptionalAttribute(CsdlConstants.Attribute_HasStream, writeHasStream, CsdlConstants.Default_HasStream, EdmValueWriter.BooleanAsXml);
}
+ ///
+ /// Asynchronously writes the EntityType element header.
+ ///
+ /// The Edm entity type.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteEntityTypeElementHeaderAsync(IEdmEntityType entityType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_EntityType, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, entityType.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_BaseType, entityType.BaseEntityType(), this.TypeDefinitionAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Abstract, entityType.IsAbstract, CsdlConstants.Default_Abstract, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_OpenType, entityType.IsOpen, CsdlConstants.Default_OpenType, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+
+ // HasStream value should be inherited. Only have it on base type is sufficient.
+ bool writeHasStream = entityType.HasStream && (entityType.BaseEntityType() == null || (entityType.BaseEntityType() != null && !entityType.BaseEntityType().HasStream));
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_HasStream, writeHasStream, CsdlConstants.Default_HasStream, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Asynchronously writes the key properties element header.
+ ///
internal override void WriteDeclaredKeyPropertiesElementHeader()
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Key);
}
+ ///
+ /// Asynchronously writes the key properties element header.
+ ///
+ /// Task represents an asynchronous operation.
+ internal override Task WriteDeclaredKeyPropertiesElementHeaderAsync()
+ {
+ return this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Key, null);
+ }
+
+ ///
+ /// Writes the PropertyRef element.
+ ///
+ /// The Edm Structural Property.
internal override void WritePropertyRefElement(IEdmStructuralProperty property)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_PropertyRef);
@@ -162,6 +408,22 @@ internal override void WritePropertyRefElement(IEdmStructuralProperty property)
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes the PropertyRef element.
+ ///
+ /// The Edm Structural Property.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritePropertyRefElementAsync(IEdmStructuralProperty property)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_PropertyRef, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, property.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the NavigationProperty element header.
+ ///
+ /// The Edm navigation property.
internal override void WriteNavigationPropertyElementHeader(IEdmNavigationProperty property)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_NavigationProperty);
@@ -181,6 +443,34 @@ internal override void WriteNavigationPropertyElementHeader(IEdmNavigationProper
this.WriteOptionalAttribute(CsdlConstants.Attribute_ContainsTarget, property.ContainsTarget, CsdlConstants.Default_ContainsTarget, EdmValueWriter.BooleanAsXml);
}
+ ///
+ /// Asynchronously writes the NavigationProperty element header.
+ ///
+ /// The Edm navigation property.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteNavigationPropertyElementHeaderAsync(IEdmNavigationProperty property)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_NavigationProperty, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, property.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, property.Type, this.TypeReferenceAsXml).ConfigureAwait(false);
+ if (!property.Type.IsCollection() && property.Type.IsNullable != CsdlConstants.Default_Nullable)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Nullable, property.Type.IsNullable, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+
+ if (property.Partner != null)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Partner, property.GetPartnerPath()?.Path, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_ContainsTarget, property.ContainsTarget, CsdlConstants.Default_ContainsTarget, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the NavigationOnDeleteAction element.
+ ///
+ /// The Edm OnDelete action.
internal override void WriteNavigationOnDeleteActionElement(EdmOnDeleteAction operationAction)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_OnDelete);
@@ -188,6 +478,24 @@ internal override void WriteNavigationOnDeleteActionElement(EdmOnDeleteAction op
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes the NavigationOnDeleteAction element.
+ ///
+ /// The Edm OnDelete action.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteNavigationOnDeleteActionElementAsync(EdmOnDeleteAction operationAction)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_OnDelete, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Action, operationAction.ToString(), EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the Schema element header.
+ ///
+ /// The Edm schema.
+ /// The alias.
+ /// Collection of mappings.
internal override void WriteSchemaElementHeader(EdmSchema schema, string alias, IEnumerable> mappings)
{
string xmlNamespace = GetCsdlNamespace(EdmVersion);
@@ -203,12 +511,55 @@ internal override void WriteSchemaElementHeader(EdmSchema schema, string alias,
}
}
+ ///
+ /// Asynchronously writes the Schema element header.
+ ///
+ /// The Edm schema.
+ /// The alias.
+ /// Collection of mappings.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteSchemaElementHeaderAsync(EdmSchema schema, string alias, IEnumerable> mappings)
+ {
+ string xmlNamespace = GetCsdlNamespace(EdmVersion);
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Schema, xmlNamespace).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Namespace, schema.Namespace, string.Empty, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Alias, alias, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (mappings != null)
+ {
+ foreach (KeyValuePair mapping in mappings)
+ {
+ await this.xmlWriter.WriteAttributeStringAsync(EdmConstants.XmlNamespacePrefix, mapping.Key, null, mapping.Value).ConfigureAwait(false);
+ }
+ }
+ }
+
+ ///
+ /// Writes the Annotations element header.
+ ///
+ /// The Key/Value of Edm Vocabulary annotation.
internal override void WriteAnnotationsElementHeader(KeyValuePair> annotationsForTarget)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Annotations);
this.WriteRequiredAttribute(CsdlConstants.Attribute_Target, annotationsForTarget.Key, EdmValueWriter.StringAsXml);
}
+
+ ///
+ /// Asynchronously writes the Annotations element header.
+ ///
+ /// The Key/Value of Edm Vocabulary annotation.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteAnnotationsElementHeaderAsync(KeyValuePair> annotationsForTarget)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Annotations, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Target, annotationsForTarget.Key, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes the StructuralProperty element header.
+ ///
+ /// The Edm Structural Property.
+ /// Is inline type or not.
internal override void WriteStructuralPropertyElementHeader(IEdmStructuralProperty property, bool inlineType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Property);
@@ -221,6 +572,28 @@ internal override void WriteStructuralPropertyElementHeader(IEdmStructuralProper
this.WriteOptionalAttribute(CsdlConstants.Attribute_DefaultValue, property.DefaultValueString, EdmValueWriter.StringAsXml);
}
+ ///
+ /// Asynchronously writes the StructuralProperty element header.
+ ///
+ /// The Edm Structural Property.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteStructuralPropertyElementHeaderAsync(IEdmStructuralProperty property, bool inlineType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Property, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, property.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (inlineType)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, property.Type, this.TypeReferenceAsXml).ConfigureAwait(false);
+ }
+
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_DefaultValue, property.DefaultValueString, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes Enum Member element header.
+ ///
+ /// The Edm enumeration member.
internal override void WriteEnumMemberElementHeader(IEdmEnumMember member)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Member);
@@ -232,16 +605,64 @@ internal override void WriteEnumMemberElementHeader(IEdmEnumMember member)
}
}
+ ///
+ /// Asynchronously writes enumeration member element header.
+ ///
+ /// The Edm enumeration member.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteEnumMemberElementHeaderAsync(IEdmEnumMember member)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Member, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, member.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ bool? isExplicit = member.IsValueExplicit(this.Model);
+ if (!isExplicit.HasValue || isExplicit.Value)
+ {
+ await this.xmlWriter.WriteAttributeStringAsync(null, CsdlConstants.Attribute_Value, null, EdmValueWriter.LongAsXml(member.Value.Value)).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes enumeration member element end.
+ ///
+ /// The Edm enumeration member.
internal override void WriteEnumMemberElementEnd(IEdmEnumMember member)
{
this.xmlWriter.WriteEndElement();
}
+ ///
+ /// Asynchronously writes EnumMember element end.
+ ///
+ /// The Edm enumeration member.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteEnumMemberElementEndAsync(IEdmEnumMember member)
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes Nullable attribute.
+ ///
+ /// The Edm type reference.
internal override void WriteNullableAttribute(IEdmTypeReference reference)
{
this.WriteOptionalAttribute(CsdlConstants.Attribute_Nullable, reference.IsNullable, CsdlConstants.Default_Nullable, EdmValueWriter.BooleanAsXml);
}
+ ///
+ /// Asynchronously writes Nullable attribute.
+ ///
+ /// The Edm type reference.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteNullableAttributeAsync(IEdmTypeReference reference)
+ {
+ return this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Nullable, reference.IsNullable, CsdlConstants.Default_Nullable, EdmValueWriter.BooleanAsXml);
+ }
+
+ ///
+ /// Writes TypeDefinition attributes.
+ ///
+ /// The Edm type defination reference.
internal override void WriteTypeDefinitionAttributes(IEdmTypeDefinitionReference reference)
{
IEdmTypeReference actualTypeReference = reference.AsActualTypeReference();
@@ -268,6 +689,47 @@ internal override void WriteTypeDefinitionAttributes(IEdmTypeDefinitionReference
}
}
+ ///
+ /// Asynchronously writes TypeDefinition attributes.
+ ///
+ /// The Edm type defination reference.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteTypeDefinitionAttributesAsync(IEdmTypeDefinitionReference reference)
+ {
+ IEdmTypeReference actualTypeReference = reference.AsActualTypeReference();
+
+ if (actualTypeReference.IsBinary())
+ {
+ return this.WriteBinaryTypeAttributesAsync(actualTypeReference.AsBinary());
+ }
+
+ if (actualTypeReference.IsString())
+ {
+ return this.WriteStringTypeAttributesAsync(actualTypeReference.AsString());
+ }
+
+ if (actualTypeReference.IsTemporal())
+ {
+ return this.WriteTemporalTypeAttributesAsync(actualTypeReference.AsTemporal());
+ }
+
+ if (actualTypeReference.IsDecimal())
+ {
+ return this.WriteDecimalTypeAttributesAsync(actualTypeReference.AsDecimal());
+ }
+
+ if (actualTypeReference.IsSpatial())
+ {
+ return this.WriteSpatialTypeAttributesAsync(actualTypeReference.AsSpatial());
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes BinaryType attributes.
+ ///
+ /// The Edm binary type reference.
internal override void WriteBinaryTypeAttributes(IEdmBinaryTypeReference reference)
{
if (reference.IsUnbounded)
@@ -280,6 +742,25 @@ internal override void WriteBinaryTypeAttributes(IEdmBinaryTypeReference referen
}
}
+ ///
+ /// Asynchronously writes BinaryType attributes.
+ ///
+ /// The Edm binary type reference.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteBinaryTypeAttributesAsync(IEdmBinaryTypeReference reference)
+ {
+ if (reference.IsUnbounded)
+ {
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_MaxLength, CsdlConstants.Value_Max, EdmValueWriter.StringAsXml);
+ }
+
+ return this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_MaxLength, reference.MaxLength, EdmValueWriter.IntAsXml);
+ }
+
+ ///
+ /// Writes DecimalType attributes.
+ ///
+ /// The Edm Decimal type reference.
internal override void WriteDecimalTypeAttributes(IEdmDecimalTypeReference reference)
{
this.WriteOptionalAttribute(CsdlConstants.Attribute_Precision, reference.Precision, EdmValueWriter.IntAsXml);
@@ -291,6 +772,21 @@ internal override void WriteDecimalTypeAttributes(IEdmDecimalTypeReference refer
this.WriteRequiredAttribute(CsdlConstants.Attribute_Scale, reference.Scale, ScaleAsXml);
}
+ ///
+ /// Asynchronously writes DecimalType attributes.
+ ///
+ /// The Edm Decimal type reference.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteDecimalTypeAttributesAsync(IEdmDecimalTypeReference reference)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Precision, reference.Precision, EdmValueWriter.IntAsXml).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Scale, reference.Scale, ScaleAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes SpatialType attributes.
+ ///
+ /// The Edm Spatial type reference.
internal override void WriteSpatialTypeAttributes(IEdmSpatialTypeReference reference)
{
if (reference.IsGeography())
@@ -303,6 +799,30 @@ internal override void WriteSpatialTypeAttributes(IEdmSpatialTypeReference refer
}
}
+ ///
+ /// Asynchronously writes SpatialType attributes.
+ ///
+ /// The Edm Spatial type reference.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteSpatialTypeAttributesAsync(IEdmSpatialTypeReference reference)
+ {
+ if (reference.IsGeography())
+ {
+ return this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Srid, reference.SpatialReferenceIdentifier, CsdlConstants.Default_SpatialGeographySrid, SridAsXml);
+ }
+
+ if (reference.IsGeometry())
+ {
+ return this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Srid, reference.SpatialReferenceIdentifier, CsdlConstants.Default_SpatialGeometrySrid, SridAsXml);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes StringType attributes.
+ ///
+ /// The Edm String type reference.
internal override void WriteStringTypeAttributes(IEdmStringTypeReference reference)
{
if (reference.IsUnbounded)
@@ -320,6 +840,32 @@ internal override void WriteStringTypeAttributes(IEdmStringTypeReference referen
}
}
+ ///
+ /// Asynchronously writes StringType attributes.
+ ///
+ /// The Edm String type reference.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteStringTypeAttributesAsync(IEdmStringTypeReference reference)
+ {
+ if (reference.IsUnbounded)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_MaxLength, CsdlConstants.Value_Max, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+ else
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_MaxLength, reference.MaxLength, EdmValueWriter.IntAsXml).ConfigureAwait(false);
+ }
+
+ if (reference.IsUnicode != null)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Unicode, reference.IsUnicode, CsdlConstants.Default_IsUnicode, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes TemporalType attributes.
+ ///
+ /// The Edm Temporal type reference.
internal override void WriteTemporalTypeAttributes(IEdmTemporalTypeReference reference)
{
if (reference.Precision != null)
@@ -328,6 +874,23 @@ internal override void WriteTemporalTypeAttributes(IEdmTemporalTypeReference ref
}
}
+ ///
+ /// Asynchronously writes TemporalType attributes.
+ ///
+ /// The Edm Temporal type reference.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteTemporalTypeAttributesAsync(IEdmTemporalTypeReference reference)
+ {
+ if (reference.Precision != null)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Precision, reference.Precision, CsdlConstants.Default_TemporalPrecision, EdmValueWriter.IntAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes ReferentialConstraint pair.
+ ///
+ /// The Edm Referential Constraint property pair.
internal override void WriteReferentialConstraintPair(EdmReferentialConstraintPropertyPair pair)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_ReferentialConstraint);
@@ -345,6 +908,32 @@ internal override void WriteReferentialConstraintPair(EdmReferentialConstraintPr
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes ReferentialConstraint pair.
+ ///
+ /// The Edm Referential Constraint property pair.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteReferentialConstraintPairAsync(EdmReferentialConstraintPropertyPair pair)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_ReferentialConstraint, null).ConfigureAwait(false);
+
+ //
+ // ...
+ //
+ //
+ //
+ //
+ //
+ // the above CategoryID is DependentProperty, ID is PrincipalProperty.
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Property, pair.DependentProperty.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_ReferencedProperty, pair.PrincipalProperty.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes Annotation string attribute.
+ ///
+ /// The Edm Direct value annotation.
internal override void WriteAnnotationStringAttribute(IEdmDirectValueAnnotation annotation)
{
var edmValue = (IEdmPrimitiveValue)annotation.Value;
@@ -354,6 +943,23 @@ internal override void WriteAnnotationStringAttribute(IEdmDirectValueAnnotation
}
}
+ ///
+ /// Asynchronously writes Annotation string attribute.
+ ///
+ /// The Edm Direct value annotation.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteAnnotationStringAttributeAsync(IEdmDirectValueAnnotation annotation)
+ {
+ if (annotation.Value is IEdmPrimitiveValue edmValue)
+ {
+ await this.xmlWriter.WriteAttributeStringAsync(null, annotation.Name, annotation.NamespaceUri, EdmValueWriter.PrimitiveValueAsXml(edmValue)).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Annotation string element.
+ ///
+ /// The Edm Direct value annotation.
internal override void WriteAnnotationStringElement(IEdmDirectValueAnnotation annotation)
{
var edmValue = (IEdmPrimitiveValue)annotation.Value;
@@ -363,12 +969,44 @@ internal override void WriteAnnotationStringElement(IEdmDirectValueAnnotation an
}
}
+ ///
+ /// Asynchronously writes Annotation string element.
+ ///
+ /// The Edm Direct value annotation.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteAnnotationStringElementAsync(IEdmDirectValueAnnotation annotation)
+ {
+ if (annotation.Value is IEdmPrimitiveValue edmValue)
+ {
+ await this.xmlWriter.WriteRawAsync(((IEdmStringValue)edmValue).Value).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Action element header.
+ ///
+ /// The Edm Action.
internal override void WriteActionElementHeader(IEdmAction action)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Action);
this.WriteOperationElementAttributes(action);
}
+ ///
+ /// Asynchronously writes Action element header.
+ ///
+ /// The Edm Action.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteActionElementHeaderAsync(IEdmAction action)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Action, null).ConfigureAwait(false);
+ await this.WriteOperationElementAttributesAsync(action).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes Function element header.
+ ///
+ /// The Edm Function.
internal override void WriteFunctionElementHeader(IEdmFunction function)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Function);
@@ -380,22 +1018,85 @@ internal override void WriteFunctionElementHeader(IEdmFunction function)
}
}
+ ///
+ /// Asynchronously writes Function element header.
+ ///
+ /// The Edm Function.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteFunctionElementHeaderAsync(IEdmFunction function)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Function, null).ConfigureAwait(false);
+ await this.WriteOperationElementAttributesAsync(function).ConfigureAwait(false);
+
+ if (function.IsComposable)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_IsComposable, function.IsComposable, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes ReturnType element header.
+ ///
+ /// The Edm Operation return.
internal override void WriteReturnTypeElementHeader(IEdmOperationReturn operationReturn)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_ReturnType);
}
+ ///
+ /// Asynchronously writes ReturnType element header.
+ ///
+ /// The Edm Operation return.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteReturnTypeElementHeaderAsync(IEdmOperationReturn operationReturn)
+ {
+ return this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_ReturnType, null);
+ }
+
+ ///
+ /// Writes Type attribute.
+ ///
+ /// The Edm type reference.
internal override void WriteTypeAttribute(IEdmTypeReference typeReference)
{
this.WriteRequiredAttribute(CsdlConstants.Attribute_Type, typeReference, this.TypeReferenceAsXml);
}
+ ///
+ /// Asynchronously writes Type attribute.
+ ///
+ /// The Edm type reference.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteTypeAttributeAsync(IEdmTypeReference typeReference)
+ {
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, typeReference, this.TypeReferenceAsXml);
+ }
+
+ ///
+ /// Writes ActionImport element header.
+ ///
+ /// The Edm action import.
internal override void WriteActionImportElementHeader(IEdmActionImport actionImport)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_ActionImport);
this.WriteOperationImportAttributes(actionImport, CsdlConstants.Attribute_Action);
}
+ ///
+ /// Asynchronously writes ActionImport element header.
+ ///
+ /// The Edm action import.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteActionImportElementHeaderAsync(IEdmActionImport actionImport)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_ActionImport, null).ConfigureAwait(false);
+ await this.WriteOperationImportAttributesAsync(actionImport, CsdlConstants.Attribute_Action).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes FunctionImport element header.
+ ///
+ /// The Edm function import.
internal override void WriteFunctionImportElementHeader(IEdmFunctionImport functionImport)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_FunctionImport);
@@ -403,6 +1104,23 @@ internal override void WriteFunctionImportElementHeader(IEdmFunctionImport funct
this.WriteOptionalAttribute(CsdlConstants.Attribute_IncludeInServiceDocument, functionImport.IncludeInServiceDocument, CsdlConstants.Default_IncludeInServiceDocument, EdmValueWriter.BooleanAsXml);
}
+ ///
+ /// Asynchronously writes FunctionImport element header.
+ ///
+ /// The Edm function import.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteFunctionImportElementHeaderAsync(IEdmFunctionImport functionImport)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_FunctionImport, null).ConfigureAwait(false);
+ await this.WriteOperationImportAttributesAsync(functionImport, CsdlConstants.Attribute_Function).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_IncludeInServiceDocument, functionImport.IncludeInServiceDocument, CsdlConstants.Default_IncludeInServiceDocument, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes OperationParameter element header.
+ ///
+ /// The Edm Operation parameter
+ /// Is inline type or not.
internal override void WriteOperationParameterElementHeader(IEdmOperationParameter parameter, bool inlineType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Parameter);
@@ -413,6 +1131,26 @@ internal override void WriteOperationParameterElementHeader(IEdmOperationParamet
}
}
+ ///
+ /// Asynchronously writes OperationParameter element header.
+ ///
+ /// The Edm Operation parameter
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteOperationParameterElementHeaderAsync(IEdmOperationParameter parameter, bool inlineType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Parameter, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, parameter.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (inlineType)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, parameter.Type, this.TypeReferenceAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes OperationParameter end element.
+ ///
+ /// The Edm operation paramater.
internal override void WriteOperationParameterEndElement(IEdmOperationParameter parameter)
{
IEdmOptionalParameter optionalParameter = parameter as IEdmOptionalParameter;
@@ -437,6 +1175,41 @@ internal override void WriteOperationParameterEndElement(IEdmOperationParameter
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes OperationParameter end element.
+ ///
+ /// The Edm operation paramater.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteOperationParameterEndElementAsync(IEdmOperationParameter parameter)
+ {
+ if (parameter is IEdmOptionalParameter optionalParameter &&
+ !(optionalParameter.VocabularyAnnotations(this.Model).Any(a => a.Term == CoreVocabularyModel.OptionalParameterTerm)))
+ {
+ var optionalValue = new EdmRecordExpression();
+
+ var vocabularyAnnotation = new EdmVocabularyAnnotation(parameter, CoreVocabularyModel.OptionalParameterTerm, optionalValue);
+ await this.WriteVocabularyAnnotationElementHeaderAsync(vocabularyAnnotation, false).ConfigureAwait(false);
+
+ if (!string.IsNullOrEmpty(optionalParameter.DefaultValueString))
+ {
+ var property = new EdmPropertyConstructor(CsdlConstants.Attribute_DefaultValue, new EdmStringConstant(optionalParameter.DefaultValueString));
+ await this.WriteRecordExpressionElementHeaderAsync(optionalValue).ConfigureAwait(false);
+ await this.WritePropertyValueElementHeaderAsync(property, true).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes CollectionType element header.
+ ///
+ /// The Edm Collection type.
+ /// Is inline type or not.
internal override void WriteCollectionTypeElementHeader(IEdmCollectionType collectionType, bool inlineType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_CollectionType);
@@ -446,6 +1219,25 @@ internal override void WriteCollectionTypeElementHeader(IEdmCollectionType colle
}
}
+ ///
+ /// Asynchronously writes CollectionType element header.
+ ///
+ /// The Edm Collection type.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteCollectionTypeElementHeaderAsync(IEdmCollectionType collectionType, bool inlineType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_CollectionType, null).ConfigureAwait(false);
+ if (inlineType)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_ElementType, collectionType.ElementType, this.TypeReferenceAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Inline expression.
+ ///
+ /// The Edm expression.
internal override void WriteInlineExpression(IEdmExpression expression)
{
IEdmPathExpression pathExpression = expression as IEdmPathExpression;
@@ -502,11 +1294,76 @@ internal override void WriteInlineExpression(IEdmExpression expression)
}
}
+ ///
+ /// Asynchronously writes Inline expression.
+ ///
+ /// The Edm expression.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteInlineExpressionAsync(IEdmExpression expression)
+ {
+ IEdmPathExpression pathExpression = expression as IEdmPathExpression;
+ switch (expression.ExpressionKind)
+ {
+ case EdmExpressionKind.BinaryConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Binary, ((IEdmBinaryConstantExpression)expression).Value, EdmValueWriter.BinaryAsXml);
+ case EdmExpressionKind.BooleanConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Bool, ((IEdmBooleanConstantExpression)expression).Value, EdmValueWriter.BooleanAsXml);
+ case EdmExpressionKind.DateTimeOffsetConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_DateTimeOffset, ((IEdmDateTimeOffsetConstantExpression)expression).Value, EdmValueWriter.DateTimeOffsetAsXml);
+ case EdmExpressionKind.DecimalConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Decimal, ((IEdmDecimalConstantExpression)expression).Value, EdmValueWriter.DecimalAsXml);
+ case EdmExpressionKind.FloatingConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Float, ((IEdmFloatingConstantExpression)expression).Value, EdmValueWriter.FloatAsXml);
+ case EdmExpressionKind.GuidConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Guid, ((IEdmGuidConstantExpression)expression).Value, EdmValueWriter.GuidAsXml);
+ case EdmExpressionKind.IntegerConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Int, ((IEdmIntegerConstantExpression)expression).Value, EdmValueWriter.LongAsXml);
+ case EdmExpressionKind.Path:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Path, pathExpression.PathSegments, PathAsXml);
+ case EdmExpressionKind.PropertyPath:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_PropertyPath, pathExpression.PathSegments, PathAsXml);
+ case EdmExpressionKind.NavigationPropertyPath:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_NavigationPropertyPath, pathExpression.PathSegments, PathAsXml);
+ case EdmExpressionKind.AnnotationPath:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_AnnotationPath, pathExpression.PathSegments, PathAsXml);
+ case EdmExpressionKind.StringConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_String, ((IEdmStringConstantExpression)expression).Value, EdmValueWriter.StringAsXml);
+ case EdmExpressionKind.DurationConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Duration, ((IEdmDurationConstantExpression)expression).Value, EdmValueWriter.DurationAsXml);
+ case EdmExpressionKind.DateConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Date, ((IEdmDateConstantExpression)expression).Value, EdmValueWriter.DateAsXml);
+ case EdmExpressionKind.TimeOfDayConstant:
+ return this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_TimeOfDay, ((IEdmTimeOfDayConstantExpression)expression).Value, EdmValueWriter.TimeOfDayAsXml);
+ default:
+ Debug.Assert(false, "Attempted to inline an expression that was not one of the expected inlineable types.");
+ return Task.CompletedTask;
+ }
+ }
+
+ ///
+ /// Writes PropertyConstructor element end.
+ ///
+ /// The Edm property constructor.
internal override void WritePropertyConstructorElementEnd(IEdmPropertyConstructor constructor)
{
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes PropertyConstructor element end.
+ ///
+ /// The Edm property constructor.
+ /// Task represents an asynchronous operation.
+ internal override Task WritePropertyConstructorElementEndAsync(IEdmPropertyConstructor constructor)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes VocabularyAnnotation element header.
+ ///
+ /// The Edm vocabulary annotation.
+ /// Is inline type or not.
internal override void WriteVocabularyAnnotationElementHeader(IEdmVocabularyAnnotation annotation, bool isInline)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Annotation);
@@ -520,11 +1377,51 @@ internal override void WriteVocabularyAnnotationElementHeader(IEdmVocabularyAnno
}
}
+ ///
+ /// Asynchronously writes VocabularyAnnotation element header.
+ ///
+ /// The Edm vocabulary annotation.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteVocabularyAnnotationElementHeaderAsync(IEdmVocabularyAnnotation annotation, bool isInline)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Annotation, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Term, annotation.Term, this.TermAsXml).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Qualifier, annotation.Qualifier, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+
+ if (isInline && !annotation.UsesDefault)
+ {
+ // in xml format, we can (should) skip writing the expression value if it matches the term default value.
+ await this.WriteInlineExpressionAsync(annotation.Value).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes VocabularyAnnotation element end.
+ ///
+ /// The Edm vocabulary annotation.
+ /// Is inline type or not.
internal override void WriteVocabularyAnnotationElementEnd(IEdmVocabularyAnnotation annotation, bool isInline)
{
WriteEndElement();
}
+ ///
+ /// Asynchronously writes VocabularyAnnotation element end.
+ ///
+ /// The Edm vocabulary annotation.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteVocabularyAnnotationElementEndAsync(IEdmVocabularyAnnotation annotation, bool isInline)
+ {
+ return WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes PropertyValue element header.
+ ///
+ /// The Edm property constructor.
+ /// Is inline type or not.
internal override void WritePropertyValueElementHeader(IEdmPropertyConstructor value, bool isInline)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_PropertyValue);
@@ -535,12 +1432,48 @@ internal override void WritePropertyValueElementHeader(IEdmPropertyConstructor v
}
}
+ ///
+ /// Asynchronously writes PropertyValue element header.
+ ///
+ /// The Edm property constructor.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritePropertyValueElementHeaderAsync(IEdmPropertyConstructor value, bool isInline)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_PropertyValue, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Property, value.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (isInline)
+ {
+ await this.WriteInlineExpressionAsync(value.Value).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes RecordExpression element header.
+ ///
+ /// The Edm Record expression.
internal override void WriteRecordExpressionElementHeader(IEdmRecordExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Record);
this.WriteOptionalAttribute(CsdlConstants.Attribute_Type, expression.DeclaredType, this.TypeReferenceAsXml);
}
+ ///
+ /// Asynchronously writes RecordExpression element header.
+ ///
+ /// The Edm Record expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteRecordExpressionElementHeaderAsync(IEdmRecordExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Record, null).ConfigureAwait(false);
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_Type, expression.DeclaredType, this.TypeReferenceAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes PropertyConstructor element header.
+ ///
+ /// The Edm property constructor.
+ /// Is inline type or not.
internal override void WritePropertyConstructorElementHeader(IEdmPropertyConstructor constructor, bool isInline)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_PropertyValue);
@@ -551,6 +1484,26 @@ internal override void WritePropertyConstructorElementHeader(IEdmPropertyConstru
}
}
+ ///
+ /// Asynchronously writes PropertyConstructor element header.
+ ///
+ /// The Edm property constructor.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritePropertyConstructorElementHeaderAsync(IEdmPropertyConstructor constructor, bool isInline)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_PropertyValue, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Property, constructor.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ if (isInline)
+ {
+ await this.WriteInlineExpressionAsync(constructor.Value).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes StringConstantExpression element.
+ ///
+ /// The Edm String constant expression.
internal override void WriteStringConstantExpressionElement(IEdmStringConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_String);
@@ -559,6 +1512,23 @@ internal override void WriteStringConstantExpressionElement(IEdmStringConstantEx
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes StringConstantExpression element.
+ ///
+ /// The Edm String constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteStringConstantExpressionElementAsync(IEdmStringConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_String, null).ConfigureAwait(false);
+
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.StringAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes BinaryConstantExpression element.
+ ///
+ /// The Edm Binary constant expression.
internal override void WriteBinaryConstantExpressionElement(IEdmBinaryConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Binary);
@@ -566,6 +1536,22 @@ internal override void WriteBinaryConstantExpressionElement(IEdmBinaryConstantEx
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes BinaryConstantExpression element.
+ ///
+ /// The Edm Binary constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteBinaryConstantExpressionElementAsync(IEdmBinaryConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Binary, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.BinaryAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes BooleanConstantExpression element.
+ ///
+ /// The Edm Boolean constant expression.
internal override void WriteBooleanConstantExpressionElement(IEdmBooleanConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Bool);
@@ -573,12 +1559,43 @@ internal override void WriteBooleanConstantExpressionElement(IEdmBooleanConstant
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes BooleanConstantExpression element.
+ ///
+ /// The Edm Boolean constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteBooleanConstantExpressionElementAsync(IEdmBooleanConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Bool, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.BooleanAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes NullConstantExpression element.
+ ///
+ /// The Edm Null expression.
internal override void WriteNullConstantExpressionElement(IEdmNullExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Null);
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes NullConstantExpression element.
+ ///
+ /// The Edm Null expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteNullConstantExpressionElementAsync(IEdmNullExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Null, null).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes DateConstantExpression element.
+ ///
+ /// The Edm Date constant expression.
internal override void WriteDateConstantExpressionElement(IEdmDateConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Date);
@@ -586,6 +1603,22 @@ internal override void WriteDateConstantExpressionElement(IEdmDateConstantExpres
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes DateConstantExpression element.
+ ///
+ /// The Edm Date constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteDateConstantExpressionElementAsync(IEdmDateConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Date, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.DateAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes DateTimeOffsetConstantExpression element.
+ ///
+ /// The Edm DateTimeOffset constant expression.
internal override void WriteDateTimeOffsetConstantExpressionElement(IEdmDateTimeOffsetConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_DateTimeOffset);
@@ -593,6 +1626,22 @@ internal override void WriteDateTimeOffsetConstantExpressionElement(IEdmDateTime
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes DateTimeOffsetConstantExpression element.
+ ///
+ /// The Edm DateTimeOffset constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteDateTimeOffsetConstantExpressionElementAsync(IEdmDateTimeOffsetConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_DateTimeOffset, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.DateTimeOffsetAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes DurationConstantExpression element.
+ ///
+ /// The Edm Duration constant expression.
internal override void WriteDurationConstantExpressionElement(IEdmDurationConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Duration);
@@ -600,6 +1649,22 @@ internal override void WriteDurationConstantExpressionElement(IEdmDurationConsta
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes DurationConstantExpression element.
+ ///
+ /// The Edm Duration constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteDurationConstantExpressionElementAsync(IEdmDurationConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Duration, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.DurationAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes DecimalConstantExpression element.
+ ///
+ /// The Edm Decimal constant expression.
internal override void WriteDecimalConstantExpressionElement(IEdmDecimalConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Decimal);
@@ -607,6 +1672,22 @@ internal override void WriteDecimalConstantExpressionElement(IEdmDecimalConstant
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes DecimalConstantExpression element.
+ ///
+ /// The Edm Decimal constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteDecimalConstantExpressionElementAsync(IEdmDecimalConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Decimal, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.DecimalAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes FloatingConstantExpression element.
+ ///
+ /// The Edm Floating constant expression.
internal override void WriteFloatingConstantExpressionElement(IEdmFloatingConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Float);
@@ -614,17 +1695,62 @@ internal override void WriteFloatingConstantExpressionElement(IEdmFloatingConsta
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes FloatingConstantExpression element.
+ ///
+ /// The Edm Floating constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteFloatingConstantExpressionElementAsync(IEdmFloatingConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Float, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.FloatAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes FunctionApplication element header.
+ ///
+ /// The Edm apply expression.
internal override void WriteFunctionApplicationElementHeader(IEdmApplyExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Apply);
this.WriteRequiredAttribute(CsdlConstants.Attribute_Function, expression.AppliedFunction, this.FunctionAsXml);
}
+ ///
+ /// Asynchronously writes FunctionApplication element header.
+ ///
+ /// The Edm apply expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteFunctionApplicationElementHeaderAsync(IEdmApplyExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Apply, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Function, expression.AppliedFunction, this.FunctionAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes FunctionApplication element end.
+ ///
+ /// The Edm Apply expression.
internal override void WriteFunctionApplicationElementEnd(IEdmApplyExpression expression)
{
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes FunctionApplication element end.
+ ///
+ /// The Edm Apply expression.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteFunctionApplicationElementEndAsync(IEdmApplyExpression expression)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes GuidConstantExpression element.
+ ///
+ /// The Edm Guid constant expression.
internal override void WriteGuidConstantExpressionElement(IEdmGuidConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Guid);
@@ -632,6 +1758,22 @@ internal override void WriteGuidConstantExpressionElement(IEdmGuidConstantExpres
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes GuidConstantExpression element.
+ ///
+ /// The Edm Guid constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteGuidConstantExpressionElementAsync(IEdmGuidConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Guid, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.GuidAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes IntegerConstant Expression element.
+ ///
+ /// The Edm Integer constant expression.
internal override void WriteIntegerConstantExpressionElement(IEdmIntegerConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Int);
@@ -639,6 +1781,22 @@ internal override void WriteIntegerConstantExpressionElement(IEdmIntegerConstant
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes IntegerConstant Expression element.
+ ///
+ /// The Edm Integer constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteIntegerConstantExpressionElementAsync(IEdmIntegerConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Int, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.LongAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes Path Expression element.
+ ///
+ /// The Edm path expression.
internal override void WritePathExpressionElement(IEdmPathExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Path);
@@ -646,6 +1804,22 @@ internal override void WritePathExpressionElement(IEdmPathExpression expression)
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes Path Expression element.
+ ///
+ /// The Edm path expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritePathExpressionElementAsync(IEdmPathExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Path, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(PathAsXml(expression.PathSegments)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes PropertyPath Expression element.
+ ///
+ /// The Edm path expression.
internal override void WritePropertyPathExpressionElement(IEdmPathExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_PropertyPath);
@@ -653,6 +1827,23 @@ internal override void WritePropertyPathExpressionElement(IEdmPathExpression exp
this.WriteEndElement();
}
+
+ ///
+ /// Asynchronously writes PropertyPath Expression element.
+ ///
+ /// The Edm path expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WritePropertyPathExpressionElementAsync(IEdmPathExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_PropertyPath, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(PathAsXml(expression.PathSegments)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes NavigationPropertyPath Expression element.
+ ///
+ /// The Edm path expression.
internal override void WriteNavigationPropertyPathExpressionElement(IEdmPathExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_NavigationPropertyPath);
@@ -660,6 +1851,22 @@ internal override void WriteNavigationPropertyPathExpressionElement(IEdmPathExpr
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes NavigationPropertyPath Expression element.
+ ///
+ /// The Edm path expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteNavigationPropertyPathExpressionElementAsync(IEdmPathExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_NavigationPropertyPath, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(PathAsXml(expression.PathSegments)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes AnnotationPath Expression element.
+ ///
+ /// The Edm path expression.
internal override void WriteAnnotationPathExpressionElement(IEdmPathExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_AnnotationPath);
@@ -667,32 +1874,119 @@ internal override void WriteAnnotationPathExpressionElement(IEdmPathExpression e
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes AnnotationPath Expression element.
+ ///
+ /// The Edm path expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteAnnotationPathExpressionElementAsync(IEdmPathExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_AnnotationPath, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(PathAsXml(expression.PathSegments)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes If Expression element header.
+ ///
+ /// EDM if Expression
internal override void WriteIfExpressionElementHeader(IEdmIfExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_If);
}
+ ///
+ /// Asynchronously writes If Expression element header.
+ ///
+ /// EDM if Expression
+ /// Task represents an asynchronous operation.
+ internal override Task WriteIfExpressionElementHeaderAsync(IEdmIfExpression expression)
+ {
+ return this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_If, null);
+ }
+
+ ///
+ /// Writes If Expression element end.
+ ///
+ /// EDM if Expression
internal override void WriteIfExpressionElementEnd(IEdmIfExpression expression)
{
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes If Expression element end.
+ ///
+ /// EDM if Expression
+ /// Task represents an asynchronous operation.
+ internal override Task WriteIfExpressionElementEndAsync(IEdmIfExpression expression)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes Collection Expression element header.
+ ///
+ /// The Edm collection expression.
internal override void WriteCollectionExpressionElementHeader(IEdmCollectionExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Collection);
}
+ ///
+ /// Asynchronously writes Collection Expression element header.
+ ///
+ /// The Edm collection expression.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteCollectionExpressionElementHeaderAsync(IEdmCollectionExpression expression)
+ {
+ return this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Collection, null);
+ }
+
+ ///
+ /// Writes Collection Expression element end.
+ ///
+ /// The Edm collection expression.
internal override void WriteCollectionExpressionElementEnd(IEdmCollectionExpression expression)
{
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes Collection Expression element end.
+ ///
+ /// The Edm collection expression.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteCollectionExpressionElementEndAsync(IEdmCollectionExpression expression)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes LabeledElement header.
+ ///
+ /// The Edm Labeled expression.
internal override void WriteLabeledElementHeader(IEdmLabeledExpression labeledElement)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_LabeledElement);
this.WriteRequiredAttribute(CsdlConstants.Attribute_Name, labeledElement.Name, EdmValueWriter.StringAsXml);
}
+ ///
+ /// Asynchronously writes LabeledElement header.
+ ///
+ /// The Edm Labeled expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteLabeledElementHeaderAsync(IEdmLabeledExpression labeledElement)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_LabeledElement, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, labeledElement.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes LabeledExpressionReference Expression.
+ ///
+ /// The Edm Labeled Expression expression.
internal override void WriteLabeledExpressionReferenceExpression(IEdmLabeledExpressionReferenceExpression labeledExpressionReference)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_LabeledElementReference);
@@ -700,6 +1994,22 @@ internal override void WriteLabeledExpressionReferenceExpression(IEdmLabeledExpr
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes LabeledExpressionReference Expression.
+ ///
+ /// The Edm Labeled Expression expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteLabeledExpressionReferenceExpressionAsync(IEdmLabeledExpressionReferenceExpression labeledExpressionReference)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_LabeledElementReference, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, labeledExpressionReference.ReferencedLabeledExpression.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes TimeOfDay Constant Expression element.
+ ///
+ /// The Edm TimeOfDay constant expression.
internal override void WriteTimeOfDayConstantExpressionElement(IEdmTimeOfDayConstantExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_TimeOfDay);
@@ -707,6 +2017,23 @@ internal override void WriteTimeOfDayConstantExpressionElement(IEdmTimeOfDayCons
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes TimeOfDay Constant Expression element.
+ ///
+ /// The Edm TimeOfDay constant expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteTimeOfDayConstantExpressionElementAsync(IEdmTimeOfDayConstantExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_TimeOfDay, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EdmValueWriter.TimeOfDayAsXml(expression.Value)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes IsType Expression header.
+ ///
+ /// The Edm IsType expression.
+ /// Is inline type or not.
internal override void WriteIsTypeExpressionElementHeader(IEdmIsTypeExpression expression, bool inlineType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_IsType);
@@ -716,6 +2043,27 @@ internal override void WriteIsTypeExpressionElementHeader(IEdmIsTypeExpression e
}
}
+
+ ///
+ /// Asynchronously writes IsType Expression header.
+ ///
+ /// The Edm IsType expression.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteIsTypeExpressionElementHeaderAsync(IEdmIsTypeExpression expression, bool inlineType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_IsType, null).ConfigureAwait(false);
+ if (inlineType)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, expression.Type, this.TypeReferenceAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Cast Expression header.
+ ///
+ /// The Edm Cast expression.
+ /// Is inline type or not.
internal override void WriteCastExpressionElementHeader(IEdmCastExpression expression, bool inlineType)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_Cast);
@@ -725,11 +2073,46 @@ internal override void WriteCastExpressionElementHeader(IEdmCastExpression expre
}
}
+ ///
+ /// Asynchronously writes Cast Expression header.
+ ///
+ /// The Edm Cast expression.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteCastExpressionElementHeaderAsync(IEdmCastExpression expression, bool inlineType)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Cast, null).ConfigureAwait(false);
+ if (inlineType)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Type, expression.Type, this.TypeReferenceAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Cast Expression end.
+ ///
+ /// The Edm Cast expression.
+ /// Is inline type or not.
internal override void WriteCastExpressionElementEnd(IEdmCastExpression expression, bool inlineType)
{
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes Cast Expression end.
+ ///
+ /// The Edm Cast expression.
+ /// Is inline type or not.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteCastExpressionElementEndAsync(IEdmCastExpression expression, bool inlineType)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes EnumMember Expression element.
+ ///
+ /// The Edm enumaration member expression.
internal override void WriteEnumMemberExpressionElement(IEdmEnumMemberExpression expression)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_EnumMember);
@@ -737,6 +2120,22 @@ internal override void WriteEnumMemberExpressionElement(IEdmEnumMemberExpression
this.WriteEndElement();
}
+ ///
+ /// Asynchronously writes EnumMember Expression element.
+ ///
+ /// The Edm enumaration member expression.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteEnumMemberExpressionElementAsync(IEdmEnumMemberExpression expression)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_EnumMember, null).ConfigureAwait(false);
+ await this.xmlWriter.WriteStringAsync(EnumMemberAsXmlOrJson(expression.EnumMembers)).ConfigureAwait(false);
+ await this.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes TypeDefinition element header.
+ ///
+ /// The Edm Type definition.
internal override void WriteTypeDefinitionElementHeader(IEdmTypeDefinition typeDefinition)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_TypeDefinition);
@@ -744,16 +2143,61 @@ internal override void WriteTypeDefinitionElementHeader(IEdmTypeDefinition typeD
this.WriteRequiredAttribute(CsdlConstants.Attribute_UnderlyingType, typeDefinition.UnderlyingType, this.TypeDefinitionAsXml);
}
+ ///
+ /// Asynchronously writes TypeDefinition element header.
+ ///
+ /// The Edm Type definition.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteTypeDefinitionElementHeaderAsync(IEdmTypeDefinition typeDefinition)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_TypeDefinition, null).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, typeDefinition.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_UnderlyingType, typeDefinition.UnderlyingType, this.TypeDefinitionAsXml).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes End Element.
+ ///
+ /// Task represents an asynchronous operation.
internal override void WriteEndElement()
{
this.xmlWriter.WriteEndElement();
}
+ ///
+ /// Asynchronously writes End Element.
+ ///
+ internal override Task WriteEndElementAsync()
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes Array End Element.
+ ///
internal override void WriteArrayEndElement()
{
this.xmlWriter.WriteEndElement();
}
+ ///
+ /// Asynchronously writes Array End Element.
+ ///
+ /// Task represents an asynchronous operation.
+ internal override Task WriteArrayEndElementAsync()
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// Writes Optional attribute.
+ ///
+ ///
+ /// The attribute name.
+ /// The attribute value.
+ /// The attribute default value.
+ /// Get string Function.
+ /// Task represents an asynchronous operation.
internal void WriteOptionalAttribute(string attribute, T value, T defaultValue, Func getStringFunc)
{
if (!value.Equals(defaultValue))
@@ -762,6 +2206,30 @@ internal void WriteOptionalAttribute(string attribute, T value, T defaultValu
}
}
+ ///
+ /// Asynchronously writes Optional attribute.
+ ///
+ ///
+ /// The attribute name.
+ /// The attribute value.
+ /// The attribute default value.
+ /// Get string Function.
+ internal async Task WriteOptionalAttributeAsync(string attribute, T value, T defaultValue, Func getStringFunc)
+ {
+ if (!value.Equals(defaultValue))
+ {
+ await this.xmlWriter.WriteAttributeStringAsync(null, attribute, null, getStringFunc(value)).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Optional attribute.
+ ///
+ ///
+ /// The attribute name.
+ /// The attribute value.
+ /// Get string Function.
+ /// Task represents an asynchronous operation.
internal void WriteOptionalAttribute(string attribute, T value, Func getStringFunc)
{
if (value != null)
@@ -770,11 +2238,51 @@ internal void WriteOptionalAttribute(string attribute, T value, Func
+ /// Asynchronously writes Optional attribute.
+ ///
+ ///
+ /// The attribute name.
+ /// The attribute value.
+ /// Get string Function.
+ /// Task represents an asynchronous operation.
+ internal async Task WriteOptionalAttributeAsync(string attribute, T value, Func getStringFunc)
+ {
+ if (value != null)
+ {
+ await this.xmlWriter.WriteAttributeStringAsync(null, attribute, null, getStringFunc(value)).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes Required attribute.
+ ///
+ ///
+ /// The attribute name.
+ /// The attribute value.
+ /// Value to xml function.
internal void WriteRequiredAttribute(string attribute, T value, Func toXml)
{
this.xmlWriter.WriteAttributeString(attribute, toXml(value));
}
+ ///
+ /// Asynchronously writes Required attribute.
+ ///
+ ///
+ /// The attribute name.
+ /// The attribute value.
+ /// Value to xml function.
+ /// Task represents an asynchronous operation.
+ internal Task WriteRequiredAttributeAsync(string attribute, T value, Func toXml)
+ {
+ return this.xmlWriter.WriteAttributeStringAsync(null, attribute, null, toXml(value));
+ }
+
+ ///
+ /// Writes Operation element attributes.
+ ///
+ /// The Edm operation.
internal override void WriteOperationElementAttributes(IEdmOperation operation)
{
this.WriteRequiredAttribute(CsdlConstants.Attribute_Name, operation.Name, EdmValueWriter.StringAsXml);
@@ -790,10 +2298,34 @@ internal override void WriteOperationElementAttributes(IEdmOperation operation)
}
}
+ ///
+ /// Asynchronously writes Operation element attributes.
+ ///
+ /// The Edm operation.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteOperationElementAttributesAsync(IEdmOperation operation)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, operation.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+
+ if (operation.IsBound)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_IsBound, operation.IsBound, EdmValueWriter.BooleanAsXml).ConfigureAwait(false);
+ }
+
+ if (operation.EntitySetPath != null)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_EntitySetPath, operation.EntitySetPath.PathSegments, PathAsXml).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Writes NavigationPropertyBinding.
+ ///
+ /// The Edm navigation property binding.
internal override void WriteNavigationPropertyBinding(IEdmNavigationPropertyBinding binding)
{
// For backwards compatability, only write annotations that vary by type cast in versions > 4.0
- if (this.Model.GetEdmVersion() > EdmConstants.EdmVersion4 || binding.Path.PathSegments.Last().IndexOf('.') < 0)
+ if (this.Model.GetEdmVersion() > EdmConstants.EdmVersion4 || binding.Path.PathSegments.Last().IndexOf('.', StringComparison.Ordinal) < 0)
{
this.xmlWriter.WriteStartElement(CsdlConstants.Element_NavigationPropertyBinding);
@@ -814,13 +2346,41 @@ internal override void WriteNavigationPropertyBinding(IEdmNavigationPropertyBind
}
}
+ ///
+ /// Asynchronously writes NavigationPropertyBinding.
+ ///
+ /// The Edm navigation property binding.
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteNavigationPropertyBindingAsync(IEdmNavigationPropertyBinding binding)
+ {
+ // For backwards compatability, only write annotations that vary by type cast in versions > 4.0
+ if (this.Model.GetEdmVersion() > EdmConstants.EdmVersion4 || binding.Path.PathSegments.Last().IndexOf('.', StringComparison.Ordinal) < 0)
+ {
+ await this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_NavigationPropertyBinding, null).ConfigureAwait(false);
+
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Path, binding.Path.Path, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+
+ // TODO: handle container names, etc.
+ if (binding.Target is IEdmContainedEntitySet containedEntitySet)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Target, containedEntitySet.Path.Path, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+ else
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Target, binding.Target.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ }
+
+ await this.xmlWriter.WriteEndElementAsync().ConfigureAwait(false);
+ }
+ }
+
private string SridAsXml(int? i)
{
if (this.writerSettings.LibraryCompatibility.HasFlag(EdmLibraryCompatibility.UseLegacyVariableCasing))
{
return i.HasValue ? Convert.ToString(i.Value, CultureInfo.InvariantCulture) : CsdlConstants.Value_SridVariable_Legacy;
}
- else
+ else
{
return i.HasValue ? Convert.ToString(i.Value, CultureInfo.InvariantCulture) : CsdlConstants.Value_SridVariable;
}
@@ -832,7 +2392,7 @@ private string ScaleAsXml(int? i)
{
return i.HasValue ? Convert.ToString(i.Value, CultureInfo.InvariantCulture) : CsdlConstants.Value_ScaleVariable_Legacy;
}
- else
+ else
{
return i.HasValue ? Convert.ToString(i.Value, CultureInfo.InvariantCulture) : CsdlConstants.Value_ScaleVariable;
}
@@ -849,6 +2409,12 @@ private static string GetCsdlNamespace(Version edmVersion)
throw new InvalidOperationException(Strings.Serializer_UnknownEdmVersion(edmVersion.ToString()));
}
+ ///
+ /// Writes OperationImport attributes.
+ ///
+ /// The Edm Operation import.
+ /// Operation attribute name.
+ ///
internal override void WriteOperationImportAttributes(IEdmOperationImport operationImport, string operationAttributeName)
{
this.WriteRequiredAttribute(CsdlConstants.Attribute_Name, operationImport.Name, EdmValueWriter.StringAsXml);
@@ -868,6 +2434,31 @@ internal override void WriteOperationImportAttributes(IEdmOperationImport operat
}
}
+ ///
+ /// Asynchronously writes OperationImport attributes.
+ ///
+ /// The Edm Operation import.
+ /// Operation attribute name.
+ ///
+ /// Task represents an asynchronous operation.
+ internal override async Task WriteOperationImportAttributesAsync(IEdmOperationImport operationImport, string operationAttributeName)
+ {
+ await this.WriteRequiredAttributeAsync(CsdlConstants.Attribute_Name, operationImport.Name, EdmValueWriter.StringAsXml).ConfigureAwait(false);
+ await this.WriteRequiredAttributeAsync(operationAttributeName, operationImport.Operation.FullName(), EdmValueWriter.StringAsXml).ConfigureAwait(false);
+
+ if (operationImport.EntitySet != null)
+ {
+ if (operationImport.EntitySet is IEdmPathExpression pathExpression)
+ {
+ await this.WriteOptionalAttributeAsync(CsdlConstants.Attribute_EntitySet, pathExpression.PathSegments, PathAsXml).ConfigureAwait(false);
+ }
+ else
+ {
+ throw new InvalidOperationException(Strings.EdmModel_Validator_Semantic_OperationImportEntitySetExpressionIsInvalid(operationImport.Name));
+ }
+ }
+ }
+
private string SerializationName(IEdmSchemaElement element)
{
if (this.NamespaceAliasMappings != null)
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs
index 45b618822f..f238c4d915 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs
@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using Microsoft.OData.Edm.Vocabularies;
namespace Microsoft.OData.Edm.Csdl.Serialization
@@ -72,6 +73,59 @@ public override void VisitEntityContainerElements(IEnumerable
+ /// Asynchronously visits the elements of the entity container.
+ ///
+ /// Collection of Edm Entity container elements.
+ ///
+ public override async Task VisitEntityContainerElementsAsync(IEnumerable elements)
+ {
+ var functionImportsWritten = new HashSet();
+ var actionImportsWritten = new HashSet();
+
+ foreach (IEdmEntityContainerElement element in elements)
+ {
+ switch (element.ContainerElementKind)
+ {
+ case EdmContainerElementKind.EntitySet:
+ await this.ProcessEntitySetAsync((IEdmEntitySet)element).ConfigureAwait(false);
+ break;
+ case EdmContainerElementKind.Singleton:
+ await this.ProcessSingletonAsync((IEdmSingleton)element).ConfigureAwait(false);
+ break;
+ case EdmContainerElementKind.ActionImport:
+ // Skip actionImports that have the same name for same overloads of a action.
+ IEdmActionImport actionImport = (IEdmActionImport)element;
+
+ var uniqueActionName = string.Concat(actionImport.Name, "_", actionImport.Action.FullName(), GetEntitySetString(actionImport));
+ if (!actionImportsWritten.Contains(uniqueActionName))
+ {
+ actionImportsWritten.Add(uniqueActionName);
+ await this.ProcessActionImportAsync(actionImport).ConfigureAwait(false);
+ }
+
+ break;
+ case EdmContainerElementKind.FunctionImport:
+ // Skip functionImports that have the same name for same overloads of a function.
+ IEdmFunctionImport functionImport = (IEdmFunctionImport)element;
+
+ var uniqueFunctionName = string.Concat(functionImport.Name, "_", functionImport.Function.FullName(), GetEntitySetString(functionImport));
+ if (!functionImportsWritten.Contains(uniqueFunctionName))
+ {
+ functionImportsWritten.Add(uniqueFunctionName);
+ await this.ProcessFunctionImportAsync(functionImport).ConfigureAwait(false);
+ }
+
+ break;
+ case EdmContainerElementKind.None:
+ await this.ProcessEntityContainerElementAsync(element).ConfigureAwait(false);
+ break;
+ default:
+ throw new InvalidOperationException(Edm.Strings.UnknownEnumVal_ContainerElementKind(element.ContainerElementKind.ToString()));
+ }
+ }
+ }
+
internal void VisitEdmSchema(EdmSchema element, IEnumerable> mappings)
{
string alias = null;
@@ -111,6 +165,50 @@ internal void VisitEdmSchema(EdmSchema element, IEnumerable
+ /// Asynchronously visits Edm Schema.
+ ///
+ /// The Edm Schema.
+ /// Collection of prefix mappings.
+ internal async Task VisitEdmSchemaAsync(EdmSchema element, IEnumerable> mappings)
+ {
+ string alias = null;
+ if (this.namespaceAliasMappings != null)
+ {
+ this.namespaceAliasMappings.TryGetValue(element.Namespace, out alias);
+ }
+
+ await this.schemaWriter.WriteSchemaElementHeaderAsync(element, alias, mappings).ConfigureAwait(false);
+
+ VisitSchemaElements(element.SchemaElements);
+
+ // process the functions/actions seperately
+ foreach (var operation in element.SchemaOperations)
+ {
+ await this.schemaWriter.WriteSchemaOperationsHeaderAsync(operation).ConfigureAwait(false);
+ VisitSchemaElements(operation.Value.AsEnumerable()); // Call AsEnumerable() to make .net 3.5 happy
+ await this.schemaWriter.WriteSchemaOperationsEndAsync(operation).ConfigureAwait(false);
+ }
+
+ // EntityContainers are excluded from the EdmSchema.SchemaElements property so they can be forced to the end.
+ VisitCollection(element.EntityContainers, async (e) => await this.ProcessEntityContainerAsync(e).ConfigureAwait(false));
+
+ if (element.OutOfLineAnnotations.Any())
+ {
+ await this.schemaWriter.WriteOutOfLineAnnotationsBeginAsync(element.OutOfLineAnnotations).ConfigureAwait(false);
+ foreach (KeyValuePair> annotationsForTarget in element.OutOfLineAnnotations)
+ {
+ await this.schemaWriter.WriteAnnotationsElementHeaderAsync(annotationsForTarget).ConfigureAwait(false);
+ VisitVocabularyAnnotations(annotationsForTarget.Value);
+ await this.schemaWriter.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
+ await this.schemaWriter.WriteOutOfLineAnnotationsEndAsync(element.OutOfLineAnnotations).ConfigureAwait(false);
+ }
+
+ await this.schemaWriter.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
protected override void ProcessEntityContainer(IEdmEntityContainer element)
{
this.BeginElement(element, this.schemaWriter.WriteEntityContainerElementHeader);
@@ -118,6 +216,17 @@ protected override void ProcessEntityContainer(IEdmEntityContainer element)
this.EndElement(element);
}
+ ///
+ /// Asynchronously processes the entity container.
+ ///
+ /// The Edm entity container.
+ protected override async Task ProcessEntityContainerAsync(IEdmEntityContainer element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteEntityContainerElementHeaderAsync).ConfigureAwait(false);
+ await base.ProcessEntityContainerAsync(element).ConfigureAwait(false);
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessEntitySet(IEdmEntitySet element)
{
this.BeginElement(element, this.schemaWriter.WriteEntitySetElementHeader);
@@ -129,6 +238,21 @@ protected override void ProcessEntitySet(IEdmEntitySet element)
this.EndElement(element);
}
+ ///
+ /// Asynchronously processes the entity set.
+ ///
+ /// The Edm Entity set.
+ protected override async Task ProcessEntitySetAsync(IEdmEntitySet element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteEntitySetElementHeaderAsync).ConfigureAwait(false);
+
+ await base.ProcessEntitySetAsync(element).ConfigureAwait(false);
+
+ await ProcessNavigationPropertyBindingsAsync(element).ConfigureAwait(false);
+
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessSingleton(IEdmSingleton element)
{
this.BeginElement(element, this.schemaWriter.WriteSingletonElementHeader);
@@ -140,6 +264,21 @@ protected override void ProcessSingleton(IEdmSingleton element)
this.EndElement(element);
}
+ ///
+ /// Asynchronously processes the singleton.
+ ///
+ /// The Edm Singleton
+ protected override async Task ProcessSingletonAsync(IEdmSingleton element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteSingletonElementHeaderAsync).ConfigureAwait(false);
+
+ await base.ProcessSingletonAsync(element).ConfigureAwait(false);
+
+ await ProcessNavigationPropertyBindingsAsync(element).ConfigureAwait(false);
+
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessEntityType(IEdmEntityType element)
{
this.BeginElement(element, this.schemaWriter.WriteEntityTypeElementHeader);
@@ -153,6 +292,23 @@ protected override void ProcessEntityType(IEdmEntityType element)
this.EndElement(element);
}
+ ///
+ /// Asynchronously processes the entity type.
+ ///
+ /// The Edm entity type.
+ protected override async Task ProcessEntityTypeAsync(IEdmEntityType element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteEntityTypeElementHeaderAsync).ConfigureAwait(false);
+ if (element.DeclaredKey != null && element.DeclaredKey.Any())
+ {
+ await this.VisitEntityTypeDeclaredKeyAsync(element.DeclaredKey).ConfigureAwait(false);
+ }
+
+ this.VisitProperties(element.DeclaredStructuralProperties().Cast());
+ this.VisitProperties(element.DeclaredNavigationProperties().Cast());
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessStructuralProperty(IEdmStructuralProperty element)
{
bool inlineType = IsInlineType(element.Type);
@@ -165,36 +321,106 @@ protected override void ProcessStructuralProperty(IEdmStructuralProperty element
this.EndElement(element);
}
+ ///
+ /// Asynchronously processes the structural property.
+ ///
+ /// The Edm structural property.
+ protected override async Task ProcessStructuralPropertyAsync(IEdmStructuralProperty element)
+ {
+ bool inlineType = IsInlineType(element.Type);
+ await this.BeginElementAsync(element, (IEdmStructuralProperty t) => this.schemaWriter.WriteStructuralPropertyElementHeaderAsync(t, inlineType), e => this.ProcessFacetsAsync(e.Type, inlineType)).ConfigureAwait(false);
+ if (!inlineType)
+ {
+ VisitTypeReference(element.Type);
+ }
+
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessTypeDefinitionReference(IEdmTypeDefinitionReference element)
{
this.schemaWriter.WriteTypeDefinitionAttributes(element);
}
+ ///
+ /// Asynchronously processes the type definition reference.
+ ///
+ /// The Edm Type definition reference.
+ protected override Task ProcessTypeDefinitionReferenceAsync(IEdmTypeDefinitionReference element)
+ {
+ return this.schemaWriter.WriteTypeDefinitionAttributesAsync(element);
+ }
+
protected override void ProcessBinaryTypeReference(IEdmBinaryTypeReference element)
{
this.schemaWriter.WriteBinaryTypeAttributes(element);
}
+ ///
+ /// Asynchronously processes the binary type reference.
+ ///
+ /// The Edm binary type reference.
+ protected override Task ProcessBinaryTypeReferenceAsync(IEdmBinaryTypeReference element)
+ {
+ return this.schemaWriter.WriteBinaryTypeAttributesAsync(element);
+ }
+
protected override void ProcessDecimalTypeReference(IEdmDecimalTypeReference element)
{
this.schemaWriter.WriteDecimalTypeAttributes(element);
}
+ ///
+ /// Asynchronously processes the decimal type reference.
+ ///
+ /// The Edm Decimal type reference.
+ protected override Task ProcessDecimalTypeReferenceAsync(IEdmDecimalTypeReference element)
+ {
+ return this.schemaWriter.WriteDecimalTypeAttributesAsync(element);
+ }
+
protected override void ProcessSpatialTypeReference(IEdmSpatialTypeReference element)
{
this.schemaWriter.WriteSpatialTypeAttributes(element);
}
+ ///
+ /// Asynchronously processes the spatial type reference.
+ ///
+ /// The Edm spatial type reference.
+ protected override Task ProcessSpatialTypeReferenceAsync(IEdmSpatialTypeReference element)
+ {
+ return this.schemaWriter.WriteSpatialTypeAttributesAsync(element);
+ }
+
protected override void ProcessStringTypeReference(IEdmStringTypeReference element)
{
this.schemaWriter.WriteStringTypeAttributes(element);
}
+ ///
+ /// Asynchronously processes the string type reference.
+ ///
+ /// The Edm string type reference.
+ protected override Task ProcessStringTypeReferenceAsync(IEdmStringTypeReference element)
+ {
+ return this.schemaWriter.WriteStringTypeAttributesAsync(element);
+ }
+
protected override void ProcessTemporalTypeReference(IEdmTemporalTypeReference element)
{
this.schemaWriter.WriteTemporalTypeAttributes(element);
}
+ ///
+ /// Asynchronously processes the temporal type reference.
+ ///
+ /// The Edm temporal type reference.
+ protected override Task ProcessTemporalTypeReferenceAsync(IEdmTemporalTypeReference element)
+ {
+ return this.schemaWriter.WriteTemporalTypeAttributesAsync(element);
+ }
+
protected override void ProcessNavigationProperty(IEdmNavigationProperty element)
{
this.BeginElement(element, this.schemaWriter.WriteNavigationPropertyElementHeader);
@@ -213,6 +439,28 @@ protected override void ProcessNavigationProperty(IEdmNavigationProperty element
this.navigationProperties.Add(element);
}
+ ///
+ /// Asynchronously processes the navigation property.
+ ///
+ /// The Edm navigation property.
+ protected override async Task ProcessNavigationPropertyAsync(IEdmNavigationProperty element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteNavigationPropertyElementHeaderAsync).ConfigureAwait(false);
+
+ // From 4.0.1 spec says:
+ // "OnDelete" has "None, Cascade, SetNull, SetDefault" values defined in 4.01.
+ // But, ODL now only process "Cascade" and "None".So we should fix it to support the others.
+ if (element.OnDelete != EdmOnDeleteAction.None)
+ {
+ await this.schemaWriter.WriteNavigationOnDeleteActionElementAsync(element.OnDelete).ConfigureAwait(false);
+ }
+
+ await this.ProcessReferentialConstraintAsync(element.ReferentialConstraint).ConfigureAwait(false);
+
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ this.navigationProperties.Add(element);
+ }
+
protected override void ProcessComplexType(IEdmComplexType element)
{
this.BeginElement(element, this.schemaWriter.WriteComplexTypeElementHeader);
@@ -220,6 +468,17 @@ protected override void ProcessComplexType(IEdmComplexType element)
this.EndElement(element);
}
+ ///
+ /// Asynchronously processes the complex type.
+ ///
+ /// The Edm complex type.
+ protected override async Task ProcessComplexTypeAsync(IEdmComplexType element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteComplexTypeElementHeaderAsync).ConfigureAwait(false);
+ await base.ProcessComplexTypeAsync(element).ConfigureAwait(false);
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessEnumType(IEdmEnumType element)
{
this.BeginElement(element, this.schemaWriter.WriteEnumTypeElementHeader);
@@ -227,12 +486,33 @@ protected override void ProcessEnumType(IEdmEnumType element)
this.EndElement(element, this.schemaWriter.WriteEnumTypeElementEnd);
}
+ ///
+ /// Asynchronously processes the enum type.
+ ///
+ /// The Edm enumeration type.
+ protected override async Task ProcessEnumTypeAsync(IEdmEnumType element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteEnumTypeElementHeaderAsync).ConfigureAwait(false);
+ await base.ProcessEnumTypeAsync(element).ConfigureAwait(false);
+ await this.EndElementAsync(element, this.schemaWriter.WriteEnumTypeElementEndAsync).ConfigureAwait(false);
+ }
+
protected override void ProcessEnumMember(IEdmEnumMember element)
{
this.BeginElement(element, this.schemaWriter.WriteEnumMemberElementHeader);
this.EndElement(element, this.schemaWriter.WriteEnumMemberElementEnd);
}
+ ///
+ /// Asynchronously processes the enum member.
+ ///
+ /// The Edm enumeration member.
+ protected override async Task ProcessEnumMemberAsync(IEdmEnumMember element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteEnumMemberElementHeaderAsync).ConfigureAwait(false);
+ await this.EndElementAsync(element, this.schemaWriter.WriteEnumMemberElementEndAsync).ConfigureAwait(false);
+ }
+
protected override void ProcessTypeDefinition(IEdmTypeDefinition element)
{
this.BeginElement(element, this.schemaWriter.WriteTypeDefinitionElementHeader);
@@ -240,6 +520,17 @@ protected override void ProcessTypeDefinition(IEdmTypeDefinition element)
this.EndElement(element);
}
+ ///
+ /// Asynchronously processes the type definition.
+ ///
+ /// The Edm type definition.
+ protected override async Task ProcessTypeDefinitionAsync(IEdmTypeDefinition element)
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteTypeDefinitionElementHeaderAsync).ConfigureAwait(false);
+ await base.ProcessTypeDefinitionAsync(element).ConfigureAwait(false);
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessTerm(IEdmTerm term)
{
bool inlineType = term.Type != null && IsInlineType(term.Type);
@@ -255,16 +546,53 @@ protected override void ProcessTerm(IEdmTerm term)
this.EndElement(term);
}
+ ///
+ /// Asynchronously processes the term.
+ ///
+ /// The Edm term.
+ protected override async Task ProcessTermAsync(IEdmTerm term)
+ {
+ bool inlineType = term.Type != null && IsInlineType(term.Type);
+ await this.BeginElementAsync(term, (IEdmTerm t) => this.schemaWriter.WriteTermElementHeaderAsync(t, inlineType), e => this.ProcessFacetsAsync(e.Type, inlineType)).ConfigureAwait(false);
+ if (!inlineType)
+ {
+ if (term.Type != null)
+ {
+ VisitTypeReference(term.Type);
+ }
+ }
+
+ await this.EndElementAsync(term).ConfigureAwait(false);
+ }
+
protected override void ProcessAction(IEdmAction action)
{
this.ProcessOperation(action, this.schemaWriter.WriteActionElementHeader);
}
+ ///
+ /// Asynchronously processes the action.
+ ///
+ /// The Edm action.
+ protected override Task ProcessActionAsync(IEdmAction action)
+ {
+ return this.ProcessOperationAsync(action, this.schemaWriter.WriteActionElementHeaderAsync);
+ }
+
protected override void ProcessFunction(IEdmFunction function)
{
this.ProcessOperation(function, this.schemaWriter.WriteFunctionElementHeader);
}
+ ///
+ /// Asynchronously processes the function.
+ ///
+ /// The Edm function.
+ protected override Task ProcessFunctionAsync(IEdmFunction function)
+ {
+ return this.ProcessOperationAsync(function, this.schemaWriter.WriteFunctionElementHeaderAsync);
+ }
+
protected override void ProcessOperationParameter(IEdmOperationParameter element)
{
bool inlineType = IsInlineType(element.Type);
@@ -287,6 +615,32 @@ protected override void ProcessOperationParameter(IEdmOperationParameter element
this.schemaWriter.WriteOperationParameterEndElement(element);
}
+ ///
+ /// Asynchronously processes the operation parameter.
+ ///
+ /// The Edm operation parameter.
+ protected override async Task ProcessOperationParameterAsync(IEdmOperationParameter element)
+ {
+ bool inlineType = IsInlineType(element.Type);
+ await this.BeginElementAsync(
+ element,
+ (IEdmOperationParameter t) => this.schemaWriter.WriteOperationParameterElementHeaderAsync(t, inlineType),
+ e => this.ProcessFacetsAsync(e.Type, inlineType)
+ ).ConfigureAwait(false);
+ if (!inlineType)
+ {
+ VisitTypeReference(element.Type);
+ }
+
+ await this.VisitPrimitiveElementAnnotationsAsync(this.Model.DirectValueAnnotations(element)).ConfigureAwait(false);
+ if (element is IEdmVocabularyAnnotatable vocabularyAnnotatableElement)
+ {
+ await this.VisitElementVocabularyAnnotationsAsync(this.Model.FindDeclaredVocabularyAnnotations(vocabularyAnnotatableElement).Where(a => a.IsInline(this.Model))).ConfigureAwait(false);
+ }
+
+ await this.schemaWriter.WriteOperationParameterEndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessOperationReturn(IEdmOperationReturn operationReturn)
{
if (operationReturn == null)
@@ -313,6 +667,36 @@ protected override void ProcessOperationReturn(IEdmOperationReturn operationRetu
this.EndElement(operationReturn);
}
+ ///
+ /// Asynchronously processes the operation return.
+ ///
+ /// The Edm operation return.
+ protected override async Task ProcessOperationReturnAsync(IEdmOperationReturn operationReturn)
+ {
+ if (operationReturn == null)
+ {
+ return;
+ }
+
+ bool inlineType = IsInlineType(operationReturn.Type);
+ await this.BeginElementAsync(
+ operationReturn.Type,
+ type => this.schemaWriter.WriteReturnTypeElementHeaderAsync(operationReturn),
+ async type =>
+ {
+ if (inlineType)
+ {
+ await this.schemaWriter.WriteTypeAttributeAsync(type).ConfigureAwait(false);
+ await this.ProcessFacetsAsync(type, true /*inlineType*/).ConfigureAwait(false);
+ }
+ else
+ {
+ this.VisitTypeReference(type);
+ }
+ }).ConfigureAwait(false);
+ await this.EndElementAsync(operationReturn).ConfigureAwait(false);
+ }
+
protected override void ProcessCollectionType(IEdmCollectionType element)
{
bool inlineType = IsInlineType(element.ElementType);
@@ -328,18 +712,58 @@ protected override void ProcessCollectionType(IEdmCollectionType element)
this.EndElement(element);
}
+ ///
+ /// Asynchronously process collection type.
+ ///
+ /// The Edm collection type.
+ protected override async Task ProcessCollectionTypeAsync(IEdmCollectionType element)
+ {
+ bool inlineType = IsInlineType(element.ElementType);
+ await this.BeginElementAsync(
+ element,
+ (IEdmCollectionType t) => this.schemaWriter.WriteCollectionTypeElementHeaderAsync(t, inlineType),
+ e => this.ProcessFacetsAsync(e.ElementType, inlineType)
+ ).ConfigureAwait(false);
+ if (!inlineType)
+ {
+ VisitTypeReference(element.ElementType);
+ }
+
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+
protected override void ProcessActionImport(IEdmActionImport actionImport)
{
this.BeginElement(actionImport, this.schemaWriter.WriteActionImportElementHeader);
this.EndElement(actionImport);
}
+ ///
+ /// Asynchronously processes the action import.
+ ///
+ /// The Edm action import.
+ protected override async Task ProcessActionImportAsync(IEdmActionImport actionImport)
+ {
+ await this.BeginElementAsync(actionImport, this.schemaWriter.WriteActionImportElementHeaderAsync).ConfigureAwait(false);
+ await this.EndElementAsync(actionImport).ConfigureAwait(false);
+ }
+
protected override void ProcessFunctionImport(IEdmFunctionImport functionImport)
{
this.BeginElement(functionImport, this.schemaWriter.WriteFunctionImportElementHeader);
this.EndElement(functionImport);
}
+ ///
+ /// Asynchronously processes the function import.
+ ///
+ /// The Edm function import.
+ protected override async Task ProcessFunctionImportAsync(IEdmFunctionImport functionImport)
+ {
+ await this.BeginElementAsync(functionImport, this.schemaWriter.WriteFunctionImportElementHeaderAsync).ConfigureAwait(false);
+ await this.EndElementAsync(functionImport).ConfigureAwait(false);
+ }
+
#region Vocabulary Annotations
protected override void ProcessAnnotation(IEdmVocabularyAnnotation annotation)
@@ -354,6 +778,22 @@ protected override void ProcessAnnotation(IEdmVocabularyAnnotation annotation)
this.EndElement(annotation, t => this.schemaWriter.WriteVocabularyAnnotationElementEnd(annotation, isInline));
}
+ ///
+ /// Asynchronously processes the annotation.
+ ///
+ /// The Edm vocabulary annotation.
+ protected override async Task ProcessAnnotationAsync(IEdmVocabularyAnnotation annotation)
+ {
+ bool isInline = IsInlineExpression(annotation.Value);
+ await this.BeginElementAsync(annotation, t => this.schemaWriter.WriteVocabularyAnnotationElementHeaderAsync(t, isInline)).ConfigureAwait(false);
+ if (!isInline)
+ {
+ await base.ProcessAnnotationAsync(annotation).ConfigureAwait(false);
+ }
+
+ await this.EndElementAsync(annotation, t => this.schemaWriter.WriteVocabularyAnnotationElementEndAsync(annotation, isInline)).ConfigureAwait(false);
+ }
+
#endregion
#region Expressions
@@ -363,11 +803,29 @@ protected override void ProcessStringConstantExpression(IEdmStringConstantExpres
this.schemaWriter.WriteStringConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the string constant expression.
+ ///
+ /// The Edm string constant expression.
+ protected override Task ProcessStringConstantExpressionAsync(IEdmStringConstantExpression expression)
+ {
+ return this.schemaWriter.WriteStringConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessBinaryConstantExpression(IEdmBinaryConstantExpression expression)
{
this.schemaWriter.WriteBinaryConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the binary constant expression.
+ ///
+ /// The Edm binary constant expression.
+ protected override Task ProcessBinaryConstantExpressionAsync(IEdmBinaryConstantExpression expression)
+ {
+ return this.schemaWriter.WriteBinaryConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessRecordExpression(IEdmRecordExpression expression)
{
this.BeginElement(expression, this.schemaWriter.WriteRecordExpressionElementHeader);
@@ -375,6 +833,17 @@ protected override void ProcessRecordExpression(IEdmRecordExpression expression)
this.EndElement(expression);
}
+ ///
+ /// Asynchronously processes the record expression.
+ ///
+ /// The Edm record expression.
+ protected override async Task ProcessRecordExpressionAsync(IEdmRecordExpression expression)
+ {
+ await this.BeginElementAsync(expression, this.schemaWriter.WriteRecordExpressionElementHeaderAsync).ConfigureAwait(false);
+ this.VisitPropertyConstructors(expression.Properties);
+ await this.EndElementAsync(expression).ConfigureAwait(false);
+ }
+
protected override void ProcessLabeledExpression(IEdmLabeledExpression element)
{
if (element.Name == null)
@@ -389,11 +858,38 @@ protected override void ProcessLabeledExpression(IEdmLabeledExpression element)
}
}
+ ///
+ /// Asynchronously processes the labeled expression.
+ ///
+ /// The Edm labeled expression.
+ protected override async Task ProcessLabeledExpressionAsync(IEdmLabeledExpression element)
+ {
+ if (element.Name == null)
+ {
+ await base.ProcessLabeledExpressionAsync(element).ConfigureAwait(false);
+ }
+ else
+ {
+ await this.BeginElementAsync(element, this.schemaWriter.WriteLabeledElementHeaderAsync).ConfigureAwait(false);
+ await base.ProcessLabeledExpressionAsync(element).ConfigureAwait(false);
+ await this.EndElementAsync(element).ConfigureAwait(false);
+ }
+ }
+
protected override void ProcessLabeledExpressionReferenceExpression(IEdmLabeledExpressionReferenceExpression element)
{
this.schemaWriter.WriteLabeledExpressionReferenceExpression(element);
}
+ ///
+ /// Asynchronously processes the labeled expression reference expression.
+ ///
+ /// The Edm labeled expression reference.
+ protected override Task ProcessLabeledExpressionReferenceExpressionAsync(IEdmLabeledExpressionReferenceExpression element)
+ {
+ return this.schemaWriter.WriteLabeledExpressionReferenceExpressionAsync(element);
+ }
+
protected override void ProcessPropertyConstructor(IEdmPropertyConstructor constructor)
{
bool isInline = IsInlineExpression(constructor.Value);
@@ -406,26 +902,78 @@ protected override void ProcessPropertyConstructor(IEdmPropertyConstructor const
this.EndElement(constructor, this.schemaWriter.WritePropertyConstructorElementEnd);
}
+ ///
+ /// Asynchronously processes the property constructor.
+ ///
+ /// The Edm property constructor.
+ protected override async Task ProcessPropertyConstructorAsync(IEdmPropertyConstructor constructor)
+ {
+ bool isInline = IsInlineExpression(constructor.Value);
+ await this.BeginElementAsync(constructor, t => this.schemaWriter.WritePropertyConstructorElementHeaderAsync(t, isInline)).ConfigureAwait(false);
+ if (!isInline)
+ {
+ await base.ProcessPropertyConstructorAsync(constructor).ConfigureAwait(false);
+ }
+
+ await this.EndElementAsync(constructor, this.schemaWriter.WritePropertyConstructorElementEndAsync).ConfigureAwait(false);
+ }
+
protected override void ProcessPathExpression(IEdmPathExpression expression)
{
this.schemaWriter.WritePathExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the path expression.
+ ///
+ /// The Edm path expression.
+ protected override Task ProcessPathExpressionAsync(IEdmPathExpression expression)
+ {
+ return this.schemaWriter.WritePathExpressionElementAsync(expression);
+ }
+
protected override void ProcessPropertyPathExpression(IEdmPathExpression expression)
{
this.schemaWriter.WritePropertyPathExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the property path expression.
+ ///
+ /// The Edm path expression.
+ protected override Task ProcessPropertyPathExpressionAsync(IEdmPathExpression expression)
+ {
+ return this.schemaWriter.WritePropertyPathExpressionElementAsync(expression);
+ }
+
protected override void ProcessNavigationPropertyPathExpression(IEdmPathExpression expression)
{
this.schemaWriter.WriteNavigationPropertyPathExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the navigation property path expression.
+ ///
+ /// The Edm path expression.
+ protected override Task ProcessNavigationPropertyPathExpressionAsync(IEdmPathExpression expression)
+ {
+ return this.schemaWriter.WriteNavigationPropertyPathExpressionElementAsync(expression);
+ }
+
protected override void ProcessAnnotationPathExpression(IEdmPathExpression expression)
{
this.schemaWriter.WriteAnnotationPathExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the annotation path expression.
+ ///
+ /// The Edm path expression.
+ protected override Task ProcessAnnotationPathExpressionAsync(IEdmPathExpression expression)
+ {
+ return this.schemaWriter.WriteAnnotationPathExpressionElementAsync(expression);
+ }
+
protected override void ProcessCollectionExpression(IEdmCollectionExpression expression)
{
this.BeginElement(expression, this.schemaWriter.WriteCollectionExpressionElementHeader);
@@ -433,6 +981,17 @@ protected override void ProcessCollectionExpression(IEdmCollectionExpression exp
this.EndElement(expression, this.schemaWriter.WriteCollectionExpressionElementEnd);
}
+ ///
+ /// Asynchronously processes the collection expression.
+ ///
+ /// The Edm collection expression.
+ protected override async Task ProcessCollectionExpressionAsync(IEdmCollectionExpression expression)
+ {
+ await this.BeginElementAsync(expression, this.schemaWriter.WriteCollectionExpressionElementHeaderAsync).ConfigureAwait(false);
+ this.VisitExpressions(expression.Elements);
+ await this.EndElementAsync(expression, this.schemaWriter.WriteCollectionExpressionElementEndAsync).ConfigureAwait(false);
+ }
+
protected override void ProcessIsTypeExpression(IEdmIsTypeExpression expression)
{
bool inlineType = IsInlineType(expression.Type);
@@ -458,11 +1017,50 @@ protected override void ProcessIsTypeExpression(IEdmIsTypeExpression expression)
}
}
+ ///
+ /// Asynchronously processes the is type expression.
+ ///
+ /// The Edm IsType expression.
+ protected override async Task ProcessIsTypeExpressionAsync(IEdmIsTypeExpression expression)
+ {
+ bool inlineType = IsInlineType(expression.Type);
+
+ if (this.isXml)
+ {
+ await this.BeginElementAsync(expression, (IEdmIsTypeExpression t) => this.schemaWriter.WriteIsTypeExpressionElementHeaderAsync(t, inlineType), e => this.ProcessFacetsAsync(e.Type, inlineType)).ConfigureAwait(false);
+
+ if (!inlineType)
+ {
+ VisitTypeReference(expression.Type);
+ }
+
+ this.VisitExpression(expression.Operand);
+ await this.EndElementAsync(expression).ConfigureAwait(false);
+ }
+ else
+ {
+ await this.BeginElementAsync(expression, (IEdmIsTypeExpression t) => this.schemaWriter.WriteIsTypeExpressionElementHeaderAsync(t, inlineType)).ConfigureAwait(false);
+ this.VisitExpression(expression.Operand);
+ await this.schemaWriter.WriteIsOfExpressionTypeAsync(expression, inlineType).ConfigureAwait(false);
+ await this.ProcessFacetsAsync(expression.Type, inlineType).ConfigureAwait(false);
+ await this.EndElementAsync(expression).ConfigureAwait(false);
+ }
+ }
+
protected override void ProcessIntegerConstantExpression(IEdmIntegerConstantExpression expression)
{
this.schemaWriter.WriteIntegerConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the integer constant expression.
+ ///
+ /// The Edm integer constant expression.
+ protected override Task ProcessIntegerConstantExpressionAsync(IEdmIntegerConstantExpression expression)
+ {
+ return this.schemaWriter.WriteIntegerConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessIfExpression(IEdmIfExpression expression)
{
this.BeginElement(expression, this.schemaWriter.WriteIfExpressionElementHeader);
@@ -470,6 +1068,17 @@ protected override void ProcessIfExpression(IEdmIfExpression expression)
this.EndElement(expression, this.schemaWriter.WriteIfExpressionElementEnd);
}
+ ///
+ /// Asynchronously processes the if expression.
+ ///
+ /// The Edm If expression.
+ protected override async Task ProcessIfExpressionAsync(IEdmIfExpression expression)
+ {
+ await this.BeginElementAsync(expression, this.schemaWriter.WriteIfExpressionElementHeaderAsync).ConfigureAwait(false);
+ await base.ProcessIfExpressionAsync(expression).ConfigureAwait(false);
+ await this.EndElementAsync(expression, this.schemaWriter.WriteIfExpressionElementEndAsync).ConfigureAwait(false);
+ }
+
protected override void ProcessFunctionApplicationExpression(IEdmApplyExpression expression)
{
this.BeginElement(expression, e => this.schemaWriter.WriteFunctionApplicationElementHeader(e));
@@ -477,56 +1086,157 @@ protected override void ProcessFunctionApplicationExpression(IEdmApplyExpression
this.EndElement(expression, e => this.schemaWriter.WriteFunctionApplicationElementEnd(e));
}
+ ///
+ /// Asynchronously processes the function application expression.
+ ///
+ /// The Edm Apply expression.
+ protected override async Task ProcessFunctionApplicationExpressionAsync(IEdmApplyExpression expression)
+ {
+ await this.BeginElementAsync(expression, this.schemaWriter.WriteFunctionApplicationElementHeaderAsync).ConfigureAwait(false);
+ this.VisitExpressions(expression.Arguments);
+ await this.EndElementAsync(expression, this.schemaWriter.WriteFunctionApplicationElementEndAsync).ConfigureAwait(false);
+ }
+
protected override void ProcessFloatingConstantExpression(IEdmFloatingConstantExpression expression)
{
this.schemaWriter.WriteFloatingConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the floating constant expression.
+ ///
+ /// The Edm floating constant expression.
+ protected override Task ProcessFloatingConstantExpressionAsync(IEdmFloatingConstantExpression expression)
+ {
+ return this.schemaWriter.WriteFloatingConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessGuidConstantExpression(IEdmGuidConstantExpression expression)
{
this.schemaWriter.WriteGuidConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the guid constant expression.
+ ///
+ /// The Edm Guid constant expression.
+ protected override Task ProcessGuidConstantExpressionAsync(IEdmGuidConstantExpression expression)
+ {
+ return this.schemaWriter.WriteGuidConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessEnumMemberExpression(IEdmEnumMemberExpression expression)
{
this.schemaWriter.WriteEnumMemberExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the enum member expression.
+ ///
+ /// The Edm enumeration member.
+ protected override Task ProcessEnumMemberExpressionAsync(IEdmEnumMemberExpression expression)
+ {
+ return this.schemaWriter.WriteEnumMemberExpressionElementAsync(expression);
+ }
+
protected override void ProcessDecimalConstantExpression(IEdmDecimalConstantExpression expression)
{
this.schemaWriter.WriteDecimalConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the decimal constant expression.
+ ///
+ /// The Edm decimal constant expression.
+ protected override Task ProcessDecimalConstantExpressionAsync(IEdmDecimalConstantExpression expression)
+ {
+ return this.schemaWriter.WriteDecimalConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessDateConstantExpression(IEdmDateConstantExpression expression)
{
this.schemaWriter.WriteDateConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the date constant expression.
+ ///
+ /// The Edm date constant expression.
+ protected override Task ProcessDateConstantExpressionAsync(IEdmDateConstantExpression expression)
+ {
+ return this.schemaWriter.WriteDateConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessDateTimeOffsetConstantExpression(IEdmDateTimeOffsetConstantExpression expression)
{
this.schemaWriter.WriteDateTimeOffsetConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the date time offset constant expression.
+ ///
+ /// The Edm DateTimeOffset constant expression.
+ protected override Task ProcessDateTimeOffsetConstantExpressionAsync(IEdmDateTimeOffsetConstantExpression expression)
+ {
+ return this.schemaWriter.WriteDateTimeOffsetConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessDurationConstantExpression(IEdmDurationConstantExpression expression)
{
this.schemaWriter.WriteDurationConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the duration constant expression.
+ ///
+ /// The Edm duration constant expression.
+ protected override Task ProcessDurationConstantExpressionAsync(IEdmDurationConstantExpression expression)
+ {
+ return this.schemaWriter.WriteDurationConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessTimeOfDayConstantExpression(IEdmTimeOfDayConstantExpression expression)
{
this.schemaWriter.WriteTimeOfDayConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the time of day constant expression.
+ ///
+ /// The Edm TimeOfDay constant expression.
+ protected override Task ProcessTimeOfDayConstantExpressionAsync(IEdmTimeOfDayConstantExpression expression)
+ {
+ return this.schemaWriter.WriteTimeOfDayConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessBooleanConstantExpression(IEdmBooleanConstantExpression expression)
{
this.schemaWriter.WriteBooleanConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the boolean constant expression.
+ ///
+ /// The Edm boolean constant expression.
+ protected override Task ProcessBooleanConstantExpressionAsync(IEdmBooleanConstantExpression expression)
+ {
+ return this.schemaWriter.WriteBooleanConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessNullConstantExpression(IEdmNullExpression expression)
{
this.schemaWriter.WriteNullConstantExpressionElement(expression);
}
+ ///
+ /// Asynchronously processes the null constant expression.
+ ///
+ /// The Edm Null expression.
+ protected override Task ProcessNullConstantExpressionAsync(IEdmNullExpression expression)
+ {
+ return this.schemaWriter.WriteNullConstantExpressionElementAsync(expression);
+ }
+
protected override void ProcessCastExpression(IEdmCastExpression expression)
{
bool inlineType = IsInlineType(expression.Type);
@@ -555,6 +1265,39 @@ protected override void ProcessCastExpression(IEdmCastExpression expression)
}
}
+ ///
+ /// Asynchronously processes the cast expression.
+ ///
+ /// The Edm cast expression.
+ protected override async Task ProcessCastExpressionAsync(IEdmCastExpression expression)
+ {
+ bool inlineType = IsInlineType(expression.Type);
+
+ if (this.isXml)
+ {
+ await this.BeginElementAsync(expression, (IEdmCastExpression t) => this.schemaWriter.WriteCastExpressionElementHeaderAsync(t, inlineType), e => this.ProcessFacetsAsync(e.Type, inlineType)).ConfigureAwait(false);
+
+ if (!inlineType)
+ {
+ VisitTypeReference(expression.Type);
+ }
+
+ this.VisitExpression(expression.Operand);
+ await this.EndElementAsync(expression).ConfigureAwait(false);
+ }
+ else
+ {
+ await this.BeginElementAsync(expression, (IEdmCastExpression t) => this.schemaWriter.WriteCastExpressionElementHeaderAsync(t, inlineType)).ConfigureAwait(false);
+
+ this.VisitExpression(expression.Operand);
+
+ await this.schemaWriter.WriteCastExpressionTypeAsync(expression, inlineType).ConfigureAwait(false);
+ await this.ProcessFacetsAsync(expression.Type, inlineType).ConfigureAwait(false);
+
+ await this.EndElementAsync(expression, t => this.schemaWriter.WriteCastExpressionElementEndAsync(t, inlineType)).ConfigureAwait(false);
+ }
+ }
+
#endregion
private void ProcessNavigationPropertyBindings(IEdmNavigationSource navigationSource)
@@ -572,6 +1315,25 @@ private void ProcessNavigationPropertyBindings(IEdmNavigationSource navigationSo
}
}
+ ///
+ /// Asynchronously processes the navigation property bindings.
+ ///
+ /// The Edm navigation source.
+ private async Task ProcessNavigationPropertyBindingsAsync(IEdmNavigationSource navigationSource)
+ {
+ if (navigationSource != null && navigationSource.NavigationPropertyBindings.Any())
+ {
+ await this.schemaWriter.WriteNavigationPropertyBindingsBeginAsync(navigationSource.NavigationPropertyBindings).ConfigureAwait(false);
+
+ foreach (IEdmNavigationPropertyBinding binding in navigationSource.NavigationPropertyBindings)
+ {
+ await this.schemaWriter.WriteNavigationPropertyBindingAsync(binding).ConfigureAwait(false);
+ }
+
+ await this.schemaWriter.WriteNavigationPropertyBindingsEndAsync(navigationSource.NavigationPropertyBindings).ConfigureAwait(false);
+ }
+ }
+
private static bool IsInlineType(IEdmTypeReference reference)
{
if (reference.Definition is IEdmSchemaElement || reference.IsEntityReference())
@@ -639,6 +1401,26 @@ private void ProcessOperation(TOperation operation, Action
+ /// Asynchronously processes the operation.
+ ///
+ ///
+ /// Operation.
+ /// Write Element action.
+ private async Task ProcessOperationAsync(TOperation operation, Func writeElementAction) where TOperation : IEdmOperation
+ {
+ await this.BeginElementAsync(operation, writeElementAction).ConfigureAwait(false);
+
+ await this.schemaWriter.WriteOperationParametersBeginAsync(operation.Parameters).ConfigureAwait(false);
+ this.VisitOperationParameters(operation.Parameters);
+ await this.schemaWriter.WriteOperationParametersEndAsync(operation.Parameters).ConfigureAwait(false);
+
+ IEdmOperationReturn operationReturn = operation.GetReturn();
+ await this.ProcessOperationReturnAsync(operationReturn).ConfigureAwait(false);
+
+ await this.EndElementAsync(operation).ConfigureAwait(false);
+ }
+
private void ProcessReferentialConstraint(IEdmReferentialConstraint element)
{
if (element != null)
@@ -653,6 +1435,24 @@ private void ProcessReferentialConstraint(IEdmReferentialConstraint element)
}
}
+ ///
+ /// Asynchronously processes the referential constraint.
+ ///
+ /// The Edm referential constraint.
+ private async Task ProcessReferentialConstraintAsync(IEdmReferentialConstraint element)
+ {
+ if (element != null)
+ {
+ await this.schemaWriter.WriteReferentialConstraintBeginAsync(element).ConfigureAwait(false);
+ foreach (var pair in element.PropertyPairs)
+ {
+ await this.schemaWriter.WriteReferentialConstraintPairAsync(pair).ConfigureAwait(false);
+ }
+
+ await this.schemaWriter.WriteReferentialConstraintEndAsync(element).ConfigureAwait(false);
+ }
+ }
+
private void ProcessFacets(IEdmTypeReference element, bool inlineType)
{
if (element != null)
@@ -680,6 +1480,38 @@ private void ProcessFacets(IEdmTypeReference element, bool inlineType)
}
}
+ ///
+ /// Asynchronously processes the facets.
+ ///
+ /// The Edm type reference.
+ /// Is inline type or not.
+ private async Task ProcessFacetsAsync(IEdmTypeReference element, bool inlineType)
+ {
+ if (element != null)
+ {
+ if (element.IsEntityReference())
+ {
+ // No facets get serialized for an entity reference.
+ return;
+ }
+
+ if (inlineType)
+ {
+ if (element.TypeKind() == EdmTypeKind.Collection)
+ {
+ IEdmCollectionTypeReference collectionElement = element.AsCollection();
+ await this.schemaWriter.WriteNullableAttributeAsync(collectionElement.CollectionDefinition().ElementType).ConfigureAwait(false);
+ VisitTypeReference(collectionElement.CollectionDefinition().ElementType);
+ }
+ else
+ {
+ await this.schemaWriter.WriteNullableAttributeAsync(element).ConfigureAwait(false);
+ VisitTypeReference(element);
+ }
+ }
+ }
+ }
+
private void VisitEntityTypeDeclaredKey(IEnumerable keyProperties)
{
this.schemaWriter.WriteDeclaredKeyPropertiesElementHeader();
@@ -687,6 +1519,17 @@ private void VisitEntityTypeDeclaredKey(IEnumerable keyP
this.schemaWriter.WriteArrayEndElement();
}
+ ///
+ /// Asynchronously visits the entity type declared key.
+ ///
+ /// Collection of Edm structural properties.
+ private async Task VisitEntityTypeDeclaredKeyAsync(IEnumerable keyProperties)
+ {
+ await this.schemaWriter.WriteDeclaredKeyPropertiesElementHeaderAsync().ConfigureAwait(false);
+ await this.VisitPropertyRefsAsync(keyProperties).ConfigureAwait(false);
+ await this.schemaWriter.WriteArrayEndElementAsync().ConfigureAwait(false);
+ }
+
private void VisitPropertyRefs(IEnumerable properties)
{
foreach (IEdmStructuralProperty property in properties)
@@ -695,6 +1538,18 @@ private void VisitPropertyRefs(IEnumerable properties)
}
}
+ ///
+ /// Asynchronously visits the property references.
+ ///
+ /// Collection of Edm structural properties.
+ private async Task VisitPropertyRefsAsync(IEnumerable properties)
+ {
+ foreach (IEdmStructuralProperty property in properties)
+ {
+ await this.schemaWriter.WritePropertyRefElementAsync(property).ConfigureAwait(false);
+ }
+ }
+
private void VisitAttributeAnnotations(IEnumerable annotations)
{
foreach (IEdmDirectValueAnnotation annotation in annotations)
@@ -716,6 +1571,24 @@ private void VisitAttributeAnnotations(IEnumerable an
}
}
+ ///
+ /// Asynchronously visits the attribute annotations.
+ ///
+ /// Collection of Edm direct value annotations.
+ private async Task VisitAttributeAnnotationsAsync(IEnumerable annotations)
+ {
+ foreach (IEdmDirectValueAnnotation annotation in annotations)
+ {
+ if (annotation.NamespaceUri != EdmConstants.InternalUri && annotation.Value is IEdmValue edmValue && !edmValue.IsSerializedAsElement(this.Model))
+ {
+ if (edmValue.Type.TypeKind() == EdmTypeKind.Primitive)
+ {
+ await this.ProcessAttributeAnnotationAsync(annotation).ConfigureAwait(false);
+ }
+ }
+ }
+ }
+
private void VisitPrimitiveElementAnnotations(IEnumerable annotations)
{
foreach (IEdmDirectValueAnnotation annotation in annotations)
@@ -737,16 +1610,52 @@ private void VisitPrimitiveElementAnnotations(IEnumerable
+ /// Asynchronously visits the primitive element annotations.
+ ///
+ /// Collection of Edm direct value annotations.
+ private async Task VisitPrimitiveElementAnnotationsAsync(IEnumerable annotations)
+ {
+ foreach (IEdmDirectValueAnnotation annotation in annotations)
+ {
+ if (annotation.NamespaceUri != EdmConstants.InternalUri && annotation.Value is IEdmValue edmValue && edmValue.IsSerializedAsElement(this.Model))
+ {
+ if (edmValue.Type.TypeKind() == EdmTypeKind.Primitive)
+ {
+ await this.ProcessElementAnnotationAsync(annotation).ConfigureAwait(false);
+ }
+ }
+ }
+ }
+
private void ProcessAttributeAnnotation(IEdmDirectValueAnnotation annotation)
{
this.schemaWriter.WriteAnnotationStringAttribute(annotation);
}
+ ///
+ /// Asynchronously processes the attribute annotation.
+ ///
+ /// The Edm direct value annotation.
+ private Task ProcessAttributeAnnotationAsync(IEdmDirectValueAnnotation annotation)
+ {
+ return this.schemaWriter.WriteAnnotationStringAttributeAsync(annotation);
+ }
+
private void ProcessElementAnnotation(IEdmDirectValueAnnotation annotation)
{
this.schemaWriter.WriteAnnotationStringElement(annotation);
}
+ ///
+ /// Asynchronously processes the element annotation.
+ ///
+ /// The Edm Direct value annotation.
+ private Task ProcessElementAnnotationAsync(IEdmDirectValueAnnotation annotation)
+ {
+ return this.schemaWriter.WriteAnnotationStringElementAsync(annotation);
+ }
+
private void VisitElementVocabularyAnnotations(IEnumerable annotations)
{
foreach (IEdmVocabularyAnnotation annotation in annotations)
@@ -755,6 +1664,18 @@ private void VisitElementVocabularyAnnotations(IEnumerable
+ /// Asynchronously visits the element vocabulary annotations.
+ ///
+ /// Collection of Edm vocabulary annotation.
+ private async Task VisitElementVocabularyAnnotationsAsync(IEnumerable annotations)
+ {
+ foreach (IEdmVocabularyAnnotation annotation in annotations)
+ {
+ await this.ProcessAnnotationAsync(annotation).ConfigureAwait(false);
+ }
+ }
+
private void BeginElement(TElement element, Action elementHeaderWriter, params Action[] additionalAttributeWriters)
where TElement : IEdmElement
{
@@ -770,6 +1691,28 @@ private void BeginElement(TElement element, Action elementHe
this.VisitAttributeAnnotations(this.Model.DirectValueAnnotations(element));
}
+ ///
+ /// Asynchronously begins the element.
+ ///
+ ///
+ /// The Edm element.
+ /// The Edm element Header writer.
+ /// Collection of additional attribute writers.
+ private async Task BeginElementAsync(TElement element, Func elementHeaderWriter, params Func[] additionalAttributeWriters)
+ where TElement : IEdmElement
+ {
+ await elementHeaderWriter(element).ConfigureAwait(false);
+ if (additionalAttributeWriters != null && additionalAttributeWriters.Length > 0)
+ {
+ foreach (Func action in additionalAttributeWriters)
+ {
+ await action(element).ConfigureAwait(false);
+ }
+ }
+
+ await this.VisitAttributeAnnotationsAsync(this.Model.DirectValueAnnotations(element)).ConfigureAwait(false);
+ }
+
private void EndElement(TElement element, Action elementEndWriter) where TElement : IEdmElement
{
this.VisitPrimitiveElementAnnotations(this.Model.DirectValueAnnotations(element));
@@ -783,6 +1726,24 @@ private void EndElement(TElement element, Action elementEndW
elementEndWriter(element);
}
+ ///
+ /// Asynchronously ends the element.
+ ///
+ ///
+ /// The Edm element.
+ /// The Edm element end writer.
+ private async Task EndElementAsync(TElement element, Func elementEndWriter) where TElement : IEdmElement
+ {
+ await this.VisitPrimitiveElementAnnotationsAsync(this.Model.DirectValueAnnotations(element)).ConfigureAwait(false);
+
+ if (element is IEdmVocabularyAnnotatable vocabularyAnnotatableElement)
+ {
+ await this.VisitElementVocabularyAnnotationsAsync(this.Model.FindDeclaredVocabularyAnnotations(vocabularyAnnotatableElement).Where(a => a.IsInline(this.Model))).ConfigureAwait(false);
+ }
+
+ await elementEndWriter(element).ConfigureAwait(false);
+ }
+
private void EndElement(IEdmElement element)
{
this.VisitPrimitiveElementAnnotations(this.Model.DirectValueAnnotations(element));
@@ -794,5 +1755,20 @@ private void EndElement(IEdmElement element)
this.schemaWriter.WriteEndElement();
}
+
+ ///
+ /// Asynchronously ends the element.
+ ///
+ /// The Edm element.
+ private async Task EndElementAsync(IEdmElement element)
+ {
+ await this.VisitPrimitiveElementAnnotationsAsync(this.Model.DirectValueAnnotations(element)).ConfigureAwait(false);
+ if (element is IEdmVocabularyAnnotatable vocabularyAnnotatableElement)
+ {
+ await this.VisitElementVocabularyAnnotationsAsync(this.Model.FindDeclaredVocabularyAnnotations(vocabularyAnnotatableElement).Where(a => a.IsInline(this.Model))).ConfigureAwait(false);
+ }
+
+ await this.schemaWriter.WriteEndElementAsync().ConfigureAwait(false);
+ }
}
}
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.cs
index 1266049fdc..7346f348a3 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.cs
@@ -10,6 +10,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
+using System.Threading.Tasks;
namespace Microsoft.OData.Edm.Csdl.Serialization
{
@@ -27,6 +28,10 @@ internal EdmModelReferenceElementsJsonVisitor(IEdmModel model, Utf8JsonWriter wr
this.schemaWriter = new EdmModelCsdlSchemaJsonWriter(model, writer, edmVersion);
}
+ ///
+ /// Visits Edm references and Write includes and annotations.
+ ///
+ /// The Edm Model.
internal void VisitEdmReferences(IEdmModel model)
{
IEnumerable references = model.GetEdmReferences();
@@ -54,6 +59,43 @@ internal void VisitEdmReferences(IEdmModel model)
}
}
+ ///
+ /// Asynchronously Visits Edm references and Write includes and annotations.
+ ///
+ /// The Edm Model.
+ /// Task represents an asynchronous operation.
+ internal async Task VisitEdmReferencesAsync(IEdmModel model)
+ {
+ IEnumerable references = model.GetEdmReferences();
+ if (model != null && references != null && references.Any())
+ {
+ // The value of $Reference is an object that contains one member per referenced CSDL document.
+ this.jsonWriter.WritePropertyName("$Reference");
+ this.jsonWriter.WriteStartObject();
+
+ foreach (IEdmReference refence in references)
+ {
+ await this.schemaWriter.WriteReferenceElementHeaderAsync(refence).ConfigureAwait(false);
+
+ await WriteIncludesAsync(model, refence.Includes).ConfigureAwait(false);
+
+ await WriteIncludeAnnotationsAsync(refence.IncludeAnnotations).ConfigureAwait(false);
+
+ await WriteAnnotationsAsync(model, refence).ConfigureAwait(false);
+
+ await this.schemaWriter.WriteReferenceElementEndAsync(refence).ConfigureAwait(false);
+ }
+
+ // End of $Reference
+ this.jsonWriter.WriteEndObject();
+ }
+ }
+
+ ///
+ /// Writes Includes
+ ///
+ /// The Edm model.
+ /// Collection of Edm includes.
private void WriteIncludes(IEdmModel model, IEnumerable includes)
{
if (includes == null || !includes.Any())
@@ -81,7 +123,39 @@ private void WriteIncludes(IEdmModel model, IEnumerable includes)
}
///
- /// $IncludeAnnotations Array.
+ /// Asynchronously Writes Includes
+ ///
+ /// The Edm model.
+ /// Collection of Edm includes.
+ /// Task represents an asynchronous operation.
+ private async Task WriteIncludesAsync(IEdmModel model, IEnumerable includes)
+ {
+ if (includes == null || !includes.Any())
+ {
+ return;
+ }
+
+ // The reference object MAY contain the members $Include
+ this.jsonWriter.WritePropertyName("$Include");
+
+ // The value of $Include is an array.
+ this.jsonWriter.WriteStartArray();
+
+ foreach (IEdmInclude include in includes)
+ {
+ // Array items are objects.
+ await this.schemaWriter.WritIncludeElementHeaderAsync(include).ConfigureAwait(false);
+
+ await WriteAnnotationsAsync(model, include).ConfigureAwait(false);
+
+ await this.schemaWriter.WriteIncludeElementEndAsync(include).ConfigureAwait(false);
+ }
+
+ this.jsonWriter.WriteEndArray();
+ }
+
+ ///
+ /// Wrties $IncludeAnnotations Array.
///
private void WriteIncludeAnnotations(IEnumerable includeAnnotations)
{
@@ -116,6 +190,51 @@ private void WriteIncludeAnnotations(IEnumerable include
this.jsonWriter.WriteEndArray();
}
+ ///
+ /// Asynchronously Writes $IncludeAnnotations Array
+ ///
+ /// Collection of Edm include annotations.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ private Task WriteIncludeAnnotationsAsync(IEnumerable includeAnnotations)
+ {
+ if (includeAnnotations == null || !includeAnnotations.Any())
+ {
+ return Task.CompletedTask;
+ }
+
+ // The reference object MAY contain the members $IncludeAnnotations
+ this.jsonWriter.WritePropertyName("$IncludeAnnotations");
+
+ // The value of $IncludeAnnotations is an array.
+ this.jsonWriter.WriteStartArray();
+
+ foreach (IEdmIncludeAnnotations includeAnnotation in includeAnnotations)
+ {
+ // Array items are objects
+ this.jsonWriter.WriteStartObject();
+
+ // MUST contain the member $TermNamespace
+ this.jsonWriter.WriteRequiredProperty("$TermNamespace", includeAnnotation.TermNamespace);
+
+ // MAY contain the members $Qualifier
+ this.jsonWriter.WriteOptionalProperty("$Qualifier", includeAnnotation.Qualifier);
+
+ // MAY contain the members $TargetNamespace
+ this.jsonWriter.WriteOptionalProperty("$TargetNamespace", includeAnnotation.TargetNamespace);
+
+ this.jsonWriter.WriteEndObject();
+ }
+
+ this.jsonWriter.WriteEndArray();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// Writes Annotations
+ ///
+ /// The Edm model.
+ /// The Edm vocabulary annotations.
private void WriteAnnotations(IEdmModel model, IEdmVocabularyAnnotatable target)
{
var annotations = model.FindDeclaredVocabularyAnnotations(target);
@@ -125,6 +244,22 @@ private void WriteAnnotations(IEdmModel model, IEdmVocabularyAnnotatable target)
this.schemaWriter.WriteVocabularyAnnotationElementEnd(annotation, true);
}
}
+
+ ///
+ /// Asynchronously Writes Annotations
+ ///
+ /// The Edm model.
+ /// The Edm vocabulary annotations.
+ /// Task represents an asynchronous operation that may or may not return a result.
+ private async Task WriteAnnotationsAsync(IEdmModel model, IEdmVocabularyAnnotatable target)
+ {
+ var annotations = model.FindDeclaredVocabularyAnnotations(target);
+ foreach (IEdmVocabularyAnnotation annotation in annotations)
+ {
+ await this.schemaWriter.WriteVocabularyAnnotationElementHeaderAsync(annotation, true).ConfigureAwait(false);
+ await this.schemaWriter.WriteVocabularyAnnotationElementEndAsync(annotation, true).ConfigureAwait(false);
+ }
+ }
}
}
#endif
\ No newline at end of file
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs
index 08cc19481b..2932f5c8fe 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs
@@ -5,6 +5,7 @@
//---------------------------------------------------------------------
using System;
+using System.Threading.Tasks;
using System.Xml;
using Microsoft.OData.Edm.Vocabularies;
@@ -52,6 +53,41 @@ internal void VisitEdmReferences(IEdmModel model, IEdmReference reference)
}
+ ///
+ /// Asynchronously visit Edm references and Write includes and annotations.
+ ///
+ /// The Edm model.
+ /// The Edm reference.
+ /// Task represents an asynchronous operation.
+ internal async Task VisitEdmReferencesAsync(IEdmModel model, IEdmReference reference)
+ {
+ await this.schemaWriter.WriteReferenceElementHeaderAsync(reference).ConfigureAwait(false);
+
+ if (reference.Includes != null)
+ {
+ foreach (IEdmInclude include in reference.Includes)
+ {
+ await this.schemaWriter.WritIncludeElementHeaderAsync(include).ConfigureAwait(false);
+
+ await WriteAnnotationsAsync(model, include).ConfigureAwait(false);
+
+ await this.schemaWriter.WriteIncludeElementEndAsync(include).ConfigureAwait(false);
+ }
+ }
+
+ if (reference.IncludeAnnotations != null)
+ {
+ foreach (IEdmIncludeAnnotations includeAnnotations in reference.IncludeAnnotations)
+ {
+ await this.schemaWriter.WriteIncludeAnnotationsElementAsync(includeAnnotations).ConfigureAwait(false);
+ }
+ }
+
+ await WriteAnnotationsAsync(model, reference).ConfigureAwait(false);
+ await this.schemaWriter.WriteReferenceElementEndAsync(reference).ConfigureAwait(false);
+
+ }
+
private void WriteAnnotations(IEdmModel model, IEdmVocabularyAnnotatable target)
{
var annotations = model.FindDeclaredVocabularyAnnotations(target);
@@ -62,6 +98,22 @@ private void WriteAnnotations(IEdmModel model, IEdmVocabularyAnnotatable target)
}
}
+ ///
+ /// Asynchronously write annotations.
+ ///
+ /// The Edm model.
+ /// The Edm vocabulary annotations.
+ /// Task represents an asynchronous operation.
+ private async Task WriteAnnotationsAsync(IEdmModel model, IEdmVocabularyAnnotatable target)
+ {
+ var annotations = model.FindDeclaredVocabularyAnnotations(target);
+ foreach (IEdmVocabularyAnnotation annotation in annotations)
+ {
+ await this.schemaWriter.WriteVocabularyAnnotationElementHeaderAsync(annotation, true).ConfigureAwait(false);
+ await this.schemaWriter.WriteVocabularyAnnotationElementEndAsync(annotation, true).ConfigureAwait(false);
+ }
+ }
+
#endregion
}
}
\ No newline at end of file
diff --git a/src/Microsoft.OData.Edm/EdmModelVisitor.cs b/src/Microsoft.OData.Edm/EdmModelVisitor.cs
index 2477986ff1..a50b58edd8 100644
--- a/src/Microsoft.OData.Edm/EdmModelVisitor.cs
+++ b/src/Microsoft.OData.Edm/EdmModelVisitor.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using Microsoft.OData.Edm.Vocabularies;
namespace Microsoft.OData.Edm
@@ -228,6 +229,33 @@ public virtual void VisitEntityContainerElements(IEnumerable elements)
+ {
+ foreach (IEdmEntityContainerElement element in elements)
+ {
+ switch (element.ContainerElementKind)
+ {
+ case EdmContainerElementKind.EntitySet:
+ await this.ProcessEntitySetAsync((IEdmEntitySet)element);
+ break;
+ case EdmContainerElementKind.Singleton:
+ await this.ProcessSingletonAsync((IEdmSingleton)element);
+ break;
+ case EdmContainerElementKind.ActionImport:
+ await this.ProcessActionImportAsync((IEdmActionImport)element);
+ break;
+ case EdmContainerElementKind.FunctionImport:
+ await this.ProcessFunctionImportAsync((IEdmFunctionImport)element);
+ break;
+ case EdmContainerElementKind.None:
+ await this.ProcessEntityContainerElementAsync(element);
+ break;
+ default:
+ throw new InvalidOperationException(Edm.Strings.UnknownEnumVal_ContainerElementKind(element.ContainerElementKind.ToString()));
+ }
+ }
+ }
+
#endregion
#region Type References
@@ -427,21 +455,45 @@ protected virtual void ProcessElement(IEdmElement element)
this.VisitAnnotations(this.Model.DirectValueAnnotations(element));
}
+ protected virtual Task ProcessElementAsync(IEdmElement element)
+ {
+ // TODO: DirectValueAnnotationsInMainSchema (not including those in referenced schemas)
+ this.VisitAnnotations(this.Model.DirectValueAnnotations(element));
+
+ return Task.CompletedTask;
+ }
+
protected virtual void ProcessNamedElement(IEdmNamedElement element)
{
this.ProcessElement(element);
}
+ protected virtual async Task ProcessNamedElementAsync(IEdmNamedElement element)
+ {
+ await this.ProcessElementAsync(element);
+ }
+
protected virtual void ProcessSchemaElement(IEdmSchemaElement element)
{
this.ProcessVocabularyAnnotatable(element);
this.ProcessNamedElement(element);
}
+ protected virtual async Task ProcessSchemaElementAsync(IEdmSchemaElement element)
+ {
+ await this.ProcessVocabularyAnnotatableAsync(element);
+ await this.ProcessNamedElementAsync(element);
+ }
+
protected virtual void ProcessVocabularyAnnotatable(IEdmVocabularyAnnotatable annotatable)
{
}
+ protected virtual Task ProcessVocabularyAnnotatableAsync(IEdmVocabularyAnnotatable annotatable)
+ {
+ return Task.CompletedTask;
+ }
+
#endregion
#region Type References
@@ -451,83 +503,165 @@ protected virtual void ProcessComplexTypeReference(IEdmComplexTypeReference refe
this.ProcessStructuredTypeReference(reference);
}
+ protected virtual async Task ProcessComplexTypeReferenceAsync(IEdmComplexTypeReference reference)
+ {
+ await this.ProcessStructuredTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessEntityTypeReference(IEdmEntityTypeReference reference)
{
this.ProcessStructuredTypeReference(reference);
}
+ protected virtual async Task ProcessEntityTypeReferenceAsync(IEdmEntityTypeReference reference)
+ {
+ await this.ProcessStructuredTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessEntityReferenceTypeReference(IEdmEntityReferenceTypeReference reference)
{
this.ProcessTypeReference(reference);
this.ProcessEntityReferenceType(reference.EntityReferenceDefinition());
}
+ protected virtual async Task ProcessEntityReferenceTypeReferenceAsync(IEdmEntityReferenceTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ await this.ProcessEntityReferenceTypeAsync(reference.EntityReferenceDefinition());
+ }
+
protected virtual void ProcessCollectionTypeReference(IEdmCollectionTypeReference reference)
{
this.ProcessTypeReference(reference);
this.ProcessCollectionType(reference.CollectionDefinition());
}
+ protected virtual async Task ProcessCollectionTypeReferenceAsync(IEdmCollectionTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ await this.ProcessCollectionTypeAsync(reference.CollectionDefinition());
+ }
+
protected virtual void ProcessEnumTypeReference(IEdmEnumTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessEnumTypeReferenceAsync(IEdmEnumTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessTypeDefinitionReference(IEdmTypeDefinitionReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessTypeDefinitionReferenceAsync(IEdmTypeDefinitionReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessBinaryTypeReference(IEdmBinaryTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessBinaryTypeReferenceAsync(IEdmBinaryTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessDecimalTypeReference(IEdmDecimalTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessDecimalTypeReferenceAsync(IEdmDecimalTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessSpatialTypeReference(IEdmSpatialTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessSpatialTypeReferenceAsync(IEdmSpatialTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessStringTypeReference(IEdmStringTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessStringTypeReferenceAsync(IEdmStringTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessTemporalTypeReference(IEdmTemporalTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessTemporalTypeReferenceAsync(IEdmTemporalTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessPrimitiveTypeReference(IEdmPrimitiveTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessPrimitiveTypeReferenceAsync(IEdmPrimitiveTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessStructuredTypeReference(IEdmStructuredTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessStructuredTypeReferenceAsync(IEdmStructuredTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessTypeReference(IEdmTypeReference element)
{
this.ProcessElement(element);
}
+ protected virtual async Task ProcessTypeReferenceAsync(IEdmTypeReference element)
+ {
+ await this.ProcessElementAsync(element);
+ }
+
protected virtual void ProcessPathTypeReference(IEdmPathTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessPathTypeReferenceAsync(IEdmPathTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ }
+
protected virtual void ProcessUntypedTypeReference(IEdmUntypedTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessUntypedTypeReferenceAsync(IEdmUntypedTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference);
+ }
+
#endregion
#region Terms
@@ -538,6 +672,12 @@ protected virtual void ProcessTerm(IEdmTerm term)
this.VisitTypeReference(term.Type);
}
+ protected virtual async Task ProcessTermAsync(IEdmTerm term)
+ {
+ await this.ProcessSchemaElementAsync(term);
+ this.VisitTypeReference(term.Type);
+ }
+
#endregion
#region Type Definitions
@@ -549,6 +689,13 @@ protected virtual void ProcessComplexType(IEdmComplexType definition)
this.ProcessSchemaType(definition);
}
+ protected virtual async Task ProcessComplexTypeAsync(IEdmComplexType definition)
+ {
+ await this.ProcessSchemaElementAsync(definition);
+ await this.ProcessStructuredTypeAsync(definition);
+ await this.ProcessSchemaTypeAsync(definition);
+ }
+
protected virtual void ProcessEntityType(IEdmEntityType definition)
{
this.ProcessSchemaElement(definition);
@@ -556,6 +703,13 @@ protected virtual void ProcessEntityType(IEdmEntityType definition)
this.ProcessSchemaType(definition);
}
+ protected virtual async Task ProcessEntityTypeAsync(IEdmEntityType definition)
+ {
+ await this.ProcessSchemaElementAsync(definition);
+ await this.ProcessStructuredTypeAsync(definition);
+ await this.ProcessSchemaTypeAsync(definition);
+ }
+
protected virtual void ProcessCollectionType(IEdmCollectionType definition)
{
this.ProcessElement(definition);
@@ -563,6 +717,13 @@ protected virtual void ProcessCollectionType(IEdmCollectionType definition)
this.VisitTypeReference(definition.ElementType);
}
+ protected virtual async Task ProcessCollectionTypeAsync(IEdmCollectionType definition)
+ {
+ await this.ProcessElementAsync(definition);
+ await this.ProcessTypeAsync(definition);
+ this.VisitTypeReference(definition.ElementType);
+ }
+
protected virtual void ProcessEnumType(IEdmEnumType definition)
{
this.ProcessSchemaElement(definition);
@@ -571,6 +732,14 @@ protected virtual void ProcessEnumType(IEdmEnumType definition)
this.VisitEnumMembers(definition.Members);
}
+ protected virtual async Task ProcessEnumTypeAsync(IEdmEnumType definition)
+ {
+ await this.ProcessSchemaElementAsync(definition);
+ await this.ProcessTypeAsync(definition);
+ await this.ProcessSchemaTypeAsync(definition);
+ this.VisitEnumMembers(definition.Members);
+ }
+
protected virtual void ProcessTypeDefinition(IEdmTypeDefinition definition)
{
this.ProcessSchemaElement(definition);
@@ -578,27 +747,57 @@ protected virtual void ProcessTypeDefinition(IEdmTypeDefinition definition)
this.ProcessSchemaType(definition);
}
+ protected virtual async Task ProcessTypeDefinitionAsync(IEdmTypeDefinition definition)
+ {
+ await this.ProcessSchemaElementAsync(definition);
+ await this.ProcessTypeAsync(definition);
+ await this.ProcessSchemaTypeAsync(definition);
+ }
+
protected virtual void ProcessEntityReferenceType(IEdmEntityReferenceType definition)
{
this.ProcessElement(definition);
this.ProcessType(definition);
}
+ protected virtual async Task ProcessEntityReferenceTypeAsync(IEdmEntityReferenceType definition)
+ {
+ await this.ProcessElementAsync(definition);
+ await this.ProcessTypeAsync(definition);
+ }
+
protected virtual void ProcessStructuredType(IEdmStructuredType definition)
{
this.ProcessType(definition);
this.VisitProperties(definition.DeclaredProperties);
}
+ protected virtual async Task ProcessStructuredTypeAsync(IEdmStructuredType definition)
+ {
+ await this.ProcessTypeAsync(definition);
+ this.VisitProperties(definition.DeclaredProperties);
+ }
+
protected virtual void ProcessSchemaType(IEdmSchemaType type)
{
// Do not visit type or schema element, because all types will do that on their own.
}
+ protected virtual Task ProcessSchemaTypeAsync(IEdmSchemaType type)
+ {
+ // Do not visit type or schema element, because all types will do that on their own.
+ return Task.CompletedTask;
+ }
+
protected virtual void ProcessType(IEdmType definition)
{
}
+ protected virtual Task ProcessTypeAsync(IEdmType definition)
+ {
+ return Task.CompletedTask;
+ }
+
#endregion
#region Definition Components
@@ -608,11 +807,21 @@ protected virtual void ProcessNavigationProperty(IEdmNavigationProperty property
this.ProcessProperty(property);
}
+ protected virtual async Task ProcessNavigationPropertyAsync(IEdmNavigationProperty property)
+ {
+ await this.ProcessPropertyAsync(property);
+ }
+
protected virtual void ProcessStructuralProperty(IEdmStructuralProperty property)
{
this.ProcessProperty(property);
}
+ protected virtual async Task ProcessStructuralPropertyAsync(IEdmStructuralProperty property)
+ {
+ await this.ProcessPropertyAsync(property);
+ }
+
protected virtual void ProcessProperty(IEdmProperty property)
{
this.ProcessVocabularyAnnotatable(property);
@@ -620,11 +829,23 @@ protected virtual void ProcessProperty(IEdmProperty property)
this.VisitTypeReference(property.Type);
}
+ protected virtual async Task ProcessPropertyAsync(IEdmProperty property)
+ {
+ await this.ProcessVocabularyAnnotatableAsync(property);
+ await this.ProcessNamedElementAsync(property);
+ this.VisitTypeReference(property.Type);
+ }
+
protected virtual void ProcessEnumMember(IEdmEnumMember enumMember)
{
this.ProcessNamedElement(enumMember);
}
+ protected virtual async Task ProcessEnumMemberAsync(IEdmEnumMember enumMember)
+ {
+ await this.ProcessNamedElementAsync(enumMember);
+ }
+
#endregion
#region Annotations
@@ -634,17 +855,33 @@ protected virtual void ProcessVocabularyAnnotation(IEdmVocabularyAnnotation anno
this.ProcessElement(annotation);
}
+ protected virtual async Task ProcessVocabularyAnnotationAsync(IEdmVocabularyAnnotation annotation)
+ {
+ await this.ProcessElementAsync(annotation);
+ }
+
protected virtual void ProcessImmediateValueAnnotation(IEdmDirectValueAnnotation annotation)
{
this.ProcessNamedElement(annotation);
}
+ protected virtual async Task ProcessImmediateValueAnnotationAsync(IEdmDirectValueAnnotation annotation)
+ {
+ await this.ProcessNamedElementAsync(annotation);
+ }
+
protected virtual void ProcessAnnotation(IEdmVocabularyAnnotation annotation)
{
this.ProcessVocabularyAnnotation(annotation);
this.VisitExpression(annotation.Value);
}
+ protected virtual async Task ProcessAnnotationAsync(IEdmVocabularyAnnotation annotation)
+ {
+ await this.ProcessVocabularyAnnotationAsync(annotation);
+ this.VisitExpression(annotation.Value);
+ }
+
protected virtual void ProcessPropertyValueBinding(IEdmPropertyValueBinding binding)
{
this.VisitExpression(binding.Value);
@@ -658,16 +895,31 @@ protected virtual void ProcessExpression(IEdmExpression expression)
{
}
+ protected virtual Task ProcessExpressionAsync(IEdmExpression expression)
+ {
+ return Task.CompletedTask;
+ }
+
protected virtual void ProcessStringConstantExpression(IEdmStringConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessStringConstantExpressionAsync(IEdmStringConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessBinaryConstantExpression(IEdmBinaryConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessBinaryConstantExpressionAsync(IEdmBinaryConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessRecordExpression(IEdmRecordExpression expression)
{
this.ProcessExpression(expression);
@@ -679,37 +931,79 @@ protected virtual void ProcessRecordExpression(IEdmRecordExpression expression)
this.VisitPropertyConstructors(expression.Properties);
}
+ protected virtual async Task ProcessRecordExpressionAsync(IEdmRecordExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ if (expression.DeclaredType != null)
+ {
+ this.VisitTypeReference(expression.DeclaredType);
+ }
+
+ this.VisitPropertyConstructors(expression.Properties);
+ }
+
protected virtual void ProcessPathExpression(IEdmPathExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessPathExpressionAsync(IEdmPathExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessPropertyPathExpression(IEdmPathExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessPropertyPathExpressionAsync(IEdmPathExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessNavigationPropertyPathExpression(IEdmPathExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessNavigationPropertyPathExpressionAsync(IEdmPathExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessAnnotationPathExpression(IEdmPathExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessAnnotationPathExpressionAsync(IEdmPathExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessCollectionExpression(IEdmCollectionExpression expression)
{
this.ProcessExpression(expression);
this.VisitExpressions(expression.Elements);
}
+ protected virtual async Task ProcessCollectionExpressionAsync(IEdmCollectionExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ this.VisitExpressions(expression.Elements);
+ }
+
protected virtual void ProcessLabeledExpressionReferenceExpression(IEdmLabeledExpressionReferenceExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessLabeledExpressionReferenceExpressionAsync(IEdmLabeledExpressionReferenceExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessIsTypeExpression(IEdmIsTypeExpression expression)
{
this.ProcessExpression(expression);
@@ -717,11 +1011,23 @@ protected virtual void ProcessIsTypeExpression(IEdmIsTypeExpression expression)
this.VisitExpression(expression.Operand);
}
+ protected virtual async Task ProcessIsTypeExpressionAsync(IEdmIsTypeExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ this.VisitTypeReference(expression.Type);
+ this.VisitExpression(expression.Operand);
+ }
+
protected virtual void ProcessIntegerConstantExpression(IEdmIntegerConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessIntegerConstantExpressionAsync(IEdmIntegerConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessIfExpression(IEdmIfExpression expression)
{
this.ProcessExpression(expression);
@@ -730,57 +1036,116 @@ protected virtual void ProcessIfExpression(IEdmIfExpression expression)
this.VisitExpression(expression.FalseExpression);
}
+ protected virtual async Task ProcessIfExpressionAsync(IEdmIfExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ this.VisitExpression(expression.TestExpression);
+ this.VisitExpression(expression.TrueExpression);
+ this.VisitExpression(expression.FalseExpression);
+ }
+
protected virtual void ProcessFunctionApplicationExpression(IEdmApplyExpression expression)
{
this.ProcessExpression(expression);
this.VisitExpressions(expression.Arguments);
}
+ protected virtual async Task ProcessFunctionApplicationExpressionAsync(IEdmApplyExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ this.VisitExpressions(expression.Arguments);
+ }
+
protected virtual void ProcessFloatingConstantExpression(IEdmFloatingConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessFloatingConstantExpressionAsync(IEdmFloatingConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessGuidConstantExpression(IEdmGuidConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessGuidConstantExpressionAsync(IEdmGuidConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessEnumMemberExpression(IEdmEnumMemberExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessEnumMemberExpressionAsync(IEdmEnumMemberExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessDecimalConstantExpression(IEdmDecimalConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDecimalConstantExpressionAsync(IEdmDecimalConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessDateConstantExpression(IEdmDateConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDateConstantExpressionAsync(IEdmDateConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessTimeOfDayConstantExpression(IEdmTimeOfDayConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessTimeOfDayConstantExpressionAsync(IEdmTimeOfDayConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessDateTimeOffsetConstantExpression(IEdmDateTimeOffsetConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDateTimeOffsetConstantExpressionAsync(IEdmDateTimeOffsetConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessDurationConstantExpression(IEdmDurationConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDurationConstantExpressionAsync(IEdmDurationConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessBooleanConstantExpression(IEdmBooleanConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessBooleanConstantExpressionAsync(IEdmBooleanConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
protected virtual void ProcessCastExpression(IEdmCastExpression expression)
{
this.ProcessExpression(expression);
@@ -788,21 +1153,48 @@ protected virtual void ProcessCastExpression(IEdmCastExpression expression)
this.VisitExpression(expression.Operand);
}
+ protected virtual async Task ProcessCastExpressionAsync(IEdmCastExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ this.VisitTypeReference(expression.Type);
+ this.VisitExpression(expression.Operand);
+ }
+
+
protected virtual void ProcessLabeledExpression(IEdmLabeledExpression element)
{
this.VisitExpression(element.Expression);
}
+ protected virtual Task ProcessLabeledExpressionAsync(IEdmLabeledExpression element)
+ {
+ this.VisitExpression(element.Expression);
+
+ return Task.CompletedTask;
+ }
+
protected virtual void ProcessPropertyConstructor(IEdmPropertyConstructor constructor)
{
this.VisitExpression(constructor.Value);
}
+ protected virtual Task ProcessPropertyConstructorAsync(IEdmPropertyConstructor constructor)
+ {
+ this.VisitExpression(constructor.Value);
+
+ return Task.CompletedTask;
+ }
+
protected virtual void ProcessNullConstantExpression(IEdmNullExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessNullConstantExpressionAsync(IEdmNullExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression);
+ }
+
#endregion
#region Data Model
@@ -814,21 +1206,43 @@ protected virtual void ProcessEntityContainer(IEdmEntityContainer container)
this.VisitEntityContainerElements(container.Elements);
}
+ protected virtual async Task ProcessEntityContainerAsync(IEdmEntityContainer container)
+ {
+ await this.ProcessVocabularyAnnotatableAsync(container);
+ await this.ProcessNamedElementAsync(container);
+ await this.VisitEntityContainerElementsAsync(container.Elements);
+ }
+
protected virtual void ProcessEntityContainerElement(IEdmEntityContainerElement element)
{
this.ProcessNamedElement(element);
}
+ protected virtual async Task ProcessEntityContainerElementAsync(IEdmEntityContainerElement element)
+ {
+ await this.ProcessNamedElementAsync(element);
+ }
+
protected virtual void ProcessEntitySet(IEdmEntitySet set)
{
this.ProcessEntityContainerElement(set);
}
+ protected virtual async Task ProcessEntitySetAsync(IEdmEntitySet set)
+ {
+ await this.ProcessEntityContainerElementAsync(set);
+ }
+
protected virtual void ProcessSingleton(IEdmSingleton singleton)
{
this.ProcessEntityContainerElement(singleton);
}
+ protected virtual async Task ProcessSingletonAsync(IEdmSingleton singleton)
+ {
+ await this.ProcessEntityContainerElementAsync(singleton);
+ }
+
#endregion
#region Operation Related
@@ -839,22 +1253,44 @@ protected virtual void ProcessAction(IEdmAction action)
this.ProcessOperation(action);
}
+ protected virtual async Task ProcessActionAsync(IEdmAction action)
+ {
+ await this.ProcessSchemaElementAsync(action);
+ await this.ProcessOperationAsync(action);
+ }
+
protected virtual void ProcessFunction(IEdmFunction function)
{
this.ProcessSchemaElement(function);
this.ProcessOperation(function);
}
+ protected virtual async Task ProcessFunctionAsync(IEdmFunction function)
+ {
+ await this.ProcessSchemaElementAsync(function);
+ await this.ProcessOperationAsync(function);
+ }
+
protected virtual void ProcessActionImport(IEdmActionImport actionImport)
{
this.ProcessEntityContainerElement(actionImport);
}
+ protected virtual async Task ProcessActionImportAsync(IEdmActionImport actionImport)
+ {
+ await this.ProcessEntityContainerElementAsync(actionImport);
+ }
+
protected virtual void ProcessFunctionImport(IEdmFunctionImport functionImport)
{
this.ProcessEntityContainerElement(functionImport);
}
+ protected virtual async Task ProcessFunctionImportAsync(IEdmFunctionImport functionImport)
+ {
+ await this.ProcessEntityContainerElementAsync(functionImport);
+ }
+
protected virtual void ProcessOperation(IEdmOperation operation)
{
// Do not visit vocabularyAnnotatable because functions and operation imports are always going to be either a schema element or a container element and will be visited through those paths.
@@ -864,6 +1300,15 @@ protected virtual void ProcessOperation(IEdmOperation operation)
this.ProcessOperationReturn(operationReturn);
}
+ protected virtual async Task ProcessOperationAsync(IEdmOperation operation)
+ {
+ // Do not visit vocabularyAnnotatable because functions and operation imports are always going to be either a schema element or a container element and will be visited through those paths.
+ this.VisitOperationParameters(operation.Parameters);
+
+ IEdmOperationReturn operationReturn = operation.GetReturn();
+ await this.ProcessOperationReturnAsync(operationReturn);
+ }
+
protected virtual void ProcessOperationParameter(IEdmOperationParameter parameter)
{
this.ProcessVocabularyAnnotatable(parameter);
@@ -871,6 +1316,13 @@ protected virtual void ProcessOperationParameter(IEdmOperationParameter paramete
this.VisitTypeReference(parameter.Type);
}
+ protected virtual async Task ProcessOperationParameterAsync(IEdmOperationParameter parameter)
+ {
+ await this.ProcessVocabularyAnnotatableAsync(parameter);
+ await this.ProcessNamedElementAsync(parameter);
+ this.VisitTypeReference(parameter.Type);
+ }
+
protected virtual void ProcessOperationReturn(IEdmOperationReturn operationReturn)
{
if (operationReturn == null)
@@ -881,6 +1333,17 @@ protected virtual void ProcessOperationReturn(IEdmOperationReturn operationRetur
this.ProcessVocabularyAnnotatable(operationReturn);
this.VisitTypeReference(operationReturn.Type);
}
+
+ protected virtual async Task ProcessOperationReturnAsync(IEdmOperationReturn operationReturn)
+ {
+ if (operationReturn == null)
+ {
+ return;
+ }
+
+ await this.ProcessVocabularyAnnotatableAsync(operationReturn);
+ this.VisitTypeReference(operationReturn.Type);
+ }
#endregion
#endregion
diff --git a/src/Microsoft.OData.Edm/PublicAPI/net48/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/net48/PublicAPI.Unshipped.txt
index 8de5ff2b2b..9016204d28 100644
--- a/src/Microsoft.OData.Edm/PublicAPI/net48/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Edm/PublicAPI/net48/PublicAPI.Unshipped.txt
@@ -1456,14 +1456,22 @@ static Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(System.Xml.XmlReader reader,
static Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(System.Xml.XmlReader reader, System.Collections.Generic.IEnumerable references, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(System.Xml.XmlReader reader, System.Func getReferencedModelReaderFunc, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.CsdlWriter.GetVersionString(System.Version version) -> string
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdmModel model, System.Text.Json.Utf8JsonWriter writer, Microsoft.OData.Edm.Csdl.CsdlJsonWriterSettings settings, out System.Collections.Generic.IEnumerable errors) -> bool
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdmModel model, System.Text.Json.Utf8JsonWriter writer, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target, Microsoft.OData.Edm.Csdl.CsdlXmlWriterSettings writerSettings, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target, out System.Collections.Generic.IEnumerable errors) -> bool
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Text.Json.Utf8JsonWriter writer) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Text.Json.Utf8JsonWriter writer, Microsoft.OData.Edm.Csdl.CsdlJsonWriterSettings settings) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target, Microsoft.OData.Edm.Csdl.CsdlXmlWriterSettings writerSettings) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, Microsoft.OData.Edm.IEdmModel reference, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, System.Collections.Generic.IEnumerable references, bool includeDefaultVocabularies, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, System.Collections.Generic.IEnumerable references, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchema(this Microsoft.OData.Edm.IEdmModel model, System.Func writerProvider, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchema(this Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, out System.Collections.Generic.IEnumerable errors) -> bool
+static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchemaAsync(this Microsoft.OData.Edm.IEdmModel model, System.Func writerProvider) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchemaAsync(this Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
static Microsoft.OData.Edm.Csdl.SerializationExtensionMethods.GetEdmxVersion(this Microsoft.OData.Edm.IEdmModel model) -> System.Version
static Microsoft.OData.Edm.Csdl.SerializationExtensionMethods.GetNamespaceAlias(this Microsoft.OData.Edm.IEdmModel model, string namespaceName) -> string
static Microsoft.OData.Edm.Csdl.SerializationExtensionMethods.GetNamespacePrefixMappings(this Microsoft.OData.Edm.IEdmModel model) -> System.Collections.Generic.IEnumerable>
@@ -1914,6 +1922,7 @@ static readonly Microsoft.OData.Edm.Vocabularies.V1.ValidationVocabularyModel.Na
static System.Collections.Generic.ReadOnlyListExtensions.FindLastIndex(this System.Collections.Generic.IReadOnlyList list, System.Func predicate) -> int
System.Collections.Generic.ReadOnlyListExtensions
virtual Microsoft.OData.Edm.Csdl.CsdlWriter.WriteCsdl() -> void
+virtual Microsoft.OData.Edm.Csdl.CsdlWriter.WriteCsdlAsync() -> System.Threading.Tasks.Task
virtual Microsoft.OData.Edm.EdmEntityContainer.AddActionImport(Microsoft.OData.Edm.IEdmAction action) -> Microsoft.OData.Edm.EdmActionImport
virtual Microsoft.OData.Edm.EdmEntityContainer.AddActionImport(string name, Microsoft.OData.Edm.IEdmAction action) -> Microsoft.OData.Edm.EdmActionImport
virtual Microsoft.OData.Edm.EdmEntityContainer.AddActionImport(string name, Microsoft.OData.Edm.IEdmAction action, Microsoft.OData.Edm.IEdmExpression entitySet) -> Microsoft.OData.Edm.EdmActionImport
diff --git a/src/Microsoft.OData.Edm/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/net8.0/PublicAPI.Unshipped.txt
index cf78498e4a..4b8c871c6f 100644
--- a/src/Microsoft.OData.Edm/PublicAPI/net8.0/PublicAPI.Unshipped.txt
+++ b/src/Microsoft.OData.Edm/PublicAPI/net8.0/PublicAPI.Unshipped.txt
@@ -1482,12 +1482,18 @@ static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdm
static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdmModel model, System.Text.Json.Utf8JsonWriter writer, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target, Microsoft.OData.Edm.Csdl.CsdlXmlWriterSettings writerSettings, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdl(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target, out System.Collections.Generic.IEnumerable errors) -> bool
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Text.Json.Utf8JsonWriter writer) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Text.Json.Utf8JsonWriter writer, Microsoft.OData.Edm.Csdl.CsdlJsonWriterSettings settings) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.CsdlWriter.TryWriteCsdlAsync(Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, Microsoft.OData.Edm.Csdl.CsdlTarget target, Microsoft.OData.Edm.Csdl.CsdlXmlWriterSettings writerSettings) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, Microsoft.OData.Edm.IEdmModel reference, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, System.Collections.Generic.IEnumerable references, bool includeDefaultVocabularies, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaReader.TryParse(System.Collections.Generic.IEnumerable readers, System.Collections.Generic.IEnumerable references, out Microsoft.OData.Edm.IEdmModel model, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchema(this Microsoft.OData.Edm.IEdmModel model, System.Func writerProvider, out System.Collections.Generic.IEnumerable errors) -> bool
static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchema(this Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer, out System.Collections.Generic.IEnumerable errors) -> bool
+static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchemaAsync(this Microsoft.OData.Edm.IEdmModel model, System.Func writerProvider) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
+static Microsoft.OData.Edm.Csdl.SchemaWriter.TryWriteSchemaAsync(this Microsoft.OData.Edm.IEdmModel model, System.Xml.XmlWriter writer) -> System.Threading.Tasks.Task<(bool, System.Collections.Generic.IEnumerable)>
static Microsoft.OData.Edm.Csdl.SerializationExtensionMethods.GetEdmxVersion(this Microsoft.OData.Edm.IEdmModel model) -> System.Version
static Microsoft.OData.Edm.Csdl.SerializationExtensionMethods.GetNamespaceAlias(this Microsoft.OData.Edm.IEdmModel model, string namespaceName) -> string
static Microsoft.OData.Edm.Csdl.SerializationExtensionMethods.GetNamespacePrefixMappings(this Microsoft.OData.Edm.IEdmModel model) -> System.Collections.Generic.IEnumerable>
@@ -1939,6 +1945,7 @@ static readonly Microsoft.OData.Edm.Vocabularies.V1.ValidationVocabularyModel.Na
static System.Collections.Generic.ReadOnlyListExtensions.FindLastIndex(this System.Collections.Generic.IReadOnlyList list, System.Func predicate) -> int
System.Collections.Generic.ReadOnlyListExtensions
virtual Microsoft.OData.Edm.Csdl.CsdlWriter.WriteCsdl() -> void
+virtual Microsoft.OData.Edm.Csdl.CsdlWriter.WriteCsdlAsync() -> System.Threading.Tasks.Task
virtual Microsoft.OData.Edm.EdmEntityContainer.AddActionImport(Microsoft.OData.Edm.IEdmAction action) -> Microsoft.OData.Edm.EdmActionImport
virtual Microsoft.OData.Edm.EdmEntityContainer.AddActionImport(string name, Microsoft.OData.Edm.IEdmAction action) -> Microsoft.OData.Edm.EdmActionImport
virtual Microsoft.OData.Edm.EdmEntityContainer.AddActionImport(string name, Microsoft.OData.Edm.IEdmAction action, Microsoft.OData.Edm.IEdmExpression entitySet) -> Microsoft.OData.Edm.EdmActionImport
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/ODataMessageWriterTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/ODataMessageWriterTests.cs
index 479c8de4eb..f469384214 100644
--- a/test/FunctionalTests/Microsoft.OData.Core.Tests/ODataMessageWriterTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/ODataMessageWriterTests.cs
@@ -806,6 +806,69 @@ public async Task WriteMetadataDocumentAsync_WorksForJsonCsdl()
}
}", payload);
}
+
+ [Fact]
+ public async Task WriteMetadataDocumentAsync_WorksForJsonCsdl_WithNoSynchronousIOSupport()
+ {
+ // Arrange
+ IEdmModel edmModel = GetEdmModel();
+
+ // Act - JSON
+ string payload = await this.WriteAndGetPayloadAsync(edmModel, "application/json", async omWriter =>
+ {
+ await omWriter.WriteMetadataDocumentAsync();
+ });
+
+ // Assert
+ Assert.Equal(@"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Container"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""Name"": {}
+ },
+ ""Container"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Customers"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Customer""
+ }
+ }
+ }
+}", payload);
+ }
+
+ [Fact]
+ public async Task WriteMetadataDocumentPayload_MustEqual_WriteMetadataDocumentAsyncPayload_ForJsonCsdl()
+ {
+ // Arrange
+ IEdmModel edmModel = GetEdmModel();
+
+ // Act
+ var contentType = "application/json";
+
+ // Json CSDL generated synchronously
+ string syncPayload = this.WriteAndGetPayload(edmModel, contentType, omWriter =>
+ {
+ omWriter.WriteMetadataDocument();
+ });
+
+ // Json CSDL generated asynchronously
+ string asyncPayload = await this.WriteAndGetPayloadAsync(edmModel, contentType, async omWriter =>
+ {
+ await omWriter.WriteMetadataDocumentAsync();
+ });
+
+ // Assert
+ Assert.Equal(syncPayload, asyncPayload);
+ }
#endif
[Fact]
@@ -851,6 +914,63 @@ public async Task WriteMetadataDocumentAsync_WorksForXmlCsdl()
"", payload);
}
+ [Fact]
+ public async Task WriteMetadataDocumentAsync_WorksForXmlCsdl_WithNoSynchronousIOSupport()
+ {
+ // Arrange
+ IEdmModel edmModel = GetEdmModel();
+
+ // Act - XML
+ string payload = await this.WriteAndGetPayloadAsync(edmModel, "application/xml", async omWriter =>
+ {
+ await omWriter.WriteMetadataDocumentAsync();
+ });
+
+ // Assert - XML
+ Assert.Equal("" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "", payload);
+ }
+
+ [Fact]
+ public async Task WriteMetadataDocumentPayload_MustEqual_WriteMetadataDocumentAsyncPayload_ForXmlCsdl()
+ {
+ // Arrange
+ IEdmModel edmModel = GetEdmModel();
+
+ // Act
+ var contentType = "application/xml";
+
+ // XML CSDL generated synchronously
+ string syncPayload = this.WriteAndGetPayload(edmModel, contentType, omWriter =>
+ {
+ omWriter.WriteMetadataDocument();
+ });
+
+ // XML CSDL generated asynchronously
+ string asyncPayload = await this.WriteAndGetPayloadAsync(edmModel, contentType, async omWriter =>
+ {
+ await omWriter.WriteMetadataDocumentAsync();
+ });
+
+ // Assert
+ Assert.Equal(asyncPayload, syncPayload);
+ }
+
#region "DisposeAsync"
#if NETCOREAPP
@@ -939,6 +1059,32 @@ public async Task DisposeAsync_Should_Dispose_Stream_Asynchronously_AfterWriting
Assert.True(stream.Disposed);
}
+ [Fact]
+ public async Task DisposeAsync_Should_Dispose_Stream_Asynchronously_AfterWritingJsonMetadata_NoSyncSupport()
+ {
+ AsyncStream stream = new AsyncStream(new MemoryStream());
+ InMemoryMessage message = new InMemoryMessage()
+ {
+ Stream = stream
+ };
+
+ IEdmModel edmModel = GetEdmModel();
+
+ ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings();
+ writerSettings.EnableMessageStreamDisposal = true;
+ writerSettings.BaseUri = new Uri("http://www.example.com/");
+ writerSettings.SetServiceDocumentUri(new Uri("http://www.example.com/"));
+ message.SetHeader("Content-Type", "application/json");
+
+ var msgWriter = new ODataMessageWriter((IODataResponseMessageAsync)message, writerSettings, edmModel);
+
+ await msgWriter.WriteMetadataDocumentAsync();
+
+ await msgWriter.DisposeAsync();
+
+ Assert.True(stream.Disposed);
+ }
+
[Fact]
public async Task DisposeAsync_Should_Dispose_Stream_Asynchronously_AfterWritingXmlMetadata()
{
@@ -976,6 +1122,32 @@ public async Task DisposeAsync_Should_Dispose_Stream_Asynchronously_AfterWriting
Assert.True(stream.Disposed);
}
+ [Fact]
+ public async Task DisposeAsync_Should_Dispose_Stream_Asynchronously_AfterWritingXmlMetadata_NoSyncSupport()
+ {
+ AsyncStream stream = new AsyncStream(new MemoryStream());
+ InMemoryMessage message = new InMemoryMessage()
+ {
+ Stream = stream
+ };
+
+ IEdmModel edmModel = GetEdmModel();
+
+ ODataMessageWriterSettings writerSettings = new ODataMessageWriterSettings();
+ writerSettings.EnableMessageStreamDisposal = true;
+ writerSettings.BaseUri = new Uri("http://www.example.com/");
+ writerSettings.SetServiceDocumentUri(new Uri("http://www.example.com/"));
+ message.SetHeader("Content-Type", "application/xml");
+
+ var msgWriter = new ODataMessageWriter((IODataResponseMessageAsync)message, writerSettings, edmModel);
+
+ await msgWriter.WriteMetadataDocumentAsync();
+
+ await msgWriter.DisposeAsync();
+
+ Assert.True(stream.Disposed);
+ }
+
[Fact]
public async void DisposeAsync_Should_Dispose_Stream_Asynchronously_AfterWritingRawValue()
{
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Roundtrip/ContextUrlWriterReaderTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Roundtrip/ContextUrlWriterReaderTests.Async.cs
new file mode 100644
index 0000000000..f4e9986755
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Roundtrip/ContextUrlWriterReaderTests.Async.cs
@@ -0,0 +1,334 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm;
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Tests;
+using Microsoft.OData.UriParser;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using Xunit;
+
+namespace Microsoft.OData.Core.Tests.ScenarioTests.Roundtrip
+{
+ public partial class ContextUrlWriterReaderTests
+ {
+ private static readonly ODataVersion[] Versions = new ODataVersion[] { ODataVersion.V4, ODataVersion.V401 };
+
+ private const string TestNameSpace = "Microsoft.OData.Tests.ScenarioTests.Roundtrip";
+ private const string TestContainerName = "InMemoryEntities";
+ private const string TestBaseUri = "http://www.example.com/";
+
+ private EdmModel model;
+
+ private EdmEntityType personType;
+ private EdmEntityType employeeType;
+ private EdmEntityType companyType;
+ private EdmEntityType workingGroupType;
+ private EdmEntityType peopleWorkingGroupsType;
+ private EdmEntityType productType;
+ private EdmEntityType productBookType;
+ private EdmEntityType productCdType;
+ private EdmEntityType locationType;
+ private EdmComplexType addressType;
+ private EdmEnumType accessLevelType;
+
+ private EdmEntitySet employeeSet;
+ private EdmEntitySet companySet;
+ private EdmEntitySet peopleSet;
+ private EdmEntitySet workingGroupsSet;
+ private EdmSingleton peopleWorkingGroupsSingleton;
+
+ private Uri testServiceRootUri;
+
+ protected readonly ODataFormat[] mimeTypes = new ODataFormat[]
+ {
+ ODataFormat.Json
+ };
+
+ public ContextUrlWriterReaderTests()
+ {
+ this.testServiceRootUri = new Uri(TestBaseUri);
+
+ this.model = new EdmModel();
+
+ var defaultContainer = new EdmEntityContainer(TestNameSpace, TestContainerName);
+ this.model.AddElement(defaultContainer);
+
+ productType = new EdmEntityType(TestNameSpace, "Product");
+ var productIdProperty = new EdmStructuralProperty(productType, "PersonId", EdmCoreModel.Instance.GetInt32(false));
+ productType.AddProperty(productIdProperty);
+ productType.AddKeys(new IEdmStructuralProperty[] { productIdProperty });
+ productType.AddProperty(new EdmStructuralProperty(productType, "Name", EdmCoreModel.Instance.GetString(false)));
+ this.model.AddElement(productType);
+
+ productBookType = new EdmEntityType(TestNameSpace, "ProductBook", productType);
+ productBookType.AddProperty(new EdmStructuralProperty(productBookType, "Author", EdmCoreModel.Instance.GetString(false)));
+ this.model.AddElement(productBookType);
+
+ productCdType = new EdmEntityType(TestNameSpace, "ProductCd", productType);
+ productCdType.AddProperty(new EdmStructuralProperty(productCdType, "Artist", EdmCoreModel.Instance.GetString(false)));
+ this.model.AddElement(productCdType);
+
+ addressType = new EdmComplexType(TestNameSpace, "Address");
+ addressType.AddProperty(new EdmStructuralProperty(addressType, "Street", EdmCoreModel.Instance.GetString(false)));
+ addressType.AddProperty(new EdmStructuralProperty(addressType, "City", EdmCoreModel.Instance.GetString(false)));
+ this.model.AddElement(addressType);
+
+ var factoryAddressType = new EdmComplexType(TestNameSpace, "FactoryAddress", addressType, false);
+ factoryAddressType.AddProperty(new EdmStructuralProperty(factoryAddressType, "FactoryType", EdmCoreModel.Instance.GetString(false)));
+ factoryAddressType.AddProperty(new EdmStructuralProperty(factoryAddressType, "FactoryPhoneNumbers", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(false)))));
+ this.model.AddElement(factoryAddressType);
+
+ var manufactoryType = new EdmComplexType(TestNameSpace, "Manufactory");
+ manufactoryType.AddProperty(new EdmStructuralProperty(manufactoryType, "ManufactoryAddress", new EdmComplexTypeReference(addressType, true)));
+ manufactoryType.AddProperty(new EdmStructuralProperty(manufactoryType, "Name", EdmCoreModel.Instance.GetString(false)));
+ manufactoryType.AddProperty(new EdmStructuralProperty(manufactoryType, "Numbers", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(false)))));
+ this.model.AddElement(manufactoryType);
+
+ var companyDivisionType = new EdmComplexType(TestNameSpace, "Division");
+ companyDivisionType.AddProperty(new EdmStructuralProperty(companyDivisionType, "Name", EdmCoreModel.Instance.GetString(false)));
+ companyDivisionType.AddProperty(new EdmStructuralProperty(companyDivisionType, "Manufactory", new EdmComplexTypeReference(manufactoryType, true)));
+ this.model.AddElement(companyDivisionType);
+
+ accessLevelType = new EdmEnumType(TestNameSpace, "AccessLevel", isFlags: true);
+ accessLevelType.AddMember("None", new EdmEnumMemberValue(0));
+ accessLevelType.AddMember("Read", new EdmEnumMemberValue(1));
+ accessLevelType.AddMember("Write", new EdmEnumMemberValue(2));
+ accessLevelType.AddMember("Execute", new EdmEnumMemberValue(4));
+ accessLevelType.AddMember("ReadWrite", new EdmEnumMemberValue(3));
+ this.model.AddElement(accessLevelType);
+
+ personType = new EdmEntityType(TestNameSpace, "Person", null, false, /*IsOpen*/ true);
+ var personIdProperty = new EdmStructuralProperty(personType, "PersonId", EdmCoreModel.Instance.GetInt32(false));
+ personType.AddProperty(personIdProperty);
+ personType.AddKeys(new IEdmStructuralProperty[] { personIdProperty });
+ personType.AddProperty(new EdmStructuralProperty(personType, "Name", EdmCoreModel.Instance.GetString(false)));
+ personType.AddProperty(new EdmStructuralProperty(personType, "Age", EdmCoreModel.Instance.GetInt32(false)));
+ personType.AddProperty(new EdmStructuralProperty(personType, "HomeAddress", new EdmComplexTypeReference(addressType, true)));
+ personType.AddProperty(new EdmStructuralProperty(personType, "PhoneNumbers", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(false)))));
+ personType.AddProperty(new EdmStructuralProperty(personType, "Addresses", new EdmCollectionTypeReference(new EdmCollectionType(new EdmComplexTypeReference(addressType, true)))));
+ personType.AddProperty(new EdmStructuralProperty(personType, "UserAccess", new EdmEnumTypeReference(accessLevelType, true)));
+ personType.AddProperty(new EdmStructuralProperty(personType, "UserAccesses", new EdmCollectionTypeReference(new EdmCollectionType(new EdmEnumTypeReference(accessLevelType, true)))));
+
+ this.model.AddElement(personType);
+
+ employeeType = new EdmEntityType(TestNameSpace, "Employee", personType, false, true);
+ employeeType.AddProperty(new EdmStructuralProperty(employeeType, "DateHired", EdmCoreModel.Instance.GetDateTimeOffset(true)));
+ employeeType.AddProperty(new EdmStructuralProperty(employeeType, "WorkNumbers", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetString(false)))));
+ this.model.AddElement(employeeType);
+
+ companyType = new EdmEntityType(TestNameSpace, "Company");
+ var companyIdProperty = new EdmStructuralProperty(companyType, "CompanyId", EdmCoreModel.Instance.GetInt32(false));
+ companyType.AddProperty(companyIdProperty);
+ companyType.AddKeys(new IEdmStructuralProperty[] { companyIdProperty });
+ companyType.AddProperty(new EdmStructuralProperty(companyType, "Name", EdmCoreModel.Instance.GetString(false)));
+ companyType.AddProperty(new EdmStructuralProperty(companyType, "Division", new EdmComplexTypeReference(companyDivisionType, true)));
+ this.model.AddElement(companyType);
+
+ locationType = new EdmEntityType(TestNameSpace, "Location");
+ var locationId = new EdmStructuralProperty(locationType, "LocationId", EdmCoreModel.Instance.GetInt32(false));
+ locationType.AddProperty(locationId);
+ locationType.AddKeys(new IEdmStructuralProperty[] { locationId });
+ locationType.AddProperty(new EdmStructuralProperty(locationType, "Name", EdmCoreModel.Instance.GetString(false)));
+ this.model.AddElement(locationType);
+
+ workingGroupType = new EdmEntityType(TestNameSpace, "WorkingGroup");
+ var workingGroupIdProperty = new EdmStructuralProperty(workingGroupType, "WorkingGroupId", EdmCoreModel.Instance.GetInt32(false));
+ workingGroupType.AddProperty(workingGroupIdProperty);
+ workingGroupType.AddKeys(new IEdmStructuralProperty[] { workingGroupIdProperty });
+ workingGroupType.AddProperty(new EdmStructuralProperty(workingGroupType, "Name", EdmCoreModel.Instance.GetString(false)));
+ this.model.AddElement(workingGroupType);
+
+ peopleWorkingGroupsType = new EdmEntityType(TestNameSpace, "PeopleWorkingGroupsRoot");
+ this.model.AddElement(peopleWorkingGroupsType);
+
+ this.peopleSet = new EdmEntitySet(defaultContainer, "People", personType);
+ this.companySet = new EdmEntitySet(defaultContainer, "Companys", companyType);
+ this.employeeSet = new EdmEntitySet(defaultContainer, "Employees", employeeType);
+ this.workingGroupsSet = new EdmEntitySet(defaultContainer, "WorkingGroups", workingGroupType);
+ defaultContainer.AddElement(this.employeeSet);
+ defaultContainer.AddElement(this.peopleSet);
+ defaultContainer.AddElement(this.companySet);
+ defaultContainer.AddElement(this.workingGroupsSet);
+
+ this.peopleWorkingGroupsSingleton = new EdmSingleton(defaultContainer, "PeopleWorkingGroups", peopleWorkingGroupsType);
+ defaultContainer.AddElement(this.peopleWorkingGroupsSingleton);
+
+ var associatedCompanyNavigation = employeeType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "AssociatedCompany",
+ Target = companyType,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+
+ employeeSet.AddNavigationTarget(associatedCompanyNavigation, companySet);
+
+ var peopleNavigation = peopleWorkingGroupsType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "People",
+ Target = personType,
+ TargetMultiplicity = EdmMultiplicity.Many,
+ ContainsTarget = true,
+ });
+
+ var workingGroupNavigation = peopleWorkingGroupsType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "WorkingGroups",
+ Target = workingGroupType,
+ TargetMultiplicity = EdmMultiplicity.Many,
+ ContainsTarget = true,
+ });
+
+ var associatedWorkingGroupsNavigation = personType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "AssociatedWorkingGroups",
+ Target = workingGroupType,
+ TargetMultiplicity = EdmMultiplicity.Many
+ });
+
+ var locationNavigation = companyType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "Locations",
+ Target = locationType,
+ TargetMultiplicity = EdmMultiplicity.Many,
+ ContainsTarget = true,
+ });
+
+ var propertyManagerNavigation = locationType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "PropertyManager",
+ Target = personType,
+ TargetMultiplicity = EdmMultiplicity.One,
+ });
+
+ var employeesNavigation = locationType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "Employees",
+ Target = personType,
+ TargetMultiplicity = EdmMultiplicity.Many,
+ });
+
+ peopleWorkingGroupsSingleton.AddNavigationTarget(associatedWorkingGroupsNavigation, peopleWorkingGroupsSingleton);
+
+ var locationNavSource = companySet.FindNavigationTarget(locationNavigation) as EdmNavigationSource;
+ locationNavSource.AddNavigationTarget(propertyManagerNavigation, peopleSet);
+ locationNavSource.AddNavigationTarget(employeesNavigation, peopleSet);
+ }
+
+ [Fact]
+ public async Task ExpandedEntity_Async()
+ {
+ ODataResource entry = new ODataResource()
+ {
+ TypeName = TestNameSpace + ".Employee",
+ Properties = new[]
+ {
+ new ODataProperty {Name = "PersonId", Value = 1},
+ new ODataProperty {Name = "Name", Value = "Test1"},
+ new ODataProperty {Name = "Age", Value = 20},
+ new ODataProperty {Name = "HomeAddress", Value = null},
+ new ODataProperty {Name = "DateHired", Value = null},
+ },
+ };
+
+ StringBuilder stringBuilder = new StringBuilder();
+ StringWriter stringWriter = new StringWriter(stringBuilder);
+
+ using (var writer = XmlWriter.Create(stringWriter, new XmlWriterSettings() { Async = true }))
+ {
+ var (success, errors) = await CsdlWriter.TryWriteCsdlAsync(this.model, writer, CsdlTarget.OData).ConfigureAwait(false);
+ if (!success)
+ {
+ Assert.True(false, "Serialization was unsuccessful");
+ }
+ }
+
+ string modelAsString = stringBuilder.ToString();
+
+ foreach (ODataFormat mimeType in mimeTypes)
+ {
+ string payload, contentType;
+ this.WriteAndValidateContextUri(mimeType, model, omWriter =>
+ {
+ var selectExpandClause = new ODataQueryOptionParser(this.model, this.employeeType, this.employeeSet, new Dictionary { { "$expand", "AssociatedCompany" }, { "$select", "AssociatedCompany" } }).ParseSelectAndExpand();
+
+ omWriter.Settings.ODataUri = new ODataUri()
+ {
+ ServiceRoot = this.testServiceRootUri,
+ SelectAndExpand = selectExpandClause
+ };
+ var writer = omWriter.CreateODataResourceWriter(this.employeeSet, this.employeeType);
+ writer.WriteStart(entry);
+ writer.WriteEnd();
+ },
+ string.Format("\"{0}$metadata#Employees(AssociatedCompany,AssociatedCompany())/$entity\"", TestBaseUri),
+ out payload, out contentType);
+
+ this.ReadPayload(payload, contentType, model, omReader =>
+ {
+ var reader = omReader.CreateODataResourceReader(this.employeeSet, this.employeeType);
+ while (reader.Read()) { }
+ Assert.Equal(ODataReaderState.Completed, reader.State);
+ });
+ }
+ }
+
+ private void WriteAndValidateContextUri(ODataFormat odataFormat, EdmModel edmModel, Action test, string expectedUri, out string payload, out string contentType)
+ {
+ var writerSettings = new ODataMessageWriterSettings();
+ WriteAndValidateContextUri(odataFormat, model, writerSettings, test, expectedUri, out payload, out contentType);
+ }
+
+ private void WriteAndValidateContextUri(ODataFormat odataFormat, EdmModel edmModel, ODataMessageWriterSettings writerSettings, Action test, string expectedUri, out string payload, out string contentType)
+ {
+ var message = new InMemoryMessage() { Stream = new MemoryStream() };
+
+ writerSettings.EnableMessageStreamDisposal = false;
+ writerSettings.BaseUri = new Uri(TestBaseUri);
+ writerSettings.SetServiceDocumentUri(new Uri(TestBaseUri));
+ writerSettings.SetContentType(odataFormat);
+
+ using (var msgWriter = new ODataMessageWriter((IODataResponseMessage)message, writerSettings, edmModel))
+ {
+ test(msgWriter);
+ }
+
+ message.Stream.Seek(0, SeekOrigin.Begin);
+ using (StreamReader reader = new StreamReader(message.Stream))
+ {
+ contentType = message.GetHeader("Content-Type");
+ payload = reader.ReadToEnd();
+ Assert.Contains(expectedUri, payload);
+ }
+ }
+
+ private void ReadPayload(string payload, string contentType, EdmModel edmModel, Action test, bool readingResponse = true, ODataVersion version = ODataVersion.V4)
+ {
+ var message = new InMemoryMessage() { Stream = new MemoryStream(Encoding.UTF8.GetBytes(payload)) };
+ message.SetHeader("Content-Type", contentType);
+
+ ODataMessageReaderSettings readerSettings = new ODataMessageReaderSettings()
+ {
+ BaseUri = new Uri(TestBaseUri + "$metadata"),
+ EnableMessageStreamDisposal = true,
+ Version = version,
+ };
+
+ using (var msgReader =
+ readingResponse
+ ? new ODataMessageReader((IODataResponseMessage)message, readerSettings, edmModel)
+ : new ODataMessageReader((IODataRequestMessage)message, readerSettings, edmModel))
+ {
+ test(msgReader);
+ }
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Roundtrip/ContextUrlWriterReaderTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Roundtrip/ContextUrlWriterReaderTests.cs
index f6106002a3..476dd7115a 100644
--- a/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Roundtrip/ContextUrlWriterReaderTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/Roundtrip/ContextUrlWriterReaderTests.cs
@@ -58,7 +58,7 @@ public enum AccessLevel
ReadWrite = 3
}
- public class ContextUrlWriterReaderTests
+ public partial class ContextUrlWriterReaderTests
{
private static readonly ODataVersion[] Versions = new ODataVersion[] { ODataVersion.V4, ODataVersion.V401 };
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderTests.Async.cs
new file mode 100644
index 0000000000..d6dc4473f8
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderTests.Async.cs
@@ -0,0 +1,327 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Validation;
+using Microsoft.OData.Edm.Vocabularies;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Linq;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Csdl
+{
+ public partial class CsdlReaderTests
+ {
+ [InlineData("4.0")]
+ [InlineData("4.01")]
+ [Theory]
+ public async Task ValidateNavigationPropertyBindingPathEndingInTypeCast_Async(string odataVersion)
+ {
+ var entitySetWithNavProperties =
+ "" +
+ "" +
+ "" +
+ "";
+ var entitySetWithoutNavProperties =
+ "";
+ var csdl =
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "{1}" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+ var model = CsdlReader.Parse(XElement.Parse(String.Format(csdl, odataVersion, entitySetWithNavProperties)).CreateReader());
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+ Assert.Empty(errors);
+
+ var setA = model.FindDeclaredNavigationSource("SetA");
+ Assert.NotNull(setA);
+
+ var navProp = setA.EntityType.FindProperty("Nav") as IEdmNavigationProperty;
+ Assert.NotNull(navProp);
+ Assert.Equal(2, setA.NavigationPropertyBindings.Count());
+
+ // NavPropBinding for for EntityX1 should be SetX1
+ var X1NavPropBinding = setA.NavigationPropertyBindings.FirstOrDefault(b => b.Path.PathSegments.Last() == "NS.EntityX1");
+ Assert.NotNull(X1NavPropBinding);
+ var setX1 = model.FindDeclaredNavigationSource("SetX1");
+ Assert.Same(setX1, X1NavPropBinding.Target);
+ Assert.Same(setX1, setA.FindNavigationTarget(navProp, new EdmPathExpression("Nav/NS.EntityX1")));
+
+ // NavPropBinding for EntityX2 should be SetX2
+ var X2NavPropBinding = setA.NavigationPropertyBindings.FirstOrDefault(b => b.Path.PathSegments.Last() == "NS.EntityX2");
+ Assert.NotNull(X2NavPropBinding);
+ var setX2 = model.FindDeclaredNavigationSource("SetX2");
+ Assert.Same(setX2, X2NavPropBinding.Target);
+ Assert.Same(setX2, setA.FindNavigationTarget(navProp, new EdmPathExpression("Nav/NS.EntityX2")));
+
+ // Navigation Property without path should return UnknownEntitySet
+ Assert.True(setA.FindNavigationTarget(navProp) is EdmUnknownEntitySet);
+
+ // Verify writing model
+ model.SetEdmVersion(Version.Parse(odataVersion));
+ await VerifyXmlModelAsync(model, odataVersion == "4.0" ? entitySetWithoutNavProperties : entitySetWithNavProperties).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ReadAnnotationWithoutSpecifiedValueAndUseDefault_Async()
+ {
+ var csdl
+ = "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" + // does not specify value
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+ // Parse into CSDL
+
+ IEdmModel model;
+ using (XmlReader xr = XElement.Parse(csdl).CreateReader())
+ {
+ model = CsdlReader.Parse(xr);
+ }
+ IEdmTerm defaultTerm = model.FindTerm("NS.MyDefaultTerm");
+ Assert.Equal("This is a test", defaultTerm.DefaultValue);
+ IEdmVocabularyAnnotation[] annotations = model.VocabularyAnnotations.ToArray();
+ Assert.Equal(2, annotations.Length);
+
+ IEdmVocabularyAnnotation annotationWithSpecifiedValue = Assert.IsAssignableFrom(annotations[0]);
+ Assert.NotNull(annotationWithSpecifiedValue.Value);
+ Assert.IsAssignableFrom(annotationWithSpecifiedValue.Value);
+
+ IEdmVocabularyAnnotation annotationWithDefaultValue = Assert.IsAssignableFrom(annotations[1]);
+ Assert.NotNull(annotationWithDefaultValue.Value);
+ IEdmStringConstantExpression stringConstantExp = Assert.IsAssignableFrom(annotationWithDefaultValue.Value);
+ Assert.Equal("This is a test", stringConstantExp.Value);
+
+ // Validate model
+ IEnumerable errors;
+ bool validated = model.Validate(out errors);
+ Assert.True(validated);
+
+ // Act & Assert for Reserialized XML
+ await CsdlWriterTests.WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" + // no longer has value
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ReadWriteAnnotationUsingDefaultValueWithContinuity_Async()
+ {
+ var csdl
+ = "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" + // does not specify value
+ "" + // specifies default
+ "" + // specifies non-default
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+ // Parse into CSDL
+ IEdmModel model;
+ using (XmlReader xr = XElement.Parse(csdl).CreateReader())
+ {
+ model = CsdlReader.Parse(xr);
+ }
+ IEdmTerm defaultTerm = model.FindTerm("NS.MyDefaultBoolTerm1");
+ Assert.True(bool.Parse(defaultTerm.DefaultValue));
+ IEdmVocabularyAnnotation[] annotations = model.VocabularyAnnotations.ToArray();
+ Assert.Equal(3, annotations.Length);
+ IEdmVocabularyAnnotation annotation1 = Assert.IsAssignableFrom(annotations[0]);
+ IEdmBooleanConstantExpression annotationValue1 = Assert.IsAssignableFrom(annotation1.Value);
+ Assert.True(annotationValue1.Value);
+
+ IEdmVocabularyAnnotation annotation2 = Assert.IsAssignableFrom(annotations[1]);
+ IEdmBooleanConstantExpression annotationValue2 = Assert.IsAssignableFrom(annotation2.Value);
+ Assert.True(annotationValue2.Value);
+
+ IEdmVocabularyAnnotation annotation3 = Assert.IsAssignableFrom(annotations[2]);
+ IEdmBooleanConstantExpression annotationValue3 = Assert.IsAssignableFrom(annotation3.Value);
+ Assert.False(annotationValue3.Value);
+
+ // Validate model
+ IEnumerable errors;
+ bool validated = model.Validate(out errors);
+ Assert.True(validated);
+
+ // Act & Assert for Reserialized XML
+ await CsdlWriterTests.WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" + // does not specify value
+ "" + // for back compatiable, write the default value again.
+ "" + // specifies non-default
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ReadAnnotationWithoutSpecifiedValueAndUsePrimitiveDefaultValues_Async()
+ {
+ CsdlXmlWriterSettings writerSettings = new CsdlXmlWriterSettings
+ {
+ LibraryCompatibility = EdmLibraryCompatibility.UseLegacyVariableCasing
+ };
+
+ var csdl = "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+ // Parse into CSDL
+ IEdmModel model;
+ using (XmlReader xr = XElement.Parse(csdl).CreateReader())
+ {
+ model = CsdlReader.Parse(xr);
+ }
+ IEdmVocabularyAnnotation[] annotations = model.VocabularyAnnotations.ToArray();
+ Assert.Equal(13, annotations.Length);
+ for (int i = 0; i < annotations.Length; i++)
+ {
+ IEdmVocabularyAnnotation annotationWithDefaultValue = Assert.IsAssignableFrom(annotations[i]);
+ Assert.NotNull(annotationWithDefaultValue.Value);
+ }
+
+ // Validate model
+ IEnumerable errors;
+ bool validated = model.Validate(out errors);
+ Assert.True(validated);
+
+ // Act & Assert for Reserialized XML
+ await CsdlWriterTests.WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "", writerSettings).ConfigureAwait(false);
+ }
+
+ static async Task VerifyXmlModelAsync(IEdmModel model, string csdl)
+ {
+ var stream = new MemoryStream();
+ XmlWriter xmlWriter = XmlWriter.Create(stream, new XmlWriterSettings() { Async = true });
+ var (success, errors) = await CsdlWriter.TryWriteCsdlAsync(model, xmlWriter, CsdlTarget.OData).ConfigureAwait(false);
+ Assert.True(success);
+ Assert.Empty(errors);
+ stream.Position = 0;
+ Assert.Contains(csdl, new StreamReader(stream).ReadToEnd());
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.Async.cs
new file mode 100644
index 0000000000..e9c79251d1
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.Async.cs
@@ -0,0 +1,3067 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+#if NETCOREAPP3_1
+using System.Text.Encodings.Web;
+using System.Text.Json;
+#endif
+using System.Xml;
+using System.Xml.Linq;
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Validation;
+using Microsoft.OData.Edm.Vocabularies;
+using Microsoft.OData.Edm.Vocabularies.V1;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Csdl
+{
+ public partial class CsdlWriterTests
+ {
+ #region Reference
+
+ [Fact]
+ public async Task ShouldWriteEdmReference_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmReference reference1 = new EdmReference(new Uri("https://example.com/Org.OData.Authorization.V1.xml"));
+ EdmInclude authInclude = new EdmInclude("Auth", "Org.OData.Authorization.V1");
+ reference1.AddInclude(authInclude);
+ reference1.AddIncludeAnnotations(new EdmIncludeAnnotations("org.example.validation", null, null));
+ reference1.AddIncludeAnnotations(new EdmIncludeAnnotations("org.example.display", "Tablet", null));
+
+ EdmReference reference2 = new EdmReference(new Uri("https://example.com/Org.OData.Core.V1.xml"));
+ reference2.AddInclude(new EdmInclude("Core", "Org.OData.Core.V1"));
+ reference2.AddIncludeAnnotations(new EdmIncludeAnnotations("org.example.hcm", null, "com.example.Sales"));
+ reference2.AddIncludeAnnotations(new EdmIncludeAnnotations("org.example.hcm", "Tablet", "com.example.Person"));
+ model.SetEdmReferences(new[] { reference1, reference2 });
+
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(authInclude,
+ CoreVocabularyModel.LongDescriptionTerm, new EdmStringConstant("Include Description."));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ annotation = new EdmVocabularyAnnotation(reference2,
+ CoreVocabularyModel.LongDescriptionTerm, new EdmStringConstant("EdmReference Description."));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$Reference"": {
+ ""https://example.com/Org.OData.Authorization.V1.xml"": {
+ ""$Include"": [
+ {
+ ""$Namespace"": ""Org.OData.Authorization.V1"",
+ ""$Alias"": ""Auth"",
+ ""@Core.LongDescription"": ""Include Description.""
+ }
+ ],
+ ""$IncludeAnnotations"": [
+ {
+ ""$TermNamespace"": ""org.example.validation""
+ },
+ {
+ ""$TermNamespace"": ""org.example.display"",
+ ""$Qualifier"": ""Tablet""
+ }
+ ]
+ },
+ ""https://example.com/Org.OData.Core.V1.xml"": {
+ ""$Include"": [
+ {
+ ""$Namespace"": ""Org.OData.Core.V1"",
+ ""$Alias"": ""Core""
+ }
+ ],
+ ""$IncludeAnnotations"": [
+ {
+ ""$TermNamespace"": ""org.example.hcm"",
+ ""$TargetNamespace"": ""com.example.Sales""
+ },
+ {
+ ""$TermNamespace"": ""org.example.hcm"",
+ ""$Qualifier"": ""Tablet"",
+ ""$TargetNamespace"": ""com.example.Person""
+ }
+ ],
+ ""@Core.LongDescription"": ""EdmReference Description.""
+ }
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ #region Annotation - Computed, OptimisticConcurrency
+
+ [Fact]
+ public async Task VerifyAnnotationComputedConcurrency_Async()
+ {
+ // Arrange
+ var model = new EdmModel();
+ var entity = new EdmEntityType("NS1", "Product");
+ var entityId = entity.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false));
+ entity.AddKeys(entityId);
+ EdmStructuralProperty name1 = entity.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false));
+ EdmStructuralProperty timeVer = entity.AddStructuralProperty("UpdatedTime", EdmCoreModel.Instance.GetDate(false));
+ model.AddElement(entity);
+
+ SetComputedAnnotation(model, entityId); // semantic meaning is V3's 'Identity' for Key property
+ SetComputedAnnotation(model, timeVer); // semantic meaning is V3's 'Computed' for non-key property
+
+ var entityContainer = new EdmEntityContainer("NS1", "Container");
+ model.AddElement(entityContainer);
+ EdmEntitySet set1 = new EdmEntitySet(entityContainer, "Products", entity);
+ model.SetOptimisticConcurrencyAnnotation(set1, new IEdmStructuralProperty[] { entityId, timeVer });
+ entityContainer.AddElement(set1);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "Id" +
+ "UpdatedTime" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS1.Container"",
+ ""NS1"": {
+ ""Product"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32"",
+ ""@Org.OData.Core.V1.Computed"": true
+ },
+ ""Name"": {},
+ ""UpdatedTime"": {
+ ""$Type"": ""Edm.Date"",
+ ""@Org.OData.Core.V1.Computed"": true
+ }
+ },
+ ""Container"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Products"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS1.Product"",
+ ""@Org.OData.Core.V1.OptimisticConcurrency"": [
+ ""Id"",
+ ""UpdatedTime""
+ ]
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task WriteNavigationPropertyInComplexType_Async()
+ {
+ // Arrange
+ var model = new EdmModel();
+
+ var person = new EdmEntityType("DefaultNs", "Person");
+ var entityId = person.AddStructuralProperty("UserName", EdmCoreModel.Instance.GetString(false));
+ person.AddKeys(entityId);
+
+ var city = new EdmEntityType("DefaultNs", "City");
+ var cityId = city.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false));
+ city.AddKeys(cityId);
+
+ var countryOrRegion = new EdmEntityType("DefaultNs", "CountryOrRegion");
+ var countryId = countryOrRegion.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false));
+ countryOrRegion.AddKeys(countryId);
+
+ var complex = new EdmComplexType("DefaultNs", "Address");
+ complex.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false));
+ var navP = complex.AddUnidirectionalNavigation(
+ new EdmNavigationPropertyInfo()
+ {
+ Name = "City",
+ Target = city,
+ TargetMultiplicity = EdmMultiplicity.One,
+ });
+
+ var derivedComplex = new EdmComplexType("DefaultNs", "WorkAddress", complex);
+ var navP2 = derivedComplex.AddUnidirectionalNavigation(
+ new EdmNavigationPropertyInfo()
+ {
+ Name = "CountryOrRegion",
+ Target = countryOrRegion,
+ TargetMultiplicity = EdmMultiplicity.One,
+ });
+
+ person.AddStructuralProperty("HomeAddress", new EdmComplexTypeReference(complex, false));
+ person.AddStructuralProperty("WorkAddress", new EdmComplexTypeReference(complex, false));
+ person.AddStructuralProperty("Addresses", new EdmCollectionTypeReference(new EdmCollectionType(new EdmComplexTypeReference(complex, false))));
+
+ model.AddElement(person);
+ model.AddElement(city);
+ model.AddElement(countryOrRegion);
+ model.AddElement(complex);
+ model.AddElement(derivedComplex);
+
+ var entityContainer = new EdmEntityContainer("DefaultNs", "Container");
+ model.AddElement(entityContainer);
+ EdmEntitySet people = new EdmEntitySet(entityContainer, "People", person);
+ EdmEntitySet cities = new EdmEntitySet(entityContainer, "City", city);
+ EdmEntitySet countriesOrRegions = new EdmEntitySet(entityContainer, "CountryOrRegion", countryOrRegion);
+ people.AddNavigationTarget(navP, cities, new EdmPathExpression("HomeAddress/City"));
+ people.AddNavigationTarget(navP, cities, new EdmPathExpression("Addresses/City"));
+ people.AddNavigationTarget(navP2, countriesOrRegions, new EdmPathExpression("WorkAddress/DefaultNs.WorkAddress/CountryOrRegion"));
+ entityContainer.AddElement(people);
+ entityContainer.AddElement(cities);
+ entityContainer.AddElement(countriesOrRegions);
+
+ IEnumerable actualErrors = null;
+ model.Validate(out actualErrors);
+ Assert.Empty(actualErrors);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "<" +
+ "/ComplexType>" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""DefaultNs.Container"",
+ ""DefaultNs"": {
+ ""Person"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""UserName""
+ ],
+ ""UserName"": {},
+ ""HomeAddress"": {
+ ""$Type"": ""DefaultNs.Address""
+ },
+ ""WorkAddress"": {
+ ""$Type"": ""DefaultNs.Address""
+ },
+ ""Addresses"": {
+ ""$Collection"": true,
+ ""$Type"": ""DefaultNs.Address""
+ }
+ },
+ ""City"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Name""
+ ],
+ ""Name"": {}
+ },
+ ""CountryOrRegion"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Name""
+ ],
+ ""Name"": {}
+ },
+ ""Address"": {
+ ""$Kind"": ""ComplexType"",
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""City"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""DefaultNs.City""
+ }
+ },
+ ""WorkAddress"": {
+ ""$Kind"": ""ComplexType"",
+ ""$BaseType"": ""DefaultNs.Address"",
+ ""CountryOrRegion"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""DefaultNs.CountryOrRegion""
+ }
+ },
+ ""Container"": {
+ ""$Kind"": ""EntityContainer"",
+ ""People"": {
+ ""$Collection"": true,
+ ""$Type"": ""DefaultNs.Person"",
+ ""$NavigationPropertyBinding"": {
+ ""Addresses/City"": ""City"",
+ ""HomeAddress/City"": ""City"",
+ ""WorkAddress/DefaultNs.WorkAddress/CountryOrRegion"": ""CountryOrRegion""
+ }
+ },
+ ""City"": {
+ ""$Collection"": true,
+ ""$Type"": ""DefaultNs.City""
+ },
+ ""CountryOrRegion"": {
+ ""$Collection"": true,
+ ""$Type"": ""DefaultNs.CountryOrRegion""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task WriteCollectionOfNavigationOnComplex_Async()
+ {
+ // Arrange
+ var model = new EdmModel();
+
+ var entity = new EdmEntityType("DefaultNs", "EntityType");
+ var entityId = entity.AddStructuralProperty("ID", EdmCoreModel.Instance.GetString(false));
+ entity.AddKeys(entityId);
+
+ var navEntity = new EdmEntityType("DefaultNs", "NavEntityType");
+ var navEntityId = navEntity.AddStructuralProperty("ID", EdmCoreModel.Instance.GetString(false));
+ navEntity.AddKeys(navEntityId);
+
+ var complex = new EdmComplexType("DefaultNs", "ComplexType");
+ complex.AddStructuralProperty("Prop1", EdmCoreModel.Instance.GetInt32(false));
+
+ var navP = complex.AddUnidirectionalNavigation(
+ new EdmNavigationPropertyInfo()
+ {
+ Name = "CollectionOfNav",
+ Target = navEntity,
+ TargetMultiplicity = EdmMultiplicity.Many,
+ });
+
+ entity.AddStructuralProperty("Complex", new EdmComplexTypeReference(complex, false));
+
+ model.AddElement(entity);
+ model.AddElement(navEntity);
+ model.AddElement(complex);
+
+ var entityContainer = new EdmEntityContainer("DefaultNs", "Container");
+ model.AddElement(entityContainer);
+ EdmEntitySet entites = new EdmEntitySet(entityContainer, "Entities", entity);
+ EdmEntitySet navEntities = new EdmEntitySet(entityContainer, "NavEntities", navEntity);
+ entites.AddNavigationTarget(navP, navEntities, new EdmPathExpression("Complex/CollectionOfNav"));
+ entityContainer.AddElement(entites);
+ entityContainer.AddElement(navEntities);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""DefaultNs.Container"",
+ ""DefaultNs"": {
+ ""EntityType"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {},
+ ""Complex"": {
+ ""$Type"": ""DefaultNs.ComplexType""
+ }
+ },
+ ""NavEntityType"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {}
+ },
+ ""ComplexType"": {
+ ""$Kind"": ""ComplexType"",
+ ""Prop1"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""CollectionOfNav"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""DefaultNs.NavEntityType""
+ }
+ },
+ ""Container"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Entities"": {
+ ""$Collection"": true,
+ ""$Type"": ""DefaultNs.EntityType"",
+ ""$NavigationPropertyBinding"": {
+ ""Complex/CollectionOfNav"": ""NavEntities""
+ }
+ },
+ ""NavEntities"": {
+ ""$Collection"": true,
+ ""$Type"": ""DefaultNs.NavEntityType""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ContainedUnderComplexTest_Async()
+ {
+ // Arrange
+ var model = new EdmModel();
+
+ var entity = new EdmEntityType("NS", "EntityType");
+ var entityId = entity.AddStructuralProperty("ID", EdmCoreModel.Instance.GetString(false));
+ entity.AddKeys(entityId);
+
+ var containedEntity = new EdmEntityType("NS", "ContainedEntityType");
+ var containedEntityId = containedEntity.AddStructuralProperty("ID", EdmCoreModel.Instance.GetString(false));
+ containedEntity.AddKeys(containedEntityId);
+
+ var complex = new EdmComplexType("NS", "ComplexType");
+ complex.AddStructuralProperty("Prop1", EdmCoreModel.Instance.GetInt32(false));
+
+ var containedUnderComplex = complex.AddUnidirectionalNavigation(
+ new EdmNavigationPropertyInfo()
+ {
+ Name = "ContainedUnderComplex",
+ Target = containedEntity,
+ TargetMultiplicity = EdmMultiplicity.Many,
+ ContainsTarget = true
+ });
+
+ var navUnderContained = containedEntity.AddUnidirectionalNavigation(
+ new EdmNavigationPropertyInfo()
+ {
+ Name = "NavUnderContained",
+ Target = entity,
+ TargetMultiplicity = EdmMultiplicity.Many
+ });
+
+ entity.AddStructuralProperty("Complex", new EdmComplexTypeReference(complex, false));
+
+ model.AddElement(entity);
+ model.AddElement(containedEntity);
+ model.AddElement(complex);
+
+ var entityContainer = new EdmEntityContainer("NS", "Container");
+ model.AddElement(entityContainer);
+ EdmEntitySet entites1 = new EdmEntitySet(entityContainer, "Entities1", entity);
+ EdmEntitySet entites2 = new EdmEntitySet(entityContainer, "Entities2", entity);
+ entites1.AddNavigationTarget(navUnderContained, entites2,
+ new EdmPathExpression("Complex/ContainedUnderComplex/NavUnderContained"));
+ entityContainer.AddElement(entites1);
+ entityContainer.AddElement(entites2);
+
+ var entitySet1 = model.EntityContainer.FindEntitySet("Entities1");
+ var entitySet2 = model.EntityContainer.FindEntitySet("Entities2");
+ var containedEntitySet = entitySet1.FindNavigationTarget(containedUnderComplex,
+ new EdmPathExpression("Complex/ContainedUnderComplex"));
+ Assert.Equal("ContainedUnderComplex", containedEntitySet.Name);
+ var entitySetUnderContained = containedEntitySet.FindNavigationTarget(navUnderContained);
+ Assert.Equal(entitySetUnderContained, entitySet2);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Container"",
+ ""NS"": {
+ ""EntityType"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {},
+ ""Complex"": {
+ ""$Type"": ""NS.ComplexType""
+ }
+ },
+ ""ContainedEntityType"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {},
+ ""NavUnderContained"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.EntityType""
+ }
+ },
+ ""ComplexType"": {
+ ""$Kind"": ""ComplexType"",
+ ""Prop1"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""ContainedUnderComplex"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.ContainedEntityType"",
+ ""$ContainsTarget"": true
+ }
+ },
+ ""Container"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Entities1"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.EntityType"",
+ ""$NavigationPropertyBinding"": {
+ ""Complex/ContainedUnderComplex/NavUnderContained"": ""Entities2""
+ }
+ },
+ ""Entities2"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.EntityType""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task SetNavigationPropertyPartnerTest_Async()
+ {
+ // build model
+ var model = new EdmModel();
+ var entityType1 = new EdmEntityType("NS", "EntityType1");
+ var entityType2 = new EdmEntityType("NS", "EntityType2");
+ var entityType3 = new EdmEntityType("NS", "EntityType3", entityType2);
+ var complexType1 = new EdmComplexType("NS", "ComplexType1");
+ var complexType2 = new EdmComplexType("NS", "ComplexType2");
+ model.AddElements(new IEdmSchemaElement[] { entityType1, entityType2, entityType3, complexType1, complexType2 });
+ entityType1.AddKeys(entityType1.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
+ entityType2.AddKeys(entityType2.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
+ var outerNav1A = entityType1.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "OuterNavA",
+ Target = entityType2,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ var outerNav2A = entityType2.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "OuterNavA",
+ Target = entityType1,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ entityType1.SetNavigationPropertyPartner(
+ outerNav1A, new EdmPathExpression("OuterNavA"), outerNav2A, new EdmPathExpression("OuterNavA"));
+ entityType1.AddStructuralProperty(
+ "ComplexProp",
+ new EdmCollectionTypeReference(
+ new EdmCollectionType(
+ new EdmComplexTypeReference(complexType1, false))));
+ entityType2.AddStructuralProperty("ComplexProp", new EdmComplexTypeReference(complexType2, false));
+ var innerNav1 = complexType1.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "InnerNav",
+ Target = entityType2,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ var innerNav2 = complexType2.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "InnerNav",
+ Target = entityType1,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ var outerNav2B = entityType2.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "OuterNavB",
+ Target = entityType1,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ entityType2.SetNavigationPropertyPartner(
+ outerNav2B, new EdmPathExpression("OuterNavB"), innerNav1, new EdmPathExpression("ComplexProp/InnerNav"));
+ var outerNav2C = entityType3.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "OuterNavC",
+ Target = entityType1,
+ TargetMultiplicity = EdmMultiplicity.Many
+ });
+ var outerNav1B = entityType1.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "OuterNavB",
+ Target = entityType2,
+ TargetMultiplicity = EdmMultiplicity.Many
+ });
+ entityType1.SetNavigationPropertyPartner(
+ outerNav1B, new EdmPathExpression("OuterNavB"), outerNav2C, new EdmPathExpression("NS.EntityType3/OuterNavC"));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""EntityType1"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ },
+ ""ComplexProp"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.ComplexType1""
+ },
+ ""OuterNavA"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityType2"",
+ ""$Partner"": ""OuterNavA""
+ },
+ ""OuterNavB"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.EntityType2"",
+ ""$Partner"": ""NS.EntityType3/OuterNavC""
+ }
+ },
+ ""EntityType2"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ },
+ ""ComplexProp"": {
+ ""$Type"": ""NS.ComplexType2""
+ },
+ ""OuterNavA"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityType1"",
+ ""$Partner"": ""OuterNavA""
+ },
+ ""OuterNavB"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityType1"",
+ ""$Partner"": ""ComplexProp/InnerNav""
+ }
+ },
+ ""EntityType3"": {
+ ""$Kind"": ""EntityType"",
+ ""$BaseType"": ""NS.EntityType2"",
+ ""OuterNavC"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.EntityType1"",
+ ""$Partner"": ""OuterNavB""
+ }
+ },
+ ""ComplexType1"": {
+ ""$Kind"": ""ComplexType"",
+ ""InnerNav"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityType2""
+ }
+ },
+ ""ComplexType2"": {
+ ""$Kind"": ""ComplexType"",
+ ""InnerNav"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityType1""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task SetNavigationPropertyPartnerTypeHierarchyTest_Async()
+ {
+ // Arrange
+ var model = new EdmModel();
+ var entityTypeA1 = new EdmEntityType("NS", "EntityTypeA1");
+ var entityTypeA2 = new EdmEntityType("NS", "EntityTypeA2", entityTypeA1);
+ var entityTypeA3 = new EdmEntityType("NS", "EntityTypeA3", entityTypeA2);
+ var entityTypeB = new EdmEntityType("NS", "EntityTypeB");
+ model.AddElements(new IEdmSchemaElement[] { entityTypeA1, entityTypeA2, entityTypeA3, entityTypeB });
+ entityTypeA1.AddKeys(entityTypeA1.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
+ var a1Nav = entityTypeA1.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "A1Nav",
+ Target = entityTypeB,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ var a3Nav = entityTypeA3.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "A3Nav",
+ Target = entityTypeB,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ entityTypeB.AddKeys(entityTypeB.AddStructuralProperty("ID", EdmPrimitiveTypeKind.Int32));
+ var bNav1 = entityTypeB.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "BNav1",
+ Target = entityTypeA2,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ var bNav2 = entityTypeB.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "BNav2",
+ Target = entityTypeA3,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+ entityTypeA2.SetNavigationPropertyPartner(a1Nav, new EdmPathExpression("A1Nav"), bNav1, new EdmPathExpression("BNav1"));
+ entityTypeA2.SetNavigationPropertyPartner(a3Nav, new EdmPathExpression("NS.EntityTypeA3/A3Nav"), bNav2, new EdmPathExpression("BNav2"));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""EntityTypeA1"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ },
+ ""A1Nav"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityTypeB"",
+ ""$Partner"": ""BNav1""
+ }
+ },
+ ""EntityTypeA2"": {
+ ""$Kind"": ""EntityType"",
+ ""$BaseType"": ""NS.EntityTypeA1""
+ },
+ ""EntityTypeA3"": {
+ ""$Kind"": ""EntityType"",
+ ""$BaseType"": ""NS.EntityTypeA2"",
+ ""A3Nav"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityTypeB"",
+ ""$Partner"": ""BNav2""
+ }
+ },
+ ""EntityTypeB"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""ID""
+ ],
+ ""ID"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ },
+ ""BNav1"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityTypeA2"",
+ ""$Partner"": ""A1Nav""
+ },
+ ""BNav2"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.EntityTypeA3"",
+ ""$Partner"": ""NS.EntityTypeA3/A3Nav""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ #region Optional Parameters
+
+ [Fact]
+ public async Task ShouldWriteInLineOptionalParameters_Async()
+ {
+ // Arrange
+ var stringTypeReference = new EdmStringTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.String), false);
+ var model = new EdmModel();
+ var function = new EdmFunction("test", "TestFunction", stringTypeReference);
+ var requiredParam = new EdmOperationParameter(function, "requiredParam", stringTypeReference);
+ var optionalParam = new EdmOptionalParameter(function, "optionalParam", stringTypeReference, null);
+ var optionalParamWithDefault = new EdmOptionalParameter(function, "optionalParamWithDefault", stringTypeReference, "Smith");
+ function.AddParameter(requiredParam);
+ function.AddParameter(optionalParam);
+ function.AddParameter(optionalParamWithDefault);
+ model.AddElement(function);
+ model.AddEntityContainer("test", "Default").AddFunctionImport("TestFunction", function);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""test.Default"",
+ ""test"": {
+ ""TestFunction"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$Parameter"": [
+ {
+ ""$Name"": ""requiredParam""
+ },
+ {
+ ""$Name"": ""optionalParam"",
+ ""@Org.OData.Core.V1.OptionalParameter"": {}
+ },
+ {
+ ""$Name"": ""optionalParamWithDefault"",
+ ""@Org.OData.Core.V1.OptionalParameter"": {
+ ""DefaultValue"": ""Smith""
+ }
+ }
+ ],
+ ""$ReturnType"": {}
+ }
+ ],
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""TestFunction"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""test.TestFunction""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteOutofLineOptionalParameters_Async()
+ {
+ var stringTypeReference = new EdmStringTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.String), false);
+ var model = new EdmModel();
+ var function = new EdmFunction("NS", "TestFunction", stringTypeReference);
+ var requiredParam = new EdmOperationParameter(function, "requiredParam", stringTypeReference);
+ var optionalParam = new EdmOptionalParameter(function, "optionalParam", stringTypeReference, null);
+ var optionalParamWithDefault = new EdmOptionalParameter(function, "optionalParamWithDefault", stringTypeReference, "Smith");
+ function.AddParameter(requiredParam);
+ function.AddParameter(optionalParam);
+ function.AddParameter(optionalParamWithDefault);
+ model.AddElement(function);
+
+ // parameter without default value
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(optionalParam, CoreVocabularyModel.OptionalParameterTerm, new EdmRecordExpression());
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ // parameter with default value
+ IEdmComplexType optionalParameterType = CoreVocabularyModel.Instance.FindDeclaredType("Org.OData.Core.V1.OptionalParameterType") as IEdmComplexType;
+ Assert.NotNull(optionalParameterType);
+
+ IEdmRecordExpression optionalParameterRecord = new EdmRecordExpression(
+ new EdmComplexTypeReference(optionalParameterType, false),
+ new EdmPropertyConstructor("DefaultValue", new EdmStringConstant("Smith")));
+ annotation = new EdmVocabularyAnnotation(optionalParamWithDefault, CoreVocabularyModel.OptionalParameterTerm, optionalParameterRecord);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""TestFunction"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$Parameter"": [
+ {
+ ""$Name"": ""requiredParam""
+ },
+ {
+ ""$Name"": ""optionalParam""
+ },
+ {
+ ""$Name"": ""optionalParamWithDefault""
+ }
+ ],
+ ""$ReturnType"": {}
+ }
+ ],
+ ""$Annotations"": {
+ ""NS.TestFunction(Edm.String, Edm.String, Edm.String)/optionalParam"": {
+ ""@Org.OData.Core.V1.OptionalParameter"": {}
+ },
+ ""NS.TestFunction(Edm.String, Edm.String, Edm.String)/optionalParamWithDefault"": {
+ ""@Org.OData.Core.V1.OptionalParameter"": {
+ ""@type"": ""Org.OData.Core.V1.OptionalParameterType"",
+ ""DefaultValue"": ""Smith""
+ }
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteOutOfLineOptionalParametersOverwriteInLineOptionalParameter_Async()
+ {
+ // Arrange
+ var stringTypeReference = new EdmStringTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.String), false);
+ var model = new EdmModel();
+ var function = new EdmFunction("NS", "TestFunction", stringTypeReference);
+ var optionalParamWithDefault = new EdmOptionalParameter(function, "optionalParamWithDefault", stringTypeReference, "InlineDefaultValue");
+ function.AddParameter(optionalParamWithDefault);
+ model.AddElement(function);
+
+ // parameter with default value
+ IEdmComplexType optionalParameterType = CoreVocabularyModel.Instance.FindDeclaredType("Org.OData.Core.V1.OptionalParameterType") as IEdmComplexType;
+ Assert.NotNull(optionalParameterType);
+
+ IEdmRecordExpression optionalParameterRecord = new EdmRecordExpression(
+ new EdmComplexTypeReference(optionalParameterType, false),
+ new EdmPropertyConstructor("DefaultValue", new EdmStringConstant("OutofLineValue")));
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(optionalParamWithDefault, CoreVocabularyModel.OptionalParameterTerm, optionalParameterRecord);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""TestFunction"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$Parameter"": [
+ {
+ ""$Name"": ""optionalParamWithDefault""
+ }
+ ],
+ ""$ReturnType"": {}
+ }
+ ],
+ ""$Annotations"": {
+ ""NS.TestFunction(Edm.String)/optionalParamWithDefault"": {
+ ""@Org.OData.Core.V1.OptionalParameter"": {
+ ""@type"": ""Org.OData.Core.V1.OptionalParameterType"",
+ ""DefaultValue"": ""OutofLineValue""
+ }
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ #endregion
+
+ [Fact]
+ public async Task ShouldWriteInLineReturnTypeAnnotation_Async()
+ {
+ // Arrange
+ IEdmModel model = GetReturnTypeModel(EdmVocabularyAnnotationSerializationLocation.Inline);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "Edm.Int32" +
+ "Edm.Boolean" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""TestFunction"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$ReturnType"": {
+ ""$Type"": ""Edm.PrimitiveType"",
+ ""@Org.OData.Validation.V1.DerivedTypeConstraint"": [
+ ""Edm.Int32"",
+ ""Edm.Boolean""
+ ]
+ }
+ }
+ ]
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteOutofLineReturnTypeAnnotation_Async()
+ {
+ // Arrange
+ IEdmModel model = GetReturnTypeModel(EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "Edm.Int32" +
+ "Edm.Boolean" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""TestFunction"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$ReturnType"": {
+ ""$Type"": ""Edm.PrimitiveType""
+ }
+ }
+ ],
+ ""$Annotations"": {
+ ""NS.TestFunction()/$ReturnType"": {
+ ""@Org.OData.Validation.V1.DerivedTypeConstraint"": [
+ ""Edm.Int32"",
+ ""Edm.Boolean""
+ ]
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteEdmComplexTypeProperty_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ customer.AddStructuralProperty("ComplexProperty", EdmCoreModel.Instance.GetComplexType(true));
+ model.AddElement(customer);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""ComplexProperty"": {
+ ""$Type"": ""Edm.ComplexType"",
+ ""$Nullable"": true
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteEdmEntityTypeProperty_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ customer.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Target = EdmCoreModel.Instance.GetEntityType(true).EntityDefinition(),
+ ContainsTarget = false,
+ TargetMultiplicity = EdmMultiplicity.ZeroOrOne,
+ Name = "EntityNavigationProperty"
+ });
+ model.AddElement(customer);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""EntityNavigationProperty"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""Edm.EntityType""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteEdmPathTypeProperty_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmComplexType complexType = new EdmComplexType("NS", "SelectType");
+ complexType.AddStructuralProperty("DefaultSelect", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetPropertyPath(true))));
+ complexType.AddStructuralProperty("DefaultHidden", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetNavigationPropertyPath(false))));
+ model.AddElement(complexType);
+ EdmTerm term = new EdmTerm("NS", "MyTerm", new EdmComplexTypeReference(complexType, true));
+ model.AddElement(term);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""SelectType"": {
+ ""$Kind"": ""ComplexType"",
+ ""DefaultSelect"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.PropertyPath"",
+ ""$Nullable"": true
+ },
+ ""DefaultHidden"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.NavigationPropertyPath""
+ }
+ },
+ ""MyTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""NS.SelectType"",
+ ""$Nullable"": true
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmSingletonWithEdmEntityTypeButValidationFailed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
+ EdmSingleton singleton = new EdmSingleton(container, "VIP", EdmCoreModel.Instance.GetEntityType());
+ container.AddElement(singleton);
+ model.AddElement(container);
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+ Assert.Single(errors);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Default"",
+ ""NS"": {
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""VIP"": {
+ ""$Type"": ""Edm.EntityType""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmEntitySetWithEdmEntityTypeButValidationFailed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
+ EdmEntitySet entitySet = new EdmEntitySet(container, "Customers", EdmCoreModel.Instance.GetEntityType());
+ container.AddElement(entitySet);
+ model.AddElement(container);
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+ Assert.Equal(2, errors.Count());
+
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Default"",
+ ""NS"": {
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Customers"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.EntityType""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmEntityTypeWithEdmPrimitiveTypeKeyButValidationFailed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetPrimitiveType(false)));
+ model.AddElement(customer);
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+ Assert.Single(errors);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.PrimitiveType""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmEntityTypeWithCollectionAbstractTypeButValidationFailed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ customer.AddStructuralProperty("Primitive",
+ new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetPrimitiveType(true))));
+ customer.AddStructuralProperty("Complex",
+ new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetComplexType(true))));
+ model.AddElement(customer);
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+ Assert.Equal(2, errors.Count());
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""Primitive"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.PrimitiveType"",
+ ""$Nullable"": true
+ },
+ ""Complex"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.ComplexType"",
+ ""$Nullable"": true
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmStructuredTypeWithAbstractBaseTypeButValidationFailed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType customer = new EdmEntityType("NS", "Customer", EdmCoreModel.Instance.GetEntityType());
+ model.AddElement(customer);
+ EdmComplexType address = new EdmComplexType("NS", "Address", EdmCoreModel.Instance.GetComplexType());
+ model.AddElement(address);
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+ Assert.Equal(2, errors.Count());
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$BaseType"": ""Edm.EntityType""
+ },
+ ""Address"": {
+ ""$Kind"": ""ComplexType"",
+ ""$BaseType"": ""Edm.ComplexType""
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmTypeDefinitionWithEdmPrimitiveTypeButValidationFailed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmTypeDefinition definition = new EdmTypeDefinition("NS", "MyType", EdmPrimitiveTypeKind.PrimitiveType);
+ model.AddElement(definition);
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+ Assert.Single(errors);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""MyType"": {
+ ""$Kind"": ""TypeDefinition"",
+ ""$UnderlyingType"": ""Edm.PrimitiveType""
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmFunctioneWithCollectionAbstractTypeButValidationFailed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmFunction function = new EdmFunction("NS", "GetCustomer", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetPrimitiveType(true))));
+ model.AddElement(function);
+ function = new EdmFunction("NS", "GetSomething", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetComplexType(false))));
+ model.AddElement(function);
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+ Assert.Equal(2, errors.Count());
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""GetCustomer"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$ReturnType"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.PrimitiveType"",
+ ""$Nullable"": true
+ }
+ }
+ ],
+ ""GetSomething"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$ReturnType"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.ComplexType""
+ }
+ }
+ ]
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteAnnotationForEnumMember_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEnumType appliance = new EdmEnumType("NS", "Appliance", EdmPrimitiveTypeKind.Int64, isFlags: true);
+ model.AddElement(appliance);
+
+ var stove = new EdmEnumMember(appliance, "Stove", new EdmEnumMemberValue(1));
+ appliance.AddMember(stove);
+
+ var washer = new EdmEnumMember(appliance, "Washer", new EdmEnumMemberValue(2));
+ appliance.AddMember(washer);
+
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(stove, CoreVocabularyModel.LongDescriptionTerm, new EdmStringConstant("Stove Inline LongDescription"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ annotation = new EdmVocabularyAnnotation(washer, CoreVocabularyModel.LongDescriptionTerm, new EdmStringConstant("Washer OutOfLine LongDescription"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ EdmTerm term = new EdmTerm("NS", "MyTerm", EdmCoreModel.Instance.GetString(true));
+ model.AddElement(term);
+ annotation = new EdmVocabularyAnnotation(stove, term, new EdmStringConstant("Stove OutOfLine MyTerm Value"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ annotation = new EdmVocabularyAnnotation(washer, term, new EdmStringConstant("Washer Inline MyTerm Value"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Appliance"": {
+ ""$Kind"": ""EnumType"",
+ ""$UnderlyingType"": ""Edm.Int64"",
+ ""$IsFlags"": true,
+ ""Stove"": 1,
+ ""Stove@Org.OData.Core.V1.LongDescription"": ""Stove Inline LongDescription"",
+ ""Washer"": 2,
+ ""Washer@NS.MyTerm"": ""Washer Inline MyTerm Value""
+ },
+ ""MyTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Nullable"": true
+ },
+ ""$Annotations"": {
+ ""NS.Appliance/Stove"": {
+ ""@NS.MyTerm"": ""Stove OutOfLine MyTerm Value""
+ },
+ ""NS.Appliance/Washer"": {
+ ""@Org.OData.Core.V1.LongDescription"": ""Washer OutOfLine LongDescription""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWritePropertyWithCoreTypeDefinitionAndValidationPassed_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ var localDateTime = model.FindType("Org.OData.Core.V1.LocalDateTime") as IEdmTypeDefinition;
+ Assert.NotNull(localDateTime);
+
+ var qualifiedTypeName = model.FindType("Org.OData.Core.V1.QualifiedTypeName") as IEdmTypeDefinition;
+ Assert.NotNull(qualifiedTypeName);
+
+ EdmComplexType type = new EdmComplexType("NS", "Complex");
+ type.AddStructuralProperty("ModifiedDate", new EdmTypeDefinitionReference(localDateTime, true));
+ type.AddStructuralProperty("QualifiedName", new EdmTypeDefinitionReference(qualifiedTypeName, true));
+
+ model.AddElement(type);
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Complex"": {
+ ""$Kind"": ""ComplexType"",
+ ""ModifiedDate"": {
+ ""$Type"": ""Org.OData.Core.V1.LocalDateTime"",
+ ""$Nullable"": true
+ },
+ ""QualifiedName"": {
+ ""$Type"": ""Org.OData.Core.V1.QualifiedTypeName"",
+ ""$Nullable"": true
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteNavigationPropertyBindingWithTargetPathOnContainmentOnSingleton_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
+ EdmEntityType order = new EdmEntityType("NS", "Order");
+ order.AddKeys(order.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
+ EdmEntityType orderLine = new EdmEntityType("NS", "OrderLine");
+ orderLine.AddKeys(orderLine.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32));
+
+ // Customer
+ // -> ContainedOrders (Contained)
+ // -> ContainedOrderLines (Contained)
+ customer.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "ContainedOrders",
+ TargetMultiplicity = EdmMultiplicity.Many,
+ Target = order,
+ ContainsTarget = true
+ });
+
+ var orderLinesContainedNav = customer.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "ContainedOrderLines",
+ TargetMultiplicity = EdmMultiplicity.Many,
+ Target = orderLine,
+ ContainsTarget = true
+ });
+
+ // Order
+ // -> OrderLines
+ var orderLinesNav = order.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo
+ {
+ Name = "OrderLines",
+ TargetMultiplicity = EdmMultiplicity.Many,
+ Target = orderLine
+ });
+
+ model.AddElement(customer);
+ model.AddElement(order);
+ model.AddElement(orderLine);
+
+ EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
+ EdmSingleton me = new EdmSingleton(container, "Me", customer);
+ container.AddElement(me);
+ EdmEntitySet customers = new EdmEntitySet(container, "Customers", customer);
+ container.AddElement(customers);
+ model.AddElement(container);
+
+ // Navigation property binding to the containment of the singleton
+ EdmContainedEntitySet containedEntitySet = new EdmContainedEntitySet(me, orderLinesContainedNav);
+ customers.AddNavigationTarget(orderLinesNav, containedEntitySet, new EdmPathExpression("ContainedOrders/OrderLines"));
+
+ IEnumerable errors;
+ Assert.False(model.Validate(out errors));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Default"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ },
+ ""ContainedOrders"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.Order"",
+ ""$ContainsTarget"": true
+ },
+ ""ContainedOrderLines"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.OrderLine"",
+ ""$ContainsTarget"": true
+ }
+ },
+ ""Order"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ },
+ ""OrderLines"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.OrderLine""
+ }
+ },
+ ""OrderLine"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ }
+ },
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Me"": {
+ ""$Type"": ""NS.Customer""
+ },
+ ""Customers"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Customer"",
+ ""$NavigationPropertyBinding"": {
+ ""ContainedOrders/OrderLines"": ""Me/ContainedOrderLines""
+ }
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteUrlEscapeFunction_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType entityType = new EdmEntityType("NS", "Entity");
+ entityType.AddKeys(entityType.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ EdmFunction function = new EdmFunction("NS", "Function", EdmCoreModel.Instance.GetInt32(true), true, null, false);
+ function.AddParameter("entity", new EdmEntityTypeReference(entityType, true));
+ function.AddParameter("path", EdmCoreModel.Instance.GetString(true));
+ model.AddElement(entityType);
+ model.AddElement(function);
+ model.SetUrlEscapeFunction(function);
+
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Entity"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ }
+ },
+ ""Function"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$IsBound"": true,
+ ""$Parameter"": [
+ {
+ ""$Name"": ""entity"",
+ ""$Type"": ""NS.Entity"",
+ ""$Nullable"": true
+ },
+ {
+ ""$Name"": ""path"",
+ ""$Nullable"": true
+ }
+ ],
+ ""$ReturnType"": {
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ },
+ ""@Org.OData.Community.V1.UrlEscapeFunction"": true
+ }
+ ]
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteAnnotationPathExpression_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmComplexType complex = new EdmComplexType("NS", "Complex");
+ model.AddElement(complex);
+ EdmTerm term1 = new EdmTerm("NS", "MyAnnotationPathTerm", EdmCoreModel.Instance.GetAnnotationPath(false));
+ EdmTerm term2 = new EdmTerm("NS", "MyNavigationPathTerm", EdmCoreModel.Instance.GetNavigationPropertyPath(false));
+ model.AddElement(term1);
+ model.AddElement(term2);
+
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(complex, term1, new EdmAnnotationPathExpression("abc/efg"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ annotation = new EdmVocabularyAnnotation(complex, term2, new EdmNavigationPropertyPathExpression("123/456.t"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Complex"": {
+ ""$Kind"": ""ComplexType"",
+ ""@NS.MyAnnotationPathTerm"": ""abc/efg"",
+ ""@NS.MyNavigationPathTerm"": ""123/456.t""
+ },
+ ""MyAnnotationPathTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.AnnotationPath""
+ },
+ ""MyNavigationPathTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.NavigationPropertyPath""
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteAnnotationWithoutSpecifiedValue_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmComplexType complex = new EdmComplexType("NS", "Complex");
+ EdmTerm term1 = new EdmTerm("NS", "MyAnnotationPathTerm", EdmCoreModel.Instance.GetAnnotationPath(false));
+ EdmTerm term2 = new EdmTerm("NS", "MyDefaultStringTerm", EdmCoreModel.Instance.GetString(false), "Property Term", "This is a test");
+ EdmTerm term3 = new EdmTerm("NS", "MyDefaultBoolTerm", EdmCoreModel.Instance.GetBoolean(false), "Property Term", "true");
+ model.AddElements(new IEdmSchemaElement[] { complex, term1, term2, term3 });
+
+ // annotation with value
+ IEdmVocabularyAnnotation annotation = term1.CreateVocabularyAnnotation(complex, new EdmAnnotationPathExpression("abc/efg"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ // annotation without value
+ annotation = term2.CreateVocabularyAnnotation(complex);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ annotation = term3.CreateVocabularyAnnotation(complex);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ // Validate model
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" + // no longer has value
+ "" + // no longer has value
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Complex"": {
+ ""$Kind"": ""ComplexType"",
+ ""@NS.MyAnnotationPathTerm"": ""abc/efg"",
+ ""@NS.MyDefaultStringTerm"": ""This is a test"",
+ ""@NS.MyDefaultBoolTerm"": true
+ },
+ ""MyAnnotationPathTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.AnnotationPath""
+ },
+ ""MyDefaultStringTerm"": {
+ ""$Kind"": ""Term"",
+ ""$AppliesTo"": [
+ ""Property Term""
+ ],
+ ""$DefaultValue"": ""This is a test""
+ },
+ ""MyDefaultBoolTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Boolean"",
+ ""$AppliesTo"": [
+ ""Property Term""
+ ],
+ ""$DefaultValue"": ""true""
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteAnnotationWithVariousPrimitiveDefaultValues_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmComplexType complex = new EdmComplexType("NS", "Complex");
+ model.AddElement(complex);
+
+ Action registerAction = (kind, value) =>
+ {
+ string name = $"Default{kind}Term";
+ EdmTerm term = new EdmTerm("NS", name, EdmCoreModel.Instance.GetPrimitive(kind, false), null, value);
+ model.AddElement(term);
+
+ IEdmVocabularyAnnotation annotation = term.CreateVocabularyAnnotation(complex);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+ Assert.NotNull(annotation.Value);
+ };
+
+ registerAction(EdmPrimitiveTypeKind.Binary, "01");
+ registerAction(EdmPrimitiveTypeKind.Decimal, "0.34");
+ registerAction(EdmPrimitiveTypeKind.String, "This is a test");
+ registerAction(EdmPrimitiveTypeKind.Duration, "P11DT23H59M59.999999999999S");
+ registerAction(EdmPrimitiveTypeKind.TimeOfDay, "21:45:00");
+ registerAction(EdmPrimitiveTypeKind.Boolean, "true");
+ registerAction(EdmPrimitiveTypeKind.Single, "0.2");
+ registerAction(EdmPrimitiveTypeKind.Double, "3.94");
+ registerAction(EdmPrimitiveTypeKind.Guid, "21EC2020-3AEA-1069-A2DD-08002B30309D");
+ registerAction(EdmPrimitiveTypeKind.Int16, "4");
+ registerAction(EdmPrimitiveTypeKind.Int32, "4");
+ registerAction(EdmPrimitiveTypeKind.Int64, "4");
+ registerAction(EdmPrimitiveTypeKind.Date, "2000-12-10");
+
+ // Validate model
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Complex"": {
+ ""$Kind"": ""ComplexType"",
+ ""@NS.DefaultBinaryTerm"": ""AQ"",
+ ""@NS.DefaultDecimalTerm"": 0.34,
+ ""@NS.DefaultStringTerm"": ""This is a test"",
+ ""@NS.DefaultDurationTerm"": ""P11DT23H59M59.9999999S"",
+ ""@NS.DefaultTimeOfDayTerm"": ""21:45:00.0000000"",
+ ""@NS.DefaultBooleanTerm"": true,
+ ""@NS.DefaultSingleTerm"": 0.2,
+ ""@NS.DefaultDoubleTerm"": 3.94,
+ ""@NS.DefaultGuidTerm"": ""21ec2020-3aea-1069-a2dd-08002b30309d"",
+ ""@NS.DefaultInt16Term"": 4,
+ ""@NS.DefaultInt32Term"": 4,
+ ""@NS.DefaultInt64Term"": 4,
+ ""@NS.DefaultDateTerm"": ""2000-12-10""
+ },
+ ""DefaultBinaryTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Binary"",
+ ""$DefaultValue"": ""01""
+ },
+ ""DefaultDecimalTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Decimal"",
+ ""$DefaultValue"": ""0.34""
+ },
+ ""DefaultStringTerm"": {
+ ""$Kind"": ""Term"",
+ ""$DefaultValue"": ""This is a test""
+ },
+ ""DefaultDurationTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Duration"",
+ ""$DefaultValue"": ""P11DT23H59M59.999999999999S"",
+ ""$Precision"": 0
+ },
+ ""DefaultTimeOfDayTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.TimeOfDay"",
+ ""$DefaultValue"": ""21:45:00"",
+ ""$Precision"": 0
+ },
+ ""DefaultBooleanTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Boolean"",
+ ""$DefaultValue"": ""true""
+ },
+ ""DefaultSingleTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Single"",
+ ""$DefaultValue"": ""0.2""
+ },
+ ""DefaultDoubleTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Double"",
+ ""$DefaultValue"": ""3.94""
+ },
+ ""DefaultGuidTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Guid"",
+ ""$DefaultValue"": ""21EC2020-3AEA-1069-A2DD-08002B30309D""
+ },
+ ""DefaultInt16Term"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Int16"",
+ ""$DefaultValue"": ""4""
+ },
+ ""DefaultInt32Term"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Int32"",
+ ""$DefaultValue"": ""4""
+ },
+ ""DefaultInt64Term"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Int64"",
+ ""$DefaultValue"": ""4""
+ },
+ ""DefaultDateTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Date"",
+ ""$DefaultValue"": ""2000-12-10""
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteScaleAndSridVariable_UsingLegacyVariable_Async()
+ {
+ CsdlXmlWriterSettings writerSettings = new CsdlXmlWriterSettings
+ {
+ LibraryCompatibility = EdmLibraryCompatibility.UseLegacyVariableCasing
+ };
+
+ string csdlTemplate = "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+ // Parse into CSDL
+ IEdmModel model;
+ using (XmlReader xr = XElement.Parse(csdlTemplate).CreateReader())
+ {
+ model = CsdlReader.Parse(xr);
+ }
+
+ // Validate model
+ IEnumerable errors;
+ bool validated = model.Validate(out errors);
+ Assert.True(validated);
+
+ // Act & Assert for Reserialized XML
+ await WriteAndVerifyXmlAsync(model, csdlTemplate, writerSettings).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteScaleAndSridVariable_UsingLowerCase_Variable_Async()
+ {
+ string csdlTemplate = "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+ // Parse into CSDL
+ IEdmModel model;
+ using (XmlReader xr = XElement.Parse(csdlTemplate).CreateReader())
+ {
+ model = CsdlReader.Parse(xr);
+ }
+
+ // Validate model
+ IEnumerable errors;
+ bool validated = model.Validate(out errors);
+ Assert.True(validated);
+
+ // Act & Assert for Reserialized XML
+ await WriteAndVerifyXmlAsync(model, csdlTemplate).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteNavigationPropertyBindingTargetOnContainmentNavigationProperty_Async()
+ {
+ EdmModel model = new EdmModel();
+
+ var areaEntityType = new EdmEntityType("NS", "Area");
+ var key = areaEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String);
+ areaEntityType.AddKeys(key);
+
+ var plantEntityType = new EdmEntityType("NS", "Plant");
+ key = plantEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String);
+ plantEntityType.AddKeys(key);
+
+ var siteEntityType = new EdmEntityType("NS", "Site");
+ key = siteEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String);
+ siteEntityType.AddKeys(key);
+
+ // Contained entity sets
+ plantEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
+ {
+ ContainsTarget = true,
+ Name = "Areas",
+ Target = areaEntityType,
+ TargetMultiplicity = EdmMultiplicity.Many
+ });
+
+ var sitePlantsNavigationProperty = siteEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
+ {
+ ContainsTarget = true,
+ Name = "Plants",
+ Target = plantEntityType,
+ TargetMultiplicity = EdmMultiplicity.Many
+ });
+
+ // Non-contained navigation property back to plant
+ var areaPlantNavigationProperty = areaEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
+ {
+ ContainsTarget = false,
+ Name = "Plant",
+ Target = plantEntityType,
+ TargetMultiplicity = EdmMultiplicity.One
+ });
+
+ model.AddElement(areaEntityType);
+ model.AddElement(plantEntityType);
+ model.AddElement(siteEntityType);
+
+ var entityContainer = new EdmEntityContainer("NS", "MyApi");
+ var sitesEntitySet = entityContainer.AddEntitySet("Sites", siteEntityType);
+ var areasEntitySet = entityContainer.AddEntitySet("Areas", areaEntityType);
+ model.AddElement(entityContainer);
+ var plantsContainedEntitySet = sitesEntitySet.FindNavigationTarget(sitePlantsNavigationProperty);
+ areasEntitySet.AddNavigationTarget(areaPlantNavigationProperty, plantsContainedEntitySet);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.MyApi"",
+ ""NS"": {
+ ""Area"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Nullable"": true
+ },
+ ""Plant"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Type"": ""NS.Plant""
+ }
+ },
+ ""Plant"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Nullable"": true
+ },
+ ""Areas"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.Area"",
+ ""$ContainsTarget"": true
+ }
+ },
+ ""Site"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Nullable"": true
+ },
+ ""Plants"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.Plant"",
+ ""$ContainsTarget"": true
+ }
+ },
+ ""MyApi"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Sites"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Site""
+ },
+ ""Areas"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Area"",
+ ""$NavigationPropertyBinding"": {
+ ""Plant"": ""Sites/Plants""
+ }
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteNavigationPropertyBindingTargetWithTypeCast_Async()
+ {
+ EdmModel model = new EdmModel();
+
+ var purchaseOrderEntityType = new EdmEntityType("NS", "PurchaseOrder");
+ var key = purchaseOrderEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String, /*isNullable*/ false);
+ purchaseOrderEntityType.AddKeys(key);
+
+ var productEntityType = new EdmEntityType("NS", "Product");
+ key = productEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String, /*isNullable*/ false);
+ productEntityType.AddKeys(key);
+
+ var widgetEntityType = new EdmEntityType("NS", "Widget", productEntityType);
+
+ var dooHickeyEntityType = new EdmEntityType("NS", "DooHickey", productEntityType);
+
+ // Navigation Property to Product
+ var productNavigationProperty = purchaseOrderEntityType.AddUnidirectionalNavigation(new EdmNavigationPropertyInfo()
+ {
+ ContainsTarget = false,
+ Name = "Product",
+ Target = productEntityType,
+ TargetMultiplicity = EdmMultiplicity.Many
+ });
+
+ model.AddElement(purchaseOrderEntityType);
+ model.AddElement(productEntityType);
+ model.AddElement(widgetEntityType);
+ model.AddElement(dooHickeyEntityType);
+
+ var entityContainer = new EdmEntityContainer("NS", "MyApi");
+ var purchaseOrdersEntitySet = entityContainer.AddEntitySet("PurchaseOrders", purchaseOrderEntityType);
+ var widgetEntitySet = entityContainer.AddEntitySet("Widgets", widgetEntityType);
+ var dooHickeyEntitySet = entityContainer.AddEntitySet("DooHickies", dooHickeyEntityType);
+ model.AddElement(entityContainer);
+ purchaseOrdersEntitySet.AddNavigationTarget(productNavigationProperty, widgetEntitySet, new EdmPathExpression("Product/NS.Widget"));
+ purchaseOrdersEntitySet.AddNavigationTarget(productNavigationProperty, dooHickeyEntitySet, new EdmPathExpression("Product/NS.DooHickey"));
+
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+ Assert.Empty(errors);
+
+ var v40Json =
+ @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.MyApi"",
+ ""NS"": {
+ ""PurchaseOrder"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {},
+ ""Product"": {
+ ""$Kind"": ""NavigationProperty"",
+ ""$Collection"": true,
+ ""$Type"": ""NS.Product""
+ }
+ },
+ ""Product"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {}
+ },
+ ""Widget"": {
+ ""$Kind"": ""EntityType"",
+ ""$BaseType"": ""NS.Product""
+ },
+ ""DooHickey"": {
+ ""$Kind"": ""EntityType"",
+ ""$BaseType"": ""NS.Product""
+ },
+ ""MyApi"": {
+ ""$Kind"": ""EntityContainer"",
+ ""PurchaseOrders"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.PurchaseOrder"",
+ ""$NavigationPropertyBinding"": {
+ ""Product/NS.DooHickey"": ""DooHickies"",
+ ""Product/NS.Widget"": ""Widgets""
+ }
+ },
+ ""Widgets"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Widget""
+ },
+ ""DooHickies"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.DooHickey""
+ }
+ }
+ }
+}";
+
+ var xmlResult =
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "{1}" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+ var v40EntitySet =
+ "";
+
+ var v401EntitySet =
+ "" +
+ "" +
+ "" +
+ "";
+
+ // Act & Assert for XML 4.0
+ await WriteAndVerifyXmlAsync(model, String.Format(xmlResult, "4.0", v40EntitySet)).ConfigureAwait(false);
+
+ // Act & Assert for JSON 4.0
+ await WriteAndVerifyJsonAsync(model, v40Json).ConfigureAwait(false);
+
+ model.SetEdmVersion(Version.Parse("4.01"));
+
+ // Act & Assert for XML 4.1
+ await WriteAndVerifyXmlAsync(model, String.Format(xmlResult, "4.01", v401EntitySet)).ConfigureAwait(false);
+
+ // Act & Assert for JSON 4.1
+ await WriteAndVerifyJsonAsync(model, v40Json.Replace("4.0", "4.01")).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task CanWriteEdmModelWithUntypedProperty_Async()
+ {
+ EdmModel model = new EdmModel();
+
+ var entityType = new EdmEntityType("NS", "Entity");
+ var key = entityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.String);
+ entityType.AddKeys(key);
+ entityType.AddStructuralProperty("Value", EdmCoreModel.Instance.GetUntyped());
+ entityType.AddStructuralProperty("Data", new EdmCollectionTypeReference(new EdmCollectionType(EdmCoreModel.Instance.GetUntyped())));
+ model.AddElement(entityType);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Entity"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Nullable"": true
+ },
+ ""Value"": {
+ ""$Type"": ""Edm.Untyped"",
+ ""$Nullable"": true
+ },
+ ""Data"": {
+ ""$Collection"": true,
+ ""$Type"": ""Edm.Untyped"",
+ ""$Nullable"": true
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Theory]
+ [InlineData("4.0")]
+ [InlineData("4.01")]
+ public async Task ValidateEdmxVersions_Async(string odataVersion)
+ {
+ // Specify the model
+ EdmModel edmModel = new EdmModel(false);
+ edmModel.SetEdmVersion(odataVersion == "4.0" ? EdmConstants.EdmVersion4 : EdmConstants.EdmVersion401);
+
+ // XML
+ await WriteAndVerifyXmlAsync(edmModel, "").ConfigureAwait(false);
+
+ // JSON
+ await WriteAndVerifyJsonAsync(edmModel, "{\"$Version\":\"" + odataVersion + "\"}", false).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldSubstituteFullyQualifiedNamespaceWithAliasIfAliasIsSet_Async()
+ {
+ // Arrange
+ var stringTypeReference = new EdmStringTypeReference(EdmCoreModel.Instance.GetPrimitiveType(EdmPrimitiveTypeKind.String), false);
+ var model = new EdmModel();
+ model.SetNamespaceAlias("Org.OData.Core.V1", "Core");
+ var function = new EdmFunction("test", "TestFunction", stringTypeReference);
+ var requiredParam = new EdmOperationParameter(function, "requiredParam", stringTypeReference);
+ var optionalParam = new EdmOptionalParameter(function, "optionalParam", stringTypeReference, null);
+ var optionalParamWithDefault = new EdmOptionalParameter(function, "optionalParamWithDefault", stringTypeReference, "Smith");
+ function.AddParameter(requiredParam);
+ function.AddParameter(optionalParam);
+ function.AddParameter(optionalParamWithDefault);
+ model.AddElement(function);
+ model.AddEntityContainer("test", "Default").AddFunctionImport("TestFunction", function);
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""test.Default"",
+ ""test"": {
+ ""TestFunction"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$Parameter"": [
+ {
+ ""$Name"": ""requiredParam""
+ },
+ {
+ ""$Name"": ""optionalParam"",
+ ""@Core.OptionalParameter"": {}
+ },
+ {
+ ""$Name"": ""optionalParamWithDefault"",
+ ""@Core.OptionalParameter"": {
+ ""DefaultValue"": ""Smith""
+ }
+ }
+ ],
+ ""$ReturnType"": {}
+ }
+ ],
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""TestFunction"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""test.TestFunction""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Theory]
+ [InlineData(CsdlTarget.OData, "", "")]
+ [InlineData(CsdlTarget.EntityFramework, "", "")]
+ public async Task TryWriteCsdlAsyncShouldFlushAsync_Async(CsdlTarget csdlTarget, string schemaParentOpeningPartial, string schemaParentClosingPartial)
+ {
+ var model = new EdmModel();
+
+ var customerEntityType = new EdmEntityType("NS", "Customer");
+ var key = customerEntityType.AddStructuralProperty("Id", EdmPrimitiveTypeKind.Int32);
+ customerEntityType.AddKeys(key);
+ customerEntityType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
+ model.AddElement(customerEntityType);
+
+ var builder = new StringBuilder();
+ using (var writer = XmlWriter.Create(builder, new XmlWriterSettings { Encoding = Encoding.UTF8, Async = true }))
+ {
+ var (result, errors) = await CsdlWriter.TryWriteCsdlAsync(model, writer, csdlTarget).ConfigureAwait(false);
+ if (!result)
+ {
+ Assert.True(false, "Serialization was unsuccessful");
+ }
+
+ // Xml writer should have flushed whatever is in the buffer before TryWriteCsdl is exited
+ Assert.Equal(
+ builder.ToString(),
+ "" +
+ "" +
+ schemaParentOpeningPartial +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ schemaParentClosingPartial +
+ "");
+ }
+ }
+
+ internal static async Task WriteAndVerifyXmlAsync(IEdmModel model, string expected, CsdlTarget target = CsdlTarget.OData)
+ {
+ using (StringWriter sw = new StringWriter())
+ {
+ XmlWriterSettings settings = new XmlWriterSettings()
+ {
+ Encoding = Encoding.UTF8,
+ Async = true
+ };
+
+ using (XmlWriter xw = XmlWriter.Create(sw, settings))
+ {
+ var (ok, errors) = await CsdlWriter.TryWriteCsdlAsync(model, xw, target).ConfigureAwait(false);
+ await xw.FlushAsync().ConfigureAwait(false);
+ }
+
+ string actual = sw.ToString();
+ Assert.Equal(expected, actual);
+ }
+ }
+
+ internal static async Task WriteAndVerifyXmlAsync(IEdmModel model, string expected, CsdlXmlWriterSettings csdlXmlWriterSettings, CsdlTarget target = CsdlTarget.OData)
+ {
+ using (StringWriter sw = new StringWriter())
+ {
+ XmlWriterSettings settings = new XmlWriterSettings()
+ {
+ Encoding = Encoding.UTF8,
+ Async = true
+ };
+
+ using (XmlWriter xw = XmlWriter.Create(sw, settings))
+ {
+ var (success, errors) = await CsdlWriter.TryWriteCsdlAsync(model, xw, target, csdlXmlWriterSettings).ConfigureAwait(false);
+ await xw.FlushAsync().ConfigureAwait(false);
+ }
+
+ string actual = sw.ToString();
+ Assert.Equal(expected, actual);
+ }
+ }
+
+ internal async Task WriteAndVerifyJsonAsync(IEdmModel model, string expected, bool indented = true, bool isIeee754Compatible = false)
+ {
+#if NETCOREAPP3_1
+ using (MemoryStream memStream = new MemoryStream())
+ {
+ JsonWriterOptions options = new JsonWriterOptions
+ {
+ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
+ Indented = indented,
+ SkipValidation = false
+ };
+
+ using (Utf8JsonWriter jsonWriter = new Utf8JsonWriter(memStream, options))
+ {
+ CsdlJsonWriterSettings settings = CsdlJsonWriterSettings.Default;
+ settings.IsIeee754Compatible = isIeee754Compatible;
+ IEnumerable errors;
+ var (ok, errors) = await CsdlWriter.TryWriteCsdlAsync(model, jsonWriter, settings).ConfigureAwait(false);
+ await jsonWriter.FlushAsync().ConfigureAwait(false);
+ Assert.True(ok);
+ }
+
+ memStream.Seek(0, SeekOrigin.Begin);
+ string actual = new StreamReader(memStream).ReadToEnd();
+ Assert.Equal(expected, actual);
+ }
+#endif
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.TargetPath.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.TargetPath.Async.cs
new file mode 100644
index 0000000000..b930bfd44a
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.TargetPath.Async.cs
@@ -0,0 +1,417 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Vocabularies;
+using System.Linq;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Csdl
+{
+ public partial class CsdlWriterTests
+ {
+
+
+ [Fact]
+ public async Task ShouldWriteAnnotationForEntitySetProperty_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ customer.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, isNullable: false);
+ model.AddElement(customer);
+
+ EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
+ EdmEntitySet entitySet = new EdmEntitySet(container, "Customers", customer);
+ container.AddElement(entitySet);
+ model.AddElement(container);
+
+ IEdmProperty nameProperty = customer.DeclaredProperties.Where(x => x.Name == "Name").FirstOrDefault();
+
+ EdmTargetPath targetPath = new EdmTargetPath(container, entitySet, nameProperty);
+
+ EdmTerm term = new EdmTerm("NS", "MyTerm", EdmCoreModel.Instance.GetString(true));
+ model.AddElement(term);
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(targetPath, term, new EdmStringConstant("Name OutOfLine MyTerm Value"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Default"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""Name"": {}
+ },
+ ""MyTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Nullable"": true
+ },
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Customers"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Customer""
+ }
+ },
+ ""$Annotations"": {
+ ""NS.Default/Customers/Name"": {
+ ""@NS.MyTerm"": ""Name OutOfLine MyTerm Value""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteAnnotationForEntitySetComplexTypeProperty_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+
+ EdmComplexType addressType = new EdmComplexType("NS", "Address");
+ addressType.AddStructuralProperty("Street", EdmPrimitiveTypeKind.String, isNullable: false);
+ addressType.AddStructuralProperty("City", EdmPrimitiveTypeKind.String, isNullable: false);
+ addressType.AddStructuralProperty("PostalCode", EdmPrimitiveTypeKind.Int32, isNullable: false);
+ model.AddElement(addressType);
+
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ customer.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, isNullable: false);
+ customer.AddStructuralProperty("Address", new EdmComplexTypeReference(addressType, isNullable: false));
+ model.AddElement(customer);
+
+ EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
+ EdmEntitySet entitySet = new EdmEntitySet(container, "Customers", customer);
+ container.AddElement(entitySet);
+ model.AddElement(container);
+
+ IEdmProperty addressProperty = customer.DeclaredProperties.Where(x => x.Name == "Address").FirstOrDefault();
+ IEdmProperty streetProperty = addressType.DeclaredProperties.Where(x => x.Name == "Street").FirstOrDefault();
+
+ EdmTargetPath targetPath = new EdmTargetPath(container, entitySet, addressProperty, streetProperty);
+
+ EdmTerm term = new EdmTerm("NS", "MyTerm", EdmCoreModel.Instance.GetString(true));
+ model.AddElement(term);
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(targetPath, term, new EdmStringConstant("Name OutOfLine MyTerm Value"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Default"",
+ ""NS"": {
+ ""Address"": {
+ ""$Kind"": ""ComplexType"",
+ ""Street"": {},
+ ""City"": {},
+ ""PostalCode"": {
+ ""$Type"": ""Edm.Int32""
+ }
+ },
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""Name"": {},
+ ""Address"": {
+ ""$Type"": ""NS.Address""
+ }
+ },
+ ""MyTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Nullable"": true
+ },
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Customers"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Customer""
+ }
+ },
+ ""$Annotations"": {
+ ""NS.Default/Customers/Address/Street"": {
+ ""@NS.MyTerm"": ""Name OutOfLine MyTerm Value""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteAnnotationForSingletonComplexTypeProperty_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+
+ EdmComplexType addressType = new EdmComplexType("NS", "Address");
+ addressType.AddStructuralProperty("Street", EdmPrimitiveTypeKind.String, isNullable: false);
+ addressType.AddStructuralProperty("City", EdmPrimitiveTypeKind.String, isNullable: false);
+ addressType.AddStructuralProperty("PostalCode", EdmPrimitiveTypeKind.Int32, isNullable: false);
+ model.AddElement(addressType);
+
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ customer.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, isNullable: false);
+ customer.AddStructuralProperty("Address", new EdmComplexTypeReference(addressType, isNullable: false));
+ model.AddElement(customer);
+
+ EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
+ EdmEntitySet entitySet = new EdmEntitySet(container, "Customers", customer);
+ container.AddElement(entitySet);
+ IEdmSingleton singleton = container.AddSingleton("SpecialCustomer", customer);
+ model.AddElement(container);
+
+ IEdmProperty addressProperty = customer.DeclaredProperties.Where(x => x.Name == "Address").FirstOrDefault();
+ IEdmProperty streetProperty = addressType.DeclaredProperties.Where(x => x.Name == "Street").FirstOrDefault();
+
+ EdmTargetPath targetPath = new EdmTargetPath(container, singleton, addressProperty, streetProperty);
+
+ EdmTerm term = new EdmTerm("NS", "MyTerm", EdmCoreModel.Instance.GetString(true));
+ model.AddElement(term);
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(targetPath, term, new EdmStringConstant("Name OutOfLine MyTerm Value"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Default"",
+ ""NS"": {
+ ""Address"": {
+ ""$Kind"": ""ComplexType"",
+ ""Street"": {},
+ ""City"": {},
+ ""PostalCode"": {
+ ""$Type"": ""Edm.Int32""
+ }
+ },
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""Name"": {},
+ ""Address"": {
+ ""$Type"": ""NS.Address""
+ }
+ },
+ ""MyTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Nullable"": true
+ },
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Customers"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Customer""
+ },
+ ""SpecialCustomer"": {
+ ""$Type"": ""NS.Customer""
+ }
+ },
+ ""$Annotations"": {
+ ""NS.Default/SpecialCustomer/Address/Street"": {
+ ""@NS.MyTerm"": ""Name OutOfLine MyTerm Value""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task ShouldWriteAnnotationForEntitySetDerivedTypeProperty_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+
+ EdmEntityType customer = new EdmEntityType("NS", "Customer");
+ customer.AddKeys(customer.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false)));
+ customer.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String, isNullable: false);
+ model.AddElement(customer);
+
+ EdmEntityType vipCustomer = new EdmEntityType("NS", "VipCustomer", customer);
+ vipCustomer.AddStructuralProperty("VipNumber", EdmPrimitiveTypeKind.String, isNullable: false);
+ model.AddElement(vipCustomer);
+
+ EdmEntityContainer container = new EdmEntityContainer("NS", "Default");
+ EdmEntitySet entitySet = new EdmEntitySet(container, "Customers", customer);
+ container.AddElement(entitySet);
+ model.AddElement(container);
+
+ IEdmProperty vipNoProperty = vipCustomer.DeclaredProperties.Where(x => x.Name == "VipNumber").FirstOrDefault();
+
+ EdmTargetPath targetPath = new EdmTargetPath(container, entitySet, vipCustomer, vipNoProperty);
+
+ EdmTerm term = new EdmTerm("NS", "MyTerm", EdmCoreModel.Instance.GetString(true));
+ model.AddElement(term);
+ EdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(targetPath, term, new EdmStringConstant("Name OutOfLine MyTerm Value"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.OutOfLine);
+ model.SetVocabularyAnnotation(annotation);
+
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""$EntityContainer"": ""NS.Default"",
+ ""NS"": {
+ ""Customer"": {
+ ""$Kind"": ""EntityType"",
+ ""$Key"": [
+ ""Id""
+ ],
+ ""Id"": {
+ ""$Type"": ""Edm.Int32""
+ },
+ ""Name"": {}
+ },
+ ""VipCustomer"": {
+ ""$Kind"": ""EntityType"",
+ ""$BaseType"": ""NS.Customer"",
+ ""VipNumber"": {}
+ },
+ ""MyTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Nullable"": true
+ },
+ ""Default"": {
+ ""$Kind"": ""EntityContainer"",
+ ""Customers"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Customer""
+ }
+ },
+ ""$Annotations"": {
+ ""NS.Default/Customers/NS.VipCustomer/VipNumber"": {
+ ""@NS.MyTerm"": ""Name OutOfLine MyTerm Value""
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.VocabularyAnnotation.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.VocabularyAnnotation.Async.cs
new file mode 100644
index 0000000000..1ada085b65
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.VocabularyAnnotation.Async.cs
@@ -0,0 +1,97 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Validation;
+using Microsoft.OData.Edm.Vocabularies;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Csdl
+{
+ public partial class CsdlWriterTests
+ {
+ [Fact]
+ public async Task CanWriteAnnotationWithoutSpecifiedValue_UsingCustomIEdmVocabularyImplementation_Async()
+ {
+ // Arrange
+ EdmModel model = new EdmModel();
+ EdmComplexType complex = new EdmComplexType("NS", "Complex");
+ EdmTerm term1 = new EdmTerm("NS", "MyAnnotationPathTerm", EdmCoreModel.Instance.GetAnnotationPath(false));
+ EdmTerm term2 = new EdmTerm("NS", "MyDefaultStringTerm", EdmCoreModel.Instance.GetString(false), "Property Term", "This is a test");
+ EdmTerm term3 = new EdmTerm("NS", "MyDefaultBoolTerm", EdmCoreModel.Instance.GetBoolean(false), "Property Term", "true");
+ model.AddElements(new IEdmSchemaElement[] { complex, term1, term2, term3 });
+
+ // annotation with value
+ IEdmVocabularyAnnotation annotation = new CustomEdmVocabularyAnnotation(complex, term1, new EdmAnnotationPathExpression("abc/efg"));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ // annotation without value
+ annotation = new CustomEdmVocabularyAnnotation(complex, term2, null);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ annotation = new CustomEdmVocabularyAnnotation(complex, term3, null);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ // Validate model
+ IEnumerable errors;
+ Assert.True(model.Validate(out errors));
+
+ // Act & Assert for XML
+ await WriteAndVerifyXmlAsync(model, "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" + // no longer has value
+ "" + // no longer has value
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await WriteAndVerifyJsonAsync(model, @"{
+ ""$Version"": ""4.0"",
+ ""NS"": {
+ ""Complex"": {
+ ""$Kind"": ""ComplexType"",
+ ""@NS.MyAnnotationPathTerm"": ""abc/efg"",
+ ""@NS.MyDefaultStringTerm"": ""This is a test"",
+ ""@NS.MyDefaultBoolTerm"": true
+ },
+ ""MyAnnotationPathTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.AnnotationPath""
+ },
+ ""MyDefaultStringTerm"": {
+ ""$Kind"": ""Term"",
+ ""$AppliesTo"": [
+ ""Property Term""
+ ],
+ ""$DefaultValue"": ""This is a test""
+ },
+ ""MyDefaultBoolTerm"": {
+ ""$Kind"": ""Term"",
+ ""$Type"": ""Edm.Boolean"",
+ ""$AppliesTo"": [
+ ""Property Term""
+ ],
+ ""$DefaultValue"": ""true""
+ }
+ }
+}").ConfigureAwait(false);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSchemaWriterTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSchemaWriterTests.Async.cs
new file mode 100644
index 0000000000..8d6c3cdcce
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSchemaWriterTests.Async.cs
@@ -0,0 +1,182 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using System.Xml;
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Csdl.Serialization;
+using Microsoft.OData.Edm.Vocabularies;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Csdl.Serialization
+{
+ public partial class EdmModelCsdlSchemaWriterTests
+ {
+ #region Action/Function element attribute writer tests.
+ [Fact]
+ public async Task BoundOperationShouldWriteIsBoundEqualTrueAttribute_Async()
+ {
+ EdmAction action = new EdmAction("Default.Namespace", "Checkout", null /*returnType*/, true /*isBound*/, null /*entitySetPath*/);
+ action.AddParameter("param", EdmCoreModel.Instance.GetString(true));
+ await this.TestWriteActionElementHeaderMethodWithAsync(action, @" await writer.WriteActionElementHeaderAsync(action).ConfigureAwait(false), expected).ConfigureAwait(false);
+ }
+
+ private async Task TestWriteFunctionElementHeaderMethodWithAsync(EdmFunction function, string expected)
+ {
+ await this.EdmModelCsdlSchemaWriterTestAsync(async (writer) => await writer.WriteFunctionElementHeaderAsync(function).ConfigureAwait(false), expected).ConfigureAwait(false);
+ }
+ #endregion
+
+ #region OperationImport tests.
+ [Fact]
+ public async Task ValidateEntitySetAtttributeCorrectlyWritesOutEntitySet_Async()
+ {
+ EdmActionImport actionImport = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("Customers"));
+
+ await this.EdmModelCsdlSchemaWriterTestAsync(
+ async (writer) => await writer.WriteActionImportElementHeaderAsync(actionImport).ConfigureAwait(false),
+ @" await writer.WriteFunctionImportElementHeaderAsync(functionImport).ConfigureAwait(false),
+ @" await csdlSchemaWriter.WriteActionImportElementHeaderAsync(actionImport).ConfigureAwait(false);
+
+ var exception = await Assert.ThrowsAsync(errorTest).ConfigureAwait(false);
+ Assert.Equal(Strings.EdmModel_Validator_Semantic_OperationImportEntitySetExpressionIsInvalid(actionImport.Name), exception.Message);
+ }
+ #endregion
+
+ #region ActionImport tests.
+ [Fact]
+ public async Task ValidateCorrectActionImportNameAndActionAttributeValueWrittenCorrectly_Async()
+ {
+ EdmActionImport actionImport = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, null);
+
+ await this.EdmModelCsdlSchemaWriterTestAsync(
+ async (writer) => await writer.WriteActionImportElementHeaderAsync(actionImport).ConfigureAwait(false),
+ @" await writer.WriteFunctionImportElementHeaderAsync(functionImport).ConfigureAwait(false),
+ @" await writer.WriteFunctionImportElementHeaderAsync(functionImport).ConfigureAwait(false),
+ @" await writer.WriteComplexTypeElementHeaderAsync(complexType).ConfigureAwait(false), expected).ConfigureAwait(false);
+ }
+
+ internal async Task EdmModelCsdlSchemaWriterTestAsync(Func testAction, string expectedPayload)
+ {
+ XmlWriter xmlWriter;
+ MemoryStream memoryStream;
+ EdmModelCsdlSchemaWriter schemaWriter = CreateEdmModelCsdlSchemaWriterForAsync(out xmlWriter, out memoryStream);
+
+ await testAction(schemaWriter).ConfigureAwait(false);
+
+ await xmlWriter.FlushAsync().ConfigureAwait(false);
+
+ memoryStream.Seek(0, SeekOrigin.Begin);
+ StreamReader reader = new StreamReader(memoryStream);
+
+ // Removing xml header to make the baseline's more compact and focused on the test at hand.
+ string result = reader.ReadToEnd().Replace(@"", string.Empty);
+ Assert.Equal(expectedPayload, result);
+ }
+
+ private static EdmModelCsdlSchemaWriter CreateEdmModelCsdlSchemaWriterForErrorTestForAsync()
+ {
+ XmlWriter writer = null;
+ MemoryStream memoryStream = null;
+
+ return CreateEdmModelCsdlSchemaWriterForAsync(out writer, out memoryStream);
+ }
+
+ private static EdmModelCsdlSchemaWriter CreateEdmModelCsdlSchemaWriterForAsync(out XmlWriter xmlWriter, out MemoryStream memoryStream)
+ {
+ memoryStream = new MemoryStream();
+ IEdmModel model = new EdmModel();
+ model.SetEdmxVersion(new Version(4, 0));
+ var namespaceAliasMappings = model.GetNamespaceAliases();
+ Version edmxVersion = model.GetEdmxVersion();
+ xmlWriter = XmlWriter.Create(memoryStream, new XmlWriterSettings() { Async = true });
+ return new EdmModelCsdlSchemaXmlWriter(model, xmlWriter, edmxVersion, new CsdlXmlWriterSettings());
+ }
+ #endregion
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSchemaWriterTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSchemaWriterTests.cs
index ac0f5058da..b98570e0dd 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSchemaWriterTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSchemaWriterTests.cs
@@ -17,7 +17,7 @@ namespace Microsoft.OData.Edm.Tests.Csdl.Serialization
///
///Tests EdmModelCsdlSchemaWriter functionalities
///
- public class EdmModelCsdlSchemaWriterTests
+ public partial class EdmModelCsdlSchemaWriterTests
{
private static readonly EdmEntityContainer defaultContainer = new EdmEntityContainer("Default.NameSpace", "Container");
private static readonly EdmAction defaultCheckoutAction = new EdmAction("Default.NameSpace2", "CheckOut", null);
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSerializationVisitorTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSerializationVisitorTests.Async.cs
new file mode 100644
index 0000000000..0831a7ed27
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSerializationVisitorTests.Async.cs
@@ -0,0 +1,833 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+#if NETCOREAPP3_1
+using System.Text.Json;
+using System.Text.Encodings.Web;
+#endif
+using System.Xml;
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Csdl.CsdlSemantics;
+using Microsoft.OData.Edm.Csdl.Parsing.Ast;
+using Microsoft.OData.Edm.Csdl.Serialization;
+using Microsoft.OData.Edm.Vocabularies;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Csdl.Serialization
+{
+ public partial class EdmModelCsdlSerializationVisitorTests
+ {
+ #region Complex Type
+ [Fact]
+ public async Task VerifyComplexTypeWrittenCorrectly_Async()
+ {
+ // Arrange
+ EdmComplexType complexType = new EdmComplexType("NS", "Dimensions");
+ complexType.AddStructuralProperty("Height", EdmCoreModel.Instance.GetDecimal(6, 2, true));
+ complexType.AddStructuralProperty("Weight", EdmCoreModel.Instance.GetDecimal(6, null, true));
+ complexType.AddStructuralProperty("Length", EdmCoreModel.Instance.GetDecimal(null, null, false));
+ complexType.AddStructuralProperty("Breadth", EdmCoreModel.Instance.GetDecimal(6, 0, true));
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(v => v.VisitSchemaType(complexType),
+ @"
+
+
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(v => v.VisitSchemaType(complexType), @"{
+ ""Dimensions"": {
+ ""$Kind"": ""ComplexType"",
+ ""Height"": {
+ ""$Type"": ""Edm.Decimal"",
+ ""$Nullable"": true,
+ ""$Precision"": 6,
+ ""$Scale"": 2
+ },
+ ""Weight"": {
+ ""$Type"": ""Edm.Decimal"",
+ ""$Nullable"": true,
+ ""$Precision"": 6
+ },
+ ""Length"": {
+ ""$Type"": ""Edm.Decimal""
+ },
+ ""Breadth"": {
+ ""$Type"": ""Edm.Decimal"",
+ ""$Nullable"": true,
+ ""$Precision"": 6,
+ ""$Scale"": 0
+ }
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ #region Action
+ [Fact]
+ public async Task VerifySchemaWithActionsWrittenCorrectly_Async()
+ {
+ // Arrange
+ EdmSchema schema = new EdmSchema("NS");
+ EdmAction action = new EdmAction("NS", "DoStuff", EdmCoreModel.Instance.GetString(true), true, null);
+ action.AddParameter("param1", EdmCoreModel.Instance.GetString(true));
+ schema.AddSchemaElement(action);
+
+ action = new EdmAction("NS", "DoStuff", EdmCoreModel.Instance.GetString(true), true, null);
+ action.AddParameter("param1", EdmCoreModel.Instance.GetInt32(true));
+ schema.AddSchemaElement(action);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false),
+ @"
+
+
+
+
+
+
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false), @"{
+ ""NS"": {
+ ""DoStuff"": [
+ {
+ ""$Kind"": ""Action"",
+ ""$IsBound"": true,
+ ""$Parameter"": [
+ {
+ ""$Name"": ""param1"",
+ ""$Nullable"": true
+ }
+ ],
+ ""$ReturnType"": {
+ ""$Nullable"": true
+ }
+ },
+ {
+ ""$Kind"": ""Action"",
+ ""$IsBound"": true,
+ ""$Parameter"": [
+ {
+ ""$Name"": ""param1"",
+ ""$Type"": ""Edm.Int32"",
+ ""$Nullable"": true
+ }
+ ],
+ ""$ReturnType"": {
+ ""$Nullable"": true
+ }
+ }
+ ]
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ #region EntitySet
+ [Fact]
+ public async Task VerifyEntitySetWrittenCorrectly_Async()
+ {
+ // Arrange
+ IEdmEntityType entityType = new EdmEntityType("NS", "EntityType");
+ IEdmEntityContainer container = new EdmEntityContainer("NS", "Container");
+ EdmEntitySet entitySet = new EdmEntitySet(container, "Set", entityType);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { entitySet }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { entitySet }).ConfigureAwait(false),
+ @"{
+ ""Set"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.EntityType""
+ }
+}").ConfigureAwait(false);
+
+ // Act & Assert for non-indent JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { entitySet }).ConfigureAwait(false),
+ @"{""Set"":{""$Collection"":true,""$Type"":""NS.EntityType""}}", false).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyEntitySetWithAllInformationsWrittenCorrectly_Async()
+ {
+ // Arrange
+ var person = new EdmEntityType("NS", "Person");
+ var entityId = person.AddStructuralProperty("UserName", EdmCoreModel.Instance.GetString(false));
+ person.AddKeys(entityId);
+
+ var city = new EdmEntityType("NS", "City");
+ var cityId = city.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false));
+ city.AddKeys(cityId);
+
+ var countryOrRegion = new EdmEntityType("NS", "CountryOrRegion");
+ var countryId = countryOrRegion.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(false));
+ countryOrRegion.AddKeys(countryId);
+
+ var complex = new EdmComplexType("NS", "Address");
+ complex.AddStructuralProperty("Id", EdmCoreModel.Instance.GetInt32(false));
+ var navP = complex.AddUnidirectionalNavigation(
+ new EdmNavigationPropertyInfo()
+ {
+ Name = "City",
+ Target = city,
+ TargetMultiplicity = EdmMultiplicity.One,
+ });
+
+ var derivedComplex = new EdmComplexType("NS", "WorkAddress", complex);
+ var navP2 = derivedComplex.AddUnidirectionalNavigation(
+ new EdmNavigationPropertyInfo()
+ {
+ Name = "CountryOrRegion",
+ Target = countryOrRegion,
+ TargetMultiplicity = EdmMultiplicity.One,
+ });
+
+ person.AddStructuralProperty("HomeAddress", new EdmComplexTypeReference(complex, false));
+ person.AddStructuralProperty("WorkAddress", new EdmComplexTypeReference(complex, false));
+ person.AddStructuralProperty("Addresses", new EdmCollectionTypeReference(new EdmCollectionType(new EdmComplexTypeReference(complex, false))));
+
+ model.AddElement(person);
+ model.AddElement(city);
+ model.AddElement(countryOrRegion);
+ model.AddElement(complex);
+ model.AddElement(derivedComplex);
+
+ var entityContainer = new EdmEntityContainer("NS", "Container");
+ model.AddElement(entityContainer);
+ EdmEntitySet people = new EdmEntitySet(entityContainer, "People", person);
+ EdmEntitySet cities = new EdmEntitySet(entityContainer, "City", city);
+ EdmEntitySet countriesOrRegions = new EdmEntitySet(entityContainer, "CountryOrRegion", countryOrRegion);
+ people.AddNavigationTarget(navP, cities, new EdmPathExpression("HomeAddress/City"));
+ people.AddNavigationTarget(navP, cities, new EdmPathExpression("Addresses/City"));
+ people.AddNavigationTarget(navP2, countriesOrRegions, new EdmPathExpression("WorkAddress/NS.WorkAddress/CountryOrRegion"));
+ entityContainer.AddElement(people);
+ entityContainer.AddElement(cities);
+ entityContainer.AddElement(countriesOrRegions);
+
+ EdmTerm term = new EdmTerm("UI", "ReadOnly", EdmPrimitiveTypeKind.Boolean);
+ IEdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(people, term, new EdmBooleanConstant(true));
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ model.SetVocabularyAnnotation(annotation);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { people }).ConfigureAwait(false),
+ @"
+
+
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { people }).ConfigureAwait(false),
+ @"{
+ ""People"": {
+ ""$Collection"": true,
+ ""$Type"": ""NS.Person"",
+ ""$NavigationPropertyBinding"": {
+ ""Addresses/City"": ""City"",
+ ""HomeAddress/City"": ""City"",
+ ""WorkAddress/NS.WorkAddress/CountryOrRegion"": ""CountryOrRegion""
+ },
+ ""@UI.ReadOnly"": true
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ #region Singleton
+ [Fact]
+ public async Task VerifySingletonWrittenCorrectly_Async()
+ {
+ IEdmEntityType entityType = new EdmEntityType("NS", "EntityType");
+ IEdmEntityContainer container = new EdmEntityContainer("NS", "Container");
+ EdmSingleton singleton = new EdmSingleton(container, "Me", entityType);
+
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { singleton }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { singleton }).ConfigureAwait(false), @"{
+ ""Me"": {
+ ""$Type"": ""NS.EntityType""
+ }
+}").ConfigureAwait(false);
+
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { singleton }).ConfigureAwait(false),
+ @"{""Me"":{""$Type"":""NS.EntityType""}}", false).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifySingletonWithAnnotationWrittenCorrectly_Async()
+ {
+ var entityType = new EdmEntityType("NS", "EntityType");
+ var container = new EdmEntityContainer("NS", "Container");
+ var singleton = new EdmSingleton(container, "Me", entityType);
+ container.AddElement(singleton);
+ this.model.AddElement(entityType);
+ this.model.AddElement(container);
+
+ var enumType = new EdmEnumType("NS", "Permission", true);
+ var read = enumType.AddMember("Read", new EdmEnumMemberValue(0));
+ var write = enumType.AddMember("Write", new EdmEnumMemberValue(1));
+ var term = new EdmTerm("NS", "MyTerm", new EdmEnumTypeReference(enumType, true));
+ this.model.AddElement(term);
+
+ var enumMemberValue = new EdmEnumMemberExpression(read, write);
+ var annotation = new EdmVocabularyAnnotation(singleton, term, enumMemberValue);
+ annotation.SetSerializationLocation(model, EdmVocabularyAnnotationSerializationLocation.Inline);
+ this.model.SetVocabularyAnnotation(annotation);
+
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { singleton }).ConfigureAwait(false),
+ @"
+
+ NS.Permission/Read NS.Permission/Write
+
+").ConfigureAwait(false);
+
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new[] { singleton }).ConfigureAwait(false), @"{
+ ""Me"": {
+ ""$Type"": ""NS.EntityType"",
+ ""@NS.MyTerm"": ""Read,Write""
+ }
+}").ConfigureAwait(false);
+ }
+
+ #endregion
+
+ #region Action Import
+ [Fact]
+ public async Task VerifyActionImportWrittenCorrectly_Async()
+ {
+ // Arrange
+ var actionImport = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, null);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport }).ConfigureAwait(false),
+ @"{
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut""
+ }
+}").ConfigureAwait(false);
+
+ // Act & Assert for non-indent JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport }).ConfigureAwait(false),
+ @"{""Checkout"":{""$Kind"":""ActionImport"",""$Action"":""Default.NameSpace2.CheckOut""}}", false).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyTwoIdenticalNamedActionImportsWithNoEntitySetPropertyOnlyWrittenOnce_Async()
+ {
+ // Arrange
+ var actionImport = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, null);
+ var actionImport2 = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, null);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport, actionImport2 }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport, actionImport2 }).ConfigureAwait(false),
+ @"{
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut""
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyTwoIdenticalNamedActionImportsWithSameEntitySetOnlyWrittenOnce_Async()
+ {
+ // Arrange
+ var actionImport = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("Set"));
+ var actionImport2 = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("Set"));
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport, actionImport2 }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport, actionImport2 }).ConfigureAwait(false),
+ @"{
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut"",
+ ""$EntitySet"": ""Set""
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyTwoIdenticalNamedActionImportsWithSameEdmPathOnlyWrittenOnce_Async()
+ {
+ // Arrange
+ var actionImport = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("path1", "path2"));
+ var actionImport2 = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("path1", "path2"));
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport, actionImport2 }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImport, actionImport2 }).ConfigureAwait(false),
+ @"{
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut"",
+ ""$EntitySet"": ""path1/path2""
+ }
+}").ConfigureAwait(false);
+ }
+
+ ///
+ /// From OData Spec, it should be invalid to have overload action import.
+ /// Need to check with OData TC.
+ ///
+ [Fact]
+ public async Task VerifyIdenticalNamedActionImportsWithDifferentEntitySetPropertiesAreWritten_Async()
+ {
+ // Arrange
+ var actionImportOnSet = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("Set"));
+ var actionImportOnSet2 = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("Set2"));
+ var actionImportWithNoEntitySet = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, null);
+ var actionImportWithUniqueEdmPath = new EdmActionImport(defaultContainer, "Checkout", defaultCheckoutAction, new EdmPathExpression("path1", "path2"));
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImportOnSet, actionImportOnSet2, actionImportWithNoEntitySet, actionImportWithUniqueEdmPath }).ConfigureAwait(false),
+ @"
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { actionImportOnSet, actionImportOnSet2, actionImportWithNoEntitySet, actionImportWithUniqueEdmPath }).ConfigureAwait(false),
+ @"{
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut"",
+ ""$EntitySet"": ""Set""
+ },
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut"",
+ ""$EntitySet"": ""Set2""
+ },
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut""
+ },
+ ""Checkout"": {
+ ""$Kind"": ""ActionImport"",
+ ""$Action"": ""Default.NameSpace2.CheckOut"",
+ ""$EntitySet"": ""path1/path2""
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ #region Function Import
+ [Fact]
+ public async Task VerifyFunctionImportWrittenCorrectly_Async()
+ {
+ // Arrange
+ var functionImport = new EdmFunctionImport(defaultContainer, "GetStuff", defaultGetStuffFunction, null, true);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport }).ConfigureAwait(false),
+ @"{
+ ""GetStuff"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$IncludeInServiceDocument"": true
+ }
+}").ConfigureAwait(false);
+
+ // Act & Assert for non-indent JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport }).ConfigureAwait(false),
+ @"{""GetStuff"":{""$Kind"":""FunctionImport"",""$Function"":""Default.NameSpace2.GetStuff"",""$IncludeInServiceDocument"":true}}", false);
+ }
+
+ [Fact]
+ public async Task VerifyTwoIdenticalNamedFunctionImportsWithoutEntitySetValueOnlyWrittenOnce_Async()
+ {
+ // Arrange
+ var functionImport = new EdmFunctionImport(defaultContainer, "GetStuff", defaultGetStuffFunction, null, true);
+ var functionImport2 = new EdmFunctionImport(defaultContainer, "GetStuff", defaultGetStuffFunction, null, true);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport, functionImport2 }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport, functionImport2 }).ConfigureAwait(false),
+ @"{
+ ""GetStuff"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$IncludeInServiceDocument"": true
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyTwoIdenticalNamedFunctionImportsWithSameEntitySetValueOnlyWrittenOnce_Async()
+ {
+ // Arrange
+ var functionImport = new EdmFunctionImport(defaultContainer, "GetStuff", defaultGetStuffFunction, new EdmPathExpression("Set"), true);
+ var functionImport2 = new EdmFunctionImport(defaultContainer, "GetStuff", defaultGetStuffFunction, new EdmPathExpression("Set"), true);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport, functionImport2 }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport, functionImport2 }).ConfigureAwait(false),
+ @"{
+ ""GetStuff"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$EntitySet"": ""Set"",
+ ""$IncludeInServiceDocument"": true
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyTwoIdenticalNamedFunctionImportsWithSameEntitySetPathValueOnlyWrittenOnce_Async()
+ {
+ // Arrange
+ var functionImport = new EdmFunctionImport(defaultContainer, "GetStuff", defaultGetStuffFunction, new EdmPathExpression("path1", "path2"), true);
+ var functionImport2 = new EdmFunctionImport(defaultContainer, "GetStuff", defaultGetStuffFunction, new EdmPathExpression("path1", "path2"), true);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport, functionImport2 }).ConfigureAwait(false),
+ @"").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImport, functionImport2 }).ConfigureAwait(false),
+ @"{
+ ""GetStuff"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$EntitySet"": ""path1/path2"",
+ ""$IncludeInServiceDocument"": true
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyIdenticalNamedFunctionImportsWithDifferentEntitySetPropertiesAreWritten_Async()
+ {
+ // Arrange
+ var functionImportOnSet = new EdmFunctionImport(defaultContainer, "Checkout", defaultGetStuffFunction, new EdmPathExpression("Set"), false);
+ var functionImportOnSet2 = new EdmFunctionImport(defaultContainer, "Checkout", defaultGetStuffFunction, new EdmPathExpression("Set2"), false);
+ var functionmportWithNoEntitySet = new EdmFunctionImport(defaultContainer, "Checkout", defaultGetStuffFunction, null, true);
+ var functionImportWithUniqueEdmPath = new EdmFunctionImport(defaultContainer, "Checkout", defaultGetStuffFunction, new EdmPathExpression("path1", "path2"), false);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImportOnSet, functionImportOnSet2, functionmportWithNoEntitySet, functionImportWithUniqueEdmPath }).ConfigureAwait(false),
+ @"
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEntityContainerElementsAsync(new IEdmEntityContainerElement[] { functionImportOnSet, functionImportOnSet2, functionmportWithNoEntitySet, functionImportWithUniqueEdmPath }).ConfigureAwait(false),
+ @"{
+ ""Checkout"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$EntitySet"": ""Set""
+ },
+ ""Checkout"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$EntitySet"": ""Set2""
+ },
+ ""Checkout"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$IncludeInServiceDocument"": true
+ },
+ ""Checkout"": {
+ ""$Kind"": ""FunctionImport"",
+ ""$Function"": ""Default.NameSpace2.GetStuff"",
+ ""$EntitySet"": ""path1/path2""
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifySchemaWithFunctionsWrittenCorrectly_Async()
+ {
+ // Arrange
+ EdmSchema schema = new EdmSchema("NS");
+ EdmFunction function = new EdmFunction("NS", "GetStuff", EdmCoreModel.Instance.GetString(true), true, null, false);
+ function.AddParameter("param1", EdmCoreModel.Instance.GetString(true));
+ schema.AddSchemaElement(function);
+
+ function = new EdmFunction("NS", "GetStuff", EdmCoreModel.Instance.GetGuid(false), true, null, false);
+ function.AddParameter("param1", EdmCoreModel.Instance.GetString(true));
+ function.AddParameter("param2", EdmCoreModel.Instance.GetInt32(false));
+ schema.AddSchemaElement(function);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false),
+ @"
+
+
+
+
+
+
+
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false), @"{
+ ""NS"": {
+ ""GetStuff"": [
+ {
+ ""$Kind"": ""Function"",
+ ""$IsBound"": true,
+ ""$Parameter"": [
+ {
+ ""$Name"": ""param1"",
+ ""$Nullable"": true
+ }
+ ],
+ ""$ReturnType"": {
+ ""$Nullable"": true
+ }
+ },
+ {
+ ""$Kind"": ""Function"",
+ ""$IsBound"": true,
+ ""$Parameter"": [
+ {
+ ""$Name"": ""param1"",
+ ""$Nullable"": true
+ },
+ {
+ ""$Name"": ""param2"",
+ ""$Type"": ""Edm.Int32""
+ }
+ ],
+ ""$ReturnType"": {
+ ""$Type"": ""Edm.Guid""
+ }
+ }
+ ]
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ #region Out of line annotation
+ [Fact]
+ public async Task VerifyOutOfLineAnnotationWrittenCorrectly_Async()
+ {
+ // Arrange
+ EdmSchema schema = new EdmSchema("NS");
+
+ EdmComplexType complexType = new EdmComplexType("NS", "ComplexType");
+ EdmProperty property = complexType.AddStructuralProperty("Name", EdmPrimitiveTypeKind.String);
+
+ EdmTerm term = new EdmTerm("UI", "Thumbnail", EdmPrimitiveTypeKind.Binary);
+ IEdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(complexType, term, new EdmBinaryConstant(new byte[] { 0x4f, 0x44, 0x61, 0x74, 0x61 }));
+ schema.AddVocabularyAnnotation(annotation);
+
+ EdmTerm displayName = new EdmTerm("UI", "DisplayName", EdmPrimitiveTypeKind.Int32);
+ annotation = new EdmVocabularyAnnotation(complexType, displayName, new EdmIntegerConstant(42));
+ schema.AddVocabularyAnnotation(annotation);
+
+ annotation = new EdmVocabularyAnnotation(complexType, displayName, "Tablet", new EdmIntegerConstant(88));
+ schema.AddVocabularyAnnotation(annotation);
+
+ annotation = new EdmVocabularyAnnotation(property, displayName, "Tablet", new EdmIntegerConstant(42));
+ schema.AddVocabularyAnnotation(annotation);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false),
+ @"
+
+
+
+
+
+
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false), @"{
+ ""NS"": {
+ ""$Annotations"": {
+ ""NS.ComplexType"": {
+ ""@UI.Thumbnail"": ""T0RhdGE"",
+ ""@UI.DisplayName"": 42,
+ ""@UI.DisplayName#Tablet"": 88
+ },
+ ""NS.ComplexType/Name"": {
+ ""@UI.DisplayName#Tablet"": 42
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task VerifyOutOfLineAnnotationForEnumMemberWrittenCorrectly_Async()
+ {
+ // Arrange
+ EdmSchema schema = new EdmSchema("NS");
+
+ EdmEnumType enumType = new EdmEnumType("NS", "Color", EdmPrimitiveTypeKind.Int16, true);
+ var blue = enumType.AddMember("Blue", new EdmEnumMemberValue(0));
+
+ EdmTerm term = new EdmTerm("UI", "Thumbnail", EdmPrimitiveTypeKind.Binary);
+ IEdmVocabularyAnnotation annotation = new EdmVocabularyAnnotation(enumType, term, new EdmBinaryConstant(new byte[] { 0x4f, 0x44, 0x61, 0x74, 0x61 }));
+ schema.AddVocabularyAnnotation(annotation);
+
+ EdmTerm displayName = new EdmTerm("UI", "DisplayName", EdmPrimitiveTypeKind.Int32);
+ annotation = new EdmVocabularyAnnotation(blue, displayName, new EdmIntegerConstant(42));
+ schema.AddVocabularyAnnotation(annotation);
+
+ annotation = new EdmVocabularyAnnotation(blue, displayName, "Tablet", new EdmIntegerConstant(88));
+ schema.AddVocabularyAnnotation(annotation);
+
+ // Act & Assert for XML
+ await VisitAndVerifyXmlAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false),
+ @"
+
+
+
+
+
+
+
+").ConfigureAwait(false);
+
+ // Act & Assert for JSON
+ await VisitAndVerifyJsonAsync(async (v) => await v.VisitEdmSchemaAsync(schema, null).ConfigureAwait(false), @"{
+ ""NS"": {
+ ""$Annotations"": {
+ ""NS.Color"": {
+ ""@UI.Thumbnail"": ""T0RhdGE""
+ },
+ ""NS.Color/Blue"": {
+ ""@UI.DisplayName"": 42,
+ ""@UI.DisplayName#Tablet"": 88
+ }
+ }
+ }
+}").ConfigureAwait(false);
+ }
+ #endregion
+
+ internal async Task VisitAndVerifyXmlAsync(Action testAction, string expected, bool indent = true)
+ {
+ XmlWriter xmlWriter;
+ MemoryStream memStream;
+
+ Version edmxVersion = model.GetEdmxVersion();
+ memStream = new MemoryStream();
+ xmlWriter = XmlWriter.Create(memStream, new XmlWriterSettings()
+ {
+ Indent = indent,
+ ConformanceLevel = ConformanceLevel.Auto,
+ Async = true
+ });
+
+ CsdlXmlWriterSettings writerSettings = new CsdlXmlWriterSettings
+ {
+ LibraryCompatibility = EdmLibraryCompatibility.UseLegacyVariableCasing
+ };
+
+ var schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, xmlWriter, edmxVersion, writerSettings);
+ var visitor = new EdmModelCsdlSerializationVisitor(model, schemaWriter);
+
+ testAction(visitor);
+ await xmlWriter.FlushAsync().ConfigureAwait(false);
+
+ memStream.Seek(0, SeekOrigin.Begin);
+ StreamReader reader = new StreamReader(memStream);
+
+ // Remove extra xml header text as its not needed.
+ string result = reader.ReadToEnd().Replace(@"", string.Empty);
+ Assert.Equal(expected, result);
+ }
+
+ internal async Task VisitAndVerifyJsonAsync(Action testAction, string expected, bool indent = true, bool wrapper = true)
+ {
+#if NETCOREAPP3_1
+ Version edmxVersion = this.model.GetEdmxVersion();
+
+ using (MemoryStream memStream = new MemoryStream())
+ {
+ JsonWriterOptions options = new JsonWriterOptions
+ {
+ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
+ Indented = indent,
+ SkipValidation = false
+ };
+
+ using (Utf8JsonWriter jsonWriter = new Utf8JsonWriter(memStream, options))
+ {
+ var csdlSchemaWriter = new EdmModelCsdlSchemaJsonWriter(this.model, jsonWriter, edmxVersion);
+ var visitor = new EdmModelCsdlSerializationVisitor(this.model, csdlSchemaWriter);
+
+ // Use {} to wrapper the input.
+ if (wrapper)
+ {
+ jsonWriter.WriteStartObject();
+ }
+
+ testAction(visitor);
+
+ if (wrapper)
+ {
+ jsonWriter.WriteEndObject();
+ }
+
+ await jsonWriter.FlushAsync().ConfigureAwait(false);
+ }
+
+ memStream.Seek(0, SeekOrigin.Begin);
+ StreamReader reader = new StreamReader(memStream);
+
+ string result = reader.ReadToEnd();
+ Assert.Equal(expected, result);
+ }
+#endif
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSerializationVisitorTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSerializationVisitorTests.cs
index 89445c0849..451cb35cdd 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSerializationVisitorTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Serialization/EdmModelCsdlSerializationVisitorTests.cs
@@ -23,7 +23,7 @@ namespace Microsoft.OData.Edm.Tests.Csdl.Serialization
///
/// Unit tests of EdmModelCsdlSerializationVisitor. Aiming for whitebox coverage of these methods.
///
- public class EdmModelCsdlSerializationVisitorTests
+ public partial class EdmModelCsdlSerializationVisitorTests
{
private EdmModel model = new EdmModel();
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisActionsFunctionsRelationshipChangesAcceptanceTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisActionsFunctionsRelationshipChangesAcceptanceTests.Async.cs
new file mode 100644
index 0000000000..e40c6ae6b4
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisActionsFunctionsRelationshipChangesAcceptanceTests.Async.cs
@@ -0,0 +1,38 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Linq;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.ScenarioTests
+{
+ public partial class OasisActionsFunctionsRelationshipChangesAcceptanceTest
+ {
+
+ [Fact]
+ public async Task VerifyRepresentativeModelWrittenOutCorrectly_Async()
+ {
+ var builder = new StringBuilder();
+ using (var writer = XmlWriter.Create(builder, new XmlWriterSettings() { Async = true }))
+ {
+ var (result, errors) = await CsdlWriter.TryWriteCsdlAsync(this.TestModel.RepresentativeModel, writer, CsdlTarget.OData).ConfigureAwait(false);
+ Assert.True(result);
+ Assert.Empty(errors);
+ await writer.FlushAsync().ConfigureAwait(false);
+ }
+
+ string actual = builder.ToString();
+ var actualXml = XElement.Parse(actual);
+ var actualNormalized = actualXml.ToString();
+
+ Assert.Equal(DefaultTestModel.RepresentativeEdmxDocument, actualNormalized);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisActionsFunctionsRelationshipChangesAcceptanceTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisActionsFunctionsRelationshipChangesAcceptanceTests.cs
index 3d6cfe894a..4063ddfeb0 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisActionsFunctionsRelationshipChangesAcceptanceTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisActionsFunctionsRelationshipChangesAcceptanceTests.cs
@@ -16,7 +16,7 @@
namespace Microsoft.OData.Edm.Tests.ScenarioTests
{
- public class OasisActionsFunctionsRelationshipChangesAcceptanceTest
+ public partial class OasisActionsFunctionsRelationshipChangesAcceptanceTest
{
private static DefaultTestModel Model;
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisRelationshipChangesAcceptanceTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisRelationshipChangesAcceptanceTests.Async.cs
new file mode 100644
index 0000000000..c4714ecab9
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisRelationshipChangesAcceptanceTests.Async.cs
@@ -0,0 +1,37 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using System.Xml.Linq;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.ScenarioTests
+{
+ public partial class OasisRelationshipChangesAcceptanceTests
+ {
+ [Fact]
+ public async Task WriterShouldContinueToWork_Async()
+ {
+ var builder = new StringBuilder();
+ using (var writer = XmlWriter.Create(builder, new XmlWriterSettings() { Async = true }))
+ {
+ var (result, errors) = await CsdlWriter.TryWriteCsdlAsync(this.representativeModel, writer, CsdlTarget.OData).ConfigureAwait(false);
+ Assert.True(result);
+ Assert.Empty(errors);
+ await writer.FlushAsync().ConfigureAwait(false);
+ }
+
+ string actual = builder.ToString();
+ var actualXml = XElement.Parse(actual);
+ var actualNormalized = actualXml.ToString();
+
+ Assert.Equal(RepresentativeEdmxDocument, actualNormalized);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisRelationshipChangesAcceptanceTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisRelationshipChangesAcceptanceTests.cs
index 9a5109cf0a..054e573eb9 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisRelationshipChangesAcceptanceTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/ScenarioTests/OasisRelationshipChangesAcceptanceTests.cs
@@ -16,7 +16,7 @@
namespace Microsoft.OData.Edm.Tests.ScenarioTests
{
- public class OasisRelationshipChangesAcceptanceTests
+ public partial class OasisRelationshipChangesAcceptanceTests
{
private const string RepresentativeEdmxDocument = @"
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AlternateKeysVocabularyTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AlternateKeysVocabularyTests.Async.cs
new file mode 100644
index 0000000000..21feebb20a
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AlternateKeysVocabularyTests.Async.cs
@@ -0,0 +1,67 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Validation;
+using Microsoft.OData.Edm.Vocabularies.Community.V1;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Vocabularies
+{
+ public partial class AlternateKeysVocabularyTests
+ {
+ [Fact]
+ public async Task TestAlternateKeysVocabularyModel_Async()
+ {
+ const string expectedText = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+
+ var alternateKeysTerm = model.FindDeclaredTerm("OData.Community.Keys.V1.AlternateKeys");
+ Assert.NotNull(alternateKeysTerm);
+ Assert.Equal(AlternateKeysVocabularyModel.AlternateKeysTerm, alternateKeysTerm);
+ Assert.Equal("OData.Community.Keys.V1", alternateKeysTerm.Namespace);
+ Assert.Equal("AlternateKeys", alternateKeysTerm.Name);
+
+ StringWriter sw = new StringWriter();
+ IEnumerable errors;
+ using (var xw = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true, Encoding = Encoding.UTF8, Async = true }))
+ {
+ var (result, errorsAsync) = await model.TryWriteSchemaAsync(xw).ConfigureAwait(false);
+ Assert.True(result);
+
+ errors = errorsAsync; // Assign the async errors to the variable
+ }
+
+ string output = sw.ToString();
+
+ Assert.False(errors.Any(), "No Errors");
+ Assert.Equal(expectedText, output);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AlternateKeysVocabularyTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AlternateKeysVocabularyTests.cs
index 80198203f5..565713742b 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AlternateKeysVocabularyTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AlternateKeysVocabularyTests.cs
@@ -17,7 +17,7 @@
namespace Microsoft.OData.Edm.Tests.Vocabularies
{
- public class AlternateKeysVocabularyTests
+ public partial class AlternateKeysVocabularyTests
{
private readonly IEdmModel model = AlternateKeysVocabularyModel.Instance;
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AuthorizationVocabularyTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AuthorizationVocabularyTests.Async.cs
new file mode 100644
index 0000000000..5573667a36
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AuthorizationVocabularyTests.Async.cs
@@ -0,0 +1,152 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Xml;
+using Microsoft.OData.Edm.Csdl;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Vocabularies
+{
+ public partial class AuthorizationVocabularyTests
+ {
+ [Fact]
+ public async Task TestAuthorizationVocabularyModel_Async()
+ {
+ const string expectedText = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+
+ var sw = new StringWriter();
+ XmlWriterSettings settings = new XmlWriterSettings() { Async = true };
+ settings.Indent = true;
+ settings.Encoding = System.Text.Encoding.UTF8;
+
+ XmlWriter xw = XmlWriter.Create(sw, settings);
+ var (_, errors) = await this._authorizationModel.TryWriteSchemaAsync(xw).ConfigureAwait(false);
+ await xw.FlushAsync().ConfigureAwait(false);
+
+#if NETCOREAPP1_1
+ xw.Dispose();
+#else
+ xw.Close();
+#endif
+ string output = sw.ToString();
+
+ Assert.True(!errors.Any(), "No Errors");
+ Assert.Equal(expectedText, output);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AuthorizationVocabularyTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AuthorizationVocabularyTests.cs
index 02e9bf006e..9dc2e63166 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AuthorizationVocabularyTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/AuthorizationVocabularyTests.cs
@@ -18,7 +18,7 @@ namespace Microsoft.OData.Edm.Tests.Vocabularies
///
/// Test authorization vocabulary
///
- public class AuthorizationVocabularyTests
+ public partial class AuthorizationVocabularyTests
{
private readonly IEdmModel _authorizationModel = AuthorizationVocabularyModel.Instance;
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CapabilitiesVocabularyTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CapabilitiesVocabularyTests.Async.cs
new file mode 100644
index 0000000000..e3673981ce
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CapabilitiesVocabularyTests.Async.cs
@@ -0,0 +1,860 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Xml;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Vocabularies
+{
+ public partial class CapabilitiesVocabularyTests
+ {
+ [Fact]
+ public async Task TestCapabilitiesVocabularyModel_Async()
+ {
+ #region Expected Vocabulary Model
+ const string expectedText = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Core.Description
+ Core.LongDescription
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Core.Description
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Core.Description
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Core.Description
+
+
+
+
+
+
+
+
+
+
+
+
+ Core.Description
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+ #endregion
+
+ StringWriter sw = new StringWriter();
+ XmlWriterSettings settings = new XmlWriterSettings() { Async = true };
+ settings.Indent = true;
+ settings.Encoding = System.Text.Encoding.UTF8;
+
+ XmlWriter xw = XmlWriter.Create(sw, settings);
+ var (_, errors) = await this.capVocModel.TryWriteSchemaAsync(xw).ConfigureAwait(false);
+ await xw.FlushAsync().ConfigureAwait(false);
+#if NETCOREAPP1_1
+ xw.Dispose();
+#else
+ xw.Close();
+#endif
+ string output = sw.ToString();
+ Assert.True(!errors.Any(), "No Errors");
+ Assert.Equal(expectedText, output);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CapabilitiesVocabularyTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CapabilitiesVocabularyTests.cs
index 4b6cbfef86..28a943b359 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CapabilitiesVocabularyTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CapabilitiesVocabularyTests.cs
@@ -21,7 +21,7 @@ namespace Microsoft.OData.Edm.Tests.Vocabularies
///
/// Test capabilities vocabulary
///
- public class CapabilitiesVocabularyTests
+ public partial class CapabilitiesVocabularyTests
{
private readonly IEdmModel capVocModel = CapabilitiesVocabularyModel.Instance;
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CommunityVocabularyTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CommunityVocabularyTests.Async.cs
new file mode 100644
index 0000000000..2430ff9c47
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CommunityVocabularyTests.Async.cs
@@ -0,0 +1,48 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using System.Text;
+using Microsoft.OData.Edm.Csdl;
+using Microsoft.OData.Edm.Validation;
+using Xunit;
+using System.Threading.Tasks;
+
+namespace Microsoft.OData.Edm.Tests.Vocabularies
+{
+ public partial class CommunityVocabularyTests
+ {
+
+ [Fact]
+ public async Task TestCommunityVocabularyModel_Async()
+ {
+ const string expectedUrlEscape = @"
+
+
+
+
+";
+
+ var sw = new StringWriter();
+ IEnumerable errors;
+ using (var xw = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true, Encoding = Encoding.UTF8, Async = true }))
+ {
+ var (result, errorsAsync) = await model.TryWriteSchemaAsync(xw).ConfigureAwait(false);
+ Assert.True(result);
+
+ errors = errorsAsync;
+ }
+
+ Assert.False(errors.Any(), "No Errors");
+
+ string output = sw.ToString();
+ Assert.True(expectedUrlEscape == output, "expected Community schema not matching");
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CommunityVocabularyTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CommunityVocabularyTests.cs
index bce588e686..71f145d50f 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CommunityVocabularyTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CommunityVocabularyTests.cs
@@ -17,7 +17,7 @@
namespace Microsoft.OData.Edm.Tests.Vocabularies
{
- public class CommunityVocabularyTests
+ public partial class CommunityVocabularyTests
{
private readonly IEdmModel model = CommunityVocabularyModel.Instance;
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CoreVocabularyTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CoreVocabularyTests.Async.cs
new file mode 100644
index 0000000000..204caf451c
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CoreVocabularyTests.Async.cs
@@ -0,0 +1,469 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Xml;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Vocabularies
+{
+ public partial class CoreVocabularyTests
+ {
+ [Fact]
+ public async Task TestBaseCoreVocabularyModel_Async()
+ {
+ #region Expected Text
+ const string expectedText = @"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+ #endregion
+
+ var s = coreVocModel.FindDeclaredTerm("Org.OData.Core.V1.OptimisticConcurrency");
+ Assert.NotNull(s);
+ Assert.Equal("Org.OData.Core.V1", s.Namespace);
+ Assert.Equal("OptimisticConcurrency", s.Name);
+
+ var type = s.Type;
+ Assert.Equal("Collection(Edm.PropertyPath)", type.FullName());
+ Assert.Equal(EdmTypeKind.Collection, type.Definition.TypeKind);
+
+ var descriptionTerm = coreVocModel.FindTerm("Org.OData.Core.V1.Description");
+ Assert.NotNull(descriptionTerm);
+ var descriptionType = descriptionTerm.Type.Definition as IEdmPrimitiveType;
+ Assert.NotNull(descriptionType);
+ Assert.Equal(EdmPrimitiveTypeKind.String, descriptionType.PrimitiveKind);
+
+ var longDescriptionTerm = coreVocModel.FindTerm("Org.OData.Core.V1.LongDescription");
+ Assert.NotNull(longDescriptionTerm);
+ var longDescriptionType = longDescriptionTerm.Type.Definition as IEdmPrimitiveType;
+ Assert.NotNull(longDescriptionType);
+ Assert.Equal(EdmPrimitiveTypeKind.String, longDescriptionType.PrimitiveKind);
+
+ var isLanguageDependentTerm = coreVocModel.FindTerm("Org.OData.Core.V1.IsLanguageDependent");
+ Assert.NotNull(isLanguageDependentTerm);
+ var isLanguageDependentType = isLanguageDependentTerm.Type.Definition as IEdmTypeDefinition;
+ Assert.NotNull(isLanguageDependentType);
+ Assert.Equal(EdmPrimitiveTypeKind.Boolean, isLanguageDependentType.UnderlyingType.PrimitiveKind);
+
+ var requiresExplicitBindingTerm = coreVocModel.FindTerm("Org.OData.Core.V1.RequiresExplicitBinding");
+ Assert.NotNull(requiresExplicitBindingTerm);
+ var requiresExplicitBindingType = requiresExplicitBindingTerm.Type.Definition as IEdmTypeDefinition;
+ Assert.NotNull(requiresExplicitBindingType);
+ Assert.Equal(EdmPrimitiveTypeKind.Boolean, requiresExplicitBindingType.UnderlyingType.PrimitiveKind);
+
+ var explicitOperationBindingsTerm = coreVocModel.FindTerm("Org.OData.Core.V1.ExplicitOperationBindings");
+ Assert.NotNull(explicitOperationBindingsTerm);
+ var explicitOperationBindingsType = explicitOperationBindingsTerm.Type.Definition;
+ Assert.NotNull(explicitOperationBindingsType);
+ Assert.Equal("Collection(Org.OData.Core.V1.QualifiedBoundOperationName)", explicitOperationBindingsType.FullTypeName());
+ Assert.Equal(EdmTypeKind.Collection, explicitOperationBindingsType.TypeKind);
+
+ var qualifiedBoundOperationNameType = coreVocModel.FindType("Org.OData.Core.V1.QualifiedBoundOperationName");
+ Assert.NotNull(qualifiedBoundOperationNameType);
+ Assert.Equal(qualifiedBoundOperationNameType, explicitOperationBindingsType.AsElementType());
+
+ var sw = new StringWriter();
+ var settings = new XmlWriterSettings()
+ {
+ Indent = true,
+ Encoding = System.Text.Encoding.UTF8,
+ Async = true
+ };
+
+ XmlWriter xw = XmlWriter.Create(sw, settings);
+ var (_, errors) = await coreVocModel.TryWriteSchemaAsync(xw).ConfigureAwait(false);
+ await xw.FlushAsync().ConfigureAwait(false);
+#if NETCOREAPP1_1
+ xw.Dispose();
+#else
+ xw.Close();
+#endif
+ string output = sw.ToString();
+ Assert.False(errors.Any(), "No Errors");
+ Assert.Equal(expectedText, output);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CoreVocabularyTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CoreVocabularyTests.cs
index 11c095062f..3214040ea2 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CoreVocabularyTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/CoreVocabularyTests.cs
@@ -18,7 +18,7 @@ namespace Microsoft.OData.Edm.Tests.Vocabularies
///
/// Test core vocabulary
///
- public class CoreVocabularyTests
+ public partial class CoreVocabularyTests
{
private readonly IEdmModel coreVocModel = CoreVocabularyModel.Instance;
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/ValidationVocabularyTests.Async.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/ValidationVocabularyTests.Async.cs
new file mode 100644
index 0000000000..db24f1a53e
--- /dev/null
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/ValidationVocabularyTests.Async.cs
@@ -0,0 +1,137 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using Microsoft.OData.Edm.Csdl;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Xml;
+using Xunit;
+
+namespace Microsoft.OData.Edm.Tests.Vocabularies
+{
+ public partial class ValidationVocabularyTests
+ {
+ [Fact]
+ public async Task TestValidationVocabularyModel_Async()
+ {
+ #region Expected Text
+ const string expectedText = @"
+
+
+
+
+
+
+
+
+
+
+ Core.SymbolicName
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Validation.Exclusive
+
+
+
+
+
+
+
+ Validation.Exclusive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+";
+ #endregion
+
+ var sw = new StringWriter();
+ var settings = new XmlWriterSettings()
+ {
+ Indent = true,
+ Encoding = System.Text.Encoding.UTF8,
+ Async = true
+ };
+
+ XmlWriter xw = XmlWriter.Create(sw, settings);
+ var (_, errors) = await this._validationModel.TryWriteSchemaAsync(xw).ConfigureAwait(false);
+ await xw.FlushAsync().ConfigureAwait(false);
+#if NETCOREAPP1_1
+ xw.Dispose();
+#else
+ xw.Close();
+#endif
+ string output = sw.ToString();
+
+ Assert.True(!errors.Any(), "No Errors");
+ Assert.Equal(expectedText, output);
+ }
+ }
+}
diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/ValidationVocabularyTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/ValidationVocabularyTests.cs
index 9f71e681e9..c6e0524a8b 100644
--- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/ValidationVocabularyTests.cs
+++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Vocabularies/ValidationVocabularyTests.cs
@@ -20,7 +20,7 @@ namespace Microsoft.OData.Edm.Tests.Vocabularies
///
/// Test validation vocabulary
///
- public class ValidationVocabularyTests
+ public partial class ValidationVocabularyTests
{
private readonly IEdmModel _validationModel = ValidationVocabularyModel.Instance;
@@ -140,7 +140,7 @@ public void TestValidationVocabularyModel()
}
[Fact]
- public void TestOpenTypePropertyConstraint()
+ public void TestOpenTypePropertyConstraint()
{
var modelCsdl = @"