granicus-platform-api 0.1.9 → 0.9.1
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/.gitignore +3 -0
- data/README.rdoc +2 -2
- data/lib/granicus-platform-api/client.rb +503 -466
- data/lib/granicus-platform-api/entities.rb +235 -207
- data/lib/granicus-platform-api/granicus-platform-api.xml +2073 -1824
- data/lib/granicus-platform-api/version.rb +1 -1
- data/spec/fixtures/About Stacks.pdf +0 -0
- data/spec/fixtures/fixtures.yml +64 -0
- data/spec/fixtures/requests.xml +52 -52
- data/spec/granicus-platform-api_spec.rb +392 -234
- metadata +18 -15
- data/Gemfile.lock +0 -53
data/README.rdoc
CHANGED
@@ -30,7 +30,7 @@ This wrapper is developed against 1.9.2.
|
|
30
30
|
|
31
31
|
= License
|
32
32
|
|
33
|
-
Copyright (c) 2011
|
33
|
+
Copyright (c) 2011 Granicus, Inc.
|
34
34
|
|
35
35
|
Permission is hereby granted, free of charge, to any person obtaining
|
36
36
|
a copy of this software and associated documentation files (the
|
@@ -56,4 +56,4 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
56
56
|
|
57
57
|
= Credits
|
58
58
|
|
59
|
-
Javier Muniz
|
59
|
+
Javier Muniz, Ryan Wold
|
@@ -1,467 +1,504 @@
|
|
1
|
-
require 'savon'
|
2
|
-
|
3
|
-
module GranicusPlatformAPI
|
4
|
-
class Client
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
self.typegenerators
|
21
|
-
|
22
|
-
self.typegenerators["
|
23
|
-
self.typegenerators["
|
24
|
-
self.typegenerators["
|
25
|
-
self.typegenerators["
|
26
|
-
self.typegenerators["
|
27
|
-
self.typegenerators["
|
28
|
-
self.typegenerators["
|
29
|
-
self.typegenerators["
|
30
|
-
self.typegenerators["
|
31
|
-
self.typegenerators["
|
32
|
-
self.typegenerators["
|
33
|
-
self.typegenerators["
|
34
|
-
self.typegenerators["
|
35
|
-
self.typegenerators["
|
36
|
-
self.typegenerators["
|
37
|
-
self.typegenerators["
|
38
|
-
self.typegenerators["
|
39
|
-
self.typegenerators["
|
40
|
-
self.typegenerators["
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
def self.classmap
|
48
|
-
@@classmap
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
self.classmap
|
57
|
-
self.classmap['
|
58
|
-
|
59
|
-
|
60
|
-
self.classmap['
|
61
|
-
self.classmap['
|
62
|
-
self.classmap['
|
63
|
-
|
64
|
-
|
65
|
-
self.classmap['
|
66
|
-
self.classmap['
|
67
|
-
self.classmap['
|
68
|
-
self.classmap['
|
69
|
-
self.classmap['
|
70
|
-
self.classmap['
|
71
|
-
self.classmap['
|
72
|
-
self.classmap['
|
73
|
-
self.classmap['
|
74
|
-
self.classmap['
|
75
|
-
self.classmap['
|
76
|
-
self.classmap['
|
77
|
-
self.classmap['
|
78
|
-
self.classmap['
|
79
|
-
self.classmap['
|
80
|
-
self.classmap['
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
@impersonation_token
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
call_soap_method(:
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
def
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
1
|
+
require 'savon'
|
2
|
+
|
3
|
+
module GranicusPlatformAPI
|
4
|
+
class Client
|
5
|
+
|
6
|
+
attr_reader :connected
|
7
|
+
|
8
|
+
# mappings between soap types and our complex types
|
9
|
+
# this area should be rewritten to auto-generate data sets properly
|
10
|
+
# and refactored to separate standard xsd types from custom types in class
|
11
|
+
# map
|
12
|
+
def self.typegenerators
|
13
|
+
@@typegenerators
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.typegenerators=(obj)
|
17
|
+
@@typegenerators = obj
|
18
|
+
end
|
19
|
+
|
20
|
+
self.typegenerators = {}
|
21
|
+
|
22
|
+
self.typegenerators["AgendaItem"] = lambda { AgendaItem.new }
|
23
|
+
self.typegenerators["Attendee"] = lambda { Attendee.new }
|
24
|
+
self.typegenerators["AttendeeStatus"] = lambda { AttendeeStatus.new }
|
25
|
+
self.typegenerators["CameraData"] = lambda { CameraData.new }
|
26
|
+
self.typegenerators["CaptionData"] = lambda { CaptionData.new }
|
27
|
+
self.typegenerators["ClipData"] = lambda { ClipData.new }
|
28
|
+
self.typegenerators["Document"] = lambda { Document.new }
|
29
|
+
self.typegenerators["EventData"] = lambda { EventData.new }
|
30
|
+
self.typegenerators["FolderData"] = lambda { FolderData.new }
|
31
|
+
self.typegenerators["GroupData"] = lambda { GroupData.new }
|
32
|
+
self.typegenerators["KeyMapping"] = lambda { KeyMapping.new }
|
33
|
+
self.typegenerators["MetaDataData"] = lambda { MetaDataData.new }
|
34
|
+
self.typegenerators["EComment"] = lambda { EComment.new }
|
35
|
+
self.typegenerators["Motion"] = lambda { Motion.new }
|
36
|
+
self.typegenerators["Note"] = lambda { Note.new }
|
37
|
+
self.typegenerators["Rollcall"] = lambda { Rollcall.new }
|
38
|
+
self.typegenerators["ServerData"] = lambda { ServerData.new }
|
39
|
+
self.typegenerators["ServerInterfaceData"] = lambda { ServerInterfaceData.new }
|
40
|
+
self.typegenerators["TemplateData"] = lambda { TemplateData.new }
|
41
|
+
self.typegenerators["ViewData"] = lambda { ViewData.new }
|
42
|
+
self.typegenerators["VoteEntry"] = lambda { VoteEntry.new }
|
43
|
+
self.typegenerators["VoteRecord"] = lambda { VoteRecord.new }
|
44
|
+
self.typegenerators["Setting"] = lambda { Setting.new }
|
45
|
+
|
46
|
+
# classmap for generating proper attributes! hash within savon calls
|
47
|
+
def self.classmap
|
48
|
+
@@classmap
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.classmap=(obj)
|
52
|
+
@@classmap = obj
|
53
|
+
end
|
54
|
+
|
55
|
+
# built-in types
|
56
|
+
self.classmap = {}
|
57
|
+
self.classmap['Fixnum'] = "xsd:int"
|
58
|
+
self.classmap['String'] = "xsd:string"
|
59
|
+
self.classmap['TrueClass'] = 'xsd:boolean'
|
60
|
+
self.classmap['FalseClass'] = 'xsd:boolean'
|
61
|
+
self.classmap['Time'] = 'xsd:dateTime'
|
62
|
+
self.classmap['File'] = 'xsd:base64Binary'
|
63
|
+
|
64
|
+
# start custom types
|
65
|
+
self.classmap['AgendaItem'] = 'granicus:AgendaItem'
|
66
|
+
self.classmap['Attendee'] = 'granicus:Attendee'
|
67
|
+
self.classmap['AttendeeStatus'] = 'granicus:AttendeeStatus'
|
68
|
+
self.classmap['CameraData'] = 'granicus:CameraData'
|
69
|
+
self.classmap['CaptionData'] = 'granicus:CaptionData'
|
70
|
+
self.classmap['ClipData'] = 'granicus:ClipData'
|
71
|
+
self.classmap['Document'] = 'granicus:Document'
|
72
|
+
self.classmap['EComment'] = 'granicus:EComment'
|
73
|
+
self.classmap['EventData'] = 'granicus:EventData'
|
74
|
+
self.classmap['FolderData'] = 'granicus:FolderData'
|
75
|
+
self.classmap['GroupData'] = 'granicus:GroupData'
|
76
|
+
self.classmap['KeyMapping'] = 'granicus:KeyMapping'
|
77
|
+
self.classmap['MetaDataData'] = 'granicus:MetaDataData'
|
78
|
+
self.classmap['Motion'] = 'granicus:Motion'
|
79
|
+
self.classmap['Note'] = 'granicus:Note'
|
80
|
+
self.classmap['Rollcall'] = 'granicus:Rollcall'
|
81
|
+
self.classmap['ServerData'] = 'granicus:ServerData'
|
82
|
+
self.classmap['ServerInterfaceData'] = 'granicus:ServerInterfaceData'
|
83
|
+
self.classmap['TemplateData'] = 'granicus:TemplateData'
|
84
|
+
self.classmap['ViewData'] = 'granicus:ViewData'
|
85
|
+
self.classmap['VoteEntry'] = 'granicus:VoteEntry'
|
86
|
+
self.classmap['VoteRecord'] = 'granicus:VoteRecord'
|
87
|
+
|
88
|
+
# create a client
|
89
|
+
def initialize(granicus_site=nil, username=nil, password=nil, options={})
|
90
|
+
# setup our private members
|
91
|
+
@options = options
|
92
|
+
@impersonation_token = nil
|
93
|
+
@connected = false
|
94
|
+
|
95
|
+
# configure savon
|
96
|
+
Savon.configure do |config|
|
97
|
+
config.log = false
|
98
|
+
end
|
99
|
+
HTTPI.log = false
|
100
|
+
|
101
|
+
# connect if we have a site and credentials
|
102
|
+
unless granicus_site.nil?
|
103
|
+
self.site = granicus_site
|
104
|
+
end
|
105
|
+
|
106
|
+
unless username.nil? or password.nil?
|
107
|
+
login(username, password)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# options
|
112
|
+
def options
|
113
|
+
@options
|
114
|
+
end
|
115
|
+
|
116
|
+
def options=(value)
|
117
|
+
@options = value
|
118
|
+
end
|
119
|
+
|
120
|
+
# connect up to a site
|
121
|
+
def connect(granicus_site, username, password, options={})
|
122
|
+
logout if @connected
|
123
|
+
|
124
|
+
# create the client
|
125
|
+
self.site = granicus_site
|
126
|
+
|
127
|
+
# call login
|
128
|
+
login username, password
|
129
|
+
end
|
130
|
+
|
131
|
+
# site property
|
132
|
+
def site
|
133
|
+
return @granicus_site
|
134
|
+
end
|
135
|
+
|
136
|
+
def site=(value)
|
137
|
+
@granicus_site = value
|
138
|
+
@client = Savon::Client.new do |wsdl, http|
|
139
|
+
wsdl.document = File.expand_path("../granicus-platform-api.xml", __FILE__)
|
140
|
+
wsdl.endpoint = "http://#{value}/SDK/User/index.php"
|
141
|
+
http.proxy = @options[:proxy] if not @options[:proxy].nil?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# impersonate a user
|
146
|
+
def impersonate(token)
|
147
|
+
@impersonation_token = token
|
148
|
+
@client.http.headers["Cookie"] = "SESS1=#{token}; path=/"
|
149
|
+
end
|
150
|
+
|
151
|
+
def impersonation_token
|
152
|
+
@impersonation_token
|
153
|
+
end
|
154
|
+
|
155
|
+
# login
|
156
|
+
def login(username, password)
|
157
|
+
logout if @connected
|
158
|
+
call_soap_method(:login, '//ns4:LoginResponse/return', {'Username' => username, 'Password' => password})
|
159
|
+
@impersonation_token = @response.http.headers['Set-Cookie'].gsub(/SESS1=(.*); path=\//, '\\1')
|
160
|
+
@connected = true
|
161
|
+
end
|
162
|
+
|
163
|
+
# return the current logged on user name
|
164
|
+
def get_current_user_logon
|
165
|
+
call_soap_method(:get_current_user_logon, '//ns4:GetCurrentUserLogonResponse/Logon')
|
166
|
+
end
|
167
|
+
|
168
|
+
# logout
|
169
|
+
def logout
|
170
|
+
call_soap_method(:logout, '//ns4:LogoutResponse')
|
171
|
+
@connected = false
|
172
|
+
end
|
173
|
+
|
174
|
+
# return all of the cameras
|
175
|
+
def get_cameras
|
176
|
+
call_soap_method(:get_cameras, '//ns5:GetCamerasResponse/cameras')
|
177
|
+
end
|
178
|
+
|
179
|
+
# create a camera
|
180
|
+
def create_camera(camera)
|
181
|
+
call_soap_method(:create_camera, '//ns4:CreateCameraResponse/CameraID', {'CameraData' => camera})
|
182
|
+
end
|
183
|
+
|
184
|
+
# return the requested camera
|
185
|
+
def get_camera(camera_id)
|
186
|
+
call_soap_method(:get_camera, '//ns5:GetCameraResponse/camera', {'CameraID' => camera_id})
|
187
|
+
end
|
188
|
+
|
189
|
+
# update a camera
|
190
|
+
def update_camera(camera)
|
191
|
+
call_soap_method(:update_camera, '//ns4:UpdateCameraResponse', {'camera' => camera})
|
192
|
+
end
|
193
|
+
|
194
|
+
# delete the requested camera
|
195
|
+
def delete_camera(camera_id)
|
196
|
+
call_soap_method(:delete_camera, '//ns4:DeleteCameraResponse', {'CameraID' => camera_id})
|
197
|
+
end
|
198
|
+
|
199
|
+
# return all of the events
|
200
|
+
def get_events
|
201
|
+
call_soap_method(:get_events, '//ns5:GetEventsResponse/events')
|
202
|
+
end
|
203
|
+
|
204
|
+
# return all of the events with matching foreign id
|
205
|
+
def get_events_by_foreign_id(foreign_id)
|
206
|
+
call_soap_method(:get_events_by_foreign_id, '//ns5:GetEventsByForeignIDResponse/events', {'ForeignID' => foreign_id})
|
207
|
+
end
|
208
|
+
|
209
|
+
# create an event
|
210
|
+
def create_event(event)
|
211
|
+
call_soap_method(:create_event, '//ns4:CreateEventResponse/EventID', {'EventData' => event})
|
212
|
+
end
|
213
|
+
|
214
|
+
# return the requested event
|
215
|
+
def get_event(event_id)
|
216
|
+
call_soap_method(:get_event, '//ns5:GetEventResponse/event', {'EventID' => event_id})
|
217
|
+
end
|
218
|
+
|
219
|
+
# return the requested event by uid
|
220
|
+
def get_event_by_uid(event_uid)
|
221
|
+
call_soap_method(:get_event_by_uid, '//ns5:GetEventByUIDResponse/event', {'EventUID' => event_uid})
|
222
|
+
end
|
223
|
+
|
224
|
+
# update an event
|
225
|
+
def update_event(event)
|
226
|
+
call_soap_method(:update_event, '//ns4:UpdateEventResponse', {'event' => event})
|
227
|
+
end
|
228
|
+
|
229
|
+
# delete the requested event
|
230
|
+
def delete_event(event_id)
|
231
|
+
call_soap_method(:delete_event, '//ns4:DeleteEventResponse', {'EventID' => event_id})
|
232
|
+
end
|
233
|
+
|
234
|
+
# return all of the event meta data
|
235
|
+
def get_event_meta_data(event_id)
|
236
|
+
build_meta_tree call_soap_method(:get_event_meta_data, '//ns5:GetEventMetaDataResponse/metadata', {'EventID' => event_id})
|
237
|
+
end
|
238
|
+
|
239
|
+
# return all of the event meta data by UID
|
240
|
+
def get_event_meta_data_by_uid(event_uid)
|
241
|
+
build_meta_tree call_soap_method(:get_event_meta_data_by_uid, '//ns5:GetEventMetaDataByUIDResponse/metadata', {'EventUID' => event_uid})
|
242
|
+
end
|
243
|
+
|
244
|
+
# import metadata for an event
|
245
|
+
def import_event_meta_data(event_id, meta_data, clear_existing=true, as_tree=true)
|
246
|
+
call_soap_method(:import_event_meta_data, '//ns5:ImportEventMetaDataResponse/KeyTable', {
|
247
|
+
'EventID' => event_id,
|
248
|
+
'MetaData' => meta_data,
|
249
|
+
'ClearExisting' => clear_existing,
|
250
|
+
'AsTree' => as_tree})
|
251
|
+
end
|
252
|
+
|
253
|
+
# set the event agenda url
|
254
|
+
def set_event_agenda_url(event_id, url)
|
255
|
+
call_soap_method(:set_event_agenda_url, '//ns4:SetEventAgendaURLResponse', {'EventID' => event_id, 'URL' => url})
|
256
|
+
end
|
257
|
+
|
258
|
+
# return all of the clip meta data
|
259
|
+
def get_clip_meta_data(clip_id)
|
260
|
+
build_meta_tree call_soap_method(:get_clip_meta_data, '//ns5:GetClipMetaDataResponse/metadata', {'ClipID' => clip_id})
|
261
|
+
end
|
262
|
+
|
263
|
+
# import metadata for a clip
|
264
|
+
# ImportClipMetaData Method (ClipID, MetaData, ClearExisting, AsTree)
|
265
|
+
def import_clip_meta_data(clip_id, meta_data, clear_existing=true, as_tree=true)
|
266
|
+
call_soap_method(:import_clip_meta_data, '//ns5:ImportClipMetaDataResponse/KeyTable', {
|
267
|
+
'ClipID' => clip_id,
|
268
|
+
'MetaData' => meta_data,
|
269
|
+
'ClearExisting' => clear_existing,
|
270
|
+
'AsTree' => as_tree})
|
271
|
+
end
|
272
|
+
|
273
|
+
# add metadata to a clip
|
274
|
+
def add_clip_meta_data(clip_id, meta_data, options={})
|
275
|
+
call_soap_method( :add_clip_meta_data, '//ns5:AddClipMetaDataResponse/KeyTable', {
|
276
|
+
'ClipID' => clip_id,
|
277
|
+
'MetaData' => meta_data}, options)
|
278
|
+
end
|
279
|
+
|
280
|
+
# fetch an attachment
|
281
|
+
def fetch_attachment(meta_id)
|
282
|
+
call_soap_method(:fetch_attachment, '//ns5:FetchAttachmentResponse/Attachment', {'MetaDataID' => meta_id})
|
283
|
+
end
|
284
|
+
|
285
|
+
# get meta data by id
|
286
|
+
def get_meta_data(meta_id)
|
287
|
+
call_soap_method(:get_meta_data, '//ns5:GetMetaDataResponse/MetaData', {'MetaDataID' => meta_id})
|
288
|
+
end
|
289
|
+
|
290
|
+
# update metadata
|
291
|
+
def update_meta_data(meta_data)
|
292
|
+
call_soap_method(:update_meta_data, '//ns4:UpdateMetaDataResponse', {'MetaData' => meta_data})
|
293
|
+
end
|
294
|
+
|
295
|
+
def get_ecomments_by_event_id(event_id)
|
296
|
+
call_soap_method(:get_ecomments_by_event_id, '//ns5:GetEcommentsByEventIDResponse/EComments', {'EventID' => event_id})
|
297
|
+
end
|
298
|
+
|
299
|
+
def get_ecomments_by_agenda_item_uid(uid)
|
300
|
+
call_soap_method(:get_ecomments_by_agenda_item_uid, '//ns5:GetEcommentsByAgendaItemUIDResponse/EComments', {'AgendaItemUID' => uid})
|
301
|
+
end
|
302
|
+
|
303
|
+
# return all of the folders
|
304
|
+
def get_folders
|
305
|
+
call_soap_method(:get_folders, '//ns5:GetFoldersResponse/folders')
|
306
|
+
end
|
307
|
+
|
308
|
+
# return all of the clips
|
309
|
+
def get_clips(folder_id)
|
310
|
+
call_soap_method(:get_clips, '//ns5:GetClipsResponse/clips', {'FolderID' => folder_id})
|
311
|
+
end
|
312
|
+
|
313
|
+
# return all of the clips with matching foreign id
|
314
|
+
def get_clips_by_foreign_id(foreign_id)
|
315
|
+
call_soap_method(:get_clips_by_foreign_id, '//ns5:GetClipsByForeignIDResponse/clips', {'ForeignID' => foreign_id})
|
316
|
+
end
|
317
|
+
|
318
|
+
# return the requested clip
|
319
|
+
def get_clip(clip_id)
|
320
|
+
call_soap_method(:get_clip, '//ns5:GetClipResponse/clip', {'ClipID' => clip_id})
|
321
|
+
end
|
322
|
+
|
323
|
+
# update a clip
|
324
|
+
def update_clip(clip)
|
325
|
+
call_soap_method(:update_clip, '//ns4:UpdateClipResponse', {'clip' => clip})
|
326
|
+
end
|
327
|
+
|
328
|
+
# return the requested clip
|
329
|
+
def get_clip_by_uid(clip_uid)
|
330
|
+
call_soap_method(:get_clip_by_uid, '//ns5:GetClipByUIDResponse/clip', {'ClipUID' => clip_uid})
|
331
|
+
end
|
332
|
+
|
333
|
+
# get servers
|
334
|
+
def get_servers
|
335
|
+
call_soap_method(:get_servers, '//ns5:GetServersResponse/servers')
|
336
|
+
end
|
337
|
+
|
338
|
+
# return the requested server
|
339
|
+
def get_server(server_id)
|
340
|
+
call_soap_method(:get_server, '//ns5:GetServerResponse/server', {'ServerID' => server_id})
|
341
|
+
end
|
342
|
+
|
343
|
+
# get settings
|
344
|
+
def get_settings
|
345
|
+
call_soap_method(:get_settings, '//ns5:GetSettingsResponse/settings')
|
346
|
+
end
|
347
|
+
|
348
|
+
#private
|
349
|
+
|
350
|
+
def call_soap_method(method, returnfilter, args={}, options={})
|
351
|
+
debug = options[:debug]
|
352
|
+
@response = @client.request :wsdl, method do
|
353
|
+
soap.namespaces['xmlns:granicus'] = "http://granicus.com/xsd"
|
354
|
+
soap.namespaces['xmlns:SOAP-ENC'] = "http://schemas.xmlsoap.org/soap/encoding/"
|
355
|
+
soap.body = prepare_hash args
|
356
|
+
if debug
|
357
|
+
puts soap.body
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
doc = Nokogiri::XML(@response.to_xml) do |config|
|
362
|
+
config.noblanks
|
363
|
+
end
|
364
|
+
if debug
|
365
|
+
puts doc
|
366
|
+
end
|
367
|
+
response = handle_response(doc.xpath(returnfilter, doc.root.namespaces)[0])
|
368
|
+
if debug
|
369
|
+
puts response
|
370
|
+
end
|
371
|
+
response
|
372
|
+
end
|
373
|
+
|
374
|
+
def prepare_hash(hash={})
|
375
|
+
attributes = {}
|
376
|
+
new_hash = {}
|
377
|
+
hash.each do |key, value|
|
378
|
+
case value.class.to_s
|
379
|
+
when /GranicusPlatformAPI::/, 'Hash'
|
380
|
+
new_hash[key] = prepare_hash value
|
381
|
+
when 'Array'
|
382
|
+
new_hash[key] = prepare_array value
|
383
|
+
when 'File'
|
384
|
+
new_hash[key] = Base64.encode64(value.read().force_encoding('BINARY'))
|
385
|
+
else
|
386
|
+
new_hash[key] = value
|
387
|
+
end
|
388
|
+
attributes[key] = attribute_of value
|
389
|
+
end
|
390
|
+
new_hash.merge({:attributes! => attributes})
|
391
|
+
end
|
392
|
+
|
393
|
+
def prepare_array(array)
|
394
|
+
return {"item" => array} if array.count == 0
|
395
|
+
new_array = []
|
396
|
+
array.each do |item|
|
397
|
+
case item.class.to_s
|
398
|
+
when /GranicusPlatformAPI::/, 'Hash'
|
399
|
+
new_array << prepare_hash(item)
|
400
|
+
when 'Array'
|
401
|
+
new_array << prepare_array(item)
|
402
|
+
else
|
403
|
+
new_array << item
|
404
|
+
end
|
405
|
+
end
|
406
|
+
{"item" => new_array, :attributes! => {"item" => attribute_of(array[0])}}
|
407
|
+
end
|
408
|
+
|
409
|
+
def attribute_of(value)
|
410
|
+
case value.class.to_s
|
411
|
+
when 'Array'
|
412
|
+
return {"xsi:type" => 'SOAP-ENC:Array'} if value.count == 0
|
413
|
+
xsd_type = self.class.classmap[value[0].class.to_s.split('::').last]
|
414
|
+
if xsd_type.nil?
|
415
|
+
puts "Couldn't get array xsd:type for #{value[0].class}"
|
416
|
+
{"xsi:type" => 'SOAP-ENC:Array'}
|
417
|
+
else
|
418
|
+
{"xsi:type" => 'SOAP-ENC:Array', "SOAP-ENC:arrayType" => "#{xsd_type}[#{value.count}]"}
|
419
|
+
end
|
420
|
+
else
|
421
|
+
xsd_type = self.class.classmap[value.class.to_s.split('::').last]
|
422
|
+
if xsd_type.nil?
|
423
|
+
puts "Couldn't get xsd:type for #{value.class}"
|
424
|
+
nil
|
425
|
+
else
|
426
|
+
{"xsi:type" => xsd_type}
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
def handle_response(node)
|
432
|
+
if node.is_a? Nokogiri::XML::NodeSet or node.is_a? Array then
|
433
|
+
return node.map { |el| handle_response el }
|
434
|
+
end
|
435
|
+
return node.to_s unless node['type']
|
436
|
+
typespace, type = node['type'].split(':')
|
437
|
+
case typespace
|
438
|
+
when 'xsd'
|
439
|
+
proc = self.class.typecasts[type]
|
440
|
+
unless proc.nil?
|
441
|
+
proc.call(node.children[0].to_s)
|
442
|
+
else
|
443
|
+
puts "Unknown xsd:type: #{type}"
|
444
|
+
node.children[0].to_s
|
445
|
+
end
|
446
|
+
when 'SOAP-ENC'
|
447
|
+
if type == 'Array' then
|
448
|
+
node.children.map { |element| handle_response element }
|
449
|
+
else
|
450
|
+
puts "Unknown SOAP-ENC:type: #{type}"
|
451
|
+
node.to_s
|
452
|
+
end
|
453
|
+
else
|
454
|
+
# we have a custom type, attempt to generate it. if that fails use a hash
|
455
|
+
proc = self.class.typegenerators[type]
|
456
|
+
value = {}
|
457
|
+
unless proc.nil?
|
458
|
+
value = proc.call
|
459
|
+
else
|
460
|
+
puts "Unknown custom type: #{type}"
|
461
|
+
end
|
462
|
+
node.children.each do |value_node|
|
463
|
+
value[value_node.name] = handle_response value_node
|
464
|
+
end
|
465
|
+
value
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
# translate metadata list returned by the get_event and get_clip meta data functions into a tree
|
470
|
+
def build_meta_tree(list, parent_id=0)
|
471
|
+
tree = []
|
472
|
+
list.each do |item|
|
473
|
+
if item.ParentID == parent_id
|
474
|
+
item.Children = build_meta_tree list, item.ID
|
475
|
+
tree << item
|
476
|
+
end
|
477
|
+
end
|
478
|
+
tree
|
479
|
+
end
|
480
|
+
|
481
|
+
# typecasts ripped from rubiii/nori, adapted for xsd types
|
482
|
+
def self.typecasts
|
483
|
+
@@typecasts
|
484
|
+
end
|
485
|
+
|
486
|
+
def self.typecasts=(obj)
|
487
|
+
@@typecasts = obj
|
488
|
+
end
|
489
|
+
|
490
|
+
self.typecasts = {}
|
491
|
+
self.typecasts["int"] = lambda { |v| v.nil? ? nil : v.to_i }
|
492
|
+
self.typecasts["boolean"] = lambda { |v| v.nil? ? nil : (v.strip != "false") }
|
493
|
+
self.typecasts["datetime"] = lambda { |v| v.nil? ? nil : Time.parse(v).utc }
|
494
|
+
self.typecasts["date"] = lambda { |v| v.nil? ? nil : Date.parse(v) }
|
495
|
+
self.typecasts["dateTime"] = lambda { |v| v.nil? ? nil : Time.parse(v).utc }
|
496
|
+
self.typecasts["decimal"] = lambda { |v| v.nil? ? nil : BigDecimal(v.to_s) }
|
497
|
+
self.typecasts["double"] = lambda { |v| v.nil? ? nil : v.to_f }
|
498
|
+
self.typecasts["float"] = lambda { |v| v.nil? ? nil : v.to_f }
|
499
|
+
self.typecasts["symbol"] = lambda { |v| v.nil? ? nil : v.to_sym }
|
500
|
+
self.typecasts["string"] = lambda { |v| v.to_s }
|
501
|
+
self.typecasts["yaml"] = lambda { |v| v.nil? ? nil : YAML.load(v) }
|
502
|
+
self.typecasts["base64Binary"] = lambda { |v| v.unpack('m').first }
|
503
|
+
end
|
467
504
|
end
|