Class: RDF::Literal

Inherits:
Object show all
Includes:
N3::Terminals, Term
Defined in:
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/json-ld-85174af7539c/lib/json/ld/extensions.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/date.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/time.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/token.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/double.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/boolean.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/decimal.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/integer.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/numeric.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/datetime.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal/temporal.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-n3-a55d2ffecc58/lib/rdf/n3/extensions.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-spec-829d16a711d8/lib/rdf/spec/inspects.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-xsd-78bac0560463/lib/rdf/xsd/xml.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-xsd-78bac0560463/lib/rdf/xsd/date.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-xsd-78bac0560463/lib/rdf/xsd/binary.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-xsd-78bac0560463/lib/rdf/xsd/double.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-xsd-78bac0560463/lib/rdf/xsd/any_uri.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-xsd-78bac0560463/lib/rdf/xsd/integer.rb,
vendor/bundler/ruby/3.1.0/bundler/gems/rdf-xsd-78bac0560463/lib/rdf/xsd/duration.rb

Overview

override several inspect functions to improve output for what we're doing

Defined Under Namespace

Classes: AnyURI, Base64Binary, Boolean, Byte, Date, DateTime, DateTimeStamp, Day, DayTimeDuration, Decimal, Double, Duration, Float, HTML, HexBinary, Int, Integer, Long, Month, MonthDay, NegativeInteger, NonNegativeInteger, NonPositiveInteger, Numeric, PositiveInteger, Short, Temporal, Time, Token, UnsignedByte, UnsignedInt, UnsignedLong, UnsignedShort, XML, Year, YearMonth, YearMonthDuration

Constant Summary collapse

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

Constants included from N3::Terminals

N3::Terminals::ANON, N3::Terminals::BASE, N3::Terminals::BLANK_NODE_LABEL, N3::Terminals::DECIMAL, N3::Terminals::DOUBLE, N3::Terminals::ECHAR, N3::Terminals::ESCAPE_CHAR4, N3::Terminals::ESCAPE_CHAR8, N3::Terminals::EXPONENT, N3::Terminals::INTEGER, N3::Terminals::IPLSTART, N3::Terminals::IRIREF, N3::Terminals::IRI_RANGE, N3::Terminals::LANGTAG, N3::Terminals::PERCENT, N3::Terminals::PLX, N3::Terminals::PNAME_LN, N3::Terminals::PNAME_NS, N3::Terminals::PN_CHARS, N3::Terminals::PN_CHARS_BASE, N3::Terminals::PN_CHARS_BODY, N3::Terminals::PN_CHARS_U, N3::Terminals::PN_LOCAL, N3::Terminals::PN_LOCAL_BODY, N3::Terminals::PN_LOCAL_ESC, N3::Terminals::PN_PREFIX, N3::Terminals::PREFIX, N3::Terminals::QUICK_VAR_NAME, N3::Terminals::STRING_LITERAL_LONG_QUOTE, N3::Terminals::STRING_LITERAL_LONG_SINGLE_QUOTE, N3::Terminals::STRING_LITERAL_QUOTE, N3::Terminals::STRING_LITERAL_SINGLE_QUOTE, N3::Terminals::UCHAR, N3::Terminals::U_CHARS1, N3::Terminals::U_CHARS2, N3::Terminals::WS

Constants included from SPARQL::Algebra::Expression

SPARQL::Algebra::Expression::PATTERN_PARENTS

Constants included from Util::Logger

Util::Logger::IOWrapper

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Term

#aggregate?, #evaluate, #ndvars, #optimize, #sameTerm?, #term?, #terms, #to_base, #to_sparql, #to_term, #vars

Methods included from SPARQL::Algebra::Expression

cast, #constant?, #evaluate, extension, extension?, extensions, for, #invalid?, #node?, open, #optimize, #optimize!, parse, register_extension, #to_sxp_bin, #variable?

Methods included from Util::Logger

#log_debug, #log_depth, #log_error, #log_fatal, #log_info, #log_recover, #log_recovering?, #log_statistics, #log_warn, #logger

Methods included from Value

#anonymous?, #canonicalize, #constant?, #formula?, #graph?, #inspect!, #invalid?, #iri?, #list?, #node?, #resource?, #start_with?, #statement?, #term?, #to_ndvar, #to_nquads, #to_ntriples, #to_rdf, #to_term, #type_error, #uri?, #variable?

Constructor Details

#initialize(value, language: nil, datatype: nil, lexical: nil, validate: false, canonicalize: false, **options) ⇒ Literal

Literals without a datatype are given either xsd:string or rdf:langString depending on if there is language

Parameters:

  • value (Object)
  • language (Symbol) (defaults to: nil)

    (nil) Language is downcased to ensure proper matching

  • lexical (String) (defaults to: nil)

    (nil) Supplied lexical representation of this literal, otherwise it comes from transforming value to a string form..

  • datatype (URI) (defaults to: nil)

    (nil)

  • validate (Boolean) (defaults to: false)

    (false)

  • canonicalize (Boolean) (defaults to: false)

    (false)

Raises:

  • (ArgumentError)

    if there is a language and datatype is no rdf:langString or datatype is rdf:langString and there is no language

See Also:



166
167
168
169
170
171
172
173
174
175
176
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 166

def initialize(value, language: nil, datatype: nil, lexical: nil, validate: false, canonicalize: false, **options)
  @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
  @datatype = RDF::URI(datatype).freeze if datatype
  @datatype ||= self.class.const_get(:DATATYPE) if self.class.const_defined?(:DATATYPE)
  @datatype ||= instance_variable_defined?(:@language) && @language ? RDF.langString : RDF::URI("http://www.w3.org/2001/XMLSchema#string")
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#String (protected)

This method is implemented when the datatype is xsd:string or rdf:langString

Returns:



541
542
543
544
545
546
547
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 541

def method_missing(name, *args)
  case name
  when :to_str
    return to_s if @datatype == RDF.langString || @datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#string")
  end
  super
end

Instance Attribute Details

#datatypeURI

Returns The XML Schema datatype URI (optional).

Returns:

  • (URI)

    The XML Schema datatype URI (optional).



145
146
147
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 145

def datatype
  @datatype
end

#languageSymbol

Returns The language tag (optional).

Returns:

  • (Symbol)

    The language tag (optional).



142
143
144
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 142

def language
  @language
end

Instance Method Details

#<=>(other) ⇒ Integer

Compares self to other for sorting purposes (with type check).

Parameters:

Returns:



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 317

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).

Examples:

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

Parameters:

Returns:

See Also:



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 287

def ==(other)
  case other
  when Literal
    case
    when self.eql?(other)
      true
    when self.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)
      # 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

#as_datetimeRDF::Literal::DateTime

Parse the value as a dateTime literal, or return now.



105
106
107
108
109
110
111
112
113
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-n3-a55d2ffecc58/lib/rdf/n3/extensions.rb', line 105

def as_datetime
  return self if is_a?(RDF::Literal::DateTime)
  mvalue = value
  mvalue = "#{mvalue}-01" if mvalue.match?(%r(^\d{4}$))
  mvalue = "#{mvalue}-01" if mvalue.match?(%r(^\d{4}-\d{2}$))
  RDF::Literal::DateTime.new(::DateTime.iso8601(mvalue), lexical: value)
rescue
  RDF::Literal(0)
end

#as_numberRDF::Literal::Numeric

Parse the value as a numeric literal, or return 0.



90
91
92
93
94
95
96
97
98
99
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-n3-a55d2ffecc58/lib/rdf/n3/extensions.rb', line 90

def as_number
  return self if self.is_a?(RDF::Literal::Numeric)
  case value
  when DOUBLE  then RDF::Literal::Double.new(value)
  when DECIMAL then RDF::Literal::Decimal.new(value)
  when INTEGER then RDF::Literal::Integer.new(value)
  else
    RDF::Literal(0)
  end
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



461
462
463
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 461

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

Examples:

compatible?("abc"	"b")                         #=> true
compatible?("abc"	"b"^^xsd:string)             #=> true
compatible?("abc"^^xsd:string	"b")             #=> true
compatible?("abc"^^xsd:string	"b"^^xsd:string) #=> true
compatible?("abc"@en	"b")                     #=> true
compatible?("abc"@en	"b"^^xsd:string)         #=> true
compatible?("abc"@en	"b"@en)                  #=> true
compatible?("abc"@fr	"b"@ja)                  #=> false
compatible?("abc"	"b"@ja)                      #=> false
compatible?("abc"	"b"@en)                      #=> false
compatible?("abc"^^xsd:string	"b"@en)          #=> false

Returns:

See Also:

Since:

  • 2.0



223
224
225
226
227
228
229
230
231
232
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 223

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? ?
    (language == other.language || other.datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#string")) :
    other.datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#string")
end

#comperable_datatype2?(other) ⇒ Boolean

Returns true if the literals are comperable.

Used for <=> operator.

Returns:



440
441
442
443
444
445
446
447
448
449
450
451
452
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 440

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

Returns:



420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 420

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

Returns:

See Also:



382
383
384
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 382

def datatype?
  !plain? && !language?
end

#eql?(other) ⇒ Boolean

Determins if self is the same term as other.

Examples:

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

Parameters:

Returns:



267
268
269
270
271
272
273
274
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 267

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

Note:

N-Triples only requires '\"\n\r' to be escaped.

Escape a literal using ECHAR escapes.

ECHAR ::= '\' [tbnrf"']

Parameters:

Returns:

See Also:



499
500
501
502
503
504
505
506
507
508
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 499

def escape(string)
  string.gsub('\\', '\\\\').
         gsub("\t", '\\t').
         gsub("\b", '\\b').
         gsub("\n", '\\n').
         gsub("\r", '\\r').
         gsub("\f", '\\f').
         gsub('"', '\\"').
         freeze
end

#hashInteger

Returns a hash code for this literal.

Returns:



238
239
240
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 238

def hash
  @hash ||= [to_s, datatype, language].hash
end

#humanize(lang = :en) ⇒ String

Returns a human-readable value for the literal

Returns:

Since:

  • 1.1.6



523
524
525
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 523

def humanize(lang = :en)
  to_s.freeze
end

#inspectString

Returns a developer-friendly representation of self.

Returns:



531
532
533
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 531

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 literal.

Returns:

See Also:



370
371
372
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 370

def language?
  datatype == RDF.langString
end

#literal?Boolean

Returns true.

Returns:



196
197
198
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 196

def literal?
  true
end

#objectObject

Returns:



188
189
190
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 188

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.

Returns:

See Also:



351
352
353
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 351

def plain?
  [RDF.langString, RDF::URI("http://www.w3.org/2001/XMLSchema#string")].include?(datatype)
end

#respond_to_missing?(name, include_private = false) ⇒ Boolean (protected)

Returns:



549
550
551
552
553
554
555
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 549

def respond_to_missing?(name, include_private = false)
  case name
  when :to_str
    return true if @datatype == RDF.langString || @datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#string")
  end
  super
end

#simple?Boolean

Returns true if this is a simple literal. A simple literal has no datatype or language.

Returns:

See Also:



361
362
363
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 361

def simple?
  datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#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.

Returns:

See Also:



472
473
474
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 472

def squish(*other_string)
  self.dup.squish!
end

#squish!Object

Performs a destructive #squish.



481
482
483
484
485
486
487
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 481

def squish!
  @string = value.
    gsub(/\A[[:space:]]+/, '').
    gsub(/[[:space:]]+\z/, '').
    gsub(/[[:space:]]+/, ' ')
  self
end

#to_sString

Returns the value as a string.

Returns:



514
515
516
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 514

def to_s
  @object.to_s.freeze
end

#valid?Boolean

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

Returns:

Since:

  • 0.2.1



395
396
397
398
399
400
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 395

def valid?
  return false if language? && language.to_s !~ /^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$/
  return false if datatype? && datatype.invalid?
  grammar = self.class.const_get(:GRAMMAR) rescue nil
  grammar.nil? || value.match?(grammar)
end

#valid_extended?Boolean

Validate extended RDF

Returns:



37
38
39
40
41
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/json-ld-85174af7539c/lib/json/ld/extensions.rb', line 37

def valid_extended?
  return false if language? && language.to_s !~ /^[a-zA-Z]+(-[a-zA-Z0-9]+)*$/
  return false if datatype? && datatype.invalid?
  value.is_a?(String)
end

#validate!RDF::Literal

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

Returns:

Raises:

  • (ArgumentError)

    if the value is invalid

Since:

  • 0.2.1



409
410
411
412
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 409

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:



182
183
184
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 182

def value
  instance_variable_defined?(:@string) && @string || to_s
end

#value_hashInteger

Returns a hash code for the value.

Returns:



247
248
249
# File 'vendor/bundler/ruby/3.1.0/bundler/gems/rdf-4f45c0ed29ed/lib/rdf/model/literal.rb', line 247

def value_hash
  @value_hash ||= value.hash
end