sparql 3.0.2 → 3.1.5

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 (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('.')