astroboa-rb 0.4.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.
@@ -0,0 +1,166 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
166
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # encoding: utf-8
2
+ source :rubygems
3
+
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ Copyright (C) 2005-2012 BetaCONCEPT LP.
2
+
3
+ Astroboa Ruby Client is free software: you can redistribute it and/or modify
4
+ it under the terms of the GNU Lesser General Public License as published by
5
+ the Free Software Foundation, either version 3 of the License, or
6
+ (at your option) any later version.
7
+
8
+ Astroboa Ruby Client is distributed in the hope that it will be useful,
9
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE or NONINFRINGEMENT.
11
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
12
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
13
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
14
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+
16
+ The included files named COPYING and COPYING.LESSER contain the full text
17
+ of the GNU and the GNU Lesser General Public License respectively.
18
+ Please read them in order to know the full details of Astroboa Ruby Client License Terms.
@@ -0,0 +1,122 @@
1
+ # astroboa-rb
2
+
3
+ While you can directly use the REST-based "Astroboa Resource API" from your Ruby projects
4
+ using the net/http library or any one of the rest client libraries, Astroboa Ruby Client greatly eases your work.
5
+
6
+ The Ruby client allows you to read, write and search content in any local or remote astroboa repository with just a few lines of code.
7
+
8
+ ## Install
9
+
10
+ === For your project using bundler
11
+
12
+ Add to your Gemfile:
13
+
14
+ gem "astroboa-rb"
15
+
16
+ and run at the command prompt:
17
+
18
+ bundle install
19
+
20
+ === or as a gem in your ruby environment
21
+
22
+ Run at the command prompt:
23
+
24
+ gem install astroboa-rb
25
+
26
+
27
+ Below are some examples on how to use the client
28
+
29
+ ## EXAMPLE USE
30
+
31
+ # encoding: utf-8
32
+ require 'astroboa-rb'
33
+
34
+ # CONNECT TO THE REPOSITORY
35
+ # provide the server where astroboa runs and the repository to connect to
36
+ astroboaClient = Astroboa::Client.new('demo.betaconcept.com', 'demorepository')
37
+
38
+ astroboaClient.on_error do |exception|
39
+ puts exception.message
40
+ end
41
+
42
+ # CREATE A NEW OBJECT
43
+ # createObject(objectHash, &exception_block)
44
+ # The example uses the 'out of the box' object type:'genericContentResourceObject'
45
+ # This type simulates a simple article or blog entry with "title", "description", "subject"(tags) and "body"(the body text) properties
46
+ # The "title", "description" and "subject" properties are stored inside the "group property" called "profile".
47
+ # "profile" is a default property inherited to all asstroboa objects and groups all dublin core metadata
48
+ my_new_text_resource = {"contentObjectTypeName" => "genericContentResourceObject", "profile" => {"title" => "My First blog entry", "description" => "How I installed astroboa"}, "body" => 'Go to github and check the installation instructions...'}
49
+ my_new_text_resource_id = astroboaClient.createObject my_new_text_resource
50
+ puts "created object with id: #{my_new_text_resource_id}"
51
+
52
+ # GET AN OBJECT AS A RUBY HASH
53
+ # getObject(idOrName, options = {}, &exception_block)
54
+ options = {}
55
+ options[:project] = 'profile.title,body' # project/filter which properties to get back
56
+ options[:output] = 'hash' # in which form to get back the object, possible values are "hash","object","xml","json", default is "hash"
57
+ retrieved_text_resource = astroboaClient.getObject my_new_text_resource_id, options
58
+ puts "The retrieved resource is: #{retrieved_text_resource}"
59
+ puts retrieved_text_resource['profile']['title']
60
+
61
+ # GET AN OBJECT AS A RUBY OBJECT
62
+ retrieved_text_resource = astroboaClient.getObject my_new_text_resource_id, output: 'object'
63
+ puts "I retrieved the resource as object and the title is: #{retrieved_text_resource.profile.title}"
64
+ puts "The retrieved resource is: #{retrieved_text_resource}"
65
+
66
+ # UPDATE AN EXISTING OBJECT
67
+ # updateObject(objectHash, updateLastModificationTime = true, &exception_block)
68
+ resource = {"contentObjectTypeName" => "genericContentResourceObject", "cmsIdentifier" => my_new_text_resource_id, "body" => "Updated Body Text...."}
69
+ response = astroboaClient.updateObject resource
70
+ puts "I updated the object and the response is: #{response}"
71
+
72
+ # GET THE UPDATED OBJECT BACK
73
+ text_resource = astroboaClient.getObject my_new_text_resource_id
74
+ puts "I will read the updated resource back and the updated body is #{text_resource['body']}"
75
+
76
+ # SEARCH AN OBJECT COLLECTION
77
+ # getObjectCollection(query = nil, options = {}, &exception_block)
78
+ options = {}
79
+
80
+ # project/filter which properties to get back, here we get back only the object titles
81
+ options[:project] = 'profile.title'
82
+
83
+ # get objects counting from 'offset' and up. Default is 0. Use it together with limit for result paging
84
+ options[:offset] = 0
85
+
86
+ # how many object to get back. Default is 50
87
+ options[:limit] = 50
88
+
89
+ # by which property to order the results.
90
+ # Use 'desc or asc after the field to ask for ascenting or descenting ordering'.
91
+ # use commas to add more ordering fields, eg. 'profile.modified desc, profile.title asc'
92
+ # Default is 'profile.modified desc'
93
+ options[:orderBy] = 'profile.modified desc'
94
+
95
+ # in which form to get back the object, possible values are "hash","object","xml","json", default is "hash"
96
+ options[:output] = 'hash'
97
+
98
+ # Express the query in a similar way you specify the WHERE in SQL queries.
99
+ # Values should be ALWAYS inside double quotes ("")
100
+ query = 'objectType="genericContentResourceObject" AND body CONTAINS "Hello"'
101
+ resource_collection = astroboaClient.getObjectCollection query, options
102
+
103
+ text_resources = resource_collection['resourceCollection']['resource']
104
+ found_id = nil
105
+ puts "Looking for resource #{my_new_text_resource_id}"
106
+ text_resources.each do |text_resource|
107
+ puts text_resource['cmsIdentifier']
108
+ if text_resource['cmsIdentifier'] == my_new_text_resource_id
109
+ found_id = text_resource['cmsIdentifier']
110
+ break
111
+ end
112
+ end
113
+ puts "found #{found_id}"
114
+
115
+
116
+ # LICENSE
117
+ -------
118
+ Released under the LGPL license; see the files LICENSE, COPYING and COPYING.LESSER.
119
+
120
+
121
+
122
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "astroboa-rb/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "astroboa-rb"
7
+ s.version = Astroboa::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["BetaCONCEPT","Gregory Chomatas"]
10
+ s.email = ["support@betaconcept.com"]
11
+ s.homepage = "http://www.astroboa.org"
12
+ s.date = Date.today.to_s
13
+ s.summary = %q{Astroboa Client for Ruby.}
14
+ s.description = %q{Provides easy access to the REST-based 'Astroboa Resource API'. With just a few lines of code you can read, write and search semi-structured content to any astroboa repository hosted in any server in the world.}
15
+
16
+ s.rubyforge_project = "astroboa-rb"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+
22
+ s.require_paths = ["lib"]
23
+ s.add_runtime_dependency 'rest-client','>= 1.6'
24
+ s.add_runtime_dependency 'json','>= 1.6'
25
+ s.add_development_dependency 'cucumber','~> 1.1'
26
+ s.add_development_dependency 'rspec-expectations','~> 2.8'
27
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+ module Astroboa; end
3
+
4
+ require 'astroboa-rb/client'
5
+ require 'astroboa-rb/clienterror'
@@ -0,0 +1,362 @@
1
+ # encoding: utf-8
2
+
3
+ require 'logger'
4
+ require 'rest-client'
5
+ require 'json'
6
+ require 'ostruct'
7
+
8
+
9
+ module Astroboa
10
+
11
+ class Client
12
+
13
+ def self.version
14
+ Astroboa::VERSION
15
+ end
16
+
17
+ # get and set options for the JSON parser
18
+ # by default the nesting level is raised from 20 to 50
19
+ attr_accessor :json_options
20
+
21
+ attr_reader :repository, :astroboaIPAddressOrFQDN, :username
22
+ attr_reader :resourceApiBasePath, :objectsApiPath, :taxonomiesApiPath, :topicsApiPath, :modelsApiPath
23
+ attr_reader :objectsResource, :taxonomiesResource, :topicsResource, :modelsResource
24
+
25
+ def initialize(astroboaIPAddressOrFQDN, repository, username = nil , password = nil)
26
+ # the IP or Fully Qualified Domain Name of the server that provides the astroboa data services
27
+ @astroboaIPAddressOrFQDN = astroboaIPAddressOrFQDN
28
+
29
+ # the id of the repository from which we want to read or write resources (multiple repositories can be served by each astroboa server)
30
+ @repository = repository
31
+
32
+ @username = username
33
+ @password = password
34
+
35
+ @resourceApiBasePath = "http://#{astroboaIPAddressOrFQDN}/resource-api"
36
+
37
+ # this resource is about all repositories and does not require a repository to be specified
38
+ @repositoriesResource = RestClient::Resource.new(@resourceApiBasePath, {:user => username, :password => password, :headers => astroboa_client_headers})
39
+
40
+ # all other resources require a repository to be specified
41
+ create_repository_resources(repository)
42
+
43
+ @log = Logger.new('/tmp/astroboa-rb-log.txt')
44
+ @log.level = Logger::WARN
45
+
46
+ RestClient.log = @log
47
+
48
+ # some json payloads have very deep nesting and the JSON parser option should be set to allow deeper nesting
49
+ # the default parser nesting is 20. We set it to 50 and the user may set it to a higher level through :json_options accessor
50
+ @json_options = {:max_nesting => 50}
51
+
52
+ end
53
+
54
+ # set the repository
55
+ def repository= (repository)
56
+ @repository = repository
57
+
58
+ # each time a repository is set we regenerate the resource api calls to target the specified repository
59
+ create_repository_resources(repository)
60
+ end
61
+
62
+ # set your own logger
63
+ def log= (logger)
64
+ @log = logger
65
+ RestClient.log = logger
66
+ end
67
+
68
+ #
69
+ # API
70
+ #
71
+
72
+ def getObject(idOrName, options = {}, &exception_block)
73
+
74
+ if idOrName && !idOrName.empty?
75
+ begin
76
+ projectionPaths = options[:project]
77
+ output = options[:output] ||= :hash
78
+
79
+ case output
80
+ when :json
81
+ acceptHeader = :json
82
+ outputParam = 'json'
83
+ when :xml
84
+ acceptHeader = :xml
85
+ outputParam = 'xml'
86
+ when :hash, :object
87
+ acceptHeader = :json
88
+ outputParam = 'json'
89
+ else
90
+ message = "Astroboa API cannot return resources as #{output}. Please see the documentation for available output options."
91
+ log.error message
92
+ handle_error(message, nil, &exception_block)
93
+ end
94
+
95
+ response = nil
96
+ params = {'output' => outputParam}
97
+ if projectionPaths
98
+ params['projectionPaths'] = projectionPaths
99
+ end
100
+
101
+ response = @objectsResource["#{idOrName}"].get :params => params, :accept => acceptHeader
102
+
103
+ case output
104
+ when :json, :xml
105
+ return response.body
106
+ when :hash
107
+ return JSON response.body
108
+ when :object
109
+ objectHash = JSON.parse(response.body, @json_options)
110
+ return objectHash.to_openstruct
111
+ end
112
+ rescue => api_exception
113
+ @log.error "Astroboa getObject call failed. Error is #{api_exception.inspect}. The requested object id (or name) was: #{idOrName}."
114
+ message = "Astroboa getObject call failed. The requested object id (or name) was: #{idOrName}."
115
+ handle_error(message, api_exception, &exception_block)
116
+ end
117
+ else
118
+ message = "You should specify the id or name of the object."
119
+ @log.error message
120
+ handle_error(message, nil, &exception_block)
121
+ end
122
+ end
123
+
124
+
125
+ def createObject(objectHash, &exception_block)
126
+ if !objectHash or objectHash.empty?
127
+ message = "You should specify an non empty hash of the object you want to create."
128
+ @log.error message
129
+ handle_error(message, nil, &exception_block)
130
+ return
131
+ end
132
+
133
+ if objectHash.has_key?('cmsIdentifier')
134
+ message = "You have specified an object identifier. Object identifiers are automatically assigned by astroboato new objects. Please remove the identifier if this is a new object or use updateObject if it is an existing object."
135
+ @log.warn message
136
+ handle_error(message, nil, &exception_block)
137
+ else
138
+ begin
139
+ response = @objectsResource.post objectHash.to_json, :content_type => :json
140
+ objectHash['cmsIdentifier'] = response.body.to_s
141
+ return response.body.to_s
142
+ rescue => api_exception
143
+ @log.error "Astroboa createObject call failed. Error is #{api_exception.inspect}. The object to be created was: #{objectHash}."
144
+ message = "Astroboa createObject call failed. The object to be created was: #{objectHash}."
145
+ handle_error(message, api_exception, &exception_block)
146
+ end
147
+ end
148
+ end
149
+
150
+
151
+ def updateObject(objectHash, updateLastModificationTime = true, &exception_block)
152
+ if !objectHash or objectHash.empty?
153
+ message = "You should specify an non empty hash of the object you want to update."
154
+ @log.error message
155
+ handle_error(message, nil, &exception_block)
156
+ return
157
+ end
158
+
159
+ if objectHash.has_key?('cmsIdentifier')
160
+ begin
161
+ response = @objectsResource["#{objectHash['cmsIdentifier']}"].put objectHash.to_json, :params => {'updateLastModificationTime' => updateLastModificationTime}, :content_type => :json
162
+ return response.body.to_s
163
+ rescue => api_exception
164
+ @log.error "Astroboa updateObject call failed. Error is #{api_exception.inspect}. The object to be updated was: #{objectHash}."
165
+ message = "Astroboa updateObject call failed. The object to be updated was: #{objectHash}."
166
+ handle_error(message, api_exception, &exception_block)
167
+ end
168
+ else
169
+ message = "You try to update an object that does not have an identifier. If your object is new then use createObject to create a new object."
170
+ @log.error message
171
+ handle_error(message, nil, &exception_block)
172
+ end
173
+ end
174
+
175
+ def getObjectCollection(query = nil, options = {}, &exception_block)
176
+ begin
177
+ projectionPaths = options[:project]
178
+ offset = options[:offset] ||= 0
179
+ limit = options[:limit] ||= 50
180
+ orderBy = options[:orderBy] ||= 'profile.modified desc'
181
+ output = options[:output] ||= :hash
182
+
183
+ case output
184
+ when :json
185
+ acceptHeader = :json
186
+ outputParam = 'json'
187
+ when :xml
188
+ acceptHeader = :xml
189
+ outputParam = 'xml'
190
+ when :hash, :object
191
+ acceptHeader = :json
192
+ outputParam = 'json'
193
+ else
194
+ message = "Astroboa API cannot return resources as #{output}. Please see the documentation for available output options."
195
+ log.error message
196
+ handle_error(message, nil, &exception_block)
197
+ end
198
+
199
+ response = nil
200
+ params = {'output' => outputParam}
201
+
202
+ if query
203
+ params['cmsQuery'] = query
204
+ end
205
+
206
+ if projectionPaths
207
+ params['projectionPaths'] = projectionPaths
208
+ end
209
+
210
+ params['offset'] = offset
211
+ params['limit'] = limit
212
+ params['orderBy'] = orderBy
213
+
214
+ response = @objectsResource.get :params => params, :accept => acceptHeader
215
+
216
+ case output
217
+ when :json, :xml
218
+ return response.body
219
+ when :hash
220
+ return JSON.parse(response.body, @json_options)
221
+ when :object
222
+ objectHash = JSON.parse(response.body, @json_options)
223
+ return objectHash.to_openstruct
224
+ end
225
+ rescue => api_exception
226
+ @log.error "Astroboa getObjectCollection call failed. Error is #{api_exception.inspect}. The requested collection query was: #{query}, with projection paths: #{projectionPaths}, offset: #{offset}, limit: #{limit}, orderBy: #{orderBy}."
227
+ message = "Astroboa getObjectCollection call failed. The requested collection query was: #{query}, with projection paths: #{projectionPaths}, offset: #{offset}, limit: #{limit}, orderBy: #{orderBy}."
228
+ handle_error(message, api_exception, &exception_block)
229
+ end
230
+ end
231
+
232
+ def getModel(objectTypeOrProperty='', output = :hash, &exception_block)
233
+ begin
234
+ case output
235
+ when :json
236
+ acceptHeader = :json
237
+ outputParam = 'json'
238
+ when :xml
239
+ acceptHeader = :xml
240
+ outputParam = 'xml'
241
+ when :hash, :object
242
+ acceptHeader = :json
243
+ outputParam = 'json'
244
+ else
245
+ message = "Astroboa API cannot return resources as #{output}. Please see the documentation for available output options."
246
+ log.error message
247
+ handle_error(message, nil, &exception_block)
248
+ end
249
+
250
+ response = nil
251
+ params = {'output' => outputParam}
252
+
253
+ if objectTypeOrProperty && !objectTypeOrProperty.empty?
254
+ response = @modelsResource["#{objectTypeOrProperty}"].get :params => params, :accept => acceptHeader
255
+ else
256
+ response = @modelsResource.get :params => params, :accept => acceptHeader
257
+ end
258
+
259
+ case output
260
+ when :json, :xml
261
+ return response.body
262
+ when :hash
263
+ return JSON.parse(response.body, @json_options)
264
+ when :object
265
+ objectHash = JSON.parse(response.body, @json_options)
266
+ return objectHash.to_openstruct
267
+ end
268
+ rescue => api_exception
269
+ @log.error "Astroboa getModel call failed. Error is #{api_exception.inspect}. The requested object type or object property was: #{objectTypeOrProperty}."
270
+ message = "Astroboa getModel call failed. The requested object type or property was: #{objectTypeOrProperty}."
271
+ handle_error(message, api_exception, &exception_block)
272
+ end
273
+ end
274
+
275
+ def on_error(&block)
276
+ @error_callback = block
277
+ end
278
+
279
+ #
280
+ # implementation
281
+ #
282
+
283
+ def handle_error(message, api_exception, &exception_block)
284
+ if block_given?
285
+ astroboaClientError = createAstroboaClientException(message, api_exception)
286
+ exception_block.call(astroboaClientError)
287
+ elsif @error_callback
288
+ astroboaClientError = createAstroboaClientException(message, api_exception)
289
+ @error_callback.call(astroboaClientError)
290
+ end
291
+
292
+ return nil
293
+
294
+ end
295
+
296
+ def createAstroboaClientException(message, api_exception)
297
+ api_code = 'There is no astroboa api return code. The api call was not send due to the error'
298
+ api_response = 'There is no astroboa api response. The api call was not send due to the error'
299
+ if api_exception
300
+ message = "#{message} - Cause: #{api_exception.message}"
301
+ if api_exception.respond_to?(:http_code)
302
+ api_code = api_exception.http_code
303
+ end
304
+ if api_exception.respond_to?(:response)
305
+ api_response = api_exception.response ||= 'The astroboa api call did not produce any response'
306
+ end
307
+ end
308
+ Astroboa::ClientError.new(message, api_code, api_response)
309
+ end
310
+
311
+ def astroboa_client_headers
312
+ if (defined? self.class.gem_version_string)
313
+ gem_version = self.class.gem_version_string
314
+ else
315
+ gem_version = nil
316
+ end
317
+
318
+ {
319
+ 'X-Astroboa-API-Version' => '3.0.0',
320
+ 'User-Agent' => gem_version,
321
+ 'X-Ruby-Version' => RUBY_VERSION,
322
+ 'X-Ruby-Platform' => RUBY_PLATFORM
323
+ }
324
+ end
325
+
326
+
327
+ def create_repository_resources(repository)
328
+ @objectsApiPath = "#{@resourceApiBasePath}/#{repository}/objects"
329
+ @taxonomiesApiPath = "#{@resourceApiBasePath}/#{repository}/taxonomies"
330
+ @topicsApiPath = "#{@resourceApiBasePath}/#{repository}/topics"
331
+ @modelsApiPath = "#{@resourceApiBasePath}/#{repository}/models"
332
+
333
+ @objectsResource = RestClient::Resource.new(@objectsApiPath, {:user => @username, :password => @password, :headers => astroboa_client_headers})
334
+ @taxonomiesResource = RestClient::Resource.new(@taxonomiesApiPath, {:user => @username, :password => @password, :headers => astroboa_client_headers})
335
+ @topicsResource = RestClient::Resource.new(@topicsApiPath, {:user => @username, :password => @password, :headers => astroboa_client_headers})
336
+ @modelsResource = RestClient::Resource.new(@modelsApiPath, {:user => @username, :password => @password, :headers => astroboa_client_headers})
337
+ end
338
+ end # class Client
339
+
340
+ end # Module Astroboa
341
+
342
+
343
+ class Object
344
+ def to_openstruct
345
+ self
346
+ end
347
+ end
348
+
349
+ class Array
350
+ def to_openstruct
351
+ map{ |el| el.to_openstruct }
352
+ end
353
+ end
354
+
355
+ class Hash
356
+ def to_openstruct
357
+ mapped = {}
358
+ each{ |key,value| mapped[key] = value.to_openstruct }
359
+ OpenStruct.new(mapped)
360
+ end
361
+ end
362
+