Class: RDF::Literal
- Inherits:
-
Object
- Object
- RDF::Literal
- Includes:
- Term
- Defined in:
- lib/rdf/model/literal.rb,
lib/rdf/model/literal/date.rb,
lib/rdf/model/literal/time.rb,
lib/rdf/model/literal/token.rb,
lib/rdf/model/literal/double.rb,
lib/rdf/model/literal/boolean.rb,
lib/rdf/model/literal/decimal.rb,
lib/rdf/model/literal/integer.rb,
lib/rdf/model/literal/numeric.rb,
lib/rdf/model/literal/datetime.rb,
lib/rdf/model/literal/temporal.rb
Overview
An RDF literal.
Subclasses of Literal should define DATATYPE and GRAMMAR constants, which are used for identifying the appropriate class to use for a datatype URI and to perform lexical matching on the value.
Literal comparison with other Value instances call Value#type_error, which, returns false. Implementations wishing to have TypeError raised should mix-in TypeCheck. This is required for strict SPARQL conformance.
Specific typed literals may have behavior different from the default implementation. See the following defined sub-classes for specific documentation. Additional sub-classes may be defined, and will interoperate by defining DATATYPE
and GRAMMAR
constants, in addition other required overrides of RDF::Literal behavior.
In RDF 1.1, all literals are typed, including plain literals and language-tagged strings. Internally, plain literals are given the xsd:string
datatype and language-tagged strings are given the rdf:langString
datatype. Creating a plain literal, without a datatype or language, will automatically provide the xsd:string
datatype; similar for language-tagged strings. Note that most serialization formats will remove this datatype. Code which depends on a literal having the xsd:string
datatype being different from a plain literal (formally, without a datatype) may break. However note that the #has\_datatype?
will continue to return false
for plain or language-tagged strings.
RDF 1.2 adds directional language-tagged strings which are effectively a subclass of language-tagged strings contining an additional direction component with value either ltr or rtl for Left-to-Right or Right-to-Left. This determines the general direction of a string when presented in n a user agent, where it might be in conflict with the inherent direction of the leading Unicode code points. Directional language-tagged strings are given the rdf:langString
datatype.
Defined Under Namespace
Classes: Boolean, Date, DateTime, Decimal, Double, Integer, Numeric, Temporal, Time, Token
Constant Summary collapse
- TRUE =
RDF::Literal.new(true)
- FALSE =
RDF::Literal.new(false)
- ZERO =
RDF::Literal.new(0)
- XSD_STRING =
RDF::URI("http://www.w3.org/2001/XMLSchema#string")
Instance Attribute Summary collapse
-
#datatype ⇒ URI
The XML Schema datatype URI (optional).
-
#direction ⇒ Symbol
The base direction (optional).
-
#language ⇒ Symbol
The language-tag (optional).
Instance Method Summary collapse
-
#<=>(other) ⇒ Integer
Compares
self
toother
for sorting purposes (with type check). -
#==(other) ⇒ Boolean
(also: #===)
Returns
true
if this literal is equivalent toother
(with type check). -
#canonicalize! ⇒ RDF::Literal
Converts this literal into its canonical lexical representation.
-
#compatible?(other) ⇒ Boolean
Term compatibility according to SPARQL.
-
#comperable_datatype2?(other) ⇒ Boolean
Returns
true
if the literals are comperable. -
#comperable_datatype?(other) ⇒ Boolean
Returns
true
if the literal has a datatype and the comparison should return false instead of raise a type error. -
#datatype? ⇒ Boolean
(also: #has_datatype?, #typed?, #datatyped?)
Returns
true
if this is a datatyped literal. -
#direction? ⇒ Boolean
Returns
true
if this is a directional language-tagged string. -
#eql?(other) ⇒ Boolean
Determins if
self
is the same term asother
. -
#escape(string) ⇒ String
Escape a literal using ECHAR escapes.
-
#hash ⇒ Integer
Returns a hash code for this literal.
-
#humanize(lang = :en) ⇒ String
Returns a human-readable value for the literal.
-
#initialize(value, language: nil, datatype: nil, direction: nil, lexical: nil, validate: false, canonicalize: false, **options) ⇒ Literal
constructor
Literals without a datatype are given either
xsd:string
,rdf:langString
, orrdf:dirLangString
, depending on if there islanguage
and/ordirection
. -
#inspect ⇒ String
Returns a developer-friendly representation of
self
. -
#language? ⇒ Boolean
(also: #has_language?)
Returns
true
if this is a language-tagged string. -
#literal? ⇒ Boolean
Returns
true
. -
# ⇒ String
protected
This method is implemented when the datatype is
xsd:string
,rdf:langString
, orrdf:dirLangString
. - #object ⇒ Object
-
#plain? ⇒ Boolean
Returns
true
if this is a plain literal. - #respond_to_missing?(name, include_private = false) ⇒ Boolean protected
-
#simple? ⇒ Boolean
Returns
true
if this is a simple literal. -
#squish(*other_string) ⇒ RDF::Literal
Returns the literal, first removing all whitespace on both ends of the value, and then changing remaining consecutive whitespace groups into one space each.
-
#squish! ⇒ Object
Performs a destructive #squish.
-
#to_s ⇒ String
Returns the value as a string.
-
#valid? ⇒ Boolean
Returns
true
if the value adheres to the defined grammar of the datatype. -
#validate! ⇒ RDF::Literal
Validates the value using Value#valid?, raising an error if the value is invalid.
-
#value ⇒ String
Returns the value as a string.
-
#value_hash ⇒ Integer
Returns a hash code for the value.
Methods included from Term
#term?, #terms, #to_base, #to_term
Methods included from Value
#anonymous?, #canonicalize, #constant?, #graph?, #inspect!, #invalid?, #iri?, #list?, #node?, #resource?, #start_with?, #statement?, #term?, #to_nquads, #to_ntriples, #to_rdf, #to_term, #type_error, #uri?, #variable?
Constructor Details
#initialize(value, language: nil, datatype: nil, direction: nil, lexical: nil, validate: false, canonicalize: false, **options) ⇒ Literal
Literals without a datatype are given either xsd:string
, rdf:langString
, or rdf:dirLangString
,
depending on if there is language
and/or direction
.
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/rdf/model/literal.rb', line 190 def initialize(value, language: nil, datatype: nil, direction: nil, lexical: nil, validate: false, canonicalize: false, **) @object = value.freeze @string = lexical if lexical @string = value if !defined?(@string) && value.is_a?(String) @string = @string.encode(Encoding::UTF_8).freeze if instance_variable_defined?(:@string) @object = @string if instance_variable_defined?(:@string) && @object.is_a?(String) @language = language.to_s.downcase.to_sym if language @direction = direction.to_s.downcase.to_sym if direction @datatype = RDF::URI(datatype).freeze if datatype @datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE) @datatype ||= if instance_variable_defined?(:@language) && @language && instance_variable_defined?(:@direction) && @direction RDF.dirLangString elsif instance_variable_defined?(:@language) && @language RDF.langString else XSD_STRING end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
# ⇒ String (protected)
593 594 595 596 597 598 599 |
# File 'lib/rdf/model/literal.rb', line 593 def method_missing(name, *args) case name when :to_str return to_s if [RDF.langString, RDF.dirLangString, XSD_STRING].include?(@datatype) end super end |
Instance Attribute Details
#datatype ⇒ URI
Returns The XML Schema datatype URI (optional).
167 168 169 |
# File 'lib/rdf/model/literal.rb', line 167 def datatype @datatype end |
#direction ⇒ Symbol
Returns The base direction (optional). Implies datatype
is rdf:dirLangString
.
164 165 166 |
# File 'lib/rdf/model/literal.rb', line 164 def direction @direction end |
#language ⇒ Symbol
Returns The language-tag (optional). Implies datatype
is rdf:langString
.
161 162 163 |
# File 'lib/rdf/model/literal.rb', line 161 def language @language end |
Instance Method Details
#<=>(other) ⇒ Integer
Compares self
to other
for sorting purposes (with type check).
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/rdf/model/literal.rb', line 353 def <=>(other) case other when Literal case when self.eql?(other) 0 when self.language? && other.language? # Literals with languages can compare if languages are identical self.to_s <=> other.to_s when self.simple? && other.simple? self.to_s <=> other.to_s when !self.valid? type_error("#{self.inspect} is invalid") || 0 when !other.valid? type_error("#{other.inspect} is invalid") || 0 when self.comperable_datatype2?(other) self.object <=> other.object else type_error("#{self.inspect} and #{other.inspect} are not comperable") || 0 end when String self.simple? && self.value <=> other else 1 end end |
#==(other) ⇒ Boolean Also known as: ===
Returns true
if this literal is equivalent to other
(with type check).
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 |
# File 'lib/rdf/model/literal.rb', line 320 def ==(other) case other when Literal case when self.eql?(other) true when self.direction? && self.direction == other.direction # Literals with directions can compare if languages and directions are identical self.value_hash == other.value_hash && self.value == other.value when self.language? && self.language == other.language # Literals with languages can compare if languages are identical self.value_hash == other.value_hash && self.value == other.value when self.simple? && other.simple? self.value_hash == other.value_hash && self.value == other.value when other.comperable_datatype?(self) || self.comperable_datatype?(other) # Comparing plain with undefined datatypes does not generate an error, but returns false # From data-r2/expr-equal/eq-2-2. false else type_error("unable to determine whether #{self.inspect} and #{other.inspect} are equivalent") end when String self.simple? && self.value.eql?(other) else false end end |
#canonicalize! ⇒ RDF::Literal
Converts this literal into its canonical lexical representation.
Subclasses should override this as needed and appropriate.
513 514 515 |
# File 'lib/rdf/model/literal.rb', line 513 def canonicalize! self end |
#compatible?(other) ⇒ Boolean
Term compatibility according to SPARQL
Compatibility of two arguments is defined as:
- The arguments are simple literals or literals typed as xsd:string
- The arguments are plain literals with identical language-tags and directions
- The first argument is a plain literal with language-tag and the second argument is a simple literal or literal typed as xsd:string
255 256 257 258 259 260 261 262 263 264 |
# File 'lib/rdf/model/literal.rb', line 255 def compatible?(other) return false unless other.literal? && plain? && other.plain? # * The arguments are simple literals or literals typed as xsd:string # * The arguments are plain literals with identical language-tags # * The first argument is a plain literal with language-tag and the second argument is a simple literal or literal typed as xsd:string language? || direction? ? (language == other.language && direction == other.direction || other.datatype == XSD_STRING) : other.datatype == XSD_STRING end |
#comperable_datatype2?(other) ⇒ Boolean
Returns true
if the literals are comperable.
Used for <=> operator.
492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/rdf/model/literal.rb', line 492 def comperable_datatype2?(other) case self when RDF::Literal::Numeric, RDF::Literal::Boolean case other when RDF::Literal::Numeric, RDF::Literal::Boolean true else false end else self.datatype == other.datatype end end |
#comperable_datatype?(other) ⇒ Boolean
Returns true
if the literal has a datatype and the comparison should
return false instead of raise a type error.
This behavior is intuited from SPARQL data-r2/expr-equal/eq-2-2
472 473 474 475 476 477 478 479 480 481 482 483 484 |
# File 'lib/rdf/model/literal.rb', line 472 def comperable_datatype?(other) return false unless self.plain? || self.language? case other when RDF::Literal::Numeric, RDF::Literal::Boolean, RDF::Literal::Date, RDF::Literal::Time, RDF::Literal::DateTime # Invald types can be compared without raising a TypeError if literal has a language (open-eq-08) !other.valid? && self.language? else # An unknown datatype may not be used for comparison, unless it has a language? (open-eq-8) self.language? end end |
#datatype? ⇒ Boolean Also known as: has_datatype?, typed?, datatyped?
Returns true
if this is a datatyped literal.
For historical reasons, this excludes xsd:string and rdf:langString
431 432 433 |
# File 'lib/rdf/model/literal.rb', line 431 def datatype? !plain? && !language? && !direction? end |
#direction? ⇒ Boolean
Returns true
if this is a directional language-tagged string.
420 421 422 |
# File 'lib/rdf/model/literal.rb', line 420 def direction? datatype == RDF.dirLangString end |
#eql?(other) ⇒ Boolean
Determins if self
is the same term as other
.
299 300 301 302 303 304 305 306 307 |
# File 'lib/rdf/model/literal.rb', line 299 def eql?(other) self.equal?(other) || (self.class.eql?(other.class) && self.value_hash == other.value_hash && self.value.eql?(other.value) && self.language.to_s.eql?(other.language.to_s) && self.direction.to_s.eql?(other.direction.to_s) && self.datatype.eql?(other.datatype)) end |
#escape(string) ⇒ String
N-Triples only requires '\"\n\r' to be escaped.
Escape a literal using ECHAR escapes.
ECHAR ::= '\' [tbnrf"']
551 552 553 554 555 556 557 558 559 560 |
# File 'lib/rdf/model/literal.rb', line 551 def escape(string) string.gsub('\\', '\\\\'). gsub("\t", '\\t'). gsub("\b", '\\b'). gsub("\n", '\\n'). gsub("\r", '\\r'). gsub("\f", '\\f'). gsub('"', '\\"'). freeze end |
#hash ⇒ Integer
Returns a hash code for this literal.
270 271 272 |
# File 'lib/rdf/model/literal.rb', line 270 def hash @hash ||= [to_s, datatype, language, direction].compact.hash end |
#humanize(lang = :en) ⇒ String
Returns a human-readable value for the literal
575 576 577 |
# File 'lib/rdf/model/literal.rb', line 575 def humanize(lang = :en) to_s.freeze end |
#inspect ⇒ String
Returns a developer-friendly representation of self
.
583 584 585 |
# File 'lib/rdf/model/literal.rb', line 583 def inspect sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, RDF::NTriples.serialize(self)) end |
#language? ⇒ Boolean Also known as: has_language?
Returns true
if this is a language-tagged string.
410 411 412 |
# File 'lib/rdf/model/literal.rb', line 410 def language? [RDF.langString, RDF.dirLangString].include?(datatype) end |
#literal? ⇒ Boolean
Returns true
.
228 229 230 |
# File 'lib/rdf/model/literal.rb', line 228 def literal? true end |
#object ⇒ Object
220 221 222 |
# File 'lib/rdf/model/literal.rb', line 220 def object defined?(@object) ? @object : value end |
#plain? ⇒ Boolean
Returns true
if this is a plain literal. A plain literal
may have a language and direction, but may not have a datatype. For
all practical purposes, this includes xsd:string literals
too.
387 388 389 390 391 392 393 |
# File 'lib/rdf/model/literal.rb', line 387 def plain? [ RDF.langString, RDF.dirLangString, XSD_STRING ].include?(datatype) end |
#respond_to_missing?(name, include_private = false) ⇒ Boolean (protected)
601 602 603 604 605 606 607 |
# File 'lib/rdf/model/literal.rb', line 601 def respond_to_missing?(name, include_private = false) case name when :to_str return true if [RDF.langString, RDF.dirLangString, XSD_STRING].include?(@datatype) end super end |
#simple? ⇒ Boolean
Returns true
if this is a simple literal.
A simple literal has no datatype or language.
401 402 403 |
# File 'lib/rdf/model/literal.rb', line 401 def simple? datatype == XSD_STRING end |
#squish(*other_string) ⇒ RDF::Literal
Returns the literal, first removing all whitespace on both ends of the value, and then changing remaining consecutive whitespace groups into one space each.
Note that it handles both ASCII and Unicode whitespace.
524 525 526 |
# File 'lib/rdf/model/literal.rb', line 524 def squish(*other_string) self.dup.squish! end |
#squish! ⇒ Object
Performs a destructive #squish.
533 534 535 536 537 538 539 |
# File 'lib/rdf/model/literal.rb', line 533 def squish! @string = value. gsub(/\A[[:space:]]+/, ''). gsub(/[[:space:]]+\z/, ''). gsub(/[[:space:]]+/, ' ') self end |
#to_s ⇒ String
Returns the value as a string.
566 567 568 |
# File 'lib/rdf/model/literal.rb', line 566 def to_s @object.to_s.freeze end |
#valid? ⇒ Boolean
Returns true
if the value adheres to the defined grammar of the
datatype.
444 445 446 447 448 449 450 451 452 |
# File 'lib/rdf/model/literal.rb', line 444 def valid? BCP47.parse(language.to_s) if language? return false if direction? && !%i{ltr rtl}.include?(direction) return false if datatype? && datatype.invalid? grammar = self.class.const_get(:GRAMMAR) rescue nil grammar.nil? || value.match?(grammar) rescue BCP47::InvalidLanguageTag false end |
#validate! ⇒ RDF::Literal
Validates the value using Value#valid?, raising an error if the value is invalid.
461 462 463 464 |
# File 'lib/rdf/model/literal.rb', line 461 def validate! raise ArgumentError, "#{to_s.inspect} is not a valid <#{datatype.to_s}> literal" if invalid? self end |
#value ⇒ String
Returns the value as a string.
214 215 216 |
# File 'lib/rdf/model/literal.rb', line 214 def value instance_variable_defined?(:@string) && @string || to_s end |
#value_hash ⇒ Integer
Returns a hash code for the value.
279 280 281 |
# File 'lib/rdf/model/literal.rb', line 279 def value_hash @value_hash ||= value.hash end |