geonames 0.2.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +7 -0
  4. data/README.markdown +82 -0
  5. data/Rakefile +13 -0
  6. data/init.rb +1 -0
  7. data/lib/geonames.rb +38 -22
  8. data/lib/geonames/bounding_box.rb +12 -0
  9. data/lib/{country_subdivision.rb → geonames/config.rb} +26 -13
  10. data/lib/geonames/country_info.rb +18 -0
  11. data/lib/{Rakefile.rb → geonames/country_subdivision.rb} +11 -6
  12. data/lib/geonames/intersection.rb +28 -0
  13. data/lib/{toponym_search_result.rb → geonames/postal_code.rb} +10 -16
  14. data/lib/geonames/postal_code_search_criteria.rb +50 -0
  15. data/lib/{timezone.rb → geonames/timezone.rb} +10 -11
  16. data/lib/geonames/toponym.rb +29 -0
  17. data/lib/geonames/toponym_search_criteria.rb +34 -0
  18. data/lib/{address.rb → geonames/toponym_search_result.rb} +10 -7
  19. data/lib/geonames/version.rb +3 -0
  20. data/lib/geonames/web_service.rb +467 -0
  21. data/lib/{wikipedia_article.rb → geonames/wikipedia_article.rb} +5 -20
  22. data/ruby-geonames.gemspec +24 -0
  23. data/spec/fixtures/country_info/thailand.xml.http +29 -0
  24. data/spec/fixtures/country_subdivision/ontario.xml.http +20 -0
  25. data/spec/fixtures/countrycode/canada.xml.http +16 -0
  26. data/spec/fixtures/find_nearby/marchtrenk.xml.http +37 -0
  27. data/spec/fixtures/find_nearby/wilkinson.xml.http +23 -0
  28. data/spec/fixtures/find_nearby_place_name/oshawa.xml.http +23 -0
  29. data/spec/fixtures/find_nearby_postal_codes/oshawa.xml.http +81 -0
  30. data/spec/fixtures/find_nearby_wikipedia/general_motors_centre.xml.http +81 -0
  31. data/spec/fixtures/find_nearest_intersection/park_ave_and_e_51st_st.xml.http +24 -0
  32. data/spec/fixtures/hierarchy/zurich.xml.http +87 -0
  33. data/spec/fixtures/postal_code_search/lat_lng.xml.http +81 -0
  34. data/spec/fixtures/postal_code_search/oshawa.xml.http +77 -0
  35. data/spec/fixtures/search/austria.xml.http +146 -0
  36. data/spec/fixtures/search/marchtrenk.xml.http +93 -0
  37. data/spec/fixtures/search/upper_austria.xml.http +48 -0
  38. data/spec/fixtures/timezone/america_toronto.xml.http +24 -0
  39. data/spec/fixtures/wikipedia_bounding_box/wyoming.xml.http +154 -0
  40. data/spec/geonames/postal_code_search_criteria_spec.rb +31 -0
  41. data/spec/geonames/web_service/country_code_spec.rb +24 -0
  42. data/spec/geonames/web_service/country_info_spec.rb +42 -0
  43. data/spec/geonames/web_service/country_subdivision_spec.rb +24 -0
  44. data/spec/geonames/web_service/find_bounding_box_wikipedia_spec.rb +28 -0
  45. data/spec/geonames/web_service/find_nearby_place_name_spec.rb +24 -0
  46. data/spec/geonames/web_service/find_nearby_postal_codes_spec.rb +29 -0
  47. data/spec/geonames/web_service/find_nearby_spec.rb +41 -0
  48. data/spec/geonames/web_service/find_nearby_wikipedia_spec.rb +26 -0
  49. data/spec/geonames/web_service/find_nearest_intersection_spec.rb +18 -0
  50. data/spec/geonames/web_service/hierarchy_spec.rb +23 -0
  51. data/spec/geonames/web_service/postal_code_search_spec.rb +49 -0
  52. data/spec/geonames/web_service/search_spec.rb +54 -0
  53. data/spec/geonames/web_service/timezone_spec.rb +22 -0
  54. data/spec/geonames/web_service_spec.rb +13 -0
  55. data/spec/spec_helper.rb +13 -0
  56. data/spec/support/fakeweb.rb +9 -0
  57. metadata +152 -61
  58. data/README +0 -0
  59. data/geonames-0.2.2.gem +0 -0
  60. data/geonames.gemspec +0 -18
  61. data/lib/intersection.rb +0 -42
  62. data/lib/main.rb +0 -63
  63. data/lib/postal_code.rb +0 -40
  64. data/lib/postal_code_search_criteria.rb +0 -84
  65. data/lib/toponym.rb +0 -45
  66. data/lib/toponym_search_criteria.rb +0 -44
  67. data/lib/web_service.rb +0 -493
  68. data/nbproject/private/private.properties +0 -0
  69. data/nbproject/private/private.xml +0 -4
  70. data/nbproject/project.properties +0 -3
  71. data/nbproject/project.xml +0 -15
@@ -0,0 +1,29 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ # Contributions by Chris Griego
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+ #
18
+ #=============================================================================
19
+
20
+ module Geonames
21
+ class Toponym
22
+ attr_accessor :geoname_id, :name, :alternate_names, :country_code,
23
+ :country_name, :population, :elevation, :feature_class,
24
+ :feature_class_name, :feature_code, :feature_code_name,
25
+ :latitude, :longitude, :distance,
26
+ :admin_code_1, :admin_code_2, :admin_name_1, :admin_name_2,
27
+ :timezone
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ # Contributions by Chris Griego
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+ #
18
+ #=============================================================================
19
+
20
+ module Geonames
21
+ class ToponymSearchCriteria
22
+ attr_accessor :q, :country_code, :name, :name_equals,
23
+ :name_starts_with, :tag, :language, :style,
24
+ :feature_class, :feature_codes, :admin_code_1,
25
+ :max_rows, :start_row, :is_name_required
26
+
27
+ def initialize(params={})
28
+ params.each do |attr, value|
29
+ self.public_send("#{attr}=", value)
30
+ end if params
31
+ end
32
+
33
+ end
34
+ end
@@ -1,12 +1,13 @@
1
1
  #=============================================================================
2
2
  #
3
- # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ # Contributions by Chris Griego
4
5
  #
5
6
  # Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
7
  # use this file except in compliance with the License. You may obtain a copy of
7
- # the License at
8
+ # the License at
8
9
  #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
+ # http://www.apache.org/licenses/LICENSE-2.0
10
11
  #
11
12
  # Unless required by applicable law or agreed to in writing, software
12
13
  # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
@@ -17,9 +18,11 @@
17
18
  #=============================================================================
18
19
 
19
20
  module Geonames
20
- class Address
21
-
21
+ class ToponymSearchResult
22
+ attr_accessor :total_results_count, :toponyms
23
+
24
+ def initialize
25
+ @toponyms = []
26
+ end
22
27
  end
23
28
  end
24
-
25
-
@@ -0,0 +1,3 @@
1
+ module Geonames
2
+ VERSION = "0.3.3"
3
+ end
@@ -0,0 +1,467 @@
1
+ #=============================================================================
2
+ #
3
+ # Copyright 2007 Adam Wisniewski <adamw@tbcn.ca>
4
+ # Contributions by Andrew Turner, High Earth Orbit
5
+ # Contributions by Chris Griego
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not
8
+ # use this file except in compliance with the License. You may obtain a copy of
9
+ # the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
+ # License for the specific language governing permissions and limitations under
17
+ # the License.
18
+ #
19
+ #=============================================================================
20
+
21
+ require 'cgi'
22
+ require 'geonames'
23
+ require 'net/http'
24
+ require 'rexml/document'
25
+
26
+ module Geonames
27
+ module WebService
28
+ module_function
29
+
30
+ def get_element_child_text(element, child)
31
+ element.elements[child][0].to_s unless element.elements[child].nil?
32
+ end
33
+
34
+ def get_element_child_float(element, child)
35
+ element.elements[child][0].to_s.to_f unless element.elements[child].nil?
36
+ end
37
+
38
+ def get_element_child_int(element, child)
39
+ element.elements[child][0].to_s.to_i unless element.elements[child].nil?
40
+ end
41
+
42
+ def get_element_child_alternates(element, child)
43
+ alternates = {}
44
+ element.each_element_with_attribute('lang',nil,0,child) { |e| alternates[e.attribute('lang').value] = e.text }
45
+ alternates
46
+ end
47
+
48
+ def element_to_postal_code(element)
49
+ postal_code = PostalCode.new
50
+
51
+ postal_code.admin_code_1 = get_element_child_text(element, 'adminCode1')
52
+ postal_code.admin_code_2 = get_element_child_text(element, 'adminCode2')
53
+ postal_code.admin_name_1 = get_element_child_text(element, 'adminName1')
54
+ postal_code.admin_name_2 = get_element_child_text(element, 'adminName2')
55
+ postal_code.country_code = get_element_child_text(element, 'countryCode')
56
+ postal_code.distance = get_element_child_float(element, 'distance')
57
+ postal_code.longitude = get_element_child_float(element, 'lng')
58
+ postal_code.latitude = get_element_child_float(element, 'lat')
59
+ postal_code.place_name = get_element_child_text(element, 'name')
60
+ postal_code.postal_code = get_element_child_text(element, 'postalcode')
61
+
62
+ postal_code
63
+ end
64
+
65
+ def element_to_wikipedia_article(element)
66
+ article = WikipediaArticle.new
67
+
68
+ article.language = get_element_child_text(element, 'lang')
69
+ article.title = get_element_child_text(element, 'title')
70
+ article.summary = get_element_child_text(element, 'summary')
71
+ article.wikipedia_url = get_element_child_text(element, 'wikipediaUrl')
72
+ article.feature = get_element_child_text(element, 'feature')
73
+ article.population = get_element_child_text(element, 'population')
74
+ article.elevation = get_element_child_text(element, 'elevation')
75
+ article.latitude = get_element_child_float(element, 'lat')
76
+ article.longitude = get_element_child_float(element, 'lng')
77
+ article.thumbnail_img = get_element_child_text(element, 'thumbnailImg')
78
+ article.distance = get_element_child_float(element, 'distance')
79
+
80
+ article
81
+ end
82
+
83
+ def element_to_toponym(element)
84
+ toponym = Toponym.new
85
+
86
+ toponym.name = get_element_child_text(element, 'name')
87
+ toponym.alternate_names = get_element_child_alternates(element, 'alternateName')
88
+ toponym.latitude = get_element_child_float(element, 'lat')
89
+ toponym.longitude = get_element_child_float(element, 'lng')
90
+ toponym.geoname_id = get_element_child_text(element, 'geonameId')
91
+ toponym.country_code = get_element_child_text(element, 'countryCode')
92
+ toponym.country_name = get_element_child_text(element, 'countryName')
93
+ toponym.feature_class = get_element_child_text(element, 'fcl')
94
+ toponym.feature_code = get_element_child_text(element, 'fcode')
95
+ toponym.feature_class_name = get_element_child_text(element, 'fclName')
96
+ toponym.feature_code_name = get_element_child_text(element, 'fcodeName')
97
+ toponym.population = get_element_child_int(element, 'population')
98
+ toponym.elevation = get_element_child_text(element, 'elevation')
99
+ toponym.distance = get_element_child_float(element, 'distance')
100
+ toponym.admin_code_1 = get_element_child_text(element, 'adminCode1')
101
+ toponym.admin_code_2 = get_element_child_text(element, 'adminCode2')
102
+ toponym.admin_name_1 = get_element_child_text(element, 'adminName1')
103
+ toponym.admin_name_2 = get_element_child_text(element, 'adminName2')
104
+ toponym.timezone = get_element_child_text(element, 'timezone')
105
+
106
+ toponym
107
+ end
108
+
109
+ def element_to_intersection(element)
110
+ intersection = Intersection.new
111
+
112
+ intersection.street_1 = get_element_child_text(element, 'street1')
113
+ intersection.street_2 = get_element_child_text(element, 'street2')
114
+ intersection.admin_code_1 = get_element_child_text(element, 'adminCode1')
115
+ intersection.admin_code_1 = get_element_child_text(element, 'adminCode1')
116
+ intersection.admin_code_2 = get_element_child_text(element, 'adminCode2')
117
+ intersection.admin_name_1 = get_element_child_text(element, 'adminName1')
118
+ intersection.admin_name_2 = get_element_child_text(element, 'adminName2')
119
+ intersection.country_code = get_element_child_text(element, 'countryCode')
120
+ intersection.distance = get_element_child_float(element, 'distance')
121
+ intersection.longitude = get_element_child_float(element, 'lat')
122
+ intersection.latitude = get_element_child_float(element, 'lng')
123
+ intersection.place_name = get_element_child_text(element, 'name')
124
+ intersection.postal_code = get_element_child_text(element, 'postalcode')
125
+
126
+ intersection
127
+ end
128
+
129
+ def element_to_country_info(element)
130
+ country_info = Geonames::CountryInfo.new
131
+
132
+ country_info.country_code = get_element_child_text(element, 'countryCode')
133
+ country_info.country_name = get_element_child_text(element, 'countryName')
134
+ country_info.iso_numeric = get_element_child_int(element, 'isoNumeric')
135
+ country_info.iso_alpha_3 = get_element_child_text(element, 'isoAlpha3')
136
+ country_info.fips_code = get_element_child_text(element, 'fipsCode')
137
+ country_info.continent = get_element_child_text(element, 'continent')
138
+ country_info.capital = get_element_child_text(element, 'capital')
139
+ country_info.area_sq_km = get_element_child_float(element, 'areaInSqKm')
140
+ country_info.population = get_element_child_int(element, 'population')
141
+ country_info.currency_code = get_element_child_text(element, 'currencyCode')
142
+ country_info.languages = get_element_child_text(element, 'languages').split(",")
143
+ country_info.geoname_id = get_element_child_int(element, 'geonameId')
144
+
145
+ north = get_element_child_float(element, 'bBoxNorth')
146
+ south = get_element_child_float(element, 'bBoxSouth')
147
+ east = get_element_child_float(element, 'bBoxEast')
148
+ west = get_element_child_float(element, 'bBoxWest')
149
+
150
+ country_info.set_bounding_box(north, south, east, west)
151
+
152
+ country_info
153
+ end
154
+
155
+ def postal_code_search(search_criteria, *args)
156
+ # postal codes to reutrn
157
+ postal_codes = []
158
+
159
+ url = "/postalCodeSearch?a=a"
160
+ url << search_criteria.to_query_params_string
161
+
162
+ res = make_request(url, args)
163
+
164
+ doc = REXML::Document.new res.body
165
+
166
+ doc.elements.each("geonames/code") do |element|
167
+ postal_codes << element_to_postal_code(element)
168
+ end
169
+
170
+ postal_codes
171
+ end
172
+
173
+ def find_nearby_postal_codes(search_criteria, *args)
174
+ # postal codes to reutrn
175
+ postal_codes = []
176
+
177
+ url = "/findNearbyPostalCodes?a=a"
178
+ url << search_criteria.to_query_params_string
179
+
180
+ res = make_request(url, args)
181
+
182
+ doc = REXML::Document.new res.body
183
+
184
+ doc.elements.each("geonames/code") do |element|
185
+ postal_codes << element_to_postal_code(element)
186
+ end
187
+
188
+ postal_codes
189
+ end
190
+
191
+ def find_toponym(action, lat, long, query_options, args)
192
+ places = []
193
+
194
+ url = "/#{action}"
195
+
196
+ url << "?lat=" + lat.to_s
197
+ url << "&lng=" + long.to_s
198
+ query_options.each { |k,v| url << "&#{k}=#{v}" }
199
+
200
+ res = make_request(url, args)
201
+
202
+ doc = REXML::Document.new res.body
203
+
204
+ doc.elements.each("geonames/geoname") do |element|
205
+ places << element_to_toponym(element)
206
+ end
207
+
208
+ places
209
+ end
210
+
211
+ def find_nearby_place_name(lat, long, query_options = {} , *args)
212
+ find_toponym("findNearbyPlaceName", lat, long, query_options, args)
213
+ end
214
+
215
+ def find_nearby(lat, long, query_options = {}, *args)
216
+ find_toponym("findNearby", lat, long, query_options, args)
217
+ end
218
+
219
+ def find_nearest_intersection(lat, long, *args)
220
+ url = "/findNearestIntersection?a=a"
221
+
222
+ url << "&lat=" + lat.to_s
223
+ url << "&lng=" + long.to_s
224
+
225
+ res = make_request(url, args)
226
+
227
+ doc = REXML::Document.new res.body
228
+
229
+ intersection = []
230
+
231
+ doc.elements.each("geonames/intersection") do |element|
232
+ intersection = element_to_intersection(element)
233
+ end
234
+
235
+ intersection
236
+ end
237
+
238
+ def hierarchy(geonameId, *args)
239
+ url = "/hierarchy?geonameId=#{geonameId.to_i}"
240
+ res = make_request(url, args)
241
+ doc = REXML::Document.new res.body
242
+ doc.elements.collect("geonames/geoname") do |element|
243
+ element_to_toponym(element)
244
+ end
245
+ end
246
+
247
+ def timezone(lat, long, *args)
248
+ res = make_request("/timezone?lat=#{lat.to_s}&lng=#{long.to_s}", args)
249
+ doc = REXML::Document.new res.body
250
+ timezone = Timezone.new
251
+
252
+ doc.elements.each("geonames/timezone") do |element|
253
+ timezone.timezone_id = get_element_child_text(element, 'timezoneId')
254
+ timezone.gmt_offset = get_element_child_float(element, 'gmtOffset')
255
+ timezone.dst_offset = get_element_child_float(element, 'dstOffset')
256
+ timezone.raw_offset = get_element_child_float(element, 'rawOffset')
257
+ end
258
+
259
+ timezone
260
+ end
261
+
262
+ def make_request(path_and_query, *args)
263
+ url = Geonames.base_url + path_and_query
264
+ url += "&username=#{Geonames.username}" if Geonames.username
265
+ url += "&lang=#{Geonames.lang}"
266
+ url += "&token=#{Geonames.token}" if Geonames.token
267
+
268
+ options = { :open_timeout => 60, :read_timeout => 60 }
269
+ options.update(args.last.is_a?(Hash) ? args.pop : {})
270
+
271
+ uri = URI.parse(url)
272
+ req = Net::HTTP::Get.new("#{uri.path}?#{uri.query}", 'User-Agent' => USER_AGENT)
273
+
274
+ Net::HTTP.start(uri.host, uri.port) do |http|
275
+ http.read_timeout = options[:read_timeout]
276
+ http.open_timeout = options[:open_timeout]
277
+ http.request(req)
278
+ end
279
+ end
280
+
281
+ def findNearbyWikipedia(hashes)
282
+ # here for backwards compatibility
283
+ find_nearby_wikipedia(hashes)
284
+ end
285
+
286
+ def find_nearby_wikipedia(hashes, *args)
287
+ articles = []
288
+
289
+ lat = hashes[:lat]
290
+ long = hashes[:long]
291
+ lang = hashes[:lang]
292
+ radius = hashes[:radius]
293
+ max_rows = hashes[:max_rows]
294
+ country = hashes[:country]
295
+ postalcode = hashes[:postalcode]
296
+ q = hashes[:q]
297
+
298
+ url = "/findNearbyWikipedia?a=a"
299
+
300
+ if !lat.nil? && !long.nil?
301
+ url << "&lat=" + lat.to_s
302
+ url << "&lng=" + long.to_s
303
+ url << "&radius=" + radius.to_s unless radius.nil?
304
+ url << "&max_rows=" + max_rows.to_s unless max_rows.nil?
305
+ elsif !q.nil?
306
+ url << "&q=" + q
307
+ url << "&radius=" + radius.to_s unless radius.nil?
308
+ url << "&max_rows=" + max_rows.to_s unless max_rows.nil?
309
+ end
310
+
311
+ res = make_request(url, args)
312
+
313
+ doc = REXML::Document.new res.body
314
+
315
+ doc.elements.each("geonames/entry") do |element|
316
+ articles << element_to_wikipedia_article(element)
317
+ end
318
+
319
+ articles
320
+ end
321
+
322
+ def findBoundingBoxWikipedia(hashes)
323
+ # here for backwards compatibility
324
+ find_bounding_box_wikipedia(hashes)
325
+ end
326
+
327
+ def find_bounding_box_wikipedia(hashes, *args)
328
+ articles = []
329
+
330
+ north = hashes[:north]
331
+ east = hashes[:east]
332
+ south = hashes[:south]
333
+ west = hashes[:west]
334
+ lang = hashes[:lang]
335
+ radius = hashes[:radius]
336
+ max_rows = hashes[:max_rows]
337
+ country = hashes[:country]
338
+ postalcode = hashes[:postalcode]
339
+ q = hashes[:q]
340
+
341
+ url = "/wikipediaBoundingBox?a=a"
342
+
343
+ url << "&north=" + north.to_s
344
+ url << "&east=" + east.to_s
345
+ url << "&south=" + south.to_s
346
+ url << "&west=" + west.to_s
347
+ url << "&radius=" + radius.to_s unless radius.nil?
348
+ url << "&max_rows=" + max_rows.to_s unless max_rows.nil?
349
+
350
+ res = make_request(url, args)
351
+
352
+ doc = REXML::Document.new res.body
353
+
354
+ doc.elements.each("geonames/entry") do |element|
355
+ articles << element_to_wikipedia_article(element)
356
+ end
357
+
358
+ articles
359
+ end
360
+
361
+ def country_subdivision(lat, long, radius=0, maxRows=1, *args)
362
+ country_subdivisions = []
363
+
364
+ # maxRows is only implemented in the xml version:
365
+ # http://groups.google.com/group/geonames/browse_thread/thread/f7f1bb2504ed216e
366
+ # Therefore 'type=xml' is added:
367
+ url = "/countrySubdivision?a=a&type=xml"
368
+
369
+ url << "&lat=" + lat.to_s
370
+ url << "&lng=" + long.to_s
371
+ url << "&maxRows=" + maxRows.to_s
372
+ url << "&radius=" + radius.to_s
373
+
374
+ res = make_request(url, args)
375
+
376
+ doc = REXML::Document.new res.body
377
+
378
+ doc.elements.each("geonames/countrySubdivision") do |element|
379
+ country_subdivision = CountrySubdivision.new
380
+
381
+ country_subdivision.country_code = get_element_child_text(element, 'countryCode')
382
+ country_subdivision.country_name = get_element_child_text(element, 'countryName')
383
+ country_subdivision.admin_code_1 = get_element_child_text(element, 'adminCode1')
384
+ country_subdivision.admin_name_1 = get_element_child_text(element, 'adminName1')
385
+ country_subdivision.code_fips = get_element_child_text(element, 'code[@type="FIPS10-4"]')
386
+ country_subdivision.code_iso = get_element_child_text(element, 'code[@type="ISO3166-2"]')
387
+
388
+ country_subdivisions << country_subdivision
389
+ end
390
+
391
+ country_subdivisions
392
+ end
393
+
394
+ def country_info(country_code=nil, *args)
395
+ url = "/countryInfo?a=a"
396
+ url += "&country=#{country_code.to_s}" unless country_code.nil?
397
+ res = make_request(url, args)
398
+
399
+ doc = REXML::Document.new res.body
400
+
401
+ countries = []
402
+
403
+ doc.elements.each("geonames/country") do |element|
404
+ countries << element_to_country_info(element)
405
+ end
406
+
407
+ countries.size > 1 ? countries : countries[0]
408
+ end
409
+
410
+ def country_code(lat, long, radius=0, maxRows=1, *args)
411
+ # maxRows is only implemented in the xml version:
412
+ # http://groups.google.com/group/geonames/browse_thread/thread/f7f1bb2504ed216e
413
+ # Therefore 'type=xml' is added:
414
+ url = "/countrycode?a=a&type=xml"
415
+
416
+ countries = []
417
+
418
+ url << "&lat=" + lat.to_s
419
+ url << "&lng=" + long.to_s
420
+ url << "&maxRows=" + maxRows.to_s
421
+ url << "&radius=" + radius.to_s
422
+
423
+ res = make_request(url, args)
424
+
425
+ doc = REXML::Document.new res.body
426
+
427
+ doc.elements.each("geonames/country") do |element|
428
+ countries << element_to_toponym(element)
429
+ end
430
+
431
+ countries
432
+ end
433
+
434
+ def search(search_criteria, *args)
435
+ #toponym search results to return
436
+ toponym_sr = ToponymSearchResult.new
437
+
438
+ url = "/search?a=a"
439
+ url << "&q=" + CGI.escape(search_criteria.q) unless search_criteria.q.nil?
440
+ url << "&name_equals=" + CGI.escape(search_criteria.name_equals) unless search_criteria.name_equals.nil?
441
+ url << "&name_startsWith=" + CGI.escape(search_criteria.name_starts_with) unless search_criteria.name_starts_with.nil?
442
+ url << "&name=" + CGI.escape(search_criteria.name) unless search_criteria.name.nil?
443
+ url << "&tag=" + CGI.escape(search_criteria.tag) unless search_criteria.tag.nil?
444
+ url << "&country=" + CGI.escape(search_criteria.country_code) unless search_criteria.country_code.nil?
445
+ url << "&adminCode1=" + CGI.escape(search_criteria.admin_code_1) unless search_criteria.admin_code_1.nil?
446
+ url << "&lang=" + CGI.escape(search_criteria.language) unless search_criteria.language.nil?
447
+ url << "&featureClass=" + CGI.escape(search_criteria.feature_class) unless search_criteria.feature_class.nil?
448
+ url << "&maxRows=" + CGI.escape(search_criteria.max_rows) unless search_criteria.max_rows.nil?
449
+ url << "&startRow=" + CGI.escape(search_criteria.start_row) unless search_criteria.start_row.nil?
450
+ url << "&style=" + CGI.escape(search_criteria.style) unless search_criteria.style.nil?
451
+ url << "&isNameRequired=" + CGI.escape(search_criteria.is_name_required) unless search_criteria.is_name_required.nil?
452
+ url << search_criteria.feature_codes.map {|fcode| "&fcode=" + CGI.escape(fcode) }.join unless search_criteria.feature_codes.nil?
453
+
454
+ res = make_request(url, args)
455
+
456
+ doc = REXML::Document.new res.body
457
+
458
+ toponym_sr.total_results_count = doc.elements["geonames/totalResultsCount"].text
459
+
460
+ doc.elements.each("geonames/geoname") do |element|
461
+ toponym_sr.toponyms << element_to_toponym(element)
462
+ end
463
+
464
+ toponym_sr
465
+ end
466
+ end
467
+ end