juxta 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9537d609ce2a9506964a49b399dce7a4f54b4cd7
4
+ data.tar.gz: be87bc4c13083793d5a0afdf3cb57edec7ae66db
5
+ SHA512:
6
+ metadata.gz: d11ec8282f12f0656d0eece0923ffbdfa33370f049a855a4af93e061384574e0ed0a1648ae58f0cbe201626a58978a293e4fe685df9dd7e787298ddcf428185d
7
+ data.tar.gz: 013597f634a633718c0fbc9cc2f7df724fc5014b5a3f4b27cb73b205ac282b41ab70b0525b69725908e356cabeb3ce9fde51604f3bf68ecbf5125cf502c2ec15
@@ -0,0 +1,107 @@
1
+ require 'json'
2
+ require 'rest_client'
3
+ require 'base64'
4
+
5
+ class Connection
6
+
7
+ attr_reader :url
8
+ attr_reader :workspace
9
+
10
+ def initialize( url, workspace, username, password )
11
+
12
+ @authtoken = "Basic #{Base64.encode64("#{username}:#{password}")}"
13
+ @url = "#{url}/juxta"
14
+ @workspace = workspace
15
+
16
+ @timeout = 600 # 10 minute get timeout...
17
+ @open_timeout = 600 # 10 minute post timeout
18
+
19
+ opts = {
20
+ :timeout => @timeout,
21
+ :open_timeout=> @open_timeout
22
+ }
23
+
24
+ @rest_client = RestClient::Resource.new( @url, opts )
25
+ end
26
+
27
+ def get_ws_version()
28
+ start_time = Time.now.to_f
29
+ resp = @rest_client.get :content_type => "application/json", :authorization => @authtoken
30
+ dump_time( "get", start_time )
31
+ json = JSON.parse(resp)
32
+ return json['version']
33
+ end
34
+
35
+ def get( request )
36
+ start_time = Time.now.to_f
37
+ resp = @rest_client[ make_url( request ) ].get :content_type => "application/json", :accept=>'application/json', :authorization => @authtoken
38
+ dump_time( "get", start_time )
39
+ JSON.parse(resp)
40
+ end
41
+
42
+ def get_html( request )
43
+ start_time = Time.now.to_f
44
+ resp = @rest_client[ make_url( request ) ].get :content_type => "text/html", :authorization => @authtoken
45
+ dump_time( "get", start_time )
46
+ return resp
47
+ end
48
+
49
+ def get_xml( request )
50
+ start_time = Time.now.to_f
51
+ resp = @rest_client[ make_url( request ) ].get :content_type => "text/xml", :authorization => @authtoken
52
+ dump_time( "get", start_time )
53
+ return resp
54
+ end
55
+
56
+ def post( request, payload )
57
+ start_time = Time.now.to_f
58
+ if payload.nil? == true
59
+ resp = @rest_client[ make_url( request ) ].post "", :authorization => @authtoken
60
+ else
61
+ resp = @rest_client[ make_url( request ) ].post payload.to_json, :authorization => @authtoken, :content_type => "application/json"
62
+ end
63
+ dump_time( "post", start_time )
64
+ return resp
65
+ end
66
+
67
+ def upload_file( file_name, content_type, file )
68
+ opts = {
69
+ :sourceName=> file_name,
70
+ :contentType => content_type,
71
+ :sourceFile=> file,
72
+ :multipart => true
73
+ }
74
+ start_time = Time.now.to_f
75
+ resp = @rest_client[ make_url( "source" ) ].post opts, :authorization => @authtoken
76
+ dump_time( "post", start_time )
77
+ json = JSON.parse(resp)
78
+ return json[ 0 ]
79
+ end
80
+
81
+ def put( request, payload )
82
+ start_time = Time.now.to_f
83
+ resp = @rest_client[ make_url( request ) ].put payload.to_json, :authorization => @authtoken, :content_type => "application/json"
84
+ dump_time( "put", start_time )
85
+ return resp
86
+ end
87
+
88
+ def delete( request )
89
+ start_time = Time.now.to_f
90
+ resp = @rest_client[ make_url( request ) ].delete :authorization => @authtoken
91
+ dump_time( "delete", start_time )
92
+ return resp
93
+ end
94
+
95
+ def make_url( request )
96
+ if @workspace.length != 0
97
+ url = "#{@workspace}/#{request}"
98
+ else
99
+ url = request
100
+ end
101
+ return url
102
+ end
103
+
104
+ def dump_time( what, start_time )
105
+ #puts "#{what}: %0.2f mS" % ( ( Time.now.to_f - start_time ) * 1000 )
106
+ end
107
+ end
@@ -0,0 +1,35 @@
1
+ require 'uuidtools'
2
+
3
+ # coordinate access to stdout...
4
+ Log_sem = Mutex.new
5
+
6
+ def log_message( message )
7
+ Log_sem.synchronize {
8
+ puts "#{Time.now.strftime("%T")}-#{Thread.current.object_id % 10000}: #{message}"
9
+ }
10
+ end
11
+
12
+ def error_message( message )
13
+ Log_sem.synchronize {
14
+ puts( "#{Time.now.strftime("%T")}-#{Thread.current.object_id % 10000}: ERROR ** #{message} **" )
15
+ }
16
+ end
17
+
18
+ def make_guid( )
19
+ UUIDTools::UUID.random_create.to_s.gsub(/-/, '')
20
+ end
21
+
22
+ def get_filelist( dir )
23
+ files = Dir.entries( dir )
24
+ files = files.map { |f| "#{dir}/#{f}"}
25
+ files = files.delete_if { |f| File.directory?( "#{f}") == true } # remove any directories
26
+ return files
27
+ end
28
+
29
+ def standard_fileset( )
30
+ fileset = []
31
+ fileset.push("good-testdata/MD_AmerCh1b.xml")
32
+ fileset.push("good-testdata/MD_Brit_v1CH1a.xml")
33
+ return fileset
34
+
35
+ end
data/lib/juxta.rb ADDED
@@ -0,0 +1,457 @@
1
+ require 'juxta/connection'
2
+ require 'juxta/utilities'
3
+
4
+ class Juxta
5
+
6
+ attr :logging
7
+ attr_reader :connection
8
+
9
+ def initialize( url, workspace )
10
+ @logging = true
11
+ @connection = Connection.new( url, workspace, "", "" )
12
+ end
13
+
14
+ #
15
+ # workspace behavior
16
+ #
17
+ def list_workspaces
18
+ log_message( "Listing workspaces..." ) unless @logging == false
19
+ ws_list = @connection.get( "workspace" )
20
+ return ws_list
21
+ end
22
+
23
+ def create_workspace( workspace_id )
24
+ log_message( "Creating workspace #{workspace_id} ..." ) unless @logging == false
25
+ json = { "name" => workspace_id, "description" => "the description for #{workspace_id}" }
26
+ workspace_id = @connection.post( "workspace", json )
27
+ return workspace_id
28
+ end
29
+
30
+ def delete_workspace( workspace_id )
31
+ return delete_asset( "workspace/#{workspace_id}" )
32
+ end
33
+
34
+ #
35
+ # witness behavior
36
+ #
37
+
38
+ def list_witnesses
39
+ log_message( "Listing witnesses..." ) unless @logging == false
40
+ witness_list = @connection.get( "witness" )
41
+ return witness_list
42
+ end
43
+
44
+ def get_witness( witness_id )
45
+ log_message( "Getting witness #{witness_id}..." ) unless @logging == false
46
+ resp = @connection.get( "witness/#{witness_id}" )
47
+ return resp
48
+ end
49
+
50
+ def rename_witness( witness_id, new_name )
51
+ log_message( "Renaming witness #{witness_id} to #{new_name}..." ) unless @logging == false
52
+ json = { 'name' => new_name }
53
+ resp = @connection.put( "witness/#{witness_id}", json )
54
+ return resp
55
+ end
56
+
57
+ #
58
+ # source behavior
59
+ #
60
+
61
+ def list_sources
62
+ log_message( "Listing sources..." ) unless @logging == false
63
+ source_list = @connection.get( "source" )
64
+ return source_list
65
+ end
66
+
67
+ #
68
+ # xslt behavior
69
+ #
70
+
71
+ def create_xslt( json )
72
+ asset_id = "xslt"
73
+ resp = @connection.post(asset_id, json)
74
+ return resp
75
+ end
76
+
77
+ def list_xslt
78
+ log_message( "Listing xslt..." ) unless @logging == false
79
+ xslt_list = @connection.get( "xslt" )
80
+ return xslt_list
81
+ end
82
+
83
+ #
84
+ # annotation behavior
85
+ #
86
+
87
+ def create_annotation( set_id, witness_id, json )
88
+ asset_id = "set/#{set_id}/witness/#{witness_id}/annotation"
89
+ log_message( "Posting annotations to #{asset_id}..." ) unless @logging == false
90
+ resp = @connection.post(asset_id, json)
91
+ return resp
92
+ end
93
+
94
+ def list_annotations( set_id, witness_id )
95
+ asset_id = "set/#{set_id}/witness/#{witness_id}"
96
+ log_message( "Listing annotations for #{asset_id}..." ) unless @logging == false
97
+ annotation_list = @connection.get( "#{asset_id}/annotation" )
98
+ return annotation_list
99
+ end
100
+
101
+ def get_annotation( annotation_id )
102
+ log_message( "Getting annotation #{annotation_id}..." ) unless @logging == false
103
+ resp = @connection.get( "#{annotation_id}?content=YES" )
104
+ return resp
105
+ end
106
+
107
+ #
108
+ # alignmant behavior
109
+ #
110
+
111
+ def create_alignment( set_id, json )
112
+ asset_id = "set/#{set_id}/alignment"
113
+ log_message( "Posting alignments to #{asset_id}..." ) unless @logging == false
114
+ resp = @connection.post(asset_id, json)
115
+ return resp
116
+ end
117
+
118
+ def list_alignments( set_id )
119
+ asset_id = "set/#{set_id}"
120
+ log_message( "Listing alignments for #{asset_id}..." ) unless @logging == false
121
+ annotation_list = @connection.get( "#{asset_id}/alignment" )
122
+ return annotation_list
123
+ end
124
+
125
+ def get_alignment( set_id, alignment_id )
126
+ asset_id = "set/#{set_id}/alignment/#{alignment_id}"
127
+ log_message( "Getting alignment #{asser_id}..." ) unless @logging == false
128
+ resp = @connection.get( "#{asset_id}" )
129
+ return resp
130
+ end
131
+
132
+ #
133
+ # delete behavior
134
+ #
135
+
136
+ def delete_asset( asset_id )
137
+
138
+ log_message( "Deleting asset #{asset_id} ..." ) unless @logging == false
139
+ resp = @connection.delete( asset_id )
140
+ if resp['status'] == 'FAILED'
141
+ error_message( "failed to delete asset: #{asset_id}")
142
+ return false
143
+ end
144
+ return true
145
+ end
146
+
147
+ def delete_witness( witness_id )
148
+ return delete_asset( "witness/#{witness_id}" )
149
+ end
150
+
151
+ def delete_source( source_id )
152
+ return delete_asset( "source/#{source_id}" )
153
+ end
154
+
155
+ def delete_set( set_id )
156
+ return delete_asset( "set/#{set_id}" )
157
+ end
158
+
159
+ def delete_annotation( set_id, witness_id, annotation_id )
160
+ return delete_asset( "set/#{set_id}/witness/#{witness_id}/annotation/#{annotation_id}" )
161
+ end
162
+
163
+ def delete_alignment( set_id, alignment_id )
164
+ return delete_asset( "set/#{set_id}/alignment/#{alignment_id}" )
165
+ end
166
+
167
+ #
168
+ # upload behavior
169
+ #
170
+
171
+ def upload_source( file_name )
172
+
173
+ id = make_guid()
174
+ log_message( "Uploading #{file_name} as #{id} ..." ) unless @logging == false
175
+ src_id = @connection.upload_file( id, "text/xml", open( file_name ))
176
+
177
+ srcs = @connection.get("source")
178
+ srcs.each do |src|
179
+ if src['id'] == src_id
180
+ log_message( "successfully uploaded file: #{file_name} (#{src['name']})" ) unless @logging == false
181
+ return src_id
182
+ end
183
+
184
+ end
185
+
186
+ error_message( "failed to upload file: #{file_name}")
187
+ return nil
188
+ end
189
+
190
+ #
191
+ # transform behavior
192
+ #
193
+
194
+ def transform_source( file_id )
195
+
196
+ log_message( "Transforming #{file_id} ..." ) unless @logging == false
197
+ json = { 'source' => file_id, 'finalName' => make_guid() }
198
+ wit_id = @connection.post( "transform", json )
199
+ return wit_id
200
+ end
201
+
202
+ #
203
+ # witness set behavior
204
+ #
205
+
206
+ def list_sets
207
+ log_message( "Listing sets..." ) unless @logging == false
208
+ set_list = @connection.get( "set" )
209
+ return set_list
210
+ end
211
+
212
+ def make_set( witness_ids )
213
+ log_message( "Creating witness set ..." ) unless @logging == false
214
+ set = { 'name' => make_guid(), 'witnesses' => witness_ids }
215
+ set_id = @connection.post( "set", set )
216
+ return set_id
217
+ end
218
+
219
+ def async_tokenize_set( set_id )
220
+ log_message( "Tokenizing witness set #{set_id}..." ) unless @logging == false
221
+ task_id = @connection.post( "set/#{set_id}/tokenize", nil)
222
+ return task_id
223
+ end
224
+
225
+ def tokenize_set( set_id )
226
+ task_id = async_tokenize_set( set_id )
227
+ while true do
228
+ sleep(2.0)
229
+ resp = get_status( task_id )
230
+ case resp
231
+ when 'COMPLETE'
232
+ return true
233
+
234
+ when 'FAILED'
235
+ error_message( "failed to tokenize set: #{set_id}")
236
+ return false
237
+ end
238
+ end
239
+ end
240
+
241
+ def async_collate_set( set_id )
242
+ log_message( "Collating witness set #{set_id}..." ) unless @logging == false
243
+ task_id = @connection.post( "set/#{set_id}/collate", nil)
244
+ return task_id
245
+ end
246
+
247
+ def collate_set( set_id )
248
+ task_id = async_collate_set( set_id )
249
+ while true do
250
+ sleep(2.0)
251
+ resp = get_status( task_id )
252
+ case resp
253
+ when 'COMPLETE'
254
+ return true
255
+
256
+ when 'FAILED'
257
+ error_message( "failed to tokenize set: #{set_id}")
258
+ return false
259
+ end
260
+ end
261
+ end
262
+
263
+ #
264
+ # Search behavior
265
+ #
266
+ def search( query )
267
+ log_message( "Searching for #{query}..." ) unless @logging == false
268
+ resp = @connection.get("search?q=#{query}")
269
+ return resp
270
+ end
271
+
272
+ #
273
+ # task status behavior
274
+ #
275
+
276
+ def get_status( task_id )
277
+ log_message( "Getting status for #{task_id}..." ) unless @logging == false
278
+ resp = @connection.get("task/#{task_id}/status")
279
+ return resp['status']
280
+ end
281
+
282
+ #
283
+ # get asset behavior
284
+ #
285
+
286
+ def async_get_as_html( asset_id )
287
+ log_message( "Getting html #{asset_id}..." ) unless @logging == false
288
+ resp = @connection.get_html( asset_id )
289
+ if resp.include?('RENDERING') == true
290
+ return resp.split( ' ' )[ 1 ]
291
+ end
292
+ return nil
293
+ end
294
+
295
+ def get_as_html( asset_id )
296
+ task_id = async_get_as_html( asset_id )
297
+ if task_id.nil? == false
298
+ while true do
299
+ sleep(2.0)
300
+ resp = get_status( task_id )
301
+ case resp
302
+ when 'COMPLETE'
303
+ return @connection.get_html( asset_id )
304
+
305
+ when 'FAILED'
306
+ error_message( "failed to get html asset: #{asset_id}")
307
+ return false
308
+ end
309
+ end
310
+ end
311
+ return resp
312
+ end
313
+
314
+ def async_get_as_json( asset_id )
315
+ log_message( "Getting json #{asset_id}..." ) unless @logging == false
316
+ resp = @connection.get( asset_id )
317
+ if resp['status'] == 'RENDERING'
318
+ return resp['taskId']
319
+ end
320
+ return nil
321
+ end
322
+
323
+ def get_as_json( asset_id )
324
+ task_id = async_get_as_json( asset_id )
325
+ if task_id.nil? == false
326
+ while true do
327
+ sleep(2.0)
328
+ resp = get_status( task_id )
329
+ case resp
330
+ when 'COMPLETE'
331
+ return @connection.get( asset_id )
332
+
333
+ when 'FAILED'
334
+ error_message( "failed to get json asset: #{asset_id}")
335
+ return false
336
+ end
337
+ end
338
+ end
339
+ return false
340
+ end
341
+
342
+ def get_info( asset_id )
343
+ log_message( "Getting info for #{asset_id}..." ) unless @logging == false
344
+ resp = @connection.get( "#{asset_id}/info" )
345
+ return resp
346
+ end
347
+
348
+ def get_usage( asset_id )
349
+ log_message( "Getting usage for #{asset_id}..." ) unless @logging == false
350
+ resp = @connection.get( "#{asset_id}/usage" )
351
+ return resp
352
+ end
353
+
354
+ def get_xslt( asset_id )
355
+ log_message( "Getting xslt #{asset_id}..." ) unless @logging == false
356
+ resp = @connection.get_html( "xslt/#{asset_id}" )
357
+ return resp
358
+ end
359
+
360
+ #
361
+ # TEI Parallel segmentation export
362
+ #
363
+
364
+ def export( set_id, base_id )
365
+ log_message( "Exporting set #{set_id}..." ) unless @logging == false
366
+ resp = @connection.get_xml( "set/#{set_id}/export?mode=teips&base=#{base_id}&sync" )
367
+ return resp
368
+ end
369
+
370
+ #
371
+ # Edition starter
372
+ #
373
+
374
+ def edition( set_id, title, line_freq, base_id, wit_siglum_map )
375
+ data = {}
376
+ data['title'] = title
377
+ data['lineFrequency'] = line_freq
378
+ data['numberBlankLines'] = false
379
+ witnesses = []
380
+ wit_siglum_map.each do |id, siglum|
381
+ wit = {"id"=> id, "include"=>true, "base"=>(id == base_id), "siglum"=>siglum}
382
+ witnesses << wit
383
+ end
384
+ data['witnesses'] = witnesses
385
+
386
+ log_message( "Exporting edition for set #{set_id}..." ) unless @logging == false
387
+ resp = @connection.post("set/#{set_id}/edition", data)
388
+
389
+ # wait for task to complete
390
+ parsed = JSON.parse(resp)
391
+ token = parsed['token']
392
+ task = parsed['taskId']
393
+
394
+ while true do
395
+ sleep(2.0)
396
+ resp = get_status( task )
397
+ puts resp
398
+ case resp
399
+ when 'COMPLETE'
400
+ break
401
+
402
+ when 'FAILED'
403
+ error_message( "failed to tokenize set: #{set_id}")
404
+ return false
405
+ end
406
+ end
407
+
408
+ # now request the HTML edition and pass along the token
409
+ html = @connection.get_html("set/#{set_id}/edition?token=#{token}&format=html")
410
+ return html
411
+
412
+ end
413
+
414
+ #
415
+ # convience methods
416
+ #
417
+
418
+ def create_witness_set( file_list )
419
+
420
+ src_ids = []
421
+ wit_ids = []
422
+
423
+ file_list.each do |file|
424
+
425
+ # create source
426
+ src_id = upload_source( file )
427
+ src_ids.push( src_id )
428
+
429
+ # xform to witness
430
+ wit_id = transform_source( src_id )
431
+ wit_ids.push( wit_id )
432
+
433
+ end
434
+
435
+ # create set from witnesses
436
+ set_id = make_set( wit_ids )
437
+
438
+ return src_ids, wit_ids, set_id
439
+ end
440
+
441
+ def destroy_witness_set( source_list, witness_list )
442
+
443
+ witness_list.each do |wit_id|
444
+ status = delete_witness( wit_id )
445
+ return false unless status == true
446
+ end
447
+
448
+ source_list.each do |src_id|
449
+ status = delete_source( src_id )
450
+ return false unless status == true
451
+ end
452
+
453
+ return true
454
+ end
455
+
456
+
457
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: juxta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Nick Laiacona
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.7.7
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.7.7
41
+ - !ruby/object:Gem::Dependency
42
+ name: OptionParser
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.5.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.5.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: uuidtools
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.1.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 2.1.3
69
+ description: JuxtaWS Ruby bindings
70
+ email: nick@performantsoftware.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/juxta.rb
76
+ - lib/juxta/connection.rb
77
+ - lib/juxta/utilities.rb
78
+ homepage: http://rubygems.org/gems/juxta
79
+ licenses: []
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.0.3
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: JuxtaWS Ruby bindings
101
+ test_files: []
102
+ has_rdoc: