DeprecatedApiTranslator/CommonAPITranslation.ps1


# The algorithm searches for matching substructs in the translation scheme
# comparing the first property of the Old and New structure scheme
# There is a risk of wrong translation if in the New structure scheme
# a property is added in front. Meaning the New APIs extend existing structure
# with new property added on the first position.

function ConvertFrom-DeprecatedBodyCommon {
    # Output body translation is always old -> new direction
    param(
        [Parameter()]
        [PSCustomObject]
        $OperationTranslateSchema,

        [Parameter()]
        [PSCustomObject]
        $OperationOutputObject
    )
    $convertArrayToPSObject = $false

    if ($OperationOutputObject -is [array]) {
        if ($OperationOutputObject.Count -eq 0) {
            $result = @()
            return , $result
        }
        else {
            if ($null -ne $OperationTranslateSchema.OldOutBodyStruct) {
                $oldSchemaProperties = $OperationTranslateSchema.OldOutBodyStruct | Get-Member -MemberType NoteProperty
                $convertArrayToPSObject = ($null -ne $oldSchemaProperties -and `
                        $oldSchemaProperties.Count -eq 2 -and `
                        $oldSchemaProperties[0].Name -eq 'key' -and `
                        $oldSchemaProperties[1].Name -eq 'value')
            }
        }
    }

    if ($convertArrayToPSObject) {
        $resultObject = New-Object PSCustomObject

        foreach ($outputObject in $OperationOutputObject) {
            $translationSchema = [PSCustomObject]@{
                'OldOutBodyStruct' = $($OperationTranslateSchema.OldOutBodyStruct.value)
                'NewOutBodyStruct' = $($OperationTranslateSchema.NewOutBodyStruct)
            }
            $resultObject | Add-Member -MemberType NoteProperty -Name $outputObject.Key -Value (ConvertFrom-DeprecatedBodyCommon $translationSchema $outputObject.value)
        }

        $resultObject

    }
    else {

        foreach ($outputObject in $OperationOutputObject) {

            if (-not $OperationTranslateSchema.OldOutBodyStruct -and -not $OperationTranslateSchema.NewOutBodyStruct) {
                # No Translation Needed
                # return
                $outputObject
            }

            if (-not $OperationTranslateSchema.OldOutBodyStruct -and $OperationTranslateSchema.NewOutBodyStruct) {
                # Translation Impossible
                # return
                $outputObject
            }

            if ($OperationTranslateSchema.OldOutBodyStruct -and -not $OperationTranslateSchema.NewOutBodyStruct) {
                # Old Operation Presents Simple Type as a Structure

                $oldSchemaProperties = $OperationTranslateSchema.OldOutBodyStruct | Get-Member -MemberType NoteProperty
                if ($null -ne $oldSchemaProperties -and $oldSchemaProperties.Count -eq 1) {
                    # Value Wrapper Pattern

                    foreach ($element in $outputObject) {
                        if ($element -is [array] -and $element.Length -eq 0) {
                            # empty array isconverted to empty object
                            $result = New-Object PSCustomObject
                            # return
                            $result
                        }
                        else {
                            # return
                            $element.$($oldSchemaProperties[0].Name)
                        }
                    }
                }

                if ($null -ne $oldSchemaProperties -and `
                        $oldSchemaProperties.Count -eq 2 -and `
                        $oldSchemaProperties[0].Name -eq 'key' -and `
                        $oldSchemaProperties[1].Name -eq 'value') {

                    $result = New-Object PSCustomObject

                    # Map to Array Pattern
                    foreach ($element in $outputObject) {
                        if ($element -is [array] -and $element.Length -eq 0) {
                            # empty array isconverted to empty object
                        }
                        else {
                            $result = New-Object PSCustomObject
                            $result | Add-Member -MemberType NoteProperty -Name $element.key -Value $element.Value
                        }
                    }

                    # return
                    $result
                }
            }


            if ($OperationTranslateSchema.OldOutBodyStruct -and $OperationTranslateSchema.NewOutBodyStruct) {
                # Structure to Structure Translation
                $oldStructProps = $OperationTranslateSchema.OldOutBodyStruct | Get-Member -MemberType NoteProperty
                $newStructProps = $OperationTranslateSchema.NewOutBodyStruct | Get-Member -MemberType NoteProperty
                if ($null -ne $newStructProps -and $null -ne $oldStructProps) {
                    if ($newStructProps[0].Name -eq $oldStructProps[0].Name) {
                        # Structures match no translation needed
                        # Traverse and Translate each property

                        $resultObject = New-Object PSCustomObject

                        foreach ($prop in $oldStructProps) {
                            $translationSchema = [PSCustomObject]@{
                                'OldOutBodyStruct' = $($OperationTranslateSchema.OldOutBodyStruct.$($prop.Name))
                                'NewOutBodyStruct' = $($OperationTranslateSchema.NewOutBodyStruct.$($prop.Name))
                            }

                            $translatedValue = (ConvertFrom-DeprecatedBodyCommon $translationSchema $outputObject.($prop.Name))

                            if ($null -ne $translatedValue) {
                                $resultObject | Add-Member `
                                    -MemberType NoteProperty `
                                    -Name $prop.Name `
                                    -Value $translatedValue
                            }
                        }

                        # return
                        $resultObject
                    }
                    else {
                        if ($oldStructProps.Count -eq 1) {
                            # Value Wrapper Pattern
                            $translationSchema = [PSCustomObject]@{
                                'OldOutBodyStruct' = $($OperationTranslateSchema.OldOutBodyStruct.$($oldStructProps[0].Name))
                                'NewOutBodyStruct' = $($OperationTranslateSchema.NewOutBodyStruct)
                            }

                            # return
                            (ConvertFrom-DeprecatedBodyCommon $translationSchema $outputObject.($oldStructProps[0].Name))
                        }

                        if ($oldStructProps.Count -eq 2 -and `
                                $oldStructProps[0].Name -eq 'key' -and `
                                $oldStructProps[1].Name -eq 'value') {
                            # Map to Array pattern

                            # Handle Empty array
                            if ($outputObject -is [array] -and $outputObject.Length -eq 0) {
                                # empty array isconverted to empty object
                                $result = New-Object PSCustomObject
                                # return
                                $result
                            }
                            else {
                                $result = New-Object PSCustomObject

                                foreach ($element in $outputObject) {
                                    $translationSchema = [PSCustomObject]@{
                                        'OldOutBodyStruct' = $($OperationTranslateSchema.OldOutBodyStruct.value)
                                        'NewOutBodyStruct' = $($OperationTranslateSchema.NewOutBodyStruct)
                                    }

                                    $result | Add-Member `
                                        -MemberType NoteProperty `
                                        -Name $element.key `
                                        -Value (ConvertFrom-DeprecatedBodyCommon $translationSchema ($element.value))
                                }

                                # return
                                $result
                            }
                        }
                    }
                }

                if ($null -eq $newStructProps -and $null -ne $oldStructProps) {
                    # Old Operation Presents Simple Type as a Structure
                    foreach ($element in $outputObject) {
                        $noteProperties = $element | Get-Member -MemberType NoteProperty
                        if ($null -ne $noteProperties -and $noteProperties.Count -eq 1) {
                            # Value Wrapper Pattern

                            # return
                            $element.$($noteProperties[0].Name)
                        }

                        if ($null -ne $noteProperties -and `
                                $noteProperties.Count -eq 2 -and `
                                $noteProperties[0].Name -eq 'key' -and `
                                $noteProperties[1].Name -eq 'value') {
                            # Map to Array Pattern
                            $result = New-Object PSCustomObject
                            $result | Add-Member -MemberType NoteProperty -Name $element.key -Value $element.Value
                            # return
                            $result
                        }
                    }
                }

                if ($null -eq $newStructProps -and $null -eq $oldStructProps) {
                    # If the OperationOutputObject is an array, using foreach will result in
                    # returning only the first element of the array, instead of the whole array.
                    if ($OperationOutputObject -is [array]) {
                        # return the whole array and use the comma syntax in the case of array with only one element
                        , $OperationOutputObject
                    } else {
                        # return the current object only
                        $outputObject
                    }
                }
            }
        }
    }
}

function ConvertTo-DeprecatedBodyCommon {
    # Input body translation is always new -> old direction
    param(
        [Parameter()]
        [PSCustomObject]
        $OperationTranslateSchema,

        [Parameter()]
        [PSCustomObject]
        $OperationInputObject
    )
    if ($OperationInputObject -is [array] -and $OperationInputObject.Count -eq 0) {
        return (New-Object PSCustomObject)
    }


    $result = $null
    if ($OperationInputObject -is [array]) {
        $result = @()
    }

    foreach ($inputObject in $OperationInputObject) {
        $singleObjectResult = $null
        if (-not $OperationTranslateSchema.OldInBodyStruct -and -not $OperationTranslateSchema.NewInBodyStruct) {
            # No Translation Needed
            $singleObjectResult = $inputObject
        }

        if (-not $OperationTranslateSchema.OldInBodyStruct -and $OperationTranslateSchema.NewInBodyStruct) {
            # Translation Impossible
            # return and let the server to fail
            $singleObjectResult = $inputObject
        }

        if ($OperationTranslateSchema.OldInBodyStruct -and -not $OperationTranslateSchema.NewInBodyStruct) {
            # Old Operation Presents Simple Type as a Structure
            $oldSchemaProperties = $OperationTranslateSchema.OldInBodyStruct | Get-Member -MemberType NoteProperty
            if ($null -ne $oldSchemaProperties -and $oldSchemaProperties.Count -eq 1) {
                # Value Wrapper Pattern

                foreach ($element in $inputObject) {
                    if ($element -is [PSCustomObject] -and ($element | Get-Member -MemberType NoteProperty).Count -eq 0) {
                        # empty PSCustom Object is converted to empty array
                        # return
                        $singleObjectResult = @()
                    }
                    else {
                        $resultObject = New-Object PSCustomObject
                        $resultObject | Add-Member -MemberType NoteProperty -Name $oldSchemaProperties[0].Name -Value $element
                        # return
                        $singleObjectResult = $resultObject
                    }
                }
            }

            if ($null -ne $oldSchemaProperties -and `
                    $oldSchemaProperties.Count -eq 2 -and `
                    $oldSchemaProperties[0].Name -eq 'key' -and `
                    $oldSchemaProperties[1].Name -eq 'value') {
                # Map to Array Pattern
                foreach ($element in $outputObject) {
                    if ($element -is [PSCustomObject] -and ($element | Get-Member -MemberType NoteProperty).Count -eq 0) {
                        # empty PSCustom Object is converted to empty array
                        # return
                        $singleObjectResult = @()
                    }
                    else {
                        $resultObject = New-Object PSCustomObject
                        $resultObject | Add-Member -MemberType NoteProperty -Name 'key' -Value $element.key
                        $resultObject | Add-Member -MemberType NoteProperty -Name 'value' -Value $element.Value
                        # return
                        $singleObjectResult = $resultObject
                    }
                }
            }
        }

        if ($OperationTranslateSchema.OldInBodyStruct -and $OperationTranslateSchema.NewInBodyStruct) {
            # Structure to Structure Translation
            $oldStructProps = $OperationTranslateSchema.OldInBodyStruct | Get-Member -MemberType NoteProperty
            $newStructProps = $OperationTranslateSchema.NewInBodyStruct | Get-Member -MemberType NoteProperty
            if ($null -ne $newStructProps -and $null -ne $oldStructProps) {
                <#
                    In the deprecated vSphere APIs, the 'client_token' is in the body
                    and in the new vSphere APIs, the 'client_token' is moved to the header parameters.
                    There're 10 vSphere APIs using the 'client_token' and in each the 'client_token' is the
                    first element. So we need to remove it from the body so that the translation algorithm can
                    work as expected - either we're left with matching Structures or the Wrapper Pattern occurs.
                #>

                if ($oldStructProps[0].Name -eq 'client_token') {
                    $oldStructProps = $oldStructProps[1..($oldStructProps.Length - 1)]
                }

                if ($newStructProps[0].Name -eq $oldStructProps[0].Name) {
                    # Structures match no translation needed
                    # Traverse and Translate each property

                    $resultObject = New-Object PSCustomObject

                    foreach ($prop in $oldStructProps) {
                        # Assuming the New Structure has all the properties the old one has
                        # In case the new one has more they won't be translated
                        $translationSchema = [PSCustomObject]@{
                            'OldInBodyStruct' = $($OperationTranslateSchema.OldInBodyStruct.$($prop.Name))
                            'NewInBodyStruct' = $($OperationTranslateSchema.NewInBodyStruct.$($prop.Name))
                        }

                        $translatedValue = (ConvertTo-DeprecatedBodyCommon $translationSchema $inputObject.($prop.Name))

                        if ($null -ne $translatedValue) {
                            $resultObject | Add-Member `
                                -MemberType NoteProperty `
                                -Name $prop.Name `
                                -Value $translatedValue
                        }
                    }

                    # return
                    $singleObjectResult = $resultObject
                }
                else {
                    if ($oldStructProps.Count -eq 1) {
                        # Spec Wrapper Pattern
                        $translationSchema = [PSCustomObject]@{
                            'OldInBodyStruct' = $($OperationTranslateSchema.OldInBodyStruct.$($oldStructProps[0].Name))
                            'NewInBodyStruct' = $($OperationTranslateSchema.NewInBodyStruct)
                        }


                        $translatedValue = (ConvertTo-DeprecatedBodyCommon $translationSchema $inputObject)
                        $resultObject = New-Object PSCustomObject
                        $resultObject | Add-Member `
                            -MemberType NoteProperty `
                            -Name $oldStructProps[0].Name `
                            -Value $translatedValue

                        # return
                        $singleObjectResult = $resultObject
                    }

                    if ($oldStructProps.Count -eq 2 -and `
                            $oldStructProps[0].Name -eq 'key' -and `
                            $oldStructProps[1].Name -eq 'value') {
                        # Array to Map pattern

                        # Handle Empty array
                        if ($inputObject -is [PSCustomObject] -and ($inputObject | Get-Member -MemberType NoteProperty).Count -eq 0) {
                            # empty PSObject is converted to empty array
                            # return
                            $singleObjectResult = @()
                        }
                        else {
                            $singleObjectResult = @()
                            foreach ($element in $inputObject) {
                                $notePropertyMemebers = $element | Get-Member -MemberType NoteProperty
                                if ($notePropertyMemebers.Count -ne 1) {
                                    throw "Input object array to map cannot be translated because element has more than one key note property"
                                }

                                # Note property name is mapped to the 'key' property of the old structure
                                # Note property value is mapped to the 'value' property of the old structure
                                $translationSchema = [PSCustomObject]@{
                                    'OldInBodyStruct' = $($OperationTranslateSchema.OldInBodyStruct.value)
                                    'NewInBodyStruct' = $($OperationTranslateSchema.NewInBodyStruct)
                                }
                                $resultObject = New-Object PSCustomObject
                                $resultObject | Add-Member -MemberType NoteProperty -Name 'key' -Value $notePropertyMemebers[0].Name
                                $resultObject | Add-Member -MemberType NoteProperty -Name 'value' -Value (ConvertTo-DeprecatedBodyCommon $translationSchema ($element.$($notePropertyMemebers[0].Name)))
                                # return
                                $singleObjectResult += $resultObject
                            }
                        }
                    }
                }
            }

            if ($null -eq $newStructProps -and $null -ne $oldStructProps) {
                # Old Operation Presents Simple Type as a Structure
                foreach ($element in $inputObject) {
                    $noteProperties = $element | Get-Member -MemberType NoteProperty
                    if ($noteProperties.Count -eq 1) {
                        # Query Input Array Parameter Pattern
                        $resultObject = [PSCustomObject] @{
                            $noteProperties[0].Name = $element.($noteProperties[0].Name)
                        }

                        $resultObject
                    } elseif ($oldStructProps.Count -eq 1) {
                        # Spec Wrapper Pattern
                        $resultObject = New-Object PSCustomObject
                        $resultObject | Add-Member `
                            -MemberType NoteProperty `
                            -Name $oldStructProps[0].Name `
                            -Value $element

                        # return
                        $singleObjectResult = $resultObject
                    }

                }
            }

            if ($null -eq $newStructProps -and $null -eq $oldStructProps) {
                # return
                $singleObjectResult = $inputObject
            }
        }

        if ($result -is [array]) {
            $result += $singleObjectResult
        } else {
            $result = $singleObjectResult
        }
    }

    # return converted result
    if ($result -is [array] -and $result.Count -eq 1) {
        return , $result
    } else {
        return $result
    }
}

function Convert-StructureDefitionToArrayDefinition {
    <#
    .SYNOPSIS
    Converts structure definition from translation scheme to array definition
 
    .DESCRIPTION
    The convertor is for the purpose of translating body structure defined in the translation schema to query parameters definition,
 
    .PARAMETER DataStructureDefinition
    PSCustomObject that represents the InBody definition of a translation schema for an API operation
    #>

    param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNull()]
        [PSCustomObject]
        $DataStructureDefinition,

        [Parameter(Mandatory=$true)]
        [ValidateNotNull()]
        [ref]$StructureObject
    )

    $newStructureObject =New-Object PSCustomObject

    foreach ($dsDef in $DataStructureDefinition) {
        $dsDef | Get-Member -MemberType NoteProperty | Foreach-Object {
            if ($dsDef.$($_.Name) -is [PSCustomObject]) {
                # For some APIs multiple structures are converted list of query params
                # We assume there are no nested structures in the query params
                # The modst complext case is assumed to be
                # {
                # 'loc_spec': {
                # 'locaiton': 'string'
                # }
                # 'filter_spec': {
                # 'max_result': 'integer'
                # }
                # }
                #
                # which is converted to @(locaiton, max_result) query parameters
                #
                $parentPropertyName = $_.Name
                $dsDef.$($_.Name) | Get-Member -MemberType NoteProperty | Foreach-Object {
                    $newStructureObject | Add-Member -MemberType NoteProperty -Name "$($parentPropertyName).$($_.Name)" -Value $($StructureObject.Value.$parentPropertyName.$($_.Name))
                    # result
                    "$($parentPropertyName).$($_.Name)"
                }
            } else {
                $newStructureObject | Add-Member -MemberType NoteProperty -Name $($_.Name) -Value $($StructureObject.Value.$($_.Name))
                # result
                $_.Name
            }
        }
    }

    $StructureObject.Value = $newStructureObject
}

function ConvertTo-DeprecatedQueryParamCommon {
    # Converts Query Param object from new -> old direction
    param(
        [Parameter()]
        [PSCustomObject]
        $OperationTranslateSchema,

        [Parameter()]
        [PSCustomObject]
        $OperationQueryInputObject
    )


    if ($null -ne $OperationTranslateSchema.OldInQueryParams -and `
            $null -ne $OperationTranslateSchema.NewInQueryParams -and `
            $OperationQueryInputObject -is [PSCustomObject]) {

        $resultObject = New-Object PSCustomObject

        $newQueryParamDefinition = $null

        if ($OperationTranslateSchema.NewInQueryParams -isnot [array] -and `
            $OperationTranslateSchema.NewInQueryParams -is [PSCustomObject]) {

            $newQueryParamDefinition = (Convert-StructureDefitionToArrayDefinition -DataStructureDefinition $OperationTranslateSchema.NewInQueryParams -StructureObject ([ref]$OperationQueryInputObject))
        } else {
            $newQueryParamDefinition = $OperationTranslateSchema.NewInQueryParams
        }

        foreach ($newQueryParam in $newQueryParamDefinition) {
            foreach ($oldQueryParam in $OperationTranslateSchema.OldInQueryParams) {
                $value = $($OperationQueryInputObject."$newQueryParam")
                if ($null -ne $value) {
                    $propName = $newQueryParam
                    if ($oldQueryParam -eq $newQueryParam) {
                        # leave it as-is
                        $resultObject | Add-Member -MemberType NoteProperty -Name $propName -Value $value
                    }
                    elseif ($oldQueryParam.EndsWith(".$newQueryParam")) {
                        # Use the old property name
                        $propName = $oldQueryParam
                        $resultObject | Add-Member -MemberType NoteProperty -Name $propName -Value $value
                    }
                }
            }
        }

        # return
        $resultObject
    }
    else {
        # The conversion is not possible
        $OperationQueryInputObject
    }
}
# SIG # Begin signature block
# MIIp0AYJKoZIhvcNAQcCoIIpwTCCKb0CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD0Tpo0XunmJgOu
# mDH1INfpGRqAXwvlDMEjyO1Q3s6bAaCCDrwwggawMIIEmKADAgECAhAIrUCyYNKc
# TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z
# NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
# UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
# ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0
# JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr
# Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF
# LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F
# LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh
# 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ
# wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay
# g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI
# YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp
# QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro
# OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB
# WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+
# YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P
# AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk
# BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC
# hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v
# dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED
# MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql
# +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF
# UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h
# mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw
# YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld
# AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw
# 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP
# LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE
# QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn
# KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji
# WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq
# yK+p/pQd52MbOoZWeE4wgggEMIIF7KADAgECAhAIV5dCqVO62Q1CN6Pz44xeMA0G
# CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
# SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
# UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjIwNTA0MDAwMDAwWhcNMjQwNTA0
# MjM1OTU5WjCBxTETMBEGCysGAQQBgjc8AgEDEwJVUzEZMBcGCysGAQQBgjc8AgEC
# EwhEZWxhd2FyZTEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNV
# BAUTBzI4NTM4OTQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIw
# EAYDVQQHEwlQYWxvIEFsdG8xFTATBgNVBAoTDFZNd2FyZSwgSW5jLjEVMBMGA1UE
# AxMMVk13YXJlLCBJbmMuMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
# 6kAACeNtbODhaayXmhKLpjNsCENWh3WTl/NOvObo1Prl949C6y2EU9zMsfYuODNI
# Tv2OoByT3nBCXk3G1gzanGscaUDgr18pzf77Og4ArUHNzil6aX7uAlvKRBPl+6Hv
# wpSMtyK0D6J79UKfYqztvf/9YOFJLGCiq7Dw8932vg0ijcH7sLGgoSjH6+jqBwTT
# suOav1lyiAxE4Q6r8KyDNjg6mYu2uu1TALU4B7/OX/zBIadArVgPHRurud9SSGPq
# itFCgd2OuY0r81Jr0LRxOnwWHLqPOwuSmsnxw7ZaQJCz7FY3oxiES8mbA+VV6zN8
# 18/s2v5htLd3SRrE5n4mhzGyXAVkqIILKiSppibj59dEc5voQ/1MXJ25W1kSy2MX
# B8XjI9j64JzcpjW5YPs2M+BR4mIEC5i2mURO/u3HGG9prRTPOv2MN1WzbLLUG98O
# sqLTrUTQtdvpcWizS1c6m9IFY14fj1OeagnUwY3W0THEloNKC1WZoe+5Oxq/NRxO
# Bz4N4fzCsqc44TBUWmHSqBVOV8PpmQ8xVrfj+aLdk40naf/cf9cdvqslsrKtzkvL
# b+ohLCvqymua9GLNmUbY2EyrOogMseRX8y0awJS4cWRLl9c1O7j7q31GwfX+ozEI
# h1z4pBNATaZSbTTsMi4eKMCzsU/QiDM/iCaZbWL6VgsCAwEAAaOCAkkwggJFMB8G
# A1UdIwQYMBaAFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB0GA1UdDgQWBBRS+9+VGnhS
# 2uj4hRdXRyZkmfv5GzBCBgNVHREEOzA5gRJub3JlcGx5QHZtd2FyZS5jb22gIwYI
# KwYBBQUHCAOgFzAVDBNVUy1ERUxBV0FSRS0yODUzODk0MA4GA1UdDwEB/wQEAwIH
# gDATBgNVHSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRw
# Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmlu
# Z1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hB
# Mzg0MjAyMUNBMS5jcmwwPQYDVR0gBDYwNDAyBgVngQwBAzApMCcGCCsGAQUFBwIB
# FhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGHMIGE
# MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUH
# MAKGUGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRH
# NENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB/wQC
# MAAwDQYJKoZIhvcNAQELBQADggIBANPAhp5gl2m66jB8Ft1vCSC2ij4PKMQ3Mwkv
# 1gtZoMKnS/NCi9jl8WpooSMth39ze0LyDrQY8nUO6CPX/LDGkWuf/f+HUoRNw2wS
# seCFw/yvQJBzmmTRzuQqdhkAIM99kD6RCo60WQxskrhOCqx8LNFl3pcsIqonSvok
# /GC1+KmwUKdV5Wuag3jkH1LLOJ5x8CnyTmMWSPsx9aVY+mIzvYuLuZIdAybGYUW7
# sOLRTzhUiGBLlxL56n1dFqzF6IgPePpZHWMwyhIKQLgbkkYNFectTeTehws5v1YZ
# f/tjw2TsVJFEB4UIS1mHnBPiCNMt+/f33jH8vfT6fxVV5FIBXqvr0ruDVseZb/Jm
# xdBfjt2AzMHk3d3l2Ar+06vo4gAFbLFtULTjV9d3jjP4YCGix5Q2UwHvkBjfB46e
# ChIEjkbWnjmkFdZPpvILRVL9lhTa1kKwBzbTnW5KSnxA5CtB3gShY7U8rYmZfPrS
# 4gBBTutdhD8nd4roDdlJZPVMIvcqeRrdb2cx8WGohV8/MCOPeEUvsMiuOwFroreG
# 6ecUwbdjCNkzx2o3hXaHyfolUj4n+iQuealnn4KKfDp7eYDabu9zWbv6UN3D//Ug
# DlYdiQWzsKF0GqJQeqeq0Lga63zr7nOSPzn82AF7QfdYkccoLnD3y2iJObDrAsY0
# KjiW7SylMYIaajCCGmYCAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln
# aUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBT
# aWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAIV5dCqVO62Q1CN6Pz44xe
# MA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJKoZIhvcNAQkD
# MQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJ
# KoZIhvcNAQkEMSIEID7jK169nGzPit/B1Gv00GqglYfk3fHL89vPvwkxdPQ7MA0G
# CSqGSIb3DQEBAQUABIICAEmjhaoHo57OCk+LDnbbiSpcPtHYgkQ9D8VQ/kBGe8NE
# DH027dvZHLizBBfapp5XfIWP8iaMWCtB0IBqSPoB9LTJ+GCFP2WORgtxDfmKTYiG
# 7HWJLa17u8sPexTx3ovz08hFpmRHxXuy75/WjY8un4PewDBKBdfzeCB0NwzCARhW
# Vm5+oT7cfExk1igAtv0Vyz465kqw/JPxH8WS5CG04dAp4fxqRhk2RGobrc6U5Pbp
# J3uaXuw5TjNXjAhoyy9p/M4Ow9pD9N6/EcuJ+oqAyzfkk+GuvS1bDFhQwWl4bN6a
# LEZn/7hiCEEDgmoqGZJvKsuk69pNTpOE2Tn7GLadN0ppECgf8lWwINXt8KR7DNEX
# osrvxzqlt8uad60G7rs5gmu0iJCnrHbyW8HCPfiK6BRhugtWR1JL2d2HzGRaCXhy
# QaEOuzrPCz13VgUxIfff5D5z7ZK9x5ULi2CCXMrdvoio7IbCAgwNshik3KKYIioa
# PQBLEgqY1yutU5Bq55j4TMyq0gNvoGhQ6FNfl04oLiOVH+dJHj374wflhzPZRHgy
# A7DL6Ne82Sc38DJqssezf/lDHsF//O/HqqecMlYCvdKxutMighUMOHiTitQ6EMKe
# MCNOJJiwVYdOYKQ8VzPvZ+cE8z8acbreMwm9YDxzmTxGKtcLSfl4aXKXIjRGHKrL
# oYIXQDCCFzwGCisGAQQBgjcDAwExghcsMIIXKAYJKoZIhvcNAQcCoIIXGTCCFxUC
# AQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0BCRABBKBpBGcwZQIBAQYJYIZI
# AYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEILX0WhxF5NDKmj81RIecLC2MpMvTcUIX
# /OF1jp5zH4XRAhEA2ssk5yKeHEdNQZ/J1lcC3hgPMjAyMzEwMjExODIyMDNaoIIT
# CTCCBsIwggSqoAMCAQICEAVEr/OUnQg5pr/bP1/lYRYwDQYJKoZIhvcNAQELBQAw
# YzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQD
# EzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGlu
# ZyBDQTAeFw0yMzA3MTQwMDAwMDBaFw0zNDEwMTMyMzU5NTlaMEgxCzAJBgNVBAYT
# AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UEAxMXRGlnaUNlcnQg
# VGltZXN0YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCj
# U0WHHYOOW6w+VLMj4M+f1+XS512hDgncL0ijl3o7Kpxn3GIVWMGpkxGnzaqyat0Q
# KYoeYmNp01icNXG/OpfrlFCPHCDqx5o7L5Zm42nnaf5bw9YrIBzBl5S0pVCB8s/L
# B6YwaMqDQtr8fwkklKSCGtpqutg7yl3eGRiF+0XqDWFsnf5xXsQGmjzwxS55Dxtm
# UuPI1j5f2kPThPXQx/ZILV5FdZZ1/t0QoRuDwbjmUpW1R9d4KTlr4HhZl+NEK0rV
# lc7vCBfqgmRN/yPjyobutKQhZHDr1eWg2mOzLukF7qr2JPUdvJscsrdf3/Dudn0x
# mWVHVZ1KJC+sK5e+n+T9e3M+Mu5SNPvUu+vUoCw0m+PebmQZBzcBkQ8ctVHNqkxm
# g4hoYru8QRt4GW3k2Q/gWEH72LEs4VGvtK0VBhTqYggT02kefGRNnQ/fztFejKqr
# UBXJs8q818Q7aESjpTtC/XN97t0K/3k0EH6mXApYTAA+hWl1x4Nk1nXNjxJ2VqUk
# +tfEayG66B80mC866msBsPf7Kobse1I4qZgJoXGybHGvPrhvltXhEBP+YUcKjP7w
# tsfVx95sJPC/QoLKoHE9nJKTBLRpcCcNT7e1NtHJXwikcKPsCvERLmTgyyIryvEo
# EyFJUX4GZtM7vvrrkTjYUQfKlLfiUKHzOtOKg8tAewIDAQABo4IBizCCAYcwDgYD
# VR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH
# AwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMB8GA1UdIwQYMBaA
# FLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSltu8T5+/N0GSh1VapZTGj
# 3tXjSTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3Js
# MIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
# aWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0Eu
# Y3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCBGtbeoKm1mBe8cI1PijxonNgl/8ss5M3q
# XSKS7IwiAqm4z4Co2efjxe0mgopxLxjdTrbebNfhYJwr7e09SI64a7p8Xb3CYTdo
# SXej65CqEtcnhfOOHpLawkA4n13IoC4leCWdKgV6hCmYtld5j9smViuw86e9NwzY
# mHZPVrlSwradOKmB521BXIxp0bkrxMZ7z5z6eOKTGnaiaXXTUOREEr4gDZ6pRND4
# 5Ul3CFohxbTPmJUaVLq5vMFpGbrPFvKDNzRusEEm3d5al08zjdSNd311RaGlWCZq
# A0Xe2VC1UIyvVr1MxeFGxSjTredDAHDezJieGYkD6tSRN+9NUvPJYCHEVkft2hFL
# jDLDiOZY4rbbPvlfsELWj+MXkdGqwFXjhr+sJyxB0JozSqg21Llyln6XeThIX8rC
# 3D0y33XWNmdaifj2p8flTzU8AL2+nCpseQHc2kTmOt44OwdeOVj0fHMxVaCAEcsU
# DH6uvP6k63llqmjWIso765qCNVcoFstp8jKastLYOrixRoZruhf9xHdsFWyuq69z
# OuhJRrfVf8y2OMDY7Bz1tqG4QyzfTkx9HmhwwHcK1ALgXGC7KP845VJa1qwXIiNO
# 9OzTF/tQa/8Hdx9xl0RBybhG02wyfFgvZ0dl5Rtztpn5aywGRu9BHvDwX+Db2a2Q
# gESvgBBBijCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcN
# AQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG
# A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3Rl
# ZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkG
# A1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdp
# Q2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCC
# AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8Ty
# kTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsm
# c5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTn
# KC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2
# R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0
# QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/
# oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1ps
# lPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhI
# fxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8
# I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkU
# EBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1G
# nrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEA
# MB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC
# 0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYB
# BQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k
# aWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0
# LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSG
# Mmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQu
# Y3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0B
# AQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7
# cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2p
# Vs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxk
# Jodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpkn
# G6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2
# n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fm
# w0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvt
# Cl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU
# 5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8K
# vYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/
# GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwggWNMIIE
# daADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNV
# BAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdp
# Y2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAe
# Fw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUw
# EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
# ITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcN
# AQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC
# 4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWl
# fr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1j
# KS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dP
# pzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3
# pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJ
# pMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aa
# dMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXD
# j/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB
# 4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ
# 33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amy
# HeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC
# 0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823I
# DzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhho
# dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNl
# cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYD
# VR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0
# QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcN
# AQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxpp
# VCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6
# mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPH
# h6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCN
# NWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg6
# 2fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggN2MIIDcgIBATB3MGMxCzAJBgNV
# BAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNl
# cnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAVE
# r/OUnQg5pr/bP1/lYRYwDQYJYIZIAWUDBAIBBQCggdEwGgYJKoZIhvcNAQkDMQ0G
# CyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yMzEwMjExODIyMDNaMCsGCyqG
# SIb3DQEJEAIMMRwwGjAYMBYEFGbwKzLCwskPgl3OqorJxk8ZnM9AMC8GCSqGSIb3
# DQEJBDEiBCCiqSAm3clC6J+XkSwisIqixILkleXCthYiwxUqDaIc5DA3BgsqhkiG
# 9w0BCRACLzEoMCYwJDAiBCDS9uRt7XQizNHUQFdoQTZvgoraVZquMxavTRqa1Ax4
# KDANBgkqhkiG9w0BAQEFAASCAgBxdR7CRtECOGmnEJ019riASGJ+615jyOGPqtPB
# KZsGgCekAOuKh1eF9/5RrgwbLbMfjghgYRxvCb0t1Ipirccl7wRRk7nEMFlyIwN6
# dH3FhUdnvcbZSG+ywrREeA3D5msGQsTIV23dQXwTLAegcu9hcUayKFG/x03L7NU+
# zotxXCOW+1NVILhBfz5hmjERc8MEeVTZ0Zk/rv4Ymu3NqttgoKFC9/ZqmZUJobzl
# KcLsjoGBJng0UoaKeqoleq60fK40WXvt+Z0CIKPf7O82ErWav9MFz/kgVADEij3K
# YvqcO8c7OpxMMnlPuC3zJprDJm3Hpv3wygd/4+IieUerj4Nk9mwD8ZkYvwhlion2
# S/91x+DSaT3JFsn1pkRIw8VRJkZhZMykr7fG4pWbAcgRgXvR9LN/C7TvZzyjNuhA
# e5KF8kuFj/DuHTNu0Kulea0BlVa6wcUo75pW5aEhrFYZk4+cHuwclQfJLgrUjb1p
# nrsbC2A37DjxcE623zb7N5RSeR77VlQX+vHSaLSHxlUhBqcyb3VzeV2C4afRXnS/
# 61fI5fT+CiOAWLpQDLC75KN+HWCWTSORkYdkIkTLeeolAZEnHUQqyTKF5dldUMwr
# nNyE8juXwUmCsAf0eS37cY0Pa6Lh4EtH09/CG8I8eyrjG9I6HUt9S4++ZuPQ2VZQ
# L+yOkw==
# SIG # End signature block