rdf-n3 3.0.1 → 3.2.0
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.
- checksums.yaml +4 -4
- data/README.md +198 -76
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/lib/rdf/n3/algebra/builtin.rb +79 -0
- data/lib/rdf/n3/algebra/formula.rb +446 -0
- data/lib/rdf/n3/algebra/list/append.rb +42 -0
- data/lib/rdf/n3/algebra/list/first.rb +24 -0
- data/lib/rdf/n3/algebra/list/in.rb +48 -0
- data/lib/rdf/n3/algebra/list/iterate.rb +96 -0
- data/lib/rdf/n3/algebra/list/last.rb +24 -0
- data/lib/rdf/n3/algebra/list/length.rb +24 -0
- data/lib/rdf/n3/algebra/list/member.rb +44 -0
- data/lib/rdf/n3/algebra/list_operator.rb +96 -0
- data/lib/rdf/n3/algebra/log/conclusion.rb +65 -0
- data/lib/rdf/n3/algebra/log/conjunction.rb +36 -0
- data/lib/rdf/n3/algebra/log/content.rb +34 -0
- data/lib/rdf/n3/algebra/log/dtlit.rb +41 -0
- data/lib/rdf/n3/algebra/log/equal_to.rb +34 -0
- data/lib/rdf/n3/algebra/log/implies.rb +102 -0
- data/lib/rdf/n3/algebra/log/includes.rb +70 -0
- data/lib/rdf/n3/algebra/log/langlit.rb +41 -0
- data/lib/rdf/n3/algebra/log/n3_string.rb +34 -0
- data/lib/rdf/n3/algebra/log/not_equal_to.rb +23 -0
- data/lib/rdf/n3/algebra/log/not_includes.rb +27 -0
- data/lib/rdf/n3/algebra/log/output_string.rb +40 -0
- data/lib/rdf/n3/algebra/log/parsed_as_n3.rb +36 -0
- data/lib/rdf/n3/algebra/log/semantics.rb +40 -0
- data/lib/rdf/n3/algebra/math/absolute_value.rb +36 -0
- data/lib/rdf/n3/algebra/math/acos.rb +26 -0
- data/lib/rdf/n3/algebra/math/acosh.rb +26 -0
- data/lib/rdf/n3/algebra/math/asin.rb +26 -0
- data/lib/rdf/n3/algebra/math/asinh.rb +26 -0
- data/lib/rdf/n3/algebra/math/atan.rb +26 -0
- data/lib/rdf/n3/algebra/math/atanh.rb +26 -0
- data/lib/rdf/n3/algebra/math/ceiling.rb +28 -0
- data/lib/rdf/n3/algebra/math/cos.rb +40 -0
- data/lib/rdf/n3/algebra/math/cosh.rb +38 -0
- data/lib/rdf/n3/algebra/math/difference.rb +40 -0
- data/lib/rdf/n3/algebra/math/equal_to.rb +54 -0
- data/lib/rdf/n3/algebra/math/exponentiation.rb +35 -0
- data/lib/rdf/n3/algebra/math/floor.rb +28 -0
- data/lib/rdf/n3/algebra/math/greater_than.rb +41 -0
- data/lib/rdf/n3/algebra/math/less_than.rb +41 -0
- data/lib/rdf/n3/algebra/math/negation.rb +38 -0
- data/lib/rdf/n3/algebra/math/not_equal_to.rb +25 -0
- data/lib/rdf/n3/algebra/math/not_greater_than.rb +25 -0
- data/lib/rdf/n3/algebra/math/not_less_than.rb +25 -0
- data/lib/rdf/n3/algebra/math/product.rb +20 -0
- data/lib/rdf/n3/algebra/math/quotient.rb +36 -0
- data/lib/rdf/n3/algebra/math/remainder.rb +35 -0
- data/lib/rdf/n3/algebra/math/rounded.rb +26 -0
- data/lib/rdf/n3/algebra/math/sin.rb +40 -0
- data/lib/rdf/n3/algebra/math/sinh.rb +38 -0
- data/lib/rdf/n3/algebra/math/sum.rb +40 -0
- data/lib/rdf/n3/algebra/math/tan.rb +40 -0
- data/lib/rdf/n3/algebra/math/tanh.rb +38 -0
- data/lib/rdf/n3/algebra/not_implemented.rb +13 -0
- data/lib/rdf/n3/algebra/resource_operator.rb +122 -0
- data/lib/rdf/n3/algebra/str/concatenation.rb +27 -0
- data/lib/rdf/n3/algebra/str/contains.rb +33 -0
- data/lib/rdf/n3/algebra/str/contains_ignoring_case.rb +33 -0
- data/lib/rdf/n3/algebra/str/ends_with.rb +33 -0
- data/lib/rdf/n3/algebra/str/equal_ignoring_case.rb +34 -0
- data/lib/rdf/n3/algebra/str/format.rb +17 -0
- data/lib/rdf/n3/algebra/str/greater_than.rb +38 -0
- data/lib/rdf/n3/algebra/str/less_than.rb +33 -0
- data/lib/rdf/n3/algebra/str/matches.rb +37 -0
- data/lib/rdf/n3/algebra/str/not_equal_ignoring_case.rb +17 -0
- data/lib/rdf/n3/algebra/str/not_greater_than.rb +17 -0
- data/lib/rdf/n3/algebra/str/not_less_than.rb +17 -0
- data/lib/rdf/n3/algebra/str/not_matches.rb +18 -0
- data/lib/rdf/n3/algebra/str/replace.rb +35 -0
- data/lib/rdf/n3/algebra/str/scrape.rb +35 -0
- data/lib/rdf/n3/algebra/str/starts_with.rb +33 -0
- data/lib/rdf/n3/algebra/time/day.rb +35 -0
- data/lib/rdf/n3/algebra/time/day_of_week.rb +27 -0
- data/lib/rdf/n3/algebra/time/gm_time.rb +29 -0
- data/lib/rdf/n3/algebra/time/hour.rb +35 -0
- data/lib/rdf/n3/algebra/time/in_seconds.rb +59 -0
- data/lib/rdf/n3/algebra/time/local_time.rb +29 -0
- data/lib/rdf/n3/algebra/time/minute.rb +35 -0
- data/lib/rdf/n3/algebra/time/month.rb +35 -0
- data/lib/rdf/n3/algebra/time/second.rb +35 -0
- data/lib/rdf/n3/algebra/time/timezone.rb +36 -0
- data/lib/rdf/n3/algebra/time/year.rb +29 -0
- data/lib/rdf/n3/algebra.rb +210 -0
- data/lib/rdf/n3/extensions.rb +221 -0
- data/lib/rdf/n3/format.rb +66 -1
- data/lib/rdf/n3/list.rb +630 -0
- data/lib/rdf/n3/reader.rb +774 -497
- data/lib/rdf/n3/reasoner.rb +282 -0
- data/lib/rdf/n3/refinements.rb +178 -0
- data/lib/rdf/n3/repository.rb +332 -0
- data/lib/rdf/n3/terminals.rb +78 -0
- data/lib/rdf/n3/vocab.rb +36 -3
- data/lib/rdf/n3/writer.rb +461 -250
- data/lib/rdf/n3.rb +11 -8
- metadata +177 -49
- data/AUTHORS +0 -1
- data/History.markdown +0 -99
- data/lib/rdf/n3/patches/array_hacks.rb +0 -53
- data/lib/rdf/n3/reader/meta.rb +0 -641
- data/lib/rdf/n3/reader/parser.rb +0 -237
@@ -0,0 +1,38 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject or object is calculated to be the negation of the other.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-unary-minus
|
6
|
+
class Negation < RDF::N3::Algebra::ResourceOperator
|
7
|
+
include RDF::N3::Algebra::Builtin
|
8
|
+
|
9
|
+
NAME = :mathNegation
|
10
|
+
URI = RDF::N3::Math.negation
|
11
|
+
|
12
|
+
##
|
13
|
+
# The math:negation operator takes may have either a bound subject or object.
|
14
|
+
#
|
15
|
+
# @param [RDF::Term] resource
|
16
|
+
# @param [:subject, :object] position
|
17
|
+
# @return [RDF::Term]
|
18
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
19
|
+
def resolve(resource, position:)
|
20
|
+
case resource
|
21
|
+
when RDF::Query::Variable
|
22
|
+
resource
|
23
|
+
when RDF::Literal
|
24
|
+
as_literal(-resource.as_number)
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Input is either the subject or object
|
32
|
+
#
|
33
|
+
# @return [RDF::Term]
|
34
|
+
def input_operand
|
35
|
+
RDF::N3::List.new(values: operands)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# True iff the subject is a string representation of a number which is NOT EQUAL to a number of which the object is a string representation.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-equal
|
6
|
+
class NotEqualTo < EqualTo
|
7
|
+
NAME = :mathNotEqualTo
|
8
|
+
URI = RDF::N3::Math.notEqualTo
|
9
|
+
|
10
|
+
##
|
11
|
+
# The math:notEqualTo operator takes a pair of strings or numbers and determines if they are not the same numeric value.
|
12
|
+
#
|
13
|
+
# @param [RDF::Term] term1
|
14
|
+
# an RDF term
|
15
|
+
# @param [RDF::Term] term2
|
16
|
+
# an RDF term
|
17
|
+
# @return [RDF::Literal::Boolean] `true` or `false`
|
18
|
+
# @raise [TypeError] if either operand is not an RDF term or operands are not comperable
|
19
|
+
#
|
20
|
+
# @see RDF::Term#==
|
21
|
+
def apply(term1, term2)
|
22
|
+
RDF::Literal(super != RDF::Literal::TRUE)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# True iff the subject is a string representation of a number which is NOT greater than the number of which the object is a string representation.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-greater-than
|
6
|
+
class NotGreaterThan < GreaterThan
|
7
|
+
NAME = :mathNotGreaterThan
|
8
|
+
URI = RDF::N3::Math.notGreaterThan
|
9
|
+
|
10
|
+
##
|
11
|
+
# Returns TRUE if `term1` is less than or equal to `term2`.
|
12
|
+
#
|
13
|
+
# @param [RDF::Term] term1
|
14
|
+
# an RDF term
|
15
|
+
# @param [RDF::Term] term2
|
16
|
+
# an RDF term
|
17
|
+
# @return [RDF::Literal::Boolean] `true` or `false`
|
18
|
+
# @raise [TypeError] if either operand is not an RDF term or operands are not comperable
|
19
|
+
#
|
20
|
+
# @see RDF::Term#==
|
21
|
+
def apply(term1, term2)
|
22
|
+
RDF::Literal(super != RDF::Literal::TRUE)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# True iff the subject is a string representation of a number which is NOT LESS than a number of which the object is a string representation.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-less-than
|
6
|
+
class NotLessThan < LessThan
|
7
|
+
NAME = :mathNotLessThan
|
8
|
+
URI = RDF::N3::Math.notLessThan
|
9
|
+
|
10
|
+
##
|
11
|
+
# Returns TRUE if `term1` is greater than or equal to `term2`.
|
12
|
+
#
|
13
|
+
# @param [RDF::Term] term1
|
14
|
+
# an RDF term
|
15
|
+
# @param [RDF::Term] term2
|
16
|
+
# an RDF term
|
17
|
+
# @return [RDF::Literal::Boolean] `true` or `false`
|
18
|
+
# @raise [TypeError] if either operand is not an RDF term or operands are not comperable
|
19
|
+
#
|
20
|
+
# @see RDF::Term#==
|
21
|
+
def apply(term1, term2)
|
22
|
+
RDF::Literal(super != RDF::Literal::TRUE)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject is a list of numbers. The object is calculated as the arithmentic product of those numbers.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-multiply
|
6
|
+
class Product < RDF::N3::Algebra::ListOperator
|
7
|
+
NAME = :mathProduct
|
8
|
+
URI = RDF::N3::Math.product
|
9
|
+
|
10
|
+
##
|
11
|
+
# The math:product operator takes a list of strings or numbers and calculates their sum.
|
12
|
+
#
|
13
|
+
# @param [RDF::N3::List] list
|
14
|
+
# @return [RDF::Term]
|
15
|
+
# @see RDF::N3::ListOperator#evaluate
|
16
|
+
def resolve(list)
|
17
|
+
list.to_a.map(&:as_number).reduce(&:*) || RDF::Literal(1) # Empty list product is 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject is a pair of numbers. The object is calculated by dividing the first number of the pair by the second.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-divide
|
6
|
+
class Quotient < RDF::N3::Algebra::ListOperator
|
7
|
+
NAME = :mathQuotient
|
8
|
+
URI = RDF::N3::Math.quotient
|
9
|
+
|
10
|
+
##
|
11
|
+
# The math:quotient operator takes a pair of strings or numbers and calculates their quotient.
|
12
|
+
#
|
13
|
+
#
|
14
|
+
# @param [RDF::N3::List] list
|
15
|
+
# @return [RDF::Term]
|
16
|
+
# @see RDF::N3::ListOperator#evaluate
|
17
|
+
def resolve(list)
|
18
|
+
list.to_a.map(&:as_number).reduce(&:/)
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# The list argument must be a pair of literals.
|
23
|
+
#
|
24
|
+
# @param [RDF::N3::List] list
|
25
|
+
# @return [Boolean]
|
26
|
+
# @see RDF::N3::ListOperator#validate
|
27
|
+
def validate(list)
|
28
|
+
if super && list.all? {|le| le.is_a?(RDF::Literal)} && list.length == 2
|
29
|
+
true
|
30
|
+
else
|
31
|
+
log_error(NAME) {"list is not a pair of literals: #{list.to_sxp}"}
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject is a pair of integers. The object is calculated by dividing the first number of the pair by the second and taking the remainder.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-mod
|
6
|
+
class Remainder < RDF::N3::Algebra::ListOperator
|
7
|
+
NAME = :mathRemainder
|
8
|
+
URI = RDF::N3::Math.remainder
|
9
|
+
|
10
|
+
##
|
11
|
+
# The math:remainder operator takes a pair of strings or numbers and calculates their remainder.
|
12
|
+
#
|
13
|
+
# @param [RDF::N3::List] list
|
14
|
+
# @return [RDF::Term]
|
15
|
+
# @see RDF::N3::ListOperator#evaluate
|
16
|
+
def resolve(list)
|
17
|
+
list.to_a.map(&:as_number).reduce(&:%)
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# The list argument must be a pair of literals.
|
22
|
+
#
|
23
|
+
# @param [RDF::N3::List] list
|
24
|
+
# @return [Boolean]
|
25
|
+
# @see RDF::N3::ListOperator#validate
|
26
|
+
def validate(list)
|
27
|
+
if super && list.all? {|li| li.is_a?(RDF::Literal) && li.as_number.is_a?(RDF::Literal::Integer)} && list.length == 2
|
28
|
+
true
|
29
|
+
else
|
30
|
+
log_error(NAME) {"list is not a pair of integers: #{list.to_sxp}"}
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The object is calulated as the subject rounded to the nearest integer.
|
4
|
+
class Rounded < RDF::N3::Algebra::ResourceOperator
|
5
|
+
NAME = :mathRounded
|
6
|
+
URI = RDF::N3::Math.rounded
|
7
|
+
|
8
|
+
##
|
9
|
+
# The math:rounded operator takes string or number rounds it to the next integer.
|
10
|
+
#
|
11
|
+
# @param [RDF::Term] resource
|
12
|
+
# @param [:subject, :object] position
|
13
|
+
# @return [RDF::Term]
|
14
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
15
|
+
def resolve(resource, position:)
|
16
|
+
case position
|
17
|
+
when :subject
|
18
|
+
return nil unless resource.literal?
|
19
|
+
as_literal(resource.as_number.round)
|
20
|
+
when :object
|
21
|
+
return nil unless resource.literal? || resource.variable?
|
22
|
+
resource
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject is an angle expressed in radians. The object is calulated as the sine value of the subject.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-math-sin
|
6
|
+
class Sin < RDF::N3::Algebra::ResourceOperator
|
7
|
+
NAME = :mathSin
|
8
|
+
URI = RDF::N3::Math.sin
|
9
|
+
|
10
|
+
##
|
11
|
+
# The math:sin operator takes string or number and calculates its sine. The arc sine of a concrete object can also calculate a variable subject.
|
12
|
+
#
|
13
|
+
# @param [RDF::Term] resource
|
14
|
+
# @param [:subject, :object] position
|
15
|
+
# @return [RDF::Term]
|
16
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
17
|
+
def resolve(resource, position:)
|
18
|
+
case resource
|
19
|
+
when RDF::Query::Variable then resource
|
20
|
+
when RDF::Literal
|
21
|
+
case position
|
22
|
+
when :subject
|
23
|
+
as_literal(Math.sin(resource.as_number.object))
|
24
|
+
when :object
|
25
|
+
as_literal(Math.sinh(resource.as_number.object))
|
26
|
+
end
|
27
|
+
else
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Input is either the subject or object
|
34
|
+
#
|
35
|
+
# @return [RDF::Term]
|
36
|
+
def input_operand
|
37
|
+
RDF::N3::List.new(values: operands)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject is an angle expressed in radians. The object is calulated as the hyperbolic sine value of the subject.
|
4
|
+
class SinH < RDF::N3::Algebra::ResourceOperator
|
5
|
+
NAME = :mathSinH
|
6
|
+
URI = RDF::N3::Math.sinh
|
7
|
+
|
8
|
+
##
|
9
|
+
# The math:sinh operator takes string or number and calculates its hyperbolic sine. The inverse hyperbolic sine of a concrete object can also calculate a variable subject.
|
10
|
+
#
|
11
|
+
# @param [RDF::Term] resource
|
12
|
+
# @param [:subject, :object] position
|
13
|
+
# @return [RDF::Term]
|
14
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
15
|
+
def resolve(resource, position:)
|
16
|
+
case resource
|
17
|
+
when RDF::Query::Variable then resource
|
18
|
+
when RDF::Literal
|
19
|
+
case position
|
20
|
+
when :subject
|
21
|
+
as_literal(Math.sinh(resource.as_number.object))
|
22
|
+
when :object
|
23
|
+
as_literal(Math.asinh(resource.as_number.object))
|
24
|
+
end
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Input is either the subject or object
|
32
|
+
#
|
33
|
+
# @return [RDF::Term]
|
34
|
+
def input_operand
|
35
|
+
RDF::N3::List.new(values: operands)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# **schema**:
|
4
|
+
# `($a_1 .. $a_n) math:sum $a_s`
|
5
|
+
#
|
6
|
+
# **summary**:
|
7
|
+
# performs addition of numbers
|
8
|
+
#
|
9
|
+
# **definition**:
|
10
|
+
# `true` if and only if the arithmetic sum of `$a_1, .. $a_n` equals `$a_s`.
|
11
|
+
# Requires either:
|
12
|
+
#
|
13
|
+
# 1. all `$a_1, .., $a_n` to be bound; or
|
14
|
+
# 2. all but one `$a_i` (subject list) to be bound, and `$a_s` to be bound.
|
15
|
+
#
|
16
|
+
# **literal domains**:
|
17
|
+
#
|
18
|
+
# * `$a_1 .. $a_n` : `xs:decimal` (or its derived types), `xs:float`, or `xs:double` (see note on type promotion, and casting from string)
|
19
|
+
# * `$a_s`: `xs:decimal` (or its derived types), `xs:float`, or `xs:double` (see note on type promotion, and casting from string)
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# { ("3" "5") math:sum ?x } => { ?x :valueOf "3 + 5" } .
|
23
|
+
# { (3 5) math:sum ?x } => { ?x :valueOf "3 + 5 = 8" } .
|
24
|
+
#
|
25
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-numeric-add
|
26
|
+
class Sum < RDF::N3::Algebra::ListOperator
|
27
|
+
NAME = :mathSum
|
28
|
+
URI = RDF::N3::Math[:sum]
|
29
|
+
|
30
|
+
##
|
31
|
+
# Evaluates to the sum of the list elements
|
32
|
+
#
|
33
|
+
# @param [RDF::N3::List] list
|
34
|
+
# @return [RDF::Term]
|
35
|
+
# @see RDF::N3::ListOperator#evaluate
|
36
|
+
def resolve(list)
|
37
|
+
list.to_a.map(&:as_number).reduce(&:+) || RDF::Literal(0) # Empty list sums to 0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject is an angle expressed in radians. The object is calulated as the tangent value of the subject.
|
4
|
+
#
|
5
|
+
# @see https://www.w3.org/TR/xpath-functions/#func-math-tan
|
6
|
+
class Tan < RDF::N3::Algebra::ResourceOperator
|
7
|
+
NAME = :mathTan
|
8
|
+
URI = RDF::N3::Math.tan
|
9
|
+
|
10
|
+
##
|
11
|
+
# The math:tan operator takes string or number and calculates its tangent. The arc tangent of a concrete object can also calculate a variable subject.
|
12
|
+
#
|
13
|
+
# @param [RDF::Term] resource
|
14
|
+
# @param [:subject, :object] position
|
15
|
+
# @return [RDF::Term]
|
16
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
17
|
+
def resolve(resource, position:)
|
18
|
+
case resource
|
19
|
+
when RDF::Query::Variable then resource
|
20
|
+
when RDF::Literal
|
21
|
+
case position
|
22
|
+
when :subject
|
23
|
+
as_literal(Math.tan(resource.as_number.object))
|
24
|
+
when :object
|
25
|
+
as_literal(Math.atan(resource.as_number.object))
|
26
|
+
end
|
27
|
+
else
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Input is either the subject or object
|
34
|
+
#
|
35
|
+
# @return [RDF::Term]
|
36
|
+
def input_operand
|
37
|
+
RDF::N3::List.new(values: operands)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module RDF::N3::Algebra::Math
|
2
|
+
##
|
3
|
+
# The subject is an angle expressed in radians. The object is calulated as the tangent value of the subject.
|
4
|
+
class TanH < RDF::N3::Algebra::ResourceOperator
|
5
|
+
NAME = :mathTanH
|
6
|
+
URI = RDF::N3::Math.tanh
|
7
|
+
|
8
|
+
##
|
9
|
+
# The math:tanh operator takes string or number and calculates its hyperbolic tangent. The inverse hyperbolic tangent of a concrete object can also calculate a variable subject.
|
10
|
+
#
|
11
|
+
# @param [RDF::Term] resource
|
12
|
+
# @param [:subject, :object] position
|
13
|
+
# @return [RDF::Term]
|
14
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
15
|
+
def resolve(resource, position:)
|
16
|
+
case resource
|
17
|
+
when RDF::Query::Variable then resource
|
18
|
+
when RDF::Literal
|
19
|
+
case position
|
20
|
+
when :subject
|
21
|
+
as_literal(Math.tanh(resource.as_number.object))
|
22
|
+
when :object
|
23
|
+
as_literal(Math.atanh(resource.as_number.object))
|
24
|
+
end
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Input is either the subject or object
|
32
|
+
#
|
33
|
+
# @return [RDF::Term]
|
34
|
+
def input_operand
|
35
|
+
RDF::N3::List.new(values: operands)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rdf'
|
2
|
+
|
3
|
+
module RDF::N3::Algebra
|
4
|
+
#
|
5
|
+
# A Notation3 Formula combines a graph with a BGP query.
|
6
|
+
class NotImplemented < SPARQL::Algebra::Operator
|
7
|
+
include RDF::N3::Algebra::Builtin
|
8
|
+
|
9
|
+
def initialize(*args, predicate:, **options)
|
10
|
+
raise NotImplementedError, "The #{predicate} operator is not implemented"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module RDF::N3::Algebra
|
2
|
+
##
|
3
|
+
# This is a generic operator where the subject is a literal or binds to a literal and the object is either a constant that equals the evaluation of the subject, or a variable to which the result is bound in a solution
|
4
|
+
class ResourceOperator < SPARQL::Algebra::Operator::Binary
|
5
|
+
include SPARQL::Algebra::Query
|
6
|
+
include SPARQL::Algebra::Update
|
7
|
+
include RDF::N3::Algebra::Builtin
|
8
|
+
|
9
|
+
NAME = :resourceOperator
|
10
|
+
|
11
|
+
##
|
12
|
+
# The operator takes a literal and provides a mechanism for subclasses to operate over (and validate) that argument.
|
13
|
+
#
|
14
|
+
# @param [RDF::Queryable] queryable
|
15
|
+
# the graph or repository to query
|
16
|
+
# @param [RDF::Query::Solutions] solutions
|
17
|
+
# solutions for chained queries
|
18
|
+
# @return [RDF::Query::Solutions]
|
19
|
+
def execute(queryable, solutions:, **options)
|
20
|
+
RDF::Query::Solutions(solutions.map do |solution|
|
21
|
+
subject = operand(0).evaluate(solution.bindings, formulae: formulae) || operand(0)
|
22
|
+
object = operand(1).evaluate(solution.bindings, formulae: formulae) || operand(1)
|
23
|
+
subject = formulae.fetch(subject, subject) if subject.node?
|
24
|
+
object = formulae.fetch(object, object) if object.node?
|
25
|
+
|
26
|
+
log_info(self.class.const_get(:NAME), "subject") {SXP::Generator.string(subject.to_sxp_bin).strip}
|
27
|
+
log_info(self.class.const_get(:NAME), "object") {SXP::Generator.string(object.to_sxp_bin).strip}
|
28
|
+
next unless valid?(subject, object)
|
29
|
+
|
30
|
+
lhs = resolve(subject, position: :subject)
|
31
|
+
if lhs.nil?
|
32
|
+
log_error(self.class.const_get(:NAME), "subject evaluates to null") {subject.inspect}
|
33
|
+
next
|
34
|
+
end
|
35
|
+
|
36
|
+
rhs = resolve(object, position: :object)
|
37
|
+
if rhs.nil?
|
38
|
+
log_error(self.class.const_get(:NAME), "object evaluates to null") {object.inspect}
|
39
|
+
next
|
40
|
+
end
|
41
|
+
|
42
|
+
if object.variable?
|
43
|
+
log_debug(self.class.const_get(:NAME), "result") {SXP::Generator.string(lhs.to_sxp_bin).strip}
|
44
|
+
solution.merge(object.to_sym => lhs)
|
45
|
+
elsif subject.variable?
|
46
|
+
log_debug(self.class.const_get(:NAME), "result") {SXP::Generator.string(rhs.to_sxp_bin).strip}
|
47
|
+
solution.merge(subject.to_sym => rhs)
|
48
|
+
elsif respond_to?(:apply)
|
49
|
+
res = apply(lhs, rhs)
|
50
|
+
log_debug(self.class.const_get(:NAME), "result") {SXP::Generator.string(res.to_sxp_bin).strip}
|
51
|
+
# Return the result applying subject and object
|
52
|
+
case res
|
53
|
+
when RDF::Literal::TRUE
|
54
|
+
solution
|
55
|
+
when RDF::Literal::FALSE
|
56
|
+
nil
|
57
|
+
when RDF::Query::Solution
|
58
|
+
solution.merge(res)
|
59
|
+
else
|
60
|
+
log_error(self.class.const_get(:NAME), "unexpected result type")
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
elsif rhs != lhs
|
64
|
+
log_debug(self.class.const_get(:NAME), "result: false")
|
65
|
+
nil
|
66
|
+
else
|
67
|
+
log_debug(self.class.const_get(:NAME), "result: true")
|
68
|
+
solution
|
69
|
+
end
|
70
|
+
end.compact.uniq)
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Input is generically the subject
|
75
|
+
#
|
76
|
+
# @return [RDF::Term]
|
77
|
+
def input_operand
|
78
|
+
operand(0)
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Subclasses implement `resolve`.
|
83
|
+
#
|
84
|
+
# Returns nil if resource does not validate, given its position
|
85
|
+
#
|
86
|
+
# @param [RDF::Term] resource
|
87
|
+
# @return [RDF::Term]
|
88
|
+
def resolve(resource, position: :subject)
|
89
|
+
raise NotImplemented
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Subclasses may override or supplement validate to perform validation on the list subject
|
94
|
+
#
|
95
|
+
# @param [RDF::Term] subject
|
96
|
+
# @param [RDF::Term] object
|
97
|
+
# @return [Boolean]
|
98
|
+
def valid?(subject, object)
|
99
|
+
case subject
|
100
|
+
when RDF::Query::Variable
|
101
|
+
object.term?
|
102
|
+
when RDF::Term
|
103
|
+
object.term? || object.variable?
|
104
|
+
else
|
105
|
+
false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Returns a literal for the numeric argument.
|
111
|
+
def as_literal(object)
|
112
|
+
case object
|
113
|
+
when Float
|
114
|
+
literal = RDF::Literal(object, canonicalize: true)
|
115
|
+
literal.instance_variable_set(:@string, literal.to_s.downcase)
|
116
|
+
literal
|
117
|
+
else
|
118
|
+
RDF::Literal(object, canonicalize: true)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RDF::N3::Algebra::Str
|
2
|
+
##
|
3
|
+
# The subject is a list of strings. The object is calculated as a concatenation of those strings.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# ("a" "b") string:concatenation :s
|
7
|
+
class Concatenation < RDF::N3::Algebra::ListOperator
|
8
|
+
NAME = :strConcatenation
|
9
|
+
URI = RDF::N3::Str.concatenation
|
10
|
+
|
11
|
+
##
|
12
|
+
# The string:concatenation operator takes a list of terms cast to strings and either binds the result of concatenating them to the output variable, removes a solution that does equal the literal object.
|
13
|
+
#
|
14
|
+
# List entries are stringified using {SPARQL::Algebra::Expression.cast}.
|
15
|
+
#
|
16
|
+
# @param [RDF::N3::List] list
|
17
|
+
# @return [RDF::Term]
|
18
|
+
# @see RDF::N3::ListOperator#evaluate
|
19
|
+
def resolve(list)
|
20
|
+
RDF::Literal(
|
21
|
+
list.to_a.map do |o|
|
22
|
+
SPARQL::Algebra::Expression.cast(RDF::XSD.string, o)
|
23
|
+
end.join("")
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RDF::N3::Algebra::Str
|
2
|
+
# True iff the subject string contains the object string.
|
3
|
+
class Contains < RDF::N3::Algebra::ResourceOperator
|
4
|
+
NAME = :strContains
|
5
|
+
URI = RDF::N3::Str.contains
|
6
|
+
|
7
|
+
##
|
8
|
+
# Resolves inputs as strings.
|
9
|
+
#
|
10
|
+
# @param [RDF::Term] resource
|
11
|
+
# @param [:subject, :object] position
|
12
|
+
# @return [RDF::Literal]
|
13
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
14
|
+
def resolve(resource, position:)
|
15
|
+
resource if resource.term?
|
16
|
+
end
|
17
|
+
|
18
|
+
# Neither subect nor object are considered inputs, and must be resolved before evaluation.
|
19
|
+
def input_operand
|
20
|
+
RDF::N3::List.new
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# @param [String] left
|
25
|
+
# a literal
|
26
|
+
# @param [String] right
|
27
|
+
# a literal
|
28
|
+
# @return [RDF::Literal::Boolean]
|
29
|
+
def apply(left, right)
|
30
|
+
RDF::Literal(left.to_s.include?(right.to_s))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module RDF::N3::Algebra::Str
|
2
|
+
# True iff the subject string contains the object string, with the comparison done ignoring the difference between upper case and lower case characters.
|
3
|
+
class ContainsIgnoringCase < RDF::N3::Algebra::ResourceOperator
|
4
|
+
NAME = :strContainsIgnoringCase
|
5
|
+
URI = RDF::N3::Str.containsIgnoringCase
|
6
|
+
|
7
|
+
##
|
8
|
+
# Resolves inputs as lower-case strings.
|
9
|
+
#
|
10
|
+
# @param [RDF::Term] resource
|
11
|
+
# @param [:subject, :object] position
|
12
|
+
# @return [RDF::Literal]
|
13
|
+
# @see RDF::N3::ResourceOperator#evaluate
|
14
|
+
def resolve(resource, position:)
|
15
|
+
RDF::Literal(resource.to_s.downcase) if resource.term?
|
16
|
+
end
|
17
|
+
|
18
|
+
# Both subject and object are inputs.
|
19
|
+
def input_operand
|
20
|
+
RDF::N3::List.new(values: operands)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# @param [String] left
|
25
|
+
# a literal
|
26
|
+
# @param [String] right
|
27
|
+
# a literal
|
28
|
+
# @return [RDF::Literal::Boolean]
|
29
|
+
def apply(left, right)
|
30
|
+
RDF::Literal(left.to_s.include?(right.to_s))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|