solis 0.87.0 → 0.89.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
  SHA256:
3
- metadata.gz: 7d5926e4dab3d02865ae5333e319a8973c79e1b0b49d1fc86ec5cd17d32204ed
4
- data.tar.gz: d33d664a73dcb56231d1fc0364314100a114d83b0c2c75c7c11479aa00fba4b7
3
+ metadata.gz: 2a994f808c376224e94848405da688602b0b3bc8a6e84271eccddaf2452e593e
4
+ data.tar.gz: b3158ae4c633f06f215e69f0bf3510499a1be90fe6ea030761213ea11e449fa5
5
5
  SHA512:
6
- metadata.gz: 64bc93c8a1767fc786d2c2528762e7707aad9e33cbe1ec9d9d1208ccbd12f76d65e8bbd244ae88a7a2a89147eb7facc4194d41bcf38cc04c6c0d29a055da207f
7
- data.tar.gz: ce928eaf3a1b43bf1a93678dd5f47544265f47e71df9c61c64d5c1819056aade67fd175fc54b611e03a6e8eb0d5d7c2b9c761b812c0e3a8a2c16a2557130d5c0
6
+ metadata.gz: 38ec27f39274069afd4cd982974aacdafe186a1e7ff301003f3cae878db55dd0a967ed0deea5c5819b162f5104c1b008834d65bdec29e01e9318480aedf1a11d
7
+ data.tar.gz: eef3af31f202871ee596148621caf7519e739fabca8feafe4f08d3fc550f2ba0df7b8505229888db534a0f2e0886bc742ebc754d9d90d1d2ed0d96d0e0b3fcaa
data/lib/solis/graph.rb CHANGED
@@ -292,6 +292,23 @@ module Solis
292
292
  "#{resource.class.graph_name.gsub(/\/$/,'')}/#{belongs_to_resource_name.tableize}?filter[id]=#{resource_ids.join(',')}" unless remote_resources.nil? || resource_ids.empty?
293
293
  end
294
294
  end
295
+ elsif (value[:mincount] && value[:mincount] == 1) || (value[:maxcount] && value[:maxcount] == 1)
296
+ has_one_resource_name = value[:datatype].nil? ? value[:class].gsub(self.model.graph_name, '') : value[:datatype].to_s.classify
297
+ LOGGER.info "\t\t\t#{resource_name}(#{resource_name.gsub('Resource','').tableize.singularize}) has_one #{has_one_resource_name}(#{key})"
298
+ resource.has_one(key.to_sym, foreign_key: :id, primary_key: :id, resource: graph.shape_as_resource("#{has_one_resource_name}", stack_level << has_one_resource_name)) do
299
+ link do |resource|
300
+ remote_resources = resource.instance_variable_get("@#{key}")
301
+ if remote_resources
302
+ remote_resources = [remote_resources] unless remote_resources.is_a?(Array)
303
+ resource_ids = remote_resources.map do |remote_resource|
304
+ remote_resource.id =~ /^http/ ? remote_resource.id.split('/').last : remote_resource.id
305
+ end
306
+
307
+ end
308
+
309
+ "#{resource.class.graph_name.gsub(/\/$/,'')}/#{has_one_resource_name.tableize}?filter[id]=#{resource_ids.join(',')}" unless remote_resources.nil? || resource_ids.empty?
310
+ end
311
+ end
295
312
  else
296
313
  has_many_resource_name = value[:datatype].nil? ? value[:class].gsub(self.model.graph_name, '') : value[:datatype].to_s.classify
297
314
  LOGGER.info "\t\t\t#{resource_name}(#{resource_name.gsub('Resource','').tableize.singularize}) has_many #{has_many_resource_name}(#{key})"
data/lib/solis/model.rb CHANGED
@@ -225,6 +225,9 @@ values ?s {<#{self.graph_id}>}
225
225
  end
226
226
  end
227
227
 
228
+ maxcount = original_klass.class.metadata[:attributes][key][:maxcount]
229
+ value = value.first if maxcount && maxcount == 1 && value.is_a?(Array)
230
+
228
231
  updated_klass.instance_variable_set("@#{key}", value)
229
232
  end
230
233
 
@@ -483,7 +486,12 @@ values ?s {<#{self.graph_id}>}
483
486
  end
484
487
  end
485
488
 
486
- make_graph(graph, hierarchy, id, original_klass, klass_metadata, resolve_all)
489
+ begin
490
+ make_graph(graph, hierarchy, id, original_klass, klass_metadata, resolve_all)
491
+ rescue => e
492
+ Solis::LOGGER.error(e.message)
493
+ raise e
494
+ end
487
495
 
488
496
  hierarchy.pop
489
497
  id
data/lib/solis/query.rb CHANGED
@@ -320,7 +320,7 @@ PREFIX #{@model.class.graph_prefix}: <#{@model.class.graph_name}>"
320
320
 
321
321
  if data.key?(attribute) # attribute exists
322
322
  raise "Cardinality error, max = #{solution_model.metadata[:attributes][attribute][:maxcount]}" if solution_model.metadata[:attributes][attribute][:maxcount] == 0
323
- if solution_model.metadata[:attributes][attribute][:maxcount] == 1 && data.key?(attribute)
323
+ if solution_model.metadata[:attributes][attribute][:maxcount] == 1 && data.key?(attribute) && data[attribute].is_a?(Array) && data[attribute].length > 1
324
324
  raise "Cardinality error, max = #{solution_model.metadata[:attributes][attribute][:maxcount]}"
325
325
  elsif solution_model.metadata[:attributes][attribute][:maxcount] == 1
326
326
  data[attribute] = object
@@ -18,11 +18,11 @@ module Solis
18
18
  end
19
19
  end
20
20
 
21
- def validate(sheets)
21
+ def validate(sheets, prefixes = nil, metadata = nil)
22
22
  # raise "Please make sure the sheet contains '_PREFIXES', '_METADATA', '_ENTITIES' tabs" unless (%w[_PREFIXES _METADATA _ENTITIES] - sheets.keys).length == 0
23
23
 
24
- prefixes = sheets['_PREFIXES']
25
- metadata = sheets['_METADATA']
24
+ prefixes = sheets.key?('_PREFIXES') && prefixes.nil? ? sheets['_PREFIXES'] : prefixes
25
+ metadata = sheets.key?('_METADATA') && metadata.nil? ? sheets['_METADATA'] : metadata
26
26
 
27
27
  raise "_PREFIXES tab must have ['base', 'prefix', 'uri'] as a header at row 1" unless (%w[base prefix uri] - prefixes.header).length == 0
28
28
  raise '_PREFIXES.base can only have one base URI' if prefixes.map { |m| m['base'] }.grep(/\*/).count != 1
@@ -53,6 +53,8 @@ module Solis
53
53
 
54
54
  def read_sheets(key, spreadsheet_id, options)
55
55
  data = nil
56
+ prefixes = options[:prefixes] || nil
57
+ metadata = options[:metadata] || nil
56
58
 
57
59
  cache_dir = ConfigFile.include?(:cache) ? ConfigFile[:cache] : '/tmp'
58
60
 
@@ -70,7 +72,7 @@ module Solis
70
72
  sheets[sheet.title] = sheet
71
73
  end
72
74
 
73
- validate(sheets)
75
+ validate(sheets, prefixes, metadata)
74
76
  end
75
77
  sheets
76
78
  end
@@ -151,6 +153,7 @@ module Solis
151
153
  if entity_data && !entity_data.nil? && (entity_data.count > 0)
152
154
  entity_data.each do |p|
153
155
  property_name = I18n.transliterate(p['name'].strip)
156
+ next if property_name.empty?
154
157
  min_max = {}
155
158
 
156
159
  %w[min max].each do |n|
@@ -473,35 +476,75 @@ hide empty members
473
476
  end
474
477
 
475
478
  def build_json_schema(shacl_file)
476
- graph = RDF::Graph.load(StringIO.new(shacl_file), format: :ttl)
477
- json_schema = {
478
- "$schema" => "http://json-schema.org/draft-07/schema#",
479
- "type" => "object",
480
- "properties" => {},
481
- "required" => []
482
- }
479
+ def map_rdf_datatype_to_json_schema(datatype)
480
+ # NOTE: "format" not supported by every client.
481
+ case datatype
482
+ when /string$/
483
+ { "type" => "string" }
484
+ when /integer$/
485
+ { "type" => "integer" }
486
+ when /decimal$/, /double$/, /float$/
487
+ { "type" => "number" }
488
+ when /boolean$/
489
+ { "type" => "boolean" }
490
+ when /date$/, /dateTime$/
491
+ { "type" => "string", "format" => "date-time" }
492
+ when /anyURI$/
493
+ { "type" => "string", "format" => "uri" }
494
+ else
495
+ { "type" => "string" }
496
+ end
497
+ end
498
+
499
+ def self.default_value_for_type(type)
500
+ case type
501
+ when "string"
502
+ ""
503
+ when "integer", "number"
504
+ 0
505
+ when "boolean"
506
+ false
507
+ when "array"
508
+ []
509
+ when "object"
510
+ {}
511
+ else
512
+ ""
513
+ end
514
+ end
483
515
 
484
- graph.query([nil, RDF.type, RDF::Vocab::SHACL.NodeShape]) do |shape|
485
- shape_subject = shape.subject
516
+ graph = RDF::Graph.new
517
+ graph.from_ttl(shacl_file)
518
+
519
+ #graph = RDF::Graph.load(StringIO.new(shacl_file), format: :ttl, content_type: "text/turtle")
520
+ json_schema = {
521
+ "$schema" => "http://json-schema.org/draft-07/schema#",
522
+ "type" => "object",
523
+ "properties" => {},
524
+ "required" => []
525
+ }
486
526
 
487
- graph.query([shape_subject, RDF::Vocab::SHACL.property, nil]) do |prop_stmt|
488
- prop_subject = prop_stmt.object
489
- prop_name = graph.query([prop_subject, RDF::Vocab::SHACL.path, nil]).first&.object.to_s
490
- datatype = graph.query([prop_subject, RDF::Vocab::SHACL.datatype, nil]).first&.object
491
- min_count = graph.query([prop_subject, RDF::Vocab::SHACL.minCount, nil]).first&.object&.to_i
492
- max_count = graph.query([prop_subject, RDF::Vocab::SHACL.maxCount, nil]).first&.object&.to_i
493
- pattern = graph.query([prop_subject, RDF::Vocab::SHACL.pattern, nil]).first&.object&.to_s
527
+ graph.query([nil, RDF.type, RDF::Vocab::SHACL.NodeShape]) do |shape|
528
+ shape_subject = shape.subject
494
529
 
495
- json_schema["properties"][prop_name] = {}
496
- json_schema["properties"][prop_name]["type"] = datatype.to_s.split("#").last.downcase if datatype
497
- json_schema["properties"][prop_name]["pattern"] = pattern if pattern
530
+ graph.query([shape_subject, RDF::Vocab::SHACL.property, nil]) do |prop_stmt|
531
+ prop_subject = prop_stmt.object
532
+ prop_name = graph.query([prop_subject, RDF::Vocab::SHACL.path, nil]).first&.object.to_s
533
+ datatype = map_rdf_datatype_to_json_schema(graph.query([prop_subject, RDF::Vocab::SHACL.datatype, nil]).first&.object)
534
+ min_count = graph.query([prop_subject, RDF::Vocab::SHACL.minCount, nil]).first&.object&.to_i
535
+ max_count = graph.query([prop_subject, RDF::Vocab::SHACL.maxCount, nil]).first&.object&.to_i
536
+ pattern = graph.query([prop_subject, RDF::Vocab::SHACL.pattern, nil]).first&.object&.to_s
498
537
 
499
- json_schema["required"] << prop_name if min_count && min_count > 0
500
- json_schema["properties"][prop_name]["maxItems"] = max_count if max_count
501
- end
538
+ json_schema["properties"][prop_name] = {}
539
+ json_schema["properties"][prop_name]["type"] = datatype["type"] if datatype
540
+ json_schema["properties"][prop_name]["pattern"] = pattern if pattern
541
+
542
+ json_schema["required"] << prop_name if min_count && min_count > 0
543
+ json_schema["properties"][prop_name]["maxItems"] = max_count if max_count
502
544
  end
545
+ end
503
546
 
504
- JSON.pretty_generate(json_schema)
547
+ JSON.pretty_generate(json_schema)
505
548
  end
506
549
 
507
550
  def every_entity(data)
@@ -652,6 +695,16 @@ hide empty members
652
695
  end
653
696
 
654
697
  sheet_data = read_sheets(key, spreadsheet_id, options)
698
+ prefixes = sheet_data['_PREFIXES']
699
+ metadata = sheet_data['_METADATA']
700
+
701
+ raise "_PREFIXES tab must have ['base', 'prefix', 'uri'] as a header at row 1" unless (%w[base prefix uri] - prefixes.header).length == 0
702
+ raise '_PREFIXES.base can only have one base URI' if prefixes.map { |m| m['base'] }.grep(/\*/).count != 1
703
+
704
+ raise "_METADATA tab must have ['key', 'value'] as a header at row 1" unless (%w[key value] - metadata.header).length == 0
705
+
706
+ options[:prefixes] = prefixes
707
+ options[:metadata] = metadata
655
708
  #TODO: cleanup
656
709
  if sheet_data.is_a?(Hash)
657
710
  raise "No _REFERENCES sheet found" unless sheet_data.key?("_REFERENCES")
@@ -670,10 +723,20 @@ hide empty members
670
723
  end
671
724
 
672
725
  datas = []
673
- references.each do |v|
726
+ references.each_with_index do |v, i|
727
+ progress((100/(references.length+1))*(i+1), options[:progress] || {})
674
728
  sheet_id = spreadsheet_id_from_url(v[:sheet_url])
675
729
 
676
730
  sheet_data = read_sheets(key, sheet_id, options)
731
+
732
+ unless sheet_data.key?('_PREFIXES')
733
+ sheet_data['_PREFIXES'] = prefixes
734
+ end
735
+
736
+ unless sheet_data.key?('_METADATA')
737
+ sheet_data['_METADATA'] = metadata
738
+ end
739
+
677
740
  if sheet_data.key?("_PREFIXES")
678
741
  datas << process_sheet(key, sheet_id, sheet_data)
679
742
  sleep 30
@@ -11,7 +11,7 @@ module Solis
11
11
  @endpoint = endpoint
12
12
  @graph_name = graph_name
13
13
 
14
- @pool = ConnectionPool.new(size:5, timeout: 60) do
14
+ @pool = ConnectionPool.new(size:5, timeout: 160) do
15
15
  SPARQL::Client.new(@endpoint, graph: @graph_name)
16
16
  #SPARQL::Client.new(@endpoint)
17
17
  end
data/lib/solis/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Solis
2
- VERSION = "0.87.0"
2
+ VERSION = "0.89.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.87.0
4
+ version: 0.89.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mehmet Celik
@@ -335,7 +335,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
335
335
  - !ruby/object:Gem::Version
336
336
  version: '0'
337
337
  requirements: []
338
- rubygems_version: 3.6.8
338
+ rubygems_version: 3.6.9
339
339
  specification_version: 4
340
340
  summary: Turn any SHACL file into an API, ORM, documentation, ...
341
341
  test_files: []