rdf_context 0.5.7 → 0.5.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/History.rdoc +15 -1
  2. data/README.rdoc +2 -0
  3. data/Rakefile +2 -4
  4. data/VERSION +1 -1
  5. data/bin/rdf_context +5 -54
  6. data/lib/rdf_context.rb +5 -0
  7. data/lib/rdf_context/graph.rb +68 -49
  8. data/lib/rdf_context/n3parser.rb +2 -2
  9. data/lib/rdf_context/namespace.rb +1 -1
  10. data/lib/rdf_context/nokogiri_hacks.rb +7 -0
  11. data/lib/rdf_context/parser.rb +57 -13
  12. data/lib/rdf_context/rdfaparser.rb +200 -130
  13. data/lib/rdf_context/rdfxmlparser.rb +8 -8
  14. data/lib/rdf_context/serializer/recursive_serializer.rb +1 -1
  15. data/lib/rdf_context/serializer/turtle_serializer.rb +15 -15
  16. data/lib/rdf_context/serializer/xml_serializer.rb +8 -8
  17. data/lib/rdf_context/store/memory_store.rb +14 -14
  18. data/lib/rdf_context/store/sqlite3_store.rb +4 -4
  19. data/lib/rdf_context/uriref.rb +11 -4
  20. data/script/console +1 -3
  21. data/script/tc +44 -0
  22. data/spec/.gitignore +1 -0
  23. data/spec/aggregate_graph_spec.rb +1 -0
  24. data/spec/bnode_spec.rb +2 -1
  25. data/spec/conjunctive_graph_spec.rb +1 -0
  26. data/spec/cwm_spec.rb +1 -0
  27. data/spec/duration_spec.rb +1 -0
  28. data/spec/graph_spec.rb +27 -0
  29. data/spec/list_store_spec.rb +1 -0
  30. data/spec/literal_spec.rb +1 -0
  31. data/spec/matchers.rb +1 -1
  32. data/spec/memory_store_spec.rb +1 -0
  33. data/spec/n3parser_spec.rb +1 -0
  34. data/spec/namespaces_spec.rb +1 -0
  35. data/spec/parser_spec.rb +1 -0
  36. data/spec/rdf_helper.rb +4 -4
  37. data/spec/rdfa_helper.rb +24 -0
  38. data/spec/rdfa_parser_spec.rb +6 -36
  39. data/spec/rdfcore/.gitignore +1 -0
  40. data/spec/rdfxml_spec.rb +1 -0
  41. data/spec/sqlite3_store_spec.rb +1 -0
  42. data/spec/string_hacks_spec.rb +2 -0
  43. data/spec/swap_test/.gitignore +1 -0
  44. data/spec/triple_spec.rb +1 -0
  45. data/spec/turtle/.gitignore +1 -0
  46. data/spec/turtle_serializer_spec.rb +3 -2
  47. data/spec/turtle_spec.rb +1 -0
  48. data/spec/uriref_spec.rb +13 -12
  49. data/spec/xml_serializer_spec.rb +7 -6
  50. metadata +26 -61
  51. data/spec/html4-manifest.yml +0 -4937
  52. data/spec/html5-manifest.yml +0 -4937
  53. data/spec/rdfcore/Manifest.yml +0 -6242
  54. data/spec/swap_test/n3parser.yml +0 -773
  55. data/spec/swap_test/regression.yml +0 -902
  56. data/spec/turtle/manifest-bad.yml +0 -807
  57. data/spec/turtle/manifest.yml +0 -807
  58. data/spec/xhtml-manifest.yml +0 -3901
  59. data/spec/xhtml11-manifest.yml +0 -4405
data/History.rdoc CHANGED
@@ -1,3 +1,17 @@
1
+ === 0.5.8.1
2
+ === 0.5.8
3
+ * Remove dependency on whatlanguage.
4
+ * Added support for Processor Graphs.
5
+ * Change Graph#seq to specifically look for subject type of rdf:Seq, rdf:Bag or rdf:Alt to trigger rdf:_n processing.
6
+ * Update RDFa processing to WD-rdfa-core-20100803 semantics
7
+ * Added Processor Graph and required output
8
+ * Reverse order of processing profiles
9
+ * Don't process element if any profile fails
10
+ * XMLLiterals must be explicitly specified as @datatype
11
+ * TERMorCURIEorAbsURI requires an absolute URI, not document relative
12
+ * Move @profile parsing before @vocabulary.
13
+ * Extract a new default vocabulary from @profile.*
14
+
1
15
  === 0.5.7
2
16
  * Add back support for RDFa 1.0 as well as RDFa 1.1. Parser checks @version to determine which
3
17
  * Remove specs for html4 and html5 until sorted out.
@@ -35,7 +49,7 @@
35
49
  * Remove old binding for a namespace URI creating a new binding
36
50
 
37
51
  === 0.5.1
38
- * Avoid stack-overflow when checking graph size (if $DEBUG == true)
52
+ * Avoid stack-overflow when checking graph size (if ::RdfContext::debug? == true)
39
53
  * Refactor serializers to be based on AbstractSerializer
40
54
  * Graph
41
55
  * Add Graph#serialize taking a serializer or symbol identifing a serialzer and a base URI
data/README.rdoc CHANGED
@@ -192,6 +192,8 @@ These interfaces work on contexts and formulae (for stores that are formula-awar
192
192
  * Reasoner/inference engine
193
193
  * SPARQL
194
194
  * RDFS logic and RDF entailment tests
195
+ * OWL 2 Test Cases
196
+ * http://owl.semanticweb.org/page/OWL_2_Test_Cases
195
197
 
196
198
  == Resources:
197
199
  * Distiller[http://kellogg-assoc/distiller]
data/Rakefile CHANGED
@@ -22,12 +22,10 @@ begin
22
22
  gemspec.email = "gregg@kellogg-assoc.com"
23
23
  gemspec.homepage = "http://github.com/gkellogg/rdf_context"
24
24
  gemspec.authors = ["Gregg Kellogg"]
25
- gemspec.add_dependency('addressable', '>= 2.0.0')
25
+ gemspec.add_dependency('addressable', '>= 2.2.0')
26
26
  gemspec.add_dependency('treetop', '>= 1.4.0')
27
- gemspec.add_dependency('whatlanguage', '>= 1.0.0')
28
- gemspec.add_dependency('nokogiri', '>= 1.3.3')
27
+ gemspec.add_dependency('nokogiri', '>= 1.4.3')
29
28
  gemspec.add_dependency('builder', '>= 2.1.2')
30
- gemspec.add_dependency('patron', '>= 0.4.6')
31
29
  gemspec.add_development_dependency('rspec')
32
30
  gemspec.add_development_dependency('activesupport', '>= 2.3.0')
33
31
  gemspec.add_development_dependency('yard')
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.7
1
+ 0.5.8.1
data/bin/rdf_context CHANGED
@@ -10,9 +10,7 @@ class Parse
10
10
  graph_opts[:store] = store if store
11
11
  parser = Parser.new(:graph => Graph.new(graph_opts))
12
12
  parser.parse(file.respond_to?(:read) ? file : File.open(file), base_uri, :strict => true)
13
- output = parser.graph.serialize(:format => $format.to_sym, :base => base_uri)
14
- puts output unless $quiet
15
-
13
+ puts parser.graph.serialize(:format => $format.to_sym, :base => base_uri) unless $quiet
16
14
  puts parser.debug.to_a.join("\n\t") if $verbose
17
15
  rescue RdfException => e
18
16
  puts "Parse failure: #{e.message}"
@@ -25,44 +23,12 @@ class Parse
25
23
  end
26
24
  end
27
25
 
28
- TEST_DIR = File.join(File.dirname(__FILE__), '..', 'spec', 'rdfa-test-suite', 'tests')
29
- BASE_MANIFEST_URL = "http://rdfa.digitalbazaar.com/test-suite/"
30
- BASE_TEST_CASE_URL = "#{BASE_MANIFEST_URL}test-cases/"
31
-
32
- def rdfa_tc(number, parse, store)
33
- f = File.expand_path("#{TEST_DIR}/#{number}.txt")
34
- found_head = false
35
- namespaces = ""
36
- body = File.readlines(f).map do |line|
37
- found_head ||= line.match(/<head/)
38
- if found_head
39
- line.chop
40
- else
41
- namespaces << line
42
- nil
43
- end
44
- end.compact.join("\n")
45
-
46
- namespaces.chop! # Remove trailing newline
47
-
48
- tcpath = BASE_TEST_CASE_URL + "xhtml1"
49
-
50
- head = "" +
51
- %(<?xml version="1.0" encoding="UTF-8"?>\n) +
52
- %(<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">\n) +
53
- %(<html xmlns="http://www.w3.org/1999/xhtml" version="XHTML+RDFa #{$rdfa_version}"\n)
54
- tc = head + "#{namespaces}>\n#{body.gsub(/\$TCPATH/, tcpath)}\n</html>"
55
-
56
- puts "Input file: #{tc}" if $DEBUG || $verbose
57
- parse.parse(StringIO.new(tc), "#{tcpath}/#{number}.xhtml")
58
- end
59
-
60
26
  mode = ARGV.shift
61
27
  raise "Mode must be one of 'parse'" unless mode == "parse"
62
28
 
63
29
  $verbose = false
30
+ $quiet = false
64
31
  $format = "ttl"
65
- $rdfa_version = "1.1"
66
32
  base_uri = "http://example.com"
67
33
  store = :list_store
68
34
  opts = GetoptLong.new(
@@ -71,19 +37,15 @@ opts = GetoptLong.new(
71
37
  ["--debug", GetoptLong::NO_ARGUMENT],
72
38
  ["--format", GetoptLong::REQUIRED_ARGUMENT],
73
39
  ["--store", GetoptLong::REQUIRED_ARGUMENT],
74
- ["--uri", GetoptLong::REQUIRED_ARGUMENT],
75
- ["--rdfa", GetoptLong::NO_ARGUMENT],
76
- ["--1_0", GetoptLong::NO_ARGUMENT]
40
+ ["--uri", GetoptLong::REQUIRED_ARGUMENT]
77
41
  )
78
42
  opts.each do |opt, arg|
79
43
  case opt
80
44
  when '--verbose' then $verbose = true
81
45
  when '--quiet' then $quiet = true
82
- when '--debug' then $DEBUG = true
46
+ when '--debug' then ::RdfContext::debug = true
83
47
  when '--format' then $format = arg
84
48
  when '--uri' then base_uri = arg
85
- when '--rdfa' then $rdfa = true
86
- when '--1_0' then $rdfa_version = "1.0"
87
49
  when '--store'
88
50
  case arg
89
51
  when /list/
@@ -98,20 +60,9 @@ opts.each do |opt, arg|
98
60
  end
99
61
 
100
62
  x = Parse.new
101
- if $rdfa && ARGV.empty?
102
- # Run all RDFa test cases
103
- Dir.foreach(TEST_DIR) do |f|
104
- next unless f.match(/^(.*)\.txt$/)
105
- rdfa_tc($1, x, store)
106
- end
107
- elsif ARGV.empty?
63
+ if ARGV.empty?
108
64
  s = $stdin.read
109
65
  x.parse(StringIO.new(s), base_uri, store)
110
- elsif $rdfa
111
- # Run specified RDFa test cases
112
- ARGV.each do |tc|
113
- rdfa_tc(tc, x, store)
114
- end
115
66
  else
116
67
  ARGV.each do |test_file|
117
68
  x.parse(test_file, base_uri, store)
data/lib/rdf_context.rb CHANGED
@@ -74,4 +74,9 @@ module RdfContext
74
74
  WELLKNOWN_NAMESPACES = [DC_NS, OWL_NS, LOG_NS, RDF_NS, RDFA_NS, RDFS_NS, XHV_NS, XML_NS, XSD_NS, XSI_NS]
75
75
 
76
76
  XH_MAPPING = {"" => Namespace.new("http://www.w3.org/1999/xhtml/vocab\#", nil)}
77
+
78
+
79
+ # Control debug output.
80
+ def self.debug?; @debug; end
81
+ def self.debug=(value); @debug = value; end
77
82
  end
@@ -265,39 +265,6 @@ module RdfContext
265
265
  self
266
266
  end
267
267
 
268
- ##
269
- # Adds a list of resources as an RDF list by creating bnodes and first/rest triples
270
- # @param [URIRef, BNode] subject the subject of the triple
271
- # @param [URIRef] predicate the predicate of the triple
272
- # @param [Array] objects List of objects to serialize
273
- # @return [Graph] Returns the graph
274
- # @raise [Error] Checks parameter types and raises if they are incorrect.
275
- def add_seq(subject, predicate, objects)
276
- if objects.empty?
277
- add_triple(subject, predicate, RDF_NS.nil)
278
- return self
279
- end
280
-
281
- if RDF_NS.first != predicate
282
- bn = BNode.new
283
- add_triple(subject, predicate, bn)
284
- subject = bn
285
- end
286
-
287
- last = objects.pop
288
-
289
- objects.each do |o|
290
- add_triple(subject, RDF_NS.first, o)
291
- bn = BNode.new
292
- add_triple(subject, RDF_NS.rest, bn)
293
- subject = bn
294
- end
295
-
296
- # Last item in list
297
- add_triple(subject, RDF_NS.first, last)
298
- add_triple(subject, RDF_NS.rest, RDF_NS.nil)
299
- end
300
-
301
268
  # Remove a triple from the graph. Delegates to store.
302
269
  # Nil matches all triples and thus empties the graph
303
270
  # @param [Triple] triple
@@ -316,19 +283,24 @@ module RdfContext
316
283
 
317
284
  # Returns ordered rdf:_n objects or rdf:first, rdf:rest for a given subject
318
285
  # @param [Resource] subject
286
+ # @param [Resource] predicate defaults to rdf:first, not used of subject is an rdf:List type
319
287
  # @return [Array<Resource>]
320
- def seq(subject)
288
+ def seq(subject, predicate = RDF_NS.first)
321
289
  props = properties(subject)
322
- rdf_type = (props[RDF_TYPE.to_s] || []).map {|t| t.to_s}
290
+ rdf_type = (props[RDF_TYPE.to_s] || [])
323
291
 
324
292
  #puts "seq; #{rdf_type} #{rdf_type - [RDF_NS.Seq, RDF_NS.Bag, RDF_NS.Alt]}"
325
- if !(rdf_type - [RDF_NS.Seq, RDF_NS.Bag, RDF_NS.Alt]).empty?
293
+ if rdf_type.include?(RDF_NS.Seq) || rdf_type.include?(RDF_NS.Bag) || rdf_type.include?(RDF_NS.Alt)
326
294
  props.keys.select {|k| k.match(/#{RDF_NS.uri}_(\d)$/)}.
327
295
  sort_by {|i| i.sub(RDF_NS._.to_s, "").to_i}.
328
296
  map {|key| props[key]}.
329
297
  flatten
330
- elsif !self.triples(Triple.new(subject, RDF_NS.first, nil)).empty?
298
+ elsif !self.triples(Triple.new(subject, predicate, nil)).empty?
331
299
  # N3-style first/rest chain
300
+ unless predicate == RDF_NS.first
301
+ subject = (properties(subject)[predicate.to_s] || []).first
302
+ end
303
+
332
304
  list = []
333
305
  while subject != RDF_NS.nil
334
306
  props = properties(subject)
@@ -346,6 +318,53 @@ module RdfContext
346
318
  end
347
319
  end
348
320
 
321
+ ##
322
+ # Adds a list of resources as an RDF list by creating bnodes and first/rest triples.
323
+ # Removes existing sequence nodes.
324
+ #
325
+ # @param [URIRef, BNode] subject the subject of the triple
326
+ # @param [URIRef] predicate the predicate of the triple
327
+ # @param [Array] objects List of objects to serialize
328
+ # @return [Graph] Returns the graph
329
+ # @raise [Error] Checks parameter types and raises if they are incorrect.
330
+ def add_seq(subject, predicate, objects)
331
+ self.triples(Triple.new(subject, predicate, nil)).each do |t, ctx|
332
+ bn = t.object
333
+ while bn != RDF_NS.nil
334
+ rest = properties(bn)[RDF_NS.rest.to_s].first
335
+ remove(Triple.new(bn, nil, nil))
336
+ bn = rest
337
+ end
338
+ end
339
+ remove(Triple.new(subject, predicate, nil))
340
+
341
+ if objects.empty?
342
+ add_triple(subject, predicate, RDF_NS.nil)
343
+ return self
344
+ end
345
+
346
+ if RDF_NS.first != predicate
347
+ bn = BNode.new
348
+ add_triple(subject, predicate, bn)
349
+ subject = bn
350
+ end
351
+
352
+ last = objects.pop
353
+
354
+ objects.each do |o|
355
+ add_triple(subject, RDF_NS.first, o)
356
+ bn = BNode.new
357
+ add_triple(subject, RDF_NS.rest, bn)
358
+ subject = bn
359
+ end
360
+
361
+ # Last item in list
362
+ add_triple(subject, RDF_NS.first, last)
363
+ add_triple(subject, RDF_NS.rest, RDF_NS.nil)
364
+
365
+ self
366
+ end
367
+
349
368
  # Resource properties
350
369
  #
351
370
  # Properties arranged as a hash with the predicate Term as index to an array of resources or literals
@@ -388,7 +407,7 @@ module RdfContext
388
407
 
389
408
  # Iterate through and add properties to graph
390
409
  props.each_pair do |pred, list|
391
- predicate = URIRef.new(pred)
410
+ predicate = URIRef.intern(pred)
392
411
  [list].flatten.compact.each do |object|
393
412
  add(Triple.new(subject, predicate, object))
394
413
  end
@@ -472,25 +491,25 @@ module RdfContext
472
491
  # @param [Graph] graph
473
492
  # @return [Boolean]
474
493
  def eql?(other)
475
- #puts "eql? size #{self.size} vs #{other.size}" if $DEBUG
494
+ #puts "eql? size #{self.size} vs #{other.size}" if ::RdfContext::debug?
476
495
  return false if !other.is_a?(Graph) || self.size != other.size
477
496
  return false unless other.identifier.to_s == identifier.to_s unless other.identifier.is_a?(BNode) && identifier.is_a?(BNode)
478
497
 
479
498
  bn_self = bnodes.values.sort
480
499
  bn_other = other.bnodes.values.sort
481
- puts "eql? bnodes '#{bn_self.to_sentence}' vs '#{bn_other.to_sentence}'" if $DEBUG
500
+ puts "eql? bnodes '#{bn_self.to_sentence}' vs '#{bn_other.to_sentence}'" if ::RdfContext::debug?
482
501
  return false unless bn_self == bn_other
483
502
 
484
503
  # Check each triple to see if it's contained in the other graph
485
504
  triples do |t, ctx|
486
505
  next if t.subject.is_a?(BNode) || t.predicate.is_a?(BNode) || t.object.is_a?(BNode)
487
- puts "eql? contains '#{t.to_ntriples}: #{other.contains?(t)}'" if $DEBUG
506
+ puts "eql? contains '#{t.to_ntriples}: #{other.contains?(t)}'" if ::RdfContext::debug?
488
507
  return false unless other.contains?(t)
489
508
  end
490
509
 
491
510
  # For each BNode, check permutations of similar bnodes in other graph
492
511
  bnode_permutations(bnodes, other.bnodes) do |bn_map|
493
- puts "bnode permutations: #{bn_map.inspect}" if $DEBUG
512
+ puts "bnode permutations: #{bn_map.inspect}" if ::RdfContext::debug?
494
513
  # bn_map contains 1-1 mapping of bnodes from self to other
495
514
  catch :next_perm do
496
515
  triples do |t, ctx|
@@ -500,10 +519,10 @@ module RdfContext
500
519
  predicate = bn_map[predicate] if bn_map.has_key?(predicate)
501
520
  object = bn_map[object] if bn_map.has_key?(object)
502
521
  tn = Triple.new(subject, predicate, object)
503
- puts " eql? contains '#{tn.inspect}': #{other.contains?(tn)}" if $DEBUG
522
+ puts " eql? contains '#{tn.inspect}': #{other.contains?(tn)}" if ::RdfContext::debug?
504
523
  next if other.contains?(tn)
505
524
 
506
- puts " no, next permutation" if $DEBUG
525
+ puts " no, next permutation" if ::RdfContext::debug?
507
526
  # Not a match, try next permutation
508
527
  throw :next_perm
509
528
  end
@@ -543,7 +562,7 @@ module RdfContext
543
562
  # Take source keys and run permutations mapping to other keys, if the permutation
544
563
  # maps to the same counts for each
545
564
  def bnode_permutations(bn_source, bn_other)
546
- puts "compare #{bn_source.inspect}\n with #{bn_other.inspect}" if $DEBUG
565
+ puts "compare #{bn_source.inspect}\n with #{bn_other.inspect}" if ::RdfContext::debug?
547
566
 
548
567
  source_keys = bn_source.keys
549
568
  other_keys = bn_other.keys
@@ -556,14 +575,14 @@ module RdfContext
556
575
  when 1
557
576
  # All keys have equivalent counts, yield permutations
558
577
  if source_keys.length == 1
559
- puts "yield #{{source_keys.first => other_keys.first}.inspect}" if $DEBUG
578
+ puts "yield #{{source_keys.first => other_keys.first}.inspect}" if ::RdfContext::debug?
560
579
  yield({source_keys.first => other_keys.first})
561
580
  else
562
581
  (0..(source_keys.length-1)).to_a.permute do |indicies|
563
- puts "indicies #{indicies.inspect}" if $DEBUG
582
+ puts "indicies #{indicies.inspect}" if ::RdfContext::debug?
564
583
  ok = other_keys.dup
565
584
  map = indicies.inject({}) { |hash, i| hash[source_keys[i]] = ok.shift; hash}
566
- puts "yield #{map.inspect}" if $DEBUG
585
+ puts "yield #{map.inspect}" if ::RdfContext::debug?
567
586
  yield(map)
568
587
  end
569
588
  end
@@ -581,7 +600,7 @@ module RdfContext
581
600
  bn_other_max[bn] = bn_other_min.delete(bn) if v == max
582
601
  end
583
602
 
584
- puts "yield permutations of multiple with max #{bn_source_max.inspect}\n and #{bn_other_max.inspect}" if $DEBUG
603
+ puts "yield permutations of multiple with max #{bn_source_max.inspect}\n and #{bn_other_max.inspect}" if ::RdfContext::debug?
585
604
  # Yield for each permutation of max joined with permutations of min
586
605
  bnode_permutations(bn_source_max, bn_other_max) do |bn_perm_max|
587
606
  bnode_permutations(bn_source_min, bn_other_min) do |bn_perm_min|
@@ -35,7 +35,7 @@ module RdfContext
35
35
  @graph.allow_n3 = true
36
36
  document = parser.parse(@doc)
37
37
  unless document
38
- puts parser.inspect if $DEBUG
38
+ puts parser.inspect if ::RdfContext::debug?
39
39
  reason = parser.failure_reason
40
40
  raise ParserException.new(reason)
41
41
  end
@@ -269,7 +269,7 @@ module RdfContext
269
269
 
270
270
  def process_uri(uri)
271
271
  uri = uri.text_value if uri.respond_to?(:text_value)
272
- URIRef.new(uri, @uri, :normalize => false)
272
+ URIRef.intern(uri, @uri, :normalize => false)
273
273
  end
274
274
 
275
275
  def process_properties(properties)
@@ -53,7 +53,7 @@ module RdfContext
53
53
  prefix = @uri
54
54
  suffix = suffix.to_s.sub(/^\#/, "") if prefix.index("#")
55
55
  suffix = suffix.to_s.sub(/_$/, '')
56
- URIRef.new(prefix + suffix.to_s, :normalize => false, :namespace => self)
56
+ URIRef.intern(prefix + suffix.to_s, :normalize => false, :namespace => self)
57
57
  end
58
58
 
59
59
  # Make sure to attach fragment
@@ -5,4 +5,11 @@ class Nokogiri::XML::Node
5
5
  ns = self.namespace ? self.namespace.href : RdfContext::XML_NS.uri.to_s
6
6
  RdfContext::URIRef.new(ns + self.node_name, :normalize => false)
7
7
  end
8
+ def display_path
9
+ @display_path ||= case self
10
+ when Nokogiri::XML::Document then ""
11
+ when Nokogiri::XML::Element then parent ? "#{parent.display_path}/#{name}" : name
12
+ when Nokogiri::XML::Attr then "#{parent.display_path}@#{name}"
13
+ end
14
+ end
8
15
  end
@@ -3,20 +3,36 @@ require File.join(File.dirname(__FILE__), 'graph')
3
3
  module RdfContext
4
4
  # Generic RdfContext Parser class
5
5
  class Parser
6
- attr_reader :debug, :uri
7
- attr_accessor :doc, :graph
6
+ attr_reader :debug
7
+
8
+ # URI of parsed document
9
+ # @return [RdfContext::URIRef]
10
+ attr_reader :uri
11
+
12
+ # Source of parsed document
13
+ # @return [Nokogiri::XML::Document, #read]
14
+ attr_accessor :doc
8
15
 
16
+ # Graph instance containing parsed statements
17
+ # @return [RdfContext::Graph]
18
+ attr_accessor :graph
19
+
20
+ # Graph instance containing informationa, warning and error statements
21
+ # @return [RdfContext::Graph]
22
+ attr_accessor :processor_graph
23
+
9
24
  ##
10
25
  # Creates a new parser
11
26
  #
12
27
  # @option options [Graph] :graph (nil) Graph to parse into, otherwise a new RdfContext::Graph instance is created
13
- # @option options [Array] :debug (nil) Array to place debug messages
28
+ # @option options [Graph] :processor_graph (nil) Graph to record information, warnings and errors.
14
29
  # @option options [:rdfxml, :html, :n3] :type (nil)
15
30
  # @option options [Boolean] :strict (false) Raise Error if true, continue with lax parsing, otherwise
16
31
  def initialize(options = {})
17
32
  # initialize the triplestore
18
33
  @graph = options[:graph]
19
- @debug = options[:debug]
34
+ @processor_graph = options[:processor_graph] if options[:processor_graph]
35
+ @debug = options[:debug] # XXX deprecated
20
36
  @strict = options[:strict]
21
37
  @named_bnodes = {}
22
38
  end
@@ -25,7 +41,7 @@ module RdfContext
25
41
  #
26
42
  # @param [#read, #to_s] stream the HTML+RDFa IO stream, string, Nokogiri::HTML::Document or Nokogiri::XML::Document
27
43
  # @param [String] uri (nil) the URI of the document
28
- # @option options [Array] :debug (nil) Array to place debug messages
44
+ # @option options [Graph] :processor_graph (nil) Graph to record information, warnings and errors.
29
45
  # @option options [:rdfxml, :html, :n3] :type (nil)
30
46
  # @option options [Boolean] :strict (false) Raise Error if true, continue with lax parsing, otherwise
31
47
  # @return [Graph] Returns the graph containing parsed triples
@@ -48,7 +64,7 @@ module RdfContext
48
64
  #
49
65
  # @param [#read, #to_s] stream the HTML+RDFa IO stream, string, Nokogiri::HTML::Document or Nokogiri::XML::Document
50
66
  # @param [String] uri (nil) the URI of the document
51
- # @option options [Array] :debug (nil) Array to place debug messages
67
+ # @option options [Graph] :processor_graph (nil) Graph to record information, warnings and errors.
52
68
  # @option options [:rdfxml, :html, :n3] :type (nil)
53
69
  # @option options [Boolean] :strict (false) Raise Error if true, continue with lax parsing, otherwise
54
70
  # @return [Graph] Returns the graph containing parsed triples
@@ -62,7 +78,8 @@ module RdfContext
62
78
 
63
79
  options[:strict] ||= @strict if @strict
64
80
  options[:graph] ||= @graph if @graph
65
- options[:debug] ||= @debug if @debug
81
+ options[:debug] ||= @debug if @debug # XXX deprecated
82
+ @processor_graph = options[:processor_graph] if options[:processor_graph]
66
83
  # Intuit type, if not provided
67
84
  options[:type] ||= detect_format(stream, uri)
68
85
 
@@ -89,6 +106,8 @@ module RdfContext
89
106
 
90
107
  # @return [Graph]
91
108
  def graph; @delegate ? @delegate.graph : (@graph || Graph.new); end
109
+ # @return [Graph]
110
+ def processor_graph; @delegate ? @delegate.processor_graph : (@processor_graph || Graph.new); end
92
111
 
93
112
  # @return [Array<String>]
94
113
  def debug; @delegate ? @delegate.debug : @debug; end
@@ -135,9 +154,8 @@ module RdfContext
135
154
  # Figure out the document path, if it is a Nokogiri::XML::Element or Attribute
136
155
  def node_path(node)
137
156
  case node
138
- when Nokogiri::XML::Element, Nokogiri::XML::Attr then "#{node_path(node.parent)}/#{node.name}"
139
- when String then node
140
- else ""
157
+ when Nokogiri::XML::Node then node.display_path
158
+ else node.to_s
141
159
  end
142
160
  end
143
161
 
@@ -146,10 +164,36 @@ module RdfContext
146
164
  # @param [XML Node, any] node:: XML Node or string for showing context
147
165
  # @param [String] message::
148
166
  def add_debug(node, message)
149
- puts "#{node_path(node)}: #{message}" if $DEBUG
150
- @debug << "#{node_path(node)}: #{message}" if @debug.is_a?(Array)
167
+ add_processor_message(node, message, RDFA_NS.InformationalMessage)
151
168
  end
152
169
 
170
+ def add_info(node, message, process_class = RDFA_NS.InformationalMessage)
171
+ add_processor_message(node, message, process_class)
172
+ end
173
+
174
+ def add_warning(node, message, process_class = RDFA_NS.MiscellaneousWarning)
175
+ add_processor_message(node, message, process_class)
176
+ end
177
+
178
+ def add_error(node, message, process_class = RDFA_NS.MiscellaneousError)
179
+ add_processor_message(node, message, process_class)
180
+ raise ParserException, message if @strict
181
+ end
182
+
183
+ def add_processor_message(node, message, process_class)
184
+ puts "#{node_path(node)}: #{message}" if ::RdfContext::debug?
185
+ @debug << "#{node_path(node)}: #{message}" if @debug.is_a?(Array)
186
+ if @processor_graph
187
+ @processor_sequence ||= 0
188
+ n = BNode.new
189
+ @processor_graph << Triple.new(n, RDF_TYPE, process_class)
190
+ @processor_graph << Triple.new(n, DC_NS.description, message)
191
+ @processor_graph << Triple.new(n, DC_NS.date, Literal.build_from(DateTime.now.to_date))
192
+ @processor_graph << Triple.new(n, RDFA_NS.sequence, Literal.build_from(@processor_sequence += 1))
193
+ @processor_graph << Triple.new(n, RDFA_NS.source, node_path(node))
194
+ end
195
+ end
196
+
153
197
  # add a triple, object can be literal or URI or bnode
154
198
  #
155
199
  # If the parser is called with a block, triples are passed to the block rather
@@ -172,7 +216,7 @@ module RdfContext
172
216
  triple
173
217
  rescue RdfException => e
174
218
  add_debug(node, "add_triple raised #{e.class}: #{e.message}")
175
- puts e.backtrace if $DEBUG
219
+ puts e.backtrace if ::RdfContext::debug?
176
220
  raise if @strict
177
221
  end
178
222
  end