eaal 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/Manifest.txt +12 -9
- data/README.rdoc +5 -1
- data/Rakefile +26 -26
- data/lib/eaal.rb +45 -6
- data/lib/eaal/api.rb +77 -0
- data/lib/eaal/cache/base.rb +27 -0
- data/lib/eaal/cache/file.rb +62 -0
- data/lib/eaal/cache/memcached.rb +30 -0
- data/lib/eaal/exception.rb +40 -0
- data/lib/eaal/{eaal_result.rb → result.rb} +123 -123
- data/lib/eaal/{eaal_rowset.rb → rowset.rb} +69 -69
- data/test/fixtures/test/test/account/Characters/Request_.xml +10 -10
- data/test/fixtures/test/test/char/Killlog/Request_.xml +5 -5
- data/test/fixtures/test/test/char/Killlog/Request_characterID:12345.xml +18 -18
- data/test/fixtures/test/test/eve/AllianceList/Request_.xml +10523 -0
- data/test/test_eaal.rb +53 -42
- metadata +25 -12
- data/lib/eaal/eaal.rb +0 -114
- data/lib/eaal/eaal_cache.rb +0 -90
- data/lib/eaal/eaal_exception.rb +0 -42
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
History.txt
|
2
|
+
LICENSE.txt
|
2
3
|
Manifest.txt
|
3
4
|
README.rdoc
|
4
|
-
LICENSE.txt
|
5
5
|
Rakefile
|
6
6
|
lib/eaal.rb
|
7
|
-
lib/eaal/
|
8
|
-
lib/eaal/
|
9
|
-
lib/eaal/
|
10
|
-
lib/eaal/
|
11
|
-
lib/eaal/
|
7
|
+
lib/eaal/api.rb
|
8
|
+
lib/eaal/cache/base.rb
|
9
|
+
lib/eaal/cache/file.rb
|
10
|
+
lib/eaal/cache/memcached.rb
|
11
|
+
lib/eaal/exception.rb
|
12
|
+
lib/eaal/result.rb
|
13
|
+
lib/eaal/rowset.rb
|
12
14
|
script/console
|
13
15
|
script/destroy
|
14
16
|
script/generate
|
15
|
-
test/test_helper.rb
|
16
|
-
test/test_eaal.rb
|
17
17
|
test/fixtures/test/test/account/Characters/Request_.xml
|
18
|
-
test/fixtures/test/test/char/Killlog/Request_characterID:12345.xml
|
19
18
|
test/fixtures/test/test/char/Killlog/Request_.xml
|
19
|
+
test/fixtures/test/test/char/Killlog/Request_characterID:12345.xml
|
20
|
+
test/fixtures/test/test/eve/AllianceList/Request_.xml
|
21
|
+
test/test_eaal.rb
|
22
|
+
test/test_helper.rb
|
data/README.rdoc
CHANGED
@@ -88,6 +88,10 @@ the XML file will be load.
|
|
88
88
|
|
89
89
|
* sudo gem install eaal
|
90
90
|
|
91
|
+
== THANKS:
|
92
|
+
special thanks go to James "Ix_Forres" Harrison for his code cleanups and
|
93
|
+
his memcache cache handler
|
94
|
+
|
91
95
|
== LICENSE:
|
92
96
|
|
93
97
|
(The MIT License)
|
@@ -111,4 +115,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
111
115
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
112
116
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
113
117
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
114
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
118
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
CHANGED
@@ -1,27 +1,27 @@
|
|
1
|
-
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
2
|
-
require File.dirname(__FILE__) + '/lib/eaal.rb'
|
3
|
-
|
4
|
-
# Generate all the Rake tasks
|
5
|
-
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
6
|
-
$hoe = Hoe.new('eaal', EAAL.version) do |p|
|
7
|
-
p.developer('Peter Petermann', 'PeterPetermann@gmx.net')
|
8
|
-
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
9
|
-
p.rubyforge_name = p.name # TODO this is default value
|
10
|
-
p.extra_deps = [
|
11
|
-
['activesupport','>= 2.0.2'], ['hpricot', '>= 0.6']
|
12
|
-
]
|
13
|
-
p.extra_dev_deps = [
|
14
|
-
['newgem', ">= #{::Newgem::VERSION}"]
|
15
|
-
]
|
16
|
-
|
17
|
-
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
18
|
-
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
19
|
-
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
20
|
-
p.rsync_args = '-av --delete --ignore-errors'
|
21
|
-
end
|
22
|
-
|
23
|
-
require 'newgem/tasks' # load /tasks/*.rake
|
24
|
-
Dir['tasks/**/*.rake'].each { |t| load t }
|
25
|
-
|
26
|
-
# TODO - want other tests/tasks run by default? Add them to the list
|
1
|
+
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
2
|
+
require File.dirname(__FILE__) + '/lib/eaal.rb'
|
3
|
+
|
4
|
+
# Generate all the Rake tasks
|
5
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
6
|
+
$hoe = Hoe.new('eaal', EAAL.version) do |p|
|
7
|
+
p.developer('Peter Petermann', 'PeterPetermann@gmx.net')
|
8
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
9
|
+
p.rubyforge_name = p.name # TODO this is default value
|
10
|
+
p.extra_deps = [
|
11
|
+
['activesupport','>= 2.0.2'], ['hpricot', '>= 0.6'], ['memcache-client','>= 1.7.1']
|
12
|
+
]
|
13
|
+
p.extra_dev_deps = [
|
14
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
15
|
+
]
|
16
|
+
|
17
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
18
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
19
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
20
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'newgem/tasks' # load /tasks/*.rake
|
24
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
25
|
+
|
26
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
27
27
|
# task :default => [:spec, :features]
|
data/lib/eaal.rb
CHANGED
@@ -1,6 +1,45 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#
|
6
|
+
# TODO:
|
7
|
+
# - more documenation
|
8
|
+
# - write tests (i know, i know, i fail badly)
|
9
|
+
# - more error handling (im certain i missed a few possibles)
|
10
|
+
# - cleanup (you can see that this is my first project in ruby, cant you?)
|
11
|
+
#
|
12
|
+
# THANKS:
|
13
|
+
# thanks go to all people on irc.coldfront.net, channel #eve-dev
|
14
|
+
# special thanks go to lisa (checkout her eve api library, reve,
|
15
|
+
# much more mature then mine) for answering my endless questions
|
16
|
+
# about ruby stuff (and for one or two snippets i stole from reve)
|
17
|
+
#++
|
18
|
+
# Neat little hack to get around path issues on require
|
19
|
+
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
20
|
+
|
21
|
+
# External libs
|
22
|
+
require 'rubygems'
|
23
|
+
require 'hpricot'
|
24
|
+
require 'activesupport'
|
25
|
+
require 'net/http'
|
26
|
+
require 'uri'
|
27
|
+
require 'cgi'
|
28
|
+
# And now EAAL stuff
|
29
|
+
require 'eaal/cache/base'
|
30
|
+
require 'eaal/cache/file'
|
31
|
+
require 'eaal/cache/memcached'
|
32
|
+
require 'eaal/exception'
|
33
|
+
require 'eaal/result'
|
34
|
+
require 'eaal/rowset'
|
35
|
+
module EAAL
|
36
|
+
mattr_reader :version_string, :version
|
37
|
+
@@version = "0.1.5"
|
38
|
+
@@version_string = "EAAL" + EAAL.version # the version string, used as client name in http requests
|
39
|
+
|
40
|
+
mattr_accessor :api_base, :additional_request_parameters, :cache
|
41
|
+
@@api_base = "http://api.eve-online.com/" # the url used as basis for all requests, you might want to use gatecamper url or a personal proxy instead
|
42
|
+
@@additional_request_parameters = {} # hash, if :key => value pairs are added those will be added to each request
|
43
|
+
@@cache = EAAL::Cache::NoCache.new # caching object, see EAAL::Cache::FileCache for an Example
|
44
|
+
end
|
45
|
+
require 'eaal/api'
|
data/lib/eaal/api.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
# EAAL::API class
|
3
|
+
# Usage Example:
|
4
|
+
# api = EAAL::API.new("my userid", "my API key")
|
5
|
+
# result = api.Characters
|
6
|
+
# result.characters.each{|character|
|
7
|
+
# puts character.name
|
8
|
+
# }
|
9
|
+
class EAAL::API
|
10
|
+
attr_accessor :userid, :key, :scope
|
11
|
+
|
12
|
+
# constructor
|
13
|
+
# Expects:
|
14
|
+
# * userid (String | Integer) the users id
|
15
|
+
# * key (String) the apikey Full or Restricted
|
16
|
+
# * scope (String) defaults to account
|
17
|
+
def initialize(userid, key, scope="account")
|
18
|
+
self.userid = userid.to_s
|
19
|
+
self.key = key.to_s
|
20
|
+
self.scope = scope.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
# create an xml request according to the method called
|
24
|
+
# this is used to dynamicaly create api calls and
|
25
|
+
# should usually not be called directly
|
26
|
+
# * method (const)
|
27
|
+
# * args
|
28
|
+
def method_missing(method, *args)
|
29
|
+
scope = self.scope
|
30
|
+
args_hash = args.first
|
31
|
+
args_hash = {} unless args_hash
|
32
|
+
self.request_xml(scope, method.id2name, args_hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
# make a request to the api. will use cache if set.
|
36
|
+
# usually not called by the user directly
|
37
|
+
# * scope (String)
|
38
|
+
# * name (String)
|
39
|
+
# * opts (Hash)
|
40
|
+
def request_xml(scope, name, opts)
|
41
|
+
opts = EAAL.additional_request_parameters.merge(opts)
|
42
|
+
xml = EAAL.cache.load(self.userid, self.key, scope, name,opts)
|
43
|
+
if not xml
|
44
|
+
source = URI.parse(EAAL.api_base + scope + '/' + name +'.xml.aspx')
|
45
|
+
req_path = source.path + format_url_request(opts.merge({
|
46
|
+
:userid => self.userid,
|
47
|
+
:apikey => self.key}))
|
48
|
+
req = Net::HTTP::Get.new(req_path)
|
49
|
+
req[EAAL.version_string]
|
50
|
+
res = Net::HTTP.new(source.host, source.port).start {|http| http.request(req) } #one request for now
|
51
|
+
case res
|
52
|
+
when Net::HTTPOK
|
53
|
+
when Net::HTTPNotFound
|
54
|
+
raise EAAL::Exception::APINotFoundError.new("The requested API (#{scope} / #{name}) could not be found.")
|
55
|
+
else
|
56
|
+
raise EAAL::Exception::HTTPError.new("An HTTP Error occured, body: " + res.body)
|
57
|
+
end
|
58
|
+
EAAL.cache.save(self.userid, self.key, scope,name,opts, res.body)
|
59
|
+
xml = res.body
|
60
|
+
end
|
61
|
+
doc = Hpricot.XML(xml)
|
62
|
+
result = EAAL::Result.new(scope.capitalize + name, doc)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Turns a hash into ?var=baz&bam=boo
|
66
|
+
# stolen from Reve (thx lisa)
|
67
|
+
# * opts (Hash)
|
68
|
+
def format_url_request(opts)
|
69
|
+
req = "?"
|
70
|
+
opts.stringify_keys!
|
71
|
+
opts.keys.sort.each do |key|
|
72
|
+
req += "#{CGI.escape(key.to_s)}=#{CGI.escape(opts[key].to_s)}&" if opts[key]
|
73
|
+
end
|
74
|
+
req.chop # We are lazy and append a & to each pair even if it's the last one. FIXME: Don't do this.
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#++
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module EAAL
|
9
|
+
# The Classes in this module are objects that may be used as value
|
10
|
+
# of EAAL.cache.
|
11
|
+
# By default EAAL uses the NoCache class, where no caching is done.
|
12
|
+
# If a working cache class is used it will store the xml data
|
13
|
+
# and return it, so no requests to the API are done (as long as valid xml is available)
|
14
|
+
module Cache
|
15
|
+
# NoCache class
|
16
|
+
# dummy class which is used for non-caching behaviour (default)
|
17
|
+
class NoCache
|
18
|
+
def load(userid, apikey, scope, name, args)
|
19
|
+
false
|
20
|
+
end
|
21
|
+
def save(userid, apikey, scope, name, args, xml)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# EAAL::Cache::FileCache
|
2
|
+
# File based xml cache which respects the cachedUntil of the Eve API
|
3
|
+
# Usage:
|
4
|
+
# EAAL.cache = EAAL::Cache::FileCache.new
|
5
|
+
# Or
|
6
|
+
# EAAL.cache = EAAL::Cache::FileCache.new("/path/to/place/to/store/xml/data")
|
7
|
+
class EAAL::Cache::FileCache
|
8
|
+
attr_accessor :basepath
|
9
|
+
|
10
|
+
# constructor, takes one argument which is the path
|
11
|
+
# where files should be written
|
12
|
+
# * basepath (String) path which should be used to store cached data. defaults to $HOME/.eaal/cache/
|
13
|
+
def initialize(basepath = "#{ENV['HOME']}/.eaal/cache")
|
14
|
+
if basepath[(basepath.length) -1, basepath.length] != "/"
|
15
|
+
basepath += "/"
|
16
|
+
end
|
17
|
+
@basepath = basepath
|
18
|
+
end
|
19
|
+
|
20
|
+
# create the path/filename for the cache file
|
21
|
+
def filename(userid, apikey, scope, name, args)
|
22
|
+
ret =""
|
23
|
+
args.delete_if { |k,v| (v || "").to_s.length == 0 }
|
24
|
+
h = args.stringify_keys
|
25
|
+
ret += h.sort.flatten.collect{ |e| e.to_s }.join(':')
|
26
|
+
hash = ret.gsub(/:$/,'')
|
27
|
+
"#{@basepath}#{userid}/#{apikey}/#{scope}/#{name}/Request_#{hash}.xml"
|
28
|
+
end
|
29
|
+
|
30
|
+
# load xml if available, return false if not available, or cachedUntil ran out
|
31
|
+
def load(userid, apikey, scope, name, args)
|
32
|
+
filename = self.filename(userid, apikey,scope,name,args)
|
33
|
+
if not File.exist?(filename)
|
34
|
+
ret = false
|
35
|
+
else
|
36
|
+
xml = File.open(filename).read
|
37
|
+
if self.validate_cache(xml, name)
|
38
|
+
ret = xml
|
39
|
+
else
|
40
|
+
ret = false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
|
46
|
+
# validate cached datas cachedUntil
|
47
|
+
def validate_cache(xml, name)
|
48
|
+
doc = Hpricot.XML(xml)
|
49
|
+
if name == "WalletJournal"
|
50
|
+
Time.at((doc/"/eveapi/cachedUntil").inner_html.to_time.to_i + 3600) > Time.now
|
51
|
+
else
|
52
|
+
(doc/"/eveapi/cachedUntil").inner_html.to_time > Time.now
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# save xml data to file
|
57
|
+
def save(userid, apikey, scope, name, args, xml)
|
58
|
+
filename = self.filename(userid, apikey,scope,name,args)
|
59
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
60
|
+
File.open(filename,'w') { |f| f.print xml }
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# EAAL::Cache::Memcached
|
2
|
+
# Cache class to allow use of Memcached server(s) as a local cache option.
|
3
|
+
require 'memcache'
|
4
|
+
class EAAL::Cache::MemcachedCache
|
5
|
+
|
6
|
+
def initialize(servers="localhost:11211",options={})
|
7
|
+
o = {:namespace => 'eaal'}.merge(options)
|
8
|
+
$cache = MemCache.new(servers,o)
|
9
|
+
end
|
10
|
+
# Returns the memcached key for a given set of args.
|
11
|
+
# Does not use the full API key string as the risk of a collision is astronomically high.
|
12
|
+
def key(userid, apikey, scope, name, args)
|
13
|
+
"#{userid}#{apikey[0..25]}#{scope}#{name}#{args}"
|
14
|
+
end
|
15
|
+
# Saves to cache. It is worth noting that memcached handles expiry for us unlike FileCache
|
16
|
+
# as a result, there is no requirement for a validate_cache method- we just get MC to expire
|
17
|
+
# the key when we can go get a new copy.
|
18
|
+
def save(userid, apikey, scope, name, args, xml)
|
19
|
+
k = key(userid, apikey, scope, name, args)
|
20
|
+
cached_until = xml.match(/<cachedUntil>(.+)<\/cachedUntil>/)[1].to_time
|
21
|
+
expires_in = (name=='WalletJournal' ? cached_until.to_i+3600 : cached_until.to_i )-Time.now.to_i
|
22
|
+
$cache.delete(k)
|
23
|
+
$cache.add(k,xml,expires_in)
|
24
|
+
end
|
25
|
+
# Loads from the cache if there's a value for it.
|
26
|
+
def load(userid, apikey, scope, name, args)
|
27
|
+
k = key(userid, apikey, scope, name, args)
|
28
|
+
($cache.get(k,xml,expires_in) or false) rescue false
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#++
|
6
|
+
module EAAL::Exception
|
7
|
+
# creates the class for an EveAPIException
|
8
|
+
def self.EveAPIException(nr)
|
9
|
+
classname = "EveAPIException#{nr}"
|
10
|
+
if not Object.const_defined? classname
|
11
|
+
klass = Object.const_set(classname, Class.new(EAAL::Exception::EveAPIException))
|
12
|
+
else
|
13
|
+
klass = Object.const_get(classname)
|
14
|
+
end
|
15
|
+
klass
|
16
|
+
end
|
17
|
+
|
18
|
+
# raise the eve API exceptions, class will be dynamicaly created by classname
|
19
|
+
# EveAPIException followed by the APIs exception Number
|
20
|
+
def self.raiseEveAPIException(nr, msg)
|
21
|
+
raise EAAL::Exception.EveAPIException(nr).new(msg)
|
22
|
+
end
|
23
|
+
|
24
|
+
# all EAAL exceptions should extend this.
|
25
|
+
class EAALError < StandardError
|
26
|
+
end
|
27
|
+
|
28
|
+
# Used when an http error is encountered
|
29
|
+
class HTTPError < EAALError
|
30
|
+
end
|
31
|
+
|
32
|
+
# Used when the Eve API returns a 404
|
33
|
+
class APINotFoundError < HTTPError
|
34
|
+
end
|
35
|
+
|
36
|
+
# All API Errors should be derived from this
|
37
|
+
class EveAPIException < EAALError
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -1,123 +1,123 @@
|
|
1
|
-
#--
|
2
|
-
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
-
# This library is licensed under the terms found in
|
4
|
-
# the LICENSE file distributed with it
|
5
|
-
#++
|
6
|
-
module EAAL
|
7
|
-
|
8
|
-
module Result
|
9
|
-
|
10
|
-
# base class for automated result class creation
|
11
|
-
class ResultBase
|
12
|
-
attr_accessor :request_time, :cached_until
|
13
|
-
end
|
14
|
-
|
15
|
-
# Result Container class, ...
|
16
|
-
class ResultContainer
|
17
|
-
attr_accessor :container
|
18
|
-
|
19
|
-
def initialize
|
20
|
-
self.container = {}
|
21
|
-
end
|
22
|
-
|
23
|
-
def add_element(key, val)
|
24
|
-
self.container.merge!({key => val})
|
25
|
-
end
|
26
|
-
|
27
|
-
def method_missing(method, *args)
|
28
|
-
self.container[method.id2name]
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# result element
|
33
|
-
class ResultElement
|
34
|
-
attr_accessor :name, :value, :attribs
|
35
|
-
def initialize(name, value)
|
36
|
-
self.name = name
|
37
|
-
self.value = value
|
38
|
-
self.attribs = {}
|
39
|
-
end
|
40
|
-
|
41
|
-
def add_attrib(key, val)
|
42
|
-
self.attribs.merge!({key => val})
|
43
|
-
end
|
44
|
-
|
45
|
-
def method_missing(method, *args)
|
46
|
-
if self.attribs.has_key?(method.id2name)
|
47
|
-
self.attribs[method.id2name]
|
48
|
-
else
|
49
|
-
self.value.send(method, *args)
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
# parses an xml element to create either the ResultElement, ResultContainer or Rowset
|
55
|
-
# necessary
|
56
|
-
def self.parse_element(prefix, element)
|
57
|
-
if element.name == "rowset"
|
58
|
-
re = EAAL::Rowset.new(prefix, element)
|
59
|
-
else
|
60
|
-
key = element.name
|
61
|
-
if element.children && element.containers.length > 0
|
62
|
-
container = ResultContainer.new
|
63
|
-
element.containers.each { |celement|
|
64
|
-
cel = EAAL::Result::ResultElement.parse_element(prefix, celement)
|
65
|
-
if element.attributes.length > 0
|
66
|
-
container.add_element(cel.name, cel)
|
67
|
-
else
|
68
|
-
container.add_element(cel.name, cel.value)
|
69
|
-
end
|
70
|
-
}
|
71
|
-
value = container
|
72
|
-
else
|
73
|
-
value = element.inner_html
|
74
|
-
end
|
75
|
-
re = ResultElement.new(key, value)
|
76
|
-
if element.attributes.length > 0
|
77
|
-
re.attribs.merge!(element.attributes)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
re
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# create a new result derived from ResultBase
|
85
|
-
def self.new(prefix, xml)
|
86
|
-
classname = prefix + 'Result'
|
87
|
-
members = []
|
88
|
-
values = {}
|
89
|
-
if (xml/"eveapi/error").length > 0
|
90
|
-
error = (xml/"eveapi/error").first
|
91
|
-
raise EAAL::Exception.raiseEveAPIException(error["code"], error.inner_html)
|
92
|
-
end
|
93
|
-
if (xml/"eveapi/result").length < 1
|
94
|
-
raise EAAL::Exception::EAALError.new("Unknown API error, no result element was found")
|
95
|
-
end
|
96
|
-
elements = (xml/"eveapi/result").first.containers
|
97
|
-
elements.each {|element|
|
98
|
-
el = EAAL::Result::ResultElement.parse_element(prefix, element)
|
99
|
-
members << el.name
|
100
|
-
if el.kind_of? EAAL::Rowset::RowsetBase
|
101
|
-
values.merge!({el.name => el})
|
102
|
-
else
|
103
|
-
values.merge!({el.name => el.value})
|
104
|
-
end
|
105
|
-
}
|
106
|
-
if not Object.const_defined? classname
|
107
|
-
klass = Object.const_set(classname, Class.new(EAAL::Result::ResultBase))
|
108
|
-
klass.class_eval do
|
109
|
-
attr_accessor
|
110
|
-
end
|
111
|
-
else
|
112
|
-
klass = Object.const_get(classname)
|
113
|
-
end
|
114
|
-
result = klass.new
|
115
|
-
result.request_time = (xml/"eveapi/currentTime").first.inner_html
|
116
|
-
result.cached_until = (xml/"eveapi/cachedUntil").first.inner_html
|
117
|
-
values.each { |key,value|
|
118
|
-
result.send(key + "=", value)
|
119
|
-
}
|
120
|
-
result
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
1
|
+
#--
|
2
|
+
# EAAL by Peter Petermann <PeterPetermann@gmx.net>
|
3
|
+
# This library is licensed under the terms found in
|
4
|
+
# the LICENSE file distributed with it
|
5
|
+
#++
|
6
|
+
module EAAL
|
7
|
+
|
8
|
+
module Result
|
9
|
+
|
10
|
+
# base class for automated result class creation
|
11
|
+
class ResultBase
|
12
|
+
attr_accessor :request_time, :cached_until
|
13
|
+
end
|
14
|
+
|
15
|
+
# Result Container class, ...
|
16
|
+
class ResultContainer
|
17
|
+
attr_accessor :container
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
self.container = {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_element(key, val)
|
24
|
+
self.container.merge!({key => val})
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(method, *args)
|
28
|
+
self.container[method.id2name]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# result element
|
33
|
+
class ResultElement
|
34
|
+
attr_accessor :name, :value, :attribs
|
35
|
+
def initialize(name, value)
|
36
|
+
self.name = name
|
37
|
+
self.value = value
|
38
|
+
self.attribs = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_attrib(key, val)
|
42
|
+
self.attribs.merge!({key => val})
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(method, *args)
|
46
|
+
if self.attribs.has_key?(method.id2name)
|
47
|
+
self.attribs[method.id2name]
|
48
|
+
else
|
49
|
+
self.value.send(method, *args)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# parses an xml element to create either the ResultElement, ResultContainer or Rowset
|
55
|
+
# necessary
|
56
|
+
def self.parse_element(prefix, element)
|
57
|
+
if element.name == "rowset"
|
58
|
+
re = EAAL::Rowset.new(prefix, element)
|
59
|
+
else
|
60
|
+
key = element.name
|
61
|
+
if element.children && element.containers.length > 0
|
62
|
+
container = ResultContainer.new
|
63
|
+
element.containers.each { |celement|
|
64
|
+
cel = EAAL::Result::ResultElement.parse_element(prefix, celement)
|
65
|
+
if element.attributes.length > 0
|
66
|
+
container.add_element(cel.name, cel)
|
67
|
+
else
|
68
|
+
container.add_element(cel.name, cel.value)
|
69
|
+
end
|
70
|
+
}
|
71
|
+
value = container
|
72
|
+
else
|
73
|
+
value = element.inner_html
|
74
|
+
end
|
75
|
+
re = ResultElement.new(key, value)
|
76
|
+
if element.attributes.length > 0
|
77
|
+
re.attribs.merge!(element.attributes)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
re
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# create a new result derived from ResultBase
|
85
|
+
def self.new(prefix, xml)
|
86
|
+
classname = prefix + 'Result'
|
87
|
+
members = []
|
88
|
+
values = {}
|
89
|
+
if (xml/"eveapi/error").length > 0
|
90
|
+
error = (xml/"eveapi/error").first
|
91
|
+
raise EAAL::Exception.raiseEveAPIException(error["code"], error.inner_html)
|
92
|
+
end
|
93
|
+
if (xml/"eveapi/result").length < 1
|
94
|
+
raise EAAL::Exception::EAALError.new("Unknown API error, no result element was found")
|
95
|
+
end
|
96
|
+
elements = (xml/"eveapi/result").first.containers
|
97
|
+
elements.each {|element|
|
98
|
+
el = EAAL::Result::ResultElement.parse_element(prefix, element)
|
99
|
+
members << el.name
|
100
|
+
if el.kind_of? EAAL::Rowset::RowsetBase
|
101
|
+
values.merge!({el.name => el})
|
102
|
+
else
|
103
|
+
values.merge!({el.name => el.value})
|
104
|
+
end
|
105
|
+
}
|
106
|
+
if not Object.const_defined? classname
|
107
|
+
klass = Object.const_set(classname, Class.new(EAAL::Result::ResultBase))
|
108
|
+
klass.class_eval do
|
109
|
+
attr_accessor(*members)
|
110
|
+
end
|
111
|
+
else
|
112
|
+
klass = Object.const_get(classname)
|
113
|
+
end
|
114
|
+
result = klass.new
|
115
|
+
result.request_time = (xml/"eveapi/currentTime").first.inner_html
|
116
|
+
result.cached_until = (xml/"eveapi/cachedUntil").first.inner_html
|
117
|
+
values.each { |key,value|
|
118
|
+
result.send(key + "=", value)
|
119
|
+
}
|
120
|
+
result
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|