juxta 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9537d609ce2a9506964a49b399dce7a4f54b4cd7
4
- data.tar.gz: be87bc4c13083793d5a0afdf3cb57edec7ae66db
3
+ metadata.gz: 59a37cdbefe64c30540822a438e0f71e95ca62e2
4
+ data.tar.gz: 7e077e5a91a479abb46c153f8e72bf4b620fcd9d
5
5
  SHA512:
6
- metadata.gz: d11ec8282f12f0656d0eece0923ffbdfa33370f049a855a4af93e061384574e0ed0a1648ae58f0cbe201626a58978a293e4fe685df9dd7e787298ddcf428185d
7
- data.tar.gz: 013597f634a633718c0fbc9cc2f7df724fc5014b5a3f4b27cb73b205ac282b41ab70b0525b69725908e356cabeb3ce9fde51604f3bf68ecbf5125cf502c2ec15
6
+ metadata.gz: ac2c27e52a38ce5e8a1b4797dc7e1fd443e16d3f650b1cc636753ca6baecc61bf4048f5d787990d43b343e9a05dca6f37cb1183ea14d6affc85cca71ee5033d0
7
+ data.tar.gz: 75b3e08ef1486e2dbc36098bca5981146997e0d1540402a3e7908a0005b0b55088bc82231835d50533d4818d98ebcbdc9455a7dd7a2c4576826d88043e986bd4
data/lib/juxta.rb CHANGED
@@ -1,52 +1,130 @@
1
1
  require 'juxta/connection'
2
2
  require 'juxta/utilities'
3
3
 
4
+ # Author:: Nick Laiacona (mailto:nick@performantsoftware.com), Lou Foster, Dave Goldstein
5
+ # Copyright:: Copyright (c) 2013
6
+ # License:: Distributes under Apache License
7
+
8
+ # This class provides the Ruby interface to the JuxtaWS REST web service.
4
9
  class Juxta
5
10
 
6
- attr :logging
11
+ # Set to true to enable logging.
12
+ attr_accessor :logging
13
+
14
+ # The connection object for this Juxta instance.
7
15
  attr_reader :connection
8
16
 
9
- def initialize( url, workspace )
10
- @logging = true
11
- @connection = Connection.new( url, workspace, "", "" )
12
- end
13
-
17
+ # Initialize a Juxta interface with optional authentication.
18
+ #
19
+ # @param [String] URL of the JuxtaWS server to connect to.
20
+ # @param [String] username if server require authentication.
21
+ # @param [String] password if server require authentication.
22
+ # @return [Connection]
23
+ def initialize( url, username=nil, password=nil )
24
+ @logging = false
25
+ @connection = Connection.new( url, username, password )
26
+ end
27
+
28
+ # The name of the currently selected workspace. Default is "public".
29
+ # @return [String] The name of the current workspace.
30
+ def workspace()
31
+ @connection.workspace
32
+ end
33
+
34
+ # Select a workspace to operate in.
14
35
  #
15
- # workspace behavior
36
+ # @param [String] workspace_name this is the name of the workspace.
37
+ # @return [Object] true if selection suceeded, false otherwise.
38
+ def select_workspace(workspace_name)
39
+ workspaces = list_workspaces()
40
+ workspace_names = workspaces.map { |workspace|
41
+ workspace["name"]
42
+ }
43
+
44
+ if workspace_names.include? workspace_name
45
+ @connection.workspace = workspace_name
46
+ return true
47
+ else
48
+ return false
49
+ end
50
+ end
51
+
52
+ # Lists the workspaces available on this server.
16
53
  #
54
+ # @return [Array] List of workspace names.
17
55
  def list_workspaces
18
56
  log_message( "Listing workspaces..." ) unless @logging == false
19
- ws_list = @connection.get( "workspace" )
57
+ ws_list = @connection.get( "workspace", false )
20
58
  return ws_list
21
59
  end
22
60
 
61
+ # Create a new workspace.
62
+ #
63
+ # @param [String] Name of the workspace to create. Must be unique to this server.
64
+ # @return [String] If successful, the created workspace's id.
23
65
  def create_workspace( workspace_id )
24
66
  log_message( "Creating workspace #{workspace_id} ..." ) unless @logging == false
25
67
  json = { "name" => workspace_id, "description" => "the description for #{workspace_id}" }
26
- workspace_id = @connection.post( "workspace", json )
68
+ workspace_id = @connection.post( "workspace", json, false )
27
69
  return workspace_id
28
70
  end
29
71
 
72
+ # Delete a new workspace and everything in it.
73
+ #
74
+ # @param [String] Name of the workspace to delete.
75
+ # @return [Object] True if successful, false otherwise.
30
76
  def delete_workspace( workspace_id )
31
- return delete_asset( "workspace/#{workspace_id}" )
77
+ log_message( "Deleting workspace #{workspace_id} ..." ) unless @logging == false
78
+ resp = @connection.delete( "workspace/#{workspace_id}", false )
79
+ if resp['status'] == 'FAILED'
80
+ error_message( "failed to delete asset: #{asset_id}")
81
+ return false
82
+ end
83
+ return true
32
84
  end
33
85
 
86
+ # List the witnesses in this workspace. Witnesses are the transformed version of the sources.
34
87
  #
35
- # witness behavior
36
- #
37
-
88
+ # @return [Array] An array of hashes with summary information about each witness.
38
89
  def list_witnesses
39
90
  log_message( "Listing witnesses..." ) unless @logging == false
40
- witness_list = @connection.get( "witness" )
41
- return witness_list
91
+ @connection.get( "witness" )
42
92
  end
43
93
 
94
+ # Get full information about a given witness.
95
+ #
96
+ # @param [String,Integer] witness_id Identifier of the witness to retrieve.
97
+ # @return [Hash] A hash with complete information about the witness, including full text.
44
98
  def get_witness( witness_id )
45
99
  log_message( "Getting witness #{witness_id}..." ) unless @logging == false
46
- resp = @connection.get( "witness/#{witness_id}" )
47
- return resp
100
+ @connection.get( "witness/#{witness_id}" )
101
+ end
102
+
103
+ # Get full information about a given source.
104
+ #
105
+ # @param [String,Integer] source_id Identifier of the source to retrieve.
106
+ # @return [Hash] A hash with complete information about the source, including full text.
107
+ def get_source( source_id )
108
+ log_message( "Getting source #{source_id}..." ) unless @logging == false
109
+ @connection.get( "source/#{source_id}" )
110
+ end
111
+
112
+ # Retrieve a text fragment from a given witness.
113
+ #
114
+ # @param [String,Integer] witness_id Identifier of the witness.
115
+ # @param [String,Integer] start_point Starting offset of the fragment.
116
+ # @param [String,Integer] end_point Ending offset of the fragment.
117
+ # @return [String] A string containing the text fragment, if found.
118
+ def get_witness_fragment( witness_id, start_point, end_point )
119
+ log_message( "Getting witness #{witness_id}..." ) unless @logging == false
120
+ @connection.get_html( "witness/#{witness_id}.txt?range=#{start_point},#{end_point}" )
48
121
  end
49
122
 
123
+ # Change the name of the witness.
124
+ #
125
+ # @param [String,Integer] witness_id Identifier of the witness.
126
+ # @param [String,Integer] new_name The new name for the witness.
127
+ # @return [Hash]
50
128
  def rename_witness( witness_id, new_name )
51
129
  log_message( "Renaming witness #{witness_id} to #{new_name}..." ) unless @logging == false
52
130
  json = { 'name' => new_name }
@@ -54,43 +132,60 @@ class Juxta
54
132
  return resp
55
133
  end
56
134
 
135
+ # List the sources in this workspace.
57
136
  #
58
- # source behavior
59
- #
60
-
137
+ # @return [Array] An array of hashes with summary information about each source.
61
138
  def list_sources
62
139
  log_message( "Listing sources..." ) unless @logging == false
63
140
  source_list = @connection.get( "source" )
64
141
  return source_list
65
142
  end
66
143
 
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
144
+ # Create a new XSLT on the server.
145
+ #
146
+ # @param [String] name A display name for this XSLT.
147
+ # @param [String] xslt XML string for the XSLT.
148
+ # @return [String] An identifier for the newly created XSLT.
149
+ def create_xslt( name, xslt )
150
+ @connection.post("xslt", {:name=>name, :xslt=>xslt } )
75
151
  end
76
152
 
153
+ # List the XSL stylesheets in this workspace.
154
+ #
155
+ # @return [Array] An array of hashes with summary information about each XSLT.
77
156
  def list_xslt
78
157
  log_message( "Listing xslt..." ) unless @logging == false
79
158
  xslt_list = @connection.get( "xslt" )
80
159
  return xslt_list
81
160
  end
82
-
83
- #
84
- # annotation behavior
161
+
162
+ # Get full information about a given comparison set.
85
163
  #
164
+ # @param [String,Integer] set_id Identifier of a comparison set.
165
+ # @return [Hash] A hash with complete information about the comparison set, including a list of witnesses.
166
+ def get_set( set_id )
167
+ log_message( "Getting set #{set_id}..." ) unless @logging == false
168
+ @connection.get( "set/#{set_id}" )
169
+ end
86
170
 
87
- def create_annotation( set_id, witness_id, json )
171
+ # Create new annotations, on a given witness in a comparison set.
172
+ #
173
+ # @param [String,Integer] set_id Identifier of a comparison set.
174
+ # @param [String,Integer] witness_id Identifier of a witness.
175
+ # @param [Array] json An array of hashes defining annotations. See JuxtaWS API docs for hash format.
176
+ # @return [String] A JSON array of annotation identifiers created.
177
+ def create_annotations( set_id, witness_id, json )
88
178
  asset_id = "set/#{set_id}/witness/#{witness_id}/annotation"
89
179
  log_message( "Posting annotations to #{asset_id}..." ) unless @logging == false
90
180
  resp = @connection.post(asset_id, json)
91
181
  return resp
92
182
  end
93
183
 
184
+ # List the annotations applied to a given witness in a comparison set.
185
+ #
186
+ # @param [String,Integer] set_id Identifier of a comparison set.
187
+ # @param [String,Integer] witness_id Identifier of a witness.
188
+ # @return [Array] An array of hashes containing annotation data.
94
189
  def list_annotations( set_id, witness_id )
95
190
  asset_id = "set/#{set_id}/witness/#{witness_id}"
96
191
  log_message( "Listing annotations for #{asset_id}..." ) unless @logging == false
@@ -98,76 +193,105 @@ class Juxta
98
193
  return annotation_list
99
194
  end
100
195
 
101
- def get_annotation( annotation_id )
196
+ # Retrieve information about a specific annotation.
197
+ #
198
+ # @param [String,Integer] set_id Identifier of a comparison set.
199
+ # @param [String,Integer] witness_id Identifier of a witness.
200
+ # @param [String,Integer] annotation_id Identifier of the specified annotation.
201
+ # @return [Hash] A hash containing the annotation data.
202
+ def get_annotation( set_id, witness_id, annotation_id )
102
203
  log_message( "Getting annotation #{annotation_id}..." ) unless @logging == false
103
- resp = @connection.get( "#{annotation_id}?content=YES" )
104
- return resp
204
+ @connection.get( "set/#{set_id}/witness/#{witness_id}/annotation/#{annotation_id}?content=YES" )
105
205
  end
106
206
 
207
+ # Create new alignments, which are associations of annotations in a comparison set.
107
208
  #
108
- # alignmant behavior
109
- #
110
-
111
- def create_alignment( set_id, json )
209
+ # @param [String,Integer] set_id Identifier of a comparison set.
210
+ # @param [Array] json An array of hashes defining alignments. See JuxtaWS API docs for hash format.
211
+ # @return [String] A JSON array of alignment identifiers created.
212
+ def create_alignments( set_id, json )
112
213
  asset_id = "set/#{set_id}/alignment"
113
214
  log_message( "Posting alignments to #{asset_id}..." ) unless @logging == false
114
215
  resp = @connection.post(asset_id, json)
115
216
  return resp
116
217
  end
117
218
 
219
+ # List the alignments for a given comparison set.
220
+ #
221
+ # @param [String,Integer] set_id Identifier of a comparison set.
222
+ # @return [Array] An array of hashes containing alignment data.
118
223
  def list_alignments( set_id )
119
224
  asset_id = "set/#{set_id}"
120
225
  log_message( "Listing alignments for #{asset_id}..." ) unless @logging == false
121
- annotation_list = @connection.get( "#{asset_id}/alignment" )
122
- return annotation_list
226
+ @connection.get( "#{asset_id}/alignment" )
123
227
  end
124
228
 
229
+ # Get full information about a given alignment.
230
+ #
231
+ # @param [String,Integer] set_id Identifier of a comparison set.
232
+ # @param [String,Integer] alignment_id Identifier of an alignment.
233
+ # @return [Hash] A hash with complete information about the alignment, including text fragments.
125
234
  def get_alignment( set_id, alignment_id )
126
235
  asset_id = "set/#{set_id}/alignment/#{alignment_id}"
127
236
  log_message( "Getting alignment #{asser_id}..." ) unless @logging == false
128
- resp = @connection.get( "#{asset_id}" )
129
- return resp
237
+ @connection.get( "#{asset_id}" )
130
238
  end
131
239
 
240
+ # Delete the specified witness.
132
241
  #
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
-
242
+ # @param [String,Integer] witness_id Identifier of the witness.
243
+ # @return [Object] True if successful, false otherwise.
147
244
  def delete_witness( witness_id )
148
245
  return delete_asset( "witness/#{witness_id}" )
149
246
  end
150
247
 
248
+ # Delete the specified source.
249
+ #
250
+ # @param [String,Integer] source_id Identifier of the source.
251
+ # @return [Object] True if successful, false otherwise.
151
252
  def delete_source( source_id )
152
253
  return delete_asset( "source/#{source_id}" )
153
254
  end
154
255
 
256
+ # Delete the specified XSLT.
257
+ #
258
+ # @param [String,Integer] xslt_id Identifier of the XSLT.
259
+ # @return [Object] True if successful, false otherwise.
260
+ def delete_xslt( xslt_id )
261
+ return delete_asset( "xslt/#{xslt_id}" )
262
+ end
263
+
264
+ # Delete the specified comparison set.
265
+ #
266
+ # @param [String,Integer] set_id Identifier of the comparison set.
267
+ # @return [Object] True if successful, false otherwise.
155
268
  def delete_set( set_id )
156
269
  return delete_asset( "set/#{set_id}" )
157
270
  end
158
271
 
272
+ # Delete the specified annotation from a given comparison set witness.
273
+ #
274
+ # @param [String,Integer] set_id Identifier of the comparison set.
275
+ # @param [String,Integer] witness_id Identifier of the witness.
276
+ # @param [String,Integer] annotation_id Identifier of the annotation.
277
+ # @return [Object] True if successful, false otherwise.
159
278
  def delete_annotation( set_id, witness_id, annotation_id )
160
279
  return delete_asset( "set/#{set_id}/witness/#{witness_id}/annotation/#{annotation_id}" )
161
280
  end
162
281
 
282
+ # Delete the specified alignment from a given comparison set.
283
+ #
284
+ # @param [String,Integer] set_id Identifier of the comparison set.
285
+ # @param [String,Integer] alignment_id Identifier of a given alignment.
286
+ # @return [Object] True if successful, false otherwise.
163
287
  def delete_alignment( set_id, alignment_id )
164
288
  return delete_asset( "set/#{set_id}/alignment/#{alignment_id}" )
165
289
  end
166
290
 
291
+ # Upload a file from local disk to the server.
167
292
  #
168
- # upload behavior
169
- #
170
-
293
+ # @param [String] file_name Local path to the file to upload.
294
+ # @return [String] Identifier of uploaded source if successful, otherwise nil.
171
295
  def upload_source( file_name )
172
296
 
173
297
  id = make_guid()
@@ -187,28 +311,57 @@ class Juxta
187
311
  return nil
188
312
  end
189
313
 
314
+ # Command the server to create source files from the provided array of hashes.
190
315
  #
191
- # transform behavior
316
+ # @param [Array] source_array Array of hashes describing the sources to be created. See JuxtaWS API for format.
317
+ # @return [Array] Identifiers of the sources if successful, otherwise nil.
318
+ def create_sources( source_array )
319
+ log_message( "Creating sources from JSON data..." ) unless @logging == false
320
+ resp = @connection.post( "source", source_array )
321
+ JSON.parse(resp)
322
+ end
323
+
324
+ # Command the server to obtain an XML source file from the specified URL.
192
325
  #
326
+ # @param [String] url URL of the XML source file to grab.
327
+ # @return [String] Identifier of the obtained source if successful, otherwise nil.
328
+ def obtain_source_from_url( url )
329
+ id = make_guid()
330
+ log_message( "Downloading #{url} as #{id} ..." ) unless @logging == false
331
+ resp = @connection.post( "source", [{name: id, type: 'url', contentType: 'xml', data: url}] )
332
+ parsed = JSON.parse(resp)
333
+ if parsed.length > 0
334
+ parsed[0]
335
+ else
336
+ nil
337
+ end
338
+ end
193
339
 
194
- def transform_source( file_id )
340
+ # Transform the specified source into a witness using the associated XSLT.
341
+ #
342
+ # @param [String,Integer] source_id Identifier of the source.
343
+ # @return [String] Identifier of the resultant witness.
344
+ def transform_source( source_id )
195
345
 
196
- log_message( "Transforming #{file_id} ..." ) unless @logging == false
197
- json = { 'source' => file_id, 'finalName' => make_guid() }
346
+ log_message( "Transforming #{source_id} ..." ) unless @logging == false
347
+ json = { 'source' => source_id, 'finalName' => make_guid() }
198
348
  wit_id = @connection.post( "transform", json )
199
349
  return wit_id
200
350
  end
201
351
 
352
+ # List the comparison sets in this workspace.
202
353
  #
203
- # witness set behavior
204
- #
205
-
354
+ # @return [Array] An array of hashes with summary information about each comparison set.
206
355
  def list_sets
207
356
  log_message( "Listing sets..." ) unless @logging == false
208
357
  set_list = @connection.get( "set" )
209
358
  return set_list
210
359
  end
211
360
 
361
+ # Group the specified witnesses into a new comparison set.
362
+ #
363
+ # @param [Array] witness_ids An array of witness identifiers.
364
+ # @return [String] Identifier of the resultant comparison set.
212
365
  def make_set( witness_ids )
213
366
  log_message( "Creating witness set ..." ) unless @logging == false
214
367
  set = { 'name' => make_guid(), 'witnesses' => witness_ids }
@@ -216,12 +369,21 @@ class Juxta
216
369
  return set_id
217
370
  end
218
371
 
372
+ # Tokenize the specified comparison set. Returns
373
+ # immediately, use get_status(task_id) to check the status of tokenization. Tokens are
374
+ # accessible as annotations of type 'token'.
375
+ #
376
+ # @param [String,Integer] set_id Identifier of the comparison set.
377
+ # @return [String] An identifier for the server task.
219
378
  def async_tokenize_set( set_id )
220
379
  log_message( "Tokenizing witness set #{set_id}..." ) unless @logging == false
221
- task_id = @connection.post( "set/#{set_id}/tokenize", nil)
222
- return task_id
380
+ @connection.post( "set/#{set_id}/tokenize", nil)
223
381
  end
224
382
 
383
+ # Tokenize the specified comparison set. Tokens are accessible as annotations of type 'token'.
384
+ #
385
+ # @param [String,Integer] set_id Identifier of the comparison set.
386
+ # @return [Object] True if successful, false otherwise.
225
387
  def tokenize_set( set_id )
226
388
  task_id = async_tokenize_set( set_id )
227
389
  while true do
@@ -238,12 +400,20 @@ class Juxta
238
400
  end
239
401
  end
240
402
 
403
+ # Collate the specified comparison set. Returns immediately, use
404
+ # get_status(task_id) to check the status of collation.
405
+ #
406
+ # @param [String,Integer] set_id Identifier of the comparison set.
407
+ # @return [String] An identifier for the server task.
241
408
  def async_collate_set( set_id )
242
409
  log_message( "Collating witness set #{set_id}..." ) unless @logging == false
243
- task_id = @connection.post( "set/#{set_id}/collate", nil)
244
- return task_id
410
+ @connection.post( "set/#{set_id}/collate", nil)
245
411
  end
246
412
 
413
+ # Collate the specified comparison set and wait for the response from server.
414
+ #
415
+ # @param [String,Integer] set_id Identifier of the target comparison set.
416
+ # @return [Object] True if successful, false otherwise.
247
417
  def collate_set( set_id )
248
418
  task_id = async_collate_set( set_id )
249
419
  while true do
@@ -260,29 +430,31 @@ class Juxta
260
430
  end
261
431
  end
262
432
 
433
+ # Search the current workspace for the specified phrase. Server must have search indexing enabled.
263
434
  #
264
- # Search behavior
265
- #
435
+ # @param [String] query The phrase to search for within the workspace.
436
+ # @return [Array] An array of objects that detail the search results.
266
437
  def search( query )
267
438
  log_message( "Searching for #{query}..." ) unless @logging == false
268
439
  resp = @connection.get("search?q=#{query}")
269
440
  return resp
270
441
  end
271
442
 
443
+ # Retrieve the status of a server side task.
272
444
  #
273
- # task status behavior
274
- #
275
-
445
+ # @param [String,Integer] task_id An identifier for a server side task.
446
+ # @return [String] A status code. Possible codes are: PENDING, PROCESSING, COMPLETE, CANCEL_REQUESTED, CANCELLED, FAILED.
276
447
  def get_status( task_id )
277
448
  log_message( "Getting status for #{task_id}..." ) unless @logging == false
278
449
  resp = @connection.get("task/#{task_id}/status")
279
450
  return resp['status']
280
451
  end
281
452
 
453
+ # Retrieve the HTML for a given asset. Returns immediately, use
454
+ # get_status(task_id) to check status.
282
455
  #
283
- # get asset behavior
284
- #
285
-
456
+ # @param [String, Integer] asset_id Identifier of a given asset.
457
+ # @return [String] Task_id for the checking status or nil if the asset can not be retrieved.
286
458
  def async_get_as_html( asset_id )
287
459
  log_message( "Getting html #{asset_id}..." ) unless @logging == false
288
460
  resp = @connection.get_html( asset_id )
@@ -292,6 +464,50 @@ class Juxta
292
464
  return nil
293
465
  end
294
466
 
467
+ # Creates an asset identifier for the heatmap of a given base text in a comparison set.
468
+ # Use get_as_html or get_as_json to retrieve the asset.
469
+ #
470
+ # @param [String, Integer] set_id Identifier of a comparison set.
471
+ # @param [String, Integer] base_id Identifier of a base text.
472
+ # @return [String] Asset identifier for the heatmap visualization of the given base text.
473
+ def get_heatmap_asset_id( set_id, base_id )
474
+ "set/#{set_id}/view?mode=heatmap&base=#{base_id}"
475
+ end
476
+
477
+ # Creates an asset identifier for a side-by-side comparison of two witnesses in a comparison set.
478
+ # Use get_as_html or get_as_json to retrieve the asset.
479
+ #
480
+ # @param [String, Integer] set_id Identifier of a comparison set.
481
+ # @param [String, Integer] witness_a Identifier of the first witness.
482
+ # @param [String, Integer] witness_b Identifier of the second witness.
483
+ # @return [String] Asset identifier for the side-by-side visualization.
484
+ def get_side_by_side_asset_id( set_id, witness_a, witness_b )
485
+ "set/#{set_id}/view?mode=sidebyside&docs=#{witness_a},#{witness_b}"
486
+ end
487
+
488
+ # Creates a URL for the heatmap of a given base text in a comparison set.
489
+ #
490
+ # @param [String, Integer] set_id Identifier of a comparison set.
491
+ # @param [String, Integer] base_id Identifier of a base text.
492
+ # @return [String] URL to the heatmap visualization of the given base text.
493
+ def get_heatmap_url( set_id, base_id )
494
+ @connection.make_full_url( get_heatmap_asset_id(set_id,base_id) )
495
+ end
496
+
497
+ # Creates a URL for a side-by-side comparison of two witnesses in a comparison set.
498
+ #
499
+ # @param [String, Integer] set_id Identifier of a comparison set.
500
+ # @param [String, Integer] witness_a Identifier of the first witness.
501
+ # @param [String, Integer] witness_b Identifier of the second witness.
502
+ # @return [String] URL to the side-by-side visualization.
503
+ def get_side_by_side_url( set_id, witness_a, witness_b )
504
+ @connection.make_full_url( get_side_by_side_asset_id(set_id, witness_a, witness_b) )
505
+ end
506
+
507
+ # Retrieve the HTML for a given asset, waiting for server to prepare asset if necessary.
508
+ #
509
+ # @param [String, Integer] asset_id Identifier of a given asset.
510
+ # @return [Object] HTML for the asset or false if the asset could not be retrieved.
295
511
  def get_as_html( asset_id )
296
512
  task_id = async_get_as_html( asset_id )
297
513
  if task_id.nil? == false
@@ -311,6 +527,11 @@ class Juxta
311
527
  return resp
312
528
  end
313
529
 
530
+ # Retrieve the JSON for a given asset. Returns immediately, use
531
+ # get_status(task_id) to check status.
532
+ #
533
+ # @param [String, Integer] asset_id Identifier of a given asset.
534
+ # @return [String] Task_id for the checking status or nil if the asset can not be retrieved.
314
535
  def async_get_as_json( asset_id )
315
536
  log_message( "Getting json #{asset_id}..." ) unless @logging == false
316
537
  resp = @connection.get( asset_id )
@@ -320,6 +541,10 @@ class Juxta
320
541
  return nil
321
542
  end
322
543
 
544
+ # Retrieve the JSON for a given asset, waiting for server to prepare asset if necessary.
545
+ #
546
+ # @param [String, Integer] asset_id Identifier of a given asset.
547
+ # @return [Object] JSON for the asset or false if the asset could not be retrieved.
323
548
  def get_as_json( asset_id )
324
549
  task_id = async_get_as_json( asset_id )
325
550
  if task_id.nil? == false
@@ -339,82 +564,28 @@ class Juxta
339
564
  return false
340
565
  end
341
566
 
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
-
567
+ # Get the specified XSLT resource from server.
568
+ #
569
+ # @param [String,Integer] asset_id The identifier of the specified XSLT.
570
+ # @return [String] XML for the specified XSLT.
354
571
  def get_xslt( asset_id )
355
572
  log_message( "Getting xslt #{asset_id}..." ) unless @logging == false
356
- resp = @connection.get_html( "xslt/#{asset_id}" )
357
- return resp
573
+ @connection.get_html( "xslt/#{asset_id}" )
358
574
  end
359
575
 
360
- #
361
576
  # TEI Parallel segmentation export
362
- #
363
-
364
577
  def export( set_id, base_id )
365
578
  log_message( "Exporting set #{set_id}..." ) unless @logging == false
366
579
  resp = @connection.get_xml( "set/#{set_id}/export?mode=teips&base=#{base_id}&sync" )
367
580
  return resp
368
581
  end
369
582
 
583
+ # Create an uncollated comparison set from an array of local files.
370
584
  #
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
-
585
+ # @param [Array] file_list An array of paths to local files to upload.
586
+ # @return [Array] Array of resultant source identifiers.
587
+ # @return [Array] Array of resultant witness identifiers.
588
+ # @return [String] The identifier for the resultant comparison set.
418
589
  def create_witness_set( file_list )
419
590
 
420
591
  src_ids = []
@@ -437,21 +608,19 @@ class Juxta
437
608
 
438
609
  return src_ids, wit_ids, set_id
439
610
  end
611
+
612
+ protected
613
+
614
+ # Helper method for deleting sets, sources, witnesses.
615
+ def delete_asset( asset_id )
440
616
 
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
617
+ log_message( "Deleting asset #{asset_id} ..." ) unless @logging == false
618
+ resp = @connection.delete( asset_id )
619
+ if resp['status'] == 'FAILED'
620
+ error_message( "failed to delete asset: #{asset_id}")
621
+ return false
451
622
  end
452
-
453
623
  return true
454
624
  end
455
625
 
456
-
457
626
  end
@@ -5,14 +5,14 @@ require 'base64'
5
5
  class Connection
6
6
 
7
7
  attr_reader :url
8
- attr_reader :workspace
8
+ attr_accessor :workspace
9
9
 
10
- def initialize( url, workspace, username, password )
10
+ def initialize( url, username=nil, password=nil )
11
11
 
12
12
  @authtoken = "Basic #{Base64.encode64("#{username}:#{password}")}"
13
- @url = "#{url}/juxta"
14
- @workspace = workspace
15
-
13
+ @url = url
14
+ @workspace = "public"
15
+
16
16
  @timeout = 600 # 10 minute get timeout...
17
17
  @open_timeout = 600 # 10 minute post timeout
18
18
 
@@ -32,9 +32,10 @@ class Connection
32
32
  return json['version']
33
33
  end
34
34
 
35
- def get( request )
35
+ def get( request, in_workspace=true )
36
36
  start_time = Time.now.to_f
37
- resp = @rest_client[ make_url( request ) ].get :content_type => "application/json", :accept=>'application/json', :authorization => @authtoken
37
+ url = in_workspace ? make_url( request ) : request
38
+ resp = @rest_client[ url ].get :content_type => "application/json", :accept=>'application/json', :authorization => @authtoken
38
39
  dump_time( "get", start_time )
39
40
  JSON.parse(resp)
40
41
  end
@@ -53,17 +54,18 @@ class Connection
53
54
  return resp
54
55
  end
55
56
 
56
- def post( request, payload )
57
+ def post( request, payload, in_workspace=true )
57
58
  start_time = Time.now.to_f
59
+ url = in_workspace ? make_url( request ) : request
58
60
  if payload.nil? == true
59
- resp = @rest_client[ make_url( request ) ].post "", :authorization => @authtoken
61
+ resp = @rest_client[ url ].post "", :authorization => @authtoken
60
62
  else
61
- resp = @rest_client[ make_url( request ) ].post payload.to_json, :authorization => @authtoken, :content_type => "application/json"
63
+ resp = @rest_client[ url ].post payload.to_json, :authorization => @authtoken, :content_type => "application/json"
62
64
  end
63
65
  dump_time( "post", start_time )
64
66
  return resp
65
67
  end
66
-
68
+
67
69
  def upload_file( file_name, content_type, file )
68
70
  opts = {
69
71
  :sourceName=> file_name,
@@ -85,20 +87,20 @@ class Connection
85
87
  return resp
86
88
  end
87
89
 
88
- def delete( request )
90
+ def delete( request, in_workspace=true )
89
91
  start_time = Time.now.to_f
90
- resp = @rest_client[ make_url( request ) ].delete :authorization => @authtoken
92
+ url = in_workspace ? make_url( request ) : request
93
+ resp = @rest_client[ url ].delete :authorization => @authtoken
91
94
  dump_time( "delete", start_time )
92
95
  return resp
93
96
  end
94
97
 
95
98
  def make_url( request )
96
- if @workspace.length != 0
97
- url = "#{@workspace}/#{request}"
98
- else
99
- url = request
100
- end
101
- return url
99
+ "#{@workspace}/#{request}"
100
+ end
101
+
102
+ def make_full_url( request )
103
+ "#{@url}/#{make_url(request)}"
102
104
  end
103
105
 
104
106
  def dump_time( what, start_time )
@@ -1,4 +1,6 @@
1
1
  require 'uuidtools'
2
+ require 'restclient'
3
+ require 'json'
2
4
 
3
5
  # coordinate access to stdout...
4
6
  Log_sem = Mutex.new
@@ -28,8 +30,30 @@ end
28
30
 
29
31
  def standard_fileset( )
30
32
  fileset = []
31
- fileset.push("good-testdata/MD_AmerCh1b.xml")
32
- fileset.push("good-testdata/MD_Brit_v1CH1a.xml")
33
+ fileset.push("test/good-testdata/MD_AmerCh1b.xml")
34
+ fileset.push("test/good-testdata/MD_Brit_v1CH1a.xml")
33
35
  return fileset
34
36
 
37
+ end
38
+
39
+ def wikipediaQueryRevisions( lang, params )
40
+ return JSON.parse(RestClient.get("http://#{lang}.wikipedia.org/w/api.php", :params => {
41
+ :format => "json",
42
+ :action => "query"
43
+ }.merge(params))).fetch("query", {}).fetch("pages", {}).values.map { |page| page.fetch("revisions", []) }.flatten
44
+ end
45
+
46
+ def wikipedia( title, limit=5, lang="en" )
47
+ revision_ids = wikipediaQueryRevisions(lang, {
48
+ :titles => title,
49
+ :prop => "revisions",
50
+ :rvlimit => 500,
51
+ :rvprop => "ids|flags"
52
+ }).select { |rev| !rev.has_key?("minor") }.map { |rev| rev["revid"] }.slice(0, limit)
53
+
54
+ wikipediaQueryRevisions(lang, {
55
+ :revids => revision_ids.join("|"),
56
+ :prop => "revisions",
57
+ :rvprop => "content"
58
+ }).map { |rev| rev.fetch("*", "") }.select { |rev| rev != "" }
35
59
  end
metadata CHANGED
@@ -1,14 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: juxta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
+ - Lou Foster
8
+ - Dave Goldstein
7
9
  - Nick Laiacona
8
10
  autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
- date: 2013-07-24 00:00:00.000000000 Z
13
+ date: 2013-07-10 00:00:00.000000000 Z
12
14
  dependencies:
13
15
  - !ruby/object:Gem::Dependency
14
16
  name: rest-client
@@ -66,7 +68,10 @@ dependencies:
66
68
  - - '='
67
69
  - !ruby/object:Gem::Version
68
70
  version: 2.1.3
69
- description: JuxtaWS Ruby bindings
71
+ description: JuxtaWS can collate two or more versions of the same textual work (“witnesses”)
72
+ and generate a list of alignments as well as two different styles of visualization
73
+ suitable for display on the web. This gem provides a Ruby interface to the JuxtaWS
74
+ REST web service.
70
75
  email: nick@performantsoftware.com
71
76
  executables: []
72
77
  extensions: []
@@ -76,7 +81,8 @@ files:
76
81
  - lib/juxta/connection.rb
77
82
  - lib/juxta/utilities.rb
78
83
  homepage: http://rubygems.org/gems/juxta
79
- licenses: []
84
+ licenses:
85
+ - Apache 2.0
80
86
  metadata: {}
81
87
  post_install_message:
82
88
  rdoc_options: []
@@ -86,7 +92,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
92
  requirements:
87
93
  - - '>='
88
94
  - !ruby/object:Gem::Version
89
- version: '0'
95
+ version: 1.9.2
90
96
  required_rubygems_version: !ruby/object:Gem::Requirement
91
97
  requirements:
92
98
  - - '>='
@@ -97,6 +103,6 @@ rubyforge_project:
97
103
  rubygems_version: 2.0.3
98
104
  signing_key:
99
105
  specification_version: 4
100
- summary: JuxtaWS Ruby bindings
106
+ summary: Provides a Ruby interface to the JuxtaWS REST web service.
101
107
  test_files: []
102
108
  has_rdoc: