solis 0.64.0

Sign up to get free protection for your applications and to get access to all the features.
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