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
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 literals. Internally, plain literals are given the ‘xsd:string` datatype and language tagged literals 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 literals. 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 literals.
Defined Under Namespace
Classes: Boolean, Date, DateTime, Decimal, Double, Integer, Numeric, Time, Token
Constant Summary collapse
- TRUE =
RDF::Literal.new(true)
- FALSE =
RDF::Literal.new(false)
- ZERO =
RDF::Literal.new(0)
Instance Attribute Summary collapse
-
#datatype ⇒ URI
The XML Schema datatype URI (optional).
-
#language ⇒ Symbol
The language tag (optional).
Class Method Summary collapse
-
.datatype_map ⇒ Object
Return Hash mapping from datatype URI to class.
-
.datatyped_class(uri) ⇒ Object
Return datatype class for uri, or nil if none is found.
- .new(value, options = {}) ⇒ Object
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
(also: #===)
Returns ‘true` if this literal is equivalent to `other` (with type check).
-
#canonicalize! ⇒ RDF::Literal
Converts this literal into its canonical lexical representation.
-
#compatible?(other) ⇒ Boolean
Term compatibility according to SPARQL.
-
#comperable_datatype?(other) ⇒ Boolean
Returns ‘true` if the literal has a datatype and the comparison should return false instead of raise a type error.
-
#eql?(other) ⇒ Boolean
Determins if ‘self` is the same term as `other`.
-
#escape(string) ⇒ String
Escape a literal using ECHAR escapes.
- #freeze ⇒ Object
-
#has_datatype? ⇒ Boolean
(also: #datatype?, #typed?, #datatyped?)
Returns ‘true` if this is a datatyped literal.
-
#has_language? ⇒ Boolean
(also: #language?)
Returns ‘true` if this is a language-tagged literal.
-
#hash ⇒ Fixnum
Returns a hash code for this literal.
-
#humanize(lang = :en) ⇒ String
Returns a human-readable value for the literal.
-
#initialize(value, options = {}) ⇒ Literal
constructor
Literals without a datatype are given either xsd:string or rdf:langString depending on if there is language.
-
#inspect ⇒ String
Returns a developer-friendly representation of ‘self`.
-
#literal? ⇒ Boolean
Returns ‘true`.
- #object ⇒ Object
-
#plain? ⇒ Boolean
Returns ‘true` if this is a plain literal.
-
#simple? ⇒ Boolean
Returns ‘true` if this is a simple literal.
-
#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 ⇒ Fixnum
Returns a hash code for the value.
Methods included from Term
#<=>, #term?, #to_base, #to_term
Methods included from Value
#anonymous?, #canonicalize, #constant?, #graph?, #inspect!, #invalid?, #iri?, #list?, #node?, #resource?, #statement?, #term?, #to_nquads, #to_ntriples, #to_rdf, #to_term, #type_error, #uri?, #variable?
Constructor Details
#initialize(value, options = {}) ⇒ Literal
Literals without a datatype are given either xsd:string or rdf:langString depending on if there is language
164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/rdf/model/literal.rb', line 164 def initialize(value, = {}) @object = value.freeze @string = [:lexical] if [:lexical] @string = value if !defined?(@string) && value.is_a?(String) @string = @string.encode(Encoding::UTF_8).freeze if @string @object = @string if @string && @object.is_a?(String) @language = [:language].to_s.downcase.to_sym if [:language] @datatype = RDF::URI([:datatype]).freeze if [:datatype] @datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE) @datatype ||= @language ? RDF.langString : RDF::XSD.string raise ArgumentError, "datatype of rdf:langString requires a language" if !@language && @datatype == RDF::langString end |
Instance Attribute Details
#datatype ⇒ URI
Returns The XML Schema datatype URI (optional).
143 144 145 |
# File 'lib/rdf/model/literal.rb', line 143 def datatype @datatype end |
#language ⇒ Symbol
Returns The language tag (optional).
140 141 142 |
# File 'lib/rdf/model/literal.rb', line 140 def language @language end |
Class Method Details
.datatype_map ⇒ Object
Return Hash mapping from datatype URI to class
90 91 92 93 94 95 96 |
# File 'lib/rdf/model/literal.rb', line 90 def self.datatype_map @@datatype_map ||= Hash[ @@subclasses .select {|klass| klass.const_defined?(:DATATYPE)} .map {|klass| [klass.const_get(:DATATYPE).to_s, klass]} ] end |
.datatyped_class(uri) ⇒ Object
Return datatype class for uri, or nil if none is found
101 102 103 |
# File 'lib/rdf/model/literal.rb', line 101 def self.datatyped_class(uri) datatype_map[uri] end |
.new(value, options = {}) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rdf/model/literal.rb', line 107 def self.new(value, = {}) raise ArgumentError, "datatype with language must be rdf:langString" if [:language] && ([:datatype] || RDF.langString).to_s != RDF.langString.to_s klass = case when !self.equal?(RDF::Literal) self # subclasses can be directly constructed without type dispatch when typed_literal = datatyped_class([:datatype].to_s) typed_literal else case value when ::TrueClass then RDF::Literal::Boolean when ::FalseClass then RDF::Literal::Boolean when ::Integer then RDF::Literal::Integer when ::Float then RDF::Literal::Double when ::BigDecimal then RDF::Literal::Decimal when ::DateTime then RDF::Literal::DateTime when ::Date then RDF::Literal::Date when ::Time then RDF::Literal::Time # FIXME: Ruby's Time class can represent datetimes as well when ::Symbol then RDF::Literal::Token else self end end literal = klass.allocate literal.send(:initialize, value, ) literal.validate! if [:validate] literal.canonicalize! if [:canonicalize] literal end |
Instance Method Details
#==(other) ⇒ Boolean Also known as: ===
Returns ‘true` if this literal is equivalent to `other` (with type check).
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/rdf/model/literal.rb', line 286 def ==(other) case other when Literal case when self.eql?(other) true when self.has_language? && self.language.to_s == other.language.to_s # 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) # Comoparing 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.
407 408 409 |
# File 'lib/rdf/model/literal.rb', line 407 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
-
The first argument is a plain literal with language tag and the second argument is a simple literal or literal typed as xsd:string
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/rdf/model/literal.rb', line 222 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 has_language? ? (language == other.language || other.datatype == RDF::XSD.string) : other.datatype == RDF::XSD.string 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
386 387 388 389 390 391 392 393 394 395 396 397 398 |
# File 'lib/rdf/model/literal.rb', line 386 def comperable_datatype?(other) return false unless self.plain? || self.has_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.has_language? else # An unknown datatype may not be used for comparison, unless it has a language? (open-eq-8) self.has_language? end end |
#eql?(other) ⇒ Boolean
Determins if ‘self` is the same term as `other`.
266 267 268 269 270 271 272 273 |
# File 'lib/rdf/model/literal.rb', line 266 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.datatype.eql?(other.datatype)) end |
#escape(string) ⇒ String
N-Triples only requires ‘"nr’ to be escaped.
Escape a literal using ECHAR escapes.
ECHAR ::= '\' [tbnrf"'\]
421 422 423 424 425 426 427 428 429 430 |
# File 'lib/rdf/model/literal.rb', line 421 def escape(string) string.gsub('\\', '\\\\'). gsub("\t", '\\t'). gsub("\b", '\\b'). gsub("\n", '\\n'). gsub("\r", '\\r'). gsub("\f", '\\f'). gsub('"', '\\"'). freeze end |
#freeze ⇒ Object
252 253 254 255 256 |
# File 'lib/rdf/model/literal.rb', line 252 def freeze hash.freeze value_hash.freeze super end |
#has_datatype? ⇒ Boolean Also known as: datatype?, typed?, datatyped?
Returns ‘true` if this is a datatyped literal.
For historical reasons, this excludes xsd:string and rdf:langString
350 351 352 |
# File 'lib/rdf/model/literal.rb', line 350 def has_datatype? !plain? && !language? end |
#has_language? ⇒ Boolean Also known as: language?
Returns ‘true` if this is a language-tagged literal.
338 339 340 |
# File 'lib/rdf/model/literal.rb', line 338 def has_language? datatype == RDF.langString end |
#hash ⇒ Fixnum
Returns a hash code for this literal.
237 238 239 |
# File 'lib/rdf/model/literal.rb', line 237 def hash @hash ||= [to_s, datatype, language].hash end |
#humanize(lang = :en) ⇒ String
Returns a human-readable value for the literal
445 446 447 |
# File 'lib/rdf/model/literal.rb', line 445 def humanize(lang = :en) to_s.freeze end |
#inspect ⇒ String
Returns a developer-friendly representation of ‘self`.
453 454 455 |
# File 'lib/rdf/model/literal.rb', line 453 def inspect sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, RDF::NTriples.serialize(self)) end |
#literal? ⇒ Boolean
Returns ‘true`.
195 196 197 |
# File 'lib/rdf/model/literal.rb', line 195 def literal? true end |
#object ⇒ Object
187 188 189 |
# File 'lib/rdf/model/literal.rb', line 187 def object defined?(@object) ? @object : value end |
#plain? ⇒ Boolean
Returns ‘true` if this is a plain literal. A plain literal may have a language, but may not have a datatype. For all practical purposes, this includes xsd:string literals too.
319 320 321 |
# File 'lib/rdf/model/literal.rb', line 319 def plain? [RDF.langString, RDF::XSD.string].include?(datatype) end |
#simple? ⇒ Boolean
Returns ‘true` if this is a simple literal. A simple literal has no datatype or language.
329 330 331 |
# File 'lib/rdf/model/literal.rb', line 329 def simple? datatype == RDF::XSD.string end |
#to_s ⇒ String
Returns the value as a string.
436 437 438 |
# File 'lib/rdf/model/literal.rb', line 436 def to_s @object.to_s.freeze end |
#valid? ⇒ Boolean
Returns ‘true` if the value adheres to the defined grammar of the datatype.
363 364 365 366 |
# File 'lib/rdf/model/literal.rb', line 363 def valid? grammar = self.class.const_get(:GRAMMAR) rescue nil grammar.nil? || !!(value =~ grammar) end |
#validate! ⇒ RDF::Literal
Validates the value using Value#valid?, raising an error if the value is invalid.
375 376 377 378 |
# File 'lib/rdf/model/literal.rb', line 375 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.
181 182 183 |
# File 'lib/rdf/model/literal.rb', line 181 def value @string || to_s end |
#value_hash ⇒ Fixnum
Returns a hash code for the value.
246 247 248 |
# File 'lib/rdf/model/literal.rb', line 246 def value_hash @value_hash ||= value.hash end |