opencellid-client 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitgnore +3 -0
- data/.simplecov +3 -0
- data/Gemfile +4 -0
- data/License.txt +22 -0
- data/README.md +96 -0
- data/Rakefile +4 -0
- data/lib/opencellid.rb +7 -0
- data/lib/opencellid/bbox.rb +34 -0
- data/lib/opencellid/cell.rb +62 -0
- data/lib/opencellid/error.rb +30 -0
- data/lib/opencellid/measure.rb +42 -0
- data/lib/opencellid/opencellid.rb +108 -0
- data/lib/opencellid/response.rb +63 -0
- data/lib/opencellid/utils.rb +25 -0
- data/lib/opencellid/version.rb +5 -0
- data/opencellid-client.gemspec +27 -0
- data/spec/lib/bbox_spec.rb +47 -0
- data/spec/lib/cell_spec.rb +138 -0
- data/spec/lib/data/cell_not_found.xml +4 -0
- data/spec/lib/data/cell_with_measures.xml +10 -0
- data/spec/lib/data/measure_added.xml +4 -0
- data/spec/lib/data/measure_list.xml +5 -0
- data/spec/lib/data/one_cell.xml +4 -0
- data/spec/lib/error_spec.rb +58 -0
- data/spec/lib/measure_spec.rb +73 -0
- data/spec/lib/opencellid_spec.rb +242 -0
- data/spec/lib/response_spec.rb +134 -0
- data/spec/lib/utils_spec.rb +98 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/spec_utils.rb +3 -0
- metadata +122 -0
data/.gitgnore
ADDED
data/.simplecov
ADDED
data/Gemfile
ADDED
data/License.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2012 Marco Sandrini
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
OpenCellID Client Library
|
2
|
+
=========================
|
3
|
+
|
4
|
+
`opencellid-client` is a ruby gem that aims at simplifying the usage of the APIs provided by opencellid.org to transform cell IDs into coordinates.
|
5
|
+
|
6
|
+
Installing
|
7
|
+
----------
|
8
|
+
|
9
|
+
Simply install the gem to your system
|
10
|
+
|
11
|
+
`gem install opencellid-client`
|
12
|
+
|
13
|
+
or if you are using Bundler add it to your gemspec file and run `bundle install`.
|
14
|
+
|
15
|
+
Usage
|
16
|
+
-----
|
17
|
+
|
18
|
+
First of all `require 'opencellid'` in your application.
|
19
|
+
|
20
|
+
Read functionality (i.e. methods that only query the database generally do not require an API key), write methods instead
|
21
|
+
do require an API key, so if you do not have one, head to the [OpenCellID website](http://www.opencellid.org/) and get one
|
22
|
+
for yourself.
|
23
|
+
|
24
|
+
Initialize the main Opencellid object with the API key (if any)
|
25
|
+
|
26
|
+
`opencellid = Opencellid::Opencellid.new`
|
27
|
+
|
28
|
+
or
|
29
|
+
|
30
|
+
`opencellid = Opencellid::Opencellid.new my_key`
|
31
|
+
|
32
|
+
and then invoke methods on the object just created. The return values of all methods is of type `Response`. invoking method
|
33
|
+
`ok?` verifies that the response is a successful one. If the response is successful, method-dependent results can be
|
34
|
+
got from the response, otherwise an error object can be extracted from the response and the use its `code` and `info`
|
35
|
+
methods to obtain the error code and human readable description.
|
36
|
+
|
37
|
+
Querying Cells
|
38
|
+
==============
|
39
|
+
|
40
|
+
Cells can be queried using a combination of parameters: the cell id, the mnc (operator) and mcc (country) code or the local area
|
41
|
+
code lac. For a more detailed description of these parameters please refere to the OpenCellID site.
|
42
|
+
|
43
|
+
Parameters are first set into a `Cell` object and then the object is passed to the method. E.g. to query for
|
44
|
+
the position of the cell with id 123000, mnc 5 and mcc 244
|
45
|
+
|
46
|
+
`target_cell = Cell.new(123000,244,5,nil
|
47
|
+
response = opencellid.get_cell(target_cell)
|
48
|
+
result_cell = response.cells[0]`
|
49
|
+
|
50
|
+
similarly to query for the measures related to the same cell
|
51
|
+
|
52
|
+
`target_cell = Cell.new(123000,244,5,nil
|
53
|
+
response = opencellid.get_cell_measures(target_cell)
|
54
|
+
result_cell = response.cells[0]
|
55
|
+
measures = result.cell.measures`
|
56
|
+
|
57
|
+
Finally to query for cells in a bounding box, a BBox object must provided. In addition to that, the set of results can
|
58
|
+
be limited by number, by mcc or by mnc code by specifying respectively the `:limit`,`:mcc` and `:mnc` keys of the options
|
59
|
+
hash.
|
60
|
+
|
61
|
+
To get the first 10 cells belonging to operator whose mnc code is 5 within the bounding box the code is the following
|
62
|
+
|
63
|
+
`bbox = BBox.new(30.0,40.0,60.0,70.0)
|
64
|
+
response = opencellid.get_cells_in_area(bbox, :limit => 10, :mnc => 5)
|
65
|
+
cells = response.cells`
|
66
|
+
|
67
|
+
Adding and Deleting Measures
|
68
|
+
============================
|
69
|
+
|
70
|
+
Adding, deleting and listing "own" measures (i.e. measures inserted by the same user) require that an API key is
|
71
|
+
made available to the library at initialization time.
|
72
|
+
|
73
|
+
Measure can be added by providing a cell object identifying the cell to which the measure refers to, and a measure containing
|
74
|
+
the actual measure details.
|
75
|
+
|
76
|
+
`target_cell = Cell.new(123000,244,5,9000)
|
77
|
+
measure = Measure.new(30.0,60.0,Time.now)
|
78
|
+
measure.signal = 15
|
79
|
+
response = opencellid.add_measure(target_cell,measure)`
|
80
|
+
|
81
|
+
The response object will contain the cell id and the measure id. Using the measure id it is later on possible to delete
|
82
|
+
the measure, if so desired
|
83
|
+
|
84
|
+
`response = opencellid.delete_measure(measure_id)
|
85
|
+
|
86
|
+
Measure Ids can also be obtained by listing all the measures belonging to the user whose API key has been provided to the
|
87
|
+
library
|
88
|
+
|
89
|
+
`response = opencellid.list_measures
|
90
|
+
measures = response.measures`
|
91
|
+
|
92
|
+
|
93
|
+
Bulk addition of measures
|
94
|
+
=========================
|
95
|
+
|
96
|
+
Bulk addition of measure by uploading a CSV formatted file to the OpenCellID server is not yet supported by this library.
|
data/Rakefile
ADDED
data/lib/opencellid.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Opencellid
|
2
|
+
|
3
|
+
# A class to simplify the setting the coordinates of a bounding box while calling methods on the
|
4
|
+
# OpenCellId API
|
5
|
+
class BBox
|
6
|
+
|
7
|
+
attr_accessor :latmin, :lonmin, :latmax, :lonmax
|
8
|
+
|
9
|
+
# @param latmin [Float] latmin the latitude of the SW corner of the box
|
10
|
+
# @param lonmin [Float] lonmin the longitude of the SW corner of the box
|
11
|
+
# @param latmax [Float] latmax the latitude of the NE corner of the box
|
12
|
+
# @param lonmax [Float] lonmax the longitude of the NE corner of the box
|
13
|
+
def initialize(latmin, lonmin, latmax, lonmax)
|
14
|
+
raise ArgumentError, "latmin must not be nil" unless latmin
|
15
|
+
raise ArgumentError, "lonmin must not be nil" unless lonmin
|
16
|
+
raise ArgumentError, "latmax must not be nil" unless latmax
|
17
|
+
raise ArgumentError, "lonmax must not be nil" unless lonmax
|
18
|
+
@latmin = latmin
|
19
|
+
@lonmin = lonmin
|
20
|
+
@latmax = latmax
|
21
|
+
@lonmax = lonmax
|
22
|
+
end
|
23
|
+
|
24
|
+
# Transforms the coordinates of this bounding box in a format suitable for the OpenCellId API
|
25
|
+
# @return [String] the coordinates of the bbox is a format compatible with the OpenCellId API
|
26
|
+
def to_s
|
27
|
+
"#{latmin},#{lonmin},#{latmax},#{lonmax}"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require_relative 'utils'
|
3
|
+
|
4
|
+
module Opencellid
|
5
|
+
|
6
|
+
# Models a Cell object, both as an output from the server and as an input to queries. When using an object of this type
|
7
|
+
# to specify query parameters, the class attributes that should be used as filters should be set to the desired values,
|
8
|
+
# while the other attributes should be set to nil
|
9
|
+
class Cell
|
10
|
+
|
11
|
+
attr_accessor :lat, :lon, :id, :mnc, :mcc, :lac, :range, :measures, :no_of_samples
|
12
|
+
|
13
|
+
# @param id [Integer] the id of the cell
|
14
|
+
# @param mnc [Integer] the mnc code of the cell
|
15
|
+
# @param mcc [Integer] the mcc code of the cell
|
16
|
+
# @param lac [Integer] the lac code of the cell
|
17
|
+
def initialize(id, mnc, mcc, lac)
|
18
|
+
@id = id
|
19
|
+
@mnc = mnc
|
20
|
+
@mcc = mcc
|
21
|
+
@lac = lac
|
22
|
+
@measures = []
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# @param element [REXML::Element] the XML element containing the representation of the Cell element
|
27
|
+
# @return [Cell] the Cell object obtained by parsing the XML
|
28
|
+
def self.from_element(element)
|
29
|
+
return nil unless element
|
30
|
+
raise ArgumentError, "element must be of type XEXML::Element" unless element.is_a? REXML::Element
|
31
|
+
raise ArgumentError, "element must be a <cell>" unless element.name == "cell"
|
32
|
+
attrs = element.attributes
|
33
|
+
|
34
|
+
result = Cell.new(::Opencellid.to_i_or_nil(attrs['cellId']), ::Opencellid.to_i_or_nil(attrs['mnc']),
|
35
|
+
::Opencellid.to_i_or_nil(attrs['mcc']),::Opencellid.to_i_or_nil(attrs['lac']))
|
36
|
+
result.lat = ::Opencellid.to_f_or_nil(attrs['lat'])
|
37
|
+
result.lon = ::Opencellid.to_f_or_nil(attrs['lon'])
|
38
|
+
result.range = ::Opencellid.to_i_or_nil(attrs['range'])
|
39
|
+
result.no_of_samples= ::Opencellid.to_i_or_nil(attrs['nbSamples'])
|
40
|
+
element.elements.each('measure') { |e| result.add_measure Measure.from_element e}
|
41
|
+
result
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [bool] whether this cell contains measure objects
|
45
|
+
def has_measures?
|
46
|
+
@measures.count > 0
|
47
|
+
end
|
48
|
+
|
49
|
+
# @param measure [Measure] a measure object to be added to this cell. Note that adding the object to the cell
|
50
|
+
# does NOT result in an add_measure call being invoked on the Opencellid object
|
51
|
+
def add_measure(measure)
|
52
|
+
@measures << measure
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Hash] a hash object containing the non nil paramters which can be used in while querying for cells
|
56
|
+
def to_query_hash
|
57
|
+
{cellid: id, mnc: mnc, mcc: mcc, lac: lac}.delete_if {|k,v| v.nil?}
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require_relative 'utils'
|
3
|
+
|
4
|
+
module Opencellid
|
5
|
+
|
6
|
+
# Models an error object received from the server
|
7
|
+
class Error
|
8
|
+
|
9
|
+
attr_accessor :info, :code
|
10
|
+
|
11
|
+
# @param code [Integer] the code identifying this error
|
12
|
+
# @param info [String] a human readable explanation of the error
|
13
|
+
def initialize(code, info)
|
14
|
+
@info = info
|
15
|
+
@code = code
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param element [REXML::Element] an XML element containing the error
|
19
|
+
# @return [Error] the error object created by parsing the XML element
|
20
|
+
def self.from_element(element)
|
21
|
+
return nil unless element
|
22
|
+
raise ArgumentError, "element must be of type XEXML::Element" unless element.is_a? REXML::Element
|
23
|
+
raise ArgumentError, "element must be an <err>" unless element.name == "err"
|
24
|
+
attrs = element.attributes
|
25
|
+
return Error.new(::Opencellid.to_i_or_nil(attrs['code']),attrs['info'])
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require_relative 'utils'
|
2
|
+
|
3
|
+
module Opencellid
|
4
|
+
|
5
|
+
# A class which models the measurement of a cell position
|
6
|
+
class Measure
|
7
|
+
|
8
|
+
# The format used by the OpenCellId API to pass date/time information
|
9
|
+
DATE_FORMAT = "%a %b %d %H:%M:%S %z %Y"
|
10
|
+
|
11
|
+
attr_accessor :lat, :lon, :taken_by, :taken_on, :id, :signal
|
12
|
+
|
13
|
+
# @param lat [Float] the latitude of the position measured
|
14
|
+
# @param lon [Float] the longitude of the position measured
|
15
|
+
# @param taken_on [DateTime] the date/time information at which the measurement was taken
|
16
|
+
def initialize(lat, lon, taken_on = nil)
|
17
|
+
@lat = lat
|
18
|
+
@lon = lon
|
19
|
+
@taken_on = taken_on
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# @param element [REXML::Element] the XML element containing the representation of the measurement
|
24
|
+
# @return [Measure] the Measure object obtained by parsing the XML
|
25
|
+
def self.from_element(element)
|
26
|
+
return nil unless element
|
27
|
+
raise ArgumentError, "element must be of type XEXML::Element" unless element.is_a? REXML::Element
|
28
|
+
raise ArgumentError, "element must be a <measure>" unless element.name == "measure"
|
29
|
+
attrs = element.attributes
|
30
|
+
date = attrs['takenOn']
|
31
|
+
date ||= attrs['measured_at']
|
32
|
+
measure = Measure.new(::Opencellid::to_f_or_nil(attrs['lat']),::Opencellid::to_f_or_nil(attrs['lon']),
|
33
|
+
::Opencellid::to_datetime_or_nil(date,DATE_FORMAT))
|
34
|
+
measure.id = ::Opencellid.to_i_or_nil(attrs['id'])
|
35
|
+
measure.taken_by= attrs['takenBy']
|
36
|
+
measure.signal = ::Opencellid.to_i_or_nil(attrs['signal'])
|
37
|
+
measure
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'net/http'
|
3
|
+
require_relative 'cell'
|
4
|
+
require_relative 'response'
|
5
|
+
require_relative 'measure'
|
6
|
+
require_relative 'bbox'
|
7
|
+
require_relative 'error'
|
8
|
+
|
9
|
+
module Opencellid
|
10
|
+
|
11
|
+
# The main entry for this library. Each method maps to the corresponding method of the
|
12
|
+
# OpenCellId API defined at {http:://www.opencellid.org/api}.
|
13
|
+
class Opencellid
|
14
|
+
|
15
|
+
DEFAULT_URI = "http://www.opencellid.org"
|
16
|
+
GET_IN_AREA_ALLOWED_PARAMS = [:limit, :mcc, :mnc]
|
17
|
+
attr_reader :key
|
18
|
+
|
19
|
+
# @param key [String] the API key used for "write" operations. Defaults to nil
|
20
|
+
def initialize(key=nil)
|
21
|
+
@key = key
|
22
|
+
end
|
23
|
+
|
24
|
+
# Retrieves the cell information based on the parameters specified inside the `cell` object
|
25
|
+
# @param[Cell] cell the object containing the parameters to be used in searching the database
|
26
|
+
# the result received from the server
|
27
|
+
def get_cell(cell)
|
28
|
+
query_cell_info "/cell/get", cell
|
29
|
+
end
|
30
|
+
|
31
|
+
# Retrieves the cell information and the measures used to calculate its position based on the parameters
|
32
|
+
# specified in the cell object
|
33
|
+
# @param[Cell] cell the object containing the parameters used to search the cell database
|
34
|
+
# @return[Response] the result received from the server
|
35
|
+
def get_cell_measures(cell)
|
36
|
+
query_cell_info "/cell/getMeasures", cell
|
37
|
+
end
|
38
|
+
|
39
|
+
# Retrieves all the cells located inside the bounding box and whose parameters match the ones specified in the options
|
40
|
+
# @param bbox [BBox] the bounding box limiting the cell search
|
41
|
+
# @param options [Hash] a hash containing further filtering criteria. Valid criteria are `:limit` (limiting the amount
|
42
|
+
# of results), `:mnc` specifying the mnc value of the desired cells and `:mcc` specifying the mcc value of the desired cells
|
43
|
+
# @return [Response] the result received from the server
|
44
|
+
def get_cells_in_area(bbox, options = {})
|
45
|
+
raise ArgumentError, "options must be a Hash" unless options.is_a? Hash
|
46
|
+
raise ArgumentError, "bbox must be of type BBox" unless bbox.is_a? BBox
|
47
|
+
params = {bbox: bbox.to_s, fmt: 'xml'}
|
48
|
+
params.merge!(options.reject { |key| !GET_IN_AREA_ALLOWED_PARAMS.include? key})
|
49
|
+
execute_request_and_parse_response "/cell/getInArea", params
|
50
|
+
end
|
51
|
+
|
52
|
+
# Adds a measure (specified by the measure object) to a given cell (specified by the cell object). In case of
|
53
|
+
# success the response object will also contain the cell_id and the measure_id of the newly created measure.
|
54
|
+
# Although the library does not check this, a valid APIkey must have been specified while initializing the
|
55
|
+
# this object
|
56
|
+
# @param cell [Object] the cell to which this measure must be added to
|
57
|
+
# @param measure [Object] the measure to be added
|
58
|
+
# @return [Response] the result obtained from the server
|
59
|
+
def add_measure(cell, measure)
|
60
|
+
raise ArgumentError, "cell must be of type Cell" unless cell.is_a? Cell
|
61
|
+
raise ArgumentError, "measure must be of type Measure" unless measure.is_a? Measure
|
62
|
+
params = cell.to_query_hash
|
63
|
+
params[:lat] = measure.lat
|
64
|
+
params[:lon] = measure.lon
|
65
|
+
params[:signal] = measure.signal if measure.signal
|
66
|
+
params[:measured_at] = measure.taken_on if measure.taken_on
|
67
|
+
execute_request_and_parse_response "/measure/add", params
|
68
|
+
end
|
69
|
+
|
70
|
+
# List the measures added with a given API key.
|
71
|
+
# @return [Response] the result received from the server
|
72
|
+
def list_measures
|
73
|
+
execute_request_and_parse_response "/measure/list"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Deletes a measure previously added with the same API key.
|
77
|
+
# @param measure_id [Integer] the id of the measure to be deleted (obtained in the response from `add_measure` or via `list_measures`)
|
78
|
+
# @return [Response] the result received from the server
|
79
|
+
def delete_measure(measure_id)
|
80
|
+
raise ArgumentError,"measure_id cannot be nil" unless measure_id
|
81
|
+
execute_request_and_parse_response "/measure/delete", {id: measure_id}
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
def query_cell_info(path, cell)
|
87
|
+
raise ArgumentError, "cell must be a Cell" unless cell.is_a? Cell
|
88
|
+
params = cell.to_query_hash
|
89
|
+
execute_request_and_parse_response path, params
|
90
|
+
end
|
91
|
+
|
92
|
+
def execute_request_and_parse_response(path, params = {})
|
93
|
+
params[:key] = @key if @key
|
94
|
+
uri = URI(DEFAULT_URI + path)
|
95
|
+
uri.query = URI.encode_www_form params if params.count > 0
|
96
|
+
res = Net::HTTP.get_response uri
|
97
|
+
if res.is_a? Net::HTTPOK
|
98
|
+
Response.from_xml res.body
|
99
|
+
else
|
100
|
+
response = Response.new false
|
101
|
+
response.error = ::Opencellid::Error.new(0, "Http Request failed with code #{res.code}")
|
102
|
+
response
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require_relative 'error'
|
3
|
+
require_relative 'utils'
|
4
|
+
|
5
|
+
module Opencellid
|
6
|
+
|
7
|
+
# The class modelling all possible answers from the server. Also when the server is not reachable or encounters an
|
8
|
+
# error (e.g. a 500 response), the library will return a Response object, so that clients will not need to handle
|
9
|
+
# application errors and HTTP errors separately
|
10
|
+
class Response
|
11
|
+
|
12
|
+
attr_accessor :cells, :error, :cell_id, :measure_id, :result, :measures
|
13
|
+
|
14
|
+
|
15
|
+
# @param ok [bool] whether the response is an ok response or a failure one
|
16
|
+
def initialize(ok)
|
17
|
+
@ok = ok
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [bool] `true` if the response is a successful response
|
21
|
+
def ok?
|
22
|
+
@ok
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [bool] `true` if the response is a failure response
|
26
|
+
def failed?
|
27
|
+
not @ok
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param string [String] a string containing the XML response received from the server
|
31
|
+
# @return [Response] the Response object obtained by parsing the XML file
|
32
|
+
def self.from_xml(string)
|
33
|
+
doc = REXML::Document.new string
|
34
|
+
raise RuntimeError, "Could not parse server response" unless doc and doc.root
|
35
|
+
case doc.root.name
|
36
|
+
when "rsp"
|
37
|
+
response = Response.new(doc.root.attributes['stat'] == "ok")
|
38
|
+
response.measures = []
|
39
|
+
if response.ok?
|
40
|
+
response.cells= doc.root.elements.collect('cell') {|e| Cell.from_element e }
|
41
|
+
response.cell_id = ::Opencellid.to_i_or_nil(doc.root.attributes['cellid'])
|
42
|
+
response.measure_id = ::Opencellid.to_i_or_nil(doc.root.attributes['id'])
|
43
|
+
res = doc.root.elements['res']
|
44
|
+
response.result = res.text if res
|
45
|
+
else
|
46
|
+
response.cells = []
|
47
|
+
response.error = Error.from_element doc.root.elements['err']
|
48
|
+
end
|
49
|
+
when "measures"
|
50
|
+
response = Response.new true
|
51
|
+
response.measures = doc.root.elements.collect('measure') {|e| Measure.from_element e }
|
52
|
+
response.cells = []
|
53
|
+
else
|
54
|
+
raise RuntimeError, "The server response does not contain a valid response"
|
55
|
+
end
|
56
|
+
response
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
end
|