solis 0.64.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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +6 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +287 -0
  8. data/Rakefile +10 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/examples/after_hooks.rb +24 -0
  12. data/examples/config.yml.template +15 -0
  13. data/examples/read_from_shacl.rb +22 -0
  14. data/examples/read_from_shacl_abv.rb +84 -0
  15. data/examples/read_from_sheet.rb +22 -0
  16. data/lib/solis/config_file.rb +91 -0
  17. data/lib/solis/error/cursor_error.rb +6 -0
  18. data/lib/solis/error/general_error.rb +6 -0
  19. data/lib/solis/error/invalid_attribute_error.rb +6 -0
  20. data/lib/solis/error/invalid_datatype_error.rb +6 -0
  21. data/lib/solis/error/not_found_error.rb +6 -0
  22. data/lib/solis/error/query_error.rb +6 -0
  23. data/lib/solis/error.rb +3 -0
  24. data/lib/solis/graph.rb +360 -0
  25. data/lib/solis/model.rb +565 -0
  26. data/lib/solis/options.rb +19 -0
  27. data/lib/solis/query/construct.rb +93 -0
  28. data/lib/solis/query/filter.rb +133 -0
  29. data/lib/solis/query/run.rb +97 -0
  30. data/lib/solis/query.rb +347 -0
  31. data/lib/solis/resource.rb +37 -0
  32. data/lib/solis/shape/data_types.rb +280 -0
  33. data/lib/solis/shape/reader/csv.rb +12 -0
  34. data/lib/solis/shape/reader/file.rb +16 -0
  35. data/lib/solis/shape/reader/sheet.rb +777 -0
  36. data/lib/solis/shape/reader/simple_sheets/sheet.rb +59 -0
  37. data/lib/solis/shape/reader/simple_sheets/worksheet.rb +173 -0
  38. data/lib/solis/shape/reader/simple_sheets.rb +40 -0
  39. data/lib/solis/shape.rb +189 -0
  40. data/lib/solis/sparql_adaptor.rb +318 -0
  41. data/lib/solis/store/sparql/client/query.rb +35 -0
  42. data/lib/solis/store/sparql/client.rb +41 -0
  43. data/lib/solis/version.rb +3 -0
  44. data/lib/solis.rb +13 -0
  45. data/solis.gemspec +50 -0
  46. metadata +304 -0
@@ -0,0 +1,318 @@
1
+ require 'graphiti'
2
+ module Solis
3
+ class SparqlAdaptor < Graphiti::Adapters::Abstract
4
+ def self.sideloading_classes
5
+ {
6
+ has_many: HasMany,
7
+ belongs_to: BelongsTo,
8
+ has_one: ::Graphiti::Sideload::HasOne,
9
+ many_to_many: ::Graphiti::Sideload::ManyToMany,
10
+ polymorphic_belongs_to: ::Graphiti::Sideload::PolymorphicBelongsTo
11
+ }
12
+ end
13
+
14
+ def base_scope(*scope)
15
+ types = ObjectSpace.each_object(Class).select { |klass| klass < self.resource.model}.map{|m| m.name.tableize.pluralize.to_sym}
16
+ types << self.resource.model.name.tableize.pluralize.to_sym if types.empty?
17
+
18
+ { type: types, sort: {}, filters: {} }
19
+ rescue Exception => e
20
+ types = [self.resource.model.name.tableize.pluralize.to_sym]
21
+ { type: types, sort: {}, filters: {} }
22
+ end
23
+
24
+ def paginate(scope, current, per)
25
+ scope.merge!(current_page: current, per_page: per)
26
+ end
27
+
28
+ def count(scope, attr)
29
+ count = self.resource.model.new().query.paging(scope).filter(scope).sort(scope).count
30
+ scope[attr] = count
31
+ end
32
+
33
+ def order(scope, att, dir)
34
+ scope[:sort].merge!({ att => dir })
35
+ scope
36
+ end
37
+
38
+ def self.default_operators
39
+ {
40
+ string: [:eq, :not_eq, :contains],
41
+ lang_string: [:eq, :not_eq, :contains],
42
+ integer: [:eq, :not_eq, :gt, :lt],
43
+ float: [:eq, :not_eq, :gt, :lt],
44
+ big_decimal: [:eq, :not_eq, :gt, :lt],
45
+ date: [:eq, :not_eq, :gt, :lt],
46
+ boolean: [:eq, :not_eq],
47
+ uuid: [:eq, :not_eq],
48
+ enum: [:eq],
49
+ datetime: [:eq, :not_eq, :gt, :lt],
50
+ }
51
+ end
52
+
53
+
54
+ def filter(scope, attribute, value, is_not = false, operator = '=')
55
+ scope[:filters][attribute] = {value: value, operator: operator, is_not: is_not}
56
+ scope
57
+ end
58
+
59
+ alias :filter_eq :filter
60
+ alias :filter_string_eq :filter
61
+ alias :filter_integer_eq :filter
62
+ alias :filter_float_eq :filter
63
+ alias :filter_big_decimal_eq :filter
64
+ alias :filter_date_eq :filter
65
+ alias :filter_boolean_eq :filter
66
+ alias :filter_uuid_eq :filter
67
+ alias :filter_enum_eq :filter
68
+ alias :filter_datetime_eq :filter
69
+ alias :filter_lang_string_eq :filter
70
+
71
+ def filter_not_eq(scope, attribute, value)
72
+ filter_eq(scope, attribute, value, true, '=')
73
+ end
74
+
75
+ alias :filter_string_not_eq :filter_not_eq
76
+ alias :filter_integer_not_eq :filter_not_eq
77
+ alias :filter_float_not_eq :filter_not_eq
78
+ alias :filter_big_decimal_not_eq :filter_not_eq
79
+ alias :filter_date_not_eq :filter_not_eq
80
+ alias :filter_boolean_not_eq :filter_not_eq
81
+ alias :filter_uuid_not_eq :filter_not_eq
82
+ alias :filter_enum_not_eq :filter_not_eq
83
+ alias :filter_datetime_not_eq :filter_not_eq
84
+ alias :filter_lang_string_not_eq :filter_not_eq
85
+
86
+ def filter_contains(scope, attribute, value)
87
+ filter_eq(scope, attribute, value, false, '~')
88
+ end
89
+
90
+ alias :filter_string_contains :filter_contains
91
+ alias :filter_lang_string_contains :filter_contains
92
+
93
+ def filter_gt(scope, attribute, value)
94
+ filter_eq(scope, attribute, value, false, '>')
95
+ end
96
+
97
+ alias :filter_string_gt :filter_gt
98
+ alias :filter_integer_gt :filter_gt
99
+ alias :filter_float_gt :filter_gt
100
+ alias :filter_big_decimal_gt :filter_gt
101
+ alias :filter_date_gt :filter_gt
102
+ alias :filter_boolean_gt :filter_gt
103
+ alias :filter_uuid_gt :filter_gt
104
+ alias :filter_enum_gt :filter_gt
105
+ alias :filter_datetime_gt :filter_gt
106
+
107
+ def filter_not_gt(scope, attribute, value)
108
+ filter_eq(scope, attribute, value, true, '>')
109
+ end
110
+
111
+ alias :filter_string_not_gt :filter_not_gt
112
+ alias :filter_integer_not_gt :filter_not_gt
113
+ alias :filter_float_not_gt :filter_not_gt
114
+ alias :filter_big_decimal_not_gt :filter_not_gt
115
+ alias :filter_date_not_gt :filter_not_gt
116
+ alias :filter_boolean_not_gt :filter_not_gt
117
+ alias :filter_uuid_not_gt :filter_not_gt
118
+ alias :filter_enum_not_gt :filter_not_gt
119
+ alias :filter_datetime_not_gt :filter_not_gt
120
+
121
+ def filter_lt(scope, attribute, value)
122
+ filter_eq(scope, attribute, value, false, '<')
123
+ end
124
+
125
+ alias :filter_string_lt :filter_lt
126
+ alias :filter_integer_lt :filter_lt
127
+ alias :filter_float_lt :filter_lt
128
+ alias :filter_big_decimal_lt :filter_lt
129
+ alias :filter_date_lt :filter_lt
130
+ alias :filter_boolean_lt :filter_lt
131
+ alias :filter_uuid_lt :filter_lt
132
+ alias :filter_enum_lt :filter_lt
133
+ alias :filter_datetime_lt :filter_lt
134
+
135
+ def filter_not_lt(scope, attribute, value)
136
+ filter_eq(scope, attribute, value, true, '<')
137
+ end
138
+
139
+ alias :filter_string_not_lt :filter_not_lt
140
+ alias :filter_integer_not_lt :filter_not_lt
141
+ alias :filter_float_not_lt :filter_not_lt
142
+ alias :filter_big_decimal_not_lt :filter_not_lt
143
+ alias :filter_date_not_lt :filter_not_lt
144
+ alias :filter_boolean_not_lt :filter_not_lt
145
+ alias :filter_uuid_not_lt :filter_not_lt
146
+ alias :filter_enum_not_lt :filter_not_lt
147
+ alias :filter_datetime_not_lt :filter_not_lt
148
+
149
+ def transaction(*)
150
+ yield
151
+ end
152
+
153
+ # def destroy(model_instance)
154
+ # super
155
+ # end
156
+
157
+ # def save(model_instance)
158
+ # pp model_instance
159
+ # end
160
+ #
161
+ # def build(model_class)
162
+ # model_class.new
163
+ # end
164
+ #
165
+ # def assign_attributes(model_instance, attributes)
166
+ # attributes.each_pair do |key, value|
167
+ # model_instance.send(:"#{key}=", value)
168
+ # end
169
+ # end
170
+
171
+ # def associate(parent, child, association_name, association_type)
172
+ # pp parent, children, association_name, association_type
173
+ # super
174
+ # end
175
+ #
176
+ # def associate_all(parent, children, association_name, association_type)
177
+ # pp parent, children, association_name, association_type
178
+ # super
179
+ # end
180
+ #
181
+ # def disassociate(parent, child, association_name, association_type)
182
+ # pp parent, children, association_name, association_type
183
+ # super
184
+ # end
185
+
186
+ def resolve(scope)
187
+ self.resource.model.before_read_proc&.call(scope)
188
+ query = self.resource.model.new().query.paging(scope).filter(scope).sort(scope)
189
+ data = query.find_all.map { |m|
190
+ m
191
+ }
192
+ self.resource.model.after_read_proc&.call(data)
193
+ data
194
+ end
195
+
196
+ # def associate_all(parent, children, association_name, association_type)
197
+ # children.each do |c|
198
+ # associate(parent, c, association_name, association_type)
199
+ # end
200
+ # end
201
+
202
+ # geeft fout als associate super gebruikt wordt
203
+ # http://127.0.0.1:9292/autocirculaties?filter%5Bgebruiker_id%5D%5Beq%5D=1221&include=uitleenformaat,wat_uitlenen
204
+ def associate(parent, child, association_name, association_type)
205
+ if activerecord_associate?(parent, child, association_name)
206
+ activerecord_adapter.associate \
207
+ parent, child, association_name, association_type
208
+ elsif [:has_many, :many_to_many].include?(association_type)
209
+ if parent.send(:"#{association_name}").nil?
210
+ parent.send(:"#{association_name}=", [child])
211
+ else
212
+ parent_child_data = parent.send(:"#{association_name}")
213
+
214
+ if parent_child_data.is_a?(Array)
215
+ parent_child_data = parent_child_data.map do |m|
216
+ m.id.eql?(child.id) ? child : m
217
+ end
218
+ else
219
+ if parent_child_data.id.eql?(child.id)
220
+ parent_child_data = [child]
221
+ # else
222
+ # parent_child_data = nil
223
+ end
224
+ end
225
+
226
+ parent.send(:"#{association_name}=", parent_child_data)
227
+ #parent.send(:"#{association_name}") << child
228
+ end
229
+ else
230
+ parent_child_data = parent.send(:"#{association_name}")
231
+
232
+ if parent_child_data.is_a?(Array)
233
+ parent_child_data = parent_child_data.map do |m|
234
+ m.id.eql?(child.id) ? child : m
235
+ end
236
+ else
237
+ if parent_child_data&.id.eql?(child.id)
238
+ parent_child_data = [child]
239
+ else
240
+ parent_child_data = nil
241
+ end
242
+ end
243
+
244
+ parent.send(:"#{association_name}=", parent_child_data)
245
+ end
246
+ end
247
+ end
248
+
249
+ class BelongsTo < Graphiti::Sideload::BelongsTo
250
+ def load_params(parents, query)
251
+ query.hash.tap do |hash|
252
+ hash[:filter] ||= {}
253
+ unless hash[:filter].include?(:id)
254
+ all_ids = parents.map{|m| m.instance_variable_get("@#{query.association_name.to_s}")}.flatten.map{|m| m.instance_variable_get("@#{primary_key}")}.uniq.compact.join(',')
255
+
256
+ hash[:filter].merge!({primary_key => all_ids})
257
+ end
258
+ end
259
+ end
260
+
261
+ private
262
+
263
+ # relations are included here
264
+ def children_for(parent, map)
265
+ map.values
266
+ end
267
+
268
+ # def child_map(children)
269
+ # children.index_by(&primary_key)
270
+ # end
271
+ #
272
+ # def children_for(parent, map)
273
+ # fk = parent.send(name).send(foreign_key) rescue nil #TODO: this is bad
274
+ # children = map[fk]
275
+ # return children if children
276
+ #
277
+ # keys = map.keys
278
+ # if fk.is_a?(String) && keys[0].is_a?(Integer)
279
+ # fk = fk.to_i
280
+ # elsif fk.is_a?(Integer) && keys[0].is_a?(String)
281
+ # fk = fk.to_s
282
+ # end
283
+ # map[fk] || []
284
+ # end
285
+ end
286
+
287
+
288
+ class HasMany < Graphiti::Sideload::HasMany
289
+ def inverse_filter
290
+ @inverse_filter || foreign_key
291
+ end
292
+
293
+ def load_params(parents, query)
294
+ query.hash.tap do |hash|
295
+ hash[:filter] ||= {}
296
+ unless hash[:filter].include?(:id)
297
+ all_ids = parents.map{|m| m.instance_variable_get("@#{query.association_name.to_s}")}.flatten.map{|m| m.instance_variable_get("@#{primary_key}")}.uniq.compact.join(',')
298
+
299
+ hash[:filter].merge!({primary_key => all_ids})
300
+ end
301
+ end
302
+ end
303
+
304
+ def children_for(parent, map)
305
+ map.values.flatten
306
+ end
307
+
308
+ def link_filter(parents)
309
+ {inverse_filter => parent_filter(parents)}
310
+ end
311
+
312
+ private
313
+
314
+ def parent_filter(parents)
315
+ ids_for_parents(parents).join(",")
316
+ end
317
+ end
318
+ end
@@ -0,0 +1,35 @@
1
+ module Solis
2
+ module Store
3
+ module Sparql
4
+ class Client
5
+ class Query
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def run(query)
11
+ result = @client.query(query)
12
+
13
+ if is_construct?(query)
14
+ repository = RDF::Repository.new
15
+ result.each { |s| repository << [s[:s], s[:p], s[:o]] }
16
+ result = SPARQL::Client.new(repository)
17
+ end
18
+
19
+ result
20
+ end
21
+
22
+ private
23
+
24
+ def is_construct?(query)
25
+ query =~ /construct/i
26
+ end
27
+
28
+ def is_insert?(query)
29
+ query =~ /insert/i
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,41 @@
1
+ require 'http'
2
+ require 'connection_pool'
3
+ require 'sparql'
4
+ require_relative 'client/query'
5
+
6
+ module Solis
7
+ module Store
8
+ module Sparql
9
+ class Client
10
+ def initialize(endpoint, graph_name)
11
+ @endpoint = endpoint
12
+ @graph_name = graph_name
13
+
14
+ @pool = ConnectionPool.new(size:5, timeout: 60) do
15
+ SPARQL::Client.new(@endpoint, graph: @graph_name)
16
+ #SPARQL::Client.new(@endpoint)
17
+ end
18
+ end
19
+
20
+ def up?
21
+ result = nil
22
+ @pool.with do |c|
23
+ result = c.query("ASK WHERE { ?s ?p ?o }")
24
+ end
25
+ result
26
+ rescue HTTP::Error => e
27
+ return false
28
+ end
29
+
30
+ def query(query)
31
+ raise Solis::Error::NotFoundError, "Server or graph(#{@graph_name} not found" unless up?
32
+ result = nil
33
+ @pool.with do |c|
34
+ result = Query.new(c).run(query)
35
+ end
36
+ result
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ module Solis
2
+ VERSION = "0.64.0"
3
+ end
data/lib/solis.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler"
2
+ Bundler.require
3
+
4
+ require 'logger'
5
+ require "solis/version"
6
+ require 'solis/config_file'
7
+ require "solis/error"
8
+ require 'solis/graph'
9
+ require 'solis/shape'
10
+
11
+ module Solis
12
+ LOGGER = Logger.new(STDOUT)
13
+ end
data/solis.gemspec ADDED
@@ -0,0 +1,50 @@
1
+ require_relative 'lib/solis/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'solis'
5
+ spec.version = Solis::VERSION
6
+ spec.authors = ['Mehmet Celik']
7
+ spec.email = ['mehmet@celik.be']
8
+
9
+ spec.summary = 'Creates a SHACL, RDF, PlantUML file from a Google sheet and a layer ontop of a data store(RDBMS, Triple store)'
10
+ spec.description = 'The SUN in latin or is it SILOS spelled backwards. Creates a SHACL, RDF, PlantUML file from a Google sheet and a layer ontop of a data store(RDBMS, Triple store)'
11
+ spec.homepage = 'https://github.com/mehmetc/solis'
12
+ spec.license = 'MIT'
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
14
+
15
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/mehmetc/solis'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/mehmetc/solis'
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.add_runtime_dependency 'activesupport', '~> 6.1'
31
+ spec.add_runtime_dependency 'http', '~> 5.1'
32
+ spec.add_runtime_dependency 'graphiti', '~> 1.3'
33
+ spec.add_runtime_dependency 'moneta', '~> 1.4'
34
+ spec.add_runtime_dependency 'linkeddata', '~> 3.2'
35
+ spec.add_runtime_dependency 'google_drive', '~> 3.0'
36
+ spec.add_runtime_dependency 'json', '~> 2.5'
37
+ spec.add_runtime_dependency 'hashdiff', '~> 1.0'
38
+ spec.add_runtime_dependency 'iso8601', '~> 0.13.0'
39
+ spec.add_runtime_dependency 'connection_pool', '~> 2.2.5'
40
+ spec.add_runtime_dependency 'uuidtools', '~> 2.2.0'
41
+ spec.add_runtime_dependency 'dry-struct', '~> 1.2'
42
+ spec.add_runtime_dependency 'psych', '< 4'
43
+
44
+ spec.add_development_dependency 'rake', '~> 13.0'
45
+ spec.add_development_dependency 'minitest', '~> 5.15.0'
46
+
47
+ # spec.add_development_dependency 'rubocop'
48
+
49
+ # spec.add_development_dependency 'webmock'
50
+ end