basuco 0.0.3

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.
@@ -0,0 +1,100 @@
1
+ module Basuco
2
+ class << self
3
+ attr_accessor :search
4
+ end
5
+
6
+ # partially taken from chris eppstein's freebase api
7
+ # http://github.com/chriseppstein/freebase/tree
8
+ class Search
9
+ include Request
10
+ public
11
+ # @param host<String> the API host
12
+ # @param username<String> freebase username
13
+ # @param password<String> user password
14
+ def initialize(options = {:host => 'http://www.freebase.com', :username => 'un', :password => 'pw'})
15
+ @host = options[:host]
16
+ @username = options[:username]
17
+ @password = options[:password]
18
+ Basuco.search = self
19
+
20
+ # TODO: check connection
21
+ end
22
+
23
+ # Perform a mqlread and return the results
24
+ # Specify :cursor => true to batch the results of a query, sending multiple requests if necessary.
25
+ # TODO: should support multiple queries
26
+ # you should be able to pass an array of queries
27
+ def mqlread(query, options = {})
28
+ cursor = options[:cursor]
29
+ if cursor
30
+ query_result = []
31
+ while cursor
32
+ response = get_query_response(query, cursor)
33
+ query_result += response['result']
34
+ cursor = response['cursor']
35
+ end
36
+ else
37
+ response = get_query_response(query, cursor)
38
+ cursor = response['cursor']
39
+ query_result = response['result']
40
+ end
41
+ query_result
42
+ end
43
+
44
+
45
+ # Executes an Mql Query against the Freebase API and returns the result as
46
+ # a <tt>Collection</tt> of <tt>Resources</tt>.
47
+ def all(options = {})
48
+ #assert_kind_of 'options', options, Hash
49
+ query = { :name => nil }.merge!(options).merge!(:id => nil)
50
+ result = mqlread([ query ], :cursor => !options[:limit])
51
+ Basuco::Collection.new(result.map { |r| Basuco::Resource.new(r) })
52
+ end
53
+
54
+
55
+ # Executes an Mql Query against the Freebase API and returns the result wrapped
56
+ # in a <tt>Resource</tt> Object.
57
+ #
58
+ # == Examples
59
+ #
60
+ # Basuco.get('/en/the_police') => #<Resource id="/en/the_police" name="The Police">
61
+ # @api public
62
+ def get(id)
63
+ Basuco::Resource.get(id)
64
+ end
65
+
66
+
67
+ def topic(id, options = {})
68
+ options.merge!({:id => id})
69
+
70
+ response = http_request topic_service_url+"/standard", options
71
+ --debugger
72
+ result = JSON.parse response
73
+ inner = result[id]
74
+ handle_read_error(inner)
75
+ inner['result']
76
+ end
77
+
78
+ def search(query, options = {})
79
+ options.merge!({:query => query})
80
+
81
+ response = http_request search_service_url, options
82
+ result = JSON.parse response
83
+
84
+ handle_read_error(result)
85
+
86
+ result['result']
87
+ end
88
+
89
+
90
+ #yes or no
91
+ def status?
92
+ response = http_request status_service_url
93
+ result = JSON.parse response
94
+ return result["code"] == "/api/status/ok"
95
+ end
96
+
97
+
98
+
99
+ end # class Search
100
+ end # module Basuco
@@ -0,0 +1,192 @@
1
+ module Basuco
2
+ class Topic
3
+
4
+ attr_reader :data
5
+
6
+ # initializes a topic using a json result
7
+ def initialize(data)
8
+ # assert_kind_of 'data', data, Hash
9
+ @data = data
10
+ @schema_loaded, @attributes_loaded = false, false
11
+ end
12
+
13
+ # Retrieves a topic using the Topic API by Freebase
14
+ # returns a <tt>Topic</tt> Object.
15
+ #
16
+ # == Examples
17
+ #
18
+ # Basuco::Topic.get('/en/the_police') => #<Topic id="/en/the_police" name="The Police">
19
+ # @api public
20
+ def self.get(id)
21
+ #assert_kind_of 'id', id, String
22
+ result = Basuco.search.topic(id)
23
+ raise TopicNotFound unless result
24
+ Basuco::Topic.new(result)
25
+ end
26
+
27
+ # topic id
28
+ # @api public
29
+ def id
30
+ @data["id"] || ""
31
+ end
32
+
33
+ # topic aliases
34
+ def aliases
35
+ @data["alias"]
36
+ end
37
+
38
+ # topic freebase url
39
+ def url
40
+ @data["url"]
41
+ end
42
+
43
+ # topic name
44
+ # @api public
45
+ def name
46
+ text
47
+ end
48
+
49
+ # topic description
50
+ # @api public
51
+ def description
52
+ @data["description"]
53
+ end
54
+
55
+ # topic text
56
+ # @api public
57
+ def text
58
+ @data["text"]
59
+ end
60
+
61
+ # topic thumbnail
62
+ def thumbnail
63
+ @data["thumbnail"]
64
+ end
65
+
66
+ # @api public
67
+ def to_s
68
+ name || id || ""
69
+ end
70
+
71
+ # @api public
72
+ def inspect
73
+ result = "#<Topic id=\"#{id}\" name=\"#{name || "nil"}\">"
74
+ end
75
+
76
+ # topic webpages
77
+ # currently returned as an array of hashes containing the keys "text" and "url"
78
+ # that hashes may be wrapped into a Webpage class later
79
+ # @api public
80
+ def webpages
81
+ @data["webpage"]
82
+ end
83
+
84
+ # returns all assigned types
85
+ # @api public
86
+ def types
87
+ load_schema! unless schema_loaded?
88
+ @types
89
+ end
90
+
91
+ # returns individual type based on the requested type id
92
+ # @api public
93
+ def type(type)
94
+ types.each { |t| return t if t.id =~ /^#{Regexp.escape(type)}$/}
95
+ nil
96
+ end
97
+
98
+ # returns all the properties from all assigned types
99
+ # @api public
100
+ def properties
101
+ @properties = Basuco::Collection.new
102
+ types.each do |type|
103
+ @properties.concat(type.properties)
104
+ end
105
+ @properties
106
+ end
107
+
108
+ # returns all attributes for every type the topic is an instance of
109
+ # @api public
110
+ def attributes
111
+ load_attributes! unless attributes_loaded?
112
+ @attributes.values
113
+ end
114
+
115
+ # returns all available views based on the assigned types
116
+ # @api public
117
+ def views
118
+ @views ||= Basuco::Collection.new(types.map { |type| Basuco::View.new(self, type) })
119
+ end
120
+
121
+ # returns individual view based on the requested type id
122
+ # @api public
123
+ def view(type)
124
+ views.each { |v| return v if v.type.id =~ /^#{Regexp.escape(type)}$/}
125
+ nil
126
+ end
127
+
128
+
129
+ # search for an attribute by name and return it
130
+ # @api public
131
+ def attribute(name)
132
+ attributes.each { |a| return a if a.property.id == name }
133
+ nil
134
+ end
135
+
136
+ # returns true if type information is already loaded
137
+ # @api public
138
+ def schema_loaded?
139
+ @schema_loaded
140
+ end
141
+
142
+ # returns true if attributes are already loaded
143
+ # @api public
144
+ def attributes_loaded?
145
+ @attributes_loaded
146
+ end
147
+
148
+ private
149
+
150
+ # loads the full set of attributes using reflection
151
+ # information is extracted from master, value and reverse attributes
152
+ # @api private
153
+ def load_attributes!
154
+ load_schema! unless schema_loaded?
155
+
156
+ @attributes = {}
157
+ @data["properties"].each do |id, data|
158
+ # skip mediator properties for now
159
+ if !data["properties"]
160
+ values = []
161
+ data["values"].each do |value|
162
+ values << { "id" => value["id"], "name" => value["text"], "value" => value["text"] }
163
+ end
164
+ @attributes[id] = Basuco::Attribute.create(values, properties.select { |p| p.id == id }.first)
165
+ end
166
+ end
167
+
168
+ @attributes_loaded = true
169
+ end
170
+
171
+ # loads the topic's metainfo
172
+ # @api private
173
+ def load_schema!
174
+ result = {}
175
+
176
+ @data["type"].each do |type|
177
+ result[type["id"]] = { "id" => type["id"], "name" => type["text"], "properties" => [] }
178
+ end
179
+ @data["properties"].each do |id, data|
180
+ result[id.gsub(/\/\w*$/, "")]["properties"] << {
181
+ "expected_type" => data["expected_type"]["id"],
182
+ "id" => id,
183
+ "name" => data["text"],
184
+ "unique" => true
185
+ }
186
+ end
187
+ @types = Basuco::Collection.new(result.values.map { |type| Basuco::Type.new(type) })
188
+ @schema_loaded = true
189
+ end
190
+
191
+ end # class Topic
192
+ end # module Basuco
@@ -0,0 +1,36 @@
1
+ module Basuco
2
+ class << self
3
+ attr_accessor :trans
4
+ end
5
+
6
+ # partially taken from chris eppstein's freebase api
7
+ # http://github.com/chriseppstein/freebase/tree
8
+ class Trans
9
+ include Request
10
+
11
+ def initialize(options = {:host => 'http://www.freebase.com', :username => 'un', :password => 'pw'})
12
+ @host = options[:host]
13
+ @username = options[:username]
14
+ @password = options[:password]
15
+ Basuco.trans = self
16
+ end
17
+
18
+ #yes or no
19
+ def status?
20
+ response = http_request status_service_url
21
+ result = JSON.parse response
22
+ return result["blob"] == "OK"
23
+ end
24
+
25
+ def raw_content(id, options = {})
26
+ response = http_request raw_service_url+id, options
27
+ response
28
+ end
29
+
30
+ def blurb_content(id, options = {})
31
+ response = http_request blurb_service_url+id, options
32
+ response
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,53 @@
1
+ module Basuco
2
+ class Type
3
+
4
+ # include Extlib::Assertions
5
+
6
+ # initializes a resource using a json result
7
+ def initialize(data)
8
+ # assert_kind_of 'data', data, Hash
9
+ @data = data
10
+ end
11
+
12
+ # access property info
13
+ # @api public
14
+ def properties
15
+ @properties ||= Basuco::Collection.new(@data["properties"].map { |property| Basuco::Property.new(property, self) })
16
+ end
17
+
18
+ # type id
19
+ # @api public
20
+ def id
21
+ @data["id"]
22
+ end
23
+
24
+ # type name
25
+ # @api public
26
+ def name
27
+ @data["name"]
28
+ end
29
+
30
+ # @api public
31
+ def to_s
32
+ name || id || ""
33
+ end
34
+
35
+ # @api public
36
+ def inspect
37
+ result = "#<Type id=\"#{id}\" name=\"#{name || "nil"}\">"
38
+ end
39
+
40
+ # delegate to property_get
41
+ def method_missing sym
42
+ property_get(sym.to_s)
43
+ end
44
+
45
+ private
46
+ # @api private
47
+ # search for a property by name and return it
48
+ def property_get(name)
49
+ properties.each { |p| return p if p.id =~ /\/#{name}$/ }
50
+ raise PropertyNotFound
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ module Basuco
2
+ module Util
3
+ # magic hash conversion
4
+ def convert_hash(source)
5
+ source.inject({}) do |result, item|
6
+ if result[item["link"]]
7
+ result[item["link"]] << { "id" => item["id"], "name" => item["name"], "value" => item["value"] }
8
+ else
9
+ result[item["link"]] = []
10
+ result[item["link"]] << { "id" => item["id"], "name" => item["name"], "value" => item["value"] }
11
+ end
12
+ result
13
+ end
14
+ end
15
+ module_function :convert_hash
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Basuco
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,54 @@
1
+ # provides an interface to view a subject (resource or topic) as a specific type
2
+ # provides an interface for working with attributes, properties
3
+ module Basuco
4
+ class View
5
+
6
+
7
+ # initializes a subject (resource or topic) by json result
8
+ def initialize(subject, type)
9
+ # assert_kind_of 'type', type, Basuco::Type
10
+ @subject, @type = subject, type
11
+ end
12
+
13
+ # @api public
14
+ def to_s
15
+ @type.to_s
16
+ end
17
+
18
+ # return correspondent type
19
+ # @api public
20
+ def type
21
+ @type
22
+ end
23
+
24
+ # @api public
25
+ def inspect
26
+ result = "#<View type=\"#{type.id || "nil"}\">"
27
+ end
28
+
29
+ # returns attributes which are member of the view's type
30
+ # @api public
31
+ def attributes
32
+ @subject.attributes.select { |a| a.property.type == @type}
33
+ end
34
+
35
+ # search for an attribute by name and return it
36
+ # @api public
37
+ def attribute(name)
38
+ attributes.each { |a| return a if a.property.id =~ /\/#{name}$/ }
39
+ nil
40
+ end
41
+
42
+ # returns properties which are member of the view's type
43
+ # @api public
44
+ def properties
45
+ @subject.properties.select { |p| p.type == @type}
46
+ end
47
+
48
+ # delegate to attribute
49
+ def method_missing sym
50
+ attribute(sym.to_s)
51
+ end
52
+
53
+ end
54
+ end