eaal 0.1.4 → 0.1.5
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/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
|