Idabus.Automation.Core.psm1

##############################################
###
### IDABUS Ressource PowerShell
### (c) 2023 Oxford Computer Group GmbH
###
##############################################

Import-Module -PassThru -Name (Join-Path $PSScriptRoot 'IDABUS.Automation.Core51.dll') 


##########################################################
###
### Get the user account this session ist connected with
###
##########################################################
function Get-IdabusLogonAccount
{
   
    $user = Send-IdabusGetRequest -ResourcePath "/user/person"

    return $user|convertfrom-json

}


##########################################################
###
### Get IDABUS Resource
###
##########################################################
function Get-IdabusResource
{
   
    [CmdletBinding(DefaultParameterSetName = 'AttributeValue')]
    param(
                    
        [Parameter(Mandatory = $true, ParameterSetName = 'AttributeValue', Position = 0)]
        [string] $ObjectType,
        
        [Parameter(Mandatory = $true, ParameterSetName = 'AttributeValue', Position = 1)]
        [string] $AttributeName,

        [Parameter(Mandatory = $true, ParameterSetName = 'AttributeValue', Position = 2)]
        [string] $AttributeValue,

        [Parameter(Mandatory = $true, ParameterSetName = 'ByID', Position = 0)]
        [Guid] $ID,

        [Parameter(ParameterSetName = 'ByID')]
        [Parameter(ParameterSetName = 'AttributeValue')]
        [switch]$IncludeNull
        
    
    )
    
    $queries = @()
    
    if($IncludeNull)
    {
        $queries += "queryFormat=IncludeNull"
    }
        
    switch ($PsCmdlet.ParameterSetName) {
        "AttributeValue" {
        
            $xpath = "/$ObjectType[$AttributeName='$AttributeValue']"
            $xpathQuery = [Uri]::EscapeDataString($xpath)
            $queries += "xPathQuery=$xpathQuery"
                
            $result = Send-IdabusGetRequest -ResourcePath "/Resources/Search" -Queries $queries

            $jsonResult = $result|ConvertFrom-Json

            return  $jsonResult.results[0]

        }
        "ByID" {
            $result = Send-IdabusGetRequest -ResourcePath "/Resources/$ID" -Queries $queries

            $result|ConvertFrom-Json
        }
    }
}

##########################################################
###
### Save IDABUS Resource
###
##########################################################
function Save-IdabusResource
{
   
    [CmdletBinding(SupportsShouldProcess)]
    param(
       
        [parameter(Mandatory=$true, ValueFromPipeline=$true, Position = 0)]
        [PSCustomObject] $InputObject
    )


    PROCESS
    {
    
        $content = $InputObject|ConvertTo-Json
        $id = $InputObject.objectid
       
        
        if([string]::IsNullOrEmpty($id))
        {
            if($PSCmdlet.ShouldProcess($content))
            {
                $result = Send-IdabusPostRequest -ResourcePath "/Resources/" -JsonContent $content
                return convertfrom-json -InputObject $result
            }
        }
        else
        {
            if($PSCmdlet.ShouldProcess($content))
            {
                $result = Send-IdabusPatchRequest -ResourcePath "/Resources/$id" -JsonContent $content
                return convertfrom-json -InputObject $result
            }
        }
        
        
  
    }
       
}

##########################################################
###
### New IDABUS Resource
###
##########################################################
function New-IdabusResource
{
    [CmdletBinding(SupportsShouldProcess)]
    param(
       
        [parameter(Mandatory=$true, Position = 0)]
        [string] $ObjectType
    )

    PROCESS
    {
        if($PSCmdlet.ShouldProcess($ObjectType))
        {
            return Get-IdabusSchemaBindings $ObjectType -WriteableOnly
        }
    }
}

##########################################################
###
### Delete IDABUS Resources
###
##########################################################
function Remove-IdabusResource
{
   
    [CmdletBinding(SupportsShouldProcess)]
    param(
       
        [parameter(Mandatory=$true,ParameterSetName = 'xpath', Position = 0)]
        [string] $XPath,

        [parameter(Mandatory=$true,ParameterSetName = 'id', Position = 0)]
        [string] $ID,
        
        [parameter(Mandatory=$true,ParameterSetName = 'entry', Position = 0,  ValueFromPipeline=$true)]
        [PSCustomObject] $InputObject,

        [parameter(ParameterSetName = 'xpath')]
        [switch]$DisableReferenceCleanup,

        [parameter(ParameterSetName = 'xpath')]
        [switch]$EnablePreUpdateTriggers,

        [parameter(ParameterSetName = 'xpath')]
        [switch]$EnablePostUpdateTriggers,

        [parameter(ParameterSetName = 'xpath')]
        [parameter(ParameterSetName = 'id')]
        [parameter(ParameterSetName = 'entry')]
        [string]$Comment
    )


    PROCESS
    {
           
        
        $queries = @()

        $queries+= "xpath=$([Uri]::EscapeDataString($XPath))"
    
        if($DisableReferenceCleanup)
        {
            $queries += "disableReferenceCleanup=true"
        }

        if($EnablePreUpdateTriggers)
        {
            $queries += "disablePreUpdateTriggers=false"
        }

        if($EnablePostUpdateTriggers)
        {
            $queries += "disablePostUpdateTriggers=false"
        }

        if(![string]::IsNullOrEmpty($Comment))
        {
            $queries += "comment=" + [Uri]::EscapeDataString($Comment)
        }



        switch ($PsCmdlet.ParameterSetName)
        {
            "id"
            {
                if($PSCmdlet.ShouldProcess($ID))
                {
                    Send-IdabusDeleteRequest -ResourcePath "/Resources/$ID" -Queries $queries
                }
            }
            "entry"
            {
                
                $entryID = $InputObject.objectid
                if($PSCmdlet.ShouldProcess($entryID))
                {
                    
                    
                    if(![String]::IsNullOrEmpty($entryID))
                    {
                        
                        Send-IdabusDeleteRequest -ResourcePath "/Resources/$entryID" -Queries $queries
                    }
                    else
                    {
                        throw "ObjectID on 'InputObject' is empty!"
                    }
                }
            }
            "xpath"
            {
                if($PSCmdlet.ShouldProcess($XPath))
                {
                    Send-IdabusDeleteRequest -ResourcePath "/Resources/xpath" -Queries $queries
                }
            }
        }
    
    }

        
}

function Search-IdabusResource {

    [CmdletBinding(DefaultParameterSetName = 'AttributesToGet')]
    param(
        [parameter(Mandatory=$true, Position = 0)]
        [string] $XPath,
        [parameter(Mandatory=$false, ParameterSetName = 'ExpectedObjectType', Position = 1)]
        [string] $ExpectedObjectType,
        [parameter(Mandatory=$false, ParameterSetName = 'AttributesToGet', Position = 1)]
        [string[]] $AttributesToGet = @("ObjectID","ObjectType"),
        [parameter(Mandatory=$false, ParameterSetName = 'Unconstrained', Position = 1)]
        [switch] $Unconstrained,
        [parameter(Mandatory=$false)]
        [ValidateRange(1,[int32]::MaxValue)]
        [int32] $PageSize = 200,
        [parameter(Mandatory=$false)]
        [ValidateRange(1,[int32]::MaxValue)]
        [int32] $MaxResults = [int32]::MaxValue,
        [parameter(Mandatory=$false)]
        [string] $SortByAttribute,
        [parameter(Mandatory=$false)]
        [switch] $Descending
    )
    
    begin {
        if ($MaxResults -lt $PageSize) {
            $PageSize = $MaxResults
        }

        $f_qry_body = [PSCustomObject]@{
            attributes   = $AttributesToGet
            queryFormat  = "IncludeNull" #"Standard"/"IncludeNull"/"Verbose"
            pageSize     = $PageSize #$PageSize
            includeCount = "fastonly" #"None"/"fastonly"/"Forced"
        }

        if ($SortByAttribute) {
            
            $f_sort_order = 'Ascending'
            if ($Descending) { $f_sort_order = 'Descending' }

            $f_qry_order = @{attribute = $SortByAttribute; order = $f_sort_order}
            
            Add-Member -InputObject $f_qry_body -MemberType NoteProperty -Name 'orderBy' -Value $f_qry_order
        }

        switch ($PSCmdlet.ParameterSetName) {

            'AttributesToGet' {

                $f_qry_atts = [System.Collections.Generic.List[object]]::new()

                $AttributesToGet.ForEach({
                    $f_qry_atts.Add($psitem)
                })

                $f_qry_body.attributes = $f_qry_atts.ToArray()

                break
            }

            'ExpectedObjectType' {
                $f_qry_body.attributes = @('*')
                $XPath =  $XPath.Substring(0,$XPath.Length-1) + " and (objecttype = values(`"$ExpectedObjectType`")) ]"
                break
            }

            'Unconstrained' {
                $f_qry_body.attributes  = @('*')
                break
            }

            default {
                break
            }
        }
    
        $f_xpath_esc = [Uri]::EscapeDataString($XPath)
        $f_qry_json  = ($f_qry_body | ConvertTo-Json -Depth 100)
    }

    process {
        
        [int]$f_total_results = 0

        $f_qry_results = (Send-IdabusPostRequest -ResourcePath "/Resources/Search" -Queries @("xPathQuery=$f_xpath_esc") -JsonContent $f_qry_json | ConvertFrom-Json)

        $f_total_results = $f_total_results + $f_qry_results.results.count
        
        Write-Output $f_qry_results.results

        if ($MaxResults -le $PageSize) {
            $f_qry_results.hasMoreItems = $false
        }

        while ([boolean]::Parse($f_qry_results.hasMoreItems)) {
            
            # Retrieve next page
            $f_qry_results = (Send-IdabusGetRequest -ResourcePath "Resources/search/continue" -Queries @("continuationToken=$($f_qry_results.continuationToken)","pageSize=$PageSize") | ConvertFrom-Json)
            
            $f_total_results = $f_total_results + $f_qry_results.results.count

            if ($f_total_results -gt $MaxResults) {
                Write-Output $f_qry_results.results | Select -first ($f_qry_results.totalCount % $MaxResults)
                break
            } else {
                Write-Output $f_qry_results.results
            }

            # Refresh Continuation Token
            if ($f_qry_results.continuationToken) {
                Send-IdabusGetRequest -ResourcePath "Resources/search/refreshtoken" -Queries @("continuationToken=$($f_qry_results.continuationToken)") | Out-Null
            }
        }
    }
    
    end {
    }
}

Export-ModuleMember -Function "Get-IdabusLogonAccount" 
Export-ModuleMember -Function "Get-IdabusResource"  
Export-ModuleMember -Function "Save-IdabusResource"
Export-ModuleMember -Function "Remove-IdabusResource"
Export-ModuleMember -Function "New-IdabusResource"
Export-ModuleMember -Function "Search-IdabusResource"



Export-ModuleMember -Cmdlet "Connect-IdabusService","Disconnect-IdabusService", "Reset-IdabusSchemaCache","Send-IdabusGetRequest","Send-IdabusPostRequest","Send-IdabusPutRequest","Send-IdabusPatchRequest","Send-IdabusDeleteRequest","IdabusSchemaBindings"



# SIG # Begin signature block
# MIIuJgYJKoZIhvcNAQcCoIIuFzCCLhMCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUKb+vl/m8nB1WPp8P6X3xHEBy
# IGeggidfMIIFcjCCA1qgAwIBAgIQdlP+rHVGSJP15ddKSDpO+DANBgkqhkiG9w0B
# AQwFADBTMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEp
# MCcGA1UEAxMgR2xvYmFsU2lnbiBDb2RlIFNpZ25pbmcgUm9vdCBSNDUwHhcNMjAw
# MzE4MDAwMDAwWhcNNDUwMzE4MDAwMDAwWjBTMQswCQYDVQQGEwJCRTEZMBcGA1UE
# ChMQR2xvYmFsU2lnbiBudi1zYTEpMCcGA1UEAxMgR2xvYmFsU2lnbiBDb2RlIFNp
# Z25pbmcgUm9vdCBSNDUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2
# LcUw3Xroq5A9A3KwOkuZFmGy5f+lZx03HOV+7JODqoT1o0ObmEWKuGNXXZsAiAQl
# 6fhokkuC2EvJSgPzqH9qj4phJ72hRND99T8iwqNPkY2zBbIogpFd+1mIBQuXBsKY
# +CynMyTuUDpBzPCgsHsdTdKoWDiW6d/5G5G7ixAs0sdDHaIJdKGAr3vmMwoMWWuO
# vPSrWpd7f65V+4TwgP6ETNfiur3EdaFvvWEQdESymAfidKv/aNxsJj7pH+XgBIet
# MNMMjQN8VbgWcFwkeCAl62dniKu6TjSYa3AR3jjK1L6hwJzh3x4CAdg74WdDhLbP
# /HS3L4Sjv7oJNz1nbLFFXBlhq0GD9awd63cNRkdzzr+9lZXtnSuIEP76WOinV+Gz
# z6ha6QclmxLEnoByPZPcjJTfO0TmJoD80sMD8IwM0kXWLuePmJ7mBO5Cbmd+QhZx
# YucE+WDGZKG2nIEhTivGbWiUhsaZdHNnMXqR8tSMeW58prt+Rm9NxYUSK8+aIkQI
# qIU3zgdhVwYXEiTAxDFzoZg1V0d+EDpF2S2kUZCYqaAHN8RlGqocaxZ396eX7D8Z
# MJlvMfvqQLLn0sT6ydDwUHZ0WfqNbRcyvvjpfgP054d1mtRKkSyFAxMCK0KA8olq
# Ns/ITKDOnvjLja0Wp9Pe1ZsYp8aSOvGCY/EuDiRk3wIDAQABo0IwQDAOBgNVHQ8B
# Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUHwC/RoAK/Hg5t6W0
# Q9lWULvOljswDQYJKoZIhvcNAQEMBQADggIBAF4runSXNERfdkgoQIST7gFu6aGz
# 1oAl5nvkvAmRPQ/8dq3X1DAgu49g0JHWHPKc73gaK5QyAsEkllJSAtDz0fzymzlu
# meEfjkNBfZoeW8ldmoT8JuaH83RyJq2kG9k9O2pSoDwJHi8ee7MztEXH96yxr5Ng
# rXauuLIVeOuDauv/20arJOXuAvqQH1nAL13Wt12kXBC3clP4QU7M+ngaJUrK/oVi
# Q2HDtDeqgdL01joPvY1ZfjBH3itr5yFQM1/UZ5vUuGefPCeZA/+FQ45zEsogzehh
# 1bFm3BfWOW0P288jN6GCiU4caz/WoM2qB50+Qiaq1wzu+ke/GlJ+0XWB08mKYhdt
# T4igIaAmPq9t2WIwH+mYKK5ujdWOTHJmk4CNKuNVx2BnkEJWXCJRD7PcTjnuTd3Z
# HXgQVDtu0JdvA7UesiNzxhKymmTQ/JWFJKj/36Gw3JFArt8JM6u53ZK38cyRdDtp
# 62eXG5C/58egb3G7V7+3j1rtekBqFs2AhC0v4QLUJJRDsxX8DCsb/XFv/Mu8dRc6
# XoPSybMvG9WcjX9U/n5+5Fajh6ed4VlSlEGPbVu+hpWa/xp23UDSUUpwtB8zYyN3
# P+wnHlnkCIftNIJKDz/+oB3B9WdzRYZ49Kop6SeHxhnbxhMUwzlJh02gl+BlE/Wd
# d1bp2rNYxzrywM2CMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkq
# hkiG9w0BAQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
# MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBB
# c3N1cmVkIElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5
# WjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
# ExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJv
# b3QgRzQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1K
# PDAiMGkz7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2r
# snnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C
# 8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBf
# sXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
# QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8
# rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaY
# dj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+
# wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw
# ++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+N
# P8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7F
# wI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUw
# AwEB/zAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAU
# Reuir/SSy4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEB
# BG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsG
# AQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1
# cmVkSURSb290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAow
# CDAGBgRVHSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/
# Vwe9mqyhhyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLe
# JLxSA8hO0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE
# 1Od/6Fmo8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9Hda
# XFSMb++hUD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbO
# byMt9H5xaiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIG
# rjCCBJagAwIBAgIQBzY3tyRUfNhHrP0oZipeWzANBgkqhkiG9w0BAQsFADBiMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw
# HhcNMjIwMzIzMDAwMDAwWhcNMzcwMzIyMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEX
# MBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0
# ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMIICIjANBgkqhkiG
# 9w0BAQEFAAOCAg8AMIICCgKCAgEAxoY1BkmzwT1ySVFVxyUDxPKRN6mXUaHW0oPR
# nkyibaCwzIP5WvYRoUQVQl+kiPNo+n3znIkLf50fng8zH1ATCyZzlm34V6gCff1D
# tITaEfFzsbPuK4CEiiIY3+vaPcQXf6sZKz5C3GeO6lE98NZW1OcoLevTsbV15x8G
# ZY2UKdPZ7Gnf2ZCHRgB720RBidx8ald68Dd5n12sy+iEZLRS8nZH92GDGd1ftFQL
# IWhuNyG7QKxfst5Kfc71ORJn7w6lY2zkpsUdzTYNXNXmG6jBZHRAp8ByxbpOH7G1
# WE15/tePc5OsLDnipUjW8LAxE6lXKZYnLvWHpo9OdhVVJnCYJn+gGkcgQ+NDY4B7
# dW4nJZCYOjgRs/b2nuY7W+yB3iIU2YIqx5K/oN7jPqJz+ucfWmyU8lKVEStYdEAo
# q3NDzt9KoRxrOMUp88qqlnNCaJ+2RrOdOqPVA+C/8KI8ykLcGEh/FDTP0kyr75s9
# /g64ZCr6dSgkQe1CvwWcZklSUPRR8zZJTYsg0ixXNXkrqPNFYLwjjVj33GHek/45
# wPmyMKVM1+mYSlg+0wOI/rOP015LdhJRk8mMDDtbiiKowSYI+RQQEgN9XyO7ZONj
# 4KbhPvbCdLI/Hgl27KtdRnXiYKNYCQEoAA6EVO7O6V3IXjASvUaetdN2udIOa5kM
# 0jO0zbECAwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE
# FLoW2W1NhS9zKXaaL3WMaiCPnshvMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/n
# upiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3Bggr
# BgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNv
# bTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lD
# ZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2Ny
# bDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0g
# BBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQB9
# WY7Ak7ZvmKlEIgF+ZtbYIULhsBguEE0TzzBTzr8Y+8dQXeJLKftwig2qKWn8acHP
# HQfpPmDI2AvlXFvXbYf6hCAlNDFnzbYSlm/EUExiHQwIgqgWvalWzxVzjQEiJc6V
# aT9Hd/tydBTX/6tPiix6q4XNQ1/tYLaqT5Fmniye4Iqs5f2MvGQmh2ySvZ180HAK
# fO+ovHVPulr3qRCyXen/KFSJ8NWKcXZl2szwcqMj+sAngkSumScbqyQeJsG33irr
# 9p6xeZmBo1aGqwpFyd/EjaDnmPv7pp1yr8THwcFqcdnGE4AJxLafzYeHJLtPo0m5
# d2aR8XKc6UsCUqc3fpNTrDsdCEkPlM05et3/JWOZJyw9P2un8WbDQc1PtkCbISFA
# 0LcTJM3cHXg65J6t5TRxktcma+Q4c6umAU+9Pzt4rUyt+8SVe+0KXzM5h0F4ejjp
# nOHdI/0dKNPH+ejxmF/7K9h+8kaddSweJywm228Vex4Ziza4k9Tm8heZWcpw8De/
# mADfIBZPJ/tgZxahZrrdVcA6KYawmKAr7ZVBtzrVFZgxtGIJDwq9gdkT/r+k0fNX
# 2bwE+oLeMt8EifAAzV3C+dAjfwAL5HYCJtnwZXZCpimHCUcr5n8apIUP/JiW9lVU
# Kx+A+sDyDivl1vupL0QVSucTDh3bNzgaoSv27dZ8/DCCBsAwggSooAMCAQICEAxN
# aXJLlPo8Kko9KQeAPVowDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAV
# BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVk
# IEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTAeFw0yMjA5MjEwMDAw
# MDBaFw0zMzExMjEyMzU5NTlaMEYxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdp
# Q2VydDEkMCIGA1UEAxMbRGlnaUNlcnQgVGltZXN0YW1wIDIwMjIgLSAyMIICIjAN
# BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAz+ylJjrGqfJru43BDZrboegUhXQz
# Gias0BxVHh42bbySVQxh9J0Jdz0Vlggva2Sk/QaDFteRkjgcMQKW+3KxlzpVrzPs
# YYrppijbkGNcvYlT4DotjIdCriak5Lt4eLl6FuFWxsC6ZFO7KhbnUEi7iGkMiMbx
# vuAvfTuxylONQIMe58tySSgeTIAehVbnhe3yYbyqOgd99qtu5Wbd4lz1L+2N1E2V
# hGjjgMtqedHSEJFGKes+JvK0jM1MuWbIu6pQOA3ljJRdGVq/9XtAbm8WqJqclUeG
# hXk+DF5mjBoKJL6cqtKctvdPbnjEKD+jHA9QBje6CNk1prUe2nhYHTno+EyREJZ+
# TeHdwq2lfvgtGx/sK0YYoxn2Off1wU9xLokDEaJLu5i/+k/kezbvBkTkVf826uV8
# MefzwlLE5hZ7Wn6lJXPbwGqZIS1j5Vn1TS+QHye30qsU5Thmh1EIa/tTQznQZPpW
# z+D0CuYUbWR4u5j9lMNzIfMvwi4g14Gs0/EH1OG92V1LbjGUKYvmQaRllMBY5eUu
# KZCmt2Fk+tkgbBhRYLqmgQ8JJVPxvzvpqwcOagc5YhnJ1oV/E9mNec9ixezhe7nM
# ZxMHmsF47caIyLBuMnnHC1mDjcbu9Sx8e47LZInxscS451NeX1XSfRkpWQNO+l3q
# RXMchH7XzuLUOncCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB
# Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EM
# AQQCMAsGCWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57I
# bzAdBgNVHQ4EFgQUYore0GH8jzEU7ZcLzT0qlBTfUpwwWgYDVR0fBFMwUTBPoE2g
# S4ZJaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNB
# NDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAw
# JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcw
# AoZMaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0
# UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOC
# AgEAVaoqGvNG83hXNzD8deNP1oUj8fz5lTmbJeb3coqYw3fUZPwV+zbCSVEseIhj
# VQlGOQD8adTKmyn7oz/AyQCbEx2wmIncePLNfIXNU52vYuJhZqMUKkWHSphCK1D8
# G7WeCDAJ+uQt1wmJefkJ5ojOfRu4aqKbwVNgCeijuJ3XrR8cuOyYQfD2DoD75P/f
# nRCn6wC6X0qPGjpStOq/CUkVNTZZmg9U0rIbf35eCa12VIp0bcrSBWcrduv/mLIm
# lTgZiEQU5QpZomvnIj5EIdI/HMCb7XxIstiSDJFPPGaUr10CU+ue4p7k0x+GAWSc
# AMLpWnR1DT3heYi/HAGXyRkjgNc2Wl+WFrFjDMZGQDvOXTXUWT5Dmhiuw8nLw/ub
# E19qtcfg8wXDWd8nYiveQclTuf80EGf2JjKYe/5cQpSBlIKdrAqLxksVStOYkEVg
# M4DgI974A6T2RUflzrgDQkfoQTZxd639ouiXdE4u2h4djFrIHprVwvDGIqhPm73Y
# HJpRxC+a9l+nJ5e6li6FV8Bg53hWf2rvwpWaSxECyIKcyRoFfLpxtU56mWz06J7U
# WpjIn7+NuxhcQ/XQKujiYu54BNu90ftbCqhwfvCXhHjjCANdRyxjqCU4lwHSPzra
# 5eX25pvcfizM/xdMTQCi2NYBDriL7ubgclWJLCcZYfZ3AYwwggboMIIE0KADAgEC
# AhB3vQ4Ft1kLth1HYVMeP3XtMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNVBAYTAkJF
# MRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSkwJwYDVQQDEyBHbG9iYWxTaWdu
# IENvZGUgU2lnbmluZyBSb290IFI0NTAeFw0yMDA3MjgwMDAwMDBaFw0zMDA3Mjgw
# MDAwMDBaMFwxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNh
# MTIwMAYDVQQDEylHbG9iYWxTaWduIEdDQyBSNDUgRVYgQ29kZVNpZ25pbmcgQ0Eg
# MjAyMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMsg75ceuQEyQ6Bb
# qYoj/SBerjgSi8os1P9B2BpV1BlTt/2jF+d6OVzA984Ro/ml7QH6tbqT76+T3Pji
# sxlMg7BKRFAEeIQQaqTWlpCOgfh8qy+1o1cz0lh7lA5tD6WRJiqzg09ysYp7ZJLQ
# 8LRVX5YLEeWatSyyEc8lG31RK5gfSaNf+BOeNbgDAtqkEy+FSu/EL3AOwdTMMxLs
# vUCV0xHK5s2zBZzIU+tS13hMUQGSgt4T8weOdLqEgJ/SpBUO6K/r94n233Hw0b6n
# skEzIHXMsdXtHQcZxOsmd/KrbReTSam35sOQnMa47MzJe5pexcUkk2NvfhCLYc+Y
# VaMkoog28vmfvpMusgafJsAMAVYS4bKKnw4e3JiLLs/a4ok0ph8moKiueG3soYgV
# PMLq7rfYrWGlr3A2onmO3A1zwPHkLKuU7FgGOTZI1jta6CLOdA6vLPEV2tG0leis
# 1Ult5a/dm2tjIF2OfjuyQ9hiOpTlzbSYszcZJBJyc6sEsAnchebUIgTvQCodLm3H
# adNutwFsDeCXpxbmJouI9wNEhl9iZ0y1pzeoVdwDNoxuz202JvEOj7A9ccDhMqeC
# 5LYyAjIwfLWTyCH9PIjmaWP47nXJi8Kr77o6/elev7YR8b7wPcoyPm593g9+m5XE
# EofnGrhO7izB36Fl6CSDySrC/blTAgMBAAGjggGtMIIBqTAOBgNVHQ8BAf8EBAMC
# AYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
# HQ4EFgQUJZ3Q/FkJhmPF7POxEztXHAOSNhEwHwYDVR0jBBgwFoAUHwC/RoAK/Hg5
# t6W0Q9lWULvOljswgZMGCCsGAQUFBwEBBIGGMIGDMDkGCCsGAQUFBzABhi1odHRw
# Oi8vb2NzcC5nbG9iYWxzaWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUwRgYIKwYB
# BQUHMAKGOmh0dHA6Ly9zZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2NvZGVz
# aWduaW5ncm9vdHI0NS5jcnQwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2NybC5n
# bG9iYWxzaWduLmNvbS9jb2Rlc2lnbmluZ3Jvb3RyNDUuY3JsMFUGA1UdIAROMEww
# QQYJKwYBBAGgMgECMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNp
# Z24uY29tL3JlcG9zaXRvcnkvMAcGBWeBDAEDMA0GCSqGSIb3DQEBCwUAA4ICAQAl
# daAJyTm6t6E5iS8Yn6vW6x1L6JR8DQdomxyd73G2F2prAk+zP4ZFh8xlm0zjWAYC
# ImbVYQLFY4/UovG2XiULd5bpzXFAM4gp7O7zom28TbU+BkvJczPKCBQtPUzosLp1
# pnQtpFg6bBNJ+KUVChSWhbFqaDQlQq+WVvQQ+iR98StywRbha+vmqZjHPlr00Bid
# /XSXhndGKj0jfShziq7vKxuav2xTpxSePIdxwF6OyPvTKpIz6ldNXgdeysEYrIEt
# GiH6bs+XYXvfcXo6ymP31TBENzL+u0OF3Lr8psozGSt3bdvLBfB+X3Uuora/Nao2
# Y8nOZNm9/Lws80lWAMgSK8YnuzevV+/Ezx4pxPTiLc4qYc9X7fUKQOL1GNYe6ZAv
# ytOHX5OKSBoRHeU3hZ8uZmKaXoFOlaxVV0PcU4slfjxhD4oLuvU/pteO9wRWXiG7
# n9dqcYC/lt5yA9jYIivzJxZPOOhRQAyuku++PX33gMZMNleElaeEFUgwDlInCI2O
# or0ixxnJpsoOqHo222q6YV8RJJWk4o5o7hmpSZle0LQ0vdb5QMcQlzFSOTUpEYck
# 08T7qWPLd0jV+mL8JOAEek7Q5G7ezp44UCb0IXFl1wkl1MkHAHq4x/N36MXU4lXQ
# 0x72f1LiSY25EXIMiEQmM2YBRN/kMw4h3mKJSAfa9TCCB/IwggXaoAMCAQICDAMj
# ZjMGqMxTW05AQjANBgkqhkiG9w0BAQsFADBcMQswCQYDVQQGEwJCRTEZMBcGA1UE
# ChMQR2xvYmFsU2lnbiBudi1zYTEyMDAGA1UEAxMpR2xvYmFsU2lnbiBHQ0MgUjQ1
# IEVWIENvZGVTaWduaW5nIENBIDIwMjAwHhcNMjMwMTE2MTU0MTExWhcNMjYwMzMw
# MTQzODMxWjCCAUAxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYD
# VQQFEwpIUkIgMTcwNzMzMRMwEQYLKwYBBAGCNzwCAQMTAkRFMRcwFQYLKwYBBAGC
# NzwCAQITBkJheWVybjEZMBcGCysGAQQBgjc8AgEBEwhNdWVuY2hlbjELMAkGA1UE
# BhMCREUxDzANBgNVBAgTBkJheWVybjEPMA0GA1UEBxMGRXJkaW5nMRkwFwYDVQQJ
# ExBHaWVzc2VyZWlzdHIuIDE2MSMwIQYDVQQKExpPeGZvcmQgQ29tcHV0ZXIgR3Jv
# dXAgR21iSDETMBEGA1UECxMKQ29uc3VsdGluZzEjMCEGA1UEAxMaT3hmb3JkIENv
# bXB1dGVyIEdyb3VwIEdtYkgxGDAWBgkqhkiG9w0BCQEWCXJiQG9jZy5kZTCCAiIw
# DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMEcgNzpx9sXDswyVwCbMLamjcIB
# IB731SqqmFXu9irF2ufrLLqmraN0M6LLNwwHLMqReKZBTFlmnotkb2BL35Jk8/vO
# TsGAmXDogatO4X+tmX6rqxGdfCtMLY1tGjzLhRlJkfRds/lrO98jstsxlT6+yIoB
# FEhET3+ERHE5SwQHiSGLdKMMZDdf4tmf9ZuK1nikk+a3eYd7kBnlXgwxBK4Z2Y6j
# LFW2iNQcL7syhI7QNcl7AVFIUIjN8eHIFH0MX8BkIlMz466GgBJzvhKTGMq/3LhG
# HxJwpcyZSlCaUuZQLqyDm2oJDThXoJ59TWweCopPrJUR+pbR6YODv4+tXylljsfG
# KLYb4Ym5CE3uez4C2KrY7kXxKfuYnuH0WfuE/JfxC6i3WyZmwu7Zn9rX3Xf6YMMT
# iSs7oV1/qKzQdlw9y41ZUzfiiJ5yNG+PwCFdXKJ8JrEbKSzt8rNWUU+22Al/JXz/
# +2fS77Z0R4OwC+aG41auLs8DrIvkAbGYEZM6Uac4q2Evop+f8u/MifiIXFSBf2wU
# OxKVT/uvXNVpeSoWZD+uI5ZmclsF/IgLJTzqeMOmelArth07cAGEcAW7Pz2ag1Pq
# t1WLjN9OYaX+zhO2AjIVENQfSR7X+RVTkzszp29apz5hyBBq+UhU8HK29AT7SzAx
# 6rfmPENFCsvX62mhAgMBAAGjggHMMIIByDAOBgNVHQ8BAf8EBAMCB4AwgZ8GCCsG
# AQUFBwEBBIGSMIGPMEwGCCsGAQUFBzAChkBodHRwOi8vc2VjdXJlLmdsb2JhbHNp
# Z24uY29tL2NhY2VydC9nc2djY3I0NWV2Y29kZXNpZ25jYTIwMjAuY3J0MD8GCCsG
# AQUFBzABhjNodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9nc2djY3I0NWV2Y29k
# ZXNpZ25jYTIwMjAwVQYDVR0gBE4wTDBBBgkrBgEEAaAyAQIwNDAyBggrBgEFBQcC
# ARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wBwYFZ4EM
# AQMwCQYDVR0TBAIwADBHBgNVHR8EQDA+MDygOqA4hjZodHRwOi8vY3JsLmdsb2Jh
# bHNpZ24uY29tL2dzZ2NjcjQ1ZXZjb2Rlc2lnbmNhMjAyMC5jcmwwFAYDVR0RBA0w
# C4EJcmJAb2NnLmRlMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaAFCWd
# 0PxZCYZjxezzsRM7VxwDkjYRMB0GA1UdDgQWBBTYOgAxf8YT9oktBxWk4pO1v3v8
# vDANBgkqhkiG9w0BAQsFAAOCAgEAKA8sD0fqdgzIeq4wkJLeqxeofgMHLt1h0Uqu
# bUeXNdYo4VchEGeJ4QF2e7NdP+Nf1TD1qvfWoYPZBUiHkR2HlWd9udiI7aO2rpm4
# PzQ9PitbPdKu3lz+49OcgPIPGVJZ0vXi2qIT5NXtSv2Pvtix1oDxQhnKkQAhhqC0
# Qe/YKkX6EDucIfDyG1zUMigevUD8WTn4u7B9v/nedxRs4wyxoHa0kp2EeQW6EFh0
# MP8UCxROyu1hVbZBaZE5tCBZ9zM5Rt2X5dwtxC8RE0EXeGQBX64arWTz5LoNEvxP
# 4m3Gar/qnyEy502l09NrdZUxXTfPx+MDssW9clylYcbWfbedRHaga/nBOiPpeFI/
# 2RDdoKNnPwiZsWKpXIhhsBK5i9Mg9xKnauVAfy0fGm/+hkdF4idxiO9z+oGap9OV
# mgDCbAZiJDHofkGOnMN1FLeweqzXSXnlpEtmIXvZ7zR0TbqBS9vyiFaJoz6YET7k
# rbfv7pLgRCWXc58PCl5ldXdMb87bz2CaIP1XZLwKFgY3IPQO7KgTO8Dy2KJgLYFA
# EJYsHnfE3fu2Lt029L2RGAjZth4OIaeXTyFVnx7q2Wr/xuPqHXvhKD6wqdpJkp7H
# +GYvY9RpnErF+0uVu0NLhmfNQRPTBmwIQL//XhQ9QWsxh1d8jCGexJQEeT2FKVyj
# WpOBPXQxggYxMIIGLQIBATBsMFwxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
# YWxTaWduIG52LXNhMTIwMAYDVQQDEylHbG9iYWxTaWduIEdDQyBSNDUgRVYgQ29k
# ZVNpZ25pbmcgQ0EgMjAyMAIMAyNmMwaozFNbTkBCMAkGBSsOAwIaBQCgeDAYBgor
# BgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEE
# MBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBR/
# ZL7YtEHS+FWzf45FAJMgXFIm/TANBgkqhkiG9w0BAQEFAASCAgAGzTdE5WyTfhZO
# 4Dpjs3UXQEXqFkf6Uo44putRfDxg70wgl/20BVNvuF96LbZs4obGRXOO0MqMSGEr
# OFWCMzTZj+UIFQ3SNhcrjMGorIV1W/7OZyLlxQhoi/CwQMAZ1b5W5xYiW071M3a4
# QxzerdhCmy7TbEHGAsSr8hiGKfGAlNfgTkwYyBSHGBra/o+kWs5N7X/Ne3zZtGjB
# z/hu6pnkZkxQKXT9Wl9ENf9/+2hbjTtGpm94jrmwxFU23G3AFB8E7IdyrcdGr1iQ
# LWLkyz6y6gtacjrM4lQDNcodjubcBR0kwi9qiw0h7zks+L+gBWYTZdArFXPGNWw4
# 72YR5h1pvWUjsXB1JJ94Mt5/A/31QE7cFSTyEWTmXLP1vVxE7MIqRvruFDODk5gB
# bggmyIHy4v5OWJQAjD6eN7/9L/C6Sa4aQysVPdjP6AkUxVRTzVoKUpmRT2zxvnja
# vvz1DVyYL0Eg/Z+j4QdN6PAusEGqVsDy8f6W3XTsLRi7r57lTzZmHXKA3aXq7/Vu
# bJpKvNtfG/XxQL/FOAxajCgPXt0lmlBeDRe6s6wH3wHQRPKsOpZ/Zqa1OakJKKhl
# 3Lb0ECNNWYsBlmF9dGaB7BUDwlEyNAsINbSgIjjZyCvZkY8iF0Lswj/gEciyiQXE
# 17ZH6P8wcypAlKeX2ybB2d6A7/FB9qGCAyAwggMcBgkqhkiG9w0BCQYxggMNMIID
# CQIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7
# MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1l
# U3RhbXBpbmcgQ0ECEAxNaXJLlPo8Kko9KQeAPVowDQYJYIZIAWUDBAIBBQCgaTAY
# BgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMzAyMjAw
# OTE5NTRaMC8GCSqGSIb3DQEJBDEiBCD3EjzJ/SDS5zxiWmxbGpe1L5EEXmsuYw2C
# mvZyuG//NDANBgkqhkiG9w0BAQEFAASCAgBfOO0rF7bBZ6Z4M8UmaDnM79flRdsM
# GhPBONP9P40rynAGxg+wk1Y5COYXmmX7BtKqahE5ns2rVCyod0rW0a4XEHlnPEvw
# ZQvhY+U1xsUnmRAabQ0gQsnqqXzJ5F1WdApSL4IvzBliDdqxpDR0Yn7jufcS+yMu
# Pfx1+/Wb8x9gQ0vZkLyn4VEoQOidouaKH3ysHdRy1kP3rnOzm3tln+ItsEFnoWc0
# kw4hLabHUvL3Lw3ePOUcJ2T7NFF5RStDvEpKzDrALp5YRLmN8ZZ2eZpqY52d+tND
# JS93cnOrKzMQaS8lRSImiDeoVkKsAujJtd8+LNsYNFLO8VfLWb/V59BCKCThLlLJ
# P6U1+lZ7INjvx71B2XDFhqB4L0mpoxbFX89Mkd+zkDb1+zc7OraLKm2zqhMe/8f3
# EL3pN0xYnBLdPtWHtxaPRcPeXhSazHXbPGHcXR+t0dqMpZvhfFqQf8ydfsyCyVT3
# OH1iWAOTRMY+sy3lJ4hWs8kDvZAZCnQc4dj8ira3OghE4lgrMHz4Asq2hBRm1xRS
# wc0W1CaSpS09fdQgj9qiPdhdxlpFc0iPHBbNbnbP9tpslet8YzYGmaBzsTWs/dyT
# PuitxYWr+P8XCoycVnDW4LBJOjiydbkVsAJJFuUvfC4TmZAomDS5CC6bnuggi1ey
# dqwvQOXMkXlDNw==
# SIG # End signature block