sparql 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/README.md +11 -4
  2. data/VERSION +1 -1
  3. data/lib/sparql/algebra/extensions.rb +36 -0
  4. data/lib/sparql/algebra/operator.rb +197 -87
  5. data/lib/sparql/algebra/operator/abs.rb +31 -0
  6. data/lib/sparql/algebra/operator/base.rb +1 -0
  7. data/lib/sparql/algebra/operator/bnode.rb +88 -0
  8. data/lib/sparql/algebra/operator/bound.rb +2 -1
  9. data/lib/sparql/algebra/operator/ceil.rb +31 -0
  10. data/lib/sparql/algebra/operator/coalesce.rb +65 -0
  11. data/lib/sparql/algebra/operator/concat.rb +49 -0
  12. data/lib/sparql/algebra/operator/contains.rb +44 -0
  13. data/lib/sparql/algebra/operator/dataset.rb +11 -48
  14. data/lib/sparql/algebra/operator/datatype.rb +4 -2
  15. data/lib/sparql/algebra/operator/day.rb +31 -0
  16. data/lib/sparql/algebra/operator/encode_for_uri.rb +38 -0
  17. data/lib/sparql/algebra/operator/extend.rb +31 -2
  18. data/lib/sparql/algebra/operator/floor.rb +33 -0
  19. data/lib/sparql/algebra/operator/hours.rb +31 -0
  20. data/lib/sparql/algebra/operator/if.rb +55 -0
  21. data/lib/sparql/algebra/operator/in.rb +68 -0
  22. data/lib/sparql/algebra/operator/iri.rb +40 -0
  23. data/lib/sparql/algebra/operator/is_numeric.rb +41 -0
  24. data/lib/sparql/algebra/operator/lang_matches.rb +2 -2
  25. data/lib/sparql/algebra/operator/lcase.rb +31 -0
  26. data/lib/sparql/algebra/operator/md5.rb +34 -0
  27. data/lib/sparql/algebra/operator/minutes.rb +31 -0
  28. data/lib/sparql/algebra/operator/month.rb +31 -0
  29. data/lib/sparql/algebra/operator/not.rb +2 -2
  30. data/lib/sparql/algebra/operator/notin.rb +70 -0
  31. data/lib/sparql/algebra/operator/now.rb +29 -0
  32. data/lib/sparql/algebra/operator/order.rb +9 -13
  33. data/lib/sparql/algebra/operator/rand.rb +24 -0
  34. data/lib/sparql/algebra/operator/replace.rb +81 -0
  35. data/lib/sparql/algebra/operator/round.rb +31 -0
  36. data/lib/sparql/algebra/operator/seconds.rb +31 -0
  37. data/lib/sparql/algebra/operator/sha1.rb +34 -0
  38. data/lib/sparql/algebra/operator/sha256.rb +34 -0
  39. data/lib/sparql/algebra/operator/sha384.rb +34 -0
  40. data/lib/sparql/algebra/operator/sha512.rb +34 -0
  41. data/lib/sparql/algebra/operator/strafter.rb +57 -0
  42. data/lib/sparql/algebra/operator/strbefore.rb +59 -0
  43. data/lib/sparql/algebra/operator/strdt.rb +33 -0
  44. data/lib/sparql/algebra/operator/strends.rb +46 -0
  45. data/lib/sparql/algebra/operator/strlang.rb +34 -0
  46. data/lib/sparql/algebra/operator/strlen.rb +34 -0
  47. data/lib/sparql/algebra/operator/strstarts.rb +46 -0
  48. data/lib/sparql/algebra/operator/struuid.rb +32 -0
  49. data/lib/sparql/algebra/operator/substr.rb +80 -0
  50. data/lib/sparql/algebra/operator/timezone.rb +34 -0
  51. data/lib/sparql/algebra/operator/tz.rb +31 -0
  52. data/lib/sparql/algebra/operator/ucase.rb +31 -0
  53. data/lib/sparql/algebra/operator/uuid.rb +32 -0
  54. data/lib/sparql/algebra/operator/year.rb +31 -0
  55. data/lib/sparql/grammar/parser11.rb +128 -70
  56. data/lib/sparql/grammar/terminals11.rb +4 -5
  57. metadata +62 -7
@@ -0,0 +1,34 @@
1
+ require 'digest'
2
+
3
+ module SPARQL; module Algebra
4
+ class Operator
5
+ ##
6
+ # The SPARQL logical `sha1` operator.
7
+ #
8
+ # @example
9
+ # (prefix ((: <http://example.org/>))
10
+ # (project (?hash)
11
+ # (extend ((?hash (sha384 ?l)))
12
+ # (bgp (triple :s1 :str ?l)))))
13
+ #
14
+ # @see http://www.w3.org/TR/sparql11-query/#func-sha384
15
+ class SHA384 < Operator::Unary
16
+ include Evaluatable
17
+
18
+ NAME = :sha384
19
+
20
+ ##
21
+ # Returns the SHA384 checksum, as a hex digit string, calculated on the UTF-8 representation of the simple literal or lexical form of the xsd:string. Hex digits should be in lower case.
22
+ #
23
+ # @param [RDF::Literal] operand
24
+ # the operand
25
+ # @return [RDF::Literal]
26
+ # @raise [TypeError] if the operand is not a simple literal
27
+ def apply(operand)
28
+ raise TypeError, "expected an RDF::Literal, but got #{operand.inspect}" unless operand.literal?
29
+ raise TypeError, "expected simple literal or xsd:string, but got #{operand.inspect}" unless (operand.datatype || RDF::XSD.string) == RDF::XSD.string
30
+ RDF::Literal(Digest::SHA384.new.hexdigest(operand.to_s))
31
+ end
32
+ end # SHA384
33
+ end # Operator
34
+ end; end # SPARQL::Algebra
@@ -0,0 +1,34 @@
1
+ require 'digest'
2
+
3
+ module SPARQL; module Algebra
4
+ class Operator
5
+ ##
6
+ # The SPARQL logical `sha512` operator.
7
+ #
8
+ # @example
9
+ # (prefix ((: <http://example.org/>))
10
+ # (project (?hash)
11
+ # (extend ((?hash (sha512 ?l)))
12
+ # (bgp (triple :s1 :str ?l)))))
13
+ #
14
+ # @see http://www.w3.org/TR/sparql11-query/#func-sha512
15
+ class SHA512 < Operator::Unary
16
+ include Evaluatable
17
+
18
+ NAME = :sha512
19
+
20
+ ##
21
+ # Returns the SHA512 checksum, as a hex digit string, calculated on the UTF-8 representation of the simple literal or lexical form of the xsd:string. Hex digits should be in lower case.
22
+ #
23
+ # @param [RDF::Literal] operand
24
+ # the operand
25
+ # @return [RDF::Literal]
26
+ # @raise [TypeError] if the operand is not a simple literal
27
+ def apply(operand)
28
+ raise TypeError, "expected an RDF::Literal, but got #{operand.inspect}" unless operand.literal?
29
+ raise TypeError, "expected simple literal or xsd:string, but got #{operand.inspect}" unless (operand.datatype || RDF::XSD.string) == RDF::XSD.string
30
+ RDF::Literal(Digest::SHA512.new.hexdigest(operand.to_s))
31
+ end
32
+ end # SHA512
33
+ end # Operator
34
+ end; end # SPARQL::Algebra
@@ -0,0 +1,57 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # A SPARQL `strafter` operator.
5
+ #
6
+ # @example
7
+ # (strafter ?x ?y)
8
+ #
9
+ # @see http://www.w3.org/TR/sparql11-query/#func-strafter
10
+ # @see http://www.w3.org/TR/xpath-functions/#func-substring-after
11
+ class StrAfter < Operator::Binary
12
+ include Evaluatable
13
+
14
+ NAME = :strafter
15
+
16
+ ##
17
+ # The STRAFTER function corresponds to the XPath fn:substring-after function. The arguments must be argument compatible otherwise an error is raised.
18
+ #
19
+ # For compatible arguments, if the lexical part of the second argument occurs as a substring of the lexical part of the first argument, the function returns a literal of the same kind as the first argument arg1 (simple literal, plain literal same language tag, xsd:string). The lexical form of the result is the substring of the lexcial form of arg1 that follows the first occurrence of the lexical form of arg2. If the lexical form of arg2 is the empty string, this is considered to be a match and the lexical form of the result is the lexical form of arg1.
20
+ #
21
+ # If there is no such occurrence, an empty simple literal is returned.
22
+ #
23
+ # @example
24
+ # strafter("abc","b") #=> "c"
25
+ # strafter("abc"@en,"ab") #=> "c"@en
26
+ # strafter("abc"@en,"b"@cy) #=> error
27
+ # strafter("abc"^^xsd:string,"") #=> "abc"^^xsd:string
28
+ # strafter("abc","xyz") #=> ""
29
+ # strafter("abc"@en, "z"@en) #=> ""
30
+ # strafter("abc"@en, "z") #=> ""
31
+ # strafter("abc"@en, ""@en) #=> "abc"@en
32
+ # strafter("abc"@en, "") #=> "abc"@en
33
+ #
34
+ # @param [RDF::Literal] left
35
+ # a literal
36
+ # @param [RDF::Literal] right
37
+ # a literal
38
+ # @return [RDF::Literal]
39
+ # @raise [TypeError] if operands are not compatible
40
+ def apply(left, right)
41
+ case
42
+ when !left.compatible?(right)
43
+ raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
44
+ when right.to_s.empty?
45
+ # If the lexical form of arg2 is the empty string, this is considered to be a match and the lexical form of the result is the lexical form of arg1.
46
+ left
47
+ when !left.to_s.include?(right.to_s)
48
+ # If the lexical form of arg2 is the empty string, this is considered to be a match and the lexical form of the result is is the empty string.
49
+ RDF::Literal("")
50
+ else
51
+ parts = left.to_s.split(right.to_s)
52
+ RDF::Literal(parts.last, :datatype => left.datatype, :language => left.language)
53
+ end
54
+ end
55
+ end # StrAfter
56
+ end # Operator
57
+ end; end # SPARQL::Algebra
@@ -0,0 +1,59 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # A SPARQL `strbefore` operator.
5
+ #
6
+ # @example
7
+ # (strbefore ?x ?y)
8
+ #
9
+ # @see http://www.w3.org/TR/sparql11-query/#func-strbefore
10
+ # @see http://www.w3.org/TR/xpath-functions/#func-substring-before
11
+ class StrBefore < Operator::Binary
12
+ include Evaluatable
13
+
14
+ NAME = :strbefore
15
+
16
+ ##
17
+ # The STRBEFORE function corresponds to the XPath fn:substring-before function. The arguments must be argument compatible otherwise an error is raised.
18
+ #
19
+ # For compatible arguments, if the lexical part of the second argument occurs as a substring of the lexical part of the first argument, the function returns a literal of the same kind as the first argument arg1 (simple literal, plain literal same language tag, xsd:string). The lexical form of the result is the substring of the lexical form of arg1 that precedes the first occurrence of the lexical form of arg2. If the lexical form of arg2 is the empty string, this is considered to be a match and the lexical form of the result is the empty string.
20
+ #
21
+ # If there is no such occurrence, an empty simple literal is returned.
22
+ #
23
+ # @example
24
+ # strbefore("abc","b") #=> "a"
25
+ # strbefore("abc"@en,"bc") #=> "a"@en
26
+ # strbefore("abc"@en,"b"@cy) #=> error
27
+ # strbefore("abc"^^xsd:string,"") #=> ""^^xsd:string
28
+ # strbefore("abc","xyz") #=> ""
29
+ # strbefore("abc"@en, "z"@en) #=> ""
30
+ # strbefore("abc"@en, "z") #=> ""
31
+ # strbefore("abc"@en, ""@en) #=> ""@en
32
+ # strbefore("abc"@en, "") #=> ""@en
33
+ #
34
+ # @param [RDF::Literal] left
35
+ # a literal
36
+ # @param [RDF::Literal] right
37
+ # a literal
38
+ # @return [RDF::Literal]
39
+ # @raise [TypeError] if operands are not compatible
40
+ def apply(left, right)
41
+ case
42
+ when !left.plain? || !right.plain?
43
+ raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
44
+ when !left.compatible?(right)
45
+ raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
46
+ when right.to_s.empty?
47
+ # If the lexical form of arg2 is the empty string, this is considered to be a match and the lexical form of the result is is the empty string.
48
+ RDF::Literal("", :language => left.language, :datatype => left.datatype)
49
+ when !left.to_s.include?(right.to_s)
50
+ # If the lexical form of arg2 is the empty string, this is considered to be a match and the lexical form of the result is is the empty string.
51
+ RDF::Literal("")
52
+ else
53
+ parts = left.to_s.split(right.to_s)
54
+ RDF::Literal(parts.first, :language => left.language, :datatype => left.datatype)
55
+ end
56
+ end
57
+ end # StrBefore
58
+ end # Operator
59
+ end; end # SPARQL::Algebra
@@ -0,0 +1,33 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL `strdt` operator.
5
+ #
6
+ # @example
7
+ # (project (?s ?str1)
8
+ # (extend ((?str1 (strdt ?str xsd:string)))
9
+ # (filter (langMatches (lang ?str) "en")
10
+ # (bgp (triple ?s :str ?str))))))
11
+ #
12
+ # @see http://www.w3.org/TR/sparql11-query/#func-strdt
13
+ class StrDT < Operator::Binary
14
+ include Evaluatable
15
+
16
+ NAME = :strdt
17
+
18
+ ##
19
+ # Constructs a literal with lexical form and type as specified by the arguments.
20
+ #
21
+ # @param [RDF::Literal] value
22
+ # a literal
23
+ # @param [RDF::URI] datatypeIRI
24
+ # datatype
25
+ # @return [RDF::Literal] a datatyped literal
26
+ # @see http://www.w3.org/TR/sparql11-query/#func-strdt
27
+ def apply(value, datatypeIRI)
28
+ raise TypeError, "Literal #{value.inspect} is not simple" unless value.simple?
29
+ RDF::Literal.new(value.to_s, :datatype => datatypeIRI)
30
+ end
31
+ end # StrDT
32
+ end # Operator
33
+ end; end # SPARQL::Algebra
@@ -0,0 +1,46 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # A SPARQL `contains` operator.
5
+ #
6
+ # @example
7
+ # (strends ?x ?y)
8
+ #
9
+ # @see http://www.w3.org/TR/sparql11-query/#func-strends
10
+ # @see http://www.w3.org/TR/xpath-functions/#func-ends-with
11
+ class StrEnds < Operator::Binary
12
+ include Evaluatable
13
+
14
+ NAME = :strends
15
+
16
+ ##
17
+ # The STRENDS function corresponds to the XPath fn:ends-with function. The arguments must be argument compatible otherwise an error is raised.
18
+ #
19
+ # For such input pairs, the function returns true if the lexical form of arg1 ends with the lexical form of arg2, otherwise it returns false.
20
+ #
21
+ # @example
22
+ # strEnds("foobar", "bar") #=> true
23
+ # strEnds("foobar"@en, "bar"@en) #=> true
24
+ # strEnds("foobar"^^xsd:string, "bar"^^xsd:string) #=> true
25
+ # strEnds("foobar"^^xsd:string, "bar") #=> true
26
+ # strEnds("foobar", "bar"^^xsd:string) #=> true
27
+ # strEnds("foobar"@en, "bar") #=> true
28
+ # strEnds("foobar"@en, "bar"^^xsd:string) #=> true
29
+ #
30
+ # @param [RDF::Literal] left
31
+ # a literal
32
+ # @param [RDF::Literal] right
33
+ # a literal
34
+ # @return [RDF::Literal::Boolean]
35
+ # @raise [TypeError] if operands are not compatible
36
+ def apply(left, right)
37
+ case
38
+ when !left.compatible?(right)
39
+ raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
40
+ when left.to_s.end_with?(right.to_s) then RDF::Literal::TRUE
41
+ else RDF::Literal::FALSE
42
+ end
43
+ end
44
+ end # StrEnds
45
+ end # Operator
46
+ end; end # SPARQL::Algebra
@@ -0,0 +1,34 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL `strlang` operator.
5
+ #
6
+ # @example
7
+ # (prefix ((: <http://example.org/>))
8
+ # (project (?s ?s2)
9
+ # (extend ((?s2 (strlang ?str "en-US")))
10
+ # (filter (langMatches (lang ?str) "en")
11
+ # (bgp (triple ?s :str ?str))))))
12
+ #
13
+ # @see http://www.w3.org/TR/sparql11-query/#func-strlang
14
+ class StrLang < Operator::Binary
15
+ include Evaluatable
16
+
17
+ NAME = :strlang
18
+
19
+ ##
20
+ # Constructs a literal with lexical form and type as specified by the arguments.
21
+ #
22
+ # @param [RDF::Literal] value
23
+ # a literal
24
+ # @param [RDF::Literal] datatypeIRI
25
+ # datatype
26
+ # @return [RDF::Literal] a datatyped literal
27
+ # @see http://www.w3.org/TR/sparql11-query/#func-strlang
28
+ def apply(value, langTag)
29
+ raise TypeError, "Literal #{value.inspect} is not simple" unless value.simple?
30
+ RDF::Literal.new(value.to_s, :language => langTag.to_s)
31
+ end
32
+ end # StrLang
33
+ end # Operator
34
+ end; end # SPARQL::Algebra
@@ -0,0 +1,34 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # The SPARQL `strlen` operator.
5
+ #
6
+ # @example
7
+ # (strlen ?x)
8
+ #
9
+ # @see http://www.w3.org/TR/sparql11-query/#func-strlen
10
+ # @see http://www.w3.org/TR/xpath-functions/#func-string-length
11
+ class StrLen < Operator::Unary
12
+ include Evaluatable
13
+
14
+ NAME = :strlen
15
+
16
+ ##
17
+ # The strlen function corresponds to the XPath fn:string-length function and returns an xsd:integer equal to the length in characters of the lexical form of the literal.
18
+ #
19
+ # @example
20
+ # strlen("chat") 4
21
+ # strlen("chat"@en) 4
22
+ # strlen("chat"^^xsd:string) 4
23
+ #
24
+ # @param [RDF::Literal] operand
25
+ # the operand
26
+ # @return [RDF::Literal::Integer] length of string
27
+ # @raise [TypeError] if the operand is not a numeric value
28
+ def apply(operand)
29
+ raise TypeError, "expected a plain RDF::Literal, but got #{operand.inspect}" unless operand.literal? && operand.plain?
30
+ RDF::Literal(operand.to_s.length)
31
+ end
32
+ end # StrLen
33
+ end # Operator
34
+ end; end # SPARQL::Algebra
@@ -0,0 +1,46 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # A SPARQL `strstarts` operator.
5
+ #
6
+ # @example
7
+ # (strstarts ?x ?y)
8
+ #
9
+ # @see http://www.w3.org/TR/sparql11-query/#func-strstarts
10
+ # @see http://www.w3.org/TR/xpath-functions/#func-starts-with
11
+ class StrStarts < Operator::Binary
12
+ include Evaluatable
13
+
14
+ NAME = :strstarts
15
+
16
+ ##
17
+ # The STRSTARTS function corresponds to the XPath fn:starts-with function. The arguments must be argument compatible otherwise an error is raised.
18
+ #
19
+ # For such input pairs, the function returns true if the lexical form of arg1 starts with the lexical form of arg2, otherwise it returns false.
20
+ #
21
+ # @example
22
+ # strStarts("foobar", "foo") #=> true
23
+ # strStarts("foobar"@en, "foo"@en) #=> true
24
+ # strStarts("foobar"^^xsd:string, "foo"^^xsd:string) #=> true
25
+ # strStarts("foobar"^^xsd:string, "foo") #=> true
26
+ # strStarts("foobar", "foo"^^xsd:string) #=> true
27
+ # strStarts("foobar"@en, "foo") #=> true
28
+ # strStarts("foobar"@en, "foo"^^xsd:string) #=> true
29
+ #
30
+ # @param [RDF::Literal] left
31
+ # a literal
32
+ # @param [RDF::Literal] right
33
+ # a literal
34
+ # @return [RDF::Literal::Boolean]
35
+ # @raise [TypeError] if operands are not compatible
36
+ def apply(left, right)
37
+ case
38
+ when !left.compatible?(right)
39
+ raise TypeError, "expected two RDF::Literal operands, but got #{left.inspect} and #{right.inspect}"
40
+ when left.to_s.start_with?(right.to_s) then RDF::Literal::TRUE
41
+ else RDF::Literal::FALSE
42
+ end
43
+ end
44
+ end # StrStarts
45
+ end # Operator
46
+ end; end # SPARQL::Algebra
@@ -0,0 +1,32 @@
1
+ require 'securerandom'
2
+
3
+ module SPARQL; module Algebra
4
+ class Operator
5
+ ##
6
+ # The SPARQL `uuid` function.
7
+ #
8
+ # @example
9
+ # (prefix ((: <http://example.org/>)
10
+ # (xsd: <http://www.w3.org/2001/XMLSchema#>))
11
+ # (project (?length)
12
+ # (extend ((?length (strlen ?uuid)))
13
+ # (filter (&& (isLiteral ?uuid) (regex ?uuid "^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$" "i"))
14
+ # (extend ((?uuid (struuid)))
15
+ # (bgp))))))
16
+ #
17
+ # @see http://www.w3.org/TR/sparql11-query/#func-struuid
18
+ class StrUUID < Operator::Nullary
19
+ include Evaluatable
20
+
21
+ NAME = :struuid
22
+
23
+ ##
24
+ # Return a string that is the scheme specific part of UUID. That is, as a simple literal, the result of generating a UUID, converting to a simple literal and removing the initial urn:uuid:.
25
+ #
26
+ # @return [RDF::URI]
27
+ def apply
28
+ RDF::Literal(SecureRandom.uuid)
29
+ end
30
+ end # StrUUID
31
+ end # Operator
32
+ end; end # SPARQL::Algebra
@@ -0,0 +1,80 @@
1
+ module SPARQL; module Algebra
2
+ class Operator
3
+ ##
4
+ # A SPARQL `substr` operator.
5
+ #
6
+ # @example
7
+ # (substr ?x ?y)
8
+ #
9
+ # @see http://www.w3.org/TR/sparql11-query/#func-substr
10
+ # @see http://www.w3.org/TR/xpath-functions/#func-substring
11
+ class SubStr < Operator::Ternary
12
+ include Evaluatable
13
+
14
+ NAME = :substr
15
+
16
+ ##
17
+ # Initializes a new operator instance.
18
+ #
19
+ # @param [RDF::Literal] source
20
+ # @param [RDF::Litereal::Integer] startingLoc
21
+ # @param [RDF::Litereal::Integer] length (-1)
22
+ # @param [Hash{Symbol => Object}] options
23
+ # any additional options (see {Operator#initialize})
24
+ # @raise [TypeError] if any operand is invalid
25
+ def initialize(source, startingLoc, length = RDF::Literal(""), options = {})
26
+ super
27
+ end
28
+
29
+ ##
30
+ # The substr function corresponds to the XPath fn:substring function and returns a literal of the same kind (simple literal, literal with language tag, xsd:string typed literal) as the source input parameter but with a lexical form formed from the substring of the lexcial form of the source.
31
+ #
32
+ # The arguments startingLoc and length may be derived types of xsd:integer.
33
+ #
34
+ # The index of the first character in a strings is 1.
35
+ #
36
+ # @example
37
+ # substr("foobar", 4) #=> "bar"
38
+ # substr("foobar"@en, 4) #=> "bar"@en
39
+ # substr("foobar"^^xsd:string, 4) #=> "bar"^^xsd:string
40
+ # substr("foobar", 4, 1) #=> "b"
41
+ # substr("foobar"@en, 4, 1) #=> "b"@en
42
+ # substr("foobar"^^xsd:string, 4, 1) #=> "b"^^xsd:string
43
+ #
44
+ # @param [RDF::Literal] source
45
+ # a literal
46
+ # @param [RDF::Literal] startingLoc
47
+ # an 1-based integer offset into source
48
+ # @param [RDF::Literal::Integer] length (-1)
49
+ # an optional length of the substring.
50
+ # @return [RDF::Literal]
51
+ # @raise [TypeError] if operands are not compatible
52
+ def apply(source, startingLoc, length)
53
+ raise TypeError, "expected a plain RDF::Literal, but got #{source.inspect}" unless source.literal? && source.plain?
54
+ text = text.to_s
55
+
56
+ raise TypeError, "expected an integer, but got #{startingLoc.inspect}" unless startingLoc.is_a?(RDF::Literal::Integer)
57
+ startingLoc = startingLoc.to_i
58
+
59
+ if length == RDF::Literal("")
60
+ RDF::Literal(source.to_s[(startingLoc-1)..-1], :datatype => source.datatype, :language => source.language)
61
+ else
62
+ raise TypeError, "expected an integer, but got #{length.inspect}" unless length.is_a?(RDF::Literal::Integer)
63
+ length = length.to_i
64
+ RDF::Literal(source.to_s[(startingLoc-1), length], :datatype => source.datatype, :language => source.language)
65
+ end
66
+ end
67
+
68
+ ##
69
+ # Returns the SPARQL S-Expression (SSE) representation of this expression.
70
+ #
71
+ # Remove the optional argument.
72
+ #
73
+ # @return [Array] `self`
74
+ # @see http://openjena.org/wiki/SSE
75
+ def to_sxp_bin
76
+ [NAME] + operands.reject {|o| o.to_s == ""}
77
+ end
78
+ end # SubStr
79
+ end # Operator
80
+ end; end # SPARQL::Algebra