sparql 3.0.1 → 3.1.4

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 +188 -73
  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 +63 -40
  14. data/lib/sparql/algebra/extensions.rb +180 -33
  15. data/lib/sparql/algebra/operator.rb +37 -16
  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 +6 -4
  23. data/lib/sparql/algebra/operator/base.rb +10 -10
  24. data/lib/sparql/algebra/operator/bgp.rb +1 -1
  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 +15 -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 +6 -4
  79. data/lib/sparql/algebra/operator/md5.rb +1 -1
  80. data/lib/sparql/algebra/operator/min.rb +6 -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 +3 -3
  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 +5 -5
  145. data/lib/sparql/grammar.rb +111 -11
  146. data/lib/sparql/grammar/meta.rb +2340 -907
  147. data/lib/sparql/grammar/parser11.rb +69 -69
  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 +38 -65
@@ -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
@@ -216,7 +216,7 @@ module SPARQL::Grammar
216
216
  unless resolve_iris?
217
217
  # Only output if we're not resolving URIs internally
218
218
  add_prod_datum(:BaseDecl, data[:BaseDecl])
219
- add_prod_datum(:PrefixDecl, data[:PrefixDecl]) if data[:PrefixDecl]
219
+ add_prod_datum(:PrefixDecl, data[:PrefixDecl])
220
220
  end
221
221
  end
222
222
 
@@ -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
@@ -624,11 +624,14 @@ module SPARQL::Grammar
624
624
  if (lhs = (input.delete(:query) || []).first) && !lhs.empty?
625
625
  query = SPARQL::Algebra::Operator::Join.new(lhs, query)
626
626
  end
627
+ if data[:path]
628
+ query = SPARQL::Algebra::Operator::Join.new(query, Array(data[:path]).first)
629
+ end
627
630
  add_prod_datum(:query, query)
628
631
  elsif !Array(data[:query]).empty?
629
632
  # Join query and path
630
633
  add_prod_datum(:query, SPARQL::Algebra::Operator::Join.new(data[:path].first, data[:query].first))
631
- else
634
+ elsif data[:path]
632
635
  add_prod_datum(:query, data[:path])
633
636
  end
634
637
  end
@@ -698,9 +701,9 @@ module SPARQL::Grammar
698
701
  end
699
702
  end
700
703
 
701
- # [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
704
+ # [60] Bind ::= 'BIND' '(' (Expression || EmbTP) 'AS' Var ')'
702
705
  production(:Bind) do |input, data, callback|
703
- add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
706
+ add_prod_datum :extend, [(data[:Expression] || data[:pattern]).unshift(data[:Var].first)]
704
707
  end
705
708
 
706
709
  # [61] InlineData ::= 'VALUES' DataBlock
@@ -856,25 +859,30 @@ module SPARQL::Grammar
856
859
  data[:Subject] = prod_data[:Subject]
857
860
  error(nil, "Expected Subject", production: :ObjectList) if !prod_data[:Subject] && validate?
858
861
  error(nil, "Expected Verb", production: :ObjectList) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
859
- if prod_data[:Verb]
860
- data[:Verb] = prod_data[:Verb]
861
- else
862
- data[:VerbPath] = prod_data[:VerbPath]
863
- end
862
+ data[:Verb] = prod_data[:Verb] if prod_data[:Verb]
863
+ data[:VerbPath] = prod_data[:VerbPath] if prod_data[:VerbPath]
864
864
  end
865
865
  production(:ObjectList) do |input, data, callback|
866
866
  add_prod_datum(:pattern, data[:pattern])
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]
873
881
  if object
874
882
  if prod_data[:Verb]
875
883
  add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
876
884
  add_prod_datum(:pattern, data[:pattern])
877
- else
885
+ elsif prod_data[:VerbPath]
878
886
  add_prod_datum(:path,
879
887
  SPARQL::Algebra::Expression(:path,
880
888
  prod_data[:Subject].first,
@@ -886,11 +894,8 @@ module SPARQL::Grammar
886
894
 
887
895
  # [81] TriplesSameSubjectPath ::= VarOrTerm PropertyListPathNotEmpty | TriplesNode PropertyListPath
888
896
  production(:TriplesSameSubjectPath) do |input, data, callback|
889
- if data[:pattern]
890
- add_prod_datum(:pattern, data[:pattern])
891
- else
892
- add_prod_datum(:path, data[:path])
893
- end
897
+ add_prod_datum(:pattern, data[:pattern])
898
+ add_prod_datum(:path, data[:path])
894
899
  end
895
900
 
896
901
  # [83] PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
@@ -900,16 +905,14 @@ module SPARQL::Grammar
900
905
  data[:Subject] = subject
901
906
  end
902
907
  production(:PropertyListPathNotEmpty) do |input, data, callback|
903
- if data[:pattern]
904
- add_prod_datum(:pattern, data[:pattern])
905
- else
906
- add_prod_datum(:path, data[:path])
907
- end
908
+ add_prod_datum(:pattern, data[:pattern])
909
+ add_prod_datum(:path, data[:path])
908
910
  end
909
911
 
910
912
  # [84] VerbPath ::= Path
911
913
  production(:VerbPath) do |input, data, callback|
912
914
  if data[:Path]
915
+ input.delete(:Verb)
913
916
  input[:VerbPath] = data[:Path]
914
917
  else
915
918
  input[:Verb] = data[:iri]
@@ -1109,6 +1112,11 @@ module SPARQL::Grammar
1109
1112
  data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
1110
1113
  end
1111
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
+
1112
1120
  # [107] VarOrIri ::= Var | iri
1113
1121
  production(:VarOrIri) do |input, data, callback|
1114
1122
  data.values.each {|v| add_prod_datum(:VarOrIri, v)}
@@ -1124,6 +1132,22 @@ module SPARQL::Grammar
1124
1132
  data[:NIL])
1125
1133
  end
1126
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
+
1127
1151
  # [110] Expression ::= ConditionalOrExpression
1128
1152
  production(:Expression) do |input, data, callback|
1129
1153
  add_prod_datum(:Expression, data[:Expression])
@@ -1420,7 +1444,7 @@ module SPARQL::Grammar
1420
1444
  str = lit.delete(:string)
1421
1445
  lit[:datatype] = lit.delete(:iri) if lit[:iri]
1422
1446
  lit[:language] = lit.delete(:language).last.downcase if lit[:language]
1423
- input[:literal] = RDF::Literal.new(str, lit) if str
1447
+ input[:literal] = RDF::Literal.new(str, **lit) if str
1424
1448
  end
1425
1449
  end
1426
1450
 
@@ -1463,25 +1487,19 @@ module SPARQL::Grammar
1463
1487
  # definitions.
1464
1488
  # @option options [Boolean] :validate (false)
1465
1489
  # whether to validate the parsed statements and values
1466
- # @option options [Boolean] :progress
1467
- # Show progress of parser productions
1468
- # @option options [Boolean] :debug
1469
- # Detailed debug output
1490
+ # @option options [Logger, #write, #<<] :logger
1491
+ # Record error/info/debug output
1470
1492
  # @yield [parser] `self`
1471
1493
  # @yieldparam [SPARQL::Grammar::Parser] parser
1472
1494
  # @yieldreturn [void] ignored
1473
1495
  # @return [SPARQL::Grammar::Parser]
1474
- def initialize(input = nil, options = {}, &block)
1496
+ def initialize(input = nil, **options, &block)
1475
1497
  @input = case input
1476
1498
  when IO, StringIO then input.read
1477
1499
  else input.to_s.dup
1478
1500
  end
1479
1501
  @input.encode!(Encoding::UTF_8) if @input.respond_to?(:encode!)
1480
1502
  @options = {anon_base: "b0", validate: false}.merge(options)
1481
- @options[:debug] ||= case
1482
- when options[:progress] then 2
1483
- when options[:validate] then 1
1484
- end
1485
1503
 
1486
1504
  debug("base IRI") {base_uri.inspect}
1487
1505
  debug("validate") {validate?.inspect}
@@ -1532,30 +1550,17 @@ module SPARQL::Grammar
1532
1550
  # @param [Symbol, #to_s] prod The starting production for the parser.
1533
1551
  # It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
1534
1552
  # @return [Array]
1535
- # @see http://www.w3.org/TR/sparql11-query/#sparqlAlgebra
1536
- # @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
1537
1555
  def parse(prod = START)
1538
- ll1_parse(@input, prod.to_sym, @options.merge(branch: BRANCH,
1539
- first: FIRST,
1540
- follow: FOLLOW,
1541
- whitespace: WS)
1542
- ) do |context, *data|
1543
- case context
1544
- when :trace
1545
- level, lineno, depth, *args = data
1546
- message = args.to_sse
1547
- d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
1548
- str = "[#{lineno}](#{level})#{d_str}#{message}".chop
1549
- case @options[:debug]
1550
- when Array
1551
- @options[:debug] << str unless level > 2
1552
- when TrueClass
1553
- $stderr.puts str
1554
- when Integer
1555
- $stderr.puts(str) if level <= @options[:debug]
1556
- end
1557
- end
1558
- end
1556
+ ll1_parse(@input,
1557
+ prod.to_sym,
1558
+ branch: BRANCH,
1559
+ first: FIRST,
1560
+ follow: FOLLOW,
1561
+ whitespace: WS,
1562
+ **@options
1563
+ )
1559
1564
 
1560
1565
  # The last thing on the @prod_data stack is the result
1561
1566
  @result = case
@@ -1723,9 +1728,7 @@ module SPARQL::Grammar
1723
1728
 
1724
1729
  if id
1725
1730
  @vars[id] ||= begin
1726
- v = RDF::Query::Variable.new(id)
1727
- v.distinguished = distinguished
1728
- v
1731
+ RDF::Query::Variable.new(id, distinguished: distinguished)
1729
1732
  end
1730
1733
  else
1731
1734
  unless distinguished
@@ -1733,9 +1736,7 @@ module SPARQL::Grammar
1733
1736
  id = @nd_var_gen
1734
1737
  @nd_var_gen = id.succ
1735
1738
  end
1736
- v = RDF::Query::Variable.new(id)
1737
- v.distinguished = distinguished
1738
- v
1739
+ RDF::Query::Variable.new(id, distinguished: distinguished)
1739
1740
  end
1740
1741
  end
1741
1742
 
@@ -1763,7 +1764,7 @@ module SPARQL::Grammar
1763
1764
  end
1764
1765
 
1765
1766
  # Create a literal
1766
- def literal(value, options = {})
1767
+ def literal(value, **options)
1767
1768
  options = options.dup
1768
1769
  # Internal representation is to not use xsd:string, although it could arguably go the other way.
1769
1770
  options.delete(:datatype) if options[:datatype] == RDF::XSD.string
@@ -1772,7 +1773,7 @@ module SPARQL::Grammar
1772
1773
  "options: #{options.inspect}, " +
1773
1774
  "validate: #{validate?.inspect}, "
1774
1775
  end
1775
- RDF::Literal.new(value, options.merge(validate: validate?))
1776
+ RDF::Literal.new(value, validate: validate?, **options)
1776
1777
  end
1777
1778
 
1778
1779
  # Take collection of objects and create RDF Collection using rdf:first, rdf:rest and rdf:nil
@@ -1803,7 +1804,7 @@ module SPARQL::Grammar
1803
1804
  #
1804
1805
  # @param [String] production Production generating pattern
1805
1806
  # @param [Hash{Symbol => Object}] options
1806
- def add_pattern(production, options)
1807
+ def add_pattern(production, **options)
1807
1808
  progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
1808
1809
  triple = {}
1809
1810
  options.each_pair do |r, v|
@@ -1885,8 +1886,7 @@ module SPARQL::Grammar
1885
1886
  avf.first
1886
1887
  else
1887
1888
  # Allocate a temporary variable for this function, and retain the mapping for outside the group
1888
- av = RDF::Query::Variable.new(".#{agg}")
1889
- av.distinguished = false
1889
+ av = RDF::Query::Variable.new(".#{agg}", distinguished: false)
1890
1890
  agg += 1
1891
1891
  aggregates << [av, function]
1892
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]