active-triples 0.10.2 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGES.md +17 -11
- data/README.md +72 -39
- data/lib/active_triples/configurable.rb +6 -1
- data/lib/active_triples/list.rb +1 -4
- data/lib/active_triples/nested_attributes.rb +10 -7
- data/lib/active_triples/persistable.rb +13 -0
- data/lib/active_triples/persistence_strategies/parent_strategy.rb +47 -34
- data/lib/active_triples/persistence_strategies/persistence_strategy.rb +14 -1
- data/lib/active_triples/properties.rb +19 -4
- data/lib/active_triples/property_builder.rb +4 -4
- data/lib/active_triples/rdf_source.rb +142 -189
- data/lib/active_triples/relation.rb +307 -156
- data/lib/active_triples/util/buffered_transaction.rb +126 -0
- data/lib/active_triples/util/extended_bounded_description.rb +75 -0
- data/lib/active_triples/version.rb +1 -1
- data/spec/active_triples/configurable_spec.rb +35 -7
- data/spec/active_triples/identifiable_spec.rb +19 -6
- data/spec/active_triples/list_spec.rb +15 -7
- data/spec/active_triples/nested_attributes_spec.rb +12 -10
- data/spec/active_triples/persistable_spec.rb +0 -4
- data/spec/active_triples/persistence_strategies/parent_strategy_spec.rb +57 -10
- data/spec/active_triples/rdf_source_spec.rb +137 -97
- data/spec/active_triples/relation_spec.rb +436 -132
- data/spec/active_triples/resource_spec.rb +8 -23
- data/spec/active_triples/util/buffered_transaction_spec.rb +187 -0
- data/spec/active_triples/util/extended_bounded_description_spec.rb +98 -0
- data/spec/integration/reciprocal_properties_spec.rb +10 -10
- data/spec/support/matchers.rb +13 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b09ad8aa6210e931834cd37965ea5664d84ef2e3
|
4
|
+
data.tar.gz: 0a33346408aaf322d817c8cb2081a2c7542ef0da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35628f4606ba23ab183d20d2bd6bc67ee39b1285b5c21e1d4d19bc9b3316ed7af3b55fdf2b44b8a431129a2a778f6e7c8c403c934d308dba9fb34843f7fac599
|
7
|
+
data.tar.gz: b8c3662e7f66c4e720e1b8db88314bd6f7b931e8a7b127f393f44e8ce8969ddcd607171abd03505f18fba25972235e6bc7288dd9943b7c2ef7bd385cc9626c73
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,16 +1,22 @@
|
|
1
|
-
0.
|
1
|
+
0.11.0
|
2
2
|
----
|
3
|
-
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
- Reworks ParentStrategy to use an Transaction over a well defined
|
4
|
+
"extended bounded description".
|
5
|
+
- Converts Relation to an Enumerable for more efficient access to
|
6
|
+
property values.
|
7
|
+
- Cleans up .Relation equality and added `#|` & `#&` for Set style
|
8
|
+
comparison.
|
9
|
+
- Deprecates `Relation#first_or_create`.
|
10
|
+
- Removes dependency on the `linkeddata` gem. Users should require
|
11
|
+
individual RDF libraries as needed.
|
12
|
+
- Adds inheritance of configured types when subclassing an
|
13
|
+
`RDFSource`.
|
14
|
+
- Uses `URI#intern` to avoid repeated allocations of common URIs.
|
15
|
+
- Changes handling of language and datatyped Literals in
|
16
|
+
`Relation#each` & `#to_a`;
|
17
|
+
- now returns `RDF::Literal` for lanugage tagged strings and
|
18
|
+
for unknown datatypes.
|
9
19
|
|
10
|
-
0.10.1
|
11
|
-
----
|
12
|
-
- Remove dependency on the `linkeddata` metagem
|
13
|
-
|
14
20
|
0.10.0
|
15
21
|
----
|
16
22
|
- Fix Identifiable for ActiveFedora [Trey Pendragon]
|
data/README.md
CHANGED
@@ -23,36 +23,47 @@ The core module of `ActiveTriples` is `ActiveTriples::RDFSource`. You can use th
|
|
23
23
|
|
24
24
|
|
25
25
|
```ruby
|
26
|
+
require 'rdf/vocab'
|
27
|
+
|
26
28
|
class Thing
|
27
29
|
include ActiveTriples::RDFSource
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
|
31
|
+
configure type: RDF::OWL.Thing, base_uri: 'http://example.org/things#'
|
32
|
+
|
33
|
+
property :title, predicate: RDF::Vocab::DC.title
|
34
|
+
property :description, predicate: RDF::Vocab::DC.description
|
31
35
|
end
|
32
36
|
|
33
|
-
obj
|
34
|
-
obj.title
|
37
|
+
obj = Thing.new('123')
|
38
|
+
obj.title = 'Resource'
|
35
39
|
obj.description = 'A resource.'
|
40
|
+
|
36
41
|
obj.dump :ntriples # => "<http://example.org/things#123> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#123> <http://purl.org/dc/terms/title> \"Resource\" .\n<http://example.org/things#123> <http://purl.org/dc/terms/description> \"A resource.\" .\n"
|
37
42
|
```
|
43
|
+
|
38
44
|
URI and bnode values are built out as generic Resources when accessed. A more specific model class can be configured on individual properties.
|
39
45
|
|
40
46
|
```ruby
|
41
|
-
Thing.property :creator, :
|
47
|
+
Thing.property :creator, predicate: RDF::Vocab::DC.creator, class_name: 'Person'
|
42
48
|
|
43
49
|
class Person
|
44
50
|
include ActiveTriples::RDFSource
|
45
|
-
|
46
|
-
|
51
|
+
|
52
|
+
configure type: RDF::Vocab::FOAF.Person,
|
53
|
+
base_uri: 'http://example.org/people#'
|
54
|
+
|
55
|
+
property :name, predicate: RDF::Vocab::FOAF.name
|
47
56
|
end
|
48
57
|
|
49
|
-
obj_2
|
58
|
+
obj_2 = Thing.new('2')
|
50
59
|
obj_2.creator = Person.new
|
60
|
+
|
51
61
|
obj_2.creator
|
52
62
|
# => [#<Person:0x3fbe84ac9234(default)>]
|
53
63
|
|
54
64
|
obj_2.creator.first.name = 'Herman Melville'
|
55
|
-
|
65
|
+
|
66
|
+
obj_2.dump :ntriples # => "_:g47361345336040 <http://xmlns.com/foaf/0.1/name> \"Herman Melville\" .\n_:g47361345336040 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .\n<http://example.org/things#2> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .\n<http://example.org/things#2> <http://purl.org/dc/terms/creator> _:g47361345336040 .\n"
|
56
67
|
```
|
57
68
|
|
58
69
|
Open Model
|
@@ -63,23 +74,33 @@ An RDFSource lets you handle data as a graph, independent of whether it is defin
|
|
63
74
|
```ruby
|
64
75
|
related = Thing.new
|
65
76
|
|
66
|
-
related << RDF::Statement(related, RDF::DC.relation, obj)
|
67
|
-
related << RDF::Statement(related, RDF::DC.subject, 'ActiveTriples')
|
77
|
+
related << RDF::Statement(related, RDF::Vocab::DC.relation, obj)
|
78
|
+
related << RDF::Statement(related, RDF::Vocab::DC.subject, 'ActiveTriples')
|
68
79
|
|
69
|
-
related.query(:
|
70
|
-
|
71
|
-
|
80
|
+
related.query(subject: related,
|
81
|
+
predicate: RDF::Vocab::DC.relation).each_statement do |s,p,o|
|
82
|
+
puts o
|
83
|
+
end
|
72
84
|
# => http://example.org/things#123
|
85
|
+
|
86
|
+
related.query(subject: related,
|
87
|
+
predicate: RDF::Vocab::DC.subject).each_statement do |s,p,o|
|
88
|
+
puts o
|
89
|
+
end
|
90
|
+
# => 'ActiveTriples'
|
73
91
|
```
|
74
92
|
|
75
93
|
Any operation you can run against an RDF::Graph works with RDFSources, too. Or you can use generic setters and getters with URI predicates:
|
76
94
|
|
77
95
|
```ruby
|
78
|
-
related.set_value(RDF::DC.relation, obj)
|
79
|
-
related.set_value(RDF::DC.subject,
|
96
|
+
related.set_value(RDF::Vocab::DC.relation, obj)
|
97
|
+
related.set_value(RDF::Vocab::DC.subject, 'ActiveTriples')
|
98
|
+
|
99
|
+
related.get_values(RDF::Vocab::DC.relation)
|
100
|
+
# => [#<Thing:0x3f949c6a2294(default)>]
|
80
101
|
|
81
|
-
related.get_values(RDF::DC.
|
82
|
-
|
102
|
+
related.get_values(RDF::Vocab::DC.subject)
|
103
|
+
# => ["ActiveTriples"]
|
83
104
|
```
|
84
105
|
|
85
106
|
Some convienience methods provide support for handling data from web sources:
|
@@ -89,10 +110,13 @@ Some convienience methods provide support for handling data from web sources:
|
|
89
110
|
```ruby
|
90
111
|
require 'linkeddata' # to support various serializations
|
91
112
|
|
92
|
-
|
113
|
+
uri = 'http://dbpedia.org/resource/Oregon_State_University'
|
114
|
+
|
115
|
+
osu = ActiveTriples::Resource.new uri
|
93
116
|
osu.fetch
|
94
117
|
|
95
|
-
osu.rdf_label
|
118
|
+
osu.rdf_label
|
119
|
+
# => ["Oregon State University", "Oregon State University", "Université d'État de l'Oregon", "Oregon State University", "Oregon State University", "オレゴン州立大学", "Universidad Estatal de Oregón", "Oregon State University", "俄勒岡州立大學", "Universidade do Estado do Oregon"]
|
96
120
|
```
|
97
121
|
|
98
122
|
Typed Data
|
@@ -101,9 +125,9 @@ Typed Data
|
|
101
125
|
Typed literals are handled natively through Ruby types and [RDF::Literal](https://github.com/ruby-rdf/rdf/tree/develop/lib/rdf/model/literal). There is no need to register a specific type for a property, simply pass the setter the appropriate typed data. See the examples in the RDF::Literal documentation for futher information about supported datatypes.
|
102
126
|
|
103
127
|
```ruby
|
104
|
-
Thing.property :date, :
|
128
|
+
Thing.property :date, predicate: RDF::Vocab::DC.date
|
105
129
|
|
106
|
-
my_thing
|
130
|
+
my_thing = Thing.new
|
107
131
|
my_thing.date = Date.today
|
108
132
|
|
109
133
|
puts my_thing.dump :ntriples
|
@@ -143,38 +167,47 @@ Resources can persist to various databases and triplestores though integration w
|
|
143
167
|
# RDF::Repository support persistence to (e.g.) triplestores & NoSQL
|
144
168
|
# databases.
|
145
169
|
ActiveTriples::Repositories.add_repository :default, RDF::Repository.new
|
146
|
-
ActiveTriples::Repositories.add_repository :people,
|
170
|
+
ActiveTriples::Repositories.add_repository :people, RDF::Repository.new
|
147
171
|
|
148
172
|
class Person
|
149
173
|
include ActiveTriples::RDFSource
|
150
|
-
|
151
|
-
|
174
|
+
|
175
|
+
configure type: RDF::Vocab::FOAF.Person,
|
176
|
+
base_uri: 'http://example.org/people#',
|
177
|
+
repository: :people
|
178
|
+
property :name, predicate: RDF::Vocab::FOAF.name
|
152
179
|
end
|
153
180
|
|
154
181
|
class Thing
|
155
182
|
include ActiveTriples::RDFSource
|
156
183
|
|
157
|
-
configure :
|
158
|
-
|
159
|
-
|
160
|
-
|
184
|
+
configure type: RDF::OWL.Thing,
|
185
|
+
base_uri: 'http://example.org/things#',
|
186
|
+
repository: :default
|
187
|
+
|
188
|
+
property :title, predicate: RDF::Vocab::DC.title
|
189
|
+
property :description, predicate: RDF::Vocab::DC.description
|
190
|
+
property :creator, predicate: RDF::Vocab::DC.creator, class_name: 'Person'
|
161
191
|
end
|
162
192
|
|
163
|
-
t
|
164
|
-
t.title
|
193
|
+
t = Thing.new('1')
|
194
|
+
t.title = 'A Thing'
|
165
195
|
t.creator = Person.new('1')
|
196
|
+
|
166
197
|
t.persisted? # => false
|
167
|
-
t.creator.first.name = 'Tove'
|
168
|
-
t.persist!
|
169
198
|
|
170
199
|
ActiveTriples::Repositories.repositories[:default].dump :ntriples
|
171
|
-
# => "
|
200
|
+
# => ""
|
172
201
|
|
173
|
-
t.creator.first.
|
174
|
-
t.
|
202
|
+
t.creator.first.name = 'Tove'
|
203
|
+
t.persist!
|
175
204
|
|
176
|
-
ActiveTriples::Repositories.repositories[:
|
177
|
-
#
|
205
|
+
puts ActiveTriples::Repositories.repositories[:default].dump :ntriples
|
206
|
+
# <http://example.org/things#1> <http://purl.org/dc/terms/title> "A Thing" .
|
207
|
+
# <http://example.org/things#1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#Thing> .
|
208
|
+
# <http://example.org/things#1> <http://purl.org/dc/terms/creator> <http://example.org/people#1> .
|
209
|
+
# <http://example.org/people#1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://xmlns.com/foaf/0.1/Person> .
|
210
|
+
# <http://example.org/people#1> <http://xmlns.com/foaf/0.1/name> "Tove" .
|
178
211
|
```
|
179
212
|
|
180
213
|
Contributing
|
@@ -14,6 +14,11 @@ module ActiveTriples
|
|
14
14
|
#
|
15
15
|
# Available properties are base_uri, rdf_label, type, and repository
|
16
16
|
module Configurable
|
17
|
+
def inherited(child_class)
|
18
|
+
child_class.configure type: self.type
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
17
22
|
def base_uri
|
18
23
|
configuration[:base_uri]
|
19
24
|
end
|
@@ -62,7 +67,7 @@ module ActiveTriples
|
|
62
67
|
|
63
68
|
def transform_type(values)
|
64
69
|
Array.wrap(values).map do |value|
|
65
|
-
RDF::URI.
|
70
|
+
RDF::URI.intern(value).tap do |uri|
|
66
71
|
RDFSource.type_registry[uri] = self
|
67
72
|
end
|
68
73
|
end
|
data/lib/active_triples/list.rb
CHANGED
@@ -37,15 +37,15 @@ module ActiveTriples
|
|
37
37
|
# { name: 'John' },
|
38
38
|
# { id: '2', _destroy: true }
|
39
39
|
# ])
|
40
|
-
def assign_nested_attributes_for_collection_association(association_name,
|
40
|
+
def assign_nested_attributes_for_collection_association(association_name,
|
41
|
+
attributes_collection)
|
41
42
|
options = self.nested_attributes_options[association_name]
|
42
43
|
|
43
44
|
# TODO
|
44
45
|
#check_record_limit!(options[:limit], attributes_collection)
|
45
46
|
|
46
|
-
|
47
|
-
attributes_collection
|
48
|
-
end
|
47
|
+
attributes_collection = attributes_collection.values if
|
48
|
+
attributes_collection.is_a?(Hash)
|
49
49
|
|
50
50
|
association = self.send(association_name)
|
51
51
|
|
@@ -53,8 +53,9 @@ module ActiveTriples
|
|
53
53
|
attributes = attributes.with_indifferent_access
|
54
54
|
|
55
55
|
if !call_reject_if(association_name, attributes)
|
56
|
-
if attributes['id'] &&
|
57
|
-
|
56
|
+
if attributes['id'] &&
|
57
|
+
existing_record = association.detect { |record| record.rdf_subject.to_s == attributes['id'].to_s }
|
58
|
+
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
58
59
|
else
|
59
60
|
association.build(attributes.except(*UNASSIGNABLE_KEYS))
|
60
61
|
end
|
@@ -66,7 +67,9 @@ module ActiveTriples
|
|
66
67
|
# +allow_destroy+ is +true+ and has_destroy_flag? returns +true+.
|
67
68
|
def assign_to_or_mark_for_destruction(record, attributes, allow_destroy)
|
68
69
|
record.attributes = attributes.except(*UNASSIGNABLE_KEYS)
|
69
|
-
|
70
|
+
|
71
|
+
record.mark_for_destruction if has_destroy_flag?(attributes) &&
|
72
|
+
allow_destroy
|
70
73
|
end
|
71
74
|
|
72
75
|
def call_reject_if(association_name, attributes)
|
@@ -14,6 +14,19 @@ module ActiveTriples
|
|
14
14
|
include RDF::Enumerable
|
15
15
|
include RDF::Mutable
|
16
16
|
|
17
|
+
##
|
18
|
+
# This gives the {RDF::Graph} which represents the current state of this
|
19
|
+
# resource.
|
20
|
+
#
|
21
|
+
# @return [RDF::Graph] the underlying graph representation of the
|
22
|
+
# `RDFSource`.
|
23
|
+
#
|
24
|
+
# @see http://www.w3.org/TR/2014/REC-rdf11-concepts-20140225/#change-over-time
|
25
|
+
# RDF Concepts and Abstract Syntax comment on "RDF source"
|
26
|
+
def graph
|
27
|
+
persistence_strategy.graph
|
28
|
+
end
|
29
|
+
|
17
30
|
##
|
18
31
|
# @see RDF::Enumerable.each
|
19
32
|
def each(*args)
|
@@ -1,4 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'active_triples/util/buffered_transaction'
|
3
|
+
|
2
4
|
module ActiveTriples
|
3
5
|
##
|
4
6
|
# Persistence strategy for projecting `RDFSource`s onto the graph of an owning
|
@@ -17,9 +19,31 @@ module ActiveTriples
|
|
17
19
|
# @param source [RDFSource, RDF::Enumerable] the `RDFSource` (or other
|
18
20
|
# `RDF::Enumerable` to persist with the strategy.
|
19
21
|
def initialize(source)
|
22
|
+
@graph = source.graph
|
20
23
|
@source = source
|
21
24
|
end
|
22
25
|
|
26
|
+
##
|
27
|
+
# @see PeristenceStrategy#graph=
|
28
|
+
def graph=(graph)
|
29
|
+
final_parent.insert(graph || source.to_a)
|
30
|
+
@graph = BufferedTransaction.begin(parent,
|
31
|
+
mutable: true,
|
32
|
+
subject: source.to_term)
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# @return [ActiveTriples::BufferedTransaction] a transaction on parent with
|
37
|
+
# buffered changes, with reads projected against an "Extended Bounded
|
38
|
+
# Description" of the strategy's `#source`.
|
39
|
+
#
|
40
|
+
# @see ActiveTriples::ExtendedBoundedDescription
|
41
|
+
def graph
|
42
|
+
@graph ||= BufferedTransaction.begin(parent,
|
43
|
+
mutable: true,
|
44
|
+
subject: source.to_term)
|
45
|
+
end
|
46
|
+
|
23
47
|
##
|
24
48
|
# Resources using this strategy are persisted only if their parent is also
|
25
49
|
# persisted.
|
@@ -29,41 +53,23 @@ module ActiveTriples
|
|
29
53
|
super && parent.persisted?
|
30
54
|
end
|
31
55
|
|
32
|
-
##
|
33
|
-
# Indicates if the resource has been loaded from the repository (used for lazy load)
|
34
|
-
#
|
35
|
-
# @return [Boolean] true if loaded; else false.
|
36
|
-
def loaded?
|
37
|
-
@loaded ||= false
|
38
|
-
end
|
39
|
-
|
40
56
|
##
|
41
57
|
# Destroys the resource by removing it graph and references from the
|
42
58
|
# parent.
|
43
59
|
#
|
44
60
|
# @see PersistenceStrategy#destroy
|
45
61
|
def destroy
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
parent.delete_statement(statement) if
|
50
|
-
statement.subject == source.rdf_subject ||
|
51
|
-
statement.object == source.rdf_subject
|
62
|
+
super do
|
63
|
+
graph.delete [source.to_term, nil, nil]
|
64
|
+
parent.delete [parent, nil, source.to_term]
|
52
65
|
end
|
53
|
-
|
54
|
-
super { source.clear }
|
55
66
|
end
|
56
67
|
|
57
68
|
##
|
58
69
|
# @abstract Clear out any old assertions in the datastore / repository
|
59
|
-
# about this node
|
70
|
+
# about this node or statement thus preparing to receive the updated
|
60
71
|
# assertions.
|
61
|
-
def erase_old_resource
|
62
|
-
final_parent.statements.each do |statement|
|
63
|
-
final_parent.send(:delete_statement, statement) if
|
64
|
-
statement.subject == source.rdf_subject
|
65
|
-
end
|
66
|
-
end
|
72
|
+
def erase_old_resource; end # noop
|
67
73
|
|
68
74
|
##
|
69
75
|
# @return [Enumerator<RDFSource>]
|
@@ -87,7 +93,9 @@ module ActiveTriples
|
|
87
93
|
def parent=(parent)
|
88
94
|
raise UnmutableParentError unless parent.is_a? RDF::Mutable
|
89
95
|
raise UnmutableParentError unless parent.mutable?
|
96
|
+
|
90
97
|
@parent = parent
|
98
|
+
reload
|
91
99
|
end
|
92
100
|
|
93
101
|
##
|
@@ -95,9 +103,16 @@ module ActiveTriples
|
|
95
103
|
#
|
96
104
|
# @return [true] true if the save did not error
|
97
105
|
def persist!
|
106
|
+
raise NilParentError unless parent
|
98
107
|
return false if final_parent.frozen?
|
99
|
-
|
100
|
-
|
108
|
+
|
109
|
+
graph.execute
|
110
|
+
|
111
|
+
parent.persist! if
|
112
|
+
ancestors.find { |a| a.is_a?(ActiveTriples::List::ListResource) }
|
113
|
+
|
114
|
+
reload
|
115
|
+
|
101
116
|
@persisted = true
|
102
117
|
end
|
103
118
|
|
@@ -107,14 +122,12 @@ module ActiveTriples
|
|
107
122
|
# @return [Boolean]
|
108
123
|
def reload
|
109
124
|
return false if source.frozen?
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
@persisted = true unless source.empty?
|
125
|
+
|
126
|
+
final_parent.persistence_strategy.class.new(source).reload
|
127
|
+
self.graph = source.to_a
|
128
|
+
|
129
|
+
@persisted = true unless graph.empty?
|
130
|
+
|
118
131
|
true
|
119
132
|
end
|
120
133
|
|
@@ -132,7 +145,7 @@ module ActiveTriples
|
|
132
145
|
def initialize(source)
|
133
146
|
@source = source
|
134
147
|
end
|
135
|
-
|
148
|
+
|
136
149
|
##
|
137
150
|
# @yield [RDFSource] gives each ancestor to the block
|
138
151
|
# @return [Enumerator<RDFSource>]
|