rdf 1.1.0p4 → 1.1.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 +6 -14
- data/README +33 -33
- data/VERSION +1 -1
- data/lib/rdf.rb +60 -12
- data/lib/rdf/cli.rb +7 -1
- data/lib/rdf/cli/vocab-loader.rb +240 -0
- data/lib/rdf/format.rb +2 -2
- data/lib/rdf/mixin/enumerable.rb +12 -4
- data/lib/rdf/mixin/queryable.rb +13 -13
- data/lib/rdf/model/graph.rb +5 -4
- data/lib/rdf/model/list.rb +15 -4
- data/lib/rdf/model/literal.rb +2 -1
- data/lib/rdf/model/statement.rb +10 -1
- data/lib/rdf/model/term.rb +8 -0
- data/lib/rdf/model/uri.rb +107 -2
- data/lib/rdf/model/value.rb +8 -0
- data/lib/rdf/ntriples/reader.rb +5 -4
- data/lib/rdf/query.rb +47 -12
- data/lib/rdf/query/solutions.rb +29 -29
- data/lib/rdf/reader.rb +13 -3
- data/lib/rdf/repository.rb +1 -0
- data/lib/rdf/util/file.rb +86 -6
- data/lib/rdf/vocab.rb +158 -58
- data/lib/rdf/vocab/cc.rb +28 -11
- data/lib/rdf/vocab/cert.rb +127 -9
- data/lib/rdf/vocab/dc.rb +242 -60
- data/lib/rdf/vocab/dc11.rb +42 -20
- data/lib/rdf/vocab/doap.rb +121 -42
- data/lib/rdf/vocab/exif.rb +540 -165
- data/lib/rdf/vocab/foaf.rb +353 -66
- data/lib/rdf/vocab/geo.rb +40 -10
- data/lib/rdf/vocab/gr.rb +1094 -0
- data/lib/rdf/vocab/http.rb +81 -23
- data/lib/rdf/vocab/ical.rb +361 -0
- data/lib/rdf/vocab/ma.rb +281 -69
- data/lib/rdf/vocab/og.rb +98 -0
- data/lib/rdf/vocab/owl.rb +226 -56
- data/lib/rdf/vocab/prov.rb +489 -0
- data/lib/rdf/vocab/rdfs.rb +38 -14
- data/lib/rdf/vocab/rsa.rb +25 -9
- data/lib/rdf/vocab/rss.rb +29 -11
- data/lib/rdf/vocab/schema.rb +3729 -647
- data/lib/rdf/vocab/sioc.rb +224 -89
- data/lib/rdf/vocab/skos.rb +141 -33
- data/lib/rdf/vocab/skosxl.rb +43 -0
- data/lib/rdf/vocab/v.rb +154 -0
- data/lib/rdf/vocab/vcard.rb +337 -0
- data/lib/rdf/vocab/void.rb +142 -0
- data/lib/rdf/vocab/wdrs.rb +129 -0
- data/lib/rdf/vocab/wot.rb +52 -18
- data/lib/rdf/vocab/xhtml.rb +3 -6
- data/lib/rdf/vocab/xhv.rb +239 -0
- data/lib/rdf/writer.rb +3 -3
- metadata +81 -14
data/lib/rdf/query/solutions.rb
CHANGED
@@ -60,6 +60,35 @@ module RDF; class Query
|
|
60
60
|
super
|
61
61
|
end
|
62
62
|
|
63
|
+
##
|
64
|
+
# Returns an array of the distinct variable names used in this solution
|
65
|
+
# sequence.
|
66
|
+
#
|
67
|
+
# @return [Array<Symbol>]
|
68
|
+
def variable_names
|
69
|
+
variables = self.inject({}) do |result, solution|
|
70
|
+
solution.each_name do |name|
|
71
|
+
result[name] ||= true
|
72
|
+
end
|
73
|
+
result
|
74
|
+
end
|
75
|
+
variables.keys
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# Returns `true` if this solution sequence contains bindings for any of
|
80
|
+
# the given `variables`.
|
81
|
+
#
|
82
|
+
# @param [Array<Symbol, #to_sym>] variables
|
83
|
+
# an array of variables to check
|
84
|
+
# @return [Boolean] `true` or `false`
|
85
|
+
# @see RDF::Query::Solution#has_variables?
|
86
|
+
# @see RDF::Query#execute
|
87
|
+
def have_variables?(variables)
|
88
|
+
self.any? { |solution| solution.has_variables?(variables) }
|
89
|
+
end
|
90
|
+
alias_method :has_variables?, :have_variables?
|
91
|
+
|
63
92
|
##
|
64
93
|
# Returns hash of bindings from each solution. Each bound variable will have
|
65
94
|
# an array of bound values representing those from each solution, where a given
|
@@ -222,34 +251,5 @@ module RDF; class Query
|
|
222
251
|
self
|
223
252
|
end
|
224
253
|
alias_method :limit!, :limit
|
225
|
-
|
226
|
-
##
|
227
|
-
# Returns an array of the distinct variable names used in this solution
|
228
|
-
# sequence.
|
229
|
-
#
|
230
|
-
# @return [Array<Symbol>]
|
231
|
-
def variable_names
|
232
|
-
variables = self.inject({}) do |result, solution|
|
233
|
-
solution.each_name do |name|
|
234
|
-
result[name] ||= true
|
235
|
-
end
|
236
|
-
result
|
237
|
-
end
|
238
|
-
variables.keys
|
239
|
-
end
|
240
|
-
|
241
|
-
##
|
242
|
-
# Returns `true` if this solution sequence contains bindings for any of
|
243
|
-
# the given `variables`.
|
244
|
-
#
|
245
|
-
# @param [Array<Symbol, #to_sym>] variables
|
246
|
-
# an array of variables to check
|
247
|
-
# @return [Boolean] `true` or `false`
|
248
|
-
# @see RDF::Query::Solution#has_variables?
|
249
|
-
# @see RDF::Query#execute
|
250
|
-
def have_variables?(variables)
|
251
|
-
self.any? { |solution| solution.has_variables?(variables) }
|
252
|
-
end
|
253
|
-
alias_method :has_variables?, :have_variables?
|
254
254
|
end # Solutions
|
255
255
|
end; end # RDF::Query
|
data/lib/rdf/reader.rb
CHANGED
@@ -217,10 +217,10 @@ module RDF
|
|
217
217
|
# @example
|
218
218
|
# reader.prefixes[:dc] #=> RDF::URI('http://purl.org/dc/terms/')
|
219
219
|
#
|
220
|
-
# @return [
|
220
|
+
# @return [RDF::URI]
|
221
221
|
# @since 0.3.0
|
222
222
|
def base_uri
|
223
|
-
@options[:base_uri]
|
223
|
+
RDF::URI(@options[:base_uri]) if @options[:base_uri]
|
224
224
|
end
|
225
225
|
|
226
226
|
##
|
@@ -486,7 +486,17 @@ module RDF
|
|
486
486
|
@line = @line_rest || @input.readline
|
487
487
|
@line, @line_rest = @line.split("\r", 2)
|
488
488
|
@line = @line.to_s.chomp
|
489
|
-
|
489
|
+
begin
|
490
|
+
@line.encode!(encoding)
|
491
|
+
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError, Encoding::ConverterNotFoundError
|
492
|
+
# It is likely the persisted line was not encoded on initial write
|
493
|
+
# (i.e. persisted via RDF <= 1.0.9 and read via RDF >= 1.0.10)
|
494
|
+
#
|
495
|
+
# Encoding::UndefinedConversionError is raised by MRI.
|
496
|
+
# Encoding::InvalidByteSequenceError is raised by jruby >= 1.7.5
|
497
|
+
# Encoding::ConverterNotFoundError is raised by jruby < 1.7.5
|
498
|
+
@line = RDF::NTriples::Reader.unescape(@line).encode(encoding)
|
499
|
+
end
|
490
500
|
@line
|
491
501
|
end
|
492
502
|
|
data/lib/rdf/repository.rb
CHANGED
data/lib/rdf/util/file.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'time'
|
3
|
+
|
1
4
|
module RDF; module Util
|
2
5
|
##
|
3
6
|
# Wrapper for Kernel.open. Allows implementations to override to get
|
@@ -23,6 +26,8 @@ module RDF; module Util
|
|
23
26
|
# Adds Accept header based on available reader content types to allow
|
24
27
|
# for content negotiation based on available readers.
|
25
28
|
#
|
29
|
+
# When retrieving documents over HTTP(S), use the mechanism described in [Providing and Discovering URI Documentation](http://www.w3.org/2001/tag/awwsw/issue57/latest/) to pass the appropriate `base_uri` to the block or as the return.
|
30
|
+
#
|
26
31
|
# @param [String] filename_or_url to open
|
27
32
|
# @param [Hash{Symbol => Object}] options
|
28
33
|
# options are ignored in this implementation. Applications are encouraged
|
@@ -31,19 +36,94 @@ module RDF; module Util
|
|
31
36
|
# options are passed to `Kernel.open`.
|
32
37
|
# @option options [Array, String] :headers
|
33
38
|
# HTTP Request headers, passed to Kernel.open.
|
34
|
-
# @return [IO] File stream
|
35
|
-
# @yield [IO] File stream
|
39
|
+
# @return [IO, Reader] File stream with no block, and the block return otherwise
|
40
|
+
# @yield [IO, StringIO] File stream
|
36
41
|
def self.open_file(filename_or_url, options = {}, &block)
|
37
42
|
filename_or_url = $1 if filename_or_url.to_s.match(/^file:(.*)$/)
|
38
|
-
if filename_or_url.to_s =~
|
39
|
-
# Open as a URL
|
43
|
+
if filename_or_url.to_s =~ /^https?/
|
44
|
+
# Open as a URL with Net::HTTP
|
40
45
|
headers = options.fetch(:headers, {})
|
41
|
-
|
42
|
-
|
46
|
+
# Receive text/html and text/plain at a lower priority than other formats
|
47
|
+
reader_types = RDF::Format.reader_types.map do |t|
|
48
|
+
t.to_s =~ /text\/(?:plain|html)/ ? "#{t};q=0.5" : t
|
49
|
+
end
|
50
|
+
headers['Accept'] ||= (reader_types + %w(*/*;q=0.1)).join(", ")
|
51
|
+
|
52
|
+
redirect_count = 0
|
53
|
+
max_redirects = 5
|
54
|
+
remote_document = nil
|
55
|
+
parsed_url = ::URI.parse(filename_or_url.to_s)
|
56
|
+
base_uri = parsed_url.to_s
|
57
|
+
result = nil
|
58
|
+
until remote_document do
|
59
|
+
Net::HTTP::start(parsed_url.host, parsed_url.port,
|
60
|
+
:open_timeout => 60 * 1000,
|
61
|
+
:use_ssl => filename_or_url.start_with?("https")
|
62
|
+
) do |http|
|
63
|
+
request = Net::HTTP::Get.new(parsed_url.request_uri, headers)
|
64
|
+
http.request(request) do |response|
|
65
|
+
case response
|
66
|
+
when Net::HTTPSuccess
|
67
|
+
# found object
|
68
|
+
|
69
|
+
# If a Location is returned, it defines the base resource for this file, not it's actual ending location
|
70
|
+
|
71
|
+
document_options = {
|
72
|
+
:content_type => response.content_type,
|
73
|
+
:charset => "utf-8",
|
74
|
+
:base_uri => RDF::URI(response["Location"] ? response["Location"] : base_uri)
|
75
|
+
}.merge(response.type_params)
|
76
|
+
document_options[:last_modified] = DateTime.parse(response["Last-Modified"]) if response["Last-Modified"]
|
77
|
+
|
78
|
+
remote_document = RemoteDocument.new(response.body, document_options)
|
79
|
+
|
80
|
+
# Yield the result and close, or cause it to be returned
|
81
|
+
result = if block_given?
|
82
|
+
ret = yield remote_document
|
83
|
+
remote_document.close
|
84
|
+
ret
|
85
|
+
else
|
86
|
+
remote_document
|
87
|
+
end
|
88
|
+
when Net::HTTPRedirection
|
89
|
+
# Follow redirection
|
90
|
+
raise IOError, "Too many redirects" if (redirect_count += 1) > max_redirects
|
91
|
+
|
92
|
+
parsed_url = ::URI.parse(response["Location"])
|
93
|
+
|
94
|
+
# If response is not a status 303, update base_uri too
|
95
|
+
base_uri = parsed_url.to_s unless response.code == "303"
|
96
|
+
else
|
97
|
+
raise IOError, "<#{parsed_url}>: #{response.msg}(#{response.code})"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
result
|
43
103
|
else
|
44
104
|
# Open as a file, passing any options
|
45
105
|
Kernel.open(filename_or_url, "r", options, &block)
|
46
106
|
end
|
47
107
|
end
|
108
|
+
|
109
|
+
class RemoteDocument < StringIO
|
110
|
+
attr_reader :base_uri
|
111
|
+
attr_reader :content_type
|
112
|
+
attr_reader :charset
|
113
|
+
attr_reader :content_encoding
|
114
|
+
attr_reader :last_modified
|
115
|
+
|
116
|
+
##
|
117
|
+
# Set content
|
118
|
+
def initialize(body, options = {})
|
119
|
+
super(body)
|
120
|
+
options.each do |key, value|
|
121
|
+
# de-quote charset
|
122
|
+
value = $1 if key == "charset" && value =~ /^["'](.*)["']$/
|
123
|
+
instance_variable_set(:"@#{key}", value)
|
124
|
+
end
|
125
|
+
set_encoding Encoding.find(@charset) if @charset
|
126
|
+
end
|
127
|
+
end
|
48
128
|
end # File
|
49
129
|
end; end # RDF::Util
|
data/lib/rdf/vocab.rb
CHANGED
@@ -15,16 +15,27 @@ module RDF
|
|
15
15
|
# * {RDF::EXIF} - Exchangeable Image File Format (EXIF)
|
16
16
|
# * {RDF::FOAF} - Friend of a Friend (FOAF)
|
17
17
|
# * {RDF::GEO} - WGS84 Geo Positioning (GEO)
|
18
|
+
# * {RDF::GR} - Good Relations
|
18
19
|
# * {RDF::HTTP} - Hypertext Transfer Protocol (HTTP)
|
20
|
+
# * {RDF::ICAL} - iCal
|
21
|
+
# * {RDF::MA} - W3C Meda Annotations
|
22
|
+
# * {RDF::OG} - FaceBook OpenGraph
|
19
23
|
# * {RDF::OWL} - Web Ontology Language (OWL)
|
24
|
+
# * {RDF::PROV} - W3C Provenance Ontology
|
20
25
|
# * {RDF::RDFS} - RDF Schema (RDFS)
|
21
26
|
# * {RDF::RSA} - W3 RSA Keys (RSA)
|
22
27
|
# * {RDF::RSS} - RDF Site Summary (RSS)
|
23
28
|
# * {RDF::SCHEMA} - Schema.org
|
24
29
|
# * {RDF::SIOC} - Semantically-Interlinked Online Communities (SIOC)
|
25
30
|
# * {RDF::SKOS} - Simple Knowledge Organization System (SKOS)
|
31
|
+
# * {RDF::SKOSXL} - SKOS Simple Knowledge Organization System eXtension for Labels (SKOS-XL)
|
32
|
+
# * {RDF::V} - Data Vocabulary
|
33
|
+
# * {RDF::VCARD} - vCard vocabulary
|
34
|
+
# * {RDF::VOID} - Vocabulary of Interlinked Datasets (VoID)
|
35
|
+
# * {RDF::WDRS} - Protocol for Web Description Resources (POWDER)
|
26
36
|
# * {RDF::WOT} - Web of Trust (WOT)
|
27
37
|
# * {RDF::XHTML} - Extensible HyperText Markup Language (XHTML)
|
38
|
+
# * {RDF::XHV} - W3C XHTML Vocabulary
|
28
39
|
# * {RDF::XSD} - XML Schema (XSD)
|
29
40
|
#
|
30
41
|
# @example Using pre-defined RDF vocabularies
|
@@ -49,72 +60,99 @@ module RDF
|
|
49
60
|
class Vocabulary
|
50
61
|
extend ::Enumerable
|
51
62
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
class << self
|
64
|
+
##
|
65
|
+
# Enumerates known RDF vocabulary classes.
|
66
|
+
#
|
67
|
+
# @yield [klass]
|
68
|
+
# @yieldparam [Class] klass
|
69
|
+
# @return [Enumerator]
|
70
|
+
def each(&block)
|
71
|
+
if self.equal?(Vocabulary)
|
72
|
+
# This is needed since all vocabulary classes are defined using
|
73
|
+
# Ruby's autoloading facility, meaning that `@@subclasses` will be
|
74
|
+
# empty until each subclass has been touched or require'd.
|
75
|
+
RDF::VOCABS.each { |v| require "rdf/vocab/#{v}" unless v == :rdf }
|
76
|
+
@@subclasses.each(&block)
|
77
|
+
else
|
78
|
+
# TODO: should enumerate vocabulary-specific defined properties.
|
79
|
+
end
|
67
80
|
end
|
68
|
-
end
|
69
81
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
82
|
+
##
|
83
|
+
# @overload property
|
84
|
+
# Returns `property` in the current vocabulary
|
85
|
+
# @return [RDF::URI]
|
86
|
+
#
|
87
|
+
# @overload property(name, options)
|
88
|
+
# Defines a new property or class in the vocabulary.
|
89
|
+
# Optional labels and comments are stripped of unnecessary whitespace.
|
90
|
+
#
|
91
|
+
# @param [String, #to_s] name
|
92
|
+
# @param [Hash{Symbol => Object}] options
|
93
|
+
# @option options [String, #to_s] :label
|
94
|
+
# @option options [String, #to_s] :comment
|
95
|
+
def property(*args)
|
96
|
+
case args.length
|
97
|
+
when 0
|
98
|
+
RDF::URI.intern("#{self}property")
|
99
|
+
else
|
100
|
+
name, options = args
|
101
|
+
options ||= {}
|
102
|
+
prop = RDF::URI.intern([to_s, name.to_s].join(''))
|
103
|
+
@@labels[prop] = options[:label].to_s.strip.gsub(/\s+/m, ' ') if options[:label]
|
104
|
+
@@comments[prop] = options[:comment].to_s.strip.gsub(/\s+/m, ' ') if options[:comment]
|
105
|
+
(class << self; self; end).send(:define_method, name) { prop } unless name.to_s == "property"
|
106
|
+
end
|
107
|
+
end
|
79
108
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
109
|
+
##
|
110
|
+
# Returns the URI for the term `property` in this vocabulary.
|
111
|
+
#
|
112
|
+
# @param [#to_s] property
|
113
|
+
# @return [RDF::URI]
|
114
|
+
def [](property)
|
115
|
+
RDF::URI.intern([to_s, property.to_s].join(''))
|
116
|
+
end
|
88
117
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
def self.to_uri
|
94
|
-
RDF::URI.intern(to_s)
|
95
|
-
end
|
118
|
+
# @return [String] The label for the named property
|
119
|
+
def label_for(name)
|
120
|
+
@@labels[self[name]]
|
121
|
+
end
|
96
122
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
def self.to_s
|
102
|
-
@@uris.has_key?(self) ? @@uris[self].to_s : super
|
103
|
-
end
|
123
|
+
# @return [String] The comment for the named property
|
124
|
+
def comment_for(name)
|
125
|
+
@@comments[self[name]]
|
126
|
+
end
|
104
127
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
128
|
+
##
|
129
|
+
# Returns the base URI for this vocabulary class.
|
130
|
+
#
|
131
|
+
# @return [RDF::URI]
|
132
|
+
def to_uri
|
133
|
+
RDF::URI.intern(to_s)
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Returns a string representation of this vocabulary class.
|
138
|
+
#
|
139
|
+
# @return [String]
|
140
|
+
def to_s
|
141
|
+
@@uris.has_key?(self) ? @@uris[self].to_s : super
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Returns a developer-friendly representation of this vocabulary class.
|
146
|
+
#
|
147
|
+
# @return [String]
|
148
|
+
def inspect
|
149
|
+
if self == Vocabulary
|
150
|
+
self.to_s
|
151
|
+
else
|
152
|
+
sprintf("%s(%s)", superclass.to_s, to_s)
|
153
|
+
end
|
114
154
|
end
|
115
|
-
end
|
116
155
|
|
117
|
-
class << self
|
118
156
|
# Preserve the class name so that it can be obtained even for
|
119
157
|
# vocabularies that define a `name` property:
|
120
158
|
alias_method :__name__, :name
|
@@ -216,5 +254,67 @@ module RDF
|
|
216
254
|
@@subclasses = [::RDF] # @private
|
217
255
|
@@uris = {} # @private
|
218
256
|
@@uri = nil # @private
|
257
|
+
@@labels = {}
|
258
|
+
@@comments = {}
|
219
259
|
end # Vocabulary
|
260
|
+
|
261
|
+
# Represents an RDF Vocabulary. The difference from {RDF::Vocabulary} is that
|
262
|
+
# that every concept in the vocabulary is required to be declared. To assist
|
263
|
+
# in this, an existing RDF representation of the vocabulary can be loaded as
|
264
|
+
# the basis for concepts being available
|
265
|
+
class StrictVocabulary < Vocabulary
|
266
|
+
class << self
|
267
|
+
begin
|
268
|
+
# Redefines method_missing to the original definition
|
269
|
+
# By remaining a subclass of Vocabulary, we remain available to
|
270
|
+
# Vocabulary::each etc.
|
271
|
+
define_method(:method_missing, BasicObject.instance_method(:method_missing))
|
272
|
+
rescue NameError
|
273
|
+
define_method(:method_missing, Kernel.instance_method(:method_missing))
|
274
|
+
end
|
275
|
+
|
276
|
+
##
|
277
|
+
# @overload property
|
278
|
+
# Returns `property` in the current vocabulary
|
279
|
+
# @return [RDF::URI]
|
280
|
+
#
|
281
|
+
# @overload property(name, options)
|
282
|
+
# Defines a new property or class in the vocabulary.
|
283
|
+
# Optional labels and comments are stripped of unnecessary whitespace.
|
284
|
+
#
|
285
|
+
# @param [String, #to_s] name
|
286
|
+
# @param [Hash{Symbol => Object}] options
|
287
|
+
# @option options [String, #to_s] :label
|
288
|
+
# @option options [String, #to_s] :comment
|
289
|
+
def property(*args)
|
290
|
+
case args.length
|
291
|
+
when 0
|
292
|
+
RDF::URI.intern("#{self}property")
|
293
|
+
else
|
294
|
+
name, options = args
|
295
|
+
options ||= {}
|
296
|
+
prop = RDF::URI.intern([to_s, name.to_s].join(''))
|
297
|
+
@@properties[prop] = true
|
298
|
+
@@labels[prop] = options[:label].to_s.strip.gsub(/\s+/m, ' ') if options[:label]
|
299
|
+
@@comments[prop] = options[:comment].to_s.strip.gsub(/\s+/m, ' ') if options[:comment]
|
300
|
+
(class << self; self; end).send(:define_method, name) { prop } unless name.to_s == "property"
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def [](name)
|
305
|
+
prop = RDF::URI.intern([to_s, name.to_s].join(''))
|
306
|
+
@@properties.fetch(prop) #raises KeyError on missing value
|
307
|
+
return prop
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
begin
|
312
|
+
define_method(:method_missing, BasicObject.instance_method(:method_missing))
|
313
|
+
rescue NameError
|
314
|
+
define_method(:method_missing, Kernel.instance_method(:method_missing))
|
315
|
+
end
|
316
|
+
|
317
|
+
private
|
318
|
+
@@properties = {}
|
319
|
+
end # StrictVocabulary
|
220
320
|
end # RDF
|