uri_service 0.3.1 → 0.4.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: e14cec0a40986cc0327fca1d58b15704fd25c2c6
4
- data.tar.gz: 6fe6e37e9ab65ded6c9c15fdeefa06e1d38c2507
3
+ metadata.gz: 6cedacdff6331c4b074d8fb744f92941cac548bd
4
+ data.tar.gz: d1416c576de2c1740d18617f9c368f68f05c1930
5
5
  SHA512:
6
- metadata.gz: f59f8f12ea92b925b3414bcb3c63106656fa3d6661081af07d613066d14d8a9dbe1ccbe6b0aeeff81391bcfc4f37fd3d9bfc54d20d3d5d55f0a668891da3810a
7
- data.tar.gz: 3d890e422301dfbd32da4920661abad3a928e646d480d1be33439d35033cc0271317f7e79654e43aeaeeabc10caa515868647897ebbc8a32e8d8df3b7cb71311
6
+ metadata.gz: f68e2613085cb5da28208422433308d3ee8511fabb52b1e48c8c13d6a901ab9aaa1f6e99bb41653169559eee7b68275ae54635beeff5ecbe7687b35a6a237817
7
+ data.tar.gz: 4fb2a5930c2e4b6f1e5c178151eba224b6aa9e68c39f18b30742bee65e7ba2ce1676fc5d8651cfb84c84b3df608a85988fb39fbf659d36b5d677b050b297e160
data/README.md CHANGED
@@ -152,8 +152,8 @@ UriService.client.create_term(UriService::TermType::EXTERNAL, {vocabulary_string
152
152
  # Create a LOCAL term in the 'departments' vocabulary (note: A URI is not passed in because LOCAL terms generate their own URIs)
153
153
  UriService.client.create_term(UriService::TermType::LOCAL, {vocabulary_string_key: 'departments', value: 'Chemistry', additional_fields: {'department_code' => 'CHEM'}})
154
154
 
155
- # Create a LOCAL term in the 'departments' vocabulary (note: A URI is not passed in because TEMPORARY terms generate their own URIs, and additional_fields are not allowed)
156
- UriService.client.create_term(UriService::TermType::LOCAL, {vocabulary_string_key: 'names', value: 'Smith, John'})
155
+ # Create a TEMPORARY term in the 'departments' vocabulary (note: A URI is not passed in because TEMPORARY terms generate their own URIs, and additional_fields are not allowed)
156
+ UriService.client.create_term(UriService::TermType::TEMPORARY, {vocabulary_string_key: 'names', value: 'Smith, John'})
157
157
  ```
158
158
 
159
159
  Searching by string query for a term in a vocabulary:
@@ -3,7 +3,7 @@ class UriService::Client
3
3
  attr_reader :db, :rsolr_pool, :local_uri_base, :temporary_uri_base
4
4
 
5
5
  ALPHANUMERIC_UNDERSCORE_KEY_REGEX = /\A[a-z]+[a-z0-9_]*\z/
6
- CORE_FIELD_NAMES = ['uri', 'vocabulary_string_key', 'value', 'type']
6
+ CORE_FIELD_NAMES = ['uri', 'vocabulary_string_key', 'value', 'authority', 'type', 'internal_id']
7
7
  VALID_TYPES = [UriService::TermType::EXTERNAL, UriService::TermType::LOCAL, UriService::TermType::TEMPORARY]
8
8
 
9
9
  def initialize(opts)
@@ -40,14 +40,16 @@ class UriService::Client
40
40
  end
41
41
  end
42
42
 
43
- # Need to use unambiguous order when using paged_each
43
+ # Need to use unambiguous order when using paged_each, so we choose to order by DB :id
44
44
  @db[UriService::TERMS].order(:id).paged_each(:rows_per_fetch=>100) do |term_db_row|
45
45
  self.send_term_to_solr(
46
46
  term_db_row[:vocabulary_string_key],
47
47
  term_db_row[:value],
48
48
  term_db_row[:uri],
49
+ term_db_row[:authority],
49
50
  JSON.parse(term_db_row[:additional_fields]),
50
51
  term_db_row[:type],
52
+ term_db_row[:id],
51
53
  false)
52
54
 
53
55
  if print_progress_to_console
@@ -125,6 +127,7 @@ class UriService::Client
125
127
  String :value, text: true
126
128
  String :value_hash, fixed: true, size: 64
127
129
  String :type, null: false
130
+ String :authority, size: 255, index: true
128
131
  String :additional_fields, text: true
129
132
  end
130
133
  puts 'Created table: ' + UriService::TERMS.to_s
@@ -166,13 +169,14 @@ class UriService::Client
166
169
  vocabulary_string_key = opts.delete(:vocabulary_string_key)
167
170
  value = opts.delete(:value)
168
171
  uri = opts.delete(:uri)
172
+ authority = opts.has_key?(:authority) ? opts.delete(:authority) : ''
169
173
  additional_fields = opts.delete(:additional_fields) || {}
170
174
 
171
175
  if type == UriService::TermType::EXTERNAL
172
176
  # URI is required
173
177
  raise UriService::InvalidOptsError, "A uri must be supplied for terms of type #{type}." if uri.nil?
174
178
 
175
- return create_term_impl(type, vocabulary_string_key, value, uri, additional_fields)
179
+ return create_term_impl(type, vocabulary_string_key, value, uri, authority, additional_fields)
176
180
  else
177
181
  # URI should not be present
178
182
  raise UriService::InvalidOptsError, "A uri cannot supplied for term type: #{type}" unless uri.nil?
@@ -180,7 +184,7 @@ class UriService::Client
180
184
  if type == UriService::TermType::TEMPORARY
181
185
  # No two TEMPORARY terms within the same vocabulary can have the same value, so we generate a unique URI from a hash of the (vocabulary_string_key + value) to ensure uniqueness.
182
186
  uri = self.generate_uri_for_temporary_term(vocabulary_string_key, value)
183
- return create_term_impl(type, vocabulary_string_key, value, uri, additional_fields)
187
+ return create_term_impl(type, vocabulary_string_key, value, uri, authority, additional_fields)
184
188
  elsif type == UriService::TermType::LOCAL
185
189
  5.times {
186
190
  # We generate a unique URI for a local term from a UUID generator.
@@ -191,7 +195,7 @@ class UriService::Client
191
195
  uri = URI(@local_uri_base)
192
196
  uri.path += SecureRandom.uuid # Generate random UUID for local URI
193
197
  uri = uri.to_s
194
- return create_term_impl(type, vocabulary_string_key, value, uri, additional_fields)
198
+ return create_term_impl(type, vocabulary_string_key, value, uri, authority, additional_fields)
195
199
  rescue UriService::ExistingUriError
196
200
  next
197
201
  end
@@ -208,59 +212,45 @@ class UriService::Client
208
212
  return uri.to_s
209
213
  end
210
214
 
211
- def generate_frozen_term_hash(vocabulary_string_key, value, uri, additional_fields, type)
215
+ def generate_frozen_term_hash(vocabulary_string_key, value, uri, authority, additional_fields, type, internal_id)
212
216
  hash_to_return = {}
213
217
  hash_to_return['uri'] = uri
214
218
  hash_to_return['value'] = value
215
219
  hash_to_return['type'] = type
220
+ hash_to_return['authority'] = authority unless authority == ''
216
221
  hash_to_return['vocabulary_string_key'] = vocabulary_string_key
222
+ hash_to_return['internal_id'] = internal_id
217
223
 
218
224
  additional_fields.each do |key, val|
219
225
  hash_to_return[key] = val
220
226
  end
221
227
 
228
+ # Delete nil values
229
+ hash_to_return.delete_if { |k, v| v.nil? }
230
+
231
+ # Freeze hash
222
232
  hash_to_return.freeze # To make this a read-only hash
223
233
 
224
234
  return hash_to_return
225
235
  end
226
236
 
227
- def create_term_solr_doc(vocabulary_string_key, value, uri, additional_fields, type)
237
+ def create_term_solr_doc(vocabulary_string_key, value, uri, authority, additional_fields, type, internal_id)
228
238
  doc = {}
229
239
  doc['uri'] = uri
230
240
  doc['value'] = value
231
241
  doc['type'] = type
232
242
  doc['vocabulary_string_key'] = vocabulary_string_key
243
+ doc['authority'] = authority
244
+ doc['internal_id'] = internal_id
233
245
 
234
246
  doc['additional_fields'] = JSON.generate(additional_fields)
235
247
 
236
248
  return doc
237
249
  end
238
250
 
239
- #def self.get_solr_suffix_for_object(obj)
240
- # if obj.is_a?(Array)
241
- # # Note boolean arrays aren't supported because they don't seem useful in this context
242
- # if obj[0].is_a?(Fixnum)
243
- # return '_isim'
244
- # else
245
- # # Treat like a string array
246
- # return '_ssim'
247
- # end
248
- # else
249
- # if obj.is_a?(String)
250
- # return '_ssi'
251
- # elsif obj.is_a?(TrueClass) || obj.is_a?(FalseClass)
252
- # return '_bsi'
253
- # elsif obj.is_a?(Fixnum)
254
- # return '_isi'
255
- # else
256
- # raise UriService::UnsupportedObjectTypeError, "Unable to determine solr suffix for unsupported object type: #{obj.class.name}"
257
- # end
258
- # end
259
- #end
260
-
261
251
  # Index the DB row term data into solr
262
- def send_term_to_solr(vocabulary_string_key, value, uri, additional_fields, type, commit=true)
263
- doc = create_term_solr_doc(vocabulary_string_key, value, uri, additional_fields, type)
252
+ def send_term_to_solr(vocabulary_string_key, value, uri, authority, additional_fields, type, internal_id, commit=true)
253
+ doc = create_term_solr_doc(vocabulary_string_key, value, uri, authority, additional_fields, type, internal_id)
264
254
  @rsolr_pool.with do |rsolr|
265
255
  rsolr.add(doc)
266
256
  rsolr.commit if commit
@@ -295,6 +285,12 @@ class UriService::Client
295
285
  return results.length == 1 ? results.first : nil
296
286
  end
297
287
 
288
+ # Finds the term with the given uri
289
+ def find_term_by_internal_id(id)
290
+ results = self.find_terms_where({internal_id: id}, 1)
291
+ return results.length == 1 ? results.first : nil
292
+ end
293
+
298
294
  # Finds terms that match the specified conditions
299
295
  def find_terms_where(opts, limit=10)
300
296
  fqs = []
@@ -332,10 +328,12 @@ class UriService::Client
332
328
  uri = term_solr_doc.delete('uri')
333
329
  vocabulary_string_key = term_solr_doc.delete('vocabulary_string_key')
334
330
  value = term_solr_doc.delete('value')
331
+ authority = term_solr_doc.delete('authority')
335
332
  type = term_solr_doc.delete('type')
336
333
  additional_fields = JSON.parse(term_solr_doc.delete('additional_fields'))
334
+ internal_id = term_solr_doc.delete('internal_id')
337
335
 
338
- return generate_frozen_term_hash(vocabulary_string_key, value, uri, additional_fields, type)
336
+ return generate_frozen_term_hash(vocabulary_string_key, value, uri, authority, additional_fields, type, internal_id)
339
337
  end
340
338
 
341
339
  def find_terms_by_query(vocabulary_string_key, value_query, limit=10, start=0)
@@ -444,7 +442,7 @@ class UriService::Client
444
442
  end
445
443
  end
446
444
 
447
- # opts format: {:value => 'new value', :additional_fields => {'key' => 'value'}}
445
+ # opts format: {:value => 'new value', :authority => 'newauthority', :additional_fields => {'key' => 'value'}}
448
446
  def update_term(uri, opts, merge_additional_fields=true)
449
447
  self.handle_database_disconnect do
450
448
  term_db_row = @db[UriService::TERMS].first(uri: uri)
@@ -456,6 +454,7 @@ class UriService::Client
456
454
  end
457
455
 
458
456
  new_value = opts[:value] || term_db_row[:value]
457
+ new_authority = opts[:authority] || term_db_row[:authority]
459
458
  new_additional_fields = term_db_row[:additional_fields].nil? ? {} : JSON.parse(term_db_row[:additional_fields])
460
459
 
461
460
  unless opts[:additional_fields].nil?
@@ -469,11 +468,11 @@ class UriService::Client
469
468
  validate_additional_field_keys(new_additional_fields)
470
469
 
471
470
  @db.transaction do
472
- @db[UriService::TERMS].where(uri: uri).update(value: new_value, value_hash: Digest::SHA256.hexdigest(new_value), additional_fields: JSON.generate(new_additional_fields))
473
- self.send_term_to_solr(term_db_row[:vocabulary_string_key], new_value, uri, new_additional_fields, term_db_row[:type])
471
+ @db[UriService::TERMS].where(uri: uri).update(value: new_value, value_hash: Digest::SHA256.hexdigest(new_value), authority: new_authority, additional_fields: JSON.generate(new_additional_fields))
472
+ self.send_term_to_solr(term_db_row[:vocabulary_string_key], new_value, uri, new_authority, new_additional_fields, term_db_row[:type], term_db_row[:id])
474
473
  end
475
474
 
476
- return generate_frozen_term_hash(term_db_row[:vocabulary_string_key], new_value, uri, new_additional_fields, term_db_row[:type])
475
+ return generate_frozen_term_hash(term_db_row[:vocabulary_string_key], new_value, uri, new_authority, new_additional_fields, term_db_row[:type], term_db_row[:id])
477
476
  end
478
477
  end
479
478
 
@@ -511,7 +510,7 @@ class UriService::Client
511
510
  # - Ensures uniqueness of URIs in database.
512
511
  # - Returns an existing TEMPORARY term if a user attempts to
513
512
  # create a new TEMPORARY term with an existing value/vocabulary combo.
514
- def create_term_impl(type, vocabulary_string_key, value, uri, additional_fields)
513
+ def create_term_impl(type, vocabulary_string_key, value, uri, authority, additional_fields)
515
514
 
516
515
  raise UriService::InvalidTermTypeError, 'Invalid type: ' + type unless VALID_TYPES.include?(type)
517
516
 
@@ -531,6 +530,11 @@ class UriService::Client
531
530
  if additional_fields.size > 0
532
531
  raise UriService::InvalidOptsError, "Terms of type #{type} cannot have additional_fields."
533
532
  end
533
+
534
+ # TEMPORARY terms are not meant to store authority information
535
+ unless authority == ''
536
+ raise UriService::InvalidOptsError, "Terms of type #{type} cannot have an authority."
537
+ end
534
538
  end
535
539
 
536
540
  unless uri =~ UriService::VALID_URI_REGEX
@@ -539,7 +543,7 @@ class UriService::Client
539
543
 
540
544
  #Ensure that vocabulary with vocabulary_string_key exists
541
545
  if self.find_vocabulary(vocabulary_string_key).nil?
542
- raise UriService::NonExistentVocabularyError, "There is no vocabulary with string key: " + vocabulary_string_key
546
+ raise UriService::NonExistentVocabularyError, "There is no vocabulary with string key: " + vocabulary_string_key.to_s
543
547
  end
544
548
 
545
549
  # Stringify and validate keys for additional_fields
@@ -550,16 +554,17 @@ class UriService::Client
550
554
  value_hash = Digest::SHA256.hexdigest(value)
551
555
 
552
556
  begin
553
- @db[UriService::TERMS].insert(
557
+ db_id = @db[UriService::TERMS].insert(
554
558
  type: type,
555
559
  uri: uri,
556
560
  uri_hash: Digest::SHA256.hexdigest(uri),
557
561
  value: value,
558
562
  value_hash: value_hash,
563
+ authority: authority,
559
564
  vocabulary_string_key: vocabulary_string_key,
560
565
  additional_fields: JSON.generate(additional_fields)
561
566
  )
562
- send_term_to_solr(vocabulary_string_key, value, uri, additional_fields, type)
567
+ send_term_to_solr(vocabulary_string_key, value, uri, authority, additional_fields, type, db_id)
563
568
  rescue Sequel::UniqueConstraintViolation
564
569
 
565
570
  # If this is a new TEMPORARY term and we ran into a Sequel::UniqueConstraintViolation,
@@ -573,7 +578,7 @@ class UriService::Client
573
578
 
574
579
  end
575
580
 
576
- return generate_frozen_term_hash(vocabulary_string_key, value, uri, additional_fields, type)
581
+ return generate_frozen_term_hash(vocabulary_string_key, value, uri, authority, additional_fields, type, db_id)
577
582
 
578
583
  end
579
584
  end
@@ -1,6 +1,6 @@
1
1
  module UriService
2
2
 
3
- VERSION = '0.3.1'
3
+ VERSION = '0.4.0'
4
4
 
5
5
  def self.version
6
6
  VERSION
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uri_service
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric O'Hanlon
@@ -201,10 +201,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
201
201
  version: '0'
202
202
  requirements: []
203
203
  rubyforge_project:
204
- rubygems_version: 2.4.3
204
+ rubygems_version: 2.4.8
205
205
  signing_key:
206
206
  specification_version: 4
207
207
  summary: A service for registering local URIs and performing both local and remote
208
208
  URI lookups.
209
209
  test_files: []
210
- has_rdoc: