UNPKG

@microsoft.azure/autorest.incubator

Version:
205 lines 12.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const dictionary_1 = require("../../../common/dictionary"); const text_manipulation_1 = require("../../../common/text-manipulation"); const access_modifier_1 = require("../../../csharp/code-dom/access-modifier"); const class_1 = require("../../../csharp/code-dom/class"); const constructor_1 = require("../../../csharp/code-dom/constructor"); const expression_1 = require("../../../csharp/code-dom/expression"); const field_1 = require("../../../csharp/code-dom/field"); const method_1 = require("../../../csharp/code-dom/method"); const dotnet = require("../../../csharp/code-dom/mscorlib"); const parameter_1 = require("../../../csharp/code-dom/parameter"); const if_1 = require("../../../csharp/code-dom/statements/if"); const statement_1 = require("../../../csharp/code-dom/statements/statement"); const clientruntime_1 = require("../../../csharp/lowlevel-generator/clientruntime"); const tweak_model_1 = require("../../../remodeler/tweak-model"); const interface_1 = require("./interface"); const property_1 = require("./property"); const proxy_property_1 = require("./proxy-property"); const model_class_json_1 = require("../../../csharp/lowlevel-generator/model/model-class-json"); const media_types_1 = require("../../../common/media-types"); const model_class_xml_1 = require("../../../csharp/lowlevel-generator/model/model-class-xml"); class ModelClass extends class_1.Class { constructor(namespace, schemaWithFeatures, state, objectInitializer) { super(namespace, schemaWithFeatures.schema.details.csharp.name); /* @internal */ this.backingFields = new Array(); this.implementation = schemaWithFeatures; this.isPolymorphic = false; this.discriminators = new Map(); this.parentModelClasses = new Array(); this.state = state; this.addGeneratedCodeAttribute = true; this.apply(objectInitializer); this.partial = true; // create an interface for this model class // mark the code-model with the class we're creating. this.schema.details.csharp.classImplementation = this; // get all the header properties for this model this.hasHeaderProperties = dictionary_1.values(this.schema.properties).linq.any(property => property.details.csharp[tweak_model_1.HeaderProperty] === tweak_model_1.HeaderPropertyType.Header || property.details.csharp[tweak_model_1.HeaderProperty] === tweak_model_1.HeaderPropertyType.Header); const modelInterface = this.schema.details.csharp.interfaceImplementation || new interface_1.ModelInterface(this.namespace, this.schema, this, this.state); this.modelInterface = modelInterface; this.interfaces.push(modelInterface); if (this.schema.discriminator) { // this has a discriminator property. // our children are expected to tell us who they are this.isPolymorphic = true; // we'll add a deserializer factory method a bit later.. } if (this.schema.extensions['x-ms-discriminator-value']) { // we have a discriminator value, and we should tell our parent who we are so that they can build a proper deserializer method. // um. just how do we *really* know which allOf is polymorphic? // that's really sad. for (const eachAllOf of dictionary_1.items(this.schema.allOf)) { const parentSchema = eachAllOf.value; const aState = this.state.path('allOf', eachAllOf.key); const parentDecl = this.state.project.modelsNamespace.resolveTypeDeclaration(parentSchema, true, aState); const parentClass = parentSchema.details.csharp.classImplementation; if (parentClass.isPolymorphic) { // remember this class for later. this.parentModelClasses.push(parentClass); // tell that parent who we are. parentClass.addDiscriminator(this.schema.extensions['x-ms-discriminator-value'], this); } } } const defaultConstructor = this.addMethod(new constructor_1.Constructor(this)); // default constructor for fits and giggles. const validationStatements = new statement_1.Statements(); // handle <allOf>s // add an 'implements' for the interface for the allOf. for (const eachSchema of dictionary_1.items(this.schema.allOf)) { // gs01: Critical -- pull thru parent allOf's! const aSchema = eachSchema.value; const aState = this.state.path('allOf', eachSchema.key); const td = this.state.project.modelsNamespace.resolveTypeDeclaration(aSchema, true, aState); const className = aSchema.details.csharp.classImplementation.fullName; const fieldName = text_manipulation_1.camelCase(text_manipulation_1.deconstruct(className.replace(/^.*\./, ''))); // add the interface as a parent to our interface. const iface = aSchema.details.csharp.interfaceImplementation; this.modelInterface.interfaces.push(iface); // add a field for the inherited values const backingField = this.addField(new field_1.InitializedField(`_${fieldName}`, td, { value: `new ${className}()` }, { access: access_modifier_1.Access.Private })); this.backingFields.push({ className, typeDeclaration: td, field: backingField }); // now, create proxy properties for the members iface.allProperties.map((each) => { // make sure we don't over expose read-only properties. const p = this.add(new proxy_property_1.ProxyProperty(backingField, each, this.state)); if (each.setAccess === access_modifier_1.Access.Internal) { p.setterStatements = undefined; } return p; }); validationStatements.add(td.validatePresence(backingField)); validationStatements.add(td.validateValue(backingField)); } // generate a protected backing field for each // and then expand the nested properties into this class forwarding to the member. // add properties for (const { key: propertyName, value: property } of dictionary_1.items(this.schema.properties)) { const prop = new property_1.ModelProperty(this, property, property.serializedName || propertyName, this.state.path('properties', propertyName)); this.add(prop); validationStatements.add(prop.validatePresenceStatement); validationStatements.add(prop.validationStatement); } if (this.schema.additionalProperties) { if (this.schema.additionalProperties === true) { // we should generate an additionalProperties property that catches all extra properties as object const valueSchema = {}; } else { // we should generate an additionalProperties property that catches all extra properties as the type specified by const valueSchema = this.schema.additionalProperties; } } if (!this.state.project.storagePipeline) { if (validationStatements.implementation.trim()) { // we do have something to valdiate! // add the IValidates implementation to this object. this.interfaces.push(clientruntime_1.ClientRuntime.IValidates); this.validateMethod = this.addMethod(new method_1.Method('Validate', dotnet.System.Threading.Tasks.Task(), { async: access_modifier_1.Modifier.Async, parameters: [new parameter_1.Parameter('listener', clientruntime_1.ClientRuntime.IEventListener)], })); this.validateMethod.add(validationStatements); } } // add from headers method if class or any of the parents pulls in header values. // FromHeaders( headers IEnumerable<KeyValuePair<string, IEnumerable<string>>> ) { ... } const headerProperties = dictionary_1.values(this.properties).linq.where(p => p.IsHeaderProperty); if (this.hasHeaderProperties) { // add header deserializer method const httpResponse = new parameter_1.Parameter('response', dotnet.System.Net.Http.HttpResponseMessage); const readHeaders = new method_1.Method('ReadHeaders', this, { access: access_modifier_1.Access.Internal, parameters: [httpResponse], *body() { for (const hp of headerProperties) { const hparam = hp; const prefix = hparam.schema.extensions['x-ms-header-collection-prefix']; if (prefix) { yield `${hparam.backingName} = System.Linq.Enumerable.ToDictionary(System.Linq.Enumerable.Where(${expression_1.valueOf(httpResponse)}.Headers, header => header.Key.StartsWith("${prefix}",System.StringComparison.InvariantCulture)), header => header.Key.Substring(10), header => System.Linq.Enumerable.FirstOrDefault(header.Value));`; } else { const values = `__${text_manipulation_1.camelCase(['header', ...text_manipulation_1.deconstruct(hparam.serializedName)])}Values`; yield if_1.If(`${expression_1.valueOf(httpResponse)}.GetHeader("${hparam.serializedName}", out var ${values})`, `${hparam.assignPrivate(hparam.deserializeFromNode(media_types_1.KnownMediaType.Header, values))}`); } } yield `return this;`; } }).addTo(this); } const hasNonHeaderProperties = dictionary_1.values(this.properties).linq.any(p => !p.IsHeaderProperty); if (hasNonHeaderProperties) { if (!this.state.project.storagePipeline) { this.jsonSerializer = new model_class_json_1.JsonSerializableClass(this); } this.xmlSerializer = new model_class_xml_1.XmlSerializableClass(this); } } deserializeFromContainerMember(mediaType, container, serializedName, defaultValue) { return this.implementation.deserializeFromContainerMember(mediaType, container, serializedName, defaultValue); } deserializeFromNode(mediaType, node, defaultValue) { return this.implementation.deserializeFromNode(mediaType, node, defaultValue); } serializeToNode(mediaType, value, serializedName) { return this.implementation.serializeToNode(mediaType, value, serializedName); } /** emits an expression serialize this to a HttpContent */ serializeToContent(mediaType, value) { return this.implementation.serializeToContent(mediaType, value); } /** emits an expression to deserialize content from a string */ deserializeFromString(mediaType, content, defaultValue) { return this.implementation.deserializeFromString(mediaType, content, defaultValue); } serializeToContainerMember(mediaType, value, container, serializedName) { return this.implementation.serializeToContainerMember(mediaType, value, container, serializedName); } get isXmlAttribute() { return this.implementation.isXmlAttribute; } get isRequired() { return this.implementation.isRequired; } /* @internal */ get schema() { return this.implementation.schema; } validateValue(property) { return this.implementation.validateValue(property); } validatePresence(property) { return this.implementation.validatePresence(property); } addDiscriminator(discriminatorValue, modelClass) { this.discriminators.set(discriminatorValue, modelClass); // tell any polymorphic parents incase we're doing subclass of a subclass. for (const each of this.parentModelClasses) { each.addDiscriminator(discriminatorValue, modelClass); } } } exports.ModelClass = ModelClass; //# sourceMappingURL=model-class.js.map