rdf_context 0.5.9.1 → 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.gitignore +0 -1
  2. data/History.rdoc +23 -2
  3. data/Rakefile +17 -17
  4. data/VERSION +1 -1
  5. data/bin/rdf_context +1 -4
  6. data/lib/rdf_context.rb +55 -19
  7. data/lib/rdf_context/aggregate_graph.rb +0 -2
  8. data/lib/rdf_context/bnode.rb +14 -1
  9. data/lib/rdf_context/conjunctive_graph.rb +0 -2
  10. data/lib/rdf_context/graph.rb +9 -10
  11. data/lib/rdf_context/literal.rb +39 -56
  12. data/lib/rdf_context/n3_grammar.treetop +2 -2
  13. data/lib/rdf_context/n3parser.rb +7 -5
  14. data/lib/rdf_context/parser.rb +2 -3
  15. data/lib/rdf_context/quoted_graph.rb +0 -2
  16. data/lib/rdf_context/rdfaparser.rb +93 -68
  17. data/lib/rdf_context/rdfxmlparser.rb +1 -1
  18. data/lib/rdf_context/resource.rb +56 -0
  19. data/lib/rdf_context/serializer/abstract_serializer.rb +0 -2
  20. data/lib/rdf_context/serializer/nt_serializer.rb +0 -2
  21. data/lib/rdf_context/serializer/recursive_serializer.rb +0 -4
  22. data/lib/rdf_context/serializer/turtle_serializer.rb +0 -2
  23. data/lib/rdf_context/serializer/xml_serializer.rb +0 -2
  24. data/lib/rdf_context/store/abstract_sql_store.rb +3 -1
  25. data/lib/rdf_context/store/active_record_store.rb +272 -0
  26. data/lib/rdf_context/store/list_store.rb +2 -2
  27. data/lib/rdf_context/store/memory_store.rb +2 -2
  28. data/lib/rdf_context/store/sqlite3_store.rb +112 -48
  29. data/lib/rdf_context/term_utils.rb +0 -4
  30. data/lib/rdf_context/triple.rb +1 -3
  31. data/lib/rdf_context/uriref.rb +14 -1
  32. data/rdf_context.gemspec +872 -0
  33. data/script/tc +4 -4
  34. data/spec/active_record_store_spec.rb +61 -0
  35. data/spec/aggregate_graph_spec.rb +1 -1
  36. data/spec/bnode_spec.rb +37 -1
  37. data/spec/conjunctive_graph_spec.rb +1 -1
  38. data/spec/cwm_spec.rb +5 -5
  39. data/spec/duration_spec.rb +1 -1
  40. data/spec/graph_spec.rb +16 -2
  41. data/spec/list_store_spec.rb +1 -1
  42. data/spec/literal_spec.rb +47 -14
  43. data/spec/memory_store_spec.rb +1 -1
  44. data/spec/n3parser_spec.rb +19 -5
  45. data/spec/namespaces_spec.rb +1 -1
  46. data/spec/parser_spec.rb +1 -1
  47. data/spec/rdf_helper.rb +18 -15
  48. data/spec/rdfa_helper.rb +27 -14
  49. data/spec/rdfa_parser_spec.rb +28 -9
  50. data/spec/rdfxml_spec.rb +3 -3
  51. data/spec/spec_helper.rb +10 -5
  52. data/spec/sqlite3_store_spec.rb +1 -1
  53. data/spec/string_hacks_spec.rb +2 -1
  54. data/spec/swap_spec.rb +7 -7
  55. data/spec/swap_test/ref/contexts-1.n3 +12 -0
  56. data/spec/swap_test/ref/prefix2.rdf +33 -0
  57. data/spec/swap_test/ref/xmllit.nt +1 -1
  58. data/spec/swap_test/regression.n3 +18 -18
  59. data/spec/triple_spec.rb +1 -1
  60. data/spec/turtle_serializer_spec.rb +3 -3
  61. data/spec/turtle_spec.rb +3 -3
  62. data/spec/uriref_spec.rb +31 -1
  63. metadata +13 -15
data/.gitignore CHANGED
@@ -7,4 +7,3 @@ rdoc/*
7
7
  pkg/*
8
8
  rena_new_spec.html
9
9
  rena-*.gem
10
- /*.gemspec
@@ -1,3 +1,24 @@
1
+ === 0.5.10
2
+ * N3 Parser
3
+ * Allow mixed case literal languages.
4
+ * Unescape literals
5
+ * Rspec 2.1.0
6
+ * Added Resource class, a common super-class of BNode, Graph, Literal and URIRef.
7
+ * Implemented Resource.parse and variations for sub-classes to parse N3-coded resources.
8
+ * Literal#typed
9
+ * Namespaces option now is {prefix => href} rather than {prefix => Namespace}.
10
+ * Add all in-scope namespaces, not just those that seem to be used.
11
+ * RDFa Parser
12
+ * Upgrade for changes to RDFa 1.1 test suite
13
+ * For non-XHTML, allow use of xml:base for non-HTML languages
14
+ * XHTML has no default vocabulary.
15
+ * No longer pass vocabularies, prefixes or terms when creating XMLLiterals. Only namespaces derived via xmlns are passed to Literal#typed.
16
+ * SQLite3Store
17
+ * Basic support for using with ActiveRecord: #initialize _configuration_ can take a _connection_ option, using ActiveRecord::Base.connection.raw_connection
18
+ * If result set is returned as a hash, change back to an array (needed, as rails sets results_as_hash attribute on DB)
19
+ * Added ActiveRecordStore
20
+ * Uses ActiveRecord connection to store graph information, not an ActiveRecord::Base model
21
+
1
22
  === 0.5.9.1
2
23
  * Fix minor graph property caching bug relating to manipulation of sequences.
3
24
 
@@ -10,7 +31,7 @@
10
31
  === 0.5.8.2
11
32
  * Don't create unnecessary namespaces when serializing RDF/XML.
12
33
  * Don't use regexp to substitute base URI in URI serialization.
13
- * Added :profile_graph option to RdfaParser#parse. This MUST be a ConjunctiveGraph and will be used to save profiles that are encountered.
34
+ * Added profile_graph option to RdfaParser#parse. This MUST be a ConjunctiveGraph and will be used to save profiles that are encountered.
14
35
  * Fixme, for now, retrieval should include HTTP headers and perform appropriate HTTP cache control and check for potential updates.
15
36
  * Added ConjunctiveGraph#add_quad. Adds a quad from the intended subject, predicate, object, and context.
16
37
  @example
@@ -137,7 +158,7 @@
137
158
  * Add Graph#contents as alias to store
138
159
  * Add ConjunctiveGraph#triples to return all triples from store, not just default context
139
160
  * Add Graph#nsbinding to retreive Store#nsbinding
140
- * Fix numerious SQLite3Store and AbstractSQLStore bugs. Add round-trip tests to Graph spec.
161
+ * Fix numerous SQLite3Store and AbstractSQLStore bugs. Add round-trip tests to Graph spec.
141
162
 
142
163
  === 0.4.4
143
164
  * Namespace usage cleanup
data/Rakefile CHANGED
@@ -26,7 +26,7 @@ begin
26
26
  gemspec.add_dependency('treetop', '>= 1.4.0')
27
27
  gemspec.add_dependency('nokogiri', '>= 1.4.3')
28
28
  gemspec.add_dependency('builder', '>= 2.1.2')
29
- gemspec.add_development_dependency('rspec')
29
+ gemspec.add_development_dependency('rspec', '>= 2.1.0')
30
30
  gemspec.add_development_dependency('activesupport', '>= 2.3.0')
31
31
  gemspec.add_development_dependency('yard')
32
32
  gemspec.extra_rdoc_files = %w(README.rdoc History.txt)
@@ -45,30 +45,29 @@ task :push do
45
45
  sh "growlnotify -m \"Updates pushed\" \"Git\""
46
46
  end
47
47
 
48
- require 'spec/rake/spectask'
49
- Spec::Rake::SpecTask.new(:spec) do |spec|
50
- spec.libs << 'lib' << 'spec'
51
- spec.spec_files = FileList['spec/*_spec.rb']
52
- end
48
+ require 'rspec/core/rake_task'
49
+ RSpec::Core::RakeTask.new(:spec)
53
50
 
54
51
  desc "Run specs through RCov"
55
- Spec::Rake::SpecTask.new("spec:rcov") do |spec|
56
- spec.libs << 'lib' << 'spec'
57
- spec.pattern = 'spec/*_spec.rb'
52
+ RSpec::Core::RakeTask.new("spec:rcov") do |spec|
58
53
  spec.rcov = true
54
+ spec.rcov_opts = %q[--exclude "spec"]
59
55
  end
60
56
 
61
57
  desc "Generate HTML report specs"
62
- Spec::Rake::SpecTask.new("doc:spec") do |spec|
63
- spec.libs << 'lib' << 'spec'
64
- spec.spec_files = FileList['spec/*_spec.rb']
65
- spec.spec_opts = ["--format", "html:doc/spec.html"]
58
+ RSpec::Core::RakeTask.new("spec") do |spec|
59
+ spec.rspec_opts = ["--format", "html:doc/spec.html"]
66
60
  end
67
61
 
68
62
  task :spec => :check_dependencies
69
63
 
70
64
  task :default => :spec
71
65
 
66
+ desc "Update N3 grammar"
67
+ task :grammar do
68
+ sh "tt -o lib/rdf_context/n3_grammar.rb lib/rdf_context/n3_grammar.treetop"
69
+ end
70
+
72
71
  namespace :doc do
73
72
  require 'rake/rdoctask'
74
73
  Rake::RDocTask.new("rdoc") do |rdoc|
@@ -93,12 +92,13 @@ desc "Generate RDF Core Manifest.yml"
93
92
  namespace :spec do
94
93
  task :prepare do
95
94
  $:.unshift(File.join(File.dirname(__FILE__), 'lib'))
95
+ $:.unshift(File.join(File.dirname(__FILE__), 'spec'))
96
96
  require 'rdf_context'
97
- require 'spec/rdfa_helper'
98
- require 'spec/rdf_helper'
97
+ require 'rdfa_helper'
98
+ require 'rdf_helper'
99
99
  require 'fileutils'
100
100
 
101
- %w(xhtml xhtml11 html4 html5).each do |suite|
101
+ %w(xhtml html4 html5 svgtiny).each do |suite|
102
102
  yaml = manifest_file = File.join(File.dirname(__FILE__), "spec", "#{suite}-manifest.yml")
103
103
  FileUtils.rm_f(yaml)
104
104
  RdfaHelper::TestCase.to_yaml(suite, yaml)
@@ -122,7 +122,7 @@ namespace :spec do
122
122
 
123
123
  yaml = File.join(TURTLE_DIR, "manifest-bad.yml")
124
124
  FileUtils.rm_f(yaml)
125
- RdfHelper::TestCase.to_yaml(TURTLE_TEST, TURTLE_DIR, yaml)
125
+ RdfHelper::TestCase.to_yaml(TURTLE_BAD_TEST, TURTLE_DIR, yaml)
126
126
  end
127
127
  end
128
128
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.9.1
1
+ 0.5.10
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby -s
1
+ #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
  require File.expand_path(File.dirname(__FILE__) + "/../lib/rdf_context")
4
4
  require 'getoptlong'
@@ -28,9 +28,6 @@ class Parse
28
28
  end
29
29
  end
30
30
 
31
- mode = ARGV.shift
32
- raise "Mode must be one of 'parse'" unless mode == "parse"
33
-
34
31
  $verbose = false
35
32
  $quiet = false
36
33
  $format = "ttl"
@@ -16,27 +16,59 @@ rescue LoadError
16
16
  require 'treetop'
17
17
  end
18
18
 
19
- Dir.glob(File.join(File.dirname(__FILE__), 'rdf_context/*.rb')).sort.each { |f| require f }
20
-
21
- # Include Storage types, but be tollerant of failure to load as dependencies might not be available
22
- Dir.glob(File.join(File.dirname(__FILE__), "rdf_context/store/*.rb")).each do |f|
23
- begin
24
- require f
25
- rescue LoadError
26
- puts "Error loading #{f}: #{$!}"
27
- end
28
- end
29
-
30
- # Include Serializer types, but be tollerant of failure to load as dependencies might not be available
31
- Dir.glob(File.join(File.dirname(__FILE__), "rdf_context/serializer/*.rb")).each do |f|
32
- begin
33
- require f
34
- rescue LoadError
35
- puts "Error loading #{f}: #{$!}"
36
- end
37
- end
19
+ require 'rdf_context/array_hacks'
20
+ require 'rdf_context/string_hacks'
38
21
 
39
22
  module RdfContext
23
+ # Primary model classes
24
+ autoload :BNode, "rdf_context/bnode"
25
+ autoload :Duration, "rdf_context/duration"
26
+ autoload :Literal, "rdf_context/literal"
27
+ autoload :Namespace, "rdf_context/namespace"
28
+ autoload :Resource, "rdf_context/resource"
29
+ autoload :Triple, "rdf_context/triple"
30
+ autoload :URIRef, "rdf_context/uriref"
31
+ autoload :TermUtils, "rdf_context/term_utils"
32
+
33
+ # Graphs
34
+ autoload :Graph, "rdf_context/graph"
35
+ autoload :ConjunctiveGraph, "rdf_context/conjunctive_graph"
36
+ autoload :AggregateGraph, "rdf_context/aggregate_graph"
37
+ autoload :QuotedGraph, "rdf_context/quoted_graph"
38
+
39
+ # Stores
40
+ autoload :AbstractStore, "rdf_context/store/abstract_store"
41
+ autoload :AbstractSQLStore, "rdf_context/store/abstract_sql_store"
42
+ autoload :ActiveRecordStore, "rdf_context/store/active_record_store"
43
+ autoload :ListStore, "rdf_context/store/list_store"
44
+ autoload :MemoryStore, "rdf_context/store/memory_store"
45
+ autoload :SQLite3Store, "rdf_context/store/sqlite3_store"
46
+
47
+ # Parsers
48
+ autoload :Parser, "rdf_context/parser"
49
+ autoload :N3Parser, "rdf_context/n3parser"
50
+ autoload :RdfaParser, "rdf_context/rdfaparser"
51
+ autoload :RdfXmlParser, "rdf_context/rdfxmlparser"
52
+
53
+ # Serializers
54
+ autoload :AbstractSerializer, "rdf_context/serializer/abstract_serializer"
55
+ autoload :NTSerializer, "rdf_context/serializer/nt_serializer"
56
+ autoload :RecursiveSerializer, "rdf_context/serializer/recursive_serializer"
57
+ autoload :TurtleSerializer, "rdf_context/serializer/turtle_serializer"
58
+ autoload :XmlSerializer, "rdf_context/serializer/xml_serializer"
59
+
60
+ # Exceptions
61
+ autoload :BNodeException, "rdf_context/exceptions"
62
+ autoload :GraphException, "rdf_context/exceptions"
63
+ autoload :InvalidNode, "rdf_context/exceptions"
64
+ autoload :InvalidPredicate, "rdf_context/exceptions"
65
+ autoload :ParserException, "rdf_context/exceptions"
66
+ autoload :RdfException, "rdf_context/exceptions"
67
+ autoload :ReadOnlyGraphException, "rdf_context/exceptions"
68
+ autoload :SparqlException, "rdf_context/exceptions"
69
+ autoload :StoreException, "rdf_context/exceptions"
70
+ autoload :TypeError, "rdf_context/exceptions"
71
+
40
72
  VERSION = File.read(File.join(File.dirname(__FILE__), "..", "VERSION")).chop # Version in parent directory
41
73
 
42
74
  LINK_TYPES = %w(
@@ -58,6 +90,10 @@ module RdfContext
58
90
  $},
59
91
  Regexp::EXTENDED)
60
92
 
93
+ LITERAL_PLAIN = /^"((?:\\"|[^"])*)"/.freeze
94
+ LITERAL_WITH_LANGUAGE = /^"((?:\\"|[^"])*)"@([a-z]+[\-A-Za-z0-9]*)/.freeze
95
+ LITERAL_WITH_DATATYPE = /^"((?:\\"|[^"])*)"\^\^<([^>]+)>/.freeze
96
+
61
97
  RDF_TYPE = URIRef.new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
62
98
  XML_LITERAL = Literal::Encoding.xmlliteral
63
99
 
@@ -1,5 +1,3 @@
1
- require File.join(File.dirname(__FILE__), "graph")
2
-
3
1
  module RdfContext
4
2
  # AggregateGraph - A read-only graph composed of multiple other graphs.
5
3
  #
@@ -1,6 +1,6 @@
1
1
  module RdfContext
2
2
  # The BNode class creates RDF blank nodes.
3
- class BNode
3
+ class BNode < Resource
4
4
  attr_accessor :identifier
5
5
 
6
6
  # Create a new BNode, optionally accept a identifier for the BNode.
@@ -27,6 +27,19 @@ module RdfContext
27
27
  end
28
28
  end
29
29
 
30
+ # Parse a BNode
31
+ def self.parse(str)
32
+ BNode.new($1) if str =~ /^_:(.*)$/
33
+ end
34
+
35
+ ##
36
+ # Returns `true`
37
+ #
38
+ # @return [Boolean]
39
+ def bnode?
40
+ true
41
+ end
42
+
30
43
  # Return BNode identifier
31
44
  def to_s
32
45
  return self.identifier.to_s
@@ -1,5 +1,3 @@
1
- require File.join(File.dirname(__FILE__), "graph")
2
-
3
1
  module RdfContext
4
2
  # ConjunctiveGraph - The top level container for all named Graphs sharing a _Store_
5
3
  #
@@ -1,17 +1,8 @@
1
- require File.join(File.dirname(__FILE__), 'namespace')
2
- require File.join(File.dirname(__FILE__), 'triple')
3
- require File.join(File.dirname(__FILE__), 'array_hacks')
4
- require File.join(File.dirname(__FILE__), 'store', 'list_store')
5
- require File.join(File.dirname(__FILE__), 'store', 'memory_store')
6
- require File.join(File.dirname(__FILE__), 'serializer', 'nt_serializer')
7
- require File.join(File.dirname(__FILE__), 'serializer', 'turtle_serializer')
8
- require File.join(File.dirname(__FILE__), 'serializer', 'xml_serializer')
9
-
10
1
  module RdfContext
11
2
  # A simple graph to hold triples.
12
3
  #
13
4
  # Graphs store triples, and the namespaces associated with those triples, where defined
14
- class Graph
5
+ class Graph < Resource
15
6
  attr_reader :triples
16
7
  attr_reader :identifier
17
8
  attr_reader :store
@@ -48,6 +39,14 @@ module RdfContext
48
39
  @identifier = Triple.coerce_node(options[:identifier]) || BNode.new
49
40
  end
50
41
 
42
+ ##
43
+ # Returns `false`, overridden in BNode
44
+ #
45
+ # @return [Boolean]
46
+ def graph?
47
+ true
48
+ end
49
+
51
50
  def inspect
52
51
  "#{self.class}[id=#{identifier},store=#{store.inspect}]"
53
52
  end
@@ -4,11 +4,12 @@ begin
4
4
  rescue LoadError
5
5
  end
6
6
 
7
- require File.join(File.dirname(__FILE__), 'duration')
7
+ require 'date'
8
+ require 'time'
8
9
 
9
10
  module RdfContext
10
11
  # An RDF Literal, with value, encoding and language elements.
11
- class Literal
12
+ class Literal < Resource
12
13
  class Encoding
13
14
  attr_reader :value
14
15
 
@@ -244,14 +245,15 @@ module RdfContext
244
245
  # @param [Object] contents
245
246
  # @option options [Hash] :namespaces ({}) Use :__default__ or "" to declare default namespace
246
247
  # @option options [String] :language (nil)
247
- # @option options [Array<URIRef>] :profiles ([]) Profiles to add to elements
248
- # @option options [Hash] :prefixes (nil) Prefixes to add to elements
249
- # @option options [String] :default_vocabulary (nil) Default vocabulary to add to elements
250
248
  def encode_contents(contents, options)
251
249
  #puts "encode_contents: '#{contents}'"
250
+ ns_hash = {}
251
+ (options[:namespaces] || {}).each_pair do |pfx, href|
252
+ href = href.uri.to_s if href.is_a?(Namespace)
253
+ ns_hash[pfx.to_s.empty? ? "xmlns" : "xmlns:#{pfx}"] = href.to_s
254
+ end
252
255
 
253
256
  if contents.is_a?(String)
254
- ns_hash = options[:namespaces].values.inject({}) {|h, ns| h.merge(ns.xmlns_hash)}
255
257
  ns_strs = []
256
258
  ns_hash.each_pair {|a, u| ns_strs << "#{a}=\"#{u}\""}
257
259
 
@@ -265,59 +267,20 @@ module RdfContext
265
267
  c = Nokogiri::XML.parse(c.copy(true).to_s) if c.is_a?(LibXML::XML::Node)
266
268
  end
267
269
  if c.is_a?(Nokogiri::XML::Element)
270
+ # For real XML C14N recursive processing is required. However, as a first step,
271
+ # we can just be sure that top-level attributes and namespace declarations are properly
272
+ # and relatively ordered
273
+ # From http://www.w3.org/TR/2000/WD-xml-c14n-20001011#Example-SETags
274
+ # * Relative order of namespace and attribute axes
275
+ # * Lexicographic ordering of namespace and attribute axes
268
276
  c = Nokogiri::XML.parse(c.dup.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::NO_EMPTY_TAGS)).root
269
- # Gather namespaces from self and decendant nodes
270
- #
271
- # prefix mappings
272
- # Look for @xmlns and @prefix mappings. Add any other mappings from options[:prefixes]
273
- # that aren't already defined on this node
274
- defined_mappings = {}
275
- prefix_mappings = {}
276
-
277
- c.traverse do |n|
278
- ns = n.namespace
279
- next unless ns
280
- prefix = ns.prefix ? "xmlns:#{ns.prefix}" : "xmlns"
281
- defined_mappings[ns.prefix.to_s] = ns.href.to_s
282
- c[prefix] = ns.href unless c.namespaces[prefix]
283
- end
284
-
285
- mappings = c["prefix"].to_s.split(/\s+/)
286
- while mappings.length > 0 do
287
- prefix, uri = mappings.shift.downcase, mappings.shift
288
- #puts "uri_mappings prefix #{prefix} <#{uri}>"
289
- next unless prefix.match(/:$/)
290
- prefix.chop!
291
-
292
- # A Conforming RDFa Processor must ignore any definition of a mapping for the '_' prefix.
293
- next if prefix == "_"
294
-
295
- defined_mappings[prefix] = uri
296
- prefix_mappings[prefix] = uri
297
- end
298
277
 
299
- # Add prefixes, being careful to honor mappings defined on the element
300
- if options[:prefixes]
301
- options[:prefixes].each_pair do |p, ns|
302
- prefix_mappings[p] = ns.uri unless defined_mappings.has_key?(p)
303
- end
304
- if prefix_mappings.length
305
- c["prefix"] = prefix_mappings.keys.sort.map {|p| "#{p}: #{prefix_mappings[p]}"}.join(" ")
306
- end
307
- end
308
-
309
- # Add profiles, being careful to honor profiles defined on the element
310
- if options[:profiles].is_a?(Array) && options[:profiles].length > 0
311
- profiles = c["profile"].to_s.split(" ")
312
- profiles += options[:profiles]
313
- c["profile"] = profiles.join(" ")
314
- end
315
-
316
- # Add default vocabulary, being careful to honor any defined on the element
317
- if options[:default_vocabulary] && !c["vocab"]
318
- c["vocab"] = options[:default_vocabulary].to_s
278
+ # Apply defined namespaces
279
+ ns_hash.each_pair do |prefix, href|
280
+ c[prefix] = href unless c.namespaces[prefix]
319
281
  end
320
282
 
283
+ # Add language
321
284
  if options[:language] && c["lang"].to_s.empty?
322
285
  c["xml:lang"] = options[:language]
323
286
  end
@@ -400,6 +363,18 @@ module RdfContext
400
363
  new(contents, encoding, options)
401
364
  end
402
365
 
366
+ # Parse a Literal in NTriples format
367
+ def self.parse(str)
368
+ case str
369
+ when LITERAL_WITH_LANGUAGE
370
+ Literal.n3_encoded($1, $2)
371
+ when LITERAL_WITH_DATATYPE
372
+ Literal.n3_encoded($1, nil, $2)
373
+ when LITERAL_PLAIN
374
+ Literal.n3_encoded($1, nil)
375
+ end
376
+ end
377
+
403
378
  # Create an un-typed literal with a language
404
379
  # @param [Object] contents
405
380
  # @param [String] language (nil)
@@ -447,7 +422,7 @@ module RdfContext
447
422
  end
448
423
  end
449
424
 
450
- class << self
425
+ class << self
451
426
  protected :new
452
427
  end
453
428
 
@@ -514,6 +489,14 @@ module RdfContext
514
489
  encoding.xml_args(@contents, @lang)
515
490
  end
516
491
 
492
+ ##
493
+ # Returns `true`
494
+ #
495
+ # @return [Boolean]
496
+ def literal?
497
+ true
498
+ end
499
+
517
500
  def untyped?; encoding == Encoding.the_null_encoding; end
518
501
  def typed?; encoding != Encoding.the_null_encoding; end
519
502