diff --git a/.gulp/regeneration.iced b/.gulp/regeneration.iced index f980307..c07a4a5 100644 --- a/.gulp/regeneration.iced +++ b/.gulp/regeneration.iced @@ -94,6 +94,10 @@ rubyAzureMappings = { 'parameter_grouping':['azure-parameter-grouping.json', 'ParameterGroupingModule'] } +rubyAzureAdditionalMappings = { + 'azure_resource_inheritance': ['resource_inheritance.json', 'AzureResourceInheritanceModule'] +} + swaggerDir = "node_modules/@microsoft.azure/autorest.testserver/swagger" task 'regenerate-rubyazure', '', (done) -> @@ -108,6 +112,20 @@ task 'regenerate-rubyazure', '', (done) -> },done return null +testSwaggerDir = "test/swagger" + +task 'regenerate-rubyazure-additional', '', (done) -> + regenExpected { + 'outputBaseDir': 'test/azure', + 'inputBaseDir': testSwaggerDir, + 'mappings': rubyAzureAdditionalMappings, + 'outputDir': 'RspecTests/Generated', + 'language': 'ruby', + 'azureArm': true, + 'nsPrefix': 'MyNamespace' + },done + return null + task 'regenerate-ruby', '', (done) -> regenExpected { 'outputBaseDir': 'test/vanilla', @@ -119,5 +137,5 @@ task 'regenerate-ruby', '', (done) -> },done return null -task 'regenerate', "regenerate expected code for tests", ['regenerate-ruby', 'regenerate-rubyazure'], (done) -> +task 'regenerate', "regenerate expected code for tests", ['regenerate-ruby', 'regenerate-rubyazure', 'regenerate-rubyazure-additional'], (done) -> done(); \ No newline at end of file diff --git a/src/azure/CodeGeneratorRba.cs b/src/azure/CodeGeneratorRba.cs index 8959e7e..b952958 100644 --- a/src/azure/CodeGeneratorRba.cs +++ b/src/azure/CodeGeneratorRba.cs @@ -67,11 +67,8 @@ public override async Task Generate(CodeModel cm) continue; } - var modelTemplate = new AzureModelTemplate { Model = model }; - if (!CompositeTypeRba.resourceOrSubResourceRegEx.IsMatch(model.Name) || !CompositeTypeRba.IsResourceModelMatchingStandardDefinition(model)) - { - await Write(modelTemplate, Path.Combine(GeneratorSettingsRb.Instance.modelsPath, CodeNamer.UnderscoreCase(model.Name) + ImplementationFileExtension)); - } + var modelTemplate = new ModelTemplate { Model = model }; + await Write(modelTemplate, Path.Combine(GeneratorSettingsRb.Instance.modelsPath, CodeNamer.UnderscoreCase(model.Name) + ImplementationFileExtension)); } // Paged Models foreach (var pageModel in codeModel.pageModels) diff --git a/src/azure/Model/CompositeTypeRba.cs b/src/azure/Model/CompositeTypeRba.cs index bb3d865..1674f40 100644 --- a/src/azure/Model/CompositeTypeRba.cs +++ b/src/azure/Model/CompositeTypeRba.cs @@ -46,70 +46,12 @@ public override string GetBaseTypeName() { if (this.BaseModelType != null) { - string typeName = this.BaseModelType.Name; - - if (this.BaseModelType.Extensions.ContainsKey(AzureExtensions.ExternalExtension) || - this.BaseModelType.Extensions.ContainsKey(AzureExtensions.AzureResourceExtension)) - { - if (!resourceOrSubResourceRegEx.IsMatch(typeName) || !IsResourceModelMatchingStandardDefinition(this)) - { - typeName = "MsRestAzure::" + typeName; - } - } - - return " < " + typeName; - } - else if (resourceOrSubResourceRegEx.IsMatch(this.Name)) - { - return " < " + "MsRestAzure::" + this.Name; + return " < " + this.BaseModelType.Name; } return string.Empty; } - /// - /// Checks if the provided definition of models 'Resource'/'SubResource' matches the standard definition, - /// as defined in MsRestAzure. For other models, it returns false. - /// - /// to be validated - /// - public static bool IsResourceModelMatchingStandardDefinition(CompositeType model) - { - string modelName = model.Name.ToString(); - if (modelName.EqualsIgnoreCase("SubResource") && - model.Properties.All(property => subResourceRegEx.IsMatch(property.Name.ToString()))) - { - return true; - } - - if(modelName.EqualsIgnoreCase("Resource") && - model.Properties.All(property => resourceRegEx.IsMatch(property.Name.ToString()))) - { - return true; - } - - return false; - } - - /// - /// Determines if the accessor needs to be generated. For Resource/SubResource models, accessors are generated only - /// for properties that are not in the standard definition, as defined in MsRestAzure. - /// - /// - /// - /// - public static bool NeedsAccessor(CompositeType model, string propertyName) - { - string modelName = model.Name.ToString(); - if((modelName.EqualsIgnoreCase("SubResource") && subResourceRegEx.IsMatch(propertyName)) || - (modelName.EqualsIgnoreCase("Resource") && resourceRegEx.IsMatch(propertyName))) - { - return false; - } - - return true; - } - /// /// Gets the list of modules/classes which need to be included. /// diff --git a/src/azure/Model/RequirementsRba.cs b/src/azure/Model/RequirementsRba.cs index a7f2863..0014c6e 100644 --- a/src/azure/Model/RequirementsRba.cs +++ b/src/azure/Model/RequirementsRba.cs @@ -21,8 +21,7 @@ class RequirementsRba : RequirementsRb protected override bool ExcludeModel(CompositeType model) { return (model.Extensions.ContainsKey(AzureExtensions.ExternalExtension) && - (bool) model.Extensions[AzureExtensions.ExternalExtension]) - ||CompositeTypeRba.IsResourceModelMatchingStandardDefinition(model); + (bool) model.Extensions[AzureExtensions.ExternalExtension]); } /// diff --git a/src/azure/Templates/AzureModelTemplate.cshtml b/src/azure/Templates/AzureModelTemplate.cshtml deleted file mode 100644 index 801e005..0000000 --- a/src/azure/Templates/AzureModelTemplate.cshtml +++ /dev/null @@ -1,69 +0,0 @@ -@using System -@using System.Linq -@using AutoRest.Core.Utilities -@using AutoRest.Ruby -@using AutoRest.Ruby.Model -@using AutoRest.Ruby.Azure.Model -@inherits AutoRest.Core.Template -# encoding: utf-8 -@Header("# ") -@EmptyLine -module @(Settings.Namespace) - module Models - # - @WrapComment("# ", Model.BuildSummaryAndDescriptionString()) - # - class @Model.Name@(Model.GetBaseTypeName()) - @if (Model.Includes.Any()) - { - @EmptyLine - foreach (var include in Model.Includes) - { - @:include @include - } - @EmptyLine - } - include MsRest::JSONable - - @if (Model.BaseIsPolymorphic && Model.BaseModelType == null) - { - @:@@@@discriminatorMap = Hash.new - foreach (var derivedType in Model.DerivedTypes) - { - @:@@@@discriminatorMap["@derivedType.SerializedName"] = "@derivedType.Name" - } - } - - @if (Model.BaseIsPolymorphic) - { - @EmptyLine - @:def initialize - @: @@@Model.PolymorphicDiscriminatorProperty.Name = "@Model.SerializedName" - @:end - @EmptyLine - @:attr_accessor :@Model.PolymorphicDiscriminatorProperty.Name - @EmptyLine - } - - @foreach (var property in Model.PropertyTemplateModels.Where(each => !each.IsPolymorphicDiscriminator)) - { - @if (CompositeTypeRba.NeedsAccessor(Model, property.Name)) - { - @:@WrapComment("# ", string.Format("@return {0}{1}", property.ModelType.GetYardDocumentation(), CompositeTypeRb.GetPropertyDocumentationString(property))) - @:attr_accessor :@property.Name - @EmptyLine - @: - } - } - - @EmptyLine - # - @WrapComment("# ", string.Format("Mapper for {0} class as Ruby Hash.", Model.Name)) - # This will be used for serialization/deserialization. - # - def self.mapper() - @(Model.ConstructModelMapper()) - end - end - end -end diff --git a/test/azure/RspecTests/models_generation_and_inheritance_spec.rb b/test/azure/RspecTests/models_generation_and_inheritance_spec.rb new file mode 100644 index 0000000..6baf1e0 --- /dev/null +++ b/test/azure/RspecTests/models_generation_and_inheritance_spec.rb @@ -0,0 +1,58 @@ +# encoding: utf-8 + +$: << 'RspecTests/Generated/azure_resource_inheritance' + +require 'rspec' +require 'generated/resource_inheritance' + +include AzureResourceInheritanceModule + +describe 'ModelsGenerationAndInheritance' do + before(:all) do + @base_url = ENV['StubServerURI'] + + dummyToken = 'dummy12321343423' + @credentials = MsRest::TokenCredentials.new(dummyToken) + + @client = AzureResourceInheritanceTest.new(@credentials, @base_url) + end + + it 'should generate expected models' do + modules = Module.const_get('AzureResourceInheritanceModule::Models') + + # Should generate AzureResource class + azure_resource = modules.const_get('AzureResource') + expect(azure_resource.is_a?(Class)).to be_truthy + + # Should generate LikeAzureResource class + like_azure_resource = modules.const_get('LikeAzureResource') + expect(like_azure_resource.is_a?(Class)).to be_truthy + + # Should generate AzureResourceAdditionaProperties class + azure_resource_additional_properties = modules.const_get('AzureResourceAdditionaProperties') + expect(azure_resource_additional_properties.is_a?(Class)).to be_truthy + + # Should generate Resource class + resource = modules.const_get('Resource') + expect(resource.is_a?(Class)).to be_truthy + end + + it 'should generate models with expected inheritance' do + modules = Module.const_get('AzureResourceInheritanceModule::Models') + + # Should generate InheritMsRestAzureResource with super class as AzureResourceInheritanceModule::Models::Resource + inherit_ms_rest_azure_resource = modules.const_get('InheritMsRestAzureResource') + expect(inherit_ms_rest_azure_resource.is_a?(Class)).to be_truthy + expect(inherit_ms_rest_azure_resource.superclass.name).to eq('AzureResourceInheritanceModule::Models::Resource') + + # Should generate InheritAzureResource with super class as AzureResource + inherit_azure_resource = modules.const_get('InheritAzureResource') + expect(inherit_azure_resource.is_a?(Class)).to be_truthy + expect(inherit_azure_resource.superclass.name).to eq('AzureResourceInheritanceModule::Models::AzureResource') + + # Should generate InheritAzureResourceAdditionaProperties with super class as AzureResourceAdditionaProperties + azure_resource_additional_properties = modules.const_get('InheritAzureResourceAdditionaProperties') + expect(azure_resource_additional_properties.is_a?(Class)).to be_truthy + expect(azure_resource_additional_properties.superclass.name).to eq('AzureResourceInheritanceModule::Models::AzureResourceAdditionaProperties') + end +end \ No newline at end of file diff --git a/test/swagger/resource_inheritance.json b/test/swagger/resource_inheritance.json new file mode 100644 index 0000000..714939c --- /dev/null +++ b/test/swagger/resource_inheritance.json @@ -0,0 +1,335 @@ +{ + "swagger": "2.0", + "info": { + "title": "Azure Resource Inheritance Test", + "description": "Test Resource and SubResource inheritance.", + "version": "1.0.0" + }, + "host": "localhost", + "schemes": [ + "http" + ], + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "paths": { + "/fakepath/{subscriptionId}/{resourceGroupName}/{id}?api-version={apiVersion}": { + "get": { + "operationId": "validationOfMethodParameters", + "summary": "", + "description": "Validates input parameters on the method. See swagger for details.", + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParamterer" + }, + { + "name": "resourceGroupName", + "in": "path", + "description": "Required string between 3 and 10 chars with pattern [a-zA-Z0-9]+.", + "required": true, + "type": "string", + "maxLength": 10, + "minLength": 3, + "pattern": "[a-zA-Z0-9]+" + }, + { + "name": "id", + "in": "path", + "description": "Required int multiple of 10 from 100 to 1000.", + "required": true, + "type": "integer", + "multipleOf": 10, + "maximum": 1000, + "minimum": 100 + }, + { + "$ref": "#/parameters/ApiVersionParameter" + } + ], + "tags": [ + "Redis" + ], + "responses": { + "200": { + "description": "A list of caches", + "schema": { + "$ref": "#/definitions/Product" + } + }, + "default": { + "description": "Unexpected error", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + } + }, + "definitions": { + "Product": { + "description": "The product documentation.", + "required": [ + "child", + "constString", + "constInt", + "constChild" + ], + "properties": { + "display_names": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Non required array of unique items from 0 to 6 elements.", + "maxItems": 6, + "uniqueItems": true, + "minItems": 0 + }, + "capacity": { + "type": "integer", + "description": "Non required int betwen 0 and 100 exclusive.", + "exclusiveMinimum": true, + "exclusiveMaximum": true, + "maximum": 100, + "minimum": 0 + }, + "image": { + "type": "string", + "description": "Image URL representing the product.", + "pattern": "http://\\w+" + }, + "child": { + "$ref": "#/definitions/ChildProduct" + }, + "constChild": { + "$ref": "#/definitions/ConstantProduct" + }, + "constInt": { + "type": "integer", + "description": "Constant int", + "enum": [ + 0 + ] + }, + "constString": { + "type": "string", + "description": "Constant string", + "enum": [ + "constant" + ] + }, + "constStringAsEnum": { + "type": "string", + "description": "Constant string as Enum", + "enum": [ + "constant_string_as_enum" + ], + "x-ms-enum": { + "name": "EnumConst", + "modelAsString": false + } + } + } + }, + "ChildProduct": { + "description": "The product documentation.", + "required": [ + "constProperty" + ], + "properties": { + "constProperty": { + "type": "string", + "description": "Constant string", + "enum": [ + "constant" + ] + }, + "count": { + "type": "integer", + "description": "Count" + } + } + }, + "ConstantProduct": { + "description": "The product documentation.", + "required": [ + "constProperty", + "constProperty2" + ], + "properties": { + "constProperty": { + "type": "string", + "description": "Constant string", + "enum": [ + "constant" + ] + }, + "constProperty2": { + "type": "string", + "description": "Constant string2", + "enum": [ + "constant2" + ] + } + } + }, + "Error": { + "properties": { + "code": { + "type": "integer", + "format": "int32" + }, + "message": { + "type": "string" + }, + "fields": { + "type": "string" + } + } + }, + "Resource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + }, + "LikeAzureResource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + }, + "AzureResource": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + } + }, + "x-ms-azure-resource": true + }, + "AzureResourceAdditionaProperties": { + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource Id for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. Ex- Microsoft.Compute/virtualMachines or Microsoft.Storage/storageAccounts." + }, + "kind": { + "type": "string", + "description": "The kind of the resource." + } + }, + "x-ms-azure-resource": true + }, + "InheritMsRestAzureResource": { + "properties": { + "foo": { + "type": "string", + "description": "Property foo" + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "InheritAzureResource": { + "properties": { + "foo": { + "type": "string", + "description": "Property foo" + } + }, + "allOf": [ + { + "$ref": "#/definitions/AzureResource" + } + ] + }, + "InheritAzureResourceAdditionaProperties": { + "properties": { + "foo": { + "type": "string", + "description": "Property foo" + } + }, + "allOf": [ + { + "$ref": "#/definitions/AzureResourceAdditionaProperties" + } + ] + } + }, + "parameters": { + "SubscriptionIdParamterer": { + "name": "subscriptionId", + "in": "path", + "description": "Subscription ID.", + "required": true, + "type": "string" + }, + "ApiVersionParameter": { + "name": "apiVersion", + "in": "query", + "description": "Required string following pattern \\d{2}-\\d{2}-\\d{4}", + "required": true, + "type": "string", + "pattern": "\\d{2}-\\d{2}-\\d{4}" + } + } +} \ No newline at end of file