SwaggerUtils.psm1
######################################################################################### # # Copyright (c) Microsoft Corporation. All rights reserved. # # Licensed under the MIT license. # # PSSwagger Module # ######################################################################################### Microsoft.PowerShell.Core\Set-StrictMode -Version Latest Import-Module (Join-Path -Path $PSScriptRoot -ChildPath Utilities.psm1) Import-Module -Name 'PSSwaggerUtility' . "$PSScriptRoot\PSSwagger.Constants.ps1" -Force . "$PSScriptRoot\Trie.ps1" -Force . "$PSScriptRoot\PSCommandVerbMap.ps1" -Force Microsoft.PowerShell.Utility\Import-LocalizedData LocalizedData -filename PSSwagger.Resources.psd1 $script:CmdVerbTrie = $null $script:CSharpCodeNamer = $null $script:CSharpCodeNamerLoadAttempted = $false $script:PluralizationService = $null # System.Data.Entity.Design.PluralizationServices.PluralizationService is not yet supported on coreclr. if(-not (Get-OperatingSystemInfo).IsCore) { if(-not ('System.Data.Entity.Design.PluralizationServices.PluralizationService' -as [Type])) { Add-Type -AssemblyName System.Data.Entity.Design } $script:PluralizationService = [System.Data.Entity.Design.PluralizationServices.PluralizationService]::CreateService([System.Globalization.CultureInfo]::CurrentCulture) $PluralToSingularMapPath = Join-Path -Path $PSScriptRoot -ChildPath 'PluralToSingularMap.json' if(Test-Path -Path $PluralToSingularMapPath -PathType Leaf) { $PluralToSingularMapJsonObject = ConvertFrom-Json -InputObject ((Get-Content -Path $PluralToSingularMapPath) -join [Environment]::NewLine) -ErrorAction Stop $PluralToSingularMapJsonObject.CustomPluralToSingularMapping | ForEach-Object { $script:PluralizationService.AddWord($_.PSObject.Properties.Value, $_.PSObject.Properties.Name) } } } $script:IgnoredAutoRestParameters = @(@('Modeler', 'm'), @('AddCredentials'), @('CodeGenerator', 'g')) $script:PSSwaggerDefaultNamespace = "Microsoft.PowerShell" function ConvertTo-SwaggerDictionary { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $SwaggerSpecPath, [Parameter(Mandatory=$true)] [string[]] $SwaggerSpecFilePaths, [Parameter(Mandatory=$true)] [hashtable] $DefinitionFunctionsDetails, [Parameter(Mandatory=$false)] [string] $ModuleName, [Parameter(Mandatory=$false)] [Version] $ModuleVersion = '0.0.1', [Parameter(Mandatory = $false)] [string] $DefaultCommandPrefix, [Parameter(Mandatory = $false)] [switch] $AzureSpec, [Parameter(Mandatory = $false)] [switch] $DisableVersionSuffix, [Parameter(Mandatory = $false)] [hashtable] $PowerShellCodeGen, [Parameter(Mandatory = $false)] [PSCustomObject] $PSMetaJsonObject ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $swaggerDocObject = ConvertFrom-Json ((Get-Content $SwaggerSpecPath) -join [Environment]::NewLine) -ErrorAction Stop $swaggerDict = @{} if(-not (Get-Member -InputObject $swaggerDocObject -Name 'info')) { Throw $LocalizedData.InvalidSwaggerSpecification } if ($PowerShellCodeGen -and (Get-Member -InputObject $swaggerDocObject -Name 'securityDefinitions')) { $swaggerDict['SecurityDefinitions'] = $swaggerDocObject.securityDefinitions if ((Get-Member -InputObject $swaggerDocObject.securityDefinitions -Name 'azure_auth')) { $PowerShellCodeGen['ServiceType'] = 'azure' } } if ((Get-Member -InputObject $swaggerDocObject -Name 'security')) { $swaggerDict['Security'] = $swaggerDocObject.security } $GetSwaggerInfo_params = @{ Info = $swaggerDocObject.info ModuleVersion = $ModuleVersion } if($ModuleName) { $GetSwaggerInfo_params['ModuleName'] = $ModuleName } $swaggerDict['Info'] = Get-SwaggerInfo @GetSwaggerInfo_params $swaggerDict['Info']['DefaultCommandPrefix'] = $DefaultCommandPrefix $SwaggerParameters = @{} $SwaggerDefinitions = @{} $SwaggerPaths = @{} $PSMetaParametersJsonObject = $null if($PSMetaJsonObject) { if(Get-Member -InputObject $PSMetaJsonObject -Name 'parameters'){ $PSMetaParametersJsonObject = $PSMetaJsonObject.parameters } } foreach($FilePath in $SwaggerSpecFilePaths) { $swaggerObject = ConvertFrom-Json ((Get-Content $FilePath) -join [Environment]::NewLine) -ErrorAction Stop if(Get-Member -InputObject $swaggerObject -Name 'parameters') { $GetSwaggerParameters_Params = @{ Parameters = $swaggerObject.parameters Info = $swaggerDict['Info'] SwaggerParameters = $swaggerParameters DefinitionFunctionsDetails = $DefinitionFunctionsDetails AzureSpec = $AzureSpec PSMetaParametersJsonObject = $PSMetaParametersJsonObject } Get-SwaggerParameters @GetSwaggerParameters_Params } if(Get-Member -InputObject $swaggerObject -Name 'definitions') { Get-SwaggerDefinitionMultiItemObject -Object $swaggerObject.definitions -SwaggerDictionary $SwaggerDefinitions } if(-not (Get-Member -InputObject $swaggerObject -Name 'paths') -or -not (Get-HashtableKeyCount -Hashtable $swaggerObject.Paths.PSObject.Properties)) { Write-Warning -Message ($LocalizedData.SwaggerPathsMissing -f $FilePath) } Get-SwaggerPathMultiItemObject -Object $swaggerObject.paths -SwaggerDictionary $SwaggerPaths } $swaggerDict['Parameters'] = $swaggerParameters $swaggerDict['Definitions'] = $swaggerDefinitions $swaggerDict['Paths'] = $swaggerPaths return $swaggerDict } function Get-SwaggerInfo { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [PSCustomObject] $Info, [Parameter(Mandatory=$false)] [string] $ModuleName, [Parameter(Mandatory=$false)] [Version] $ModuleVersion = '0.0.1' ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $infoVersion = '1-0-0' if((Get-Member -InputObject $Info -Name 'Version') -and $Info.Version) { $infoVersion = $Info.Version } $infoTitle = $Info.title $CodeOutputDirectory = '' $infoName = '' $NameSpace = '' $codeGenFileRequired = $false $modelsName = 'Models' if(Get-Member -InputObject $Info -Name 'x-ms-code-generation-settings') { $prop = Test-PropertyWithAliases -InputObject $Info.'x-ms-code-generation-settings' -Aliases @('ClientName', 'Name') if ($prop) { $infoName = $Info.'x-ms-code-generation-settings'.$prop } $prop = Test-PropertyWithAliases -InputObject $Info.'x-ms-code-generation-settings' -Aliases @('OutputDirectory', 'o', 'output') if ($prop) { # When OutputDirectory is specified, we'll have to copy the code from here to the module directory later on $CodeOutputDirectory = $Info.'x-ms-code-generation-settings'.$prop if ((Test-Path -Path $CodeOutputDirectory) -and (Get-ChildItem -Path (Join-Path -Path $CodeOutputDirectory -ChildPath "*.cs") -Recurse)) { throw $LocalizedData.OutputDirectoryMustBeEmpty -f ($CodeOutputDirectory) } else { Write-Warning -Message ($LocalizedData.CodeDirectoryWillBeCreated -f $CodeOutputDirectory) } } $prop = Test-PropertyWithAliases -InputObject $Info.'x-ms-code-generation-settings' -Aliases @('ModelsName', 'mname') if ($prop) { # When ModelsName is specified, this changes the subnamespace of the models from 'Models' to whatever is specified $modelsName = $Info.'x-ms-code-generation-settings'.$prop } $prop = Test-PropertyWithAliases -InputObject $Info.'x-ms-code-generation-settings' -Aliases @('Namespace', 'n') if ($prop) { # When NameSpace is specified, this overrides our namespace $NameSpace = $Info.'x-ms-code-generation-settings'.$prop # Warn the user that custom namespaces are not recommended Write-Warning -Message $LocalizedData.CustomNamespaceNotRecommended } # When the following values are specified, the property will be overwritten by PSSwagger using a CodeGenSettings file foreach ($ignoredParameterAliases in $script:IgnoredAutoRestParameters) { $prop = Test-PropertyWithAliases -InputObject $Info.'x-ms-code-generation-settings' -Aliases $ignoredParameterAliases if ($prop) { Write-Warning -Message ($LocalizedData.AutoRestParameterIgnored -f ($prop, $Info.'x-ms-code-generation-settings'.$prop)) $codeGenFileRequired = $true } } } if (-not $infoName) { # Remove special characters as info name is used as client variable name in the generated commands. $infoName = ($infoTitle -replace '[^a-zA-Z0-9_]','') } $Description = '' if((Get-Member -InputObject $Info -Name 'Description') -and $Info.Description) { $Description = $Info.Description } $ProjectUri = '' $ContactEmail = '' $ContactName = '' if(Get-Member -InputObject $Info -Name 'Contact') { # The identifying name of the contact person/organization. if((Get-Member -InputObject $Info.Contact -Name 'Name') -and $Info.Contact.Name) { $ContactName = $Info.Contact.Name } # The URL pointing to the contact information. MUST be in the format of a URL. if((Get-Member -InputObject $Info.Contact -Name 'Url') -and $Info.Contact.Url) { $ProjectUri = $Info.Contact.Url } # The email address of the contact person/organization. MUST be in the format of an email address. if((Get-Member -InputObject $Info.Contact -Name 'Email') -and $Info.Contact.Email) { $ContactEmail = $Info.Contact.Email } } $LicenseUri = '' $LicenseName = '' if(Get-Member -InputObject $Info -Name 'License') { # A URL to the license used for the API. MUST be in the format of a URL. if((Get-Member -InputObject $Info.License -Name 'Url') -and $Info.License.Url) { $LicenseUri = $Info.License.Url } # License name. if((Get-Member -InputObject $Info.License -Name 'Name') -and $Info.License.Name) { $LicenseName = $Info.License.Name } } # Using the info name as module name when $ModuleName is not specified. # This is required for PSMeta generaration. if(-not $ModuleName) { $ModuleName = $infoName } if (-not $NameSpace) { # Default namespace supports sxs $NamespaceVersionSuffix = "v$("$ModuleVersion" -replace '\.','')" $NameSpace = "$script:PSSwaggerDefaultNamespace.$ModuleName.$NamespaceVersionSuffix" } # AutoRest generates client name with 'Client' appended to info title when a NameSpace part is same as the info name. if($NameSpace.Split('.', [System.StringSplitOptions]::RemoveEmptyEntries) -contains $infoName) { $infoName = $infoName + 'Client' } return @{ InfoVersion = $infoVersion InfoTitle = $infoTitle InfoName = $infoName Version = $ModuleVersion NameSpace = $NameSpace ModuleName = $ModuleName Description = $Description ContactName = $ContactName ContactEmail = $ContactEmail ProjectUri = $ProjectUri LicenseUri = $LicenseUri LicenseName = $LicenseName CodeOutputDirectory = $CodeOutputDirectory CodeGenFileRequired = $codeGenFileRequired Models = $modelsName } } function Test-PropertyWithAliases { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [PSCustomObject] $InputObject, [Parameter(Mandatory=$true)] [string[]] $Aliases ) foreach ($alias in $Aliases) { if ((Get-Member -InputObject $InputObject -Name $alias) -and $InputObject.$alias) { return $alias } } return $null } function Get-SwaggerParameters { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [PSCustomObject] $Parameters, [Parameter(Mandatory=$true)] [PSCustomObject] $Info, [Parameter(Mandatory=$true)] [hashtable] $DefinitionFunctionsDetails, [Parameter(Mandatory=$true)] [PSCustomObject] $SwaggerParameters, [Parameter(Mandatory = $false)] [switch] $AzureSpec, [Parameter(Mandatory=$false)] [PSCustomObject] $PSMetaParametersJsonObject ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState foreach($Parameter in $Parameters.PSObject.Properties.GetEnumerator()) { $GlobalParameterName = $Parameter.Name $GPJsonValueObject = $Parameter.Value if ($SwaggerParameters.ContainsKey($GlobalParameterName)) { Write-Verbose -Message ($LocalizedData.SkippingExistingParameter -f $GlobalParameterName) continue } $IsParamMandatory = '$false' $ParameterDescription = '' $x_ms_parameter_location = 'client' $x_ms_parameter_grouping = '' $ConstantValue = '' $ReadOnlyGlobalParameter = $false if ((Get-Member -InputObject $GPJsonValueObject -Name 'x-ms-client-name') -and $GPJsonValueObject.'x-ms-client-name') { $parameterName = Get-PascalCasedString -Name $GPJsonValueObject.'x-ms-client-name' } elseif ((Get-Member -InputObject $GPJsonValueObject -Name 'Name') -and $GPJsonValueObject.Name) { $parameterName = Get-PascalCasedString -Name $GPJsonValueObject.Name } if(Get-Member -InputObject $GPJsonValueObject -Name 'x-ms-parameter-location') { $x_ms_parameter_location = $GPJsonValueObject.'x-ms-parameter-location' } if ($AzureSpec) { # Some global parameters have constant values not expressed in the Swagger spec when dealing with Azure if ('subscriptionId' -eq $parameterName) { # See PSSwagger.Constants.ps1 $functionBodyStr for this variable name $ConstantValue = '`$subscriptionId' } elseif ('apiversion' -eq $parameterName) { $ReadOnlyGlobalParameter = $true } } if((Get-Member -InputObject $GPJsonValueObject -Name 'Required') -and $GPJsonValueObject.Required) { $IsParamMandatory = '$true' } if ((Get-Member -InputObject $GPJsonValueObject -Name 'Description') -and $GPJsonValueObject.Description) { $ParameterDescription = $GPJsonValueObject.Description } $GetParamTypeParams = @{ ParameterJsonObject = $GPJsonValueObject ModelsNameSpace = "$($Info.NameSpace).$($Info.Models)" ParameterName = $parameterName DefinitionFunctionsDetails = $DefinitionFunctionsDetails } $paramTypeObject = Get-ParamType @GetParamTypeParams if (Get-Member -InputObject $GPJsonValueObject -Name 'x-ms-parameter-grouping') { $groupObject = $GPJsonValueObject.'x-ms-parameter-grouping' if (Get-Member -InputObject $groupObject -Name 'name') { $parsedName = Get-ParameterGroupName -RawName $groupObject.name } elseif (Get-Member -InputObject $groupObject -Name 'postfix') { $parsedName = Get-ParameterGroupName -OperationId $OperationId -Postfix $groupObject.postfix } else { $parsedName = Get-ParameterGroupName -OperationId $OperationId } $x_ms_parameter_grouping = $parsedName } $FlattenOnPSCmdlet = $false if($PSMetaParametersJsonObject -and (Get-Member -InputObject $PSMetaParametersJsonObject -Name $GlobalParameterName) -and (Get-Member -InputObject $PSMetaParametersJsonObject.$GlobalParameterName -Name 'x-ps-parameter-info') -and (Get-Member -InputObject $PSMetaParametersJsonObject.$GlobalParameterName.'x-ps-parameter-info' -Name 'flatten')) { $FlattenOnPSCmdlet = $PSMetaParametersJsonObject.$GlobalParameterName.'x-ps-parameter-info'.'flatten' } $SwaggerParameters[$GlobalParameterName] = @{ Name = $parameterName Type = $paramTypeObject.ParamType ValidateSet = $paramTypeObject.ValidateSetString Mandatory = $IsParamMandatory Description = $ParameterDescription IsParameter = $paramTypeObject.IsParameter x_ms_parameter_location = $x_ms_parameter_location x_ms_parameter_grouping = $x_ms_parameter_grouping ConstantValue = $ConstantValue ReadOnlyGlobalParameter = $ReadOnlyGlobalParameter FlattenOnPSCmdlet = $FlattenOnPSCmdlet } } } function Get-SwaggerPathMultiItemObject { param( [Parameter(Mandatory=$true)] [PSCustomObject] $Object, [Parameter(Mandatory=$true)] [PSCustomObject] $SwaggerDictionary ) $Object.PSObject.Properties | ForEach-Object { if($SwaggerDictionary.ContainsKey($_.name)) { Write-Verbose -Message ($LocalizedData.SkippingExistingKeyFromSwaggerMultiItemObject -f $_) } else { $SwaggerDictionary[$_.name] = $_ } } } function Get-SwaggerDefinitionMultiItemObject { param( [Parameter(Mandatory=$true)] [PSCustomObject] $Object, [Parameter(Mandatory=$true)] [PSCustomObject] $SwaggerDictionary ) $Object.PSObject.Properties | ForEach-Object { $ModelName = Get-CSharpModelName -Name $_.Name if($SwaggerDictionary.ContainsKey($ModelName)) { Write-Verbose -Message ($LocalizedData.SkippingExistingKeyFromSwaggerMultiItemObject -f $ModelName) } else { $SwaggerDictionary[$ModelName] = $_ } } } function Get-PathParamInfo { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [PSObject] $JsonPathItemObject, [Parameter(Mandatory=$true)] [hashtable] $SwaggerDict, [Parameter(Mandatory=$true)] [hashtable] $DefinitionFunctionsDetails, [Parameter(Mandatory=$true)] [hashtable] $ParameterGroupCache, [Parameter(Mandatory=$true)] [hashtable] $ParametersTable, [Parameter(Mandatory=$false)] [PSCustomObject] $PSMetaParametersJsonObject ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $index = (Get-HashtableKeyCount -Hashtable $ParametersTable) $operationId = $null if(Get-Member -InputObject $JsonPathItemObject -Name 'OperationId'){ $operationId = $JsonPathItemObject.operationId } $JsonPathItemObject.parameters | ForEach-Object { $AllParameterDetails = Get-ParameterDetails -ParameterJsonObject $_ ` -SwaggerDict $SwaggerDict ` -DefinitionFunctionsDetails $DefinitionFunctionsDetails ` -OperationId $operationId ` -ParameterGroupCache $ParameterGroupCache ` -PSMetaParametersJsonObject $PSMetaParametersJsonObject foreach ($ParameterDetails in $AllParameterDetails) { if($ParameterDetails -and ($ParameterDetails.ContainsKey('x_ms_parameter_grouping_group') -or $ParameterDetails.Type)) { $ParametersTable[$index] = $ParameterDetails $index = $index + 1 } } } } function Get-ParameterDetails { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [PSObject] $ParameterJsonObject, [Parameter(Mandatory=$true)] [hashtable] $SwaggerDict, [Parameter(Mandatory=$true)] [hashtable] $DefinitionFunctionsDetails, [Parameter(Mandatory=$false)] [string] $OperationId, [Parameter(Mandatory=$true)] [hashtable] $ParameterGroupCache, [Parameter(Mandatory=$false)] [PSCustomObject] $PSMetaParametersJsonObject ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $NameSpace = $SwaggerDict['Info'].NameSpace $Models = $SwaggerDict['Info'].Models $DefinitionTypeNamePrefix = "$Namespace.$Models." $parameterName = '' if ((Get-Member -InputObject $ParameterJsonObject -Name 'x-ms-client-name') -and $ParameterJsonObject.'x-ms-client-name') { $parameterName = Get-PascalCasedString -Name $ParameterJsonObject.'x-ms-client-name' } elseif ((Get-Member -InputObject $ParameterJsonObject -Name 'Name') -and $ParameterJsonObject.Name) { $parameterName = Get-PascalCasedString -Name $ParameterJsonObject.Name } $GetParamTypeParameters = @{ ParameterJsonObject = $ParameterJsonObject ModelsNamespace = "$NameSpace.$Models" ParameterName = $parameterName DefinitionFunctionsDetails = $DefinitionFunctionsDetails SwaggerDict = $SwaggerDict } $paramTypeObject = Get-ParamType @GetParamTypeParameters # Swagger Path Operations can be defined with reference to the global method based parameters. # Add the method based global parameters as a function parameter. $AllParameterDetailsArrayTemp = @() $x_ms_parameter_grouping = '' if($paramTypeObject.GlobalParameterDetails) { $ParameterDetails = $paramTypeObject.GlobalParameterDetails $x_ms_parameter_grouping = $ParameterDetails.'x_ms_parameter_grouping' } else { $IsParamMandatory = '$false' $ParameterDescription = '' $x_ms_parameter_location = 'method' if ((Get-Member -InputObject $ParameterJsonObject -Name 'Required') -and $ParameterJsonObject.Required) { $IsParamMandatory = '$true' } if ((Get-Member -InputObject $ParameterJsonObject -Name 'Description') -and $ParameterJsonObject.Description) { $ParameterDescription = $ParameterJsonObject.Description } if ($OperationId -and (Get-Member -InputObject $ParameterJsonObject -Name 'x-ms-parameter-grouping')) { $groupObject = $ParameterJsonObject.'x-ms-parameter-grouping' if (Get-Member -InputObject $groupObject -Name 'name') { $parsedName = Get-ParameterGroupName -RawName $groupObject.name } elseif (Get-Member -InputObject $groupObject -Name 'postfix') { $parsedName = Get-ParameterGroupName -OperationId $OperationId -Postfix $groupObject.postfix } else { $parsedName = Get-ParameterGroupName -OperationId $OperationId } $x_ms_parameter_grouping = $parsedName } $FlattenOnPSCmdlet = $false if($PSMetaParametersJsonObject -and (Get-Member -InputObject $PSMetaParametersJsonObject -Name $parameterName) -and (Get-Member -InputObject $PSMetaParametersJsonObject.$parameterName -Name 'x-ps-parameter-info') -and (Get-Member -InputObject $PSMetaParametersJsonObject.$parameterName.'x-ps-parameter-info' -Name 'flatten')) { $FlattenOnPSCmdlet = $PSMetaParametersJsonObject.$parameterName.'x-ps-parameter-info'.'flatten' } $ParameterDetails = @{ Name = $parameterName Type = $paramTypeObject.ParamType ValidateSet = $paramTypeObject.ValidateSetString Mandatory = $IsParamMandatory Description = $ParameterDescription IsParameter = $paramTypeObject.IsParameter x_ms_parameter_location = $x_ms_parameter_location x_ms_parameter_grouping = $x_ms_parameter_grouping OriginalParameterName = $ParameterJsonObject.Name FlattenOnPSCmdlet = $FlattenOnPSCmdlet } } if ((Get-Member -InputObject $ParameterJsonObject -Name 'x-ms-client-flatten') -and $ParameterJsonObject.'x-ms-client-flatten') { $referenceTypeName = $ParameterDetails.Type.Replace($DefinitionTypeNamePrefix, '') # If the parameter should be flattened, return an array of parameter detail objects for each parameter of the referenced definition Write-Verbose -Message ($LocalizedData.FlatteningParameterType -f ($parameterName, $referenceTypeName)) $AllParameterDetails = @{} Expand-Parameters -ReferenceTypeName $referenceTypeName -DefinitionFunctionsDetails $DefinitionFunctionsDetails -AllParameterDetails $AllParameterDetails foreach ($expandedParameterDetail in $AllParameterDetails.GetEnumerator()) { Write-Verbose -Message ($LocalizedData.ParameterExpandedTo -f ($parameterName, $expandedParameterDetail.Key)) $AllParameterDetailsArrayTemp += $expandedParameterDetail.Value } } else { # If the parameter shouldn't be flattened, just return the original parameter detail object $AllParameterDetailsArrayTemp += $ParameterDetails } # Loop through the parameters in case they belong to different groups after being expanded $AllParameterDetailsArray = @() foreach ($expandedParameterDetail in $AllParameterDetailsArrayTemp) { # The parent parameter object, wherever it is, set a grouping name if ($x_ms_parameter_grouping) { $expandedParameterDetail.'x_ms_parameter_grouping' = $x_ms_parameter_grouping # An empty parameter details object is created that contains all known parameters in this group if ($ParameterGroupCache.ContainsKey($x_ms_parameter_grouping)) { $ParameterDetails = $ParameterGroupCache[$x_ms_parameter_grouping] } else { $ParameterDetails = @{ Name = $x_ms_parameter_grouping x_ms_parameter_grouping_group = @{} IsParameter = $true } } if (-not $ParameterDetails.'x_ms_parameter_grouping_group'.ContainsKey($expandedParameterDetail.Name)) { $ParameterDetails.'x_ms_parameter_grouping_group'[$expandedParameterDetail.Name] = $expandedParameterDetail } $AllParameterDetailsArray += $ParameterDetails $ParameterGroupCache[$x_ms_parameter_grouping] = $ParameterDetails } else { $AllParameterDetailsArray += $expandedParameterDetail } } # Properties of ParameterDetails object # .x_ms_parameter_grouping - string - non-empty if this is part of a group, contains the group's parsed name (should be the C# Type name) # .x_ms_parameter_grouping_group - hashtable - table of parameter names to ParameterDetails, indicates this ParameterDetails object is a grouping return $AllParameterDetailsArray } function Expand-Parameters { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string] $ReferenceTypeName, [Parameter(Mandatory=$true)] [hashtable] $DefinitionFunctionsDetails, [Parameter(Mandatory=$true)] [hashtable] $AllParameterDetails ) # Expand unexpanded x-ms-client-flatten # Leave it unexpanded afterwards if ($DefinitionFunctionsDetails[$ReferenceTypeName].ContainsKey('Unexpanded_x_ms_client_flatten_DefinitionNames') -and ($DefinitionFunctionsDetails[$ReferenceTypeName].'Unexpanded_x_ms_client_flatten_DefinitionNames'.Count -gt 0)) { foreach ($unexpandedDefinitionName in $DefinitionFunctionsDetails[$ReferenceTypeName].'Unexpanded_x_ms_client_flatten_DefinitionNames') { if ($DefinitionFunctionsDetails[$unexpandedDefinitionName].ContainsKey('ExpandedParameters') -and -not $DefinitionFunctionsDetails[$unexpandedDefinitionName].ExpandedParameters) { Expand-Parameters -ReferenceTypeName $unexpandedDefinitionName -DefinitionFunctionsDetails $DefinitionFunctionsDetails -AllParameterDetails $AllParameterDetails } Flatten-ParameterTable -ReferenceTypeName $unexpandedDefinitionName -DefinitionFunctionsDetails $DefinitionFunctionsDetails -AllParameterDetails $AllParameterDetails } } Flatten-ParameterTable -ReferenceTypeName $ReferenceTypeName -DefinitionFunctionsDetails $DefinitionFunctionsDetails -AllParameterDetails $AllParameterDetails } <# .DESCRIPTION Flattens the given type's parameter table into cmdlet parameters. #> function Flatten-ParameterTable { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $ReferenceTypeName, [Parameter(Mandatory=$true)] [hashtable] $DefinitionFunctionsDetails, [Parameter(Mandatory=$true)] [hashtable] $AllParameterDetails ) foreach ($parameterEntry in $DefinitionFunctionsDetails[$ReferenceTypeName]['ParametersTable'].GetEnumerator()) { if ($AllParameterDetails.ContainsKey($parameterEntry.Key)) { throw $LocalizedData.DuplicateExpandedProperty -f ($parameterEntry.Key) } $AllParameterDetails[$parameterEntry.Key] = Clone-ParameterDetail -ParameterDetail $parameterEntry.Value -OtherEntries @{'IsParameter'=$true} } } <# .DESCRIPTION Clones a given parameter detail object by shallow copying all properties. Optionally adds additional entries. #> function Clone-ParameterDetail { param( [Parameter(Mandatory=$true)] [hashtable] $ParameterDetail, [Parameter(Mandatory=$false)] [hashtable] $OtherEntries ) $clonedParameterDetail = @{} foreach ($kvp in $ParameterDetail.GetEnumerator()) { $clonedParameterDetail[$kvp.Key] = $kvp.Value } foreach ($kvp in $OtherEntries.GetEnumerator()) { $clonedParameterDetail[$kvp.Key] = $kvp.Value } return $clonedParameterDetail } function Get-ParamType { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [PSObject] $ParameterJsonObject, [Parameter(Mandatory=$true)] [string] $ModelsNamespace, [Parameter(Mandatory=$true)] [string] [AllowEmptyString()] $ParameterName, [Parameter(Mandatory=$false)] [hashtable] $SwaggerDict, [Parameter(Mandatory=$false)] [hashtable] $DefinitionFunctionsDetails ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $DefinitionTypeNamePrefix = "$ModelsNamespace." $paramType = "" $ValidateSetString = $null $isParameter = $true $GlobalParameterDetails = $null $ReferenceTypeName = $null if((Get-Member -InputObject $ParameterJsonObject -Name 'Type') -and $ParameterJsonObject.Type) { $paramType = $ParameterJsonObject.Type # Use the format as parameter type if that is available as a type in PowerShell if ((Get-Member -InputObject $ParameterJsonObject -Name 'Format') -and $ParameterJsonObject.Format -and ($null -ne ($ParameterJsonObject.Format -as [Type]))) { $paramType = $ParameterJsonObject.Format } elseif (($ParameterJsonObject.Type -eq 'array') -and (Get-Member -InputObject $ParameterJsonObject -Name 'Items') -and $ParameterJsonObject.Items) { if((Get-Member -InputObject $ParameterJsonObject.Items -Name '$ref') -and $ParameterJsonObject.Items.'$ref') { $ReferenceTypeValue = $ParameterJsonObject.Items.'$ref' $ReferenceTypeName = Get-CSharpModelName -Name $ReferenceTypeValue.Substring( $( $ReferenceTypeValue.LastIndexOf('/') ) + 1 ) $paramType = $DefinitionTypeNamePrefix + "$ReferenceTypeName[]" } elseif((Get-Member -InputObject $ParameterJsonObject.Items -Name 'Type') -and $ParameterJsonObject.Items.Type) { $ReferenceTypeName = Get-PSTypeFromSwaggerObject -JsonObject $ParameterJsonObject.Items $paramType = "$($ReferenceTypeName)[]" } } elseif ((Get-Member -InputObject $ParameterJsonObject -Name 'AdditionalProperties') -and $ParameterJsonObject.AdditionalProperties) { # Dictionary if($ParameterJsonObject.Type -eq 'object') { if((Get-Member -InputObject $ParameterJsonObject.AdditionalProperties -Name 'Type') -and $ParameterJsonObject.AdditionalProperties.Type) { $AdditionalPropertiesType = Get-PSTypeFromSwaggerObject -JsonObject $ParameterJsonObject.AdditionalProperties $paramType = "System.Collections.Generic.Dictionary[[$AdditionalPropertiesType],[$AdditionalPropertiesType]]" } elseif((Get-Member -InputObject $ParameterJsonObject.AdditionalProperties -Name '$ref') -and $ParameterJsonObject.AdditionalProperties.'$ref') { $ReferenceTypeValue = $ParameterJsonObject.AdditionalProperties.'$ref' $ReferenceTypeName = Get-CSharpModelName -Name $ReferenceTypeValue.Substring( $( $ReferenceTypeValue.LastIndexOf('/') ) + 1 ) $AdditionalPropertiesType = $DefinitionTypeNamePrefix + "$ReferenceTypeName" $paramType = "System.Collections.Generic.Dictionary[[string],[$AdditionalPropertiesType]]" } else { $Message = $LocalizedData.UnsupportedSwaggerProperties -f ('ParameterJsonObject', $($ParameterJsonObject | Out-String)) Write-Warning -Message $Message } } else { $Message = $LocalizedData.UnsupportedSwaggerProperties -f ('ParameterJsonObject', $($ParameterJsonObject | Out-String)) Write-Warning -Message $Message } } } elseif($parameterName -eq 'Properties' -and (Get-Member -InputObject $ParameterJsonObject -Name 'x-ms-client-flatten') -and ($ParameterJsonObject.'x-ms-client-flatten') ) { # 'x-ms-client-flatten' extension allows to flatten deeply nested properties into the current definition. # Users often provide feedback that they don't want to create multiple levels of properties to be able to use an operation. # By applying the x-ms-client-flatten extension, you move the inner properties to the top level of your definition. $ReferenceParameterValue = $ParameterJsonObject.'$ref' $x_ms_client_flatten_ReferenceTypeName = Get-CSharpModelName -Name $ReferenceParameterValue.Substring( $( $ReferenceParameterValue.LastIndexOf('/') ) + 1 ) Set-TypeUsedAsClientFlatten -ReferenceTypeName $x_ms_client_flatten_ReferenceTypeName -DefinitionFunctionsDetails $DefinitionFunctionsDetails } elseif ( (Get-Member -InputObject $ParameterJsonObject -Name '$ref') -and ($ParameterJsonObject.'$ref') ) { <# Currently supported parameter references: #/parameters/<PARAMETERNAME> or #../../<Parameters>.Json/parameters/<PARAMETERNAME> #/definitions/<DEFINITIONNAME> or #../../<Definitions>.Json/definitions/<DEFINITIONNAME> #> $ReferenceParameterValue = $ParameterJsonObject.'$ref' $ReferenceParts = $ReferenceParameterValue -split '/' | ForEach-Object { if($_.Trim()){ $_.Trim() } } if($ReferenceParts.Count -ge 3) { if($ReferenceParts[-2] -eq 'Parameters') { # #<...>/parameters/<PARAMETERNAME> $GlobalParameters = $SwaggerDict['Parameters'] $GlobalParamDetails = $GlobalParameters[$ReferenceParts[-1]] # Get the definition name of the global parameter so that 'New-<DefinitionName>Object' can be generated. if($GlobalParamDetails.Type -and $GlobalParamDetails.Type -match '[.]') { $ReferenceTypeName = ($GlobalParamDetails.Type -split '[.]')[-1] } # Valid values for this extension are: "client", "method". $GlobalParameterDetails = $GlobalParamDetails if(-not ($GlobalParamDetails -and $GlobalParamDetails.ContainsKey('x_ms_parameter_location') -and ($GlobalParamDetails.x_ms_parameter_location -eq 'method'))) { $isParameter = $false } } elseif($ReferenceParts[-2] -eq 'Definitions') { # #<...>/definitions/<DEFINITIONNAME> $ReferenceTypeName = Get-CSharpModelName -Name $ReferenceParts[-1] $paramType = $DefinitionTypeNamePrefix + $ReferenceTypeName } } } elseif ((Get-Member -InputObject $ParameterJsonObject -Name 'Schema') -and ($ParameterJsonObject.Schema) -and (Get-Member -InputObject $ParameterJsonObject.Schema -Name '$ref') -and ($ParameterJsonObject.Schema.'$ref') ) { $ReferenceParameterValue = $ParameterJsonObject.Schema.'$ref' $ReferenceTypeName = Get-CSharpModelName -Name $ReferenceParameterValue.Substring( $( $ReferenceParameterValue.LastIndexOf('/') ) + 1 ) $paramType = $DefinitionTypeNamePrefix + $ReferenceTypeName if((Get-Member -InputObject $ParameterJsonObject -Name 'x-ms-client-flatten') -and ($ParameterJsonObject.'x-ms-client-flatten')) { Set-TypeUsedAsClientFlatten -ReferenceTypeName $ReferenceTypeName -DefinitionFunctionsDetails $DefinitionFunctionsDetails # Assigning $null to $ReferenceTypeName so that this referenced definition is not set as UsedAsPathOperationInputType $ReferenceTypeName = $null } } else { $paramType = 'object' } $paramType = Get-PSTypeFromSwaggerObject -ParameterType $paramType if ((Get-Member -InputObject $ParameterJsonObject -Name 'Enum') -and $ParameterJsonObject.Enum) { # AutoRest doesn't generate a parameter on Async method for the path operation # when a parameter is required and has singly enum value. # Also, no enum type gets generated by AutoRest. if(($ParameterJsonObject.Enum.Count -eq 1) -and (Get-Member -InputObject $ParameterJsonObject -Name 'Required') -and $ParameterJsonObject.Required -eq 'true') { $paramType = "" } elseif((Get-Member -InputObject $ParameterJsonObject -Name 'x-ms-enum') -and $ParameterJsonObject.'x-ms-enum' -and ($ParameterJsonObject.'x-ms-enum'.modelAsString -eq $false)) { $paramType = $DefinitionTypeNamePrefix + (Get-CSharpModelName -Name $ParameterJsonObject.'x-ms-enum'.Name) } else { $ValidateSet = $ParameterJsonObject.Enum | ForEach-Object {$_ -replace "'","''"} $ValidateSetString = "'$($ValidateSet -join "', '")'" } } if ($ReferenceTypeName) { $ReferencedDefinitionDetails = @{} if($DefinitionFunctionsDetails.ContainsKey($ReferenceTypeName)) { $ReferencedDefinitionDetails = $DefinitionFunctionsDetails[$ReferenceTypeName] } $ReferencedDefinitionDetails['UsedAsPathOperationInputType'] = $true } if($paramType -and (-not $paramType.Contains($DefinitionTypeNamePrefix)) -and ($null -eq ($paramType -as [Type]))) { Write-Warning -Message ($LocalizedData.InvalidPathParameterType -f $paramType, $ParameterName) } return @{ ParamType = $paramType ValidateSetString = $ValidateSetString IsParameter = $isParameter GlobalParameterDetails = $GlobalParameterDetails } } function Set-TypeUsedAsClientFlatten { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string] $ReferenceTypeName, [Parameter(Mandatory=$true)] [hashtable] $DefinitionFunctionsDetails ) $ReferencedFunctionDetails = @{} if($DefinitionFunctionsDetails.ContainsKey($ReferenceTypeName)) { $ReferencedFunctionDetails = $DefinitionFunctionsDetails[$ReferenceTypeName] } else { $ReferencedFunctionDetails['Name'] = $ReferenceTypeName } $ReferencedFunctionDetails['IsUsedAs_x_ms_client_flatten'] = $true $DefinitionFunctionsDetails[$ReferenceTypeName] = $ReferencedFunctionDetails } function Get-PSTypeFromSwaggerObject { param( [Parameter(Mandatory=$false)] [AllowEmptyString()] [string] $ParameterType, [Parameter(Mandatory=$false)] [PSObject] $JsonObject ) $ParameterFormat = $null if($JsonObject) { if((Get-Member -InputObject $JsonObject -Name 'Type') -and $JsonObject.Type) { $ParameterType = $JsonObject.Type } if((Get-Member -InputObject $JsonObject -Name 'Format') -and $JsonObject.Format -and ($null -ne ($JsonObject.Format -as [Type]))) { $ParameterFormat = $JsonObject.Format } } switch ($ParameterType) { 'Boolean' { $ParameterType = 'switch' break } 'Integer' { if($ParameterFormat) { $ParameterType = $ParameterFormat } else { $ParameterType = 'int64' } break } 'Number' { if($ParameterFormat) { $ParameterType = $ParameterFormat } else { $ParameterType = 'double' } break } } return $ParameterType } function Get-SingularizedValue { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $Name ) if($script:PluralizationService) { $Name = $script:PluralizationService.Singularize($Name) } return Get-PascalCasedString -Name $Name } function Get-PathCommandName { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [string] $OperationId ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $opId = $OperationId if ($script:CmdVerbTrie -eq $null) { $script:CmdVerbTrie = New-Trie $script:PSCommandVerbMap.GetEnumerator() | ForEach-Object { $script:CmdVerbTrie = Add-WordToTrie -Word $_.Name -Trie $script:CmdVerbTrie } # Add approved verbs to Command Verb Trie Get-Verb | ForEach-Object { $script:CmdVerbTrie = Add-WordToTrie -Word $_.Verb -Trie $script:CmdVerbTrie } } $currentTriePtr = $script:CmdVerbTrie $opIdValues = $opId -split "_",2 if($opIdValues -and ($opIdValues.Count -eq 2)) { $cmdNoun = (Get-SingularizedValue -Name $opIdValues[0]) $cmdVerb = $opIdValues[1] } else { # OperationId can be specified without '_' (Underscore), Verb will retrieved by the below logic for non-approved verbs. $cmdNoun = '' $cmdVerb = Get-SingularizedValue -Name $opId } if (-not (Get-Verb -Verb $cmdVerb)) { $UnapprovedVerb = $cmdVerb $message = $LocalizedData.UnapprovedVerb -f ($UnapprovedVerb) Write-Verbose $message if ($script:PSCommandVerbMap.ContainsKey($cmdVerb)) { # This condition happens when there aren't any suffixes $cmdVerb = $script:PSCommandVerbMap[$cmdVerb] -Split ',' | ForEach-Object { if($_.Trim()){ $_.Trim() } } $cmdVerb | ForEach-Object { $message = $LocalizedData.ReplacedVerb -f ($_, $UnapprovedVerb) Write-Verbose -Message $message } } else { # This condition happens in cases like: CreateSuffix, CreateOrUpdateSuffix $longestVerbMatch = $null $currentVerbCandidate = '' $firstWord = '' $firstWordStarted = $false $buildFirstWord = $false $firstWordEnd = -1 $verbMatchEnd = -1 for($i = 0; $i -lt $UnapprovedVerb.Length; $i++) { # Add the start condition of the first word so that the end condition is easier if (-not $firstWordStarted) { $firstWordStarted = $true $buildFirstWord = $true } elseif ($buildFirstWord -and ([int]$UnapprovedVerb[$i] -ge 65) -and ([int]$UnapprovedVerb[$i] -le 90)) { # Stop building the first word when we encounter another capital letter $buildFirstWord = $false $firstWordEnd = $i } if ($buildFirstWord) { $firstWord += $UnapprovedVerb[$i] } if ($currentTriePtr) { # If we're still running along the trie just fine, keep checking the next letter $currentVerbCandidate += $UnapprovedVerb[$i] $currentTriePtr = Test-Trie -Trie $currentTriePtr -Letter $UnapprovedVerb[$i] if ($currentTriePtr -and (Test-TrieLeaf -Trie $currentTriePtr)) { # The latest verb match is also the longest verb match $longestVerbMatch = $currentVerbCandidate $verbMatchEnd = $i+1 } } } if ($longestVerbMatch) { $beginningOfSuffix = $verbMatchEnd $cmdVerb = $longestVerbMatch } else { $beginningOfSuffix = $firstWordEnd $cmdVerb = $firstWord } if ($script:PSCommandVerbMap.ContainsKey($cmdVerb)) { $cmdVerb = $script:PSCommandVerbMap[$cmdVerb] -Split ',' | ForEach-Object { if($_.Trim()){ $_.Trim() } } } if (-1 -ne $beginningOfSuffix) { # This is still empty when a verb match is found that is the entire string, but it might not be worth checking for that case and skipping the below operation $cmdNounSuffix = $UnapprovedVerb.Substring($beginningOfSuffix) # Add command noun suffix only when the current noun doesn't contain it or vice-versa. if(-not $cmdNoun -or (($cmdNoun -notmatch $cmdNounSuffix) -and ($cmdNounSuffix -notmatch $cmdNoun))) { $cmdNoun = $cmdNoun + (Get-PascalCasedString -Name $UnapprovedVerb.Substring($beginningOfSuffix)) } elseif($cmdNounSuffix -match $cmdNoun) { $cmdNoun = $cmdNounSuffix } } } } # Singularize command noun if($cmdNoun) { $cmdNoun = Get-SingularizedValue -Name $cmdNoun } $cmdletInfos = $cmdVerb | ForEach-Object { $Verb = Get-PascalCasedString -Name $_ if($cmdNoun){ $CommandName = "$Verb-$cmdNoun" } else { $CommandName = Get-SingularizedValue -Name $Verb } $cmdletInfo = @{} $cmdletInfo['name'] = $CommandName $cmdletInfo Write-Verbose -Message ($LocalizedData.UsingCmdletNameForSwaggerPathOperation -f ($CommandName, $OperationId)) } return $cmdletInfos } function Get-PathFunctionBody { [CmdletBinding()] param ( [Parameter(Mandatory=$true)] [PSCustomObject[]] $ParameterSetDetails, [Parameter(Mandatory=$true)] [string] [AllowEmptyString()] $ODataExpressionBlock, [Parameter(Mandatory=$true)] [string] [AllowEmptyString()] $ParameterGroupsExpressionBlock, [Parameter(Mandatory=$true)] [string] [AllowEmptyString()] $GlobalParameterBlock, [Parameter(Mandatory=$true)] [PSCustomObject] $SwaggerDict, [Parameter(Mandatory=$true)] [PSCustomObject] $SwaggerMetaDict, [Parameter(Mandatory=$true)] [string] $SecurityBlock, [Parameter(Mandatory=$true)] [string] [AllowEmptyString()] $OverrideBaseUriBlock, [Parameter(Mandatory=$true)] [PSCustomObject] $FlattenedParametersOnPSCmdlet, [Parameter(Mandatory=$true)] [string] $ClientArgumentList ) Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $outputTypeBlock = $null $Info = $swaggerDict['Info'] $DefinitionList = $swaggerDict['Definitions'] $UseAzureCsharpGenerator = $SwaggerMetaDict['UseAzureCsharpGenerator'] $infoVersion = $Info['infoVersion'] $modulePostfix = $Info['infoName'] $clientName = '$' + $modulePostfix $NameSpace = $info.namespace $fullModuleName = $Namespace + '.' + $modulePostfix $apiVersion = $null $SubscriptionId = $null $BaseUri = $null $GetServiceCredentialStr = '' $AdvancedFunctionEndCodeBlock = '' $GetServiceCredentialStr = 'Get-AzServiceCredential' # Expanding again expands $clientName $GlobalParameterBlock = $executionContext.InvokeCommand.ExpandString($GlobalParameterBlock) $parameterSetBasedMethodStr = '' foreach ($parameterSetDetail in $ParameterSetDetails) { # Responses isn't actually used right now, but keeping this when we need to handle responses per parameter set $Responses = $parameterSetDetail.Responses $operationId = $parameterSetDetail.OperationId $methodName = $parameterSetDetail.MethodName $operations = $parameterSetDetail.Operations $ParamList = $parameterSetDetail.ExpandedParamList $Cmdlet = '' if ($parameterSetDetail.ContainsKey('Cmdlet') -and $parameterSetDetail.Cmdlet) { $Cmdlet = $parameterSetDetail.Cmdlet } $CmdletArgs = '' if ($parameterSetDetail.ContainsKey('CmdletArgs') -and $parameterSetDetail.CmdletArgs) { $CmdletArgs = $parameterSetDetail.CmdletArgs } $CmdletParameter = '' if ($parameterSetDetail.ContainsKey('CmdletParameter') -and $parameterSetDetail.CmdletParameter) { $CmdletParameter = $parameterSetDetail.CmdletParameter } if ($Responses) { $responseBodyParams = @{ responses = $Responses.PSObject.Properties namespace = $Namespace definitionList = $DefinitionList Models = $Info.Models } $responseBody, $currentOutputTypeBlock = Get-Response @responseBodyParams # For now, use the first non-empty output type if ((-not $outputTypeBlock) -and $currentOutputTypeBlock) { $outputTypeBlock = $currentOutputTypeBlock } } if ($methodName) { $methodBlock = $executionContext.InvokeCommand.ExpandString($methodBlockFunctionCall) } else { $methodBlock = $executionContext.InvokeCommand.ExpandString($methodBlockCmdletCall) } $additionalConditionStart = '' $additionalConditionEnd = '' if ($parameterSetDetail.ContainsKey('AdditionalConditions') -and $parameterSetDetail.AdditionalConditions) { if ($parameterSetDetail.AdditionalConditions.Count -eq 1) { $additionalConditionStart = " if ($($parameterSetDetail.AdditionalConditions[0])) {$([Environment]::NewLine)" $additionalConditionEnd = "$([Environment]::NewLine) } else { `$taskResult = `$null }" } elseif ($parameterSetDetail.AdditionalConditions.Count -gt 1) { $additionalConditionStart = " if (" foreach ($condition in $parameterSetDetail.AdditionalConditions) { $additionalConditionStart += "($condition) -and" } $additionalConditionStart = $additionalConditionStart.Substring(0, $additionalConditionStart.Length-5) $additionalConditionStart = ") {$([Environment]::NewLine)" $additionalConditionEnd = "$([Environment]::NewLine) } else { `$taskResult = `$null }" } } if ($parameterSetBasedMethodStr) { # Add the elseif condition $parameterSetBasedMethodStr += $executionContext.InvokeCommand.ExpandString($parameterSetBasedMethodStrElseIfCase) } else { # Add the beginning if condition $parameterSetBasedMethodStr += $executionContext.InvokeCommand.ExpandString($parameterSetBasedMethodStrIfCase) } } # Prepare the code block for constructing the actual operation parameters which got flattened on the generated cmdlet. $FlattenedParametersBlock = '' $FlattenedParametersOnPSCmdlet.GetEnumerator() | ForEach-Object { $SwaggerOperationParameterName = $_.Name $DefinitionDetails = $_.Value $FlattenedParamType = $DefinitionDetails.Name $FlattenedParametersList = $DefinitionDetails.ParametersTable.GetEnumerator() | ForEach-Object { $_.Name } $FlattenedParametersListStr = '' if($FlattenedParametersList) { $FlattenedParametersListStr = "@('$($flattenedParametersList -join "', '")')" } $FlattenedParametersBlock += $executionContext.InvokeCommand.ExpandString($constructFlattenedParameter) } $body = $executionContext.InvokeCommand.ExpandString($functionBodyStr) $bodyObject = @{ OutputTypeBlock = $outputTypeBlock; Body = $body; } $result = @{ BodyObject = $bodyObject ParameterSetDetails = $ParameterSetDetails } return $result } function Test-OperationNameInDefinitionList { param( [Parameter(Mandatory=$true)] [string] $Name, [Parameter(Mandatory=$true)] [PSCustomObject] $SwaggerDict ) return $SwaggerDict['Definitions'].ContainsKey($Name) } function Get-OutputType { param ( [Parameter(Mandatory=$true)] [PSCustomObject] $Schema, [Parameter(Mandatory=$true)] [string] $ModelsNamespace, [Parameter(Mandatory=$true)] [PSCustomObject] $DefinitionList ) $outputType = "" if(Get-member -inputobject $schema -name '$ref') { $ref = $schema.'$ref' $RefParts = $ref -split '/' | ForEach-Object { if($_.Trim()){ $_.Trim() } } if(($RefParts.Count -ge 3) -and ($RefParts[-2] -eq 'definitions')) { $key = Get-CSharpModelName -Name $RefParts[-1] if ($definitionList.ContainsKey($key)) { $definition = ($definitionList[$key]).Value if(Get-Member -InputObject $definition -name 'properties') { $fullPathDataType = "" if(Get-HashtableKeyCount -Hashtable $definition.properties.PSObject.Properties) { $defProperties = $definition.properties # If this data type is actually a collection of another $ref if(Get-member -InputObject $defProperties -Name 'value') { $defValue = $defProperties.value $outputValueType = "" # Iff the value has items with $ref nested properties, # this is a collection and hence we need to find the type of collection if((Get-Member -InputObject $defValue -Name 'items') -and (Get-Member -InputObject $defValue.items -Name '$ref')) { $defRef = $defValue.items.'$ref' $DefRefParts = $defRef -split '/' | ForEach-Object { if($_.Trim()){ $_.Trim() } } if(($DefRefParts.Count -ge 3) -and ($DefRefParts[-2] -eq 'definitions')) { $defKey = Get-CSharpModelName -Name $DefRefParts[-1] $fullPathDataType = "$ModelsNamespace.$defKey" } if(Get-member -InputObject $defValue -Name 'type') { $defType = $defValue.type switch ($defType) { "array" { $outputValueType = '[]' } Default { $exceptionMessage = $LocalizedData.DataTypeNotImplemented -f ($defType, $ref) throw ([System.NotImplementedException] $exceptionMessage) } } } if($outputValueType -and $fullPathDataType) {$fullPathDataType = $fullPathDataType + " " + $outputValueType} } else { # if this datatype has value, but no $ref and items $fullPathDataType = "$ModelsNamespace.$key" } } else { # if this datatype is not a collection of another $ref $fullPathDataType = "$ModelsNamespace.$key" } } if($fullPathDataType) { $fullPathDataType = $fullPathDataType.Replace('[','').Replace(']','').Trim() $outputType += $executionContext.InvokeCommand.ExpandString($outputTypeStr) } } } } } return $outputType } function Get-Response { param ( [Parameter(Mandatory=$true)] [PSCustomObject] $Responses, [Parameter(Mandatory=$true)] [string] $NameSpace, [Parameter(Mandatory=$true)] [string] $Models, [Parameter(Mandatory=$true)] [hashtable] $DefinitionList ) $outputTypeFlag = $false $responseBody = "" $outputType = "" $failWithDesc = "" $failWithDesc = "" $responses | ForEach-Object { $responseStatusValue = "'" + $_.Name + "'" $value = $_.Value switch($_.Name) { # Handle Success {200..299 -contains $_} { if(-not $outputTypeFlag -and (Get-member -inputobject $value -name "schema")) { # Add the [OutputType] for the function $OutputTypeParams = @{ "schema" = $value.schema "ModelsNamespace" = "$NameSpace.$Models" "definitionList" = $definitionList } $outputType = Get-OutputType @OutputTypeParams $outputTypeFlag = $true } } # Handle Client Error {400..499 -contains $_} { if($Value.description) { $failureDescription = "Write-Error 'CLIENT ERROR: " + $value.description + "'" $failWithDesc += $executionContext.InvokeCommand.ExpandString($failCase) } } # Handle Server Error {500..599 -contains $_} { if($Value.description) { $failureDescription = "Write-Error 'SERVER ERROR: " + $value.description + "'" $failWithDesc += $executionContext.InvokeCommand.ExpandString($failCase) } } } } $responseBody += $executionContext.InvokeCommand.ExpandString($responseBodySwitchCase) return $responseBody, $outputType } <# Get-ToolsPath #> function Get-ToolsPath { [string]$AutoRestToolsPath = $null # Note: DLLs are automatically downloaded and extracted into the folder # "$env:USERPROFILE/.autorest/plugins/autorest/$VERSION" if they do not # exist for newer versions of autorest. [string]$basePath = Join-Path -Path $env:USERPROFILE -ChildPath ".autorest" | Join-Path -ChildPath "plugins" | Join-Path -ChildPath "autorest" if(Test-Path $basePath) { # Try to load newer version of autorest $versions = @(Get-ChildItem -Directory $basePath | ForEach-Object {[System.Version]$_.Name} | Sort-Object -Descending) if($versions.Length -ne 0) { [string]$version = $versions[0] # Get newest $AutoRestToolsPath = Join-Path -Path $basePath -ChildPath $version } } else { # Fallback to old version of autorest $AutoRestToolsPath = Get-Command -Name 'AutoRest.exe' | Select-Object -First 1 -ErrorAction Ignore | ForEach-Object {Split-Path -LiteralPath $_.Source} } if (-not ($AutoRestToolsPath)) { throw $LocalizedData.AutoRestNotInPath } return $AutoRestToolsPath } function Get-CSharpModelName { param( [Parameter(Mandatory=$true)] [string] $Name ) if (-not $script:CSharpCodeNamerLoadAttempted) { $script:CSharpCodeNamerLoadAttempted = $true $script:CSharpCodeNamer = New-ObjectFromDependency -TypeNames @('AutoRest.CSharp.CodeNamerCs', 'AutoRest.CSharp.CSharpCodeNamer') -AssemblyName 'AutoRest.CSharp.dll' -AssemblyResolver { param( [string] $AssemblyName ) [string]$AutoRestToolsPath = Get-ToolsPath $AssemblyFilePath = Join-Path -Path $AutoRestToolsPath -ChildPath $AssemblyName if(-not $AssemblyFilePath -or -not (Test-Path -LiteralPath $AssemblyFilePath -PathType Leaf)) { throw ($LocalizedData.PathNotFound -f $AssemblyFilePath) } Add-Type -LiteralPath $AssemblyFilePath } } if($script:CSharpCodeNamer) { return $script:CSharpCodeNamer.GetTypeName($Name) } else { return $Name.Replace('[','').Replace(']','') } } <# Create an object from an external dependency with possible type name changes. Optionally resolve the external dependency using a delegate. Input to $AssemblyResolver is $AssemblyName. Doesn't support constructors with args currently. #> function New-ObjectFromDependency { param( [Parameter(Mandatory=$true)] [string[]] $TypeNames, [Parameter(Mandatory=$true)] [string] $AssemblyName, [Parameter(Mandatory=$false)] [System.Action[string]] $AssemblyResolver ) if ($TypeNames.Count -gt 0) { $assemblyLoadAttempted = $false foreach ($typeName in $TypeNames) { if (-not ($typeName -as [Type])) { if (-not $assemblyLoadAttempted) { if ($AssemblyResolver -ne $null) { $AssemblyResolver.Invoke($AssemblyName) } else { $null = Add-Type -Path $AssemblyName } $assemblyLoadAttempted = $true } } else { return New-Object -TypeName $typeName } } } return $null } function Get-PowerShellCodeGenSettings { [CmdletBinding()] param( [Parameter(Mandatory=$true)] [string] $Path, [Parameter(Mandatory=$true)] [hashtable] $CodeGenSettings, [Parameter(Mandatory=$false)] [PSCustomObject] $PSMetaJsonObject ) if($PSMetaJsonObject) { $swaggerObject = $PSMetaJsonObject } else { $swaggerObject = ConvertFrom-Json ((Get-Content $Path) -join [Environment]::NewLine) -ErrorAction Stop } if ((Get-Member -InputObject $swaggerObject -Name 'info') -and (Get-Member -InputObject $swaggerObject.'info' -Name 'x-ps-code-generation-settings')) { $props = Get-Member -InputObject $swaggerObject.'info'.'x-ps-code-generation-settings' -MemberType NoteProperty foreach ($prop in $props) { if (-not $CodeGenSettings.ContainsKey($prop.Name)) { Write-Warning -Message ($LocalizedData.UnknownPSMetadataProperty -f ('x-ps-code-generation-settings', $prop.Name)) } else { $CodeGenSettings[$prop.Name] = $swaggerObject.'info'.'x-ps-code-generation-settings'.$($prop.Name) } } } } # SIG # Begin signature block # MIIasAYJKoZIhvcNAQcCoIIaoTCCGp0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUhI4H5sNjtsvBG9aGF+SO9Xhv # uMugghWDMIIEwzCCA6ugAwIBAgITMwAAALfuAa/68MeouwAAAAAAtzANBgkqhkiG # 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw # HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTYwOTA3MTc1ODQ1 # WhcNMTgwOTA3MTc1ODQ1WjCBszELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjENMAsGA1UECxMETU9QUjEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNO # OkJCRUMtMzBDQS0yREJFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT # ZXJ2aWNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuCMjQSw3ep1m # SndFRK0xgVRgm9wSl3i2llRtDdxzAWN9gQtYAE3hJP0/pV/7HHkshYPfMIRf7Pm/ # dxSsAN+7ATnNUk+wpe46rfe0FDNxoE6CYaiMSNjKcMXH55bGXNnwrrcsMaZrVXzS # IQcmAhUQw1jdLntbdTyCAwJ2UqF/XmVtWV/U466G8JP8VGLddeaucY0YKhgYwMnt # Sp9ElCkVDcUP01L9pgn9JmKUfD3yFt2p1iZ9VKCrlla10JQwe7aNW7xjzXxvcvlV # IXeA4QSabo4dq8HUh7JoYMqh3ufr2yNgTs/rSxG6D5ITcI0PZkH4PYjO2GbGIcOF # RVOf5RxVrwIDAQABo4IBCTCCAQUwHQYDVR0OBBYEFJZnqouaH5kw+n1zGHTDXjCT # 5OMAMB8GA1UdIwQYMBaAFCM0+NlSRnAK7UD7dvuzK7DDNbMPMFQGA1UdHwRNMEsw # SaBHoEWGQ2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3Rz # L01pY3Jvc29mdFRpbWVTdGFtcFBDQS5jcmwwWAYIKwYBBQUHAQEETDBKMEgGCCsG # AQUFBzAChjxodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jv # c29mdFRpbWVTdGFtcFBDQS5jcnQwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDQYJKoZI # hvcNAQEFBQADggEBAG7J+Fdd7DgxG6awnA8opmQfW5DHnNDC/JPLof1sA8Nqczym # cnWIHmlWhqA7TUy4q02lKenO+R/vbmHna1BrC/KkczAyhOzkI2WFU3PeYubv8EjK # fYPmrNvS8fCsHJXj3N6fuFwXkHmCVBjTchK93auG09ckBYx5Mt4zW0TUbbw4/QAZ # X64rbut6Aw/C1bpxqBb8vvMssBB9Hw2m8ApFTApaEVOE/sKemVlq0VIo0fCXqRST # Lb6/QOav3S8S+N34RBNx/aKKOFzBDy6Ni45QvtRfBoNX3f4/mm4TFdNs+SeLQA+0 # oBs7UgdoxGSpX6vsWaH8dtlBw3NZK7SFi9bBMI4wggTtMIID1aADAgECAhMzAAAB # QJap7nBW/swHAAEAAAFAMA0GCSqGSIb3DQEBBQUAMHkxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xIzAhBgNVBAMTGk1pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBMB4XDTE2MDgxODIwMTcxN1oXDTE3MTEwMjIwMTcxN1owgYMxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDTALBgNVBAsTBE1PUFIx # HjAcBgNVBAMTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjCCASIwDQYJKoZIhvcNAQEB # BQADggEPADCCAQoCggEBANtLi+kDal/IG10KBTnk1Q6S0MThi+ikDQUZWMA81ynd # ibdobkuffryavVSGOanxODUW5h2s+65r3Akw77ge32z4SppVl0jII4mzWSc0vZUx # R5wPzkA1Mjf+6fNPpBqks3m8gJs/JJjE0W/Vf+dDjeTc8tLmrmbtBDohlKZX3APb # LMYb/ys5qF2/Vf7dSd9UBZSrM9+kfTGmTb1WzxYxaD+Eaxxt8+7VMIruZRuetwgc # KX6TvfJ9QnY4ItR7fPS4uXGew5T0goY1gqZ0vQIz+lSGhaMlvqqJXuI5XyZBmBre # ueZGhXi7UTICR+zk+R+9BFF15hKbduuFlxQiCqET92ECAwEAAaOCAWEwggFdMBMG # A1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBSc5ehtgleuNyTe6l6pxF+QHc7Z # ezBSBgNVHREESzBJpEcwRTENMAsGA1UECxMETU9QUjE0MDIGA1UEBRMrMjI5ODAz # K2Y3ODViMWMwLTVkOWYtNDMxNi04ZDZhLTc0YWU2NDJkZGUxYzAfBgNVHSMEGDAW # gBTLEejK0rQWWAHJNy4zFha5TJoKHzBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v # Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNDb2RTaWdQQ0Ff # MDgtMzEtMjAxMC5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY0NvZFNpZ1BDQV8wOC0z # MS0yMDEwLmNydDANBgkqhkiG9w0BAQUFAAOCAQEAa+RW49cTHSBA+W3p3k7bXR7G # bCaj9+UJgAz/V+G01Nn5XEjhBn/CpFS4lnr1jcmDEwxxv/j8uy7MFXPzAGtOJar0 # xApylFKfd00pkygIMRbZ3250q8ToThWxmQVEThpJSSysee6/hU+EbkfvvtjSi0lp # DimD9aW9oxshraKlPpAgnPWfEj16WXVk79qjhYQyEgICamR3AaY5mLPuoihJbKwk # Mig+qItmLPsC2IMvI5KR91dl/6TV6VEIlPbW/cDVwCBF/UNJT3nuZBl/YE7ixMpT # Th/7WpENW80kg3xz6MlCdxJfMSbJsM5TimFU98KNcpnxxbYdfqqQhAQ6l3mtYDCC # BbwwggOkoAMCAQICCmEzJhoAAAAAADEwDQYJKoZIhvcNAQEFBQAwXzETMBEGCgmS # JomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29mdDEtMCsGA1UE # AxMkTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgz # MTIyMTkzMloXDTIwMDgzMTIyMjkzMloweTELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEjMCEGA1UEAxMaTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ # Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCycllcGTBkvx2aYCAg # Qpl2U2w+G9ZvzMvx6mv+lxYQ4N86dIMaty+gMuz/3sJCTiPVcgDbNVcKicquIEn0 # 8GisTUuNpb15S3GbRwfa/SXfnXWIz6pzRH/XgdvzvfI2pMlcRdyvrT3gKGiXGqel # cnNW8ReU5P01lHKg1nZfHndFg4U4FtBzWwW6Z1KNpbJpL9oZC/6SdCnidi9U3RQw # WfjSjWL9y8lfRjFQuScT5EAwz3IpECgixzdOPaAyPZDNoTgGhVxOVoIoKgUyt0vX # T2Pn0i1i8UU956wIAPZGoZ7RW4wmU+h6qkryRs83PDietHdcpReejcsRj1Y8wawJ # XwPTAgMBAAGjggFeMIIBWjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTLEejK # 0rQWWAHJNy4zFha5TJoKHzALBgNVHQ8EBAMCAYYwEgYJKwYBBAGCNxUBBAUCAwEA # ATAjBgkrBgEEAYI3FQIEFgQU/dExTtMmipXhmGA7qDFvpjy82C0wGQYJKwYBBAGC # NxQCBAweCgBTAHUAYgBDAEEwHwYDVR0jBBgwFoAUDqyCYEBWJ5flJRP8KuEKU5VZ # 5KQwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br # aS9jcmwvcHJvZHVjdHMvbWljcm9zb2Z0cm9vdGNlcnQuY3JsMFQGCCsGAQUFBwEB # BEgwRjBEBggrBgEFBQcwAoY4aHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9j # ZXJ0cy9NaWNyb3NvZnRSb290Q2VydC5jcnQwDQYJKoZIhvcNAQEFBQADggIBAFk5 # Pn8mRq/rb0CxMrVq6w4vbqhJ9+tfde1MOy3XQ60L/svpLTGjI8x8UJiAIV2sPS9M # uqKoVpzjcLu4tPh5tUly9z7qQX/K4QwXaculnCAt+gtQxFbNLeNK0rxw56gNogOl # VuC4iktX8pVCnPHz7+7jhh80PLhWmvBTI4UqpIIck+KUBx3y4k74jKHK6BOlkU7I # G9KPcpUqcW2bGvgc8FPWZ8wi/1wdzaKMvSeyeWNWRKJRzfnpo1hW3ZsCRUQvX/Ta # rtSCMm78pJUT5Otp56miLL7IKxAOZY6Z2/Wi+hImCWU4lPF6H0q70eFW6NB4lhhc # yTUWX92THUmOLb6tNEQc7hAVGgBd3TVbIc6YxwnuhQ6MT20OE049fClInHLR82zK # wexwo1eSV32UjaAbSANa98+jZwp0pTbtLS8XyOZyNxL0b7E8Z4L5UrKNMxZlHg6K # 3RDeZPRvzkbU0xfpecQEtNP7LN8fip6sCvsTJ0Ct5PnhqX9GuwdgR2VgQE6wQuxO # 7bN2edgKNAltHIAxH+IOVN3lofvlRxCtZJj/UBYufL8FIXrilUEnacOTj5XJjdib # Ia4NXJzwoq6GaIMMai27dmsAHZat8hZ79haDJLmIz2qoRzEvmtzjcT3XAH5iR9HO # iMm4GPoOco3Boz2vAkBq/2mbluIQqBC0N1AI1sM9MIIGBzCCA++gAwIBAgIKYRZo # NAAAAAAAHDANBgkqhkiG9w0BAQUFADBfMRMwEQYKCZImiZPyLGQBGRYDY29tMRkw # FwYKCZImiZPyLGQBGRYJbWljcm9zb2Z0MS0wKwYDVQQDEyRNaWNyb3NvZnQgUm9v # dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcwNDAzMTI1MzA5WhcNMjEwNDAz # MTMwMzA5WjB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw # HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwggEiMA0GCSqGSIb3DQEB # AQUAA4IBDwAwggEKAoIBAQCfoWyx39tIkip8ay4Z4b3i48WZUSNQrc7dGE4kD+7R # p9FMrXQwIBHrB9VUlRVJlBtCkq6YXDAm2gBr6Hu97IkHD/cOBJjwicwfyzMkh53y # 9GccLPx754gd6udOo6HBI1PKjfpFzwnQXq/QsEIEovmmbJNn1yjcRlOwhtDlKEYu # J6yGT1VSDOQDLPtqkJAwbofzWTCd+n7Wl7PoIZd++NIT8wi3U21StEWQn0gASkdm # EScpZqiX5NMGgUqi+YSnEUcUCYKfhO1VeP4Bmh1QCIUAEDBG7bfeI0a7xC1Un68e # eEExd8yb3zuDk6FhArUdDbH895uyAc4iS1T/+QXDwiALAgMBAAGjggGrMIIBpzAP # BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQjNPjZUkZwCu1A+3b7syuwwzWzDzAL # BgNVHQ8EBAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwgZgGA1UdIwSBkDCBjYAUDqyC # YEBWJ5flJRP8KuEKU5VZ5KShY6RhMF8xEzARBgoJkiaJk/IsZAEZFgNjb20xGTAX # BgoJkiaJk/IsZAEZFgltaWNyb3NvZnQxLTArBgNVBAMTJE1pY3Jvc29mdCBSb290 # IENlcnRpZmljYXRlIEF1dGhvcml0eYIQea0WoUqgpa1Mc1j0BxMuZTBQBgNVHR8E # STBHMEWgQ6BBhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9k # dWN0cy9taWNyb3NvZnRyb290Y2VydC5jcmwwVAYIKwYBBQUHAQEESDBGMEQGCCsG # AQUFBzAChjhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY3Jv # c29mdFJvb3RDZXJ0LmNydDATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0B # AQUFAAOCAgEAEJeKw1wDRDbd6bStd9vOeVFNAbEudHFbbQwTq86+e4+4LtQSooxt # YrhXAstOIBNQmd16QOJXu69YmhzhHQGGrLt48ovQ7DsB7uK+jwoFyI1I4vBTFd1P # q5Lk541q1YDB5pTyBi+FA+mRKiQicPv2/OR4mS4N9wficLwYTp2OawpylbihOZxn # LcVRDupiXD8WmIsgP+IHGjL5zDFKdjE9K3ILyOpwPf+FChPfwgphjvDXuBfrTot/ # xTUrXqO/67x9C0J71FNyIe4wyrt4ZVxbARcKFA7S2hSY9Ty5ZlizLS/n+YWGzFFW # 6J1wlGysOUzU9nm/qhh6YinvopspNAZ3GmLJPR5tH4LwC8csu89Ds+X57H2146So # dDW4TsVxIxImdgs8UoxxWkZDFLyzs7BNZ8ifQv+AeSGAnhUwZuhCEl4ayJ4iIdBD # 6Svpu/RIzCzU2DKATCYqSCRfWupW76bemZ3KOm+9gSd0BhHudiG/m4LBJ1S2sWo9 # iaF2YbRuoROmv6pH8BJv/YoybLL+31HIjCPJZr2dHYcSZAI9La9Zj7jkIeW1sMpj # tHhUBdRBLlCslLCleKuzoJZ1GtmShxN1Ii8yqAhuoFuMJb+g74TKIdbrHk/Jmu5J # 4PcBZW+JC33Iacjmbuqnl84xKf8OxVtc2E0bodj6L54/LlUWa8kTo/0xggSXMIIE # kwIBATCBkDB5MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSMw # IQYDVQQDExpNaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQQITMwAAAUCWqe5wVv7M # BwABAAABQDAJBgUrDgMCGgUAoIGwMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEE # MBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBTC # tUSUu72+8oP/8/qVuDfJZFUM+zBQBgorBgEEAYI3AgEMMUIwQKAWgBQAUABvAHcA # ZQByAFMAaABlAGwAbKEmgCRodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vUG93ZXJT # aGVsbCAwDQYJKoZIhvcNAQEBBQAEggEALPASQxd0p52LKnkCO7sgy2nGMXx1iTLq # Lnq2JexI6jMqHGb0hDWaUIX+Ueeg2EoVFrroB1otBa+SztTrrc+Yq1700Bj+Hknu # 4AFjXCIIYFjvnu45ybCx1yJjqiIvg/1+vLJ2gdk+g0+mDNTbRYOENTuYxagjKWHl # BQjT1MyHe9za148CybRdQmJrzO3YonrTsR7bhyhiWCy1EFAM4uUtUxyZET3+k+NI # u+gxwj+c12Hb6pygDoo8gh3oJkkufgE+VkWXUG7tnoYraxTzcYiA9nKFd4QyC5xt # 57OtGvMU6QwOxdFsw8mbS9105oQ8jOn+KNHYhQaz0BUJ7hhptDJ2QqGCAigwggIk # BgkqhkiG9w0BCQYxggIVMIICEQIBATCBjjB3MQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQ # Q0ECEzMAAAC37gGv+vDHqLsAAAAAALcwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJ # AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE3MDgwODE3MzUyMVowIwYJ # KoZIhvcNAQkEMRYEFH2RNVdMCpJgTtSMqc5VsF2Cni2gMA0GCSqGSIb3DQEBBQUA # BIIBAA/MKEPgbhOU7RhcpkBRghiNas6DQqKp3S1y10W53JThziOnIHXKTSe6OwlY # BHXi2WiwyMnwCXz6MyxDeQIeVHpqwzBWZVICFTXUqzBnKGmtsvN+QMPucKfNGnvw # lRFUr063SrvPhwlI6JMYybzfkH6D8Qz3x2aDxXp0VXop85odqZA4N7MXh4yGFNWv # gXi2oN2qUGJ+bnHUPVkCT7bZLzcHpdmkjkmSwBR8BeszYSn3TwEuIUQ/pA4zJzJg # r/Udv+g+mtka7rS4+8HLuj5DUSCxwCXVFDliqemm+k+QpiITGgsZF7SqKaXOZXrN # CMGf7BAQBGZvQIIzwOHSsrn65kk= # SIG # End signature block |