juxta 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: