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 +4 -4
- data/lib/juxta.rb +324 -155
- data/lib/juxta/connection.rb +21 -19
- data/lib/juxta/utilities.rb +26 -2
- metadata +12 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59a37cdbefe64c30540822a438e0f71e95ca62e2
|
4
|
+
data.tar.gz: 7e077e5a91a479abb46c153f8e72bf4b620fcd9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
47
|
-
|
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
|
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
|
-
#
|
69
|
-
#
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
109
|
-
#
|
110
|
-
|
111
|
-
def
|
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
|
-
|
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
|
-
|
129
|
-
return resp
|
237
|
+
@connection.get( "#{asset_id}" )
|
130
238
|
end
|
131
239
|
|
240
|
+
# Delete the specified witness.
|
132
241
|
#
|
133
|
-
#
|
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
|
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
|
-
#
|
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
|
-
|
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 #{
|
197
|
-
json = { 'source' =>
|
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
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
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
|
-
|
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
|
-
#
|
372
|
-
#
|
373
|
-
|
374
|
-
|
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
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
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
|
data/lib/juxta/connection.rb
CHANGED
@@ -5,14 +5,14 @@ require 'base64'
|
|
5
5
|
class Connection
|
6
6
|
|
7
7
|
attr_reader :url
|
8
|
-
|
8
|
+
attr_accessor :workspace
|
9
9
|
|
10
|
-
def initialize( url,
|
10
|
+
def initialize( url, username=nil, password=nil )
|
11
11
|
|
12
12
|
@authtoken = "Basic #{Base64.encode64("#{username}:#{password}")}"
|
13
|
-
@url =
|
14
|
-
@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
|
-
|
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[
|
61
|
+
resp = @rest_client[ url ].post "", :authorization => @authtoken
|
60
62
|
else
|
61
|
-
resp = @rest_client[
|
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
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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 )
|
data/lib/juxta/utilities.rb
CHANGED
@@ -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.
|
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-
|
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
|
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:
|
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:
|
106
|
+
summary: Provides a Ruby interface to the JuxtaWS REST web service.
|
101
107
|
test_files: []
|
102
108
|
has_rdoc:
|