Class: RDF::Literal

Inherits:
Object
  • Object
show all
Includes:
Term
Defined in:
lib/rdf/model/literal.rb,
lib/rdf/model/literal/xml.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.

Examples:

Creating a plain literal

value = RDF::Literal.new("Hello, world!")
value.plain?                                   #=> true`

Creating a language-tagged literal (1)

value = RDF::Literal.new("Hello!", :language => :en)
value.has_language?                            #=> true
value.language                                 #=> :en

Creating a language-tagged literal (2)

RDF::Literal.new("Wazup?", :language => :"en-US")
RDF::Literal.new("Hej!",   :language => :sv)
RDF::Literal.new("¡Hola!", :language => :es)

Creating an explicitly datatyped literal

value = RDF::Literal.new("2009-12-31", :datatype => RDF::XSD.date)
value.has_datatype?                            #=> true
value.datatype                                 #=> RDF::XSD.date

Creating an implicitly datatyped literal

value = RDF::Literal.new(Date.today)
value.has_datatype?                            #=> true
value.datatype                                 #=> RDF::XSD.date

Creating implicitly datatyped literals

RDF::Literal.new(false).datatype               #=> XSD.boolean
RDF::Literal.new(true).datatype                #=> XSD.boolean
RDF::Literal.new(123).datatype                 #=> XSD.integer
RDF::Literal.new(9223372036854775807).datatype #=> XSD.integer
RDF::Literal.new(3.1415).datatype              #=> XSD.double
RDF::Literal.new(Time.now).datatype            #=> XSD.dateTime
RDF::Literal.new(Date.new(2010)).datatype      #=> XSD.date
RDF::Literal.new(DateTime.new(2010)).datatype  #=> XSD.dateTime

See Also:

Direct Known Subclasses

Boolean, Date, DateTime, Numeric, Time, Token, XML

Defined Under Namespace

Classes: Boolean, Date, DateTime, Decimal, Double, Integer, Numeric, Time, Token, XML

Constant Summary collapse

TRUE =
RDF::Literal.new(true).freeze
FALSE =
RDF::Literal.new(false).freeze
ZERO =
RDF::Literal.new(0).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Term

#<=>, #constant?, #variable?

Methods included from Value

#graph?, #inspect!, #iri?, #node?, #resource?, #statement?, #to_ntriples, #to_quad, #to_rdf, #type_error, #uri?, #variable?

Constructor Details

#initialize(value, options = {}) ⇒ Literal

Returns a new instance of Literal.

Parameters:

  • value (Object)
  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :language (Symbol) — default: nil
  • :datatype (URI) — default: nil


139
140
141
142
143
144
145
146
# File 'lib/rdf/model/literal.rb', line 139

def initialize(value, options = {})
  @object   = value
  @string   = options[:lexical] if options[:lexical]
  @string   = value if !defined?(@string) && value.is_a?(String)
  @language = options[:language].to_s.to_sym if options[:language]
  @datatype = RDF::URI(options[:datatype]) if options[:datatype]
  @datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE)
end

Instance Attribute Details

#datatypeURI

Returns The XML Schema datatype URI (optional).

Returns:

  • (URI)

    The XML Schema datatype URI (optional).



133
134
135
# File 'lib/rdf/model/literal.rb', line 133

def datatype
  @datatype
end

#languageSymbol

Returns The language tag (optional).

Returns:

  • (Symbol)

    The language tag (optional).



130
131
132
# File 'lib/rdf/model/literal.rb', line 130

def language
  @language
end

Class Method Details

.datatyped_class(uri) ⇒ Object

Return datatype class for uri, or nil if none is found



93
94
95
# File 'lib/rdf/model/literal.rb', line 93

def self.datatyped_class(uri)
  @@subclasses.detect {|klass| klass.const_defined?(:DATATYPE) && klass.const_get(:DATATYPE) == uri}
end

.new(value, options = {}) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rdf/model/literal.rb', line 99

def self.new(value, options = {})
  klass = case
    when !self.equal?(RDF::Literal)
      self # subclasses can be directly constructed without type dispatch
    when typed_literal = datatyped_class(RDF::URI(options[:datatype]))
      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, options)
  literal.validate!     if options[:validate]
  literal.canonicalize! if options[:canonicalize]
  literal
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: ===

Returns ‘true` if this literal is equivalent to `other` (with type check).

Examples:

RDF::Literal(1) == RDF::Literal(1.0)     #=> true

Parameters:

  • other (Object)

Returns:

  • (Boolean)

    ‘true` or `false`

See Also:



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/rdf/model/literal.rb', line 213

def ==(other)
  case other
  when Literal
    case
    when self.eql?(other)
      true
    when self.has_language? && self.language.to_s.downcase == other.language.to_s.downcase
      # Literals with languages can compare if languages are identical
      self.value == other.value
    when (self.simple? || self.datatype == XSD.string) && (other.simple? || other.datatype == XSD.string)
      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.plain? && self.value.eql?(other)
  else false
  end
end

#anonymous?Boolean

Returns ‘false`.

Returns:

  • (Boolean)

    ‘true` or `false`



174
175
176
# File 'lib/rdf/model/literal.rb', line 174

def anonymous?
  false
end

#canonicalizeRDF::Literal

Returns a copy of this literal converted into its canonical lexical representation.

Subclasses should override ‘#canonicalize!` as needed and appropriate, not this method.

Returns:

Since:

  • 0.2.1



341
342
343
# File 'lib/rdf/model/literal.rb', line 341

def canonicalize
  self.dup.canonicalize!
end

#canonicalize!RDF::Literal

Converts this literal into its canonical lexical representation.

Subclasses should override this as needed and appropriate.

Returns:

Since:

  • 0.3.0



352
353
354
355
# File 'lib/rdf/model/literal.rb', line 352

def canonicalize!
  @language = @language.to_s.downcase.to_sym if @language
  self
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

Returns:



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/rdf/model/literal.rb', line 297

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
    case other.datatype
    when XSD.string
      true
    when nil
      # A different language will not generate a type error
      other.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
end

#eql?(other) ⇒ Boolean

Determins if ‘self` is the same term as `other`.

Examples:

RDF::Literal(1).eql?(RDF::Literal(1.0))  #=> false

Parameters:

  • other (Object)

Returns:

  • (Boolean)

    ‘true` or `false`



194
195
196
197
198
199
200
# File 'lib/rdf/model/literal.rb', line 194

def eql?(other)
  self.equal?(other) ||
    (self.class.eql?(other.class) &&
     self.value.eql?(other.value) &&
     self.language.to_s.downcase.eql?(other.language.to_s.downcase) &&
     self.datatype.eql?(other.datatype))
end

#has_datatype?Boolean Also known as: datatype?, typed?, datatyped?

Returns ‘true` if this is a datatyped literal.

Returns:

  • (Boolean)

    ‘true` or `false`

See Also:



263
264
265
# File 'lib/rdf/model/literal.rb', line 263

def has_datatype?
  !datatype.nil?
end

#has_language?Boolean Also known as: language?

Returns ‘true` if this is a language-tagged literal.

Returns:

  • (Boolean)

    ‘true` or `false`

See Also:



253
254
255
# File 'lib/rdf/model/literal.rb', line 253

def has_language?
  !language.nil?
end

#hashFixnum

Returns a hash code for this literal.

Returns:

  • (Fixnum)


182
183
184
# File 'lib/rdf/model/literal.rb', line 182

def hash
  to_s.hash
end

#inspectString

Returns a developer-friendly representation of ‘self`.

Returns:

  • (String)


369
370
371
# File 'lib/rdf/model/literal.rb', line 369

def inspect
  sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, RDF::NTriples.serialize(self))
end

#invalid?Boolean

Returns ‘true` if the value does not adhere to the defined grammar of the datatype.

Returns:

  • (Boolean)

    ‘true` or `false`

Since:

  • 0.2.1



287
288
289
# File 'lib/rdf/model/literal.rb', line 287

def invalid?
  !valid?
end

#literal?Boolean

Returns ‘true`.

Returns:

  • (Boolean)

    ‘true` or `false`



166
167
168
# File 'lib/rdf/model/literal.rb', line 166

def literal?
  true
end

#objectObject

Returns:

  • (Object)


158
159
160
# File 'lib/rdf/model/literal.rb', line 158

def object
  defined?(@object) ? @object : value
end

#plain?Boolean Also known as: simple?

Returns ‘true` if this is a plain literal.

Returns:

  • (Boolean)

    ‘true` or `false`

See Also:



243
244
245
# File 'lib/rdf/model/literal.rb', line 243

def plain?
  language.nil? && datatype.nil?
end

#to_sString

Returns the value as a string.

Returns:

  • (String)


361
362
363
# File 'lib/rdf/model/literal.rb', line 361

def to_s
  @object.to_s
end

#valid?Boolean

Returns ‘true` if the value adheres to the defined grammar of the datatype.

Returns:

  • (Boolean)

    ‘true` or `false`

Since:

  • 0.2.1



276
277
278
279
# File 'lib/rdf/model/literal.rb', line 276

def valid?
  grammar = self.class.const_get(:GRAMMAR) rescue nil
  grammar.nil? || !!(value =~ grammar)
end

#validate!RDF::Literal Also known as: validate

Validates the value using #valid?, raising an error if the value is invalid.

Returns:

Raises:

  • (ArgumentError)

    if the value is invalid

Since:

  • 0.2.1



326
327
328
329
# File 'lib/rdf/model/literal.rb', line 326

def validate!
  raise ArgumentError, "#{to_s.inspect} is not a valid <#{datatype.to_s}> literal" if invalid?
  self
end

#valueString

Returns the value as a string.

Returns:

  • (String)


152
153
154
# File 'lib/rdf/model/literal.rb', line 152

def value
  @string || to_s
end