Class: RDF::Vocabulary
- Inherits:
-
Object
- Object
- RDF::Vocabulary
- Extended by:
- Enumerable
- Defined in:
- lib/rdf/vocabulary.rb,
lib/rdf/vocab/writer.rb
Overview
A Vocabulary represents an RDFS or OWL vocabulary.
A Vocabulary can also serve as a Domain Specific Language (DSL) for generating an RDF Graph definition for the vocabulary (see #to_enum).
### Defining a vocabulary using the DSL Vocabularies can be defined based on Vocabulary or StrictVocabulary using a simple Domain Specific Language (DSL).
-
Ontology information for the vocabulary itself can be specified using the Vocabulary.ontology method.
-
Terms of the vocabulary are specified using either ‘property` or `term` (alias), with the attributes of the term listed in a hash. See Vocabulary.property for description of the hash. Term attributes become properties of the associated Term (see Term#attributes).
Note that, by default, the prefix associated with the vocabulary for forming and interpreting PNames is created from the class name of the vocabulary. See _<em>prefix</em>_= for overriding this at runtime.
The simplest way to generate a DSL representation of a vocabulary is using Writer given an Graph representation of the vocabulary.
### Vocabularies:
The following vocabularies are pre-defined for your convenience:
-
RDF - Resource Description Framework (RDF)
-
OWL - Web Ontology Language (OWL)
-
RDFS - RDF Schema (RDFS)
-
XSD - XML Schema (XSD)
Other vocabularies are defined in the [rdf-vocab](rubygems.org/gems/rdf-vocab) gem
Direct Known Subclasses
Defined Under Namespace
Modules: Term Classes: Format, Writer
Class Method Summary collapse
-
.[](property) ⇒ RDF::URI
Returns the URI for the term ‘property` in this vocabulary.
-
.__prefix__ ⇒ Symbol
Returns a suggested vocabulary prefix for this vocabulary class.
-
.__prefix__=(prefix) ⇒ Symbol
Sets the vocabulary prefix to use for this vocabulary..
-
.each {|klass| ... } ⇒ Enumerator
Enumerates known RDF vocabulary classes.
-
.each_statement {|| ... } ⇒ Object
Enumerate each statement constructed from the defined vocabulary terms.
-
.enum_for(method = :each_statement, *args) ⇒ RDF::Enumerable::Enumerator
(also: to_enum)
Return an enumerator over Statement defined for this vocabulary.
-
.expand_pname(pname) ⇒ Term
Attempt to expand a Compact IRI/PName using loaded vocabularies.
-
.find(uri) ⇒ Vocabulary
Return the Vocabulary associated with a URI.
-
.find_term(uri) ⇒ Vocabulary::Term
Return the Vocabulary term associated with a URI.
-
.from_graph(graph, url: nil, class_name: nil, extra: nil) ⇒ RDF::Vocabulary
Create a vocabulary from a graph or enumerable.
-
.from_sym(sym) ⇒ RDF::Vocabulary
Return the vocabulary based on it’s class_name symbol.
-
.imported_from ⇒ Array<RDF::Vocabulary>
List of vocabularies which import this vocabulary.
-
.imports ⇒ Array<RDF::Vocabulary>
(also: __imports__)
List of vocabularies this vocabulary ‘owl:imports`.
-
.inspect ⇒ String
Returns a developer-friendly representation of this vocabulary class.
-
.limit_vocabs(*vocabs) ⇒ Array<RDF::Vocabulary>
Limits iteration over vocabularies to just those selected.
- .ontology(*args) ⇒ Object (also: __ontology__)
-
.properties ⇒ Object
(also: __properties__)
@return [Array<RDF::URI>] a list of properties in the current vocabulary.
- .property(*args) ⇒ Object (also: term, __property__)
-
.register(prefix, vocab, **params) ⇒ Hash
Register a vocabulary for internal prefix lookups.
-
.strict? ⇒ Boolean
Is this a strict vocabulary, or a liberal vocabulary allowing arbitrary properties?.
-
.to_iri ⇒ RDF::URI
Returns the base URI for this vocabulary class.
-
.to_s ⇒ String
Returns a string representation of this vocabulary class.
-
.to_uri ⇒ RDF::URI
Returns the base URI for this vocabulary class.
-
.vocab_map ⇒ Hash{Symbol => Hash{Symbol => String}}
A hash of all vocabularies by prefix showing relevant URI and associated vocabulary Class Name.
Instance Method Summary collapse
-
#[](property) ⇒ URI
Returns the URI for the term ‘property` in this vocabulary.
-
#initialize(uri) ⇒ Vocabulary
constructor
A new instance of Vocabulary.
-
#inspect ⇒ String
Returns a developer-friendly representation of this vocabulary.
-
#to_s ⇒ String
Returns a string representation of this vocabulary.
-
#to_uri ⇒ URI
(also: #to_iri)
Returns the base URI for this vocabulary.
Constructor Details
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(property, *args, &block) ⇒ Object (protected)
723 724 725 726 727 728 729 730 731 732 |
# File 'lib/rdf/vocabulary.rb', line 723 def method_missing(property, *args, &block) property = self.class.camelize(property.to_s) if %w(to_ary).include?(property.to_s) super elsif args.empty? self[property] else super end end |
Class Method Details
.[](property) ⇒ RDF::URI
Returns the URI for the term ‘property` in this vocabulary.
405 406 407 408 409 410 411 |
# File 'lib/rdf/vocabulary.rb', line 405 def [](property) if props.key?(property.to_sym) props[property.to_sym] else Term.intern([to_s, property.to_s].join(''), vocab: self, attributes: {}) end end |
.__prefix__ ⇒ Symbol
Returns a suggested vocabulary prefix for this vocabulary class.
609 610 611 612 613 |
# File 'lib/rdf/vocabulary.rb', line 609 def __prefix__ instance_variable_defined?(:@__prefix__) ? @__prefix__ : __name__.split('::').last.downcase.to_sym end |
.__prefix__=(prefix) ⇒ Symbol
Sets the vocabulary prefix to use for this vocabulary..
625 626 627 628 629 630 |
# File 'lib/rdf/vocabulary.rb', line 625 def __prefix__=(prefix) params = RDF::Vocabulary.vocab_map[__prefix__] @__prefix__ = prefix.to_sym RDF::Vocabulary.register(@__prefix__, self, **params) @__prefix__ end |
.each {|klass| ... } ⇒ Enumerator
Enumerates known RDF vocabulary classes.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/rdf/vocabulary.rb', line 93 def each(&block) if self.equal?(Vocabulary) if instance_variable_defined?(:@vocabs) && @vocabs @vocabs.select(&:name).each(&block) else # This is needed since all vocabulary classes are defined using # Ruby's autoloading facility, meaning that `@@subclasses` will be # empty until each subclass has been touched or require'd. RDF::VOCABS.each { |v, p| RDF.const_get(p[:class_name].to_sym) unless v == :rdf } @@subclasses.select(&:name).each(&block) end else __properties__.each(&block) end end |
.each_statement {|| ... } ⇒ Object
468 469 470 471 472 473 474 475 |
# File 'lib/rdf/vocabulary.rb', line 468 def each_statement(&block) props.each do |name, subject| subject.each_statement(&block) end # Also include the ontology, if it's not also a property @ontology.each_statement(&block) if self.ontology && self.ontology != self end |
.enum_for(method = :each_statement, *args) ⇒ RDF::Enumerable::Enumerator Also known as: to_enum
Return an enumerator over Statement defined for this vocabulary.
452 453 454 455 456 457 458 |
# File 'lib/rdf/vocabulary.rb', line 452 def enum_for(method = :each_statement, *args) # Ensure that enumerators are, themselves, queryable this = self Enumerable::Enumerator.new do |yielder| this.send(method, *args) {|*y| yielder << (y.length > 1 ? y : y.first)} end end |
.expand_pname(pname) ⇒ Term
Attempt to expand a Compact IRI/PName using loaded vocabularies
The local-part of the PName will will have [reserved character escapes](www.w3.org/TR/turtle/#reserved) unescaped.
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/rdf/vocabulary.rb', line 346 def (pname) return pname unless pname.is_a?(String) || pname.is_a?(Symbol) prefix, suffix = pname.to_s.split(":", 2) # Unescape escaped PN_ESCAPE_CHARS if suffix.match?(RDF::URI::PN_ESCAPES) suffix = suffix.gsub(RDF::URI::PN_ESCAPES) {|matched| matched[1..-1]} end if prefix == "rdf" RDF[suffix] elsif vocab_detail = RDF::Vocabulary.vocab_map[prefix.to_sym] vocab = vocab_detail[:class] || RDF::Vocabulary.from_sym(vocab_detail[:class_name]) suffix.to_s.empty? ? vocab.to_uri : vocab[suffix] else (RDF::Vocabulary.find_term(pname) rescue nil) || RDF::URI(pname, validate: true) end end |
.find(uri) ⇒ Vocabulary
Return the Vocabulary associated with a URI. Allows the trailing ‘/’ or ‘#’ to be excluded
369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/rdf/vocabulary.rb', line 369 def find(uri) uri = RDF::URI(uri) if uri.is_a?(String) return nil unless uri.uri? && uri.valid? RDF::Vocabulary.detect do |v| if uri.length >= v.to_uri.length uri.start_with?(v.to_uri) else v.to_uri.to_s.sub(%r([/#]$), '') == uri.to_s end end end |
.find_term(uri) ⇒ Vocabulary::Term
Return the Vocabulary term associated with a URI
387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/rdf/vocabulary.rb', line 387 def find_term(uri) uri = RDF::URI(uri) return uri if uri.is_a?(Vocabulary::Term) if vocab = find(uri) if vocab.ontology == uri vocab.ontology else suffix = uri.to_s[vocab.to_uri.to_s.length..-1].to_s vocab[suffix] end end end |
.from_graph(graph, url: nil, class_name: nil, extra: nil) ⇒ RDF::Vocabulary
Create a vocabulary from a graph or enumerable
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 |
# File 'lib/rdf/vocabulary.rb', line 495 def from_graph(graph, url: nil, class_name: nil, extra: nil) vocab = case class_name when RDF::Vocabulary class_name.instance_variable_set(:@ontology, nil) class_name.instance_variable_set(:@properties, nil) class_name when String Object.const_set(class_name, Class.new(self.create(url))) else Class.new(self.create(url)) end ont_url = url.to_s.sub(%r([/#]$), '') term_defs = {} = {} graph.each do |statement| #next unless statement.subject.uri? if statement.subject.start_with?(url) || statement.subject == ont_url name = statement.subject.to_s[url.to_s.length..-1].to_s term = (term_defs[name.to_sym] ||= {}) else # subject is not a URI or is not associated with the vocabulary term = ([statement.subject] ||= {}) end key = Term::URI_ATTRs.fetch(statement.predicate) do statement.predicate.to_s.to_sym end (term[key] ||= []) << statement.object end # Create extra terms term_defs = case extra when Array extra.inject({}) {|memo, s| memo[s.to_sym] = {}; memo}.merge(term_defs) when Hash extra.merge(term_defs) else term_defs end # Pass over embedded_defs with anonymous references, once .each do |term, attributes| attributes.each do |ak, avs| # Turn embedded BNodes into either their Term definition or a List avs = [avs] unless avs.is_a?(Array) attributes[ak] = avs.map do |av| l = RDF::List.new(subject: av, graph: graph) if l.valid? RDF::List.new(subject: av) do |nl| l.each do |lv| nl << ([lv] ? Term.new(vocab: vocab, attributes: [lv]) : lv) end end elsif av.is_a?(RDF::Node) Term.new(vocab: vocab, attributes: [av]) if [av] else av end end.compact end end term_defs.each do |term, attributes| # Turn embedded BNodes into either their Term definition or a List attributes.each do |ak, avs| attributes[ak] = avs.is_a?(Array) ? (avs.map do |av| l = RDF::List.new(subject: av, graph: graph) if l.valid? RDF::List.new(subject: av) do |nl| l.each do |lv| nl << ([lv] ? Term.new(vocab: vocab, attributes: [lv]) : lv) end end elsif av.is_a?(RDF::Node) Term.new(vocab: vocab, attributes: [av]) if [av] else av end end).compact : avs end if term == :"" vocab.__ontology__ vocab, attributes else vocab.__property__ term, attributes end end vocab end |
.from_sym(sym) ⇒ RDF::Vocabulary
Return the vocabulary based on it’s class_name symbol
126 127 128 |
# File 'lib/rdf/vocabulary.rb', line 126 def from_sym(sym) RDF.const_get(sym.to_sym) end |
.imported_from ⇒ Array<RDF::Vocabulary>
List of vocabularies which import this vocabulary
431 432 433 434 435 |
# File 'lib/rdf/vocabulary.rb', line 431 def imported_from @imported_from ||= begin RDF::Vocabulary.select {|v| v.__imports__.include?(self)} end end |
.imports ⇒ Array<RDF::Vocabulary> Also known as: __imports__
the alias __imports__ guards against ‘RDF::OWL.imports` returning a term, rather than an array of vocabularies
List of vocabularies this vocabulary ‘owl:imports`
418 419 420 421 422 423 424 425 |
# File 'lib/rdf/vocabulary.rb', line 418 def imports return [] unless self.ontology @imports ||= begin Array(self.ontology.properties[:"http://www.w3.org/2002/07/owl#imports"]).compact rescue KeyError [] end end |
.inspect ⇒ String
Returns a developer-friendly representation of this vocabulary class.
592 593 594 595 596 597 598 |
# File 'lib/rdf/vocabulary.rb', line 592 def inspect if self == Vocabulary self.to_s else sprintf("%s(%s)", superclass.to_s, to_s) end end |
.limit_vocabs(*vocabs) ⇒ Array<RDF::Vocabulary>
Limits iteration over vocabularies to just those selected
179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/rdf/vocabulary.rb', line 179 def limit_vocabs(*vocabs) @vocabs = if Array(vocabs).empty? nil else vocabs.map do |vocab| vocab = :rdfv if vocab == :rdf vocab.is_a?(Symbol) && RDF::VOCABS.key?(vocab) ? RDF.const_get(RDF::VOCABS[vocab][:class_name].to_sym) : vocab end.compact end end |
.ontology ⇒ RDF::Vocabulary::Term .ontology(name, options) ⇒ RDF::Vocabulary::Term Also known as: __ontology__
If the ontology URI has the vocabulary namespace URI as a prefix, it may also be defined using ‘#property` or `#term`
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/rdf/vocabulary.rb', line 313 def ontology(*args) case args.length when 0 @ontology if instance_variable_defined?(:@ontology) else uri, = args URI.cache.delete(uri.to_s.to_sym) # Clear any previous entry # Term attributes passed in a block for lazy evaluation. This helps to avoid load-time circular dependencies @ontology = Term.intern(uri.to_s, vocab: self, attributes: || {}) # If the URI is the same as the vocabulary namespace, also define it as a term props[:""] ||= @ontology if self.to_s == uri.to_s @ontology end end |
.properties ⇒ Object Also known as: __properties__
@return [Array<RDF::URI>] a list of properties in the current vocabulary
333 334 335 |
# File 'lib/rdf/vocabulary.rb', line 333 def properties props.values end |
.property ⇒ RDF::Vocabulary::Term .property(name, options) ⇒ RDF::Vocabulary::Term Also known as: term, __property__
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/rdf/vocabulary.rb', line 245 def property(*args) case args.length when 0 Term.intern("#{self}property", vocab: self, attributes: {}) else name = args.shift unless args.first.is_a?(Hash) = args.last if name uri_str = [to_s, name.to_s].join('') URI.cache.delete(uri_str.to_sym) # Clear any previous entry # Term attributes passed in a block for lazy evaluation. This helps to avoid load-time circular dependencies prop = Term.intern(uri_str, vocab: self, attributes: || {}) props[name.to_sym] = prop # If name is empty, also treat it as the ontology @ontology ||= prop if name.to_s.empty? # Define an accessor, except for problematic properties (class << self; self; end).send(:define_method, name) { prop } unless %w(property term hash).include?(name.to_s) else # Define the term without a name # Term attributes passed in a block for lazy evaluation. This helps to avoid load-time circular dependencies prop = Term.new(vocab: self, attributes: ) end prop end end |
.register(prefix, vocab, **params) ⇒ Hash
Register a vocabulary for internal prefix lookups. Parameters of interest include ‘:uri`, `:class_name`, `:source`, and `:skip`.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/rdf/vocabulary.rb', line 138 def register(prefix, vocab, **params) # check the input raise ArgumentError, "#{prefix} must be symbol-able" unless [String, Symbol].any? { |c| prefix.is_a? c } # note an explicit uri: param overrides case vocab when String then params[:uri] ||= vocab when Class raise ArgumentError, 'vocab must be an RDF::(Strict)Vocabulary' unless vocab.ancestors.include? RDF::Vocabulary params[:class] = vocab params[:uri] ||= vocab.to_uri.to_s end # fill in the class name params[:class_name] ||= prefix.to_s.upcase # now freeze and assign vocab_map[prefix.to_s.to_sym] = params.freeze end |
.strict? ⇒ Boolean
Is this a strict vocabulary, or a liberal vocabulary allowing arbitrary properties?
194 |
# File 'lib/rdf/vocabulary.rb', line 194 def strict?; false; end |
.to_iri ⇒ RDF::URI
Returns the base URI for this vocabulary class. For IRI compatibility
446 447 448 |
# File 'lib/rdf/vocabulary.rb', line 446 def to_uri RDF::URI.intern(@@uris[self].to_s) end |
.to_s ⇒ String
Returns a string representation of this vocabulary class.
481 482 483 |
# File 'lib/rdf/vocabulary.rb', line 481 def to_s @@uris.key?(self) ? @@uris[self].to_s : super end |
.to_uri ⇒ RDF::URI
Returns the base URI for this vocabulary class.
441 442 443 |
# File 'lib/rdf/vocabulary.rb', line 441 def to_uri RDF::URI.intern(@@uris[self].to_s) end |
.vocab_map ⇒ Hash{Symbol => Hash{Symbol => String}}
A hash of all vocabularies by prefix showing relevant URI and associated vocabulary Class Name
114 115 116 117 118 119 |
# File 'lib/rdf/vocabulary.rb', line 114 def vocab_map # Create an initial duplicate of RDF::VOCABS. We want to # ensure the hash itself is modifiable but the values are # frozen. @vocab_map ||= RDF::VOCABS.transform_values(&:freeze) end |
Instance Method Details
#[](property) ⇒ URI
Returns the URI for the term ‘property` in this vocabulary.
685 686 687 |
# File 'lib/rdf/vocabulary.rb', line 685 def [](property) Term.intern([to_s, property.to_s].join(''), vocab: self, attributes: {}) end |
#inspect ⇒ String
Returns a developer-friendly representation of this vocabulary.
712 713 714 |
# File 'lib/rdf/vocabulary.rb', line 712 def inspect sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, to_s) end |
#to_s ⇒ String
Returns a string representation of this vocabulary.
704 705 706 |
# File 'lib/rdf/vocabulary.rb', line 704 def to_s @uri.to_s end |