diff --git a/src/Microsoft.OData.Core/ErrorUtils.cs b/src/Microsoft.OData.Core/ErrorUtils.cs
index 30995dc4e0..e6a67fb238 100644
--- a/src/Microsoft.OData.Core/ErrorUtils.cs
+++ b/src/Microsoft.OData.Core/ErrorUtils.cs
@@ -6,6 +6,7 @@
using System;
using System.Diagnostics;
+using System.Threading.Tasks;
using System.Xml;
using Microsoft.OData.Metadata;
@@ -57,12 +58,31 @@ internal static void WriteXmlError(XmlWriter writer, ODataError error, bool incl
}
///
- /// Write an error message.
+ /// Asynchronously writes an error message.
+ ///
+ /// The Xml writer to write to.
+ /// The error instance to write.
+ /// A flag indicating whether error details should be written (in debug mode only) or not.
+ /// The maximum number of nested inner errors to allow.
+ internal static async Task WriteXmlErrorAsync(XmlWriter writer, ODataError error, bool includeDebugInformation, int maxInnerErrorDepth)
+ {
+ Debug.Assert(writer != null, "writer != null");
+ Debug.Assert(error != null, "error != null");
+
+ string code, message;
+ ErrorUtils.GetErrorDetails(error, out code, out message);
+
+ ODataInnerError innerError = includeDebugInformation ? error.InnerError : null;
+ await WriteXmlErrorAsync(writer, code, message, innerError, maxInnerErrorDepth).ConfigureAwait(false);
+ }
+
+ ///
+ /// Writes an error message.
///
/// The Xml writer to write to.
- /// The code of the error.
- /// The message of the error.
- /// Inner error details that will be included in debug mode (if present).
+ /// The error code.
+ /// The error message.
+ /// The inner error details of the error that will be included in debug mode (if present).
/// The maximum number of nested inner errors to allow.
private static void WriteXmlError(XmlWriter writer, string code, string message, ODataInnerError innerError, int maxInnerErrorDepth)
{
@@ -88,6 +108,38 @@ private static void WriteXmlError(XmlWriter writer, string code, string message,
writer.WriteEndElement();
}
+ ///
+ /// Asynchronously writes an error message.
+ ///
+ /// The Xml writer to write to.
+ /// The error code.
+ /// The error message.
+ /// The inner error details of the error that will be included in debug mode (if present).
+ /// The maximum number of nested inner errors to allow.
+ private static async Task WriteXmlErrorAsync(XmlWriter writer, string code, string message, ODataInnerError innerError, int maxInnerErrorDepth)
+ {
+ Debug.Assert(writer != null, "writer != null");
+ Debug.Assert(code != null, "code != null");
+ Debug.Assert(message != null, "message != null");
+
+ //
+ await writer.WriteStartElementAsync(ODataMetadataConstants.ODataMetadataNamespacePrefix, ODataMetadataConstants.ODataErrorElementName, ODataMetadataConstants.ODataMetadataNamespace).ConfigureAwait(false);
+
+ // code
+ await writer.WriteElementStringAsync(ODataMetadataConstants.ODataMetadataNamespacePrefix, ODataMetadataConstants.ODataErrorCodeElementName, ODataMetadataConstants.ODataMetadataNamespace, code).ConfigureAwait(false);
+
+ // error message
+ await writer.WriteElementStringAsync(ODataMetadataConstants.ODataMetadataNamespacePrefix, ODataMetadataConstants.ODataErrorMessageElementName, ODataMetadataConstants.ODataMetadataNamespace, message).ConfigureAwait(false);
+
+ if (innerError != null)
+ {
+ await WriteXmlInnerErrorAsync(writer, innerError, ODataMetadataConstants.ODataInnerErrorElementName, /* recursionDepth */ 0, maxInnerErrorDepth).ConfigureAwait(false);
+ }
+
+ //
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+ }
+
///
/// Writes the inner exception information in debug mode.
///
@@ -142,5 +194,60 @@ private static void WriteXmlInnerError(XmlWriter writer, ODataInnerError innerEr
// or
writer.WriteEndElement();
}
+
+ ///
+ /// Asynchronously writes the inner exception information in debug mode.
+ ///
+ /// The Xml writer to write to.
+ /// The inner error to write.
+ /// The local name of the element representing the inner error.
+ /// The number of times this method has been called recursively.
+ /// The maximum number of nested inner errors to allow.
+ private static async Task WriteXmlInnerErrorAsync(XmlWriter writer, ODataInnerError innerError, string innerErrorElementName, int recursionDepth, int maxInnerErrorDepth)
+ {
+ Debug.Assert(writer != null, "writer != null");
+
+ recursionDepth++;
+ if (recursionDepth > maxInnerErrorDepth)
+ {
+#if ODATA_CORE
+ throw new ODataException(Strings.ValidationUtils_RecursionDepthLimitReached(maxInnerErrorDepth));
+#else
+ throw new ODataException(Microsoft.OData.Service.Strings.BadRequest_DeepRecursion(maxInnerErrorDepth));
+#endif
+ }
+
+ // or
+ await writer.WriteStartElementAsync(ODataMetadataConstants.ODataMetadataNamespacePrefix, innerErrorElementName, ODataMetadataConstants.ODataMetadataNamespace).ConfigureAwait(false);
+
+ //// NOTE: we add empty elements if no information is provided for the message, error type and stack trace
+ //// to stay compatible with Astoria.
+
+ // ...
+ string errorMessage = innerError.Message ?? String.Empty;
+ await writer.WriteStartElementAsync(null, ODataMetadataConstants.ODataInnerErrorMessageElementName, ODataMetadataConstants.ODataMetadataNamespace).ConfigureAwait(false);
+ await writer.WriteStringAsync(errorMessage).ConfigureAwait(false);
+ await writer.WriteEndElementAsync();
+
+ // ...
+ string errorType = innerError.TypeName ?? string.Empty;
+ await writer.WriteStartElementAsync(null, ODataMetadataConstants.ODataInnerErrorTypeElementName, ODataMetadataConstants.ODataMetadataNamespace).ConfigureAwait(false);
+ await writer.WriteStringAsync(errorType).ConfigureAwait(false);
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+
+ // ...
+ string errorStackTrace = innerError.StackTrace ?? String.Empty;
+ await writer.WriteStartElementAsync(null, ODataMetadataConstants.ODataInnerErrorStackTraceElementName, ODataMetadataConstants.ODataMetadataNamespace).ConfigureAwait(false);
+ await writer.WriteStringAsync(errorStackTrace).ConfigureAwait(false);
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+
+ if (innerError.InnerError != null)
+ {
+ await WriteXmlInnerErrorAsync(writer, innerError.InnerError, ODataMetadataConstants.ODataInnerErrorInnerErrorElementName, recursionDepth, maxInnerErrorDepth).ConfigureAwait(false);
+ }
+
+ // or
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/Microsoft.OData.Core/Metadata/ODataMetadataWriterUtils.cs b/src/Microsoft.OData.Core/Metadata/ODataMetadataWriterUtils.cs
index 068991f9c1..79d4670359 100644
--- a/src/Microsoft.OData.Core/Metadata/ODataMetadataWriterUtils.cs
+++ b/src/Microsoft.OData.Core/Metadata/ODataMetadataWriterUtils.cs
@@ -10,6 +10,7 @@ namespace Microsoft.OData.Metadata
using System.Diagnostics;
using System.IO;
using System.Text;
+ using System.Threading.Tasks;
using System.Xml;
#endregion Namespaces
@@ -58,6 +59,18 @@ internal static void WriteError(XmlWriter writer, ODataError error, bool include
ErrorUtils.WriteXmlError(writer, error, includeDebugInformation, maxInnerErrorDepth);
}
+ ///
+ /// Asynchronously writes an error message.
+ ///
+ /// The Xml writer to write to.
+ /// The error instance to write.
+ /// A flag indicating whether error details should be written (in debug mode only) or not.
+ /// The maximum number of nested inner errors to allow.
+ internal static Task WriteErrorAsync(XmlWriter writer, ODataError error, bool includeDebugInformation, int maxInnerErrorDepth)
+ {
+ return ErrorUtils.WriteXmlErrorAsync(writer, error, includeDebugInformation, maxInnerErrorDepth);
+ }
+
///
/// Creates a new XmlWriterSettings instance using the encoding.
///
diff --git a/src/Microsoft.OData.Core/ODataMetadataJsonOutputContext.cs b/src/Microsoft.OData.Core/ODataMetadataJsonOutputContext.cs
index 39cb190fd3..dea1e613ce 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()
+ {
+ CsdlJsonWriterSettings writerSettings = new CsdlJsonWriterSettings
+ {
+ IsIeee754Compatible = MessageWriterSettings.IsIeee754Compatible,
+ };
+
+ (bool success, IEnumerable 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 ad554f6cb9..99b3b7d4f2 100644
--- a/src/Microsoft.OData.Core/ODataMetadataOutputContext.cs
+++ b/src/Microsoft.OData.Core/ODataMetadataOutputContext.cs
@@ -100,16 +100,13 @@ internal Task FlushAsync()
/// be included in the payload. This should only be used in debug scenarios.
///
/// Task which represents the pending write operation.
- internal override Task WriteInStreamErrorAsync(ODataError error, bool includeDebugInformation)
+ internal override async Task WriteInStreamErrorAsync(ODataError error, bool includeDebugInformation)
{
this.AssertAsynchronous();
- return TaskUtils.GetTaskForSynchronousOperationReturningTask(
- () =>
- {
- ODataMetadataWriterUtils.WriteError(this.xmlWriter, error, includeDebugInformation, this.MessageWriterSettings.MessageQuotas.MaxNestingDepth);
- return this.FlushAsync();
- });
+ await ODataMetadataWriterUtils.WriteErrorAsync(this.xmlWriter, error, includeDebugInformation, this.MessageWriterSettings.MessageQuotas.MaxNestingDepth).ConfigureAwait(false);
+
+ await this.FlushAsync().ConfigureAwait(false);
}
///
@@ -117,16 +114,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);
}
///
@@ -280,5 +273,26 @@ private void WriteMetadataDocumentImplementation()
throw new ODataException(Strings.ODataMetadataOutputContext_ErrorWritingMetadata(builder.ToString()));
}
}
+
+ private async Task WriteMetadataDocumentImplementationAsync()
+ {
+ Tuple> result = await CsdlWriter.TryWriteCsdlAsync(this.Model, this.xmlWriter, CsdlTarget.OData).ConfigureAwait(false);
+ bool success = result.Item1;
+
+ if (!success)
+ {
+ IEnumerable errors = result.Item2;
+
+ 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 99ceec418c..ecbc7961e6 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()
+ {
+ EdmModelReferenceElementsJsonVisitor 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();
}
+
+ ///
+ /// Asynchronously writes the end of the CSDL JSON document.
+ ///
+ /// A task that flushing the JSON writer (jsonWriter) asynchronously.
+ private async Task WriteCsdlEndAsync()
+ {
+ // End of the CSDL JSON document.
+ this.jsonWriter.WriteEndObject();
+
+ await this.jsonWriter.FlushAsync().ConfigureAwait(false);
+ }
}
}
#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 466bdcf8fd..bad4b16e43 100644
--- a/src/Microsoft.OData.Edm/Csdl/CsdlWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/CsdlWriter.cs
@@ -11,9 +11,10 @@
#if NETSTANDARD2_0
using System.Text.Json;
#endif
+using System.Threading.Tasks;
using System.Xml;
using Microsoft.OData.Edm.Csdl.Serialization;
-
+using Microsoft.OData.Edm.Helpers;
using Microsoft.OData.Edm.Validation;
namespace Microsoft.OData.Edm.Csdl
@@ -55,6 +56,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 Edm errors 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.
///
@@ -81,6 +93,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 Edm errors 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
///
@@ -109,6 +146,30 @@ 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.
+ /// A task with a value indicating whether serialization was successful.
+ public static async Task>> TryWriteCsdlAsync(IEdmModel model, XmlWriter writer, CsdlTarget target)
+ {
+ EdmUtil.CheckArgumentNull(model, "model");
+ EdmUtil.CheckArgumentNull(writer, "writer");
+
+ Version edmxVersion;
+ if (!VerifyAndGetVersion(model, out edmxVersion, out IEnumerable errors))
+ {
+ return Tuple.Create(false, errors);
+ }
+
+ CsdlWriter csdlWriter = new CsdlXmlWriter(model, writer, edmxVersion, target);
+ await csdlWriter.WriteCsdlAsync().ConfigureAwait(false);
+
+ return Tuple.Create(true, Enumerable.Empty());
+ }
+
///
/// Write CSDL output.
///
@@ -117,6 +178,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 TaskUtils.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 abf5026c2a..34c9f3e78a 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;
@@ -58,6 +59,25 @@ protected override void WriteCsdl()
}
}
+ ///
+ /// Asynchronously writes 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();
@@ -69,6 +89,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();
@@ -81,22 +112,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 writes 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;
@@ -126,11 +189,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);
+ 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.
@@ -138,15 +235,32 @@ private void WriteSchemas()
Version edmVersion = this.model.GetEdmVersion() ?? EdmConstants.EdmVersionLatest;
foreach (EdmSchema schema in this.schemas)
{
- var schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, this.writer, edmVersion);
+ EdmModelCsdlSchemaXmlWriter schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, this.writer, edmVersion);
visitor = new EdmModelCsdlSerializationVisitor(this.model, schemaWriter);
visitor.VisitEdmSchema(schema, this.model.GetNamespacePrefixMappings());
}
}
+ private async Task WriteSchemasAsync()
+ {
+ EdmModelCsdlSerializationVisitor visitor;
+ Version edmVersion = this.model.GetEdmVersion() ?? EdmConstants.EdmVersionLatest;
+ foreach (EdmSchema schema in this.schemas)
+ {
+ EdmModelCsdlSchemaXmlWriter schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, this.writer, edmVersion);
+ 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 64421d47ad..d80851a494 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>> TryWriteSchemaAsync(this IEdmModel model, XmlWriter writer)
+ {
+ return TryWriteSchemaAsync(model, x => writer, singleFileExpected: 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>> TryWriteSchemaAsync(this IEdmModel model, Func writerProvider)
+ {
+ return TryWriteSchemaAsync(model, writerProvider, singleFileExpected: 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>> TryWriteSchemaAsync(IEdmModel model, Func writerProvider, bool singleFileExpected)
+ {
+ EdmUtil.CheckArgumentNull(model, "model");
+ EdmUtil.CheckArgumentNull(writerProvider, "writerProvider");
+
+ IEnumerable errors = model.GetSerializationErrors();
+ if (errors.FirstOrDefault() != null)
+ {
+ return Tuple.Create(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 Tuple.Create(false, errors);
+ }
+
+ if (!schemas.Any())
+ {
+ errors = new EdmError[] { new EdmError(new CsdlLocation(0, 0), EdmErrorCode.NoSchemasProduced, Edm.Strings.Serializer_NoSchemasProduced) };
+ return Tuple.Create(false, errors);
+ }
+
+ await WriteSchemasAsync(model, schemas, writerProvider).ConfigureAwait(false);
+
+ errors = Enumerable.Empty();
+ return Tuple.Create(true, errors);
+ }
+
internal static void WriteSchemas(IEdmModel model, IEnumerable schemas, Func writerProvider)
{
EdmModelCsdlSerializationVisitor visitor;
@@ -81,11 +134,27 @@ internal static void WriteSchemas(IEdmModel model, IEnumerable schema
XmlWriter writer = writerProvider(schema.Namespace);
if (writer != null)
{
- var schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, writer, edmVersion);
+ EdmModelCsdlSchemaXmlWriter schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, writer, edmVersion);
visitor = new EdmModelCsdlSerializationVisitor(model, schemaWriter);
visitor.VisitEdmSchema(schema, model.GetNamespacePrefixMappings());
}
}
}
+
+ 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)
+ {
+ EdmModelCsdlSchemaXmlWriter schemaWriter = new EdmModelCsdlSchemaXmlWriter(model, writer, edmVersion);
+ visitor = new EdmModelCsdlSerializationVisitor(model, schemaWriter);
+ await visitor.VisitEdmSchemaAsync(schema, model.GetNamespacePrefixMappings()).ConfigureAwait(false);
+ }
+ }
+ }
}
}
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.Async.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.Async.cs
new file mode 100644
index 0000000000..7cd63d11a5
--- /dev/null
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.Async.cs
@@ -0,0 +1,1722 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+#if NETSTANDARD2_0
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+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;
+using Microsoft.OData.Edm.Vocabularies.V1;
+
+namespace Microsoft.OData.Edm.Csdl.Serialization
+{
+ ///
+ /// OData Common Schema Definition Language (CSDL) JSON writer
+ ///
+ internal partial class EdmModelCsdlSchemaJsonWriter : EdmModelCsdlSchemaWriter
+ {
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes include element end.
+ ///
+ /// The Edm include information.
+ /// Task representing asynchronous
+ internal override Task WriteIncludeElementEndAsync(IEdmInclude include)
+ {
+ this.jsonWriter.WriteEndObject();
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// 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 != 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 != null)
+ {
+ string[] appliesTo = term.AppliesTo.Split(',');
+ this.jsonWriter.WritePropertyName("$AppliesTo");
+ this.jsonWriter.WriteStartArray();
+ foreach (string 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);
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes schema object.
+ ///
+ /// 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)
+ {
+ // 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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 != null)
+ {
+ this.jsonWriter.WriteRequiredProperty(annotation.Name, EdmValueWriter.PrimitiveValueAsXml((IEdmPrimitiveValue)annotation.Value));
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// 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)
+ {
+ IEdmPrimitiveValue edmValue = (IEdmPrimitiveValue)annotation.Value;
+ if (edmValue != null)
+ {
+ this.jsonWriter.WriteStringValue(((IEdmStringValue)edmValue).Value);
+ }
+
+ return Task.CompletedTask;
+ }
+
+ ///
+ /// 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)
+ {
+ // 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes type attribute
+ ///
+ /// The Edm type reference.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteTypeAttributeAsync(IEdmTypeReference typeReference)
+ {
+ return WriteTypeReferenceAsync(typeReference);
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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))
+ {
+ EdmPropertyConstructor 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);
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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 != 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;
+ }
+
+ ///
+ /// 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.
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes DateTimeOffset 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes IsOf 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;
+ }
+
+ ///
+ /// Asynchronously writes 'IsOf' 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes navigation property bindings begin
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes navigation property bindings end
+ ///
+ /// 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;
+ }
+
+ ///
+ /// Asynchronously writes the navigation property binding member in navigation property binding 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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;
+ }
+
+ ///
+ /// 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 != 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;
+ }
+ }
+}
+#endif
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs
index 5944ae5749..3d369b40f3 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs
@@ -22,7 +22,7 @@ namespace Microsoft.OData.Edm.Csdl.Serialization
///
/// OData Common Schema Definition Language (CSDL) JSON writer
///
- internal class EdmModelCsdlSchemaJsonWriter : EdmModelCsdlSchemaWriter
+ internal partial class EdmModelCsdlSchemaJsonWriter : EdmModelCsdlSchemaWriter
{
private Utf8JsonWriter jsonWriter;
private CsdlJsonWriterSettings settings;
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs
index a299e6a77e..34ad936e63 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs
@@ -7,6 +7,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.OData.Edm.Helpers;
using Microsoft.OData.Edm.Vocabularies;
namespace Microsoft.OData.Edm.Csdl.Serialization
@@ -47,227 +49,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 TaskUtils.CompletedTask;
+ }
+
internal virtual void WriteOutOfLineAnnotationsEnd(IEnumerable>> outOfLineAnnotations)
{
// nothing here
}
+ internal virtual Task WriteOutOfLineAnnotationsEndAsync(IEnumerable>> outOfLineAnnotations)
+ {
+ return TaskUtils.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 TaskUtils.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 TaskUtils.CompletedTask;
+ }
+
internal virtual void WriteNavigationPropertyBindingsEnd(IEnumerable bindings)
{
// Nothing here
}
+ internal virtual Task WriteNavigationPropertyBindingsEndAsync(IEnumerable bindings)
+ {
+ return TaskUtils.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 TaskUtils.CompletedTask;
+ }
+
internal virtual void WriteReferentialConstraintEnd(IEdmReferentialConstraint referentialConstraint)
{
// nothing here
}
+ internal virtual Task WriteReferentialConstraintEndAsync(IEdmReferentialConstraint referentialConstraint)
+ {
+ return TaskUtils.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 TaskUtils.CompletedTask;
+ }
+
internal virtual void WriteSchemaOperationsEnd(KeyValuePair> operation)
{
// nothing here
}
+ internal virtual Task WriteSchemaOperationsEndAsync(KeyValuePair> operation)
+ {
+ return TaskUtils.CompletedTask;
+ }
+
internal virtual void WriteOperationParametersBegin(IEnumerable parameters)
{
// nothing here
}
+ internal virtual Task WriteOperationParametersBeginAsync(IEnumerable parameters)
+ {
+ return TaskUtils.CompletedTask;
+ }
+
internal virtual void WriteOperationParametersEnd(IEnumerable parameters)
{
// nothing here
}
+ internal virtual Task WriteOperationParametersEndAsync(IEnumerable parameters)
+ {
+ return TaskUtils.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 TaskUtils.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 TaskUtils.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)
{
@@ -278,7 +425,7 @@ protected static string EnumMemberAsXmlOrJson(IEnumerable member
{
string enumTypeName = members.First().DeclaringType.FullName();
List memberList = new List();
- foreach (var member in members)
+ foreach (IEdmEnumMember member in members)
{
memberList.Add(enumTypeName + "/" + member.Name);
}
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.Async.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.Async.cs
new file mode 100644
index 0000000000..994b03605c
--- /dev/null
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.Async.cs
@@ -0,0 +1,1250 @@
+//---------------------------------------------------------------------
+//
+// 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.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;
+using Microsoft.OData.Edm.Helpers;
+using Microsoft.OData.Edm.Vocabularies;
+using Microsoft.OData.Edm.Vocabularies.V1;
+
+namespace Microsoft.OData.Edm.Csdl.Serialization
+{
+ ///
+ /// OData Common Schema Definition Language (CSDL) XML writer
+ ///
+ internal partial class EdmModelCsdlSchemaXmlWriter : EdmModelCsdlSchemaWriter
+ {
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes the reference element end.
+ ///
+ /// edmx:Reference element
+ /// Task represents an asynchronous operation.
+ internal override Task WriteReferenceElementEndAsync(IEdmReference reference)
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes the include annotations end.
+ ///
+ /// The Edm include information.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteIncludeElementEndAsync(IEdmInclude include)
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// Asynchronously writes the include annotations 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);
+ }
+
+ ///
+ /// 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 != 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);
+ }
+
+ ///
+ /// Asynchronously writes the complex type 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);
+ }
+
+ ///
+ /// Asynchronously writes the enum type 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);
+ }
+
+ ///
+ /// Asynchronously writes the enum container element end.
+ ///
+ /// The Edm enumaration type.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteEnumTypeElementEndAsync(IEdmEnumType enumType)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Asynchronously writes the entity container 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes the entity set 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);
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes the entity type 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.
+ ///
+ /// Task represents an asynchronous operation.
+ internal override Task WriteDeclaredKeyPropertiesElementHeaderAsync()
+ {
+ return this.xmlWriter.WriteStartElementAsync(null, CsdlConstants.Element_Key, null);
+ }
+
+ ///
+ /// Asynchronously writes the property ref 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);
+ }
+
+ ///
+ /// Asynchronously writes the navigation property 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);
+ }
+
+ ///
+ /// Asynchronously writes the navigation OnDelete action 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+ }
+
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes the structural property 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes enum member element end.
+ ///
+ /// The Edm enumeration member.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteEnumMemberElementEndAsync(IEdmEnumMember member)
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes type definition 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 TaskUtils.CompletedTask;
+ }
+
+ ///
+ /// Asynchronously writes binary type 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);
+ }
+
+ ///
+ /// Asynchronously writes decimal type 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);
+ }
+
+ ///
+ /// Asynchronously writes spatial type 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 TaskUtils.CompletedTask;
+ }
+
+ ///
+ /// Asynchronously writes string type 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes temporal type 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes referential constraint 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes return type 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);
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes action import 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);
+ }
+
+ ///
+ /// Asynchronously writes function import 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);
+ }
+
+ ///
+ /// Asynchronously writes operation parameter 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes operation parameter 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)))
+ {
+ EdmRecordExpression optionalValue = new EdmRecordExpression();
+
+ EdmVocabularyAnnotation vocabularyAnnotation = new EdmVocabularyAnnotation(parameter, CoreVocabularyModel.OptionalParameterTerm, optionalValue);
+ await this.WriteVocabularyAnnotationElementHeaderAsync(vocabularyAnnotation, false).ConfigureAwait(false);
+
+ if (!string.IsNullOrEmpty(optionalParameter.DefaultValueString))
+ {
+ EdmPropertyConstructor 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);
+ }
+
+ ///
+ /// Asynchronously writes collection type 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);
+ }
+ }
+
+ ///
+ /// 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 TaskUtils.CompletedTask;
+ }
+ }
+
+ ///
+ /// Asynchronously writes property constructor element end.
+ ///
+ /// The Edm property constructor.
+ /// Task represents an asynchronous operation.
+ internal override Task WritePropertyConstructorElementEndAsync(IEdmPropertyConstructor constructor)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Asynchronously writes vocabulary annotation 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 && !IsUsingDefaultValue(annotation))
+ {
+ // 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes vocabulary annotation 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();
+ }
+
+ ///
+ /// Asynchronously writes property value 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes record expression 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);
+ }
+
+ ///
+ /// Asynchronously writes property constructor 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes string constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes binary constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes boolean constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes null constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes Date constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes DateTimeOffset constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes durarion constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes decimal constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes floating constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes function apply 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);
+ }
+
+ ///
+ /// Asynchronously writes function apply element end.
+ ///
+ /// The Edm apply expression.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteFunctionApplicationElementEndAsync(IEdmApplyExpression expression)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Asynchronously writes Guid constant expression 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);
+ }
+
+ ///
+ /// Asynchronously writes integer constant 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);
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes property path 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);
+ }
+
+ ///
+ /// Asynchronously writes navigation property path 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);
+ }
+
+ ///
+ /// Asynchronously writes annotation path 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);
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes If expression element end.
+ ///
+ /// Edm if Expression
+ /// Task represents an asynchronous operation.
+ internal override Task WriteIfExpressionElementEndAsync(IEdmIfExpression expression)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// Asynchronously writes collection expression element end.
+ ///
+ /// The Edm collection expression.
+ /// Task represents an asynchronous operation.
+ internal override Task WriteCollectionExpressionElementEndAsync(IEdmCollectionExpression expression)
+ {
+ return this.WriteEndElementAsync();
+ }
+
+ ///
+ /// Asynchronously writes labeled element 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);
+ }
+
+ ///
+ /// Asynchronously writes labeled expression reference.
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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);
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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();
+ }
+
+ ///
+ /// Asynchronously writes enum member 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);
+ }
+
+ ///
+ /// Asynchronously writes type definition 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);
+ }
+
+ ///
+ /// Asynchronously writes end element.
+ ///
+ internal override Task WriteEndElementAsync()
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// Asynchronously writes array end element.
+ ///
+ /// Task represents an asynchronous operation.
+ internal override Task WriteArrayEndElementAsync()
+ {
+ return this.xmlWriter.WriteEndElementAsync();
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// 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));
+ }
+
+ ///
+ /// 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes navigation property binding.
+ ///
+ /// 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('.') < 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);
+ }
+ }
+
+ ///
+ /// Asynchronously writes operation import 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));
+ }
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs
index 075c68d7f8..4b4a5fe5c8 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs
@@ -20,7 +20,7 @@ namespace Microsoft.OData.Edm.Csdl.Serialization
///
/// OData Common Schema Definition Language (CSDL) XML writer
///
- internal class EdmModelCsdlSchemaXmlWriter : EdmModelCsdlSchemaWriter
+ internal partial class EdmModelCsdlSchemaXmlWriter : EdmModelCsdlSchemaWriter
{
protected XmlWriter xmlWriter;
protected readonly string edmxNamespace;
@@ -342,7 +342,7 @@ internal override void WriteReferentialConstraintPair(EdmReferentialConstraintPr
internal override void WriteAnnotationStringAttribute(IEdmDirectValueAnnotation annotation)
{
- var edmValue = (IEdmPrimitiveValue)annotation.Value;
+ IEdmPrimitiveValue edmValue = (IEdmPrimitiveValue)annotation.Value;
if (edmValue != null)
{
this.xmlWriter.WriteAttributeString(annotation.Name, annotation.NamespaceUri, EdmValueWriter.PrimitiveValueAsXml(edmValue));
@@ -351,7 +351,7 @@ internal override void WriteAnnotationStringAttribute(IEdmDirectValueAnnotation
internal override void WriteAnnotationStringElement(IEdmDirectValueAnnotation annotation)
{
- var edmValue = (IEdmPrimitiveValue)annotation.Value;
+ IEdmPrimitiveValue edmValue = (IEdmPrimitiveValue)annotation.Value;
if (edmValue != null)
{
this.xmlWriter.WriteRaw(((IEdmStringValue)edmValue).Value);
@@ -854,7 +854,7 @@ internal override void WriteOperationImportAttributes(IEdmOperationImport operat
if (operationImport.EntitySet != null)
{
- var pathExpression = operationImport.EntitySet as IEdmPathExpression;
+ IEdmPathExpression pathExpression = operationImport.EntitySet as IEdmPathExpression;
if (pathExpression != null)
{
this.WriteOptionalAttribute(CsdlConstants.Attribute_EntitySet, pathExpression.PathSegments, PathAsXml);
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs
index 45b618822f..82d133325b 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)
+ {
+ HashSet functionImportsWritten = new HashSet();
+ HashSet 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;
+
+ string 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;
+
+ string 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;
@@ -85,7 +139,7 @@ internal void VisitEdmSchema(EdmSchema element, IEnumerable> operation in element.SchemaOperations)
{
this.schemaWriter.WriteSchemaOperationsHeader(operation);
VisitSchemaElements(operation.Value.AsEnumerable()); // Call AsEnumerable() to make .net 3.5 happy
@@ -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 (KeyValuePair> 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())
@@ -615,7 +1377,7 @@ private static string GetEntitySetString(IEdmOperationImport operationImport)
{
if (operationImport.EntitySet != null)
{
- var pathExpression = operationImport.EntitySet as IEdmPathExpression;
+ IEdmPathExpression pathExpression = operationImport.EntitySet as IEdmPathExpression;
if (pathExpression != null)
{
return EdmModelCsdlSchemaWriter.PathAsXml(pathExpression.PathSegments);
@@ -639,12 +1401,32 @@ 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)
{
this.schemaWriter.WriteReferentialConstraintBegin(element);
- foreach (var pair in element.PropertyPairs)
+ foreach (EdmReferentialConstraintPropertyPair pair in element.PropertyPairs)
{
this.schemaWriter.WriteReferentialConstraintPair(pair);
}
@@ -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 (EdmReferentialConstraintPropertyPair 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,13 +1538,25 @@ 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)
{
if (annotation.NamespaceUri != EdmConstants.InternalUri)
{
- var edmValue = annotation.Value as IEdmValue;
+ IEdmValue edmValue = annotation.Value as IEdmValue;
if (edmValue != null)
{
if (!edmValue.IsSerializedAsElement(this.Model))
@@ -716,13 +1571,31 @@ 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)
{
if (annotation.NamespaceUri != EdmConstants.InternalUri)
{
- var edmValue = annotation.Value as IEdmValue;
+ IEdmValue edmValue = annotation.Value as IEdmValue;
if (edmValue != null)
{
if (edmValue.IsSerializedAsElement(this.Model))
@@ -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.Async.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.Async.cs
new file mode 100644
index 0000000000..f8d3196ab0
--- /dev/null
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.Async.cs
@@ -0,0 +1,143 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+#if NETSTANDARD2_0
+using Microsoft.OData.Edm.Vocabularies;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Threading.Tasks;
+
+namespace Microsoft.OData.Edm.Csdl.Serialization
+{
+ ///
+ /// The visitor for outputting Edm reference elements for referenced model.
+ ///
+ internal partial class EdmModelReferenceElementsJsonVisitor
+ {
+ ///
+ /// Asynchronously visits Edm references and writes 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();
+ }
+ }
+
+ ///
+ /// 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();
+ }
+
+ ///
+ /// Asynchronously writes include annotations 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;
+ }
+
+ ///
+ /// 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)
+ {
+ IEnumerable 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/EdmModelReferenceElementsJsonVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.cs
index 5784622525..ca59a1a371 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsJsonVisitor.cs
@@ -16,7 +16,7 @@ namespace Microsoft.OData.Edm.Csdl.Serialization
///
/// The visitor for outputting Edm reference elements for referenced model.
///
- internal class EdmModelReferenceElementsJsonVisitor
+ internal partial class EdmModelReferenceElementsJsonVisitor
{
private readonly EdmModelCsdlSchemaJsonWriter schemaWriter;
private Utf8JsonWriter jsonWriter;
@@ -118,7 +118,7 @@ private void WriteIncludeAnnotations(IEnumerable include
private void WriteAnnotations(IEdmModel model, IEdmVocabularyAnnotatable target)
{
- var annotations = model.FindDeclaredVocabularyAnnotations(target);
+ IEnumerable annotations = model.FindDeclaredVocabularyAnnotations(target);
foreach (IEdmVocabularyAnnotation annotation in annotations)
{
this.schemaWriter.WriteVocabularyAnnotationElementHeader(annotation, true);
@@ -127,4 +127,4 @@ private void WriteAnnotations(IEdmModel model, IEdmVocabularyAnnotatable target)
}
}
}
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.Async.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.Async.cs
new file mode 100644
index 0000000000..d614b62d3b
--- /dev/null
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.Async.cs
@@ -0,0 +1,74 @@
+//---------------------------------------------------------------------
+//
+// 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.Threading.Tasks;
+using System.Xml;
+using Microsoft.OData.Edm.Vocabularies;
+
+namespace Microsoft.OData.Edm.Csdl.Serialization
+{
+ ///
+ /// The visitor for outputting <edmx:Reference> elements for referenced model.
+ ///
+ internal partial class EdmModelReferenceElementsXmlVisitor
+ {
+ #region write IEdmModel.References for referenced models.
+ ///
+ /// Asynchronously visits Edm references and writes 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);
+
+ }
+
+ ///
+ /// Asynchronously writes annotations.
+ ///
+ /// The Edm model.
+ /// The Edm vocabulary annotations.
+ /// Task represents an asynchronous operation.
+ private async Task WriteAnnotationsAsync(IEdmModel model, IEdmVocabularyAnnotatable target)
+ {
+ IEnumerable 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/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs
index 9869447e6e..d228404b3f 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelReferenceElementsXmlVisitor.cs
@@ -14,7 +14,7 @@ namespace Microsoft.OData.Edm.Csdl.Serialization
///
/// The visitor for outputting <edmx:referenced> elements for referenced model.
///
- internal class EdmModelReferenceElementsXmlVisitor
+ internal partial class EdmModelReferenceElementsXmlVisitor
{
private readonly EdmModelCsdlSchemaXmlWriter schemaWriter;
@@ -55,7 +55,7 @@ internal void VisitEdmReferences(IEdmModel model, IEdmReference reference)
private void WriteAnnotations(IEdmModel model, IEdmVocabularyAnnotatable target)
{
- var annotations = model.FindDeclaredVocabularyAnnotations(target);
+ IEnumerable annotations = model.FindDeclaredVocabularyAnnotations(target);
foreach (IEdmVocabularyAnnotation annotation in annotations)
{
this.schemaWriter.WriteVocabularyAnnotationElementHeader(annotation, true);
diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelSchemaSeparationSerializationVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelSchemaSeparationSerializationVisitor.cs
index 34c7480016..4eb8a323b0 100644
--- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelSchemaSeparationSerializationVisitor.cs
+++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelSchemaSeparationSerializationVisitor.cs
@@ -77,7 +77,7 @@ protected override void ProcessVocabularyAnnotation(IEdmVocabularyAnnotation ann
{
if (!annotation.IsInline(this.Model))
{
- var annotationSchemaNamespace = annotation.GetSchemaNamespace(this.Model) ?? this.modelSchemas.Select(s => s.Key).FirstOrDefault() ?? string.Empty;
+ string annotationSchemaNamespace = annotation.GetSchemaNamespace(this.Model) ?? this.modelSchemas.Select(s => s.Key).FirstOrDefault() ?? string.Empty;
EdmSchema annotationSchema;
if (!this.modelSchemas.TryGetValue(annotationSchemaNamespace, out annotationSchema))
@@ -106,7 +106,7 @@ protected override void ProcessVocabularyAnnotation(IEdmVocabularyAnnotation ann
/// The entity container being processed.
protected override void ProcessEntityContainer(IEdmEntityContainer element)
{
- var containerSchemaNamespace = element.Namespace;
+ string containerSchemaNamespace = element.Namespace;
EdmSchema containerSchema;
if (!this.modelSchemas.TryGetValue(containerSchemaNamespace, out containerSchema))
diff --git a/src/Microsoft.OData.Edm/EdmModelVisitor.cs b/src/Microsoft.OData.Edm/EdmModelVisitor.cs
index 2477986ff1..0806adfe8d 100644
--- a/src/Microsoft.OData.Edm/EdmModelVisitor.cs
+++ b/src/Microsoft.OData.Edm/EdmModelVisitor.cs
@@ -6,6 +6,8 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.OData.Edm.Helpers;
using Microsoft.OData.Edm.Vocabularies;
namespace Microsoft.OData.Edm
@@ -228,6 +230,33 @@ public virtual void VisitEntityContainerElements(IEnumerable elements)
+ {
+ 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:
+ await this.ProcessActionImportAsync((IEdmActionImport)element).ConfigureAwait(false);
+ break;
+ case EdmContainerElementKind.FunctionImport:
+ await this.ProcessFunctionImportAsync((IEdmFunctionImport)element).ConfigureAwait(false);
+ break;
+ case EdmContainerElementKind.None:
+ await this.ProcessEntityContainerElementAsync(element).ConfigureAwait(false);
+ break;
+ default:
+ throw new InvalidOperationException(Edm.Strings.UnknownEnumVal_ContainerElementKind(element.ContainerElementKind.ToString()));
+ }
+ }
+ }
+
#endregion
#region Type References
@@ -414,7 +443,6 @@ protected virtual void ProcessModel(IEdmModel model)
{
this.ProcessElement(model);
- // TODO: also visit referenced models?
this.VisitSchemaElements(model.SchemaElements);
this.VisitVocabularyAnnotations(model.VocabularyAnnotations);
}
@@ -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 TaskUtils.CompletedTask;
+ }
+
protected virtual void ProcessNamedElement(IEdmNamedElement element)
{
this.ProcessElement(element);
}
+ protected virtual async Task ProcessNamedElementAsync(IEdmNamedElement element)
+ {
+ await this.ProcessElementAsync(element).ConfigureAwait(false);
+ }
+
protected virtual void ProcessSchemaElement(IEdmSchemaElement element)
{
this.ProcessVocabularyAnnotatable(element);
this.ProcessNamedElement(element);
}
+ protected virtual async Task ProcessSchemaElementAsync(IEdmSchemaElement element)
+ {
+ await this.ProcessVocabularyAnnotatableAsync(element).ConfigureAwait(false);
+ await this.ProcessNamedElementAsync(element).ConfigureAwait(false);
+ }
+
protected virtual void ProcessVocabularyAnnotatable(IEdmVocabularyAnnotatable annotatable)
{
}
+ protected virtual Task ProcessVocabularyAnnotatableAsync(IEdmVocabularyAnnotatable annotatable)
+ {
+ return TaskUtils.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).ConfigureAwait(false);
+ }
+
protected virtual void ProcessEntityTypeReference(IEdmEntityTypeReference reference)
{
this.ProcessStructuredTypeReference(reference);
}
+ protected virtual async Task ProcessEntityTypeReferenceAsync(IEdmEntityTypeReference reference)
+ {
+ await this.ProcessStructuredTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessEntityReferenceTypeReference(IEdmEntityReferenceTypeReference reference)
{
this.ProcessTypeReference(reference);
this.ProcessEntityReferenceType(reference.EntityReferenceDefinition());
}
+ protected virtual async Task ProcessEntityReferenceTypeReferenceAsync(IEdmEntityReferenceTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ await this.ProcessEntityReferenceTypeAsync(reference.EntityReferenceDefinition()).ConfigureAwait(false);
+ }
+
protected virtual void ProcessCollectionTypeReference(IEdmCollectionTypeReference reference)
{
this.ProcessTypeReference(reference);
this.ProcessCollectionType(reference.CollectionDefinition());
}
+ protected virtual async Task ProcessCollectionTypeReferenceAsync(IEdmCollectionTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ await this.ProcessCollectionTypeAsync(reference.CollectionDefinition()).ConfigureAwait(false);
+ }
+
protected virtual void ProcessEnumTypeReference(IEdmEnumTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessEnumTypeReferenceAsync(IEdmEnumTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessTypeDefinitionReference(IEdmTypeDefinitionReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessTypeDefinitionReferenceAsync(IEdmTypeDefinitionReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessBinaryTypeReference(IEdmBinaryTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessBinaryTypeReferenceAsync(IEdmBinaryTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessDecimalTypeReference(IEdmDecimalTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessDecimalTypeReferenceAsync(IEdmDecimalTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessSpatialTypeReference(IEdmSpatialTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessSpatialTypeReferenceAsync(IEdmSpatialTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessStringTypeReference(IEdmStringTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessStringTypeReferenceAsync(IEdmStringTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessTemporalTypeReference(IEdmTemporalTypeReference reference)
{
this.ProcessPrimitiveTypeReference(reference);
}
+ protected virtual async Task ProcessTemporalTypeReferenceAsync(IEdmTemporalTypeReference reference)
+ {
+ await this.ProcessPrimitiveTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessPrimitiveTypeReference(IEdmPrimitiveTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessPrimitiveTypeReferenceAsync(IEdmPrimitiveTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessStructuredTypeReference(IEdmStructuredTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessStructuredTypeReferenceAsync(IEdmStructuredTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessTypeReference(IEdmTypeReference element)
{
this.ProcessElement(element);
}
+ protected virtual async Task ProcessTypeReferenceAsync(IEdmTypeReference element)
+ {
+ await this.ProcessElementAsync(element).ConfigureAwait(false);
+ }
+
protected virtual void ProcessPathTypeReference(IEdmPathTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessPathTypeReferenceAsync(IEdmPathTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
protected virtual void ProcessUntypedTypeReference(IEdmUntypedTypeReference reference)
{
this.ProcessTypeReference(reference);
}
+ protected virtual async Task ProcessUntypedTypeReferenceAsync(IEdmUntypedTypeReference reference)
+ {
+ await this.ProcessTypeReferenceAsync(reference).ConfigureAwait(false);
+ }
+
#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).ConfigureAwait(false);
+ 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).ConfigureAwait(false);
+ await this.ProcessStructuredTypeAsync(definition).ConfigureAwait(false);
+ await this.ProcessSchemaTypeAsync(definition).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ await this.ProcessStructuredTypeAsync(definition).ConfigureAwait(false);
+ await this.ProcessSchemaTypeAsync(definition).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ await this.ProcessTypeAsync(definition).ConfigureAwait(false);
+ 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).ConfigureAwait(false);
+ await this.ProcessTypeAsync(definition).ConfigureAwait(false);
+ await this.ProcessSchemaTypeAsync(definition).ConfigureAwait(false);
+ 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).ConfigureAwait(false);
+ await this.ProcessTypeAsync(definition).ConfigureAwait(false);
+ await this.ProcessSchemaTypeAsync(definition).ConfigureAwait(false);
+ }
+
protected virtual void ProcessEntityReferenceType(IEdmEntityReferenceType definition)
{
this.ProcessElement(definition);
this.ProcessType(definition);
}
+ protected virtual async Task ProcessEntityReferenceTypeAsync(IEdmEntityReferenceType definition)
+ {
+ await this.ProcessElementAsync(definition).ConfigureAwait(false);
+ await this.ProcessTypeAsync(definition).ConfigureAwait(false);
+ }
+
protected virtual void ProcessStructuredType(IEdmStructuredType definition)
{
this.ProcessType(definition);
this.VisitProperties(definition.DeclaredProperties);
}
+ protected virtual async Task ProcessStructuredTypeAsync(IEdmStructuredType definition)
+ {
+ await this.ProcessTypeAsync(definition).ConfigureAwait(false);
+ 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 TaskUtils.CompletedTask;
+ }
+
protected virtual void ProcessType(IEdmType definition)
{
}
+ protected virtual Task ProcessTypeAsync(IEdmType definition)
+ {
+ return TaskUtils.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).ConfigureAwait(false);
+ }
+
protected virtual void ProcessStructuralProperty(IEdmStructuralProperty property)
{
this.ProcessProperty(property);
}
+ protected virtual async Task ProcessStructuralPropertyAsync(IEdmStructuralProperty property)
+ {
+ await this.ProcessPropertyAsync(property).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ await this.ProcessNamedElementAsync(property).ConfigureAwait(false);
+ this.VisitTypeReference(property.Type);
+ }
+
protected virtual void ProcessEnumMember(IEdmEnumMember enumMember)
{
this.ProcessNamedElement(enumMember);
}
+ protected virtual async Task ProcessEnumMemberAsync(IEdmEnumMember enumMember)
+ {
+ await this.ProcessNamedElementAsync(enumMember).ConfigureAwait(false);
+ }
+
#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).ConfigureAwait(false);
+ }
+
protected virtual void ProcessImmediateValueAnnotation(IEdmDirectValueAnnotation annotation)
{
this.ProcessNamedElement(annotation);
}
+ protected virtual async Task ProcessImmediateValueAnnotationAsync(IEdmDirectValueAnnotation annotation)
+ {
+ await this.ProcessNamedElementAsync(annotation).ConfigureAwait(false);
+ }
+
protected virtual void ProcessAnnotation(IEdmVocabularyAnnotation annotation)
{
this.ProcessVocabularyAnnotation(annotation);
this.VisitExpression(annotation.Value);
}
+ protected virtual async Task ProcessAnnotationAsync(IEdmVocabularyAnnotation annotation)
+ {
+ await this.ProcessVocabularyAnnotationAsync(annotation).ConfigureAwait(false);
+ 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 TaskUtils.CompletedTask;
+ }
+
protected virtual void ProcessStringConstantExpression(IEdmStringConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessStringConstantExpressionAsync(IEdmStringConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessBinaryConstantExpression(IEdmBinaryConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessBinaryConstantExpressionAsync(IEdmBinaryConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ 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).ConfigureAwait(false);
+ }
+
protected virtual void ProcessPropertyPathExpression(IEdmPathExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessPropertyPathExpressionAsync(IEdmPathExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessNavigationPropertyPathExpression(IEdmPathExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessNavigationPropertyPathExpressionAsync(IEdmPathExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessAnnotationPathExpression(IEdmPathExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessAnnotationPathExpressionAsync(IEdmPathExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessCollectionExpression(IEdmCollectionExpression expression)
{
this.ProcessExpression(expression);
this.VisitExpressions(expression.Elements);
}
+ protected virtual async Task ProcessCollectionExpressionAsync(IEdmCollectionExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ this.VisitExpressions(expression.Elements);
+ }
+
protected virtual void ProcessLabeledExpressionReferenceExpression(IEdmLabeledExpressionReferenceExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessLabeledExpressionReferenceExpressionAsync(IEdmLabeledExpressionReferenceExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ 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).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ 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).ConfigureAwait(false);
+ this.VisitExpressions(expression.Arguments);
+ }
+
protected virtual void ProcessFloatingConstantExpression(IEdmFloatingConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessFloatingConstantExpressionAsync(IEdmFloatingConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessGuidConstantExpression(IEdmGuidConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessGuidConstantExpressionAsync(IEdmGuidConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessEnumMemberExpression(IEdmEnumMemberExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessEnumMemberExpressionAsync(IEdmEnumMemberExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessDecimalConstantExpression(IEdmDecimalConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDecimalConstantExpressionAsync(IEdmDecimalConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessDateConstantExpression(IEdmDateConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDateConstantExpressionAsync(IEdmDateConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessTimeOfDayConstantExpression(IEdmTimeOfDayConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessTimeOfDayConstantExpressionAsync(IEdmTimeOfDayConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessDateTimeOffsetConstantExpression(IEdmDateTimeOffsetConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDateTimeOffsetConstantExpressionAsync(IEdmDateTimeOffsetConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessDurationConstantExpression(IEdmDurationConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessDurationConstantExpressionAsync(IEdmDurationConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
protected virtual void ProcessBooleanConstantExpression(IEdmBooleanConstantExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessBooleanConstantExpressionAsync(IEdmBooleanConstantExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ 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 TaskUtils.CompletedTask;
+ }
+
protected virtual void ProcessPropertyConstructor(IEdmPropertyConstructor constructor)
{
this.VisitExpression(constructor.Value);
}
+ protected virtual Task ProcessPropertyConstructorAsync(IEdmPropertyConstructor constructor)
+ {
+ this.VisitExpression(constructor.Value);
+
+ return TaskUtils.CompletedTask;
+ }
+
protected virtual void ProcessNullConstantExpression(IEdmNullExpression expression)
{
this.ProcessExpression(expression);
}
+ protected virtual async Task ProcessNullConstantExpressionAsync(IEdmNullExpression expression)
+ {
+ await this.ProcessExpressionAsync(expression).ConfigureAwait(false);
+ }
+
#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).ConfigureAwait(false);
+ await this.ProcessNamedElementAsync(container).ConfigureAwait(false);
+ await this.VisitEntityContainerElementsAsync(container.Elements).ConfigureAwait(false);
+ }
+
protected virtual void ProcessEntityContainerElement(IEdmEntityContainerElement element)
{
this.ProcessNamedElement(element);
}
+ protected virtual async Task ProcessEntityContainerElementAsync(IEdmEntityContainerElement element)
+ {
+ await this.ProcessNamedElementAsync(element).ConfigureAwait(false);
+ }
+
protected virtual void ProcessEntitySet(IEdmEntitySet set)
{
this.ProcessEntityContainerElement(set);
}
+ protected virtual async Task ProcessEntitySetAsync(IEdmEntitySet set)
+ {
+ await this.ProcessEntityContainerElementAsync(set).ConfigureAwait(false);
+ }
+
protected virtual void ProcessSingleton(IEdmSingleton singleton)
{
this.ProcessEntityContainerElement(singleton);
}
+ protected virtual async Task ProcessSingletonAsync(IEdmSingleton singleton)
+ {
+ await this.ProcessEntityContainerElementAsync(singleton).ConfigureAwait(false);
+ }
+
#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).ConfigureAwait(false);
+ await this.ProcessOperationAsync(action).ConfigureAwait(false);
+ }
+
protected virtual void ProcessFunction(IEdmFunction function)
{
this.ProcessSchemaElement(function);
this.ProcessOperation(function);
}
+ protected virtual async Task ProcessFunctionAsync(IEdmFunction function)
+ {
+ await this.ProcessSchemaElementAsync(function).ConfigureAwait(false);
+ await this.ProcessOperationAsync(function).ConfigureAwait(false);
+ }
+
protected virtual void ProcessActionImport(IEdmActionImport actionImport)
{
this.ProcessEntityContainerElement(actionImport);
}
+ protected virtual async Task ProcessActionImportAsync(IEdmActionImport actionImport)
+ {
+ await this.ProcessEntityContainerElementAsync(actionImport).ConfigureAwait(false);
+ }
+
protected virtual void ProcessFunctionImport(IEdmFunctionImport functionImport)
{
this.ProcessEntityContainerElement(functionImport);
}
+ protected virtual async Task ProcessFunctionImportAsync(IEdmFunctionImport functionImport)
+ {
+ await this.ProcessEntityContainerElementAsync(functionImport).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ }
+
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).ConfigureAwait(false);
+ await this.ProcessNamedElementAsync(parameter).ConfigureAwait(false);
+ 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).ConfigureAwait(false);
+ this.VisitTypeReference(operationReturn.Type);
+ }
#endregion
#endregion
diff --git a/src/Microsoft.OData.Edm/Helpers/TaskUtils.cs b/src/Microsoft.OData.Edm/Helpers/TaskUtils.cs
new file mode 100644
index 0000000000..d6038a71c5
--- /dev/null
+++ b/src/Microsoft.OData.Edm/Helpers/TaskUtils.cs
@@ -0,0 +1,44 @@
+//---------------------------------------------------------------------
+//
+// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
+//
+//---------------------------------------------------------------------
+
+using System.Threading.Tasks;
+
+namespace Microsoft.OData.Edm.Helpers
+{
+ internal class TaskUtils
+ {
+ ///
+ /// Already completed task.
+ ///
+ private static Task _completedTask;
+
+ //
+ /// Returns already completed task instance.
+ ///
+ public static Task CompletedTask
+ {
+ get
+ {
+#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP2_0_OR_GREATER
+ _completedTask = Task.CompletedTask;
+#else
+ // Note that in case of two threads competing here we would create two completed tasks, but only one
+ // will be stored in the static variable. In any case, they are identical for all other purposes,
+ // so it doesn't matter which one wins
+ if (_completedTask == null)
+ {
+ // Create a TaskCompletionSource - since there's no non-generic version use a dummy one
+ // and then cast to the non-generic version.
+ TaskCompletionSource