-
Notifications
You must be signed in to change notification settings - Fork 68
/
query.go
188 lines (147 loc) · 4.45 KB
/
query.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package gountries
import (
"strings"
"sync"
)
// Query holds a reference to the QueryHolder struct
var queryInitOnce sync.Once
var queryInstance *Query
// Query contains queries for countries, cities, etc.
type Query struct {
Countries map[string]Country
NameToAlpha2 map[string]string
Alpha3ToAlpha2 map[string]string
NativeNameToAlpha2 map[string]string
CallingCodeToAlpha2 map[string]string
CurrencyToAlpha2 map[string][]Country
}
// FindCountryByName finds a country by given name
func (q *Query) FindCountryByName(name string) (result Country, err error) {
lowerName := strings.ToLower(name)
alpha2, exists := q.NameToAlpha2[lowerName]
if !exists {
return Country{}, makeError("Could not find country with name", name)
}
return q.Countries[alpha2], nil
}
// FindCountryByNativeName
func (q *Query) FindCountryByNativeName(name string) (result Country, err error) {
lowerName := strings.ToLower(name)
alpha2, exists := q.NativeNameToAlpha2[lowerName]
if !exists {
return Country{}, makeError("Could not find country with native name", name)
}
return q.Countries[alpha2], nil
}
// FindCountryByAlpha fincs a country by given code
func (q *Query) FindCountryByAlpha(code string) (result Country, err error) {
codeU := strings.ToUpper(code)
switch {
case len(code) == 2:
country, exists := q.Countries[codeU]
if !exists {
return Country{}, makeError("Could not find country with code %s", code)
}
return country, nil
case len(code) == 3:
alpha2, exists := q.Alpha3ToAlpha2[codeU]
if !exists {
return Country{}, makeError("Could not find country with code", code)
}
return q.Countries[alpha2], nil
default:
return Country{}, makeError("Invalid code format", code)
}
}
func (q *Query) FindCountryByCallingCode(callingCode string) (result Country, err error) {
alpha2, exists := q.CallingCodeToAlpha2[callingCode]
if !exists {
return Country{}, makeError("Could not find country with callingCode", callingCode)
}
return q.Countries[alpha2], nil
}
// FindCountriesByCurrency finds a Country based on the given struct data
func (q *Query) FindCountriesByCurrency(currency string) (results []Country, err error) {
if len(currency) != 3 {
return nil, makeError("Invalid currency format", currency)
}
alpha2, exists := q.CurrencyToAlpha2[currency]
if !exists {
return []Country{}, makeError("Could not find countries with currency name", currency)
}
return alpha2, nil
}
// FindAllCountries returns a list of all countries
func (q *Query) FindAllCountries() (countries map[string]Country) {
return q.Countries
}
// FindCountries finds a Country based on the given struct data
func (q Query) FindCountries(c Country) (countries []Country) {
for _, country := range q.Countries {
// Name
//
if c.Name.Common != "" && strings.ToLower(c.Name.Common) == strings.ToLower(country.Name.Common) {
continue
}
// Alpha
//
if c.Alpha2 != "" && c.Alpha2 != country.Alpha2 {
continue
}
if c.Alpha3 != "" && c.Alpha3 != country.Alpha3 {
continue
}
// Geo
//
if c.Geo.Continent != "" && strings.ToLower(c.Geo.Continent) != strings.ToLower(country.Geo.Continent) {
continue
}
if c.Geo.Region != "" && strings.ToLower(c.Geo.Region) != strings.ToLower(country.Geo.Region) {
continue
}
if c.Geo.SubRegion != "" && strings.ToLower(c.Geo.SubRegion) != strings.ToLower(country.Geo.SubRegion) {
continue
}
// Misc
//
if c.InternationalPrefix != "" && strings.ToLower(c.InternationalPrefix) != strings.ToLower(country.InternationalPrefix) {
continue
}
// Bordering countries
//
allMatch := false
if len(c.BorderingCountries()) > 0 {
for _, c1 := range c.BorderingCountries() {
match := false
for _, c2 := range country.BorderingCountries() {
match = c1.Alpha2 == c2.Alpha2
if match == true {
break
}
}
if match == true {
allMatch = true
} else {
allMatch = false
break
}
}
if allMatch == false {
continue
}
}
// Append if all matches
//
countries = append(countries, country)
}
return
}
// FindSubdivisionCountryByName finds the country of a given subdivision name
func (q *Query) FindSubdivisionCountryByName(subdivisionName string) (result Country, err error) {
for _, country := range q.Countries {
if _, ok := country.nameToSubdivision[strings.ToLower(subdivisionName)]; ok {
return country, nil
}
}
return Country{}, makeError("Invalid subdivision name", subdivisionName)
}