rdf_context 0.4.8 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (248) hide show
  1. data/History.txt +27 -0
  2. data/README.rdoc +22 -9
  3. data/Rakefile +11 -6
  4. data/VERSION +1 -1
  5. data/bin/rdf_context +12 -4
  6. data/lib/rdf_context.rb +3 -1
  7. data/lib/rdf_context/aggregate_graph.rb +86 -0
  8. data/lib/rdf_context/array_hacks.rb +53 -0
  9. data/lib/rdf_context/conjunctive_graph.rb +1 -1
  10. data/lib/rdf_context/exceptions.rb +9 -7
  11. data/lib/rdf_context/graph.rb +174 -15
  12. data/lib/rdf_context/literal.rb +34 -2
  13. data/lib/rdf_context/n3_grammar.treetop +213 -129
  14. data/lib/rdf_context/n3parser.rb +281 -57
  15. data/lib/rdf_context/namespace.rb +23 -12
  16. data/lib/rdf_context/parser.rb +4 -3
  17. data/lib/rdf_context/quoted_graph.rb +38 -0
  18. data/lib/rdf_context/rdfaparser.rb +2 -1
  19. data/lib/rdf_context/rdfxmlparser.rb +4 -3
  20. data/lib/rdf_context/store/abstract_sql_store.rb +4 -4
  21. data/lib/rdf_context/store/abstract_store.rb +5 -1
  22. data/lib/rdf_context/store/sqlite3_store.rb +10 -8
  23. data/lib/rdf_context/string_hacks.rb +44 -21
  24. data/lib/rdf_context/term_utils.rb +73 -4
  25. data/lib/rdf_context/triple.rb +32 -47
  26. data/lib/rdf_context/uriref.rb +33 -26
  27. data/spec/aggregate_graph_spec.rb +59 -0
  28. data/spec/conjunctive_graph_spec.rb +1 -1
  29. data/spec/cwm_spec.rb +32 -0
  30. data/spec/graph_spec.rb +114 -3
  31. data/spec/literal_spec.rb +107 -5
  32. data/spec/matchers.rb +104 -51
  33. data/spec/n3parser_spec.rb +798 -99
  34. data/spec/namespaces_spec.rb +26 -0
  35. data/spec/quoted_graph_spec.rb +0 -0
  36. data/spec/rdf_helper.rb +197 -0
  37. data/spec/rdfa_helper.rb +15 -11
  38. data/spec/rdfa_parser_spec.rb +6 -8
  39. data/spec/rdfxml_spec.rb +21 -28
  40. data/spec/spec_helper.rb +20 -0
  41. data/spec/sqlite3_store_spec.rb +6 -5
  42. data/spec/store_helper.rb +9 -1
  43. data/spec/string_hacks_spec.rb +14 -0
  44. data/spec/{rdfxml_helper.rb → swap_helper.rb} +8 -9
  45. data/spec/swap_spec.rb +77 -0
  46. data/spec/swap_test/animal.rdf +17 -0
  47. data/spec/swap_test/anon-prop.n3 +14 -0
  48. data/spec/swap_test/anonymous_loop.n3 +2 -0
  49. data/spec/swap_test/contexts.n3 +16 -0
  50. data/spec/swap_test/daml-pref.n3 +10 -0
  51. data/spec/swap_test/i18n/hiragana.n3 +22 -0
  52. data/spec/swap_test/i18n/n3string.n3 +4 -0
  53. data/spec/swap_test/list/itemType.rdf +12 -0
  54. data/spec/swap_test/lists-simple.n3 +40 -0
  55. data/spec/swap_test/lists.n3 +35 -0
  56. data/spec/swap_test/n3/n3parser.tests_n3_10001.nt +3 -0
  57. data/spec/swap_test/n3/n3parser.tests_n3_10002.nt +7 -0
  58. data/spec/swap_test/n3/n3parser.tests_n3_10003.nt +3 -0
  59. data/spec/swap_test/n3/n3parser.tests_n3_10004.nt +119 -0
  60. data/spec/swap_test/n3/n3parser.tests_n3_10005.nt +3 -0
  61. data/spec/swap_test/n3/n3parser.tests_n3_10006.nt +225 -0
  62. data/spec/swap_test/n3/n3parser.tests_n3_10007.nt +79 -0
  63. data/spec/swap_test/n3/n3parser.tests_n3_10008.nt +5 -0
  64. data/spec/swap_test/n3/n3parser.tests_n3_10009.nt +13 -0
  65. data/spec/swap_test/n3/n3parser.tests_n3_10010.nt +21 -0
  66. data/spec/swap_test/n3/n3parser.tests_n3_10011.nt +9 -0
  67. data/spec/swap_test/n3/n3parser.tests_n3_10012.nt +53 -0
  68. data/spec/swap_test/n3/n3parser.tests_n3_10013.nt +19 -0
  69. data/spec/swap_test/n3/n3parser.tests_n3_10014.nt +103 -0
  70. data/spec/swap_test/n3/n3parser.tests_n3_10015.nt +103 -0
  71. data/spec/swap_test/n3/n3parser.tests_n3_10016.nt +3 -0
  72. data/spec/swap_test/n3/n3parser.tests_n3_10017.nt +151 -0
  73. data/spec/swap_test/n3/n3parser.tests_n3_10018.nt +9 -0
  74. data/spec/swap_test/n3/n3parser.tests_n3_10019.nt +3 -0
  75. data/spec/swap_test/n3/n3parser.tests_n3_10020.nt +13 -0
  76. data/spec/swap_test/n3parser.tests +160 -0
  77. data/spec/swap_test/nodeID/classes.n3 +9 -0
  78. data/spec/swap_test/nodeID/classes.ref.rdf +15 -0
  79. data/spec/swap_test/nodeID/ex1.rdf +15 -0
  80. data/spec/swap_test/norm/fix.rdf +33 -0
  81. data/spec/swap_test/owl-ex.rdf +150 -0
  82. data/spec/swap_test/ref/animal.n3 +11 -0
  83. data/spec/swap_test/ref/anon-prop-1.n3 +8 -0
  84. data/spec/swap_test/ref/anonymous_loop.ref +7 -0
  85. data/spec/swap_test/ref/bnode.n3 +6 -0
  86. data/spec/swap_test/ref/bnode.rdf +16 -0
  87. data/spec/swap_test/ref/colon-in-uri.n3 +15 -0
  88. data/spec/swap_test/ref/daml-ex.n3 +103 -0
  89. data/spec/swap_test/ref/daml-ont.n3 +289 -0
  90. data/spec/swap_test/ref/djb1a-out.n3 +4 -0
  91. data/spec/swap_test/ref/dot-dash.n3 +8 -0
  92. data/spec/swap_test/ref/in-xml-t.n3 +4 -0
  93. data/spec/swap_test/ref/itemType.n3 +9 -0
  94. data/spec/swap_test/ref/keywords1.n3 +11 -0
  95. data/spec/swap_test/ref/keywords2.n3 +11 -0
  96. data/spec/swap_test/ref/lists-simple-1.rdf +108 -0
  97. data/spec/swap_test/ref/lists.n3 +43 -0
  98. data/spec/swap_test/ref/lstring-out.n3 +20 -0
  99. data/spec/swap_test/ref/n3string.n3 +13 -0
  100. data/spec/swap_test/ref/no-last-nl.n3 +3 -0
  101. data/spec/swap_test/ref/numbers.n3 +18 -0
  102. data/spec/swap_test/ref/path1.n3 +8 -0
  103. data/spec/swap_test/ref/path2.n3 +39 -0
  104. data/spec/swap_test/ref/prefix1.rdf +31 -0
  105. data/spec/swap_test/ref/prefix3.rdf +31 -0
  106. data/spec/swap_test/ref/rdf-redefine.rdf +11 -0
  107. data/spec/swap_test/ref/reluri-1.rdf +18 -0
  108. data/spec/swap_test/ref/strquot.n3 +23 -0
  109. data/spec/swap_test/ref/strquot_a.n3 +23 -0
  110. data/spec/swap_test/ref/xml-base3.n3 +5 -0
  111. data/spec/swap_test/ref/xml-redefine.rdf +20 -0
  112. data/spec/swap_test/ref/xml-redefine2.rdf +23 -0
  113. data/spec/swap_test/ref/xml-syntax-basic-serialization.rdf +10 -0
  114. data/spec/swap_test/ref/xmllit.nt +3 -0
  115. data/spec/swap_test/regression.n3 +231 -0
  116. data/spec/swap_test/reluri-1.n3 +10 -0
  117. data/spec/swap_test/strquot.n3 +23 -0
  118. data/spec/swap_test/syntax/colon-in-uri.rdf +27 -0
  119. data/spec/swap_test/syntax/djb1a.n3 +3 -0
  120. data/spec/swap_test/syntax/dot-dash.n3 +15 -0
  121. data/spec/swap_test/syntax/equals1.n3 +1 -0
  122. data/spec/swap_test/syntax/equals2.n3 +1 -0
  123. data/spec/swap_test/syntax/keywords1.n3 +17 -0
  124. data/spec/swap_test/syntax/keywords2.n3 +18 -0
  125. data/spec/swap_test/syntax/lstring.n3 +26 -0
  126. data/spec/swap_test/syntax/neg-formula-predicate.n3 +1 -0
  127. data/spec/swap_test/syntax/neg-keywords3.n3 +1 -0
  128. data/spec/swap_test/syntax/neg-literal-predicate.n3 +1 -0
  129. data/spec/swap_test/syntax/neg-single-quote.n3 +1 -0
  130. data/spec/swap_test/syntax/neg-thisadoc.n3 +1 -0
  131. data/spec/swap_test/syntax/no-last-nl.n3 +2 -0
  132. data/spec/swap_test/syntax/numbers.n3 +26 -0
  133. data/spec/swap_test/syntax/path1.n3 +23 -0
  134. data/spec/swap_test/syntax/path2.n3 +31 -0
  135. data/spec/swap_test/syntax/qvars1.n3 +19 -0
  136. data/spec/swap_test/syntax/qvars2.n3 +19 -0
  137. data/spec/swap_test/syntax/this-quantifiers.n3 +164 -0
  138. data/spec/swap_test/syntax/this-rules.n3 +43 -0
  139. data/spec/swap_test/syntax/too-nested.n3 +25 -0
  140. data/spec/swap_test/syntax/trailing-semicolon.n3 +12 -0
  141. data/spec/swap_test/syntax/zero-objects.n3 +1 -0
  142. data/spec/swap_test/syntax/zero-predicates.n3 +3 -0
  143. data/spec/swap_test/tests-work.txt +25 -0
  144. data/spec/swap_test/xml-syntax/basic-serialization.n3 +8 -0
  145. data/spec/swap_test/xml-syntax/in-xml.xml +13 -0
  146. data/spec/swap_test/xml-syntax/non-ascii-pred.rdf +14 -0
  147. data/spec/swap_test/xml-syntax/rdf_prefix.n3 +2 -0
  148. data/spec/swap_test/xml-syntax/xml_prefix.n3 +7 -0
  149. data/spec/swap_test/xml-syntax/xml_prefix2.n3 +9 -0
  150. data/spec/swap_test/xml-syntax/xmlbase3.rdf +10 -0
  151. data/spec/swap_test/xml-syntax/xmllit.rdf +33 -0
  152. data/spec/triple_spec.rb +90 -46
  153. data/spec/turtle/README.txt +20 -0
  154. data/spec/turtle/bad-00.ttl +2 -0
  155. data/spec/turtle/bad-01.ttl +3 -0
  156. data/spec/turtle/bad-02.ttl +3 -0
  157. data/spec/turtle/bad-03.ttl +3 -0
  158. data/spec/turtle/bad-04.ttl +3 -0
  159. data/spec/turtle/bad-05.ttl +4 -0
  160. data/spec/turtle/bad-06.ttl +3 -0
  161. data/spec/turtle/bad-07.ttl +4 -0
  162. data/spec/turtle/bad-08.ttl +2 -0
  163. data/spec/turtle/bad-09.ttl +3 -0
  164. data/spec/turtle/bad-10.ttl +3 -0
  165. data/spec/turtle/bad-11.ttl +3 -0
  166. data/spec/turtle/bad-12.ttl +3 -0
  167. data/spec/turtle/bad-13.ttl +3 -0
  168. data/spec/turtle/bad-14.ttl +6 -0
  169. data/spec/turtle/manifest-bad.ttl +88 -0
  170. data/spec/turtle/manifest.ttl +215 -0
  171. data/spec/turtle/rdf-schema.out +126 -0
  172. data/spec/turtle/rdf-schema.ttl +156 -0
  173. data/spec/turtle/rdfq-results.out +36 -0
  174. data/spec/turtle/rdfq-results.ttl +39 -0
  175. data/spec/turtle/rdfs-namespace.out +131 -0
  176. data/spec/turtle/rdfs-namespace.ttl +160 -0
  177. data/spec/turtle/test-00.out +1 -0
  178. data/spec/turtle/test-00.ttl +2 -0
  179. data/spec/turtle/test-01.out +3 -0
  180. data/spec/turtle/test-01.ttl +7 -0
  181. data/spec/turtle/test-02.out +3 -0
  182. data/spec/turtle/test-02.ttl +5 -0
  183. data/spec/turtle/test-03.out +3 -0
  184. data/spec/turtle/test-03.ttl +5 -0
  185. data/spec/turtle/test-04.out +2 -0
  186. data/spec/turtle/test-04.ttl +4 -0
  187. data/spec/turtle/test-05.out +4 -0
  188. data/spec/turtle/test-05.ttl +4 -0
  189. data/spec/turtle/test-06.out +1 -0
  190. data/spec/turtle/test-06.ttl +3 -0
  191. data/spec/turtle/test-07.out +5 -0
  192. data/spec/turtle/test-07.ttl +3 -0
  193. data/spec/turtle/test-08.out +1 -0
  194. data/spec/turtle/test-08.ttl +3 -0
  195. data/spec/turtle/test-09.out +4 -0
  196. data/spec/turtle/test-09.ttl +10 -0
  197. data/spec/turtle/test-10.out +5 -0
  198. data/spec/turtle/test-10.ttl +5 -0
  199. data/spec/turtle/test-11.out +4 -0
  200. data/spec/turtle/test-11.ttl +10 -0
  201. data/spec/turtle/test-12.out +4 -0
  202. data/spec/turtle/test-12.ttl +9 -0
  203. data/spec/turtle/test-13.out +2 -0
  204. data/spec/turtle/test-13.ttl +7 -0
  205. data/spec/turtle/test-14.out +10000 -0
  206. data/spec/turtle/test-14.ttl +10002 -0
  207. data/spec/turtle/test-15.out +10000 -0
  208. data/spec/turtle/test-15.ttl +3 -0
  209. data/spec/turtle/test-16.out +10000 -0
  210. data/spec/turtle/test-16.ttl +10002 -0
  211. data/spec/turtle/test-17.out +1 -0
  212. data/spec/turtle/test-17.ttl +6 -0
  213. data/spec/turtle/test-18.out +2 -0
  214. data/spec/turtle/test-18.ttl +9 -0
  215. data/spec/turtle/test-19.out +1 -0
  216. data/spec/turtle/test-19.ttl +4 -0
  217. data/spec/turtle/test-20.out +2 -0
  218. data/spec/turtle/test-20.ttl +6 -0
  219. data/spec/turtle/test-21.out +3 -0
  220. data/spec/turtle/test-21.ttl +4 -0
  221. data/spec/turtle/test-22.out +3 -0
  222. data/spec/turtle/test-22.ttl +4 -0
  223. data/spec/turtle/test-23.out +1 -0
  224. data/spec/turtle/test-23.ttl +3 -0
  225. data/spec/turtle/test-24.out +2 -0
  226. data/spec/turtle/test-24.ttl +3 -0
  227. data/spec/turtle/test-25.out +7 -0
  228. data/spec/turtle/test-25.ttl +14 -0
  229. data/spec/turtle/test-26.out +1 -0
  230. data/spec/turtle/test-26.ttl +4 -0
  231. data/spec/turtle/test-27.out +1 -0
  232. data/spec/turtle/test-27.ttl +5 -0
  233. data/spec/turtle/test-28-out.ttl +6 -0
  234. data/spec/turtle/test-28.out +22 -0
  235. data/spec/turtle/test-28.ttl +22 -0
  236. data/spec/turtle/test-29.out +1 -0
  237. data/spec/turtle/test-29.ttl +1 -0
  238. data/spec/turtle/test-30.out +5 -0
  239. data/spec/turtle/test-30.ttl +12 -0
  240. data/spec/turtle_spec.rb +64 -0
  241. data/spec/uriref_spec.rb +74 -34
  242. data/test/n3_tests/rdflib/n3-writer-teset-26.n3 +31 -0
  243. data/test/n3_tests/rdflib/n3-writer-teset-26.nt +14 -0
  244. data/test/rdf_tests/xml-literal-mixed.nt +1 -2
  245. metadata +278 -39
  246. data/lib/rdf_context/n3_grammar.rb +0 -2171
  247. data/test/perf_test/test.rb +0 -11
  248. data/test/perf_test/tommorris.rdf +0 -2267
@@ -12,8 +12,8 @@ module RdfContext
12
12
  ##
13
13
  # Creates a new triple directly from the intended subject, predicate, and object.
14
14
  #
15
- # Any or all of _subject_, _predicate_ or _object_ may be nil, to create a triple patern.
16
- # A patern may not be added to a graph.
15
+ # Any or all of _subject_, _predicate_ or _object_ may be nil, to create a triple pattern.
16
+ # A pattern may not be added to a graph.
17
17
  #
18
18
  # ==== Example
19
19
  # Triple.new(BNode.new, URIRef.new("http://xmlns.com/foaf/0.1/knows"), BNode.new) # => results in the creation of a new triple and returns it
@@ -21,24 +21,24 @@ module RdfContext
21
21
  # @param [URIRef, BNode] subject:: the subject of the triple
22
22
  # @param [URIRef] predicate:: the predicate of the triple
23
23
  # @param [URIRef, BNode, Literal, TypedLiteral] object:: the object of the triple
24
- # @return [Triple]:: An array of the triples (leaky abstraction? consider returning the graph instead)
24
+ # @return [Triple]:: Generated triple
25
25
  # @raise [Error]:: Checks parameter types and raises if they are incorrect.
26
26
  #
27
27
  # @author Tom Morris
28
28
  def initialize (subject, predicate, object)
29
- @subject = self.class.coerce_subject(subject)
29
+ @subject = self.class.coerce_node(subject)
30
30
  @predicate = self.class.coerce_predicate(predicate)
31
- @object = self.class.coerce_object(object)
32
- @patern = subject.nil? || predicate.nil? || object.nil?
31
+ @object = self.class.coerce_node(object)
32
+ @pattern = subject.nil? || predicate.nil? || object.nil?
33
33
  end
34
34
 
35
- def is_patern?
36
- @patern
35
+ def is_pattern?
36
+ @pattern
37
37
  end
38
38
 
39
39
  # Serialize Triple to N3
40
40
  def to_n3
41
- raise RdfException.new("Can't serialize patern triple") if is_patern?
41
+ raise RdfException.new("Can't serialize pattern triple '#{@subject.inspect}, #{@predicate.inspect}, #{@object.inspect}'") if is_pattern?
42
42
  @subject.to_ntriples + " " + @predicate.to_ntriples + " " + @object.to_ntriples + " ."
43
43
  end
44
44
  alias_method :to_ntriples, :to_n3
@@ -55,7 +55,7 @@ module RdfContext
55
55
  end
56
56
 
57
57
  # Two triples are equal if their of their subjects, predicates and objects are equal.
58
- # Or self or other is a patern and subject, predicate, object matches
58
+ # Or self or other is a pattern and subject, predicate, object matches
59
59
  def eql? (other)
60
60
  other.is_a?(Triple) &&
61
61
  (other.subject == self.subject || other.subject.nil? || self.subject.nil?) &&
@@ -67,13 +67,19 @@ module RdfContext
67
67
 
68
68
  # Clone triple, keeping references to literals and URIRefs, but cloning BNodes
69
69
  def clone
70
- raise RdfException.new("Can't clone patern triple") if is_patern?
70
+ raise RdfException.new("Can't clone pattern triple") if is_pattern?
71
71
  s = subject.is_a?(BNode) ? subject.clone : subject
72
72
  p = predicate.is_a?(BNode) ? predicate.clone : predicate
73
73
  o = object.is_a?(BNode) ? object.clone : object
74
74
  Triple.new(subject, predicate, object)
75
75
  end
76
76
 
77
+ # Validate that this triple is legal RDF, not extended for Notation-3
78
+ def validate_rdf
79
+ raise InvalidNode, "Triple has illegal RDF subject #{subject.inspect}" unless subject.is_a?(URIRef) || subject.is_a?(BNode)
80
+ raise InvalidPredicate, "Triple has illegal RDF predicate #{predicate.inspect}" unless predicate.is_a?(URIRef)
81
+ end
82
+
77
83
  # For indexes
78
84
  def hash
79
85
  [subject, predicate, object].hash
@@ -81,25 +87,6 @@ module RdfContext
81
87
 
82
88
  protected
83
89
 
84
- # Coerce a subject to the appropriate RdfContext type.
85
- #
86
- # @param[URI, URIRef, String] subject:: If a String looks like a URI, a URI is created, otherwise a BNode.
87
- # @raise[InvalidSubject]:: If subject can't be intuited.
88
- def self.coerce_subject(subject)
89
- case subject
90
- when Addressable::URI
91
- URIRef.new(subject.to_s)
92
- when URIRef, BNode
93
- subject
94
- when nil
95
- subject
96
- when /^\w+:\/\/\S+/, /^file:\S+/ # does it smell like a URI?
97
- URIRef.new(subject)
98
- else
99
- raise InvalidSubject, "Subject is not of a known class (#{subject.class}: #{subject.inspect})"
100
- end
101
- end
102
-
103
90
  # Coerce a predicate to the appropriate RdfContext type.
104
91
  #
105
92
  # @param[URI, URIRef, String] predicate:: If a String looks like a URI, a URI is created
@@ -108,7 +95,7 @@ module RdfContext
108
95
  case predicate
109
96
  when Addressable::URI
110
97
  URIRef.new(predicate.to_s)
111
- when URIRef
98
+ when URIRef, BNode
112
99
  predicate
113
100
  when String
114
101
  URIRef.new predicate
@@ -118,31 +105,29 @@ module RdfContext
118
105
  raise InvalidPredicate, "Predicate should be a URI"
119
106
  end
120
107
  rescue ParserException => e
121
- raise InvalidPredicate, "Couldn't make a URIRef: #{e.message}"
108
+ raise InvalidPredicate, "#{predicate.class}: #{predicate.inspect} is not a valid predicate"
122
109
  end
123
110
 
124
- # Coerce a object to the appropriate RdfContext type.
111
+ # Coerce a node (subject or object) to the appropriate RdfContext type.
125
112
  #
126
113
  # @param[URI, URIRef, String, Integer, Float, BNode, Literal] object:: If a String looks like a URI, a URI is created, otherwise an untyped Literal.
127
- # @raise[InvalidObject]:: If object can't be predicate.
128
- def self.coerce_object(object)
129
- case object
114
+ # @raise[InvalidNode]:: If node can't be predicate.
115
+ def self.coerce_node(node)
116
+ case node
130
117
  when Addressable::URI
131
- URIRef.new(object.to_s)
118
+ URIRef.new(node.to_s)
132
119
  when String
133
- if object.to_s =~ /^\w+:\/\/\S+/ # does it smell like a URI?
134
- URIRef.new(object.to_s)
120
+ if node.to_s =~ /^\w+:\/\/\S+/ # does it smell like a URI?
121
+ URIRef.new(node.to_s)
135
122
  else
136
- Literal.untyped(object)
123
+ Literal.untyped(node)
137
124
  end
138
- when Integer, Float, Date
139
- Literal.build_from(object)
140
- when URIRef, BNode, Literal
141
- object
142
- when nil
143
- object
125
+ when Numeric, Date, Duration, Time, DateTime
126
+ Literal.build_from(node)
127
+ when URIRef, BNode, Literal, Graph, nil
128
+ node
144
129
  else
145
- raise InvalidObject, "#{object.class}: #{object.inspect} is not a valid object"
130
+ raise InvalidNode, "#{node.class}: #{node.inspect} is not a valid node"
146
131
  end
147
132
  end
148
133
  end
@@ -11,24 +11,31 @@ module RdfContext
11
11
  # u = URIRef.new("http://example.com")
12
12
  # u = URIRef.new("foo", u) => "http://example.com/foo"
13
13
  #
14
+ # Last argument may be an options hash to set:
15
+ # @options[:normalize]:: Normalize URI when transforming to string, defaults to true
16
+ # @options[:namespace]:: Namespace used to create this URI, useful for to_qname
14
17
  def initialize (*args)
18
+ options = args.last.is_a?(Hash) ? args.pop : { :normalize => true }
19
+ @normalize = options[:normalize]
20
+ @namespace = options[:namespace]
21
+
15
22
  args.each {|s| test_string(s)}
16
23
  if args.size == 1
17
- @uri = Addressable::URI.parse(args[0].to_s)
24
+ uri = Addressable::URI.parse(args[0].to_s)
18
25
  else
19
- @uri = Addressable::URI.join(*args.map{|s| s.to_s}.reverse)
20
- end
21
- if @uri.relative?
22
- raise ParserException, "<" + @uri.to_s + "> is a relative URI"
26
+ uri = Addressable::URI.join(*args.map{|s| s.to_s}.reverse)
23
27
  end
24
- if !@uri.to_s.match(/^javascript/).nil?
25
- raise ParserException, "Javascript pseudo-URIs are not acceptable"
26
- end
27
-
28
+
29
+ raise ParserException, "<" + uri.to_s + "> is a relative URI" if uri.relative?
30
+
28
31
  # Unique URI through class hash to ensure that URIRefs can be easily compared
29
32
  @@uri_hash ||= {}
30
- @@uri_hash[@uri.to_s] ||= @uri.freeze
31
- @uri = @@uri_hash[@uri.to_s]
33
+ @uri = @@uri_hash["#{uri}#{@normalize}"] ||= begin
34
+ # Special case if URI has no path, and the authority ends with a '#'
35
+ uri = Addressable::URI.parse($1) if @normalize && uri.to_s.match(/^(.*)\#$/)
36
+
37
+ @normalize ? uri.normalize : uri
38
+ end.freeze
32
39
  end
33
40
 
34
41
  # Create a URI, either by appending a fragment, or using the input URI
@@ -40,7 +47,9 @@ module RdfContext
40
47
  # short_name of URI for creating QNames.
41
48
  # "#{base]{#short_name}}" == uri
42
49
  def short_name
43
- @short_name ||= if @uri.fragment()
50
+ @short_name ||= if @namespace
51
+ self.to_s.sub(@namespace.uri.to_s, "")
52
+ elsif @uri.fragment()
44
53
  @uri.fragment()
45
54
  elsif @uri.path.split("/").last.class == String and @uri.path.split("/").last.length > 0
46
55
  @uri.path.split("/").last
@@ -53,14 +62,14 @@ module RdfContext
53
62
  # "#{base]{#short_name}}" == uri
54
63
  def base
55
64
  @base ||= begin
56
- uri_base = @uri.to_s
65
+ uri_base = self.to_s
57
66
  sn = short_name.to_s
58
67
  uri_base[0, uri_base.length - sn.length]
59
68
  end
60
69
  end
61
70
 
62
71
  def eql?(other)
63
- @uri.to_s == other.to_s
72
+ self.to_s == other.to_s
64
73
  end
65
74
  alias_method :==, :eql?
66
75
 
@@ -68,24 +77,26 @@ module RdfContext
68
77
  def hash; to_s.hash; end
69
78
 
70
79
  def to_s
71
- @uri.to_s
80
+ @to_s ||= @uri.to_s
72
81
  end
73
82
 
74
83
  def to_n3
75
- "<" + @uri.to_s + ">"
84
+ "<" + self.to_s + ">"
76
85
  end
77
86
  alias_method :to_ntriples, :to_n3
78
87
 
79
88
  # Output URI as QName using URI binding
80
89
  def to_qname(uri_binding = {})
81
- "#{namespace(uri_binding).prefix}:#{self.short_name}"
90
+ ns = namespace(uri_binding)
91
+ sn = self.to_s.sub(ns.uri.to_s, "")
92
+ "#{ns.prefix}:#{sn}"
82
93
  end
83
94
 
84
95
  def namespace(uri_binding = {})
85
96
  @namespace ||= begin
86
- ns = uri_binding[self.base]
87
- raise RdfException, "Couldn't find namespace for #{@uri}" unless ns
88
- ns
97
+ uri = uri_binding.keys.detect {|u| self.to_s.index(u) == 0 }
98
+ raise RdfException, "Couldn't find namespace for #{@uri}" unless uri
99
+ uri_binding[uri]
89
100
  end
90
101
  end
91
102
 
@@ -95,9 +106,10 @@ module RdfContext
95
106
 
96
107
  # Output URI as resource reference for RDF/XML
97
108
  def xml_args
98
- [{"rdf:resource" => @uri.to_s}]
109
+ [{"rdf:resource" => self.to_s}]
99
110
  end
100
111
 
112
+ protected
101
113
  def test_string (string)
102
114
  string.to_s.each_byte do |b|
103
115
  if b >= 0 and b <= 31
@@ -105,10 +117,5 @@ module RdfContext
105
117
  end
106
118
  end
107
119
  end
108
-
109
- # def load_graph
110
- # get = Net::HTTP.start(@uri.host, @uri.port) {|http| [:xml, http.get(@uri.path)] }
111
- # return RdfContext::RdfXmlParser.new(get[1].body, @uri.to_s).graph if get[0] == :xml
112
- # end
113
120
  end
114
121
  end
@@ -0,0 +1,59 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ describe "AggregateGraph" do
4
+ before(:all) do
5
+ @store = MemoryStore.new(@identifier)
6
+ @graph1 = Graph.new(:store => @store)
7
+ @graph2 = Graph.new(:store => @store)
8
+ @graph3 = Graph.new(:store => @store)
9
+
10
+ @graph1.parse(%(
11
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
12
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
13
+ @prefix : <http://test/> .
14
+ :foo a rdfs:Class.
15
+ :bar :d :c.
16
+ :a :d :c.
17
+ ), "http://test/")
18
+
19
+ @graph2.parse(%(
20
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
21
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
22
+ @prefix : <http://test/> .
23
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
24
+ :foo a rdfs:Resource.
25
+ :bar rdfs:isDefinedBy [ a log:Formula ].
26
+ :a :d :e.
27
+ ), "http://test/")
28
+
29
+ @graph3.parse(%(
30
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
31
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
32
+ @prefix log: <http://www.w3.org/2000/10/swap/log#>.
33
+ @prefix : <http://test/> .
34
+ <> a log:N3Document.
35
+ ), "http://test/")
36
+ end
37
+
38
+ subject { AggregateGraph.new(@graph1, @graph2, @graph3)}
39
+
40
+ it "should return types" do
41
+ subject.triples(Triple.new(nil, RDF_TYPE, nil)).length.should == 4
42
+ end
43
+
44
+ it "should return subjects" do
45
+ subject.triples(Triple.new("http://test/bar", nil, nil)).length.should == 2
46
+ end
47
+
48
+ it "should return predicates" do
49
+ subject.triples(Triple.new(nil, "http://test/d", nil)).length.should == 3
50
+ end
51
+
52
+ it "should have size sum of graphs" do
53
+ subject.size.should == @graph1.size + @graph2.size + @graph3.size
54
+ end
55
+
56
+ it "should contain a triple" do
57
+ subject.contains?(Triple.new("http://test/foo", RDF_TYPE, RDFS_NS.Resource)).should be_true
58
+ end
59
+ end
@@ -56,7 +56,7 @@ describe "ConjunctiveGraph" do
56
56
  it "should parse into new context" do
57
57
  n3_string = "<http://example.org/> <http://xmlns.com/foaf/0.1/name> \"Gregg Kellogg\" . "
58
58
  graph = subject.parse(n3_string, "http://foo.bar", :type => :n3)
59
- graph.identifier.should == "http://foo.bar"
59
+ graph.identifier.should == "http://foo.bar/"
60
60
  subject.size.should == 1
61
61
  t = subject.triples.first
62
62
  t.subject.to_s.should == "http://example.org/"
@@ -0,0 +1,32 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ include RdfContext
3
+
4
+ describe "N3 parser" do
5
+ describe "w3c cwm tests" do
6
+ require 'rdf_helper'
7
+
8
+ def self.test_cases
9
+ RdfHelper::TestCase.test_cases(CWM_TEST, SWAP_DIR) rescue []
10
+ end
11
+
12
+ # Negative parser tests should raise errors.
13
+ test_cases.each do |t|
14
+ #next unless t.about.uri.to_s =~ /rdfms-rdf-names-use/
15
+ #next unless t.name =~ /11/
16
+ #puts t.inspect
17
+ specify "test #{t.name}: " + (t.description || "#{t.inputDocument} against #{t.outputDocument}") do
18
+ begin
19
+ t.run_test do |rdf_string, parser|
20
+ parser.parse(rdf_string, t.about.uri.to_s, :strict => true, :debug => [])
21
+ end
22
+ rescue #Spec::Expectations::ExpectationNotMetError => e
23
+ if t.status == "pending"
24
+ pending("Formulae not supported") { raise }
25
+ else
26
+ raise
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -188,6 +188,43 @@ HERE
188
188
  xml.should include("Ralph Swick")
189
189
  xml.should include("Manu Sporny")
190
190
  end
191
+
192
+ it "should find bnodes" do
193
+ subject.bnodes.length.should == 2
194
+ end
195
+
196
+ it "should find predicate bnodes" do
197
+ subject.allow_n3 = true
198
+ c = BNode.new("c")
199
+ subject << Triple.new(URIRef.new("http://foo"), c, Literal.untyped("BNode predicate"))
200
+ subject.bnodes.length.should == 3
201
+ subject.bnodes.should include(c)
202
+ end
203
+ end
204
+
205
+ describe "with namespaces" do
206
+ subject { Graph.new(:store => ListStore.new) }
207
+
208
+ it "should use namespace with trailing slash" do
209
+ ns = Namespace.new("http://www.example.com/ontologies/test/", "test")
210
+ subject.bind(ns)
211
+ subject.add_triple("http://example.com", ns.hasChallenge, "Interesting Title")
212
+ subject.to_rdfxml.should =~ /<test:hasChallenge/
213
+ end
214
+
215
+ it "should use namespace with trailing #" do
216
+ ns = Namespace.new("http://www.example.com/ontologies/test#", "test")
217
+ subject.bind(ns)
218
+ subject.add_triple("http://example.com", ns.hasChallenge, "Interesting Title")
219
+ subject.to_rdfxml.should =~ /<test:hasChallenge/
220
+ end
221
+
222
+ it "should use namespace with trailing word" do
223
+ ns = Namespace.new("http://www.example.com/ontologies/test", "test")
224
+ subject.bind(ns)
225
+ subject.add_triple("http://example.com", ns.hasChallenge, "Interesting Title")
226
+ subject.to_rdfxml.should =~ /<test:hasChallenge/
227
+ end
191
228
  end
192
229
 
193
230
  describe "with triples" do
@@ -307,6 +344,41 @@ HERE
307
344
  subject.to_rdfxml.should be_equivalent_xml(rdfxml)
308
345
  end
309
346
  end
347
+
348
+ describe "rdf:_n sequences" do
349
+ subject {
350
+ g = Graph.new(:store => ListStore.new)
351
+ g.add_triple(@ex.Seq, RDF_TYPE, RDF_NS.Seq)
352
+ g.add_triple(@ex.Seq, RDF_NS._1, @ex.john)
353
+ g.add_triple(@ex.Seq, RDF_NS._2, @ex.jane)
354
+ g.add_triple(@ex.Seq, RDF_NS._3, @ex.rick)
355
+ g.bind(@ex)
356
+ g
357
+ }
358
+
359
+ it "should return object list" do
360
+ subject.seq(@ex.Seq).should == [@ex.john, @ex.jane, @ex.rick]
361
+ end
362
+ end
363
+
364
+ describe "rdf:first/rdf:rest sequences" do
365
+ subject {
366
+ a, b = BNode.new("a"), BNode.new("b"), BNode.new("c")
367
+ g = Graph.new(:store => ListStore.new)
368
+ g.add_triple(@ex.List, RDF_NS.first, @ex.john)
369
+ g.add_triple(@ex.List, RDF_NS.rest, a)
370
+ g.add_triple(a, RDF_NS.first, @ex.jane)
371
+ g.add_triple(a, RDF_NS.rest, b)
372
+ g.add_triple(b, RDF_NS.first, @ex.rick)
373
+ g.add_triple(b, RDF_NS.rest, RDF_NS.nil)
374
+ g.bind(@ex)
375
+ g
376
+ }
377
+
378
+ it "should return object list" do
379
+ subject.seq(@ex.List).should == [@ex.john, @ex.jane, @ex.rick]
380
+ end
381
+ end
310
382
  end
311
383
 
312
384
  describe "which are merged" do
@@ -335,9 +407,9 @@ HERE
335
407
  g.add_triple(BNode.new("a1", @bn_ctx), URIRef.new("http://xmlns.com/foaf/0.1/knows"), BNode.new("a2", @bn_ctx))
336
408
  g.merge!(subject)
337
409
  g.size.should == 2
338
- s1, s2 = g.triples.map(&:subject)
339
- p1, p2 = g.triples.map(&:predicate)
340
- o1, o2 = g.triples.map(&:object)
410
+ s1, s2 = g.triples.map {|s| s.subject}
411
+ p1, p2 = g.triples.map {|p| p.predicate}
412
+ o1, o2 = g.triples.map {|o| o.object}
341
413
  s1.should_not == s2
342
414
  p1.should == p1
343
415
  o1.should_not == o2
@@ -380,6 +452,17 @@ HERE
380
452
  subject.should == f
381
453
  end
382
454
 
455
+ it "should be true for equivalent graphs with different BNode predicates" do
456
+ subject.allow_n3 = true
457
+ subject.add_triple(@ex.a, BNode.new("knows", @bn_ctx), @ex.b)
458
+ subject.add_triple(@ex.b, BNode.new("knows", @bn_ctx), @ex.a)
459
+
460
+ f = Graph.new(:store => s, :identifier => subject.identifier, :allow_n3 => true)
461
+ f.add_triple(@ex.a, BNode.new("knows", @bn_ctx), @ex.b)
462
+ f.add_triple(@ex.b, BNode.new("knows", @bn_ctx), @ex.a)
463
+ subject.should == f
464
+ end
465
+
383
466
  it "should be true for graphs with literals" do
384
467
  subject.add_triple(@ex.a, @foaf.knows, Literal.untyped("foo"))
385
468
 
@@ -390,4 +473,32 @@ HERE
390
473
  end
391
474
  end
392
475
  end
476
+
477
+ describe "Bnode Permutation matching" do
478
+ {
479
+ "a1" => %w(aA),
480
+ "a1b1" => %w(aAbB aBbA),
481
+ "a2b1" => %w(aAbB),
482
+ "a2b2c1" => %w(aAbBcC aBbAcC),
483
+ "a2b2c3d3e1f4" => %w(
484
+ aAbBcCdDeEfF
485
+ aBbAcCdDeEfF
486
+ aAbBcDdCeEfF
487
+ aBbAcDdCeEfF
488
+ )
489
+ }.each_pair do |list, perms|
490
+ it "should permute #{list} as #{perms.to_sentence}" do
491
+ h_source = list.scan(/\w\d/).inject({}) {|hash, ad| hash[ad[0,1]] = ad[1,1]; hash}
492
+ h_dest = list.upcase.scan(/\w\d/).inject({}) {|hash, ad| hash[ad[0,1]] = ad[1,1]; hash}
493
+ subject.send(:bnode_permutations, h_source, h_dest) do |hash|
494
+ perm = ""
495
+ #puts hash.inspect
496
+ hash.keys.sort.each {|k| perm << "#{k}#{hash[k]}"}
497
+ perms.should include(perm)
498
+ perms -= [perm]
499
+ end
500
+ perms.should be_empty
501
+ end
502
+ end
503
+ end
393
504
  end