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 +4 -4
- data/lib/solis/graph.rb +17 -0
- data/lib/solis/model.rb +9 -1
- data/lib/solis/query.rb +1 -1
- data/lib/solis/shape/reader/sheet.rb +91 -28
- data/lib/solis/store/sparql/client.rb +1 -1
- data/lib/solis/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a994f808c376224e94848405da688602b0b3bc8a6e84271eccddaf2452e593e
|
4
|
+
data.tar.gz: b3158ae4c633f06f215e69f0bf3510499a1be90fe6ea030761213ea11e449fa5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
"
|
481
|
-
|
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
|
-
|
485
|
-
|
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
|
-
|
488
|
-
|
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
|
-
|
496
|
-
|
497
|
-
|
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
|
-
|
500
|
-
|
501
|
-
|
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
|
-
|
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.
|
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
|
-
|
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
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.
|
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.
|
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: []
|