Private/Docs/ConvertFrom-AvmBicepDocsParameterBlock.ps1
|
function ConvertFrom-AvmBicepDocsParameterBlock { [CmdletBinding()] [OutputType([hashtable])] param( [AllowEmptyString()] [string] $Block, [Parameter(Mandatory)] [string] $SourcePath ) Set-StrictMode -Version 3.0 $ErrorActionPreference = 'Stop' if ([string]::IsNullOrWhiteSpace($Block)) { return @{} } $commentFree = Get-AvmBicepCommentFreeSource -Source $Block $lines = $commentFree.ReplaceLineEndings("`n") -split "`n" $firstParameter = $lines | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -First 1 if ($null -eq $firstParameter) { return @{} } $indent = ([regex]::Match($firstParameter, '^(\s+)')).Groups[1].Value.Length $names = @($lines | Where-Object { $_ -match "^\s{$indent}[0-9a-zA-Z]+:.*" } | ForEach-Object { ($_ -split ':')[0].Trim() }) $originalLines = $Block.ReplaceLineEndings("`n") -split "`n" $sourceLines = [System.Collections.Generic.List[string]]::new() $sourceLines.Add('{') for ($index = 0; $index -lt $lines.Count; $index++) { if (-not [string]::IsNullOrWhiteSpace($lines[$index])) { $sourceLines.Add($originalLines[$index]) } } $sourceLines.Add('}') $jsonLines = @('{', $commentFree, '}') -join "`n" $jsonLines = $jsonLines.Replace('"', '\"').Replace("'", '"') $jsonLines = @($jsonLines -split "`n" | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) for ($index = 0; $index -lt $jsonLines.Count; $index++) { $line = $jsonLines[$index] if ($null -eq $line) { continue } if ($line -match '^\s*//') { continue } $line = [regex]::Replace($line, '^\s*"{0}([0-9a-zA-Z_]+):', '"$1":', 1) if ($line -match '^\s*.+?:\s+') { $value = ($line -split '^\s*.+?:\s+')[1].Trim() $emptyObject = $line -match '^.+:\s*{\s*}\s*$' $propertyReference = $value -match '(?<=[^"])\b\.\b(?=[^"]*$)' $referenceKey = ($line -split ':')[0].Trim() -like '*.*' $interpolated = $value -match "['|`"]{1}.*(?<!\\)\$\{.+" $stringValue = $value -match '^".+"$' $functionValue = $value -match '^[a-zA-Z0-9]+\(.+' $plainValue = $value -match '^\w+$' $primitiveValue = $value -match '^\s*(true|false|[0-9])+$' $conditional = $value -match '^\w+ [=!?|&]{2} .+\?.+\:.+$' $multilineFunction = $value -match '[a-zA-Z]+\s*\([^\)]*\){0}\s*$' if ($multilineFunction) { $functionIndent = ([regex]::Match($jsonLines[$index], '^(\s+)')).Groups[1].Value.Length $end = $index + 1 while ($end -lt $jsonLines.Count -and $jsonLines[$end] -match "^\s{$($functionIndent+1),}") { $end++ } if ($end -ge $jsonLines.Count) { throw [AvmConfigurationException]::new( "Cannot locate the end of a Bicep function in '$SourcePath'.") } if ($jsonLines[$end] -notmatch '^\s*\)\s*$') { throw [AvmConfigurationException]::new( "Cannot locate the closing Bicep function parenthesis in '$SourcePath'.") } $key = ([regex]::Match(($line -split ':')[0], '"(.+)"')).Groups[1].Value $line = '{0}: "<{1}>"' -f ($line -split ':')[0], $key for ($functionLine = $index + 1; $functionLine -le $end; $functionLine++) { $jsonLines[$functionLine] = $null } } elseif ((-not $emptyObject -and -not $stringValue -and $propertyReference) -or $interpolated -or $functionValue -or ($plainValue -and -not $primitiveValue) -or $conditional) { $key = ([regex]::Match(($line -split ':')[0], '"(.+)"')).Groups[1].Value $line = '{0}: "<{1}>"' -f ($line -split ':')[0], $key } elseif ($emptyObject -and $referenceKey) { $line = '"<{0}>": {1}' -f (($line -split ':')[0] -split '\.')[-1].TrimEnd('}"'), $value } } else { if ($line -notlike '*"*"*' -and $line -like '*.*') { $placeholder = $line.Split('.')[-1].Trim() $reference = [regex]::Match( $sourceLines[$index].Trim(), '^(?<code>[a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)+)(?<comment>\s+//[^\r\n]*)$') if ($reference.Success -and $reference.Groups['code'].Value -ceq $line.Trim()) { $placeholder += $reference.Groups['comment'].Value.TrimEnd() $line = ConvertTo-Json -InputObject "<$placeholder>" -Compress } else { $line = '"<{0}>"' -f $placeholder } } elseif ($line -match '^\s*[a-zA-Z]+\s*$') { $line = '"<{0}>"' -f $line.Trim() } elseif ($line -match "['|`"]{1}.*\$\{.+") { $line = $line -replace '\$\{.+\}', '<value>' } } $jsonLines[$index] = $line -replace '\\\$', '\\$' } $jsonLines = @($jsonLines | Where-Object { $null -ne $_ }) for ($index = 0; $index -lt $jsonLines.Count; $index++) { $open = $jsonLines[$index] -match '[\{|\[]\s*$' $closingNext = $index -lt $jsonLines.Count - 1 -and $jsonLines[$index + 1] -match '^\s*[\]|\}]\s*$' if ($open -or $closingNext -or $index -eq $jsonLines.Count - 1 -or $jsonLines[$index] -match '^\s*//') { continue } $jsonLines[$index] = $jsonLines[$index].TrimEnd() + ',' } try { $parsed = ($jsonLines -join "`n") | ConvertFrom-Json -AsHashtable -Depth 99 -ErrorAction Stop } catch { throw [AvmConfigurationException]::new( "Cannot parse Bicep example parameters in '$SourcePath': $($_.Exception.Message)") } $parameters = @{} foreach ($name in $names) { if (-not $parsed.ContainsKey($name)) { throw [AvmConfigurationException]::new( "Bicep example '$SourcePath' is missing the extracted parameter '$name'.") } $parameters[$name] = @{ value = $parsed[$name] } } return $parameters } # SIG # Begin signature block # MIInUgYJKoZIhvcNAQcCoIInQzCCJz8CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAhPafaPYhVXpQh # mLiwjJPEL8ycPL6oueuNBSzyWE0GuKCCDMkwggYEMIID7KADAgECAhMzAAACHPrN # xZvoL37EAAAAAAIcMA0GCSqGSIb3DQEBCwUAMFcxCzAJBgNVBAYTAlVTMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBD # b2RlIFNpZ25pbmcgUENBIDIwMjQwHhcNMjYwNDE2MTg1OTQxWhcNMjcwNDE1MTg1 # OTQxWjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYD # VQQDExVNaWNyb3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IB # DwAwggEKAoIBAQDVsZfgOKmM31HPfoWOoNEiw0SlCiIxUMC0I9NMWbucKOw/e9lP # oAoehQVu6SG65V4EPzrYsnBnFPNoi4/HoOdjhz1qkrEt4I6tEcxXU6oOeY9zGveC # /3iBeuhLYxM3M/PkcUoebF+Nednm8OkdSPoDu8imViHPQq/8CQUu0WRR4rE+dMRf # rpVqfmNi2qWCX94T4MsepijGVkwE//tJg0ryAiYdHT34LSnlG/RSBZmQRGWZ5g8j # qnKjRParSqMft1gvjuUTVgtWNZfgcLFSK5Wa0myrq8OPcgTGGsRgun+tnSS+IxDT # xVsAPH1OzvPjwomguByhUe/OcvUN0D5Wmp7xAgMBAAGjggGqMIIBpjAOBgNVHQ8B # Af8EBAMCB4AwHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0O # BBYEFNoH7a2YDjOSwpkp6DHcmUS7J+0yMFQGA1UdEQRNMEukSTBHMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxFjAUBgNVBAUT # DTIzMDAxMis1MDc1NjkwHwYDVR0jBBgwFoAUf1k/VCHarU/vBeXmo9ctBpQSCDEw # YAYDVR0fBFkwVzBVoFOgUYZPaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w # cy9jcmwvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmclMjBQQ0ElMjAyMDI0LmNy # bDBtBggrBgEFBQcBAQRhMF8wXQYIKwYBBQUHMAKGUWh0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwQ29kZSUyMFNpZ25pbmcl # MjBQQ0ElMjAyMDI0LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IC # AQAUnEqhaRXe0T3hIJjvdQErEkrA/7bByjn6t5IArODkkRjzkYwtKMc2yYj2quaN # rLutWw2YZcngKPy1b71YyDJQTy4NDRwaSh9Tw5thrk3NmcPrAHia5vtcBJ1CgtKK # 7mQbIcQ22d/N3813ayCDDFewu1+jsZmX+r/aTEqaOM4TVxVtRSkuCy8nAXKuChOK # Li/zA4XuH8iEYqIsj2YoNaeSxVmeGiERXpKdo3dDmYi0kO5w2D8VS4c3+9h6gElY # BaAAg/dYErBg27qT3vv0zRDJhJufvCNylA8S7/+8H5E/PV5cng6na9VV/w9OV3qu # uND6zdGa2EX38Glp50F9AIQk3p2xXmcvorDeM4XJ7UlWYBi6g80J1SSOQnInCYFE # msfUNn3+1AaTJKSJL83quKArTac2pKhu0Yzzzrzo6HrsRiQKzpnRBb1/dMa6P3hz # 75XbMRBctNsFhZC07WCmjExdLg2eHW5uV0TY8D5+6wozJf7vF3+WHkYPO85Z+BC6 # U4FkNbYNycZ9cE4j1tXRdyDCfml6c0HWPHjNVDObrv9lKt3qUqFpX38VCqVCyNOO # 1UcXfQiVjJw32U2WUKZjt/neJKHEBsm9kFsLuWzkQ53+qcaSaytmsCnk2gOglrlD # 5d3kKyvvAw+rzm0lT8K38P6PLxfZQHhu4W8dV7Av8N2ZmDCCBr0wggSloAMCAQIC # EzMAAAA5O7Y3Gb8GHWcAAAAAADkwDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBS # b290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTI0MDgwODIwNTQxOFoX # DTM2MDMyMjIyMTMwNFowVzELMAkGA1UEBhMCVVMxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQ # Q0EgMjAyNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANgBnB7jOMeq # lRYHNa265v4IY9fH8TKhemHfPINe1gpLaV3dhg324WwH06LcHbpnsBukCDNitryo # 0dtS/EW6I/yEL/bLSY8hKpbfQuWusBPr9qazYcDxCW/qnjb5JsI1s8bNOg3bVATv # QVL4tcf03aTycsz8QeCdM0l/yHRObJ9QqazM1r6VPEOJ7LL+uEEb73w6QCuhs89a # 1uv1zerOYMnsneRRwCbpyW11IcggU0cRKDDq1pjVJzIbIF6+oiXXbReOsgeI8zu1 # FyQfK0fVkaya8SmVHQ/tOf23mZ4W9k0Ri22QW9p3UgSC5OUDktKxxcCmGL6tXLfO # GSWHIIV4YrTJTT6PNty5REojHJuZHArkF9VnHTERWoTjAzfI3kP+5b4alUdhgAZ7 # ttOu1bVnXfHaqPYl2rPs20ji03LOVWsh/radgE17es5hL+t6lV0eVHrVhsssROWJ # uz2MXMCt7iw7lFPG9LXKGjsmonn2gotGdHIuEg5JnJMJVmixd5LRlkmgYRZKzhxS # CwyoGIq0PhaA7Y+VPct5pCHkijcIIDm0nlkK+0KyepolcqGm0T/GYQRMhHJlGOOm # VQop36wUVUYklUy++vDWeEgEo4s7hxN6mIbf2MSIQ/iIfMZgJxC69oukMUXCrOC3 # SkE/xIkgpfl22MM1itkZ35nNXkMolU1lAgMBAAGjggFOMIIBSjAOBgNVHQ8BAf8E # BAMCAYYwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFH9ZP1Qh2q1P7wXl5qPX # LQaUEggxMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMA8GA1UdEwEB/wQFMAMB # Af8wHwYDVR0jBBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0fBFMwUTBP # oE2gS4ZJaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMv # TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRSMFAw # TgYIKwYBBQUHMAKGQmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMv # TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNydDANBgkqhkiG9w0BAQwFAAOC # AgEAFJQfOChP7onn6fLIMKrSlN1WYKwDFgAddymOUO3FrM8d7B/W/iQ6DxXsDn7D # 5W4wMwYeLystcEqfkjz4NURRgazyMu5yRzQh4LqjA4tStTcJh1opExo7nn5PuPBY # nbu0+THSuVHTe0VTTPVhily/piFrDo3axQ9P4C+Ol5yet+2gTfekICS5xS+cYfSI # vgn0JksVBVMYVI5QFu/qhnLhsEFEUzG8fvv0hjgkO+lkpV9ty6GkN4vdnd7ya6Q6 # aR9y34aiM1qmxaxBi6OUnyNl6fkuun/diTFnYDLTppOkr/mg5WSfCiDVMNCxtj4w # PKC5OmHm1DQIt/MNokbbH3UGsFP1QbzsLocuSqLCvH09Io3fDPTmscR9Y75G4qX7 # RTX8AdBPo0I6OEojf39zuFZt0qOHm65YWQE69cZM2ueE1MB05dNNgHK9gTE7zKvK # /fg8B2qjW88MT/WF5V5uvZGtqa9FSL2RazArA+rDPuf6JGYz4HpgMZHB4S6szWSK # YBv0VisCzfxgeU+dquXW9bd0auYlOB58DPcOYKdc3Se94g+xL4pcEhbB54JOgAkw # YTu/9dLeH2pDqeJZAABVDWRQCaXfO5LgyKwKCLYXpigrZYCjUSBcr+Ve8PFWMhVT # Ql0v4q8J/AUmQN5W4n101cY2L4A7GTQG1h32HHAvfQESWP0xghnfMIIZ2wIBATBu # MFcxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24x # KDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMjQCEzMAAAIc # +s3Fm+gvfsQAAAAAAhwwDQYJYIZIAWUDBAIBBQCggZAwGQYJKoZIhvcNAQkDMQwG # CisGAQQBgjcCAQQwLwYJKoZIhvcNAQkEMSIEIOjE0mVmnFQ6q1zzHHGBsCGQpEKU # HpDv8j7hvaTu5U9GMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBv # AGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAE # ggEAdUjE5db0d3XCmTRVusQULTc8/BDo6cc2Z8ohQ00sovb2J/84IZYAgDiWKClv # 32eahM+y14hbr4Ot6Ua3vOjQNlfC0U+aPohpYRJSBlSI2O01oy/ziedO5jkQIhSq # k7p5gb53p0h+dsExzo1Ryz9wWrBz4u6HivPVExiMUHX9DyDsJfIb7HddEJG2D32G # J01WJRVrYQgzuKM8rT/U/jMVzLcu8YznB90czyAt2EPrTgD0mjj1NsYyb1GgJ62n # ugfHsw7Bpe2eNmwzFr9N/gAwruiIhhL36UVNER9eCTtHbFYpYZukm60f+U8JuFTe # XSBoO7je1Hte+rsZV+COH6o/3KGCF68wgherBgorBgEEAYI3AwMBMYIXmzCCF5cG # CSqGSIb3DQEHAqCCF4gwgheEAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFZBgsqhkiG # 9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQC # AQUABCDCXmNIyqTK+gj1axcgmj9jFXprqDL4S9n0uMommCoZ6gIGavNpRvfLGBIy # MDI2MTExMzE1NDI1My4wNVowBIACAfSggdmkgdYwgdMxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5k # IE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjJE # MUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2 # aWNloIIR/jCCBygwggUQoAMCAQICEzMAAAI3pB13SYKcdwYAAQAAAjcwDQYJKoZI # hvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO # BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEm # MCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcNMjYxMDE1 # MTgzNzQ2WhcNMjgwMTExMTgzNzQ2WjCB0zELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0 # aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046MkQxQS0wNUUw # LUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIi # MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzM1ua7N8pyIf1IsNZAND3JWx4 # CXWsdp3tAL/N0cQFBH5pn1xYnfzgzhz7yg4FzNTdxwQC5YaUrVsux/24wBQZ2q16 # ET3xBKcaWQ5nhpjVmDzFqslsDlpLu5iboTOPiwkYUhl+9jti5u+L1xgBtO4728y/ # YI4QPNtB0RYD2mVu6Cp7AnztsfNZFB15wFCBtPQQxHa0gTxJ8gL5RBYuo02HwgKc # Ow9VW1PvakEkGGaKHrP4AflbpqrboVD+dEOJ8DTGf8wB/7JiLT0C+yo4WbpyjSqm # RER/LFWgANV9b/qbyXOHcy06y/e/uyQJwlphiXk/9Ovksv2GYACG8nNcUonXEl9r # nE1cH/l4IWk4FeizWxYhsRdJUIbRiKY5+VR8PsVdJ3CvpMUeIoyLWfWzA0bE9In+ # DUWQCY4+4/i8H6nIevXysHQPxnvGSE58bdbQIXySdx0zmH7EI0m/+7iA5SPh11rP # LsC5+LveEiMFhMt7H4vALSyE0wUE9jQjrwhafkznzEt3y8ofe1b7iSTJitiX06l2 # p1pAVynMfwWYxF/QffN0m9ayi32IuDyvVygySnpWN40jTiTNaDSSNGrXLPV07lBb # 9wU7J4o0h4bDc9oSnLt8rwOeeXmH7GmWU5TV5c1yTTXjxY7Svvnuis8PSmxJBU14 # vxUOLkvA6+n+TYBWBwIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFFmYj+wQ9N6dmWoI # 3vQJUYSC2cPEMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1Ud # HwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3Js # L01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggr # BgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNv # bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIw # MTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgw # DgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQBzrBoMHtMEcT7ep5/F # GFV/ByTeBrgzIaKxeI4V74HMlS5ACxBDssg7IyCijvf/a9ZQRz+KS25owvRu5/tQ # AGvkgm6C2NwnxrbmmlES3sGR8SW4nSkrOlI3KgV47TUnDg4NQQnmyaa5oQ1/Zg0n # VpeIqcJXBmLaSTPGvVULGT0DPw7Z4UsxcwnLHCgUknPknYuSVsAH9/8K0hUwgwcI # N0SYKdGD+RO8Nqx31TH5SrBJjK3qPN+r4kj2Jp2zeQJiT4EH+LOt0ZB0YW9eBq0T # RtF+C7FmzsO6gw4SN6RbYKWoZ8wXmAzENg71BOUXtYBljW9yDdp0gKCGDC+f/IEy # v2J04DGv87qtXdZnZ8rZWJsLIF+9WOx3CoGl3tXcTrn2cca2raGuEfokeGgda+cQ # NmvvRtARyZTryGSpm79+scZHdPAqj35fupKbEzIXh9CnxLGt3/QwpNCdHyMTOHDr # +L9dUFIwBYoroz6G4+J6XStAvMINP4mS+KwX03oUIjAYCW8dNmoM8TkwMbgMp2Bn # ZRC92u494shqOl/o3T2oEh8Ce1kfOxVPpFqbPCfx+YX96IKy5doDl9OhKPFlGBIY # FCChsngAjJq2wVMxK3X2RWWBtX0N7Jx93jeutzt/sZfB2zLdBTdTs+YMqtfJuUpU # hk4doZ425dDMWozDcOjE1jKjpDCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkA # AAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRl # IEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVow # fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd # TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX # 9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1q # UoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8d # q6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byN # pOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2k # rnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4d # Pf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgS # Uei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8 # QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6Cm # gyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzF # ER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQID # AQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQU # KqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1 # GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0 # dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0 # bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA # QTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbL # j+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1p # Y3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0w # Ni0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIz # LmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwU # tj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN # 3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU # 5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5 # KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGy # qVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB6 # 2FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltE # AY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFp # AUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcd # FYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRb # atGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQd # VTNYs6FwZvKhggNZMIICQQIBATCCAQGhgdmkgdYwgdMxCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5k # IE9wZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjJE # MUEtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2 # aWNloiMKAQEwBwYFKw4DAhoDFQDvgH4FlWKdx0o0N9f/BDuvjdy1eKCBgzCBgKR+ # MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT # HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA # 7qEzFDAiGA8yMDI2MTExMzA2NTYyMFoYDzIwMjYxMTE0MDY1NjIwWjB3MD0GCisG # AQQBhFkKBAExLzAtMAoCBQDuoTMUAgEAMAoCAQACAhWdAgH/MAcCAQACAhM3MAoC # BQDuooSUAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEA # AgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBAIY0LVb7y7puEaJW # WGv78gHSV2kKIEO3pB/m26Dnl+vbEes0YutU8VgaBdC/GmsHWgYCNGRrsrYoy7rG # Kz4obQq9RH2MF0zBZ/SMqsQQJxZhUY0dUYUGhyqvEVNDFOPMS+bgi9hFIRh6jfB8 # Gij+KiMBehHBRdqv+0+dsxfJfJke7jlAfSGw91XFknVxACso8Vs/FWzRjPlLP0Lt # K64W2/lm/ci6zC8FyudFfI87sHwhAX+Uli32NsQFaUNNOoB6CAFwOzLdRr3BNYR9 # lXcXxL8hVNmCE/5OZ2ZY6PNbZdNz2re7JOvpt6IsCR/Big6SNDCwzyPu0VZO0de8 # NAp5QvcxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx # MAITMwAAAjekHXdJgpx3BgABAAACNzANBglghkgBZQMEAgEFAKCCAUowGgYJKoZI # hvcNAQkDMQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCBy6+rAaFhSkM5R # EU7CwIDh7xgEsMEuXAzdI2LxznS7BzCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQw # gb0EIFBPSgCtY8ZMN84d4pMoBurMr1YNsbAtCtSPffC16vX1MIGYMIGApH4wfDEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWlj # cm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAI3pB13SYKcdwYAAQAAAjcw # IgQgBi0V7IBnPgzqs14q5tWvEBsziBu8TTmZITtVfPTXpq0wDQYJKoZIhvcNAQEL # BQAEggIAMfm61pwUYs4xXk98xzVumfgaMsk85MCXA1Tg5smER/lZFhuaY4jqnGE5 # +pAhNJjk7/0nzBnhEackLSJUHvcSyN16HDwH8e5n6hRXEbwXUz6lprdcobpVPGzv # DjsY5QoVQHgwRDvqeB6Zdlb9zbaWkSSucRVf1wTmzqtnWlm5xBl1MwY2SEalI7Wr # wKZ43jfniFGZ0a15ugsWMUI+tDtV7r7fOrFHNWKdP8FiY0OKoK+XnL3tSTC4nexv # u6pv72e17UUxU1756RowqB/G5mp839T5LhgNFDA/G21cAEToKCU34DCbJFLBjsoW # xfCR1d/4f/3xf2RWjN7+I+nnbLwD4ED91onW8TwMjhvrfGiabHP+6vEhrE0P41a8 # qZqDVImAvWpyJq3doEhIWNT5K8cWbm8kMtE0m5b+6JBFMVz2BbBr2o1de6dwJ05M # tmRHd+ESnLgEKSs3IOTvC4cqex2p0Co12aD9jvi131WzkLd+x1+/ITmAx2FMcdlF # /Yr+0SuqatMisTcnumVFhvWgGfOtg6B6kU5ix7A1sOO26ywrxl7FZGlFu9U9+QVQ # aPR48kNXu21irU1DzUHEhg39ZBRQyJ+3vqb1UJ2flaaeMqwll0f7I19pPGLuZPEM # JFF+nTCRs3wklrMSon8bqRPVj4ZKpVzumqtQZcdsskBbPf87J0M= # SIG # End signature block |