opencellid-client 0.1.0
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.
- 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
|