powershell/llcsharp/schema/object.ts (132 lines of code) (raw):

/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { values } from '@azure-tools/linq'; import { KnownMediaType } from '@azure-tools/codemodel-v3'; import { camelCase, deconstruct, EOL, nameof } from '@azure-tools/codegen'; import { IsNotNull } from '@azure-tools/codegen-csharp'; import { System } from '@azure-tools/codegen-csharp'; import { Expression, ExpressionOrLiteral, StringExpression, toExpression, valueOf } from '@azure-tools/codegen-csharp'; import { OneOrMoreStatements } from '@azure-tools/codegen-csharp'; import { Ternery } from '@azure-tools/codegen-csharp'; import { Variable } from '@azure-tools/codegen-csharp'; import { ClientRuntime } from '../clientruntime'; import { Schema } from '../code-model'; import { Schema as NewSchema, ObjectSchema } from '@autorest/codemodel'; import { popTempVar, pushTempVar } from './primitive'; import { EnhancedTypeDeclaration } from './extended-type-declaration'; export class ObjectImplementation implements EnhancedTypeDeclaration { public isXmlAttribute = false; get defaultOfType() { return toExpression('null /* object */'); } get isNullable(): boolean { return true; } get convertObjectMethod() { return `${this.schema.language.csharp?.fullname}TypeConverter.ConvertFrom`; } deserializeFromContainerMember(mediaType: KnownMediaType, container: ExpressionOrLiteral, serializedName: string, defaultValue: Expression): Expression { switch (mediaType) { case KnownMediaType.Json: { // JsonObject const tmp = `__${camelCase(['json', ...deconstruct(serializedName)])}`; return toExpression(`If( ${valueOf(container)}?.PropertyT<${ClientRuntime.JsonObject}>("${serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromJson(${tmp}) : ${defaultValue}`); } case KnownMediaType.Xml: { // XElement/XElement or XElement/XAttribute const tmp = `__${camelCase(['xml', ...deconstruct(serializedName)])}`; // prefer specified XML name if available return toExpression(`If( ${valueOf(container)}?.Element("${this.schema.serialization?.xml ? this.schema.serialization.xml.name || serializedName : serializedName}"), out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); } } return toExpression(`${defaultValue} /* deserializeFromContainerMember doesn't support '${mediaType}' ${__filename} */`); } /** emits an expression to deserialze a container as the value itself. */ deserializeFromNode(mediaType: KnownMediaType, node: ExpressionOrLiteral, defaultValue: Expression): Expression { try { const tmp = pushTempVar(); switch (mediaType) { case KnownMediaType.Json: { // we're always going to go thru FromJson; it'll handle nulls and polymorphism. return toExpression(`${this.classDeclaration}.FromJson(${node}) `); } case KnownMediaType.Xml: { return toExpression(`If( ${valueOf(node)}, out var ${tmp}) ? ${this.classDeclaration}.FromXml(${tmp}) : ${defaultValue}`); } } } finally { popTempVar(); } return toExpression(`null /* deserializeFromNode doesn't support '${mediaType}' ${__filename}*/`); } /** emits an expression serialize this to a HttpContent */ serializeToNode(mediaType: KnownMediaType, value: ExpressionOrLiteral, serializedName: string, mode: Expression): Expression { switch (mediaType) { case KnownMediaType.Json: { return toExpression(`${value}?.ToJson(null, ${mode.value})`); } case KnownMediaType.Xml: { return toExpression(`${value}?.ToXml(null, ${mode.value})`); } } return toExpression(`null /* serializeToNode doesn't support '${mediaType}' ${__filename}*/`); } /** emits an expression serialize this to the value required by the container */ serializeToContent(mediaType: KnownMediaType, value: ExpressionOrLiteral, mode: Expression): Expression { switch (mediaType) { case KnownMediaType.Json: { return System.Net.Http.StringContent.new( Ternery( IsNotNull(value), `${value}.ToJson(null, ${mode}).ToString()`, new StringExpression('{}')), System.Text.Encoding.UTF8); } case KnownMediaType.Xml: { return System.Net.Http.StringContent.new( Ternery( IsNotNull(value), `${value}.ToXml(null).ToString()`, System.String.Empty), System.Text.Encoding.UTF8); } //skip-for-time-being // case KnownMediaType.Multipart: { // let contents = ''; // for (const p of values(this.schema.properties)) { // // to do -- add in a potential support for the filename too. // contents = `${contents}${EOL} bodyContent.Add( ${System.Net.Http.StreamContent.new(`${value}.${p.details.csharp.name}`)},"${p.serializedName}");`; // } // // bodyContent.Add(new _ystem.Net.Http.StreamContent(body.AudioFile), "audioFile"); // return toExpression(`new ${System.Func(System.Net.Http.MultipartFormDataContent)}(() => // { // var bodyContent = ${System.Net.Http.MultipartFormDataContent.new()}; // ${contents} // return bodyContent; // })()`); // } } return toExpression(`null /* serializeToContent doesn't support '${mediaType}' ${__filename}*/`); } /** emits an expression to deserialize content from a string */ deserializeFromString(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { switch (mediaType) { case KnownMediaType.Json: { return this.deserializeFromNode(mediaType, ClientRuntime.JsonNode.Parse(content), defaultValue); } case KnownMediaType.Xml: { return this.deserializeFromNode(mediaType, `${System.Xml.Linq.XElement}.Parse(${content})`, defaultValue); } } return undefined; } /** emits an expression to deserialize content from a content/response */ deserializeFromResponse(mediaType: KnownMediaType, content: ExpressionOrLiteral, defaultValue: Expression): Expression | undefined { switch (mediaType) { case KnownMediaType.Json: { if (this.schema.language.csharp?.hasHeaders) { return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)}.ReadHeaders(_response.Headers))`); } return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); } case KnownMediaType.Xml: { return toExpression(`${content}.Content.ReadAsStringAsync().ContinueWith( body => ${this.deserializeFromString(mediaType, 'body.Result', defaultValue)})`); } } return toExpression(`null /* deserializeFromResponse doesn't support '${mediaType}' ${__filename}*/`); } /** emits the code required to serialize this into a container */ serializeToContainerMember(mediaType: KnownMediaType, value: ExpressionOrLiteral, container: Variable, serializedName: string, mode: Expression): OneOrMoreStatements { // const v = (<any>value).valuePrivate || value; switch (mediaType) { case KnownMediaType.Json: return `AddIf( null != ${value} ? (${ClientRuntime.JsonNode}) ${value}.ToJson(null,${mode.value}) : null, "${serializedName}" ,${container}.Add );`; case KnownMediaType.Xml: // prefer specified XML name if available return `AddIf( null != ${value} ? ${value}.ToXml(new ${System.Xml.Linq.XElement}("${this.schema.serialization?.xml ? this.schema.serialization.xml.name || serializedName : serializedName}")) : null, ${container}.Add );`; } return `/* serializeToContainerMember doesn't support '${mediaType}' ${__filename}*/`; } isRequired = false; constructor(public schema: ObjectSchema) { } public validatePresence(eventListener: Variable, property: Variable): OneOrMoreStatements { return `await ${eventListener}.AssertNotNull(${nameof(property.value)}, ${property}); `.trim(); } public validateValue(eventListener: Variable, property: Variable): OneOrMoreStatements { return `await ${eventListener}.AssertObjectIsValid(${nameof(property.value)}, ${property}); `; } get declaration(): string { return `${this.schema.language.csharp?.namespace}.${this.schema.language.csharp?.interfaceName}`; } get classDeclaration(): string { return `${this.schema.language.csharp?.namespace}.${this.schema.language.csharp?.name}`; } }