Framework/Helpers/JsonHelper.ps1

using namespace Newtonsoft.Json
Set-StrictMode -Version Latest
class JsonHelper {
    static [JsonSerializerSettings] $SerializerSettings = $null;

    hidden static [JsonSerializerSettings] GetSerializerSettings() {
        if (-not [JsonHelper]::SerializerSettings) {
            $settings = [JsonSerializerSettings]::new();
            $settings.Converters.Add([Converters.StringEnumConverter]::new());
            $settings.Formatting = [Formatting]::Indented;
            $settings.NullValueHandling = [NullValueHandling]::Ignore;
            $settings.ReferenceLoopHandling = [ReferenceLoopHandling]::Ignore;
            [JsonHelper]::SerializerSettings = $settings;
        }
        return [JsonHelper]::SerializerSettings;
    }

    static [string] ConvertToJson([PSObject] $dataObject) {
        if ($dataObject) {
            if ($dataObject.GetType() -eq [System.Object[]] -and $dataObject.Count -ne 0) {
                $list = New-Object -TypeName "System.Collections.Generic.List[$($dataObject[0].GetType().fullname)]";
                $dataObject | ForEach-Object {
                    if ($_) {
                        $list.Add($_);
                    }
                }
                return [JsonConvert]::SerializeObject($list, [JsonHelper]::GetSerializerSettings());
            }

            return [JsonConvert]::SerializeObject($dataObject, [JsonHelper]::GetSerializerSettings());
        }
        return "";
    }

    static [string] ConvertToJsonCustom([PSObject] $Object, [Int]$Depth, [Int]$Layers) {
        Set-StrictMode -Off
        $res = [JsonHelper]::ConvertToJsonCustomNotStrict($Object, $Depth, $Layers, $false)
        Set-StrictMode -Version Latest
        return $res
    }

    static [string] ConvertToJsonCustom([PSObject] $Object) {
       return [JsonHelper]::ConvertToJsonCustom($Object, 10, 10);
    }

    static [string] ConvertToJsonCustomCompressed([PSObject] $Object) {
        Set-StrictMode -Off
        $res = [JsonHelper]::ConvertToJsonCustomNotStrict($Object, 10, 0, $false)
        Set-StrictMode -Version Latest
        return $res
    }

    static [string] ConvertToPson([PSObject] $Object) {
        Set-StrictMode -Off
        $res = [JsonHelper]::ConvertToPsonNotStrict($Object, 10, 10, $false, $false, (Get-Variable -Name PSVersionTable).Value.PSVersion)
        Set-StrictMode -Version Latest
        return $res
    }

    static [string] ConvertToJsonCustomNotStrict([PSObject] $Object, [Int]$Depth, [Int]$Layers, [bool]$IsWind) {
        $Format = $Null
        $Quote = If ($Depth -le 0) {""}
        Else {""""}
        $Space = If ($Layers -le 0) {""}
        Else {" "}
        If ($null-eq $Object) { return "null"}
        Else {
            $JSON = If ($Object -is "Array") {
                $Format = "[", ",$Space", "]"
                If ($Depth -gt 1) {
                    For ($i = 0; $i -lt $Object.Count; $i++) {
                        [JsonHelper]::ConvertToJsonCustomNotStrict($Object[$i], $Depth - 1, $Layers - 1, $IsWind)
                    }
                }
            }
            ElseIf ($Object -is "Xml") {
                $String = New-Object System.IO.StringWriter
                $Object.Save($String)
                $Xml = "'" + ([String]$String).Replace("`'", "'") + "'"
                If ($Layers -le 0) {
                    ($Xml -Replace "\r\n\s*", "") -Replace "\s+", " "
                }
                ElseIf ($Layers -eq 1) {
                    $Xml
                }
                Else {
                    $Xml.Replace("`r`n", "`r`n ")
                }
                $String.Dispose()
            }
            ElseIf ($Object -is "Enum") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "DateTime") {
                "$Quote$($Object.ToString("o"))$Quote"
            }
            ElseIf ($Object -is "TimeSpan") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "String") {
                $Object = ConvertTo-Json $Object -Depth 1
                "$Object"
            }
            ElseIf ($Object -is "Boolean") {
                If ($Object) {"true"}
                Else {"false"}
            }
            ElseIf ($Object -is "Char") {
                "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "guid") {
                "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "ValueType") {
                $Object
            }
            ElseIf ($Object -is [System.Collections.IDictionary]) {
                If ($null -eq $Object.Keys) {
                    return "null"
                }
                $Format = "{", ",$Space", "}"
                If ($Depth -gt 1) {
                    $Object.GetEnumerator() | ForEach-Object {
                        $Quote + $_.Key + $Quote + "$Space`:$Space" + ([JsonHelper]::ConvertToJsonCustomNotStrict($_.Value, $Depth - 1, $Layers - 1, $IsWind))
                    }
                }
            }
            ElseIf ($Object -is 'System.Collections.IList') {
                $Format = "[", ",$Space", "]"
                If ($Depth -gt 1) {
                    $Object | ForEach-Object {
                        [JsonHelper]::ConvertToJsonCustomNotStrict($_, $Depth - 1, $Layers - 1, $IsWind)
                    }
                }
            }
            ElseIf ($Object -is "Object") {
                If ($Object -is "System.Management.Automation.ErrorRecord" -and !$IsWind) {
                    $Depth = 3
                    $Layers = 3
                    $IsWind = $true
                }
                $Format = "{", ",$Space", "}"
                If ($Depth -gt 1) {
                    Get-Member -InputObject $Object -MemberType Properties | ForEach-Object {
                        $Quote + $_.Name + $Quote + "$Space`:$Space" + ([JsonHelper]::ConvertToJsonCustomNotStrict($Object.$($_.Name), $Depth - 1, $Layers - 1, $IsWind))
                    }
                }
            }
            Else {$Object}
            If ($Format) {
                $JSON = $Format[0] + (& {
                        If (($Layers -le 1) -or ($JSON.Count -le 0)) {
                            $JSON -Join $Format[1]
                        }
                        Else {
                            ("`r`n" + ($JSON -Join "$($Format[1])`r`n")).Replace("`r`n", "`r`n ") + "`r`n"
                        }
                    }) + $Format[2]
            }
            return "$JSON"
        }
    }


    # Adapted from https://stackoverflow.com/questions/15139552/save-hash-table-in-powershell-object-notation-pson
    # PSON - PowerShell Object Notation
    static [string] ConvertToPsonNotStrict([PSObject] $Object, [Int]$Depth, [Int]$Layers, [bool]$IsWind, [bool]$Strict, [Version]$Version) {
        $Format = $Null
        $Quote = If ($Depth -le 0) {""}
        Else {""""}
        $Space = If ($Layers -le 0) {""}
        Else {" "}
        If ($null -eq $Object) {
            return "`$Null"
        }
        Else {
            $Type = "[" + $Object.GetType().Name + "]"
            $PSON = If ($Object -is "Array") {
                $Format = "@(", ",$Space", ")"
                If ($Depth -gt 1) {
                    For ($i = 0; $i -lt $Object.Count; $i++) {
                        [JsonHelper]::ConvertToPsonNotStrict($Object[$i], $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version)
                    }
                }
            }
            ElseIf ($Object -is "Xml") {
                $Type = "[Xml]"
                $String = New-Object System.IO.StringWriter
                $Object.Save($String)
                $Xml = "'" + ([String]$String).Replace("`'", "'") + "'"
                If ($Layers -le 0) {
                    ($Xml -Replace "\r\n\s*", "") -Replace "\s+", " "
                }
                ElseIf ($Layers -eq 1) {
                    $Xml
                }
                Else {
                    $Xml.Replace("`r`n", "`r`n ")
                }
                $String.Dispose()
            }
            ElseIf ($Object -is "Enum") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "DateTime") {
                "$Quote$($Object.ToString('s'))$Quote"
            }
            ElseIf ($Object -is "TimeSpan") {
                "$Quote$($Object.ToString())$Quote"
            }
            ElseIf ($Object -is "String") {
                0..11 | ForEach-Object {
                    $Object = $Object.Replace([String]"```'""`0`a`b`f`n`r`t`v`$"[$_], ('`' + '`''"0abfnrtv$'[$_]))}; "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "Boolean") {
                If ($Object) {"`$True"}
                Else {"`$False"}
            }
            ElseIf ($Object -is "Char") {
                If ($Strict) {[Int]$Object}
                Else {"$Quote$Object$Quote"}
            }
            ElseIf ($Object -is "guid") {
                "$Quote$Object$Quote"
            }
            ElseIf ($Object -is "ValueType") {
                $Object
            }
            ElseIf ($Object -is [System.Collections.IDictionary]) {
                If ($null -eq $Object.Keys) {
                    return "`$Null"
                }
                If ($Type -eq "[OrderedDictionary]") {$Type = "[Ordered]"}
                $Format = "@{", ";$Space", "}"
                If ($Depth -gt 1) {
                    $Object.GetEnumerator() | ForEach-Object {
                        $Quote + $_.Key + $Quote + "$Space=$Space" + ([JsonHelper]::ConvertToPsonNotStrict($_.Value, $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version))
                    }
                }
            }
            ElseIf ($Object -is 'System.Collections.IList') {
                $Format = "@(", ",$Space", ")"
                If ($Depth -gt 1) {
                    $Object | ForEach-Object {
                        [JsonHelper]::ConvertToPsonNotStrict($_, $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version)
                    }
                }
            }
            ElseIf ($Object -is "Object") {
                If ($Object -is "System.Management.Automation.ErrorRecord" -and !$IsWind) {
                    $Depth = 3
                    $Layers = 3
                    $IsWind = $true
                }
                If ($Version -le [Version]"2.0") {$Type = "New-Object PSObject -Property "}
                $Format = "@{", ";$Space", "}"
                If ($Depth -gt 1) {
                    Get-Member -InputObject $Object -MemberType Properties | ForEach-Object {
                        $Quote + $_.Name + $Quote + "$Space=$Space" + ([JsonHelper]::ConvertToPsonNotStrict($Object.$($_.Name), $Depth - 1, $Layers - 1, $IsWind, $Strict, $Version))
                    }
                }
            }
            Else {$Object}
            If ($Format) {
                $PSON = $Format[0] + (& {
                        If (($Layers -le 1) -or ($PSON.Count -le 0)) {
                            $PSON -Join $Format[1]
                        }
                        Else {
                            ("`r`n" + ($PSON -Join "$($Format[1])`r`n")).Replace("`r`n", "`r`n ") + "`r`n"
                        }
                    }) + $Format[2]
            }
            If ($Strict) {
                return "$Type$PSON"
            }
            Else {
                return "$PSON"
            }
        }
    }

}
# SIG # Begin signature block
# MIIjoAYJKoZIhvcNAQcCoIIjkTCCI40CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDXi3Z8gVnTZE9V
# Y5pGA8ByY3U2ZCaOEzX1Q/TOwvbwgKCCDYEwggX/MIID56ADAgECAhMzAAABh3IX
# chVZQMcJAAAAAAGHMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD
# VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p
# bmcgUENBIDIwMTEwHhcNMjAwMzA0MTgzOTQ3WhcNMjEwMzAzMTgzOTQ3WjB0MQsw
# CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
# ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy
# b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQDOt8kLc7P3T7MKIhouYHewMFmnq8Ayu7FOhZCQabVwBp2VS4WyB2Qe4TQBT8aB
# znANDEPjHKNdPT8Xz5cNali6XHefS8i/WXtF0vSsP8NEv6mBHuA2p1fw2wB/F0dH
# sJ3GfZ5c0sPJjklsiYqPw59xJ54kM91IOgiO2OUzjNAljPibjCWfH7UzQ1TPHc4d
# weils8GEIrbBRb7IWwiObL12jWT4Yh71NQgvJ9Fn6+UhD9x2uk3dLj84vwt1NuFQ
# itKJxIV0fVsRNR3abQVOLqpDugbr0SzNL6o8xzOHL5OXiGGwg6ekiXA1/2XXY7yV
# Fc39tledDtZjSjNbex1zzwSXAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE
# AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhov4ZyO96axkJdMjpzu2zVXOJcsw
# UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1
# ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDU4Mzg1MB8GA1UdIwQYMBaAFEhu
# ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu
# bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w
# Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3
# Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx
# MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAixmy
# S6E6vprWD9KFNIB9G5zyMuIjZAOuUJ1EK/Vlg6Fb3ZHXjjUwATKIcXbFuFC6Wr4K
# NrU4DY/sBVqmab5AC/je3bpUpjtxpEyqUqtPc30wEg/rO9vmKmqKoLPT37svc2NV
# BmGNl+85qO4fV/w7Cx7J0Bbqk19KcRNdjt6eKoTnTPHBHlVHQIHZpMxacbFOAkJr
# qAVkYZdz7ikNXTxV+GRb36tC4ByMNxE2DF7vFdvaiZP0CVZ5ByJ2gAhXMdK9+usx
# zVk913qKde1OAuWdv+rndqkAIm8fUlRnr4saSCg7cIbUwCCf116wUJ7EuJDg0vHe
# yhnCeHnBbyH3RZkHEi2ofmfgnFISJZDdMAeVZGVOh20Jp50XBzqokpPzeZ6zc1/g
# yILNyiVgE+RPkjnUQshd1f1PMgn3tns2Cz7bJiVUaqEO3n9qRFgy5JuLae6UweGf
# AeOo3dgLZxikKzYs3hDMaEtJq8IP71cX7QXe6lnMmXU/Hdfz2p897Zd+kU+vZvKI
# 3cwLfuVQgK2RZ2z+Kc3K3dRPz2rXycK5XCuRZmvGab/WbrZiC7wJQapgBodltMI5
# GMdFrBg9IeF7/rP4EqVQXeKtevTlZXjpuNhhjuR+2DMt/dWufjXpiW91bo3aH6Ea
# jOALXmoxgltCp1K7hrS6gmsvj94cLRf50QQ4U8Qwggd6MIIFYqADAgECAgphDpDS
# AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0
# ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla
# MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
# ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT
# H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG
# OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S
# 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz
# y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7
# 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u
# M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33
# X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl
# XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP
# 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB
# l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF
# RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM
# CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ
# BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud
# DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO
# 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0
# LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y
# Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB
# FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw
# cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA
# XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY
# 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj
# 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd
# d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ
# Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf
# wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ
# aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j
# NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B
# xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96
# eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7
# r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I
# RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIVdTCCFXECAQEwgZUwfjELMAkG
# A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx
# HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z
# b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAYdyF3IVWUDHCQAAAAABhzAN
# BglghkgBZQMEAgEFAKCBsDAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor
# BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgxnCG2mxi
# G4NJZUALqcoU1G7BuQdIsQ1M4n3XtMDBAA4wRAYKKwYBBAGCNwIBDDE2MDSgFIAS
# AE0AaQBjAHIAbwBzAG8AZgB0oRyAGmh0dHBzOi8vd3d3Lm1pY3Jvc29mdC5jb20g
# MA0GCSqGSIb3DQEBAQUABIIBAL3f4fvUTIWYkeZ2siEG1zwcqcC7GczUkXIrszwG
# FqvVi347jriWrAwOKd8p9MzN0fVWY/tLnOQZFE3XqQ64KGvxNdjoLMYdcqBTOU/3
# Jpimyb2ZHFV38tXs5PsVHJtCC8CzwZ8LuBlXFBl3J82WPUFN57Ma2W6fUM7Dj8oq
# bP/riz0iN0ge91nAI2ZZeeasvqnmkOjp1UyDZ1rB7cae2h9fvkfC/yK15QxZlmh+
# WgQFUe9Yik7FjC6ZgohwF8itNDdR0jillXzrVYILlDJP6gHjTh5JP7YY71Uf2VAQ
# wshDfCp0JAjA5UOSChrkeISKDhwQiwivcPBoLKc6s3pHyCehghL9MIIS+QYKKwYB
# BAGCNwMDATGCEukwghLlBgkqhkiG9w0BBwKgghLWMIIS0gIBAzEPMA0GCWCGSAFl
# AwQCAQUAMIIBWAYLKoZIhvcNAQkQAQSgggFHBIIBQzCCAT8CAQEGCisGAQQBhFkK
# AwEwMTANBglghkgBZQMEAgEFAAQgCeYKvPWvkpmMN9qYRuFtwPmtub4fUY6EUemN
# xqQ+ulkCBmAlqXF5IBgSMjAyMTAyMTUwNDUyMjUuMjRaMASAAgH0oIHYpIHVMIHS
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRN
# aWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRo
# YWxlcyBUU1MgRVNOOkQwODItNEJGRC1FRUJBMSUwIwYDVQQDExxNaWNyb3NvZnQg
# VGltZS1TdGFtcCBTZXJ2aWNloIIOTTCCBPkwggPhoAMCAQICEzMAAAFBr39Sl1zy
# 3EUAAAAAAUEwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
# Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
# dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB
# IDIwMTAwHhcNMjAxMDE1MTcyODI3WhcNMjIwMTEyMTcyODI3WjCB0jELMAkGA1UE
# BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc
# BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0
# IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMgVFNT
# IEVTTjpEMDgyLTRCRkQtRUVCQTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3Rh
# bXAgU2VydmljZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPIqy6i9
# vHWpfjyVJlCTsL2J/7DghM0M2co/eF2xT7UYQ4T42oL7yjr9RoDKDrl75KTN7jOR
# Ou78jgj8aoUwM6uwJN85BF1wb+yaDPF5tMeVHJwJKVIhKNHsnEZem52CAdypWVt7
# s+CXNr9hVdCghpC676nyj/Ff4toVcjfOeDno1qcfMBlGszOAmFFaMHIBA3O+jmPl
# 2uFtuwwmSZtn/aJeAY0i/m9i/0/J/yxBpJ2lMcEkEzdS0ArfrgQwgEnelUEeQiyy
# VbejAS9FtTZWlsRACcJSHcgZ0tYoS70YNY3PylGXtLERXQ934Sq4z2nN4aMtNOxb
# 6+hqNFieKa9qyXUCAwEAAaOCARswggEXMB0GA1UdDgQWBBQtKD8sbi6Q/UVwa/XP
# DTtBBRLGxDAfBgNVHSMEGDAWgBTVYzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8E
# TzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9k
# dWN0cy9NaWNUaW1TdGFQQ0FfMjAxMC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBM
# MEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRz
# L01pY1RpbVN0YVBDQV8yMDEwLTA3LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1Ud
# JQQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBCwUAA4IBAQBSet8ifdgoagoKXsQ+
# PKJL4hrguIpDbL5sJQknrdbBabyRMyyQfHExeM+KkE8/ALELXHsOpgFZkAmA7vX+
# XntdcV49S8B2LGRp0rPzn0bpdVSpmOdTkKaryuTvwreH7NCG5c6PHsjiycoE5Pe2
# l1QOFM6vBm5S+y0OV4sAGOOOjDgC5zVxaPyqvbb84qcGNWHEZ/55TEPm/djoiy5h
# 1TItsAFDkYihb2gH2Fo4UHftqhyzLHaTZbsAW1nuxReQAbA6NB0TjFsgoMXS0N76
# q9wzEh92ViooqxbL1iZnIX2TxkTm8KrM70lzxZjwWfaPnq/uFKC1fudBlp50JMux
# 1YC5MIIGcTCCBFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDEL
# MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
# bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWlj
# cm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAx
# MjEzNjU1WhcNMjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMK
# V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
# IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0Eg
# MjAxMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8
# E5f1+n9plGt0VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3O
# CROOfGEwWbEwRA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJY
# YEbyWEeGMoQedGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIa
# IYqvS2SJUGKxXf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo
# 8noqCjHw2k4GkbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhac
# AQVPIk0CAwEAAaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTV
# YzpcijGQ80N7fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL
# BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+ii
# XGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jv
# c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0y
# My5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1p
# Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNy
# dDCBoAYDVR0gAQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEW
# MWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5o
# dG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBT
# AHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbg
# mD+BcQM9naOhIW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4vceoniXj+bzt
# a1RXCCtRgkQS+7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/y
# N31aPxzymXlKkVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8
# tv0E4XCfMkon/VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpx
# Y517IW3DnKOiPPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4
# ILUl5WTs9/S/fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/Dh
# O3EJ3110mCIIYdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJ
# rDm77MbL2IK0cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXA
# L1QnIffIrE7aKLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8ch
# r1m1rtxEPJdQcdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQ
# NdrvCScc1bN+NR4Iuto229Nfj950iEkSoYIC1zCCAkACAQEwggEAoYHYpIHVMIHS
# MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk
# bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRN
# aWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsTHVRo
# YWxlcyBUU1MgRVNOOkQwODItNEJGRC1FRUJBMSUwIwYDVQQDExxNaWNyb3NvZnQg
# VGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQCq5b8ptQqriKEHK853
# C75A9VqVA6CBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
# dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
# YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0G
# CSqGSIb3DQEBBQUAAgUA49QcFTAiGA8yMDIxMDIxNTA2MDA1M1oYDzIwMjEwMjE2
# MDYwMDUzWjB3MD0GCisGAQQBhFkKBAExLzAtMAoCBQDj1BwVAgEAMAoCAQACAh6w
# AgH/MAcCAQACAhE7MAoCBQDj1W2VAgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisG
# AQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZIhvcNAQEFBQAD
# gYEAdug8YqkRKLCVBxGlYxAcLlyr7BCbLN5hBXoRlAY5Q/P/sUMHS5o00dwK4UUV
# XvlEFSDDtpZgiphHzi3ZU9cF0CPBn1C/StvbFT0zLiP8xfL2LIka005Z8Cfm/Yo+
# dPJb5K0/sBPoZo247yNgxMutMhbRKGxcmtbYbduqGGSiY+QxggMNMIIDCQIBATCB
# kzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
# UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD
# Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAUGvf1KXXPLcRQAA
# AAABQTANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJ
# EAEEMC8GCSqGSIb3DQEJBDEiBCAaYZwRns35jF98yINfdOwQMDJh/DwF9T4tZSjU
# Rc2CUDCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIFE/ATyM6nN0nnB0Tyyg
# bVtLzjp0/u/IWlqPl3MVXq3eMIGYMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNV
# BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv
# c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg
# UENBIDIwMTACEzMAAAFBr39Sl1zy3EUAAAAAAUEwIgQgCyk1sWeQ0wMdUrNsQrm+
# fQMKd4cPnKzUG+Ml9E9XfA8wDQYJKoZIhvcNAQELBQAEggEAkTnChYjd7GqAAnX/
# Ci6CuYbFWVXsJkOZaEUPcJi/dA5YCot2/DqD2fJ7KE61aJ1VXLgISZtH7NFk+ptT
# nliTDbTzTcp/DpCWlbN71LhVlPq25KsJ4O9jEg4esoFGEEpqzR5Yy+75X2DKtGrY
# G2rubH4jlnb/t/7QVZzSjbK8LmO/z8vCis7cRzucR4vOyG8nLJefSP7fW7Cd1F7N
# QbatP62OOxG9cm0TJGfVHBTWWPfSdYvKP/Pajbfs4b3A87IQyek3hx+WwqtdybdE
# hNqpXOLQBHOkngkmLEOJ2UM7bjg6bqHCLBg7BIsktklCyprGe/qpT79ALd7d8cww
# z0MVkw==
# SIG # End signature block