tools/classes.ps1

class UtilsCountry {
    [string]$Country
    [string]$Identifier
    [string]$EuProtocolOrder
    [string]$Name
    [string]$AlternateName
    [string]$Iso_3166_1_num
    [string]$Iso_3166_1_alpha_2
    [string]$Iso_3166_1_alpha_3
    [string]$PhonePrefix
    [string]$IanaDomain
    [string[]]$GeoScheme
    [string[]]$Continent
    [string]$Status
    [string[]]$Language
    [string[]]$Classification

    static [UtilsCountry[]] $AllCountries = @()

    UtilsCountry() {
        $this.InitFromHashtable(@{})
    }
    UtilsCountry([UtilsCountry]$UtilsCountry) {
        $this.InitFromHashtable($UtilsCountry.ToHashtable())
    }
    UtilsCountry([pscustomobject]$Object) {
        $this.InitFromHashtable($Object)
    }
    UtilsCountry([hashtable]$Hashtable) {
        $this.InitFromHashtable($Hashtable)
    }
    UtilsCountry([string]$Country,[string]$Identifier,[string]$EuProtocolOrder,[string]$Name,[string]$AlternateName,[string]$Iso_3166_1_num,[string]$Iso_3166_1_alpha_2,[string]$Iso_3166_1_alpha_3,[string]$PhonePrefix,[string]$IanaDomain,[string[]]$GeoScheme,[string[]]$Continent,[string]$Status,[string[]]$Language,[string[]]$Classification) {
        $this.InitFromHashtable(@{
            Country = $Country
            Identifier = $Identifier
            EuProtocolOrder = $EuProtocolOrder
            Name = $Name
            AlternateName = $AlternateName
            Iso_3166_1_num = $Iso_3166_1_num
            Iso_3166_1_alpha_2 = $Iso_3166_1_alpha_2
            Iso_3166_1_alpha_3 = $Iso_3166_1_alpha_3
            PhonePrefix = $PhonePrefix
            IanaDomain = $IanaDomain
            GeoScheme = $GeoScheme | Foreach-Object { $_ }
            Continent = $Continent | Foreach-Object { $_ }
            Status = $Status
            Language = $Language | Foreach-Object { $_ }
            Classification = $Classification | Foreach-Object { $_ }
        })
    }

    [void] SetCountry([string]$Country) { $this.Country = $Country }
    [void] SetIdentifier([string]$Identifier) { $this.Identifier = $Identifier }
    [void] SetEuProtocolOrder([string]$EuProtocolOrder) { $this.EuProtocolOrder = $EuProtocolOrder }
    [void] SetName([string]$Name) { $this.Name = $Name }
    [void] SetDefinition([string]$AlternateName) { $this.AlternateName = $AlternateName }
    [void] SetIso_3166_1_num([string]$Iso_3166_1_num) { $this.Iso_3166_1_num = $Iso_3166_1_num }
    [void] SetIso_3166_1_alpha_2([string]$Iso_3166_1_alpha_2) { $this.Iso_3166_1_alpha_2 = $Iso_3166_1_alpha_2 }
    [void] SetIso_3166_1_alpha_3([string]$Iso_3166_1_alpha_3) { $this.Iso_3166_1_alpha_3 = $Iso_3166_1_alpha_3 }
    [void] SetPhonePrefix([string]$PhonePrefix) { $this.PhonePrefix = $PhonePrefix }
    [void] SetIanaDomain([string]$IanaDomain) { $this.IanaDomain = $IanaDomain }
    [void] SetGeoScheme([string[]]$GeoScheme) { $this.GeoScheme = $GeoScheme | Foreach-Object { $_ } }
    [void] SetContinent([string[]]$Continent) { $this.Continent = $Continent | Foreach-Object { $_ } }
    [void] SetStatus([string]$Status) { $this.Status = $Status }
    [void] SetLanguage([string[]]$Language) { $this.Language = $Language | Foreach-Object { $_ } }
    [void] SetClassification([string[]]$Classification) { $this.Classification = $Classification | Foreach-Object { $_ } }

    [hashtable] ToHashtable() {
        return @{
            Country = $this.Country
            Identifier = $this.Identifier
            EuProtocolOrder = $this.EuProtocolOrder
            Name = $this.Name
            AlternateName = $this.AlternateName
            Iso_3166_1_num = $this.Iso_3166_1_num
            Iso_3166_1_alpha_2 = $this.Iso_3166_1_alpha_2
            Iso_3166_1_alpha_3 = $this.Iso_3166_1_alpha_3
            PhonePrefix = $this.PhonePrefix
            IanaDomain = $this.IanaDomain
            GeoScheme = $this.GeoScheme | Foreach-Object { $_ }
            Continent = $this.Continent | Foreach-Object { $_ }
            Status = $this.Status
            Language = $this.Language | Foreach-Object { $_ }
            Classification = $this.Classification | Foreach-Object { $_ }
        }
    }

    static [UtilsCountry] FromHashtable([hashtable]$properties) {
        $UtilsCountry = [UtilsCountry]::new()
        $UtilsCountry.InitFromHashtable($properties)
        return $UtilsCountry
    }

    static [UtilsCountry] FromCustomObject([pscustomobject]$object) {
        $UtilsCountry = [UtilsCountry]::new()
        $UtilsCountry.InitFromCustomObject($object)
        return $UtilsCountry
    }

    [void] InitFromCustomObject([pscustomobject]$object) {
        $properties = @{}
        $object | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | Foreach-Object {
            $properties += @{ $_ = $object.$_ }
        }
        $this.InitFromHashtable($properties)
    }

    [void] InitFromHashtable([hashtable]$Properties) {
        if($Properties -eq [hashtable]::empty -or $null -eq $Properties) {
            Write-Warning "EMPTY INPUT"
            # Nothing to do (empty input)
        } else {
            $NamesReceived = [object[]]$Properties.Keys
            $NamesCustomObject = [object[]](@('country','identifier','protocol','name_en','iso_3166_1_alpha_2','iso_3166_1_alpha_3','iso_3166_1_num','phone_prefix','iana_domain','unsd_geoscheme','status','alt_name_en','continent','language','classification'))

            if(Compare-Object $NamesReceived $NamesCustomObject) {
                # This is the default case, input matches UtilsCountry's structure
                foreach ($Property in $Properties.Keys) {
                    switch($Property) {
                        'Country' {  $this.SetCountry($Properties.Country)}
                        'Identifier' {  $this.SetIdentifier($Properties.Identifier)}
                        'EuProtocolOrder' {  $this.SetEuProtocolOrder($Properties.EuProtocolOrder)}
                        'Name' {  $this.SetName($Properties.Name)}
                        'AlternateName' {  $this.SetDefinition($Properties.AlternateName)}
                        'Iso_3166_1_num' {  $this.SetIso_3166_1_num($Properties.Iso_3166_1_num)}
                        'Iso_3166_1_alpha_2' {  $this.SetIso_3166_1_alpha_2($Properties.Iso_3166_1_alpha_2)}
                        'Iso_3166_1_alpha_3' {  $this.SetIso_3166_1_alpha_3($Properties.Iso_3166_1_alpha_3)}
                        'PhonePrefix' {  $this.SetPhonePrefix($Properties.PhonePrefix)}
                        'IanaDomain' {  $this.SetIanaDomain($Properties.IanaDomain)}
                        'GeoScheme' {  $this.SetGeoScheme($Properties.GeoScheme)}
                        'Continent' {  $this.SetContinent($Properties.Continent)}
                        'Status' {  $this.SetStatus($Properties.Status)}
                        'Language' {  $this.SetLanguage($Properties.Language)}
                        'Classification' {  $this.SetClassification($Properties.Classification)}
                        default {   [System.ArgumentException]::New("No such property: $($Property).")  }
                    }
                }
            } else {
                # The received data comes from a call to Get-Language, returning data from Invoke-PublicationOffice
                # The keys have to be mapped to those of UtilsCountry
                foreach ($Property in $Properties.Keys) {
                    switch($Property) {

                        'country' {  $this.SetCountry($Properties.country)}
                        'identifier' {  $this.SetIdentifier($Properties.identifier)}
                        'protocol' {  $this.SetEuProtocolOrder($Properties.protocol)}
                        'name_en' {  $this.SetName($Properties.name_en)}
                        'alt_name_en' {  $this.SetDefinition($Properties.alt_name_en)}
                        'iso_3166_1_num' {  $this.SetIso_3166_1_num($Properties.iso_3166_1_num)}
                        'iso_3166_1_alpha_2' {  $this.SetIso_3166_1_alpha_2($Properties.Iso_3166_1_alpha_2)}
                        'iso_3166_1_alpha_3' {  $this.SetIso_3166_1_alpha_3($Properties.Iso_3166_1_alpha_3)}
                        'phone_prefix' {  $this.SetPhonePrefix($Properties.phone_prefix)}
                        'iana_domain' {  $this.SetIanaDomain($Properties.iana_domain)}
                        'unsd_geoscheme' {  $this.SetGeoScheme($Properties.unsd_geoscheme)}
                        'continent' {  $this.SetContinent($Properties.continent)}
                        'status' {  $this.SetStatus($Properties.status)}
                        'language' {  $this.SetLanguage($Properties.language)}
                        'classification' {  $this.SetClassification($Properties.classification)}
                        default {   [System.ArgumentException]::New("No such property: $($Property).")  }
                    }
                }
            }

            [UtilsCountry]::AllCountries += $this
        }
    }

    [UtilsCountry] Clone() {
        return $this.PSObject.Copy()
    }

    [string] ToString() {
        return "$($this.Name)"
    }

    static [void] ClearAllCountries() {
        [UtilsCountry]::AllCountries = @()
    }
}
class UtilsLanguage {
    [string]$Language
    [string]$Status
    [string[]]$Classification
    [string]$Identifier
    [string]$EuProtocolOrder
    [string]$Name
    [string]$Definition
    [string[]]$Iso2
    [string]$Iso_639_1
    [string]$Iso_639_3
    [string]$NameTranslated

    static [UtilsLanguage[]] $AllLanguages = @()

    UtilsLanguage() {
        $this.InitFromHashtable(@{})
    }
    UtilsLanguage([UtilsLanguage]$UtilsLanguage) {
        $this.InitFromHashtable($UtilsLanguage.ToHashtable())
    }
    UtilsLanguage([pscustomobject]$Object) {
        $this.InitFromHashtable($Object)
    }
    UtilsLanguage([hashtable]$Hashtable) {
        $this.InitFromHashtable($Hashtable)
    }
    UtilsLanguage([string]$Language,[string]$Status,[string[]]$Classification,[string]$Identifier,[string]$EuProtocolOrder,[string]$Name,[string]$Definition,[string[]]$Iso2,[string]$Iso_639_1,[string]$Iso_639_3,[string]$NameTranslated) {
        $this.InitFromHashtable(@{
            Language = $Language
            Status = $Status
            Classification = $Classification | Foreach-Object { $_ }
            Identifier = $Identifier
            EuProtocolOrder = $EuProtocolOrder
            Name = $Name
            Definition = $Definition
            Iso2 = $Iso2 | Foreach-Object { $_ }
            Iso_639_1 = $Iso_639_1
            Iso_639_3 = $Iso_639_3
            NameTranslated = $NameTranslated
        })
    }

    [void] SetLanguage([string]$Language) { $this.Language = $Language }
    [void] SetStatus([string]$Status) { $this.Status = $Status }
    [void] SetClassification([string[]]$Classification) { $this.Classification = $Classification | Foreach-Object { $_ } }
    [void] SetIdentifier([string]$Identifier) { $this.Identifier = $Identifier }
    [void] SetEuProtocolOrder([string]$EuProtocolOrder) { $this.EuProtocolOrder = $EuProtocolOrder }
    [void] SetName([string]$Name) { $this.Name = $Name }
    [void] SetDefinition([string]$Definition) { $this.Definition = $Definition }
    [void] SetIso2([string[]]$Iso2) { $this.Iso2 = $Iso2 | Foreach-Object { $_ } }
    [void] SetIso_639_1([string]$Iso_639_1) { $this.Iso_639_1 = $Iso_639_1 }
    [void] SetIso_639_3([string]$Iso_639_3) { $this.Iso_639_3 = $Iso_639_3 }
    [void] SetNameTranslated([string]$NameTranslated) { $this.NameTranslated = $NameTranslated }

    [hashtable] ToHashtable() {
        return @{
            Language = $this.Language
            Status = $this.Status
            Classification = $this.Classification | Foreach-Object { $_ }
            Identifier = $this.Identifier
            EuProtocolOrder = $this.EuProtocolOrder
            Name = $this.Name
            Definition = $this.Definition
            Iso2 = $this.Iso2 | Foreach-Object { $_ }
            Iso_639_1 = $this.Iso_639_1
            Iso_639_3 = $this.Iso_639_3
            NameTranslated = $this.NameTranslated
        }
    }

    static [UtilsLanguage] FromHashtable([hashtable]$properties) {
        $UtilsLanguage = [UtilsLanguage]::new()
        $UtilsLanguage.InitFromHashtable($properties)
        return $UtilsLanguage
    }

    static [UtilsLanguage] FromCustomObject([pscustomobject]$object) {
        $UtilsLanguage = [UtilsLanguage]::new()
        $UtilsLanguage.InitFromCustomObject($object)
        return $UtilsLanguage
    }

    [void] InitFromCustomObject([pscustomobject]$object) {
        $properties = @{}
        $object | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | Foreach-Object {
            $properties += @{ $_ = $object.$_ }
        }
        $this.InitFromHashtable($properties)
    }

    [void] InitFromHashtable([hashtable]$Properties) {
        if($Properties -eq [hashtable]::empty -or $null -eq $Properties) {
            Write-Warning "EMPTY INPUT"
            # Nothing to do (empty input)
        } else {
            $NamesReceived = [object[]]$Properties.Keys
            $NamesCustomObject = [object[]](@('language','identifier','protocol','name_en','definition_en','name','iso','iso_639_1','iso_639_3','status','classification'))

            if(Compare-Object $NamesReceived $NamesCustomObject) {
                # This is the default case, input matches UtilsLanguage's structure
                foreach ($Property in $Properties.Keys) {
                    switch($Property) {
                        'Language' {  $this.SetLanguage($Properties.Language)}
                        'Status' {  $this.SetStatus($Properties.Status)}
                        'Classification' {  $this.SetClassification($Properties.Classification)}
                        'Identifier' {  $this.SetIdentifier($Properties.Identifier)}
                        'EuProtocolOrder' {  $this.SetEuProtocolOrder($Properties.EuProtocolOrder)}
                        'Name' {  $this.SetName($Properties.Name)}
                        'Definition' {  $this.SetDefinition($Properties.Definition)}
                        'Iso2' {  $this.SetIso2($Properties.Iso2)}
                        'Iso_639_1' {  $this.SetIso_639_1($Properties.Iso_639_1)}
                        'Iso_639_3' {  $this.SetIso_639_3($Properties.Iso_639_3)}
                        'NameTranslated' {  $this.SetNameTranslated($Properties.NameTranslated)}
                        default {   [System.ArgumentException]::New("No such property: $($Property).")  }
                    }
                }
            } else {
                # The received data comes from a call to Get-Language, returning data from Invoke-PublicationOffice
                # The keys have to be mapped to those of UtilsLanguage
                foreach ($Property in $Properties.Keys) {
                    switch($Property) {
                        'language' {  $this.SetLanguage($Properties.language)}
                        'status' {  $this.SetStatus($Properties.status)}
                        'classification' {  $this.SetClassification($Properties.classification)}
                        'identifier' {  $this.SetIdentifier($Properties.identifier)}
                        'protocol' {  $this.SetEuProtocolOrder($Properties.protocol)}
                        'name_en' {  $this.SetName($Properties.name_en)}
                        'definition_en' {  $this.SetDefinition($Properties.definition_en)}
                        'iso' {  $this.SetIso2($Properties.iso)}
                        'iso_639_1' {  $this.SetIso_639_1($Properties.iso_639_1)}
                        'iso_639_3' {  $this.SetIso_639_3($Properties.iso_639_3)}
                        'name' {  $this.SetNameTranslated($Properties.name)}
                        default {   [System.ArgumentException]::New("No such property: $($Property).")  }
                    }
                }
            }

            [UtilsLanguage]::AllLanguages += $this
        }
    }

    [UtilsLanguage] Clone() {
        return $this.PSObject.Copy()
    }

    [string] ToString() {
        return "$($this.Name)"
    }

    static [void] ClearAllLanguages() {
        [UtilsLanguage]::AllLanguages = @()
    }
}
class UtilsXDocument {
    static [System.Xml.Linq.XDocument] HTmlToXDocument([string] $InputString,[string[]] $Namespaces) {
        return [System.Xml.Linq.XDocument]::Parse([UtilsXDocument]::Xmlify($InputString,$Namespaces))
    }
    static [object[]] Xpath([object] $InputObject, [string] $XPath, [string[]] $Namespaces) {
        if($null -ne $Namespaces -and $Namespaces.Length) {
            $NS = @{}
            $Namespaces | Where-Object { $_ } | ForEach-Object {
                $NS.$_ = $_
            }
            return $InputObject | Select-Xml -Namespace $NS -XPath $Xpath
        } else {
            return $InputObject | Select-Xml -XPath $Xpath
        }
    }
    static [string] Xmlify([string] $InputString,[string[]] $Namespaces) {
        $Xml = '<!DOCTYPE xml [ '
        [UtilsXDocument]::HtmlEntities | Where-Object { $_ } | ForEach-Object {
            $Xml += "<!ENTITY $($_) """">"
        }
        $Xml += ']>'
        $Xml += '<xml'
        if($Namespaces -is [Array]) {
            $Namespaces | Where-Object { $_ } | ForEach-Object {
                $Xml += " xmlns:$($_)=""$($_)"""
            }
        }
        $Xml += '>'
        $InputString | Foreach-Object {
            $Xml += $_
        }
        $Xml += '</xml>'
        return $Xml
    }
    static [string[]] $HtmlEntities = @(
        'acute'
        'aacute'
        'Aacute'
        'Acirc'
        'acirc'
        'Aelig'
        'aelig'
        'agrave'
        'Agrave'
        'aring'
        'Aring'
        'atilde'
        'Atilde'
        'auml'
        'Auml'
        'bdquo'
        'brvbar'
        'bull'
        'ccedil'
        'clubs'
        'copy'
        'darr'
        'diams'
        'eacute'
        'Eacute'
        'ecirc'
        'Ecirc'
        'egrave'
        'Egrave'
        'euml'
        'Euml'
        'hearts'
        'hellip'
        'iacute'
        'Iacute'
        'icirc'
        'Icirc'
        'igrave'
        'Igrave'
        'iuml'
        'Iuml'
        'laquo'
        'larr'
        'ldquo'
        'lsaquo'
        'lsquo'
        'mbash'
        'middot'
        'nbsp'
        'ndash'
        'nearr'
        'ntilde'
        'Ntilde'
        'nwarr'
        'oacute'
        'Oacute'
        'ocirc'
        'Ocirc'
        'ograve'
        'Ograve'
        'otilde'
        'Otilde'
        'ouml'
        'Ouml'
        'quot'
        'raquo'
        'rarr'
        'rdquo'
        'rsaquo'
        'rsquo'
        'sbquo'
        'searr'
        'spades'
        'swarr'
        'szlig'
        'trade'
        'uacute'
        'Uacute'
        'uarr'
        'Uarr'
        'Ucirc'
        'ucirc'
        'ugrave'
        'Ugrave'
        'uuml'
        'Uuml'
    )
}