rdf_context 0.5.7 → 0.5.8.1

Sign up to get free protection for your applications and to get access to all the features.
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