geonames 0.2.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
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