juxta 0.1.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.
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: