sparql 3.0.2 → 3.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +189 -74
  3. data/UNLICENSE +1 -1
  4. data/VERSION +1 -1
  5. data/bin/sparql +44 -24
  6. data/lib/rack/sparql.rb +1 -1
  7. data/lib/rack/sparql/conneg.rb +3 -3
  8. data/lib/sinatra/sparql.rb +5 -5
  9. data/lib/sparql.rb +17 -16
  10. data/lib/sparql/algebra.rb +15 -23
  11. data/lib/sparql/algebra/aggregate.rb +4 -4
  12. data/lib/sparql/algebra/evaluatable.rb +2 -2
  13. data/lib/sparql/algebra/expression.rb +70 -44
  14. data/lib/sparql/algebra/extensions.rb +181 -34
  15. data/lib/sparql/algebra/operator.rb +44 -23
  16. data/lib/sparql/algebra/operator/abs.rb +2 -2
  17. data/lib/sparql/algebra/operator/add.rb +3 -3
  18. data/lib/sparql/algebra/operator/alt.rb +4 -4
  19. data/lib/sparql/algebra/operator/and.rb +7 -7
  20. data/lib/sparql/algebra/operator/asc.rb +3 -3
  21. data/lib/sparql/algebra/operator/ask.rb +4 -14
  22. data/lib/sparql/algebra/operator/avg.rb +13 -4
  23. data/lib/sparql/algebra/operator/base.rb +10 -10
  24. data/lib/sparql/algebra/operator/bgp.rb +2 -2
  25. data/lib/sparql/algebra/operator/bnode.rb +5 -5
  26. data/lib/sparql/algebra/operator/bound.rb +3 -3
  27. data/lib/sparql/algebra/operator/ceil.rb +2 -2
  28. data/lib/sparql/algebra/operator/clear.rb +3 -3
  29. data/lib/sparql/algebra/operator/coalesce.rb +3 -13
  30. data/lib/sparql/algebra/operator/compare.rb +8 -8
  31. data/lib/sparql/algebra/operator/concat.rb +4 -4
  32. data/lib/sparql/algebra/operator/construct.rb +4 -14
  33. data/lib/sparql/algebra/operator/contains.rb +2 -2
  34. data/lib/sparql/algebra/operator/copy.rb +3 -3
  35. data/lib/sparql/algebra/operator/count.rb +3 -3
  36. data/lib/sparql/algebra/operator/create.rb +3 -3
  37. data/lib/sparql/algebra/operator/dataset.rb +6 -17
  38. data/lib/sparql/algebra/operator/datatype.rb +1 -1
  39. data/lib/sparql/algebra/operator/day.rb +1 -1
  40. data/lib/sparql/algebra/operator/delete.rb +9 -7
  41. data/lib/sparql/algebra/operator/delete_data.rb +3 -3
  42. data/lib/sparql/algebra/operator/delete_where.rb +6 -6
  43. data/lib/sparql/algebra/operator/desc.rb +1 -1
  44. data/lib/sparql/algebra/operator/describe.rb +3 -13
  45. data/lib/sparql/algebra/operator/distinct.rb +4 -14
  46. data/lib/sparql/algebra/operator/divide.rb +1 -1
  47. data/lib/sparql/algebra/operator/drop.rb +3 -3
  48. data/lib/sparql/algebra/operator/encode_for_uri.rb +3 -3
  49. data/lib/sparql/algebra/operator/equal.rb +2 -2
  50. data/lib/sparql/algebra/operator/exists.rb +5 -5
  51. data/lib/sparql/algebra/operator/exprlist.rb +3 -13
  52. data/lib/sparql/algebra/operator/extend.rb +19 -18
  53. data/lib/sparql/algebra/operator/filter.rb +6 -16
  54. data/lib/sparql/algebra/operator/floor.rb +2 -2
  55. data/lib/sparql/algebra/operator/graph.rb +6 -17
  56. data/lib/sparql/algebra/operator/greater_than.rb +5 -5
  57. data/lib/sparql/algebra/operator/greater_than_or_equal.rb +5 -5
  58. data/lib/sparql/algebra/operator/group.rb +25 -25
  59. data/lib/sparql/algebra/operator/group_concat.rb +6 -6
  60. data/lib/sparql/algebra/operator/hours.rb +1 -1
  61. data/lib/sparql/algebra/operator/if.rb +5 -15
  62. data/lib/sparql/algebra/operator/in.rb +4 -14
  63. data/lib/sparql/algebra/operator/insert.rb +7 -5
  64. data/lib/sparql/algebra/operator/insert_data.rb +3 -3
  65. data/lib/sparql/algebra/operator/iri.rb +1 -1
  66. data/lib/sparql/algebra/operator/is_blank.rb +1 -1
  67. data/lib/sparql/algebra/operator/is_iri.rb +1 -1
  68. data/lib/sparql/algebra/operator/is_literal.rb +1 -1
  69. data/lib/sparql/algebra/operator/is_numeric.rb +1 -1
  70. data/lib/sparql/algebra/operator/join.rb +12 -10
  71. data/lib/sparql/algebra/operator/lang.rb +1 -1
  72. data/lib/sparql/algebra/operator/lang_matches.rb +3 -3
  73. data/lib/sparql/algebra/operator/lcase.rb +2 -2
  74. data/lib/sparql/algebra/operator/left_join.rb +19 -12
  75. data/lib/sparql/algebra/operator/less_than.rb +5 -5
  76. data/lib/sparql/algebra/operator/less_than_or_equal.rb +5 -5
  77. data/lib/sparql/algebra/operator/load.rb +3 -3
  78. data/lib/sparql/algebra/operator/max.rb +13 -4
  79. data/lib/sparql/algebra/operator/md5.rb +1 -1
  80. data/lib/sparql/algebra/operator/min.rb +13 -4
  81. data/lib/sparql/algebra/operator/minus.rb +12 -11
  82. data/lib/sparql/algebra/operator/minutes.rb +1 -1
  83. data/lib/sparql/algebra/operator/modify.rb +4 -4
  84. data/lib/sparql/algebra/operator/month.rb +1 -1
  85. data/lib/sparql/algebra/operator/move.rb +3 -3
  86. data/lib/sparql/algebra/operator/multiply.rb +1 -1
  87. data/lib/sparql/algebra/operator/negate.rb +1 -1
  88. data/lib/sparql/algebra/operator/not.rb +1 -1
  89. data/lib/sparql/algebra/operator/not_equal.rb +2 -2
  90. data/lib/sparql/algebra/operator/notexists.rb +4 -4
  91. data/lib/sparql/algebra/operator/notin.rb +4 -14
  92. data/lib/sparql/algebra/operator/notoneof.rb +5 -6
  93. data/lib/sparql/algebra/operator/now.rb +1 -1
  94. data/lib/sparql/algebra/operator/or.rb +7 -7
  95. data/lib/sparql/algebra/operator/order.rb +6 -16
  96. data/lib/sparql/algebra/operator/path.rb +6 -5
  97. data/lib/sparql/algebra/operator/path_opt.rb +16 -16
  98. data/lib/sparql/algebra/operator/path_plus.rb +8 -8
  99. data/lib/sparql/algebra/operator/path_star.rb +4 -4
  100. data/lib/sparql/algebra/operator/plus.rb +3 -3
  101. data/lib/sparql/algebra/operator/prefix.rb +10 -10
  102. data/lib/sparql/algebra/operator/project.rb +4 -14
  103. data/lib/sparql/algebra/operator/rand.rb +1 -1
  104. data/lib/sparql/algebra/operator/reduced.rb +4 -14
  105. data/lib/sparql/algebra/operator/regex.rb +6 -6
  106. data/lib/sparql/algebra/operator/replace.rb +4 -4
  107. data/lib/sparql/algebra/operator/reverse.rb +4 -4
  108. data/lib/sparql/algebra/operator/round.rb +2 -2
  109. data/lib/sparql/algebra/operator/same_term.rb +8 -5
  110. data/lib/sparql/algebra/operator/sample.rb +11 -4
  111. data/lib/sparql/algebra/operator/seconds.rb +1 -1
  112. data/lib/sparql/algebra/operator/seq.rb +5 -6
  113. data/lib/sparql/algebra/operator/sequence.rb +4 -4
  114. data/lib/sparql/algebra/operator/sha1.rb +1 -1
  115. data/lib/sparql/algebra/operator/sha256.rb +1 -1
  116. data/lib/sparql/algebra/operator/sha384.rb +1 -1
  117. data/lib/sparql/algebra/operator/sha512.rb +1 -1
  118. data/lib/sparql/algebra/operator/slice.rb +4 -14
  119. data/lib/sparql/algebra/operator/str.rb +1 -1
  120. data/lib/sparql/algebra/operator/strafter.rb +2 -2
  121. data/lib/sparql/algebra/operator/strbefore.rb +2 -2
  122. data/lib/sparql/algebra/operator/strdt.rb +2 -2
  123. data/lib/sparql/algebra/operator/strends.rb +2 -2
  124. data/lib/sparql/algebra/operator/strlang.rb +2 -2
  125. data/lib/sparql/algebra/operator/strlen.rb +2 -2
  126. data/lib/sparql/algebra/operator/strstarts.rb +2 -2
  127. data/lib/sparql/algebra/operator/struuid.rb +1 -1
  128. data/lib/sparql/algebra/operator/substr.rb +4 -4
  129. data/lib/sparql/algebra/operator/subtract.rb +1 -1
  130. data/lib/sparql/algebra/operator/sum.rb +6 -4
  131. data/lib/sparql/algebra/operator/table.rb +3 -3
  132. data/lib/sparql/algebra/operator/timezone.rb +1 -1
  133. data/lib/sparql/algebra/operator/tz.rb +1 -1
  134. data/lib/sparql/algebra/operator/ucase.rb +2 -2
  135. data/lib/sparql/algebra/operator/union.rb +9 -8
  136. data/lib/sparql/algebra/operator/update.rb +4 -4
  137. data/lib/sparql/algebra/operator/using.rb +4 -4
  138. data/lib/sparql/algebra/operator/uuid.rb +1 -1
  139. data/lib/sparql/algebra/operator/with.rb +7 -7
  140. data/lib/sparql/algebra/operator/year.rb +1 -1
  141. data/lib/sparql/algebra/query.rb +2 -2
  142. data/lib/sparql/algebra/update.rb +2 -2
  143. data/lib/sparql/algebra/version.rb +1 -1
  144. data/lib/sparql/extensions.rb +11 -17
  145. data/lib/sparql/grammar.rb +113 -13
  146. data/lib/sparql/grammar/meta.rb +2340 -907
  147. data/lib/sparql/grammar/parser11.rb +57 -52
  148. data/lib/sparql/grammar/terminals11.rb +2 -0
  149. data/lib/sparql/results.rb +73 -46
  150. data/lib/sparql/version.rb +1 -1
  151. metadata +46 -63
@@ -6,8 +6,8 @@ module SPARQL::Grammar
6
6
  ##
7
7
  # A parser for the SPARQL 1.1 grammar.
8
8
  #
9
- # @see http://www.w3.org/TR/sparql11-query/#grammar
10
- # @see http://en.wikipedia.org/wiki/LR_parser
9
+ # @see https://www.w3.org/TR/sparql11-query/#grammar
10
+ # @see https://en.wikipedia.org/wiki/LR_parser
11
11
  class Parser
12
12
  include SPARQL::Grammar::Meta
13
13
  include SPARQL::Grammar::Terminals
@@ -586,7 +586,7 @@ module SPARQL::Grammar
586
586
  production(:GroupGraphPatternSub) do |input, data, callback|
587
587
  debug("GroupGraphPatternSub") {"q #{data[:query].inspect}"}
588
588
 
589
- res = case data[:query].length
589
+ res = case Array(data[:query]).length
590
590
  when 0 then SPARQL::Algebra::Operator::BGP.new
591
591
  when 1 then data[:query].first
592
592
  when 2
@@ -701,9 +701,9 @@ module SPARQL::Grammar
701
701
  end
702
702
  end
703
703
 
704
- # [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
704
+ # [60] Bind ::= 'BIND' '(' (Expression || EmbTP) 'AS' Var ')'
705
705
  production(:Bind) do |input, data, callback|
706
- add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
706
+ add_prod_datum :extend, [(data[:Expression] || data[:pattern]).unshift(data[:Var].first)]
707
707
  end
708
708
 
709
709
  # [61] InlineData ::= 'VALUES' DataBlock
@@ -867,13 +867,21 @@ module SPARQL::Grammar
867
867
  add_prod_datum(:path, data[:path])
868
868
  end
869
869
 
870
- # [80] Object ::= GraphNode
870
+ # [177] AnnotationPattern ::= '{|' PropertyListNotEmpty '|}'
871
+ start_production(:AnnotationPattern) do |input, data, callback|
872
+ data[:TriplesNode] = prod_data[:pattern].first
873
+ end
874
+ production(:AnnotationPattern) do |input, data, callback|
875
+ add_prod_datum(:pattern, data[:pattern])
876
+ end
877
+
878
+ # [80] Object ::= GraphNode | EmbTP
871
879
  production(:Object) do |input, data, callback|
872
- object = data[:VarOrTerm] || data[:TriplesNode] || data[:GraphNode]
880
+ object = data[:GraphNode] || data[:EmbTP]
881
+ add_prod_datum(:pattern, data[:pattern])
873
882
  if object
874
883
  if prod_data[:Verb]
875
884
  add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
876
- add_prod_datum(:pattern, data[:pattern])
877
885
  elsif prod_data[:VerbPath]
878
886
  add_prod_datum(:path,
879
887
  SPARQL::Algebra::Expression(:path,
@@ -1104,6 +1112,11 @@ module SPARQL::Grammar
1104
1112
  data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
1105
1113
  end
1106
1114
 
1115
+ # [106s] VarOrTermOrEmbTP ::= Var | GraphTerm | EmbTP
1116
+ production(:VarOrTermOrEmbTP) do |input, data, callback|
1117
+ data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
1118
+ end
1119
+
1107
1120
  # [107] VarOrIri ::= Var | iri
1108
1121
  production(:VarOrIri) do |input, data, callback|
1109
1122
  data.values.each {|v| add_prod_datum(:VarOrIri, v)}
@@ -1119,6 +1132,22 @@ module SPARQL::Grammar
1119
1132
  data[:NIL])
1120
1133
  end
1121
1134
 
1135
+ # [174] EmbTP ::= '<<' EmbSubjectOrObject Verb EmbSubjectOrObject '>>'
1136
+ production(:EmbTP) do |input, data, callback|
1137
+ subject, object = data[:EmbSubjectOrObject]
1138
+ predicate = data[:Verb]
1139
+ add_pattern(:EmbTP,
1140
+ subject: subject,
1141
+ predicate: predicate,
1142
+ object: object)
1143
+ end
1144
+
1145
+ # [175] EmbSubjectOrObject ::= Var | BlankNode | iri | RDFLiteral
1146
+ # | NumericLiteral | BooleanLiteral | EmbTP
1147
+ production(:EmbSubjectOrObject) do |input, data, callback|
1148
+ data.values.each {|v| add_prod_datum(:EmbSubjectOrObject, v)}
1149
+ end
1150
+
1122
1151
  # [110] Expression ::= ConditionalOrExpression
1123
1152
  production(:Expression) do |input, data, callback|
1124
1153
  add_prod_datum(:Expression, data[:Expression])
@@ -1415,7 +1444,7 @@ module SPARQL::Grammar
1415
1444
  str = lit.delete(:string)
1416
1445
  lit[:datatype] = lit.delete(:iri) if lit[:iri]
1417
1446
  lit[:language] = lit.delete(:language).last.downcase if lit[:language]
1418
- input[:literal] = RDF::Literal.new(str, lit) if str
1447
+ input[:literal] = RDF::Literal.new(str, **lit) if str
1419
1448
  end
1420
1449
  end
1421
1450
 
@@ -1458,25 +1487,19 @@ module SPARQL::Grammar
1458
1487
  # definitions.
1459
1488
  # @option options [Boolean] :validate (false)
1460
1489
  # whether to validate the parsed statements and values
1461
- # @option options [Boolean] :progress
1462
- # Show progress of parser productions
1463
- # @option options [Boolean] :debug
1464
- # Detailed debug output
1490
+ # @option options [Logger, #write, #<<] :logger
1491
+ # Record error/info/debug output
1465
1492
  # @yield [parser] `self`
1466
1493
  # @yieldparam [SPARQL::Grammar::Parser] parser
1467
1494
  # @yieldreturn [void] ignored
1468
1495
  # @return [SPARQL::Grammar::Parser]
1469
- def initialize(input = nil, options = {}, &block)
1496
+ def initialize(input = nil, **options, &block)
1470
1497
  @input = case input
1471
1498
  when IO, StringIO then input.read
1472
1499
  else input.to_s.dup
1473
1500
  end
1474
1501
  @input.encode!(Encoding::UTF_8) if @input.respond_to?(:encode!)
1475
1502
  @options = {anon_base: "b0", validate: false}.merge(options)
1476
- @options[:debug] ||= case
1477
- when options[:progress] then 2
1478
- when options[:validate] then 1
1479
- end
1480
1503
 
1481
1504
  debug("base IRI") {base_uri.inspect}
1482
1505
  debug("validate") {validate?.inspect}
@@ -1527,30 +1550,17 @@ module SPARQL::Grammar
1527
1550
  # @param [Symbol, #to_s] prod The starting production for the parser.
1528
1551
  # It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
1529
1552
  # @return [Array]
1530
- # @see http://www.w3.org/TR/sparql11-query/#sparqlAlgebra
1531
- # @see http://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
1553
+ # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
1554
+ # @see https://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
1532
1555
  def parse(prod = START)
1533
- ll1_parse(@input, prod.to_sym, @options.merge(branch: BRANCH,
1534
- first: FIRST,
1535
- follow: FOLLOW,
1536
- whitespace: WS)
1537
- ) do |context, *data|
1538
- case context
1539
- when :trace
1540
- level, lineno, depth, *args = data
1541
- message = args.to_sse
1542
- d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
1543
- str = "[#{lineno}](#{level})#{d_str}#{message}".chop
1544
- case @options[:debug]
1545
- when Array
1546
- @options[:debug] << str unless level > 2
1547
- when TrueClass
1548
- $stderr.puts str
1549
- when Integer
1550
- $stderr.puts(str) if level <= @options[:debug]
1551
- end
1552
- end
1553
- end
1556
+ ll1_parse(@input,
1557
+ prod.to_sym,
1558
+ branch: BRANCH,
1559
+ first: FIRST,
1560
+ follow: FOLLOW,
1561
+ whitespace: WS,
1562
+ **@options
1563
+ )
1554
1564
 
1555
1565
  # The last thing on the @prod_data stack is the result
1556
1566
  @result = case
@@ -1718,9 +1728,7 @@ module SPARQL::Grammar
1718
1728
 
1719
1729
  if id
1720
1730
  @vars[id] ||= begin
1721
- v = RDF::Query::Variable.new(id)
1722
- v.distinguished = distinguished
1723
- v
1731
+ RDF::Query::Variable.new(id, distinguished: distinguished)
1724
1732
  end
1725
1733
  else
1726
1734
  unless distinguished
@@ -1728,9 +1736,7 @@ module SPARQL::Grammar
1728
1736
  id = @nd_var_gen
1729
1737
  @nd_var_gen = id.succ
1730
1738
  end
1731
- v = RDF::Query::Variable.new(id)
1732
- v.distinguished = distinguished
1733
- v
1739
+ RDF::Query::Variable.new(id, distinguished: distinguished)
1734
1740
  end
1735
1741
  end
1736
1742
 
@@ -1758,7 +1764,7 @@ module SPARQL::Grammar
1758
1764
  end
1759
1765
 
1760
1766
  # Create a literal
1761
- def literal(value, options = {})
1767
+ def literal(value, **options)
1762
1768
  options = options.dup
1763
1769
  # Internal representation is to not use xsd:string, although it could arguably go the other way.
1764
1770
  options.delete(:datatype) if options[:datatype] == RDF::XSD.string
@@ -1767,7 +1773,7 @@ module SPARQL::Grammar
1767
1773
  "options: #{options.inspect}, " +
1768
1774
  "validate: #{validate?.inspect}, "
1769
1775
  end
1770
- RDF::Literal.new(value, options.merge(validate: validate?))
1776
+ RDF::Literal.new(value, validate: validate?, **options)
1771
1777
  end
1772
1778
 
1773
1779
  # Take collection of objects and create RDF Collection using rdf:first, rdf:rest and rdf:nil
@@ -1798,7 +1804,7 @@ module SPARQL::Grammar
1798
1804
  #
1799
1805
  # @param [String] production Production generating pattern
1800
1806
  # @param [Hash{Symbol => Object}] options
1801
- def add_pattern(production, options)
1807
+ def add_pattern(production, **options)
1802
1808
  progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
1803
1809
  triple = {}
1804
1810
  options.each_pair do |r, v|
@@ -1880,8 +1886,7 @@ module SPARQL::Grammar
1880
1886
  avf.first
1881
1887
  else
1882
1888
  # Allocate a temporary variable for this function, and retain the mapping for outside the group
1883
- av = RDF::Query::Variable.new(".#{agg}")
1884
- av.distinguished = false
1889
+ av = RDF::Query::Variable.new(".#{agg}", distinguished: false)
1885
1890
  agg += 1
1886
1891
  aggregates << [av, function]
1887
1892
  av
@@ -110,6 +110,8 @@ module SPARQL::Grammar
110
110
  |isBLANK|isIRI|isURI|isLITERAL|isNUMERIC|sameTerm
111
111
  |true
112
112
  |false
113
+ |<<|>>
114
+ |\{\||\|\}
113
115
  |&&|!=|!|<=|>=|\^\^|\|\||[\(\),.;\[\]\{\}\+\-=<>\?\^\|\*\/a]
114
116
  )xim.freeze
115
117
 
@@ -14,28 +14,38 @@ module SPARQL
14
14
  ##
15
15
  # Generate Solutions as JSON
16
16
  # @return [String]
17
- # @see http://www.w3.org/TR/rdf-sparql-json-res/
17
+ # @see https://www.w3.org/TR/rdf-sparql-json-res/
18
18
  def to_json
19
19
  require 'json' unless defined?(::JSON)
20
-
21
- bindings = self.map do |solution|
22
- variable_names.inject({}) do |memo, n|
23
- memo.merge case s = solution[n]
24
- when RDF::URI
25
- {n => {type: "uri", value: s.to_s }}
26
- when RDF::Node
27
- {n => {type: "bnode", value: s.id }}
28
- when RDF::Literal
29
- if s.datatype?
30
- {n => {type: "typed-literal", datatype: s.datatype.to_s, value: s.to_s }}
31
- elsif s.language
32
- {n => {type: "literal", "xml:lang" => s.language.to_s, value: s.to_s }}
33
- else
34
- {n => {type: "literal", value: s.to_s }}
35
- end
20
+
21
+ format = ->(value) do
22
+ case value
23
+ when RDF::URI then {type: "uri", value: value.to_s }
24
+ when RDF::Node then {type: "bnode", value: value.id }
25
+ when RDF::Literal
26
+ if value.datatype?
27
+ {type: "typed-literal", datatype: value.datatype.to_s, value: value.to_s }
28
+ elsif value.language?
29
+ {type: "literal", "xml:lang" => value.language.to_s, value: value.to_s }
36
30
  else
37
- {}
31
+ {type: "literal", value: value.to_s }
38
32
  end
33
+ when RDF::Statement
34
+ {
35
+ type: 'triple',
36
+ value: {
37
+ subject: format.call(value.subject),
38
+ predicate: format.call(value.predicate),
39
+ object: format.call(value.object)
40
+ }
41
+ }
42
+ end
43
+ end
44
+
45
+ bindings = self.map do |solution|
46
+ variable_names.inject({}) do |memo, n|
47
+ rep = format.call(solution[n])
48
+ rep ? memo.merge(n => rep) : memo
39
49
  end
40
50
  end
41
51
 
@@ -48,12 +58,36 @@ module SPARQL
48
58
  ##
49
59
  # Generate Solutions as XML
50
60
  # @return [String]
51
- # @see http://www.w3.org/TR/rdf-sparql-XMLres/
61
+ # @see https://www.w3.org/TR/rdf-sparql-XMLres/
52
62
  def to_xml
53
63
  require 'builder' unless defined?(::Builder)
54
64
 
55
65
  xml = ::Builder::XmlMarkup.new(indent: 2)
56
66
  xml.instruct!
67
+
68
+ format = ->(s) do
69
+ case s
70
+ when RDF::URI
71
+ xml.uri(s.to_s)
72
+ when RDF::Node
73
+ xml.bnode(s.id)
74
+ when RDF::Literal
75
+ if s.datatype?
76
+ xml.literal(s.to_s, "datatype" => s.datatype.to_s)
77
+ elsif s.language
78
+ xml.literal(s.to_s, "xml:lang" => s.language.to_s)
79
+ else
80
+ xml.literal(s.to_s)
81
+ end
82
+ when RDF::Statement
83
+ xml.triple do
84
+ xml.subject {format.call(s.subject)}
85
+ xml.predicate {format.call(s.predicate)}
86
+ xml.object {format.call(s.object)}
87
+ end
88
+ end
89
+ end
90
+
57
91
  xml.sparql(xmlns: "http://www.w3.org/2005/sparql-results#") do
58
92
  xml.head do
59
93
  variable_names.each do |n|
@@ -67,20 +101,7 @@ module SPARQL
67
101
  s = solution[n]
68
102
  next unless s
69
103
  xml.binding(name: n) do
70
- case s
71
- when RDF::URI
72
- xml.uri(s.to_s)
73
- when RDF::Node
74
- xml.bnode(s.id)
75
- when RDF::Literal
76
- if s.datatype?
77
- xml.literal(s.to_s, "datatype" => s.datatype.to_s)
78
- elsif s.language
79
- xml.literal(s.to_s, "xml:lang" => s.language.to_s)
80
- else
81
- xml.literal(s.to_s)
82
- end
83
- end
104
+ format.call(s)
84
105
  end
85
106
  end
86
107
  end
@@ -118,10 +139,9 @@ module SPARQL
118
139
  ##
119
140
  # Generate Solutions as CSV
120
141
  # @return [String]
121
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#results
122
- def to_csv
142
+ # @see https://www.w3.org/TR/2013/REC-sparql11-results-csv-tsv-20130321/
143
+ def to_csv(bnode_map: {})
123
144
  require 'csv' unless defined?(::CSV)
124
- bnode_map = {}
125
145
  bnode_gen = "_:a"
126
146
  CSV.generate(row_sep: "\r\n") do |csv|
127
147
  csv << variable_names.to_a
@@ -134,8 +154,12 @@ module SPARQL
134
154
  bnode_gen = bnode_gen.succ
135
155
  this
136
156
  end
157
+ when RDF::Statement
158
+ RDF::Query::Solutions(
159
+ RDF::Query::Solution.new(subject: term.subject, predicate: term.predicate, object: term.object)
160
+ ).to_csv(bnode_map: bnode_map).split.last.strip
137
161
  else
138
- solution[n].to_s
162
+ solution[n].to_s.strip
139
163
  end
140
164
  end
141
165
  end
@@ -144,11 +168,9 @@ module SPARQL
144
168
  ##
145
169
  # Generate Solutions as TSV
146
170
  # @return [String]
147
- # @see http://www.w3.org/TR/rdf-sparql-json-res/#results
171
+ # @see https://www.w3.org/TR/2013/REC-sparql11-results-csv-tsv-20130321/
148
172
  def to_tsv
149
173
  require 'csv' unless defined?(::CSV)
150
- bnode_map = {}
151
- bnode_gen = "_:a"
152
174
  results = [
153
175
  variable_names.map {|v| "?#{v}"}.join("\t")
154
176
  ] + self.map do |solution|
@@ -156,10 +178,15 @@ module SPARQL
156
178
  case term = solution[n]
157
179
  when RDF::Literal::Integer, RDF::Literal::Decimal, RDF::Literal::Double
158
180
  term.canonicalize.to_s
181
+ when RDF::Statement
182
+ emb_stmt = RDF::Query::Solutions(
183
+ RDF::Query::Solution.new(subject: term.subject, predicate: term.predicate, object: term.object)
184
+ ).to_tsv.split("\n").last.strip
185
+ emb_stmt.gsub(/[\t\n\r]/, "\t" => '\t', "\n" => '\n', "\r" => '\r')
159
186
  when nil
160
187
  ""
161
188
  else
162
- RDF::NTriples.serialize(term)
189
+ RDF::NTriples.serialize(term).strip.gsub(/[\t\n\r]/, "\t" => '\t', "\n" => '\n', "\r" => '\r')
163
190
  end
164
191
  end.join("\t")
165
192
  end
@@ -185,7 +212,7 @@ module SPARQL
185
212
  # @return [String]
186
213
  # String with serialized results and `#content_type`
187
214
  # @raise [RDF::WriterError] when inappropriate formatting options are used
188
- def serialize_results(solutions, options = {})
215
+ def serialize_results(solutions, **options)
189
216
  format = options[:format].to_sym if options[:format]
190
217
  content_type = options[:content_type].to_s.split(';').first
191
218
  content_types = Array(options[:content_types] || '*/*')
@@ -226,7 +253,7 @@ module SPARQL
226
253
  when RDF::Queryable
227
254
  begin
228
255
  require 'linkeddata'
229
- rescue LoadError => e
256
+ rescue LoadError
230
257
  require 'rdf/ntriples'
231
258
  end
232
259
  fmt = RDF::Format.for(format ? format.to_sym : {content_type: content_type})
@@ -236,7 +263,7 @@ module SPARQL
236
263
  end
237
264
  format ||= fmt.to_sym
238
265
  content_type ||= fmt.content_type.first
239
- results = solutions.dump(format, options)
266
+ results = solutions.dump(format, **options)
240
267
  raise RDF::WriterError, "Unknown format #{fmt.inspect} for #{solutions.class}" unless results
241
268
  results
242
269
  when RDF::Query::Solutions
@@ -280,7 +307,7 @@ module SPARQL
280
307
  # @param [Array<String>] available
281
308
  # @return [String]
282
309
  #
283
- # @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
310
+ # @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
284
311
  def first_content_type(acceptable, available)
285
312
  return acceptable.first if available.empty?
286
313
  available.flatten!
@@ -306,7 +333,7 @@ module SPARQL
306
333
  # May also be an RDF::Writer content_type to serialize DESCRIBE or CONSTRUCT results
307
334
  # @return [String]
308
335
  # String with serialized results and #content_type
309
- def serialize_exception(exception, options = {})
336
+ def serialize_exception(exception, **options)
310
337
  format = options[:format]
311
338
  content_type = options[:content_type]
312
339
  content_type ||= SPARQL::Results::MIME_TYPES[format]
@@ -1,6 +1,6 @@
1
1
  module SPARQL
2
2
  module VERSION
3
- VERSION_FILE = File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "VERSION")
3
+ VERSION_FILE = File.expand_path("../../../VERSION", __FILE__)
4
4
  MAJOR, MINOR, TINY, EXTRA = File.read(VERSION_FILE).chomp.split(".")
5
5
 
6
6
  STRING = [MAJOR, MINOR, TINY, EXTRA].compact.join('.')