rdf-ordered-repo 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f43439c8ba4d9d9cb2376e134f91ac477800433d3fdc035a84ad557ce8f93d78
4
+ data.tar.gz: 266350c62103ab7c4d32cc25602bb7aa14499222f2ea085c1918e5e6952e8925
5
+ SHA512:
6
+ metadata.gz: 3942cd5d98be5cc13ebdb26fa7c155788466e2ab0f5051677aa18553e20230325bb8eda2cc2983c472f745addded4d0d356627d6dad09abd5704bd51e0d0b932
7
+ data.tar.gz: 7f19953b673e3e571f2c6a997d8ab6c6a771f099b176238775f276223912668917f7cb78877daeb23e6dee47217250f0f0007fcfe1835e84fe8343396375cf80
data/AUTHORS ADDED
@@ -0,0 +1 @@
1
+ * Gregg Kellogg <gregg@greggkellogg.net>
@@ -0,0 +1,57 @@
1
+ # RDF::OrderedRepo
2
+
3
+ An order-preserving repository for RDF.rb.
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/rdf-ordered-repo.png)](https://badge.fury.io/rb/rdf-ordered-repo)
6
+ [![Build Status](https://travis-ci.org/ruby-rdf/rdf-ordered-repo.png?branch=master)](https://travis-ci.org/ruby-rdf/rdf-ordered-repo)
7
+
8
+ ## Description
9
+
10
+ An in-memory implementation of RDF::Repository using native Ruby Hashes having insert-order preserving properties.
11
+
12
+ ## Examples
13
+
14
+ require 'rdf/ordered_repo'
15
+ require 'rdf/nquads'
16
+ repo = RDF::OrderedRepo.load("https://ruby-rdf.github.com/rdf/etc/doap.nq")
17
+
18
+ ## Dependencies
19
+
20
+ * [Ruby](https://ruby-lang.org/) (>= 2.4)
21
+ * [RDF.rb][] (~> 3.1)
22
+
23
+ ## Mailing List
24
+
25
+ * <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
26
+
27
+ ## Author
28
+
29
+ * [Gregg Kellogg](https://github.com/gkellogg) - <https://greggkellogg.net/>
30
+
31
+ ## Contributing
32
+ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
33
+
34
+ * Do your best to adhere to the existing coding conventions and idioms.
35
+ * Don't use hard tabs, and don't leave trailing whitespace on any line.
36
+ Before committing, run `git diff --check` to make sure of this.
37
+ * Do document every method you add using [YARD][] annotations. Read the
38
+ [tutorial][YARD-GS] or just look at the existing code for examples.
39
+ * Don't touch the `.gemspec` or `VERSION` files. If you need to change them,
40
+ do so on your private branch only.
41
+ * Do feel free to add yourself to the `CREDITS` file and the
42
+ corresponding list in the the `README`. Alphabetical order applies.
43
+ * Don't touch the `AUTHORS` file. If your contributions are significant
44
+ enough, be assured we will eventually add you in there.
45
+ * Do note that in order for us to merge any non-trivial changes (as a rule
46
+ of thumb, additions larger than about 15 lines of code), we need an
47
+ explicit [public domain dedication][PDD] on record from you.
48
+
49
+ ## License
50
+
51
+ This is free and unencumbered public domain software. For more information,
52
+ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
53
+
54
+ [RDF.rb]: https://ruby-rdf.github.com/
55
+ [YARD]: https://yardoc.org/
56
+ [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
57
+ [PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <https://unlicense.org>
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 3.1.0
@@ -0,0 +1,30 @@
1
+ @base <https://rubygems.org/gems/rdf-ordered-repo> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix dc: <http://purl.org/dc/terms/> .
5
+ @prefix foaf: <http://xmlns.com/foaf/0.1/> .
6
+ @prefix doap: <http://usefulinc.com/ns/doap#> .
7
+ @prefix ex: <http://example.org/> .
8
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
9
+
10
+ <> a doap:Project ;
11
+ doap:name "RDF::N3" ;
12
+ doap:homepage <https://github.com/ruby-rdf/rdf-ordered-repo> ;
13
+ doap:license <https://unlicense.org/1.0/> ;
14
+ doap:shortdesc "An order-preserving repository for RDF.rb."@en ;
15
+ doap:description "An in-memory implementation of RDF::Repository using native Ruby Hashes having insert-order preserving properties."@en ;
16
+ doap:created "2020-09-22"^^xsd:date;
17
+ doap:programming-language "Ruby" ;
18
+ doap:implements <http://www.w3.org/TR/rdf11-concepts/> ;
19
+ doap:category <http://dbpedia.org/resource/Resource_Description_Framework>,
20
+ <http://dbpedia.org/resource/Ruby_(programming_language)> ;
21
+ doap:download-page <> ;
22
+ doap:mailing-list <https://lists.w3.org/Archives/Public/public-rdf-ruby/> ;
23
+ doap:bug-database <https://github.com/ruby-rdf/rdf-ordered-repo/issues> ;
24
+ doap:blog <https://greggkellogg.net/> ;
25
+ doap:developer <https://greggkellogg.net/foaf#me> ;
26
+ doap:helper <http://njh.me/> ;
27
+ doap:maintainer <https://greggkellogg.net/foaf#me> ;
28
+ doap:documenter <https://greggkellogg.net/foaf#me> ;
29
+ foaf:maker <https://greggkellogg.net/foaf#me> ;
30
+ dc:creator <https://greggkellogg.net/foaf#me> .
@@ -0,0 +1,310 @@
1
+ require 'rdf'
2
+
3
+ module RDF
4
+ ##
5
+ # Sub-class of RDF::Repository with order-preserving properties.
6
+ class OrderedRepo < RDF::Repository
7
+ DEFAULT_GRAPH = false
8
+
9
+ ##
10
+ # Initializes this repository instance.
11
+ #
12
+ # @param [URI, #to_s] uri (nil)
13
+ # @param [String, #to_s] title (nil)
14
+ # @param [Hash{Symbol => Object}] options
15
+ # @option options [Boolean] :with_graph_name (true)
16
+ # Indicates that the repository supports named graphs, otherwise,
17
+ # only the default graph is supported.
18
+ # @option options [Boolean] :with_validity (true)
19
+ # Indicates that the repository supports named validation.
20
+ # @option options [Boolean] :transaction_class (DEFAULT_TX_CLASS)
21
+ # Specifies the RDF::Transaction implementation to use in this Repository.
22
+ # @yield [repository]
23
+ # @yieldparam [Repository] repository
24
+ def initialize(uri: nil, title: nil, **options, &block)
25
+ @data = options.delete(:data) || {}
26
+ super do
27
+ if block_given?
28
+ case block.arity
29
+ when 1 then block.call(self)
30
+ else instance_eval(&block)
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ ##
37
+ # Returns `true` if this respository supports the given `feature`.
38
+ #
39
+ # This repository supports list_terms.
40
+ def supports?(feature)
41
+ case feature.to_sym
42
+ when :rdfstar then true
43
+ when :snapshots then false
44
+ else super
45
+ end
46
+ end
47
+
48
+ ##
49
+ # Creates a query from the statements in this repository, turning blank nodes into non-distinguished variables. This can be used to determine if this repository is logically a subset of another repository.
50
+ #
51
+ # @return [RDF::Query]
52
+ def to_query
53
+ RDF::Query.new do |query|
54
+ each do |statement|
55
+ query.pattern RDF::Query::Pattern.from(statement, ndvars: true)
56
+ end
57
+ end
58
+ end
59
+
60
+ ##
61
+ # @private
62
+ # @see RDF::Countable#count
63
+ def count
64
+ count = 0
65
+ @data.each do |_, ss|
66
+ ss.each do |_, ps|
67
+ ps.each { |_, os| count += os.size }
68
+ end
69
+ end
70
+ count
71
+ end
72
+
73
+ ##
74
+ # @private
75
+ # @see RDF::Enumerable#has_graph?
76
+ def has_graph?(graph)
77
+ @data.has_key?(graph)
78
+ end
79
+
80
+ ##
81
+ # @private
82
+ # @see RDF::Enumerable#each_graph
83
+ def graph_names(options = nil, &block)
84
+ @data.keys.reject { |g| g == DEFAULT_GRAPH }.to_a
85
+ end
86
+
87
+ ##
88
+ # @private
89
+ # @see RDF::Enumerable#each_graph
90
+ def each_graph(&block)
91
+ if block_given?
92
+ @data.each_key do |gn|
93
+ yield RDF::Graph.new(graph_name: (gn == DEFAULT_GRAPH ? nil : gn), data: self)
94
+ end
95
+ end
96
+ enum_graph
97
+ end
98
+
99
+ ##
100
+ # @private
101
+ # @see RDF::Enumerable#has_statement?
102
+ def has_statement?(statement)
103
+ has_statement_in?(@data, statement)
104
+ end
105
+
106
+ ##
107
+ # @private
108
+ # @see RDF::Enumerable#each_statement
109
+ def each_statement(&block)
110
+ if block_given?
111
+ @data.each do |g, ss|
112
+ ss.each do |s, ps|
113
+ ps.each do |p, os|
114
+ os.each do |o, object_options|
115
+ yield RDF::Statement.new(s, p, o, object_options.merge(graph_name: g.equal?(DEFAULT_GRAPH) ? nil : g))
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ enum_statement
122
+ end
123
+ alias_method :each, :each_statement
124
+
125
+ ##
126
+ # @see Mutable#apply_changeset
127
+ def apply_changeset(changeset)
128
+ data = @data
129
+ changeset.deletes.each do |del|
130
+ if del.constant?
131
+ data = delete_from(data, del)
132
+ else
133
+ # we need this condition to handle wildcard statements
134
+ query_pattern(del) { |stmt| data = delete_from(data, stmt) }
135
+ end
136
+ end
137
+ changeset.inserts.each { |ins| data = insert_to(data, ins) }
138
+ @data = data
139
+ end
140
+
141
+ ##
142
+ # @see RDF::Dataset#isolation_level
143
+ def isolation_level
144
+ :serializable
145
+ end
146
+
147
+ protected
148
+
149
+ ##
150
+ # Match elements with `eql?`, not `==`
151
+ #
152
+ # `graph_name` of `false` matches default graph. Unbound variable matches
153
+ # non-false graph name.
154
+ #
155
+ # Matches terms which are native lists.
156
+ #
157
+ # @private
158
+ # @see RDF::Queryable#query_pattern
159
+ def query_pattern(pattern, **options, &block)
160
+ if block_given?
161
+ graph_name = pattern.graph_name
162
+ subject = pattern.subject
163
+ predicate = pattern.predicate
164
+ object = pattern.object
165
+
166
+ cs = @data.has_key?(graph_name) ? { graph_name => @data[graph_name] } : @data
167
+
168
+ cs.each do |c, ss|
169
+ next unless graph_name.nil? ||
170
+ graph_name == DEFAULT_GRAPH && !c ||
171
+ graph_name.eql?(c)
172
+
173
+ ss = if subject.nil? || subject.is_a?(RDF::Query::Variable)
174
+ ss
175
+ elsif subject.is_a?(RDF::Query::Pattern)
176
+ # Match subjects which are statements matching this pattern
177
+ ss.keys.select {|s| s.statement? && subject.eql?(s)}.inject({}) do |memo, st|
178
+ memo.merge(st => ss[st])
179
+ end
180
+ elsif ss.has_key?(subject)
181
+ { subject => ss[subject] }
182
+ else
183
+ []
184
+ end
185
+ ss.each do |s, ps|
186
+ ps = if predicate.nil? || predicate.is_a?(RDF::Query::Variable)
187
+ ps
188
+ elsif ps.has_key?(predicate)
189
+ { predicate => ps[predicate] }
190
+ else
191
+ []
192
+ end
193
+ ps.each do |p, os|
194
+ os.each do |o, object_options|
195
+ next unless object.nil? || object.eql?(o)
196
+ yield RDF::Statement.new(s, p, o, object_options.merge(graph_name: c.equal?(DEFAULT_GRAPH) ? nil : c))
197
+ end
198
+ end
199
+ end
200
+ end
201
+ else
202
+ enum_for(:query_pattern, pattern, **options)
203
+ end
204
+ end
205
+
206
+ ##
207
+ # @private
208
+ # @see RDF::Mutable#insert
209
+ def insert_statement(statement)
210
+ @data = insert_to(@data, statement)
211
+ end
212
+
213
+ ##
214
+ # @private
215
+ # @see RDF::Mutable#delete
216
+ def delete_statement(statement)
217
+ @data = delete_from(@data, statement)
218
+ end
219
+
220
+ ##
221
+ # @private
222
+ # @see RDF::Mutable#clear
223
+ def clear_statements
224
+ @data = @data.clear
225
+ end
226
+
227
+ ##
228
+ # @private
229
+ # @return [Hash]
230
+ def data
231
+ @data
232
+ end
233
+
234
+ ##
235
+ # @private
236
+ # @return [Hash]
237
+ def data=(hash)
238
+ @data = hash
239
+ end
240
+
241
+ private
242
+
243
+ ##
244
+ # @private
245
+ # @see #has_statement
246
+ def has_statement_in?(data, statement)
247
+ s, p, o, g = statement.to_quad
248
+ g ||= DEFAULT_GRAPH
249
+
250
+ data.has_key?(g) &&
251
+ data[g].has_key?(s) &&
252
+ data[g][s].has_key?(p) &&
253
+ data[g][s][p].has_key?(o)
254
+ end
255
+
256
+ ##
257
+ # @private
258
+ # @return [Hash] a new, updated hash
259
+ def insert_to(data, statement)
260
+ raise ArgumentError, "Statement #{statement.inspect} is incomplete" if statement.incomplete?
261
+
262
+ unless has_statement_in?(data, statement)
263
+ s, p, o, c = statement.to_quad
264
+ c ||= DEFAULT_GRAPH
265
+
266
+ data = data.has_key?(c) ? data.dup : data.merge(c => {})
267
+ data[c] = data[c].has_key?(s) ? data[c].dup : data[c].merge(s => {})
268
+ data[c][s] = data[c][s].has_key?(p) ? data[c][s].dup : data[c][s].merge(p => {})
269
+ data[c][s][p] = data[c][s][p].merge(o => statement.options)
270
+ end
271
+ data
272
+ end
273
+
274
+ ##
275
+ # @private
276
+ # @return [Hash] a new, updated hash
277
+ def delete_from(data, statement)
278
+ if has_statement_in?(data, statement)
279
+ s, p, o, g = statement.to_quad
280
+ g = DEFAULT_GRAPH unless supports?(:graph_name)
281
+ g ||= DEFAULT_GRAPH
282
+
283
+ os = data[g][s][p].dup.delete(o)
284
+ ps = os.empty? ? data[g][s].dup.delete_if {|k,v| k == p} : data[g][s].merge(p => os)
285
+ ss = ps.empty? ? data[g].dup.delete_if {|k,v| k == s} : data[g].merge(s => ps)
286
+ return ss.empty? ? data.dup.delete_if {|k,v| k == g} : data.merge(g => ss)
287
+ end
288
+ data
289
+ end
290
+
291
+ module VERSION
292
+ VERSION_FILE = File.expand_path("../../../VERSION", __FILE__)
293
+ MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chop.split(".")
294
+
295
+ STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')
296
+
297
+ ##
298
+ # @return [String]
299
+ def self.to_s() STRING end
300
+
301
+ ##
302
+ # @return [String]
303
+ def self.to_str() STRING end
304
+
305
+ ##
306
+ # @return [Array(Integer, Integer, Integer)]
307
+ def self.to_a() STRING.split(".") end
308
+ end
309
+ end
310
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rdf-ordered-repo
3
+ version: !ruby/object:Gem::Version
4
+ version: 3.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gregg Kellogg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-09-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rdf
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdf-spec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.20
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.20
69
+ description: An in-memory implementation of RDF::Repository using native Ruby Hashes
70
+ having insert-order preserving properties.
71
+ email: public-rdf-ruby@w3.org
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - AUTHORS
77
+ - README.md
78
+ - UNLICENSE
79
+ - VERSION
80
+ - etc/doap.ttl
81
+ - lib/rdf/ordered_repo.rb
82
+ homepage: https://github.com/ruby-rdf/rdf-ordered-repo
83
+ licenses:
84
+ - Unlicense
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '2.4'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.1.3
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: An order-preserving repository for RDF.rb.
105
+ test_files: []