rdf 2.2.12 → 3.0.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 +5 -5
- data/README.md +1 -1
- data/VERSION +1 -1
- data/lib/rdf.rb +1 -1
- data/lib/rdf/format.rb +97 -66
- data/lib/rdf/mixin/enumerable.rb +0 -17
- data/lib/rdf/mixin/enumerator.rb +0 -34
- data/lib/rdf/model/literal/date.rb +1 -1
- data/lib/rdf/model/literal/datetime.rb +1 -1
- data/lib/rdf/model/literal/decimal.rb +1 -1
- data/lib/rdf/model/literal/double.rb +1 -1
- data/lib/rdf/model/literal/integer.rb +1 -1
- data/lib/rdf/model/literal/time.rb +1 -1
- data/lib/rdf/model/node.rb +3 -14
- data/lib/rdf/model/statement.rb +0 -28
- data/lib/rdf/model/uri.rb +3 -24
- data/lib/rdf/query.rb +23 -8
- data/lib/rdf/query/pattern.rb +6 -12
- data/lib/rdf/query/solution.rb +2 -14
- data/lib/rdf/query/variable.rb +0 -21
- data/lib/rdf/util/file.rb +1 -2
- data/lib/rdf/vocab/owl.rb +84 -84
- data/lib/rdf/vocab/rdfs.rb +17 -17
- data/lib/rdf/vocab/rdfv.rb +23 -23
- data/lib/rdf/vocab/writer.rb +50 -8
- data/lib/rdf/vocabulary.rb +554 -191
- metadata +23 -24
- data/lib/df.rb +0 -1
data/lib/rdf/vocab/rdfs.rb
CHANGED
@@ -11,46 +11,46 @@ module RDF
|
|
11
11
|
|
12
12
|
# Ontology definition
|
13
13
|
ontology :"http://www.w3.org/2000/01/rdf-schema#",
|
14
|
-
|
15
|
-
|
14
|
+
"dc11:title": %(The RDF Schema vocabulary \(RDFS\)).freeze,
|
15
|
+
"rdfs:seeAlso": %(http://www.w3.org/2000/01/rdf-schema-more).freeze,
|
16
16
|
type: "owl:Ontology".freeze
|
17
17
|
|
18
18
|
# Class definitions
|
19
19
|
term :Class,
|
20
20
|
comment: %(The class of classes.).freeze,
|
21
21
|
label: "Class".freeze,
|
22
|
-
:
|
22
|
+
isDefinedBy: %(rdfs:).freeze,
|
23
23
|
subClassOf: "rdfs:Resource".freeze,
|
24
24
|
type: "rdfs:Class".freeze
|
25
25
|
term :Container,
|
26
26
|
comment: %(The class of RDF containers.).freeze,
|
27
27
|
label: "Container".freeze,
|
28
|
-
:
|
28
|
+
isDefinedBy: %(rdfs:).freeze,
|
29
29
|
subClassOf: "rdfs:Resource".freeze,
|
30
30
|
type: "rdfs:Class".freeze
|
31
31
|
term :ContainerMembershipProperty,
|
32
32
|
comment: %(The class of container membership properties, rdf:_1, rdf:_2, ...,
|
33
33
|
all of which are sub-properties of 'member'.).freeze,
|
34
34
|
label: "ContainerMembershipProperty".freeze,
|
35
|
-
:
|
35
|
+
isDefinedBy: %(rdfs:).freeze,
|
36
36
|
subClassOf: "rdf:Property".freeze,
|
37
37
|
type: "rdfs:Class".freeze
|
38
38
|
term :Datatype,
|
39
39
|
comment: %(The class of RDF datatypes.).freeze,
|
40
40
|
label: "Datatype".freeze,
|
41
|
-
:
|
41
|
+
isDefinedBy: %(rdfs:).freeze,
|
42
42
|
subClassOf: "rdfs:Class".freeze,
|
43
43
|
type: "rdfs:Class".freeze
|
44
44
|
term :Literal,
|
45
45
|
comment: %(The class of literal values, eg. textual strings and integers.).freeze,
|
46
46
|
label: "Literal".freeze,
|
47
|
-
:
|
47
|
+
isDefinedBy: %(rdfs:).freeze,
|
48
48
|
subClassOf: "rdfs:Resource".freeze,
|
49
49
|
type: "rdfs:Class".freeze
|
50
50
|
term :Resource,
|
51
51
|
comment: %(The class resource, everything.).freeze,
|
52
52
|
label: "Resource".freeze,
|
53
|
-
:
|
53
|
+
isDefinedBy: %(rdfs:).freeze,
|
54
54
|
type: "rdfs:Class".freeze
|
55
55
|
|
56
56
|
# Property definitions
|
@@ -59,21 +59,21 @@ module RDF
|
|
59
59
|
domain: "rdfs:Resource".freeze,
|
60
60
|
label: "comment".freeze,
|
61
61
|
range: "rdfs:Literal".freeze,
|
62
|
-
:
|
62
|
+
isDefinedBy: %(rdfs:).freeze,
|
63
63
|
type: "rdf:Property".freeze
|
64
64
|
property :domain,
|
65
65
|
comment: %(A domain of the subject property.).freeze,
|
66
66
|
domain: "rdf:Property".freeze,
|
67
67
|
label: "domain".freeze,
|
68
68
|
range: "rdfs:Class".freeze,
|
69
|
-
:
|
69
|
+
isDefinedBy: %(rdfs:).freeze,
|
70
70
|
type: "rdf:Property".freeze
|
71
71
|
property :isDefinedBy,
|
72
72
|
comment: %(The defininition of the subject resource.).freeze,
|
73
73
|
domain: "rdfs:Resource".freeze,
|
74
74
|
label: "isDefinedBy".freeze,
|
75
75
|
range: "rdfs:Resource".freeze,
|
76
|
-
:
|
76
|
+
isDefinedBy: %(rdfs:).freeze,
|
77
77
|
subPropertyOf: "rdfs:seeAlso".freeze,
|
78
78
|
type: "rdf:Property".freeze
|
79
79
|
property :label,
|
@@ -81,42 +81,42 @@ module RDF
|
|
81
81
|
domain: "rdfs:Resource".freeze,
|
82
82
|
label: "label".freeze,
|
83
83
|
range: "rdfs:Literal".freeze,
|
84
|
-
:
|
84
|
+
isDefinedBy: %(rdfs:).freeze,
|
85
85
|
type: "rdf:Property".freeze
|
86
86
|
property :member,
|
87
87
|
comment: %(A member of the subject resource.).freeze,
|
88
88
|
domain: "rdfs:Resource".freeze,
|
89
89
|
label: "member".freeze,
|
90
90
|
range: "rdfs:Resource".freeze,
|
91
|
-
:
|
91
|
+
isDefinedBy: %(rdfs:).freeze,
|
92
92
|
type: "rdf:Property".freeze
|
93
93
|
property :range,
|
94
94
|
comment: %(A range of the subject property.).freeze,
|
95
95
|
domain: "rdf:Property".freeze,
|
96
96
|
label: "range".freeze,
|
97
97
|
range: "rdfs:Class".freeze,
|
98
|
-
:
|
98
|
+
isDefinedBy: %(rdfs:).freeze,
|
99
99
|
type: "rdf:Property".freeze
|
100
100
|
property :seeAlso,
|
101
101
|
comment: %(Further information about the subject resource.).freeze,
|
102
102
|
domain: "rdfs:Resource".freeze,
|
103
103
|
label: "seeAlso".freeze,
|
104
104
|
range: "rdfs:Resource".freeze,
|
105
|
-
:
|
105
|
+
isDefinedBy: %(rdfs:).freeze,
|
106
106
|
type: "rdf:Property".freeze
|
107
107
|
property :subClassOf,
|
108
108
|
comment: %(The subject is a subclass of a class.).freeze,
|
109
109
|
domain: "rdfs:Class".freeze,
|
110
110
|
label: "subClassOf".freeze,
|
111
111
|
range: "rdfs:Class".freeze,
|
112
|
-
:
|
112
|
+
isDefinedBy: %(rdfs:).freeze,
|
113
113
|
type: "rdf:Property".freeze
|
114
114
|
property :subPropertyOf,
|
115
115
|
comment: %(The subject is a subproperty of a property.).freeze,
|
116
116
|
domain: "rdf:Property".freeze,
|
117
117
|
label: "subPropertyOf".freeze,
|
118
118
|
range: "rdf:Property".freeze,
|
119
|
-
:
|
119
|
+
isDefinedBy: %(rdfs:).freeze,
|
120
120
|
type: "rdf:Property".freeze
|
121
121
|
end
|
122
122
|
end
|
data/lib/rdf/vocab/rdfv.rb
CHANGED
@@ -16,45 +16,45 @@ module RDF
|
|
16
16
|
|
17
17
|
# Ontology definition
|
18
18
|
ontology :"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
19
|
-
|
20
|
-
|
19
|
+
"dc11:description": %(This is the RDF Schema for the RDF vocabulary terms in the RDF Namespace, defined in RDF 1.1 Concepts.).freeze,
|
20
|
+
"dc11:title": %(The RDF Concepts Vocabulary \(RDF\)).freeze,
|
21
21
|
type: "owl:Ontology".freeze
|
22
22
|
|
23
23
|
# Class definitions
|
24
24
|
term :Alt,
|
25
25
|
comment: %(The class of containers of alternatives.).freeze,
|
26
26
|
label: "Alt".freeze,
|
27
|
-
:
|
27
|
+
isDefinedBy: %(rdf:).freeze,
|
28
28
|
subClassOf: "rdfs:Container".freeze,
|
29
29
|
type: "rdfs:Class".freeze
|
30
30
|
term :Bag,
|
31
31
|
comment: %(The class of unordered containers.).freeze,
|
32
32
|
label: "Bag".freeze,
|
33
|
-
:
|
33
|
+
isDefinedBy: %(rdf:).freeze,
|
34
34
|
subClassOf: "rdfs:Container".freeze,
|
35
35
|
type: "rdfs:Class".freeze
|
36
36
|
term :List,
|
37
37
|
comment: %(The class of RDF Lists.).freeze,
|
38
38
|
label: "List".freeze,
|
39
|
-
:
|
39
|
+
isDefinedBy: %(rdf:).freeze,
|
40
40
|
subClassOf: "rdfs:Resource".freeze,
|
41
41
|
type: "rdfs:Class".freeze
|
42
42
|
term :Property,
|
43
43
|
comment: %(The class of RDF properties.).freeze,
|
44
44
|
label: "Property".freeze,
|
45
|
-
:
|
45
|
+
isDefinedBy: %(rdf:).freeze,
|
46
46
|
subClassOf: "rdfs:Resource".freeze,
|
47
47
|
type: "rdfs:Class".freeze
|
48
48
|
term :Seq,
|
49
49
|
comment: %(The class of ordered containers.).freeze,
|
50
50
|
label: "Seq".freeze,
|
51
|
-
:
|
51
|
+
isDefinedBy: %(rdf:).freeze,
|
52
52
|
subClassOf: "rdfs:Container".freeze,
|
53
53
|
type: "rdfs:Class".freeze
|
54
54
|
term :Statement,
|
55
55
|
comment: %(The class of RDF statements.).freeze,
|
56
56
|
label: "Statement".freeze,
|
57
|
-
:
|
57
|
+
isDefinedBy: %(rdf:).freeze,
|
58
58
|
subClassOf: "rdfs:Resource".freeze,
|
59
59
|
type: "rdfs:Class".freeze
|
60
60
|
|
@@ -64,77 +64,77 @@ module RDF
|
|
64
64
|
domain: "rdf:List".freeze,
|
65
65
|
label: "first".freeze,
|
66
66
|
range: "rdfs:Resource".freeze,
|
67
|
-
:
|
67
|
+
isDefinedBy: %(rdf:).freeze,
|
68
68
|
type: "rdf:Property".freeze
|
69
69
|
property :object,
|
70
70
|
comment: %(The object of the subject RDF statement.).freeze,
|
71
71
|
domain: "rdf:Statement".freeze,
|
72
72
|
label: "object".freeze,
|
73
73
|
range: "rdfs:Resource".freeze,
|
74
|
-
:
|
74
|
+
isDefinedBy: %(rdf:).freeze,
|
75
75
|
type: "rdf:Property".freeze
|
76
76
|
property :predicate,
|
77
77
|
comment: %(The predicate of the subject RDF statement.).freeze,
|
78
78
|
domain: "rdf:Statement".freeze,
|
79
79
|
label: "predicate".freeze,
|
80
80
|
range: "rdfs:Resource".freeze,
|
81
|
-
:
|
81
|
+
isDefinedBy: %(rdf:).freeze,
|
82
82
|
type: "rdf:Property".freeze
|
83
83
|
property :rest,
|
84
84
|
comment: %(The rest of the subject RDF list after the first item.).freeze,
|
85
85
|
domain: "rdf:List".freeze,
|
86
86
|
label: "rest".freeze,
|
87
87
|
range: "rdf:List".freeze,
|
88
|
-
:
|
88
|
+
isDefinedBy: %(rdf:).freeze,
|
89
89
|
type: "rdf:Property".freeze
|
90
90
|
property :subject,
|
91
91
|
comment: %(The subject of the subject RDF statement.).freeze,
|
92
92
|
domain: "rdf:Statement".freeze,
|
93
93
|
label: "subject".freeze,
|
94
94
|
range: "rdfs:Resource".freeze,
|
95
|
-
:
|
95
|
+
isDefinedBy: %(rdf:).freeze,
|
96
96
|
type: "rdf:Property".freeze
|
97
97
|
property :type,
|
98
98
|
comment: %(The subject is an instance of a class.).freeze,
|
99
99
|
domain: "rdfs:Resource".freeze,
|
100
100
|
label: "type".freeze,
|
101
101
|
range: "rdfs:Class".freeze,
|
102
|
-
:
|
102
|
+
isDefinedBy: %(rdf:).freeze,
|
103
103
|
type: "rdf:Property".freeze
|
104
104
|
property :value,
|
105
105
|
comment: %(Idiomatic property used for structured values.).freeze,
|
106
106
|
domain: "rdfs:Resource".freeze,
|
107
107
|
label: "value".freeze,
|
108
108
|
range: "rdfs:Resource".freeze,
|
109
|
-
:
|
109
|
+
isDefinedBy: %(rdf:).freeze,
|
110
110
|
type: "rdf:Property".freeze
|
111
111
|
|
112
112
|
# Datatype definitions
|
113
113
|
term :HTML,
|
114
114
|
comment: %(The datatype of RDF literals storing fragments of HTML content).freeze,
|
115
115
|
label: "HTML".freeze,
|
116
|
-
:
|
117
|
-
|
116
|
+
isDefinedBy: %(rdf:).freeze,
|
117
|
+
"rdfs:seeAlso": %(http://www.w3.org/TR/rdf11-concepts/#section-html).freeze,
|
118
118
|
subClassOf: "rdfs:Literal".freeze,
|
119
119
|
type: "rdfs:Datatype".freeze
|
120
120
|
term :PlainLiteral,
|
121
121
|
comment: %(The class of plain \(i.e. untyped\) literal values, as used in RIF and OWL 2).freeze,
|
122
122
|
label: "PlainLiteral".freeze,
|
123
|
-
:
|
124
|
-
|
123
|
+
isDefinedBy: %(rdf:).freeze,
|
124
|
+
"rdfs:seeAlso": %(http://www.w3.org/TR/rdf-plain-literal/).freeze,
|
125
125
|
subClassOf: "rdfs:Literal".freeze,
|
126
126
|
type: "rdfs:Datatype".freeze
|
127
127
|
term :XMLLiteral,
|
128
128
|
comment: %(The datatype of XML literal values.).freeze,
|
129
129
|
label: "XMLLiteral".freeze,
|
130
|
-
:
|
130
|
+
isDefinedBy: %(rdf:).freeze,
|
131
131
|
subClassOf: "rdfs:Literal".freeze,
|
132
132
|
type: "rdfs:Datatype".freeze
|
133
133
|
term :langString,
|
134
134
|
comment: %(The datatype of language-tagged string values).freeze,
|
135
135
|
label: "langString".freeze,
|
136
|
-
:
|
137
|
-
|
136
|
+
isDefinedBy: %(rdf:).freeze,
|
137
|
+
"rdfs:seeAlso": %(http://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal).freeze,
|
138
138
|
subClassOf: "rdfs:Literal".freeze,
|
139
139
|
type: "rdfs:Datatype".freeze
|
140
140
|
|
@@ -157,7 +157,7 @@ module RDF
|
|
157
157
|
term :nil,
|
158
158
|
comment: %(The empty list, with no items in it. If the rest of a list is nil then the list has no more items in it.).freeze,
|
159
159
|
label: "nil".freeze,
|
160
|
-
:
|
160
|
+
isDefinedBy: %(rdf:).freeze,
|
161
161
|
type: "rdf:List".freeze
|
162
162
|
term :nodeID,
|
163
163
|
comment: %(RDF/XML Blank Node identifier).freeze,
|
data/lib/rdf/vocab/writer.rb
CHANGED
@@ -5,6 +5,44 @@ module RDF
|
|
5
5
|
##
|
6
6
|
# Vocabulary format specification. This can be used to generate a Ruby class definition from a loaded vocabulary.
|
7
7
|
#
|
8
|
+
# Definitions can include recursive term definitions, when the value of a property is a blank-node term. They can also include list definitions, to provide a reasonable way to represent `owl:unionOf`-type relationships.
|
9
|
+
#
|
10
|
+
# @example a simple term definition
|
11
|
+
# property :comment,
|
12
|
+
# comment: %(A description of the subject resource.).freeze,
|
13
|
+
# domain: "rdfs:Resource".freeze,
|
14
|
+
# label: "comment".freeze,
|
15
|
+
# range: "rdfs:Literal".freeze,
|
16
|
+
# isDefinedBy: %(rdfs:).freeze,
|
17
|
+
# type: "rdf:Property".freeze
|
18
|
+
#
|
19
|
+
# @example an embedded skos:Concept
|
20
|
+
# term :ad,
|
21
|
+
# exactMatch: [term(
|
22
|
+
# type: "skos:Concept".freeze,
|
23
|
+
# inScheme: "country:iso3166-1-alpha-2".freeze,
|
24
|
+
# notation: %(ad).freeze
|
25
|
+
# ), term(
|
26
|
+
# type: "skos:Concept".freeze,
|
27
|
+
# inScheme: "country:iso3166-1-alpha-3".freeze,
|
28
|
+
# notation: %(and).freeze
|
29
|
+
# )],
|
30
|
+
# "foaf:name": "Andorra".freeze,
|
31
|
+
# isDefinedBy: "country:".freeze,
|
32
|
+
# type: "http://sweet.jpl.nasa.gov/2.3/humanJurisdiction.owl#Country".freeze
|
33
|
+
#
|
34
|
+
# @example owl:unionOf
|
35
|
+
# property :duration,
|
36
|
+
# comment: %(The duration of a track or a signal in ms).freeze,
|
37
|
+
# domain: term(
|
38
|
+
# "owl:unionOf": list("mo:Track".freeze, "mo:Signal".freeze),
|
39
|
+
# type: "owl:Class".freeze
|
40
|
+
# ),
|
41
|
+
# isDefinedBy: "mo:".freeze,
|
42
|
+
# "mo:level": "1".freeze,
|
43
|
+
# range: "xsd:float".freeze,
|
44
|
+
# type: "owl:DatatypeProperty".freeze,
|
45
|
+
# "vs:term_status": "testing".freeze
|
8
46
|
class Vocabulary
|
9
47
|
class Format < RDF::Format
|
10
48
|
content_encoding 'utf-8'
|
@@ -171,24 +209,28 @@ module RDF
|
|
171
209
|
|
172
210
|
components = [" #{op} #{name.to_sym.inspect}"]
|
173
211
|
attributes.keys.sort_by(&:to_s).map(&:to_sym).each do |key|
|
174
|
-
next if key == :vocab
|
175
212
|
value = Array(attributes[key])
|
176
|
-
component = key.inspect.start_with?(':"') ? "#{key.inspect}
|
213
|
+
component = key.inspect.start_with?(':"') ? "#{key.to_s.inspect}: " : "#{key}: "
|
177
214
|
value = value.first if value.length == 1
|
178
215
|
component << if value.is_a?(Array)
|
179
|
-
'[' + value.map {|v| serialize_value(v, key)}.sort.join(", ") + "]"
|
216
|
+
'[' + value.map {|v| serialize_value(v, key, indent: " ")}.sort.join(", ") + "]"
|
180
217
|
else
|
181
|
-
serialize_value(value, key)
|
218
|
+
serialize_value(value, key, indent: " ")
|
182
219
|
end
|
183
220
|
components << component
|
184
221
|
end
|
185
222
|
@output.puts components.join(",\n ")
|
186
223
|
end
|
187
224
|
|
188
|
-
def serialize_value(value, key)
|
189
|
-
|
190
|
-
|
191
|
-
|
225
|
+
def serialize_value(value, key, indent: "")
|
226
|
+
if value.is_a?(Literal) && %w(: comment definition notation note editorialNote).include?(key.to_s)
|
227
|
+
"%(#{value.to_s.gsub('(', '\(').gsub(')', '\)')}).freeze"
|
228
|
+
elsif value.is_a?(RDF::URI)
|
229
|
+
"#{value.pname.inspect}.freeze"
|
230
|
+
elsif value.is_a?(RDF::Vocabulary::Term)
|
231
|
+
value.to_ruby(indent: indent + " ")
|
232
|
+
elsif value.is_a?(RDF::Term)
|
233
|
+
"#{value.to_s.inspect}.freeze"
|
192
234
|
else
|
193
235
|
"#{value.inspect}.freeze"
|
194
236
|
end
|
data/lib/rdf/vocabulary.rb
CHANGED
@@ -40,8 +40,6 @@ module RDF
|
|
40
40
|
# foaf['family_name'] #=> RDF::URI("http://xmlns.com/foaf/0.1/family_name")
|
41
41
|
# foaf[:family_name] #=> RDF::URI("http://xmlns.com/foaf/0.1/family_name")
|
42
42
|
#
|
43
|
-
#
|
44
|
-
#
|
45
43
|
# @example Generating RDF from a vocabulary definition
|
46
44
|
# graph = RDF::Graph.new << RDF::RDFS.to_enum
|
47
45
|
# graph.dump(:ntriples)
|
@@ -91,41 +89,128 @@ module RDF
|
|
91
89
|
# @overload property(name, options)
|
92
90
|
# Defines a new property or class in the vocabulary.
|
93
91
|
#
|
92
|
+
# @example A simple term definition
|
93
|
+
# property :domain,
|
94
|
+
# comment: %(A domain of the subject property.).freeze,
|
95
|
+
# domain: "rdf:Property".freeze,
|
96
|
+
# label: "domain".freeze,
|
97
|
+
# range: "rdfs:Class".freeze,
|
98
|
+
# isDefinedBy: %(rdfs:).freeze,
|
99
|
+
# type: "rdf:Property".freeze
|
100
|
+
#
|
101
|
+
# @example A SKOS term with anonymous values
|
102
|
+
# term: :af,
|
103
|
+
# type: "jur:Country",
|
104
|
+
# isDefinedBy: "http://eulersharp.sourceforge.net/2003/03swap/countries#",
|
105
|
+
# "skos:exactMatch": [
|
106
|
+
# Term.new(
|
107
|
+
# type: "skos:Concept",
|
108
|
+
# inScheme: "iso3166-1-alpha-2",
|
109
|
+
# notation: "ax"),
|
110
|
+
# Term.new(
|
111
|
+
# type: "skos:Concept",
|
112
|
+
# inScheme: "iso3166-1-alpha-3",
|
113
|
+
# notation: "ala")
|
114
|
+
# ],
|
115
|
+
# "foaf:name": "Aland Islands"
|
116
|
+
#
|
94
117
|
# @param [String, #to_s] name
|
95
|
-
# @param [Hash{Symbol
|
96
|
-
# Any other values are expected to
|
97
|
-
# @option options [String, Array<String>] :
|
98
|
-
# Shortcut for `
|
118
|
+
# @param [Hash{Symbol=>String,Array<String,Term>}] options
|
119
|
+
# Any other values are expected to expands to a {URI} using built-in vocabulary prefixes. The value is a `String`, `Array<String>` or `Array<Term>` which is interpreted according to the `range` of the associated property.
|
120
|
+
# @option options [String, Array<String,Term>] :type
|
121
|
+
# Shortcut for `rdf:type`, values are interpreted as a {Term}.
|
99
122
|
# @option options [String, Array<String>] :comment
|
100
|
-
# Shortcut for `rdfs:comment`, values are
|
101
|
-
# @option options [String, Array<String>] :
|
102
|
-
# Shortcut for `rdfs:
|
103
|
-
# @option options [String, Array<String>] :
|
104
|
-
# Shortcut for `rdfs:
|
105
|
-
# @option options [String, Array<String>] :
|
106
|
-
# Shortcut for `rdfs:
|
107
|
-
# @option options [String, Array<String>] :range
|
108
|
-
# Shortcut for `rdfs:range`, values are
|
109
|
-
# @option options [String, Array<String>] :
|
110
|
-
# Shortcut for `
|
123
|
+
# Shortcut for `rdfs:comment`, values are interpreted as a {Literal}.
|
124
|
+
# @option options [String, Array<String,Term>] :domain
|
125
|
+
# Shortcut for `rdfs:domain`, values are interpreted as a {Term}.
|
126
|
+
# @option options [String, Array<String,Term>] :isDefinedBy
|
127
|
+
# Shortcut for `rdfs:isDefinedBy`, values are interpreted as a {Term}.
|
128
|
+
# @option options [String, Array<String>] :label
|
129
|
+
# Shortcut for `rdfs:label`, values are interpreted as a {Literal}.
|
130
|
+
# @option options [String, Array<String,Term>] :range
|
131
|
+
# Shortcut for `rdfs:range`, values are interpreted as a {Term}.
|
132
|
+
# @option options [String, Array<String,Term>] :subClassOf
|
133
|
+
# Shortcut for `rdfs:subClassOf`, values are interpreted as a {Term}.
|
134
|
+
# @option options [String, Array<String,Term>] :subPropertyOf
|
135
|
+
# Shortcut for `rdfs:subPropertyOf`, values are interpreted as a {Term}.
|
136
|
+
# @option options [String, Array<String,Term>] :allValuesFrom
|
137
|
+
# Shortcut for `owl:allValuesFrom`, values are interpreted as a {Term}.
|
138
|
+
# @option options [String, Array<String,Term>] :cardinality
|
139
|
+
# Shortcut for `owl:cardinality`, values are interpreted as a {Literal}.
|
140
|
+
# @option options [String, Array<String,Term>] :equivalentClass
|
141
|
+
# Shortcut for `owl:equivalentClass`, values are interpreted as a {Term}.
|
142
|
+
# @option options [String, Array<String,Term>] :equivalentProperty
|
143
|
+
# Shortcut for `owl:equivalentProperty`, values are interpreted as a {Term}.
|
144
|
+
# @option options [String, Array<String,Term>] :intersectionOf
|
145
|
+
# Shortcut for `owl:intersectionOf`, values are interpreted as a {Term}.
|
146
|
+
# @option options [String, Array<String,Term>] :inverseOf
|
147
|
+
# Shortcut for `owl:inverseOf`, values are interpreted as a {Term}.
|
148
|
+
# @option options [String, Array<String,Term>] :maxCardinality
|
149
|
+
# Shortcut for `owl:maxCardinality`, values are interpreted as a {Literal}.
|
150
|
+
# @option options [String, Array<String,Term>] :minCardinality
|
151
|
+
# Shortcut for `owl:minCardinality`, values are interpreted as a {Literal}.
|
152
|
+
# @option options [String, Array<String,Term>] :onProperty
|
153
|
+
# Shortcut for `owl:onProperty`, values are interpreted as a {Term}.
|
154
|
+
# @option options [String, Array<String,Term>] :someValuesFrom
|
155
|
+
# Shortcut for `owl:someValuesFrom`, values are interpreted as a {Term}.
|
156
|
+
# @option options [String, Array<String,Term>] :unionOf
|
157
|
+
# Shortcut for `owl:unionOf`, values are interpreted as a {Term}.
|
158
|
+
# @option options [String, Array<String,Term>] :domainIncludes
|
159
|
+
# Shortcut for `schema:domainIncludes`, values are interpreted as a {Term}.
|
160
|
+
# @option options [String, Array<String,Term>] :rangeIncludes
|
161
|
+
# Shortcut for `schema:rangeIncludes`, values are interpreted as a {Term}.
|
162
|
+
# @option options [String, Array<String>] :altLabel
|
163
|
+
# Shortcut for `skos:altLabel`, values are interpreted as a {Literal}.
|
164
|
+
# @option options [String, Array<String,Term>] :broader
|
165
|
+
# Shortcut for `skos:broader`, values are interpreted as a {Term}.
|
166
|
+
# @option options [String, Array<String>] :definition
|
167
|
+
# Shortcut for `skos:definition`, values are interpreted as a {Literal}.
|
168
|
+
# @option options [String, Array<String>] :editorialNote
|
169
|
+
# Shortcut for `skos:editorialNote`, values are interpreted as a {Literal}.
|
170
|
+
# @option options [String, Array<String,Term>] :exactMatch
|
171
|
+
# Shortcut for `skos:exactMatch`, values are interpreted as a {Term}.
|
172
|
+
# @option options [String, Array<String,Term>] :hasTopConcept
|
173
|
+
# Shortcut for `skos:hasTopConcept`, values are interpreted as a {Term}.
|
174
|
+
# @option options [String, Array<String,Term>] :inScheme
|
175
|
+
# Shortcut for `skos:inScheme`, values are interpreted as a {Term}.
|
176
|
+
# @option options [String, Array<String,Term>] :member
|
177
|
+
# Shortcut for `skos:member`, values are interpreted as a {Term}.
|
178
|
+
# @option options [String, Array<String,Term>] :narrower
|
179
|
+
# Shortcut for `skos:narrower`, values are interpreted as a {Term}.
|
180
|
+
# @option options [String, Array<String>] :notation
|
181
|
+
# Shortcut for `skos:notation`, values are interpreted as a {Literal}.
|
182
|
+
# @option options [String, Array<String>] :note
|
183
|
+
# Shortcut for `skos:note`, values are interpreted as a {Literal}.
|
184
|
+
# @option options [String, Array<String>] :prefLabel
|
185
|
+
# Shortcut for `skos:prefLabel`, values are interpreted as a {Literal}.
|
186
|
+
# @option options [String, Array<String,Term>] :related
|
187
|
+
# Shortcut for `skos:related`, values are interpreted as a {Term}.
|
111
188
|
# @return [RDF::Vocabulary::Term]
|
112
189
|
def property(*args)
|
113
190
|
case args.length
|
114
191
|
when 0
|
115
|
-
Term.intern("#{self}property",
|
192
|
+
Term.intern("#{self}property", vocab: self, attributes: {})
|
116
193
|
else
|
117
|
-
name
|
118
|
-
options =
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
194
|
+
name = args.shift unless args.first.is_a?(Hash)
|
195
|
+
options = args.last
|
196
|
+
if name
|
197
|
+
uri_str = [to_s, name.to_s].join('')
|
198
|
+
URI.cache.delete(uri_str.to_sym) # Clear any previous entry
|
199
|
+
|
200
|
+
# Term attributes passed in a block for lazy evaluation. This helps to avoid load-time circular dependencies
|
201
|
+
prop = Term.intern(uri_str, vocab: self, attributes: options)
|
202
|
+
props[name.to_sym] = prop
|
203
|
+
|
204
|
+
# If name is empty, also treat it as the ontology
|
205
|
+
@ontology ||= prop if name.to_s.empty?
|
206
|
+
|
207
|
+
# Define an accessor, except for problematic properties
|
208
|
+
(class << self; self; end).send(:define_method, name) { prop } unless %w(property hash).include?(name.to_s)
|
209
|
+
else
|
210
|
+
# Define the term without a name
|
211
|
+
# Term attributes passed in a block for lazy evaluation. This helps to avoid load-time circular dependencies
|
212
|
+
prop = Term.new(vocab: self, attributes: options)
|
213
|
+
end
|
129
214
|
prop
|
130
215
|
end
|
131
216
|
end
|
@@ -145,13 +230,27 @@ module RDF
|
|
145
230
|
# @param [String, #to_s] uri
|
146
231
|
# The URI of the ontology.
|
147
232
|
# @param [Hash{Symbol => Object}] options
|
148
|
-
#
|
149
|
-
# @
|
150
|
-
#
|
233
|
+
# See {property}
|
234
|
+
# @param [Hash{Symbol=>String,Array<String,Term>}] options
|
235
|
+
# Any other values are expected to expands to a {URI} using built-in vocabulary prefixes. The value is a `String`, `Array<String>` or `Array<Term>` which is interpreted according to the `range` of the associated property.
|
236
|
+
# @option options [String, Array<String,Term>] :type
|
237
|
+
# Shortcut for `rdf:type`, values are interpreted as a {Term}.
|
151
238
|
# @option options [String, Array<String>] :comment
|
152
|
-
# Shortcut for `rdfs:comment`, values are
|
153
|
-
# @option options [String, Array<String>] :
|
154
|
-
# Shortcut for `
|
239
|
+
# Shortcut for `rdfs:comment`, values are interpreted as a {Literal}.
|
240
|
+
# @option options [String, Array<String,Term>] :isDefinedBy
|
241
|
+
# Shortcut for `rdfs:isDefinedBy`, values are interpreted as a {Term}.
|
242
|
+
# @option options [String, Array<String>] :label
|
243
|
+
# Shortcut for `rdfs:label`, values are interpreted as a {Literal}.
|
244
|
+
# @option options [String, Array<String>] :altLabel
|
245
|
+
# Shortcut for `skos:altLabel`, values are interpreted as a {Literal}.
|
246
|
+
# @option options [String, Array<String>] :definition
|
247
|
+
# Shortcut for `skos:definition`, values are interpreted as a {Literal}.
|
248
|
+
# @option options [String, Array<String>] :editorialNote
|
249
|
+
# Shortcut for `skos:editorialNote`, values are interpreted as a {Literal}.
|
250
|
+
# @option options [String, Array<String>] :note
|
251
|
+
# Shortcut for `skos:note`, values are interpreted as a {Literal}.
|
252
|
+
# @option options [String, Array<String>] :prefLabel
|
253
|
+
# Shortcut for `skos:prefLabel`, values are interpreted as a {Literal}.
|
155
254
|
# @return [RDF::Vocabulary::Term]
|
156
255
|
#
|
157
256
|
# @note If the ontology URI has the vocabulary namespace URI as a prefix, it may also be defined using `#property` or `#term`
|
@@ -161,9 +260,9 @@ module RDF
|
|
161
260
|
@ontology
|
162
261
|
else
|
163
262
|
uri, options = args
|
164
|
-
|
165
|
-
Term.
|
166
|
-
@ontology = Term.intern(uri.to_s, attributes: options)
|
263
|
+
URI.cache.delete(uri.to_s.to_sym) # Clear any previous entry
|
264
|
+
# Term attributes passed in a block for lazy evaluation. This helps to avoid load-time circular dependencies
|
265
|
+
@ontology = Term.intern(uri.to_s, vocab: self, attributes: options)
|
167
266
|
|
168
267
|
# If the URI is the same as the vocabulary namespace, also define it as a term
|
169
268
|
props[:""] ||= @ontology if self.to_s == uri.to_s
|
@@ -184,16 +283,18 @@ module RDF
|
|
184
283
|
# Attempt to expand a Compact IRI/PName/QName using loaded vocabularies
|
185
284
|
#
|
186
285
|
# @param [String, #to_s] pname
|
187
|
-
# @return [
|
286
|
+
# @return [Term]
|
188
287
|
# @raise [KeyError] if pname suffix not found in identified vocabulary
|
288
|
+
# @raise [ArgumentError] if resulting URI is not valid
|
189
289
|
def expand_pname(pname)
|
290
|
+
return pname unless pname.is_a?(String) || pname.is_a?(Symbol)
|
190
291
|
prefix, suffix = pname.to_s.split(":", 2)
|
191
292
|
if prefix == "rdf"
|
192
293
|
RDF[suffix]
|
193
294
|
elsif vocab = RDF::Vocabulary.each.detect {|v| v.__name__ && v.__prefix__ == prefix.to_sym}
|
194
295
|
suffix.to_s.empty? ? vocab.to_uri : vocab[suffix]
|
195
296
|
else
|
196
|
-
(RDF::Vocabulary.find_term(pname) rescue nil) || RDF::URI(pname)
|
297
|
+
(RDF::Vocabulary.find_term(pname) rescue nil) || RDF::URI(pname, validate: true)
|
197
298
|
end
|
198
299
|
end
|
199
300
|
|
@@ -238,7 +339,7 @@ module RDF
|
|
238
339
|
if props.has_key?(property.to_sym)
|
239
340
|
props[property.to_sym]
|
240
341
|
else
|
241
|
-
Term.intern([to_s, property.to_s].join(''), attributes: {
|
342
|
+
Term.intern([to_s, property.to_s].join(''), vocab: self, attributes: {})
|
242
343
|
end
|
243
344
|
end
|
244
345
|
|
@@ -340,50 +441,111 @@ module RDF
|
|
340
441
|
|
341
442
|
ont_url = url.to_s.sub(%r([/#]$), '')
|
342
443
|
term_defs = {}
|
444
|
+
embedded_defs = {}
|
343
445
|
graph.each do |statement|
|
344
|
-
next unless statement.subject.uri?
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
446
|
+
#next unless statement.subject.uri?
|
447
|
+
if statement.subject.start_with?(url) || statement.subject == ont_url
|
448
|
+
name = statement.subject.to_s[url.to_s.length..-1].to_s
|
449
|
+
term = (term_defs[name.to_sym] ||= {})
|
450
|
+
else
|
451
|
+
# subject is not a URI or is not associated with the vocabulary
|
452
|
+
term = (embedded_defs[statement.subject] ||= {})
|
453
|
+
end
|
349
454
|
|
350
455
|
key = case statement.predicate
|
351
456
|
when RDF.type then :type
|
352
|
-
when RDF::RDFS.subClassOf then :subClassOf
|
353
|
-
when RDF::RDFS.subPropertyOf then :subPropertyOf
|
354
|
-
when RDF::RDFS.range then :range
|
355
|
-
when RDF::RDFS.domain then :domain
|
356
457
|
when RDF::RDFS.comment then :comment
|
458
|
+
when RDF::RDFS.domain then :domain
|
459
|
+
when RDF::RDFS.isDefinedBy then :isDefinedBy
|
357
460
|
when RDF::RDFS.label then :label
|
358
|
-
when RDF::
|
461
|
+
when RDF::RDFS.range then :range
|
462
|
+
when RDF::RDFS.subClassOf then :subClassOf
|
463
|
+
when RDF::RDFS.subPropertyOf then :subPropertyOf
|
359
464
|
when RDF::URI("http://schema.org/domainIncludes") then :domainIncludes
|
360
465
|
when RDF::URI("http://schema.org/rangeIncludes") then :rangeIncludes
|
466
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#allValuesFrom") then :allValuesFrom
|
467
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#cardinality") then :cardinality
|
468
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#equivalentClass") then :equivalentClass
|
469
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#equivalentProperty") then :equivalentProperty
|
470
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#intersectionOf") then :intersectionOf
|
471
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#inverseOf") then :inverseOf
|
472
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#maxCardinality") then :maxCardinality
|
473
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#minCardinality") then :minCardinality
|
474
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#onProperty") then :onProperty
|
475
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#someValuesFrom") then :someValuesFrom
|
476
|
+
when RDF::URI("http://www.w3.org/2002/07/owl#unionOf") then :unionOf
|
477
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#altLabel") then :altLabel
|
478
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#broader") then :broader
|
479
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#definition") then :definition
|
480
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#editorialNote") then :editorialNote
|
481
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#exactMatch") then :exactMatch
|
482
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#hasTopConcept") then :hasTopConcept
|
483
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#inScheme") then :inScheme
|
484
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#member") then :member
|
485
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#narrower") then :narrower
|
486
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#notation") then :notation
|
487
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#note") then :note
|
488
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#prefLabel") then :prefLabel
|
489
|
+
when RDF::URI("http://www.w3.org/2004/02/skos/core#related") then :related
|
361
490
|
else statement.predicate.pname.to_sym
|
362
491
|
end
|
363
492
|
|
364
|
-
|
365
|
-
statement.object.pname
|
366
|
-
elsif statement.object.literal? && (statement.object.language || :en).to_s =~ /^en-?/
|
367
|
-
statement.object.to_s
|
368
|
-
end
|
369
|
-
|
370
|
-
(term[key] ||= []) << value if value
|
493
|
+
(term[key] ||= []) << statement.object
|
371
494
|
end
|
372
495
|
|
373
496
|
# Create extra terms
|
374
497
|
term_defs = case extra
|
375
498
|
when Array
|
376
|
-
extra.inject({}) {|memo, s| memo[s.to_sym] = {
|
499
|
+
extra.inject({}) {|memo, s| memo[s.to_sym] = {}; memo}.merge(term_defs)
|
377
500
|
when Hash
|
378
501
|
extra.merge(term_defs)
|
379
502
|
else
|
380
503
|
term_defs
|
381
504
|
end
|
382
505
|
|
506
|
+
# Pass over embedded_defs with anonymous references, once
|
507
|
+
embedded_defs.each do |term, attributes|
|
508
|
+
attributes.each do |ak, avs|
|
509
|
+
# Turn embedded BNodes into either their Term definition or a List
|
510
|
+
avs = [avs] unless avs.is_a?(Array)
|
511
|
+
attributes[ak] = avs.map do |av|
|
512
|
+
l = RDF::List.new(subject: av, graph: graph)
|
513
|
+
if l.valid?
|
514
|
+
RDF::List.new(subject: av) do |nl|
|
515
|
+
l.each do |lv|
|
516
|
+
nl << (embedded_defs[lv] ? Term.new(vocab: vocab, attributes: embedded_defs[lv]) : lv)
|
517
|
+
end
|
518
|
+
end
|
519
|
+
elsif av.is_a?(RDF::Node)
|
520
|
+
Term.new(vocab: vocab, attributes: embedded_defs[av]) if embedded_defs[av]
|
521
|
+
else
|
522
|
+
av
|
523
|
+
end
|
524
|
+
end.compact
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
383
528
|
term_defs.each do |term, attributes|
|
529
|
+
# Turn embedded BNodes into either their Term definition or a List
|
530
|
+
attributes.each do |ak, avs|
|
531
|
+
attributes[ak] = avs.is_a?(Array) ? avs.map do |av|
|
532
|
+
l = RDF::List.new(subject: av, graph: graph)
|
533
|
+
if l.valid?
|
534
|
+
RDF::List.new(subject: av) do |nl|
|
535
|
+
l.each do |lv|
|
536
|
+
nl << (embedded_defs[lv] ? Term.new(vocab: vocab, attributes: embedded_defs[lv]) : lv)
|
537
|
+
end
|
538
|
+
end
|
539
|
+
elsif av.is_a?(RDF::Node)
|
540
|
+
Term.new(vocab: vocab, attributes: embedded_defs[av]) if embedded_defs[av]
|
541
|
+
else
|
542
|
+
av
|
543
|
+
end
|
544
|
+
end.compact : avs
|
545
|
+
end
|
546
|
+
|
384
547
|
if term == :""
|
385
|
-
|
386
|
-
vocab.__ontology__ uri, attributes
|
548
|
+
vocab.__ontology__ vocab, attributes
|
387
549
|
else
|
388
550
|
vocab.__property__ term, attributes
|
389
551
|
end
|
@@ -430,15 +592,20 @@ module RDF
|
|
430
592
|
|
431
593
|
def method_missing(property, *args, &block)
|
432
594
|
property = RDF::Vocabulary.camelize(property.to_s)
|
433
|
-
if
|
434
|
-
|
435
|
-
elsif args.empty? && !to_s.empty?
|
436
|
-
Term.intern([to_s, property.to_s].join(''), attributes: {vocab: self})
|
595
|
+
if args.empty? && !to_s.empty?
|
596
|
+
Term.intern([to_s, property.to_s].join(''), vocab: self, attributes: {})
|
437
597
|
else
|
438
598
|
super
|
439
599
|
end
|
440
600
|
end
|
441
601
|
|
602
|
+
# Create a list of terms
|
603
|
+
# @param [Array<String>] values
|
604
|
+
# Each value treated as a URI or PName
|
605
|
+
# @return [RDF::List]
|
606
|
+
def list(*values)
|
607
|
+
RDF::List[*values.map {|v| expand_pname(v) rescue RDF::Literal(v)}]
|
608
|
+
end
|
442
609
|
private
|
443
610
|
|
444
611
|
def props; @properties ||= {}; end
|
@@ -466,7 +633,7 @@ module RDF
|
|
466
633
|
# @param [#to_s] property
|
467
634
|
# @return [URI]
|
468
635
|
def [](property)
|
469
|
-
Term.intern([to_s, property.to_s].join(''),
|
636
|
+
Term.intern([to_s, property.to_s].join(''), vocab: self.class, attributes: {})
|
470
637
|
end
|
471
638
|
|
472
639
|
##
|
@@ -526,94 +693,190 @@ module RDF
|
|
526
693
|
@@uris = {} # @private
|
527
694
|
@@uri = nil # @private
|
528
695
|
|
529
|
-
# A Vocabulary Term is a
|
530
|
-
|
531
|
-
|
696
|
+
# A Vocabulary Term is a {RDF::Resource} that can also act as an {Enumerable} to generate the RDF definition of vocabulary terms as defined within the vocabulary definition.
|
697
|
+
#
|
698
|
+
# Terms include `attributes` where values a embedded resources, lists or other terms. This allows, for example, navigation of a concept heirarchy.
|
699
|
+
module Term
|
700
|
+
include RDF::Resource
|
701
|
+
|
702
|
+
# @!attribute [r] comment
|
532
703
|
# `rdfs:comment` accessor
|
533
|
-
# @return [
|
534
|
-
# @!
|
704
|
+
# @return [Literal, Array<Literal>]
|
705
|
+
# @!attribute [r] label
|
535
706
|
# `rdfs:label` accessor
|
536
|
-
# @return [
|
537
|
-
# @!
|
707
|
+
# @return [Literal]
|
708
|
+
# @!attribute [r] type
|
538
709
|
# `rdf:type` accessor
|
539
|
-
# @return [
|
540
|
-
# @!
|
710
|
+
# @return [Array<Term>]
|
711
|
+
# @!attribute [r] subClassOf
|
541
712
|
# `rdfs:subClassOf` accessor
|
542
|
-
# @return [
|
543
|
-
# @!
|
713
|
+
# @return [Array<Term>]
|
714
|
+
# @!attribute [r] subPropertyOf
|
544
715
|
# `rdfs:subPropertyOf` accessor
|
545
|
-
# @return [
|
546
|
-
# @!
|
716
|
+
# @return [Array<Term>]
|
717
|
+
# @!attribute [r] domain
|
547
718
|
# `rdfs:domain` accessor
|
548
|
-
# @return [
|
549
|
-
# @!
|
719
|
+
# @return [Array<Term>]
|
720
|
+
# @!attribute [r] range
|
550
721
|
# `rdfs:range` accessor
|
551
|
-
# @return [
|
552
|
-
# @!
|
722
|
+
# @return [Array<Term>]
|
723
|
+
# @!attribute [r] isDefinedBy
|
724
|
+
# `rdfs:isDefinedBy` accessor
|
725
|
+
# @return [Array<Term>]
|
726
|
+
|
727
|
+
# @!attribute [r] allValuesFrom
|
728
|
+
# `owl:allValuesFrom` accessor
|
729
|
+
# @return [Array<Term>]
|
730
|
+
# @!attribute [r] cardinality
|
731
|
+
# `owl:cardinality` accessor
|
732
|
+
# @return [Array<Literal>]
|
733
|
+
# @!attribute [r] equivalentClass
|
734
|
+
# `owl:equivalentClass` accessor
|
735
|
+
# @return [Array<Term>]
|
736
|
+
# @!attribute [r] equivalentProperty
|
737
|
+
# `owl:equivalentProperty` accessor
|
738
|
+
# @return [Array<Term>]
|
739
|
+
# @!attribute [r] intersectionOf
|
740
|
+
# `owl:intersectionOf` accessor
|
741
|
+
# @return [Array<Term>]
|
742
|
+
# @!attribute [r] inverseOf
|
553
743
|
# `owl:inverseOf` accessor
|
554
|
-
# @return [
|
555
|
-
# @!
|
744
|
+
# @return [Array<Term>]
|
745
|
+
# @!attribute [r] maxCardinality
|
746
|
+
# `owl:maxCardinality` accessor
|
747
|
+
# @return [Array<Literal>]
|
748
|
+
# @!attribute [r] minCardinality
|
749
|
+
# `owl:minCardinality` accessor
|
750
|
+
# @return [Array<Literal>]
|
751
|
+
# @!attribute [r] onProperty
|
752
|
+
# `owl:onProperty` accessor
|
753
|
+
# @return [Array<Term>]
|
754
|
+
# @!attribute [r] someValuesFrom
|
755
|
+
# `owl:someValuesFrom` accessor
|
756
|
+
# @return [Array<Term>]
|
757
|
+
# @!attribute [r] unionOf
|
758
|
+
# `owl:unionOf` accessor
|
759
|
+
# @return [List<Term>, Array<Term>]
|
760
|
+
|
761
|
+
# @!attribute [r] domainIncludes
|
556
762
|
# `schema:domainIncludes` accessor
|
557
|
-
# @return [
|
558
|
-
# @!
|
559
|
-
# `schema:rangeIncludes`
|
560
|
-
# @return [
|
561
|
-
|
763
|
+
# @return [Array<Term>]
|
764
|
+
# @!attribute [r] rangeIncludes
|
765
|
+
# `schema:rangeIncludes` accessor
|
766
|
+
# @return [Array<Term>]
|
767
|
+
|
768
|
+
# @!attribute [r] altLabel
|
769
|
+
# `skos:altLabel` accessor
|
770
|
+
# @return [Literal, Array<Literal>]
|
771
|
+
# @!attribute [r] broader
|
772
|
+
# `skos:broader` accessor
|
773
|
+
# @return [Array<Term>]
|
774
|
+
# @!attribute [r] definition
|
775
|
+
# `skos:definition` accessor
|
776
|
+
# @return [Literal, Array<Literal>]
|
777
|
+
# @!attribute [r] editorialNote
|
778
|
+
# `skos:editorialNote` accessor
|
779
|
+
# @return [Literal, Array<Literal>]
|
780
|
+
# @!attribute [r] exactMatch
|
781
|
+
# `skos:exactMatch` accessor
|
782
|
+
# @return [Array<Term>]
|
783
|
+
# @!attribute [r] hasTopConcept
|
784
|
+
# `skos:hasTopConcept` accessor
|
785
|
+
# @return [Array<Term>]
|
786
|
+
# @!attribute [r] inScheme
|
787
|
+
# `skos:inScheme` accessor
|
788
|
+
# @return [Array<Term>]
|
789
|
+
# @!attribute [r] member
|
790
|
+
# `skos:member` accessor
|
791
|
+
# @return [Array<Term>]
|
792
|
+
# @!attribute [r] narrower
|
793
|
+
# `skos:narrower` accessor
|
794
|
+
# @return [Array<Term>]
|
795
|
+
# @!attribute [r] notation
|
796
|
+
# `skos:notation` accessor
|
797
|
+
# @return [Literal, Array<Literal>]
|
798
|
+
# @!attribute [r] note
|
799
|
+
# `skos:note` accessor
|
800
|
+
# @return [Literal, Array<Literal>]
|
801
|
+
# @!attribute [r] prefLabel
|
802
|
+
# `skos:prefLabel` accessor
|
803
|
+
# @return [Literal]
|
804
|
+
# @!attribute [r] related
|
805
|
+
# `skos:related` accessor
|
806
|
+
# @return [Array<Term>]
|
807
|
+
|
808
|
+
##
|
809
|
+
# Vocabulary of this term.
|
810
|
+
#
|
811
|
+
# @return [RDF::Vocabulary]
|
812
|
+
attr_reader :vocab
|
813
|
+
|
562
814
|
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF.
|
563
815
|
# @return [Hash{Symbol,Resource => Term, #to_s}]
|
564
|
-
|
816
|
+
attr_reader :attributes
|
817
|
+
|
565
818
|
|
566
819
|
##
|
567
|
-
# @overload
|
820
|
+
# @overload new(uri, attributes:, **options)
|
568
821
|
# @param [URI, String, #to_s] uri
|
822
|
+
# @param [Vocabulary] vocab Vocabulary of this term.
|
569
823
|
# @param [Hash{Symbol,Resource => Term, #to_s}] attributes
|
570
824
|
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF
|
571
825
|
# @param [Hash{Symbol => Object}] options
|
572
|
-
#
|
573
|
-
# @option options [Boolean] :canonicalize (false)
|
826
|
+
# Options from {URI#initialize}
|
574
827
|
#
|
575
|
-
# @overload
|
828
|
+
# @overload new(attributes:, **options)
|
576
829
|
# @param [Hash{Symbol => Object}] options
|
577
|
-
# @param [
|
578
|
-
#
|
579
|
-
#
|
580
|
-
# @
|
581
|
-
#
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
# useri optionsnfo, host, and port components must be omitted.
|
593
|
-
# @option options [String, #to_s] :path The path component.
|
594
|
-
# @option options [String, #to_s] :query The query component.
|
595
|
-
# @option options [String, #to_s] :fragment The fragment component.
|
596
|
-
def initialize(*args, attributes:, **options)
|
597
|
-
@attributes = attributes
|
598
|
-
if RUBY_ENGINE == "rbx"
|
599
|
-
super(*args, **options)
|
600
|
-
else
|
601
|
-
super
|
830
|
+
# @param [Vocabulary] vocab Vocabulary of this term.
|
831
|
+
# @param [Hash{Symbol => String,Array<String,Term>}] attributes
|
832
|
+
# Attributes of this vocabulary term, used for finding `label` and `comment` and to serialize the term back to RDF.
|
833
|
+
# @param [Hash{Symbol => Object}] options
|
834
|
+
# Options from {URI#initialize}
|
835
|
+
def self.new(*args, vocab: nil, attributes: {}, **options)
|
836
|
+
klass = if args.first.nil?
|
837
|
+
RDF::Node
|
838
|
+
elsif args.first.is_a?(Hash)
|
839
|
+
args.unshift(nil)
|
840
|
+
RDF::Node
|
841
|
+
elsif args.first.to_s.start_with?("_:")
|
842
|
+
args = args[1..-1].unshift($1)
|
843
|
+
RDF::Node
|
844
|
+
else RDF::URI
|
602
845
|
end
|
846
|
+
term = klass.allocate.extend(Term)
|
847
|
+
term.send(:initialize, *args)
|
848
|
+
term.instance_variable_set(:@vocab, vocab)
|
849
|
+
term.instance_variable_set(:@attributes, attributes)
|
850
|
+
term
|
603
851
|
end
|
604
852
|
|
605
853
|
##
|
606
|
-
#
|
854
|
+
# Returns an interned `RDF::URI` instance based on the given `uri`
|
855
|
+
# string.
|
607
856
|
#
|
608
|
-
#
|
609
|
-
|
857
|
+
# The maximum number of cached interned URI references is given by the
|
858
|
+
# `CACHE_SIZE` constant. This value is unlimited by default, in which
|
859
|
+
# case an interned URI object will be purged only when the last strong
|
860
|
+
# reference to it is garbage collected (i.e., when its finalizer runs).
|
861
|
+
#
|
862
|
+
# Excepting special memory-limited circumstances, it should always be
|
863
|
+
# safe and preferred to construct new URI references using
|
864
|
+
# `RDF::URI.intern` instead of `RDF::URI.new`, since if an interned
|
865
|
+
# object can't be returned for some reason, this method will fall back
|
866
|
+
# to returning a freshly-allocated one.
|
867
|
+
#
|
868
|
+
# @param (see #initialize)
|
869
|
+
# @return [RDF::URI] an immutable, frozen URI object
|
870
|
+
def self.intern(str, *args)
|
871
|
+
(URI.cache[(str = str.to_s).to_sym] ||= self.new(str, *args)).freeze
|
872
|
+
end
|
610
873
|
|
611
874
|
##
|
612
875
|
# Returns a duplicate copy of `self`.
|
613
876
|
#
|
614
877
|
# @return [RDF::URI]
|
615
878
|
def dup
|
616
|
-
self.class.new((@value || @object).dup, attributes:
|
879
|
+
self.class.new((@value || @object).dup, attributes: attributes).extend(Term)
|
617
880
|
end
|
618
881
|
|
619
882
|
##
|
@@ -623,35 +886,88 @@ module RDF
|
|
623
886
|
# @since 0.3.9
|
624
887
|
def valid?
|
625
888
|
# Validate relative to RFC3987
|
626
|
-
RDF::URI::IRI.match(to_s) || false
|
889
|
+
node? || RDF::URI::IRI.match(to_s) || false
|
627
890
|
end
|
628
891
|
|
629
892
|
##
|
630
893
|
# Is this a class term?
|
631
894
|
# @return [Boolean]
|
632
895
|
def class?
|
633
|
-
|
896
|
+
Array(self.type).any? {|t| t.to_s.include?('Class')}
|
634
897
|
end
|
635
898
|
|
636
899
|
##
|
637
900
|
# Is this a class term?
|
638
901
|
# @return [Boolean]
|
639
902
|
def property?
|
640
|
-
|
903
|
+
Array(self.type).any? {|t| t.to_s.include?('Property')}
|
641
904
|
end
|
642
905
|
|
643
906
|
##
|
644
907
|
# Is this a class term?
|
645
908
|
# @return [Boolean]
|
646
909
|
def datatype?
|
647
|
-
|
910
|
+
Array(self.type).any? {|t| t.to_s.include?('Datatype')}
|
911
|
+
end
|
912
|
+
|
913
|
+
##
|
914
|
+
# Is this a Restriction term?
|
915
|
+
# @return [Boolean]
|
916
|
+
def restriction?
|
917
|
+
Array(self.type).any? {|t| t.to_s.include?('Restriction')}
|
648
918
|
end
|
649
919
|
|
650
920
|
##
|
651
921
|
# Is this neither a class, property or datatype term?
|
652
922
|
# @return [Boolean]
|
653
923
|
def other?
|
654
|
-
|
924
|
+
Array(self.type).none? {|t| t.to_s =~ /(Class|Property|Datatype|Restriction)/}
|
925
|
+
end
|
926
|
+
|
927
|
+
##
|
928
|
+
# Enumerate attributes with values transformed into {RDF::Value} instances
|
929
|
+
#
|
930
|
+
# @return [Hash{Symbol => Array<RDF::Value>}]
|
931
|
+
def properties
|
932
|
+
attributes.keys.inject({}) do |memo, p|
|
933
|
+
memo.merge(p => attribute_value(p))
|
934
|
+
end
|
935
|
+
end
|
936
|
+
|
937
|
+
##
|
938
|
+
# Values of an attributes as {RDF::Value}
|
939
|
+
#
|
940
|
+
# @property [Symbol] prop
|
941
|
+
# @return [RDF::Value, Array<RDF::Value>]
|
942
|
+
def attribute_value(prop)
|
943
|
+
values = attributes[prop]
|
944
|
+
values = [values].compact unless values.is_a?(Array)
|
945
|
+
prop_values = values.map do |value|
|
946
|
+
v = value.is_a?(Symbol) ? value.to_s : value
|
947
|
+
value = (RDF::Vocabulary.expand_pname(v) rescue nil) if v.is_a?(String) && v.include?(':')
|
948
|
+
value = value.to_uri if value.respond_to?(:to_uri)
|
949
|
+
unless value.is_a?(RDF::Value) && value.valid?
|
950
|
+
# Use as most appropriate literal
|
951
|
+
value = [
|
952
|
+
RDF::Literal::Date,
|
953
|
+
RDF::Literal::DateTime,
|
954
|
+
RDF::Literal::Integer,
|
955
|
+
RDF::Literal::Decimal,
|
956
|
+
RDF::Literal::Double,
|
957
|
+
RDF::Literal::Boolean,
|
958
|
+
RDF::Literal
|
959
|
+
].inject(nil) do |m, klass|
|
960
|
+
m || begin
|
961
|
+
l = klass.new(v)
|
962
|
+
l if l.valid?
|
963
|
+
end
|
964
|
+
end
|
965
|
+
end
|
966
|
+
|
967
|
+
value
|
968
|
+
end
|
969
|
+
|
970
|
+
prop_values.length <= 1 ? prop_values.first : prop_values
|
655
971
|
end
|
656
972
|
|
657
973
|
##
|
@@ -662,61 +978,36 @@ module RDF
|
|
662
978
|
# @yield statement
|
663
979
|
# @yieldparam [RDF::Statement]
|
664
980
|
def each_statement
|
665
|
-
attributes.
|
666
|
-
|
981
|
+
attributes.keys.each do |p|
|
982
|
+
values = attribute_value(p)
|
983
|
+
values = [values].compact unless values.is_a?(Array)
|
984
|
+
values.each do |value|
|
667
985
|
begin
|
668
|
-
case
|
986
|
+
prop = case p
|
669
987
|
when :type
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
value = RDF::Vocabulary.expand_pname(value)
|
684
|
-
when :inverseOf
|
685
|
-
prop = RDF::URI("http://schema.org/inverseOf")
|
686
|
-
value = RDF::Vocabulary.expand_pname(value)
|
687
|
-
when :domainIncludes
|
688
|
-
prop = RDF::URI("http://schema.org/domainIncludes")
|
689
|
-
value = RDF::Vocabulary.expand_pname(value)
|
690
|
-
when :rangeIncludes
|
691
|
-
prop = RDF::URI("http://schema.org/rangeIncludes")
|
692
|
-
value = RDF::Vocabulary.expand_pname(value)
|
693
|
-
when :label
|
694
|
-
prop = RDF::RDFS.label
|
695
|
-
when :comment
|
696
|
-
prop = RDF::RDFS.comment
|
988
|
+
RDF::RDFV[p]
|
989
|
+
when :subClassOf, :subPropertyOf, :domain, :range, :isDefinedBy, :label, :comment
|
990
|
+
RDF::RDFS[p]
|
991
|
+
when :allValuesFrom, :cardinality, :equivalentClass, :equivalentProperty,
|
992
|
+
:intersectionOf, :inverseOf, :maxCardinality, :minCardinality,
|
993
|
+
:onProperty, :someValuesFrom, :unionOf
|
994
|
+
RDF::OWL[p]
|
995
|
+
when :domainIncludes, :rangeIncludes
|
996
|
+
RDF::Vocabulary.find_term("http://schema.org/#{p}")
|
997
|
+
when :broader, :definition, :exactMatch, :hasTopConcept, :inScheme,
|
998
|
+
:member, :narrower, :related, :altLabel, :definition, :editorialNote,
|
999
|
+
:notation, :note, :prefLabel
|
1000
|
+
RDF::Vocabulary.find_term("http://www.w3.org/2004/02/skos/core##{p}")
|
697
1001
|
else
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
RDF::Literal::Date,
|
707
|
-
RDF::Literal::DateTime,
|
708
|
-
RDF::Literal::Integer,
|
709
|
-
RDF::Literal::Decimal,
|
710
|
-
RDF::Literal::Double,
|
711
|
-
RDF::Literal::Boolean,
|
712
|
-
RDF::Literal
|
713
|
-
].inject(nil) do |memo, klass|
|
714
|
-
l = klass.new(v)
|
715
|
-
memo || (l if l.valid?)
|
716
|
-
end
|
717
|
-
end
|
1002
|
+
RDF::Vocabulary.expand_pname(p)
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
yield RDF::Statement(self, prop, value) if prop.is_a?(RDF::URI)
|
1006
|
+
|
1007
|
+
# Enumerate over value statements, if enumerable
|
1008
|
+
if value.is_a?(RDF::Enumerable) || (value.is_a?(Term) && value.node?)
|
1009
|
+
value.each_statement {|s| yield s}
|
718
1010
|
end
|
719
|
-
yield RDF::Statement(self, prop, value)
|
720
1011
|
rescue KeyError
|
721
1012
|
# Skip things eroneously defined in the vocabulary
|
722
1013
|
end
|
@@ -742,36 +1033,108 @@ module RDF
|
|
742
1033
|
#
|
743
1034
|
# @return [String] The URI object's state, as a <code>String</code>.
|
744
1035
|
def inspect
|
745
|
-
sprintf("#<%s:%#0x
|
1036
|
+
sprintf("#<%s:%#0x ID:%s>", Term.to_s, self.object_id, self.to_s)
|
746
1037
|
end
|
747
1038
|
|
748
1039
|
# Implement accessor to symbol attributes
|
749
1040
|
def respond_to?(method, include_all = false)
|
750
|
-
|
1041
|
+
case method
|
1042
|
+
when :comment, :notation, :note, :editorialNote, :definition,
|
1043
|
+
:label, :altLabel, :prefLabel, :type, :isDefinedBy
|
1044
|
+
true
|
1045
|
+
when :subClassOf, :subPropertyOf,
|
1046
|
+
:domainIncludes, :rangeIncludes,
|
1047
|
+
:equivalentClass, :intersectionOf, :unionOf
|
1048
|
+
self.class?
|
1049
|
+
when :domain, :range, :equivalentProperty, :inverseOf
|
1050
|
+
self.property?
|
1051
|
+
when :allValuesFrom, :cardinality,
|
1052
|
+
:maxCardinality, :minCardinality,
|
1053
|
+
:onProperty, :someValuesFrom
|
1054
|
+
self.restriction?
|
1055
|
+
when :broader, :exactMatch, :hasTopConcept, :inScheme, :member, :narrower, :related
|
1056
|
+
@attributes.has_key?(method)
|
1057
|
+
else
|
1058
|
+
super
|
1059
|
+
end
|
751
1060
|
end
|
752
1061
|
|
753
1062
|
# Accessor for `schema:domainIncludes`
|
754
1063
|
# @return [RDF::URI]
|
755
1064
|
def domain_includes
|
756
|
-
|
1065
|
+
domainIncludes
|
757
1066
|
end
|
758
1067
|
|
759
1068
|
# Accessor for `schema:rangeIncludes`
|
760
1069
|
# @return [RDF::URI]
|
761
1070
|
def range_includes
|
762
|
-
|
1071
|
+
rangeIncludes
|
763
1072
|
end
|
764
1073
|
|
1074
|
+
# Serialize back to a Ruby source initializer
|
1075
|
+
# @param [String] indent
|
1076
|
+
# @return [String]
|
1077
|
+
def to_ruby(indent: "")
|
1078
|
+
"term(" +
|
1079
|
+
(self.uri? ? self.to_s.inspect + ",\n" : "\n") +
|
1080
|
+
"#{indent} " +
|
1081
|
+
attributes.keys.map do |k|
|
1082
|
+
values = attribute_value(k)
|
1083
|
+
values = [values].compact unless values.is_a?(Array)
|
1084
|
+
values = values.map do |value|
|
1085
|
+
if value.is_a?(Literal) && %w(: comment definition notation note editorialNote).include?(k.to_s)
|
1086
|
+
"%(#{value.to_s.gsub('(', '\(').gsub(')', '\)')}).freeze"
|
1087
|
+
elsif value.is_a?(RDF::URI)
|
1088
|
+
"#{value.pname.inspect}.freeze"
|
1089
|
+
elsif value.is_a?(RDF::Vocabulary::Term)
|
1090
|
+
value.to_ruby(indent: indent + " ")
|
1091
|
+
elsif value.is_a?(RDF::Term)
|
1092
|
+
"#{value.to_s.inspect}.freeze"
|
1093
|
+
elsif value.is_a?(RDF::List)
|
1094
|
+
list_elements = value.map do |u|
|
1095
|
+
if u.uri?
|
1096
|
+
"#{u.pname.inspect}.freeze"
|
1097
|
+
elsif u.respond_to?(:to_ruby)
|
1098
|
+
u.to_ruby(indent: indent + " ")
|
1099
|
+
else
|
1100
|
+
"#{u.to_s.inspect}.freeze"
|
1101
|
+
end
|
1102
|
+
end
|
1103
|
+
"list(#{list_elements.join(', ')})"
|
1104
|
+
else
|
1105
|
+
"#{value.inspect}.freeze"
|
1106
|
+
end
|
1107
|
+
end
|
1108
|
+
"#{k.to_s.include?(':') ? k.to_s.inspect : k}: " +
|
1109
|
+
(values.length == 1 ? values.first : ('[' + values.join(',') + ']'))
|
1110
|
+
end.join(",\n#{indent} ") + "\n#{indent})"
|
1111
|
+
|
1112
|
+
end
|
765
1113
|
protected
|
766
1114
|
# Implement accessor to symbol attributes
|
767
1115
|
def method_missing(method, *args, &block)
|
768
1116
|
case method
|
769
|
-
when :comment
|
770
|
-
|
771
|
-
when :label
|
772
|
-
|
773
|
-
|
774
|
-
|
1117
|
+
when :comment, :notation, :note, :editorialNote, :definition
|
1118
|
+
attribute_value(method)
|
1119
|
+
when :label, :altLabel, :prefLabel
|
1120
|
+
# Defaults to URI fragment or path tail
|
1121
|
+
begin
|
1122
|
+
attribute_value(method)
|
1123
|
+
rescue KeyError
|
1124
|
+
to_s.split(/[\/\#]/).last
|
1125
|
+
end
|
1126
|
+
when :type, :subClassOf, :subPropertyOf, :domain, :range, :isDefinedBy,
|
1127
|
+
:allValuesFrom, :cardinality, :equivalentClass, :equivalentProperty,
|
1128
|
+
:intersectionOf, :inverseOf, :maxCardinality, :minCardinality,
|
1129
|
+
:onProperty, :someValuesFrom, :unionOf,
|
1130
|
+
:domainIncludes, :rangeIncludes,
|
1131
|
+
:broader, :exactMatch, :hasTopConcept, :inScheme, :member, :narrower, :related
|
1132
|
+
|
1133
|
+
# Return value as an Array, unless it is a list
|
1134
|
+
case value = attribute_value(method)
|
1135
|
+
when Array, RDF::List then value
|
1136
|
+
else [value].compact
|
1137
|
+
end
|
775
1138
|
else
|
776
1139
|
super
|
777
1140
|
end
|