rdf-n3 2.2.0 → 3.1.2

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 (101) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +192 -69
  3. data/UNLICENSE +1 -1
  4. data/VERSION +1 -1
  5. data/lib/rdf/n3.rb +11 -8
  6. data/lib/rdf/n3/algebra.rb +204 -0
  7. data/lib/rdf/n3/algebra/builtin.rb +79 -0
  8. data/lib/rdf/n3/algebra/formula.rb +446 -0
  9. data/lib/rdf/n3/algebra/list/append.rb +42 -0
  10. data/lib/rdf/n3/algebra/list/first.rb +24 -0
  11. data/lib/rdf/n3/algebra/list/in.rb +48 -0
  12. data/lib/rdf/n3/algebra/list/last.rb +24 -0
  13. data/lib/rdf/n3/algebra/list/length.rb +24 -0
  14. data/lib/rdf/n3/algebra/list/member.rb +44 -0
  15. data/lib/rdf/n3/algebra/list_operator.rb +83 -0
  16. data/lib/rdf/n3/algebra/log/conclusion.rb +65 -0
  17. data/lib/rdf/n3/algebra/log/conjunction.rb +36 -0
  18. data/lib/rdf/n3/algebra/log/content.rb +34 -0
  19. data/lib/rdf/n3/algebra/log/equal_to.rb +34 -0
  20. data/lib/rdf/n3/algebra/log/implies.rb +102 -0
  21. data/lib/rdf/n3/algebra/log/includes.rb +70 -0
  22. data/lib/rdf/n3/algebra/log/n3_string.rb +34 -0
  23. data/lib/rdf/n3/algebra/log/not_equal_to.rb +23 -0
  24. data/lib/rdf/n3/algebra/log/not_includes.rb +27 -0
  25. data/lib/rdf/n3/algebra/log/output_string.rb +40 -0
  26. data/lib/rdf/n3/algebra/log/parsed_as_n3.rb +36 -0
  27. data/lib/rdf/n3/algebra/log/semantics.rb +40 -0
  28. data/lib/rdf/n3/algebra/math/absolute_value.rb +36 -0
  29. data/lib/rdf/n3/algebra/math/acos.rb +26 -0
  30. data/lib/rdf/n3/algebra/math/acosh.rb +26 -0
  31. data/lib/rdf/n3/algebra/math/asin.rb +26 -0
  32. data/lib/rdf/n3/algebra/math/asinh.rb +26 -0
  33. data/lib/rdf/n3/algebra/math/atan.rb +26 -0
  34. data/lib/rdf/n3/algebra/math/atanh.rb +26 -0
  35. data/lib/rdf/n3/algebra/math/ceiling.rb +28 -0
  36. data/lib/rdf/n3/algebra/math/cos.rb +40 -0
  37. data/lib/rdf/n3/algebra/math/cosh.rb +38 -0
  38. data/lib/rdf/n3/algebra/math/difference.rb +40 -0
  39. data/lib/rdf/n3/algebra/math/equal_to.rb +54 -0
  40. data/lib/rdf/n3/algebra/math/exponentiation.rb +35 -0
  41. data/lib/rdf/n3/algebra/math/floor.rb +28 -0
  42. data/lib/rdf/n3/algebra/math/greater_than.rb +41 -0
  43. data/lib/rdf/n3/algebra/math/less_than.rb +41 -0
  44. data/lib/rdf/n3/algebra/math/negation.rb +38 -0
  45. data/lib/rdf/n3/algebra/math/not_equal_to.rb +25 -0
  46. data/lib/rdf/n3/algebra/math/not_greater_than.rb +25 -0
  47. data/lib/rdf/n3/algebra/math/not_less_than.rb +25 -0
  48. data/lib/rdf/n3/algebra/math/product.rb +20 -0
  49. data/lib/rdf/n3/algebra/math/quotient.rb +36 -0
  50. data/lib/rdf/n3/algebra/math/remainder.rb +35 -0
  51. data/lib/rdf/n3/algebra/math/rounded.rb +26 -0
  52. data/lib/rdf/n3/algebra/math/sin.rb +40 -0
  53. data/lib/rdf/n3/algebra/math/sinh.rb +38 -0
  54. data/lib/rdf/n3/algebra/math/sum.rb +40 -0
  55. data/lib/rdf/n3/algebra/math/tan.rb +40 -0
  56. data/lib/rdf/n3/algebra/math/tanh.rb +38 -0
  57. data/lib/rdf/n3/algebra/not_implemented.rb +13 -0
  58. data/lib/rdf/n3/algebra/resource_operator.rb +123 -0
  59. data/lib/rdf/n3/algebra/str/concatenation.rb +27 -0
  60. data/lib/rdf/n3/algebra/str/contains.rb +33 -0
  61. data/lib/rdf/n3/algebra/str/contains_ignoring_case.rb +33 -0
  62. data/lib/rdf/n3/algebra/str/ends_with.rb +33 -0
  63. data/lib/rdf/n3/algebra/str/equal_ignoring_case.rb +34 -0
  64. data/lib/rdf/n3/algebra/str/format.rb +17 -0
  65. data/lib/rdf/n3/algebra/str/greater_than.rb +38 -0
  66. data/lib/rdf/n3/algebra/str/less_than.rb +33 -0
  67. data/lib/rdf/n3/algebra/str/matches.rb +37 -0
  68. data/lib/rdf/n3/algebra/str/not_equal_ignoring_case.rb +17 -0
  69. data/lib/rdf/n3/algebra/str/not_greater_than.rb +17 -0
  70. data/lib/rdf/n3/algebra/str/not_less_than.rb +17 -0
  71. data/lib/rdf/n3/algebra/str/not_matches.rb +18 -0
  72. data/lib/rdf/n3/algebra/str/replace.rb +35 -0
  73. data/lib/rdf/n3/algebra/str/scrape.rb +35 -0
  74. data/lib/rdf/n3/algebra/str/starts_with.rb +33 -0
  75. data/lib/rdf/n3/algebra/time/day.rb +35 -0
  76. data/lib/rdf/n3/algebra/time/day_of_week.rb +27 -0
  77. data/lib/rdf/n3/algebra/time/gm_time.rb +29 -0
  78. data/lib/rdf/n3/algebra/time/hour.rb +35 -0
  79. data/lib/rdf/n3/algebra/time/in_seconds.rb +59 -0
  80. data/lib/rdf/n3/algebra/time/local_time.rb +29 -0
  81. data/lib/rdf/n3/algebra/time/minute.rb +35 -0
  82. data/lib/rdf/n3/algebra/time/month.rb +35 -0
  83. data/lib/rdf/n3/algebra/time/second.rb +35 -0
  84. data/lib/rdf/n3/algebra/time/timezone.rb +36 -0
  85. data/lib/rdf/n3/algebra/time/year.rb +29 -0
  86. data/lib/rdf/n3/extensions.rb +221 -0
  87. data/lib/rdf/n3/format.rb +66 -1
  88. data/lib/rdf/n3/list.rb +630 -0
  89. data/lib/rdf/n3/reader.rb +834 -492
  90. data/lib/rdf/n3/reasoner.rb +282 -0
  91. data/lib/rdf/n3/refinements.rb +178 -0
  92. data/lib/rdf/n3/repository.rb +332 -0
  93. data/lib/rdf/n3/terminals.rb +80 -0
  94. data/lib/rdf/n3/vocab.rb +36 -3
  95. data/lib/rdf/n3/writer.rb +476 -239
  96. metadata +187 -68
  97. data/AUTHORS +0 -1
  98. data/History.markdown +0 -99
  99. data/lib/rdf/n3/patches/array_hacks.rb +0 -53
  100. data/lib/rdf/n3/reader/meta.rb +0 -641
  101. data/lib/rdf/n3/reader/parser.rb +0 -237
@@ -0,0 +1,42 @@
1
+ module RDF::N3::Algebra::List
2
+ ##
3
+ # Iff the subject is a list of lists and the concatenation of all those lists is the object, then this is true. The object can be calculated as a function of the subject.
4
+ #
5
+ # @example
6
+ # ( (1 2) (3 4) ) list:append (1 2 3 4).
7
+ #
8
+ # The object can be calculated as a function of the subject.
9
+ class Append < RDF::N3::Algebra::ListOperator
10
+ NAME = :listAppend
11
+ URI = RDF::N3::List.append
12
+
13
+ ##
14
+ # Resolves this operator using the given variable `bindings`.
15
+ # If the last operand is a variable, it creates a solution for each element in the list.
16
+ #
17
+ # @param [RDF::N3::List] list
18
+ # @return [RDF::Term]
19
+ # @see RDF::N3::ListOperator#evaluate
20
+ def resolve(list)
21
+ flattened = list.to_a.map(&:to_a).flatten
22
+ # Bind a new list based on the values, whos subject use made up from original list subjects
23
+ subj = RDF::Node.intern(list.map(&:subject).hash)
24
+ RDF::N3::List.new(subject: subj, values: flattened)
25
+ end
26
+
27
+ ##
28
+ # The list argument must be a pair of literals.
29
+ #
30
+ # @param [RDF::N3::List] list
31
+ # @return [Boolean]
32
+ # @see RDF::N3::ListOperator#validate
33
+ def validate(list)
34
+ if super && list.to_a.all? {|li| li.list?}
35
+ true
36
+ else
37
+ log_error(NAME) {"operand is not a list of lists: #{list.to_sxp}"}
38
+ false
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ module RDF::N3::Algebra::List
2
+ ##
3
+ # Iff the subject is a list and the object is the first thing that list, then this is true. The object can be calculated as a function of the list.
4
+ #
5
+ # @example
6
+ # { ( 1 2 3 4 5 6 ) list:first 1 } => { :test1 a :SUCCESS }.
7
+ #
8
+ # The object can be calculated as a function of the list.
9
+ class First < RDF::N3::Algebra::ListOperator
10
+ NAME = :listFirst
11
+ URI = RDF::N3::List.first
12
+
13
+ ##
14
+ # Resolves this operator using the given variable `bindings`.
15
+ # If the last operand is a variable, it creates a solution for each element in the list.
16
+ #
17
+ # @param [RDF::N3::List] list
18
+ # @return [RDF::Term]
19
+ # @see RDF::N3::ListOperator#evaluate
20
+ def resolve(list)
21
+ list.first
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,48 @@
1
+ module RDF::N3::Algebra::List
2
+ ##
3
+ # Iff the object is a list and the subject is in that list, then this is true.
4
+ #
5
+ # @example
6
+ # { 1 list:in ( 1 2 3 4 5 ) } => { :test4a a :SUCCESS }.
7
+ class In < RDF::N3::Algebra::ListOperator
8
+ NAME = :listIn
9
+ URI = RDF::N3::List.in
10
+
11
+ ##
12
+ # Evaluates this operator using the given variable `bindings`.
13
+ # If the first operand is a variable, it creates a solution for each element in the list.
14
+ #
15
+ # @param [RDF::Queryable] queryable
16
+ # the graph or repository to query
17
+ # @param [RDF::Query::Solutions] solutions
18
+ # solutions for chained queries
19
+ # @return [RDF::Query::Solutions]
20
+ def execute(queryable, solutions:, **options)
21
+ RDF::Query::Solutions(solutions.map do |solution|
22
+ subject = operand(0).evaluate(solution.bindings, formulae: formulae) || operand(0)
23
+ # Might be a variable or node evaluating to a list in queryable, or might be a list with variables
24
+ list = operand(1).evaluate(solution.bindings, formulae: formulae)
25
+ next unless list
26
+ # If it evaluated to a BNode, re-expand as a list
27
+ list = RDF::N3::List.try_list(list, queryable).evaluate(solution.bindings, formulae: formulae)
28
+
29
+ log_debug(NAME) {"subject: #{subject.to_sxp}, list: #{list.to_sxp}"}
30
+ unless list.list? && list.valid?
31
+ log_error(NAME) {"operand is not a list: #{list.to_sxp}"}
32
+ next
33
+ end
34
+
35
+ if subject.variable?
36
+ # Bind all list entries to this solution, creates an array of solutions
37
+ list.to_a.map do |term|
38
+ solution.merge(subject.to_sym => term)
39
+ end
40
+ elsif list.to_a.include?(subject)
41
+ solution
42
+ else
43
+ nil
44
+ end
45
+ end.flatten.compact.uniq)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ module RDF::N3::Algebra::List
2
+ ##
3
+ # Iff the subject is a list and the object is the last thing that list, then this is true. The object can be calculated as a function of the list.
4
+ #
5
+ # @example
6
+ # { ( 1 2 3 4 5 6 ) list:last 6 } => { :test1 a :SUCCESS }.
7
+ #
8
+ # The object can be calculated as a function of the list.
9
+ class Last < RDF::N3::Algebra::ListOperator
10
+ NAME = :listLast
11
+ URI = RDF::N3::List.last
12
+
13
+ ##
14
+ # Resolves this operator using the given variable `bindings`.
15
+ # If the last operand is a variable, it creates a solution for each element in the list.
16
+ #
17
+ # @param [RDF::N3::List] list
18
+ # @return [RDF::Term]
19
+ # @see RDF::N3::ListOperator#evaluate
20
+ def resolve(list)
21
+ list.last
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ module RDF::N3::Algebra::List
2
+ ##
3
+ # Iff the subject is a list and the object is the last thing that list, then this is true. The object can be calculated as a function of the list.
4
+ #
5
+ # @example
6
+ # { ( 1 2 3 4 5 6 ) list:length 6 } => { :test1 a :SUCCESS }.
7
+ #
8
+ # The object can be calculated as a function of the list.
9
+ class Length < RDF::N3::Algebra::ListOperator
10
+ NAME = :listLength
11
+ URI = RDF::N3::List.length
12
+
13
+ ##
14
+ # Resolves this operator using the given variable `bindings`.
15
+ # If the last operand is a variable, it creates a solution for each element in the list.
16
+ #
17
+ # @param [RDF::N3::List] list
18
+ # @return [RDF::Term]
19
+ # @see RDF::N3::ListOperator#evaluate
20
+ def resolve(list)
21
+ RDF::Literal(list.length)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,44 @@
1
+ module RDF::N3::Algebra::List
2
+ ##
3
+ # Iff the subject is a list and the object is in that list, then this is true.
4
+ class Member < RDF::N3::Algebra::ListOperator
5
+ NAME = :listMember
6
+ URI = RDF::N3::List.member
7
+
8
+ ##
9
+ # Evaluates this operator using the given variable `bindings`.
10
+ # If the last operand is a variable, it creates a solution for each element in the list.
11
+ #
12
+ # @param [RDF::Queryable] queryable
13
+ # the graph or repository to query
14
+ # @param [RDF::Query::Solutions] solutions
15
+ # solutions for chained queries
16
+ # @return [RDF::Query::Solutions]
17
+ def execute(queryable, solutions:, **options)
18
+ RDF::Query::Solutions(solutions.map do |solution|
19
+ list = operand(0).evaluate(solution.bindings, formulae: formulae)
20
+ next unless list
21
+ list = RDF::N3::List.try_list(list, queryable).evaluate(solution.bindings, formulae: formulae)
22
+ object = operand(1).evaluate(solution.bindings, formulae: formulae) || operand(1)
23
+ object = formulae[object].deep_dup if object.node? && formulae.has_key?(object)
24
+
25
+ log_debug(NAME) {"list: #{list.to_sxp}, object: #{object.to_sxp}"}
26
+ unless list.list? && list.valid?
27
+ log_error(NAME) {"operand is not a list: #{list.to_sxp}"}
28
+ next
29
+ end
30
+
31
+ if object.variable?
32
+ # Bind all list entries to this solution, creates an array of solutions
33
+ list.to_a.map do |term|
34
+ solution.merge(object.to_sym => term)
35
+ end
36
+ elsif list.to_a.include?(object)
37
+ solution
38
+ else
39
+ nil
40
+ end
41
+ end.flatten.compact.uniq)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,83 @@
1
+ module RDF::N3::Algebra
2
+ ##
3
+ # This is a generic operator where the subject is a list or binds to a list 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 ListOperator < SPARQL::Algebra::Operator::Binary
5
+ include SPARQL::Algebra::Query
6
+ include SPARQL::Algebra::Update
7
+ include RDF::N3::Algebra::Builtin
8
+
9
+ NAME = :listOperator
10
+
11
+ ##
12
+ # The operator takes a list and provides a mechanism for subclasses to operate over (and validate) that list 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
+ # Might be a variable or node evaluating to a list in queryable, or might be a list with variables
22
+ subject = operand(0).evaluate(solution.bindings, formulae: formulae)
23
+ next unless subject
24
+ # If it evaluated to a BNode, re-expand as a list
25
+ subject = RDF::N3::List.try_list(subject, queryable).evaluate(solution.bindings, formulae: formulae)
26
+ object = operand(1).evaluate(solution.bindings, formulae: formulae) || operand(1)
27
+ object = formulae.fetch(object, object) if object.node?
28
+
29
+ log_info(self.class.const_get(:NAME), "subject") {SXP::Generator.string(subject.to_sxp_bin).strip}
30
+ log_info(self.class.const_get(:NAME), "object") {SXP::Generator.string(object.to_sxp_bin).strip}
31
+ next unless validate(subject)
32
+
33
+ lhs = resolve(subject)
34
+ if lhs.nil?
35
+ log_error(self.class.const_get(:NAME), "subject evaluates to null") {subject.inspect}
36
+ next
37
+ end
38
+
39
+ if object.variable?
40
+ log_debug(self.class.const_get(:NAME), "result") {SXP::Generator.string(lhs.to_sxp_bin).strip}
41
+ solution.merge(object.to_sym => lhs)
42
+ elsif object != lhs
43
+ log_debug(self.class.const_get(:NAME), "result: false")
44
+ nil
45
+ else
46
+ log_debug(self.class.const_get(:NAME), "result: true")
47
+ solution
48
+ end
49
+ end.compact.uniq)
50
+ end
51
+
52
+ ##
53
+ # Input is generically the subject
54
+ #
55
+ # @return [RDF::Term]
56
+ def input_operand
57
+ operand(0)
58
+ end
59
+
60
+ ##
61
+ # Subclasses implement `resolve`.
62
+ #
63
+ # @param [RDF::N3::List] list
64
+ # @return [RDF::Term]
65
+ def resolve(list)
66
+ raise NotImplemented
67
+ end
68
+
69
+ ##
70
+ # Subclasses may override or supplement validate to perform validation on the list subject
71
+ #
72
+ # @param [RDF::N3::List] list
73
+ # @return [Boolean]
74
+ def validate(list)
75
+ if list.list? && list.valid?
76
+ true
77
+ else
78
+ log_error(NAME) {"operand is not a list: #{list.to_sxp}"}
79
+ false
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,65 @@
1
+ module RDF::N3::Algebra::Log
2
+ ##
3
+ # All possible conclusions which can be drawn from a formula.
4
+ #
5
+ # The object of this function, a formula, is the set of conclusions which can be drawn from the subject formula, by successively applying any rules it contains to the data it contains. This is equivalent to cwm's "--think" command line function. It does use built-ins, so it may for example indirectly invoke other documents, validate signatures, etc.
6
+ class Conclusion < RDF::N3::Algebra::ResourceOperator
7
+ NAME = :logConclusion
8
+ URI = RDF::N3::Log.conclusion
9
+
10
+ ##
11
+ # Evaluates this operator by creating a new formula containing the triples generated by reasoning over the input formula using think.
12
+ #
13
+ # The subject is evaluated into an isolated repository so that conclusions evaluated when evaluating the subject are not necessarily conclusions resulting from evaluating this operator.
14
+ #
15
+ # @param [RDF::N3::Algebra:Formula] resource
16
+ # @return [RDF::N3::Algebra::Formula]
17
+ # @see RDF::N3::ListOperator#evaluate
18
+ def resolve(resource, position:)
19
+ return resource unless position == :subject
20
+
21
+ log_depth do
22
+ reasoner = RDF::N3::Reasoner.new(resource, **@options)
23
+ conclusions = RDF::N3::Repository.new
24
+ reasoner.execute(think: true) {|stmt| conclusions << stmt}
25
+
26
+ # The result is a formula containing the conclusions
27
+ form = RDF::N3::Algebra::Formula.from_enumerable(conclusions, **@options).deep_dup
28
+
29
+ log_info("#{NAME} resolved") {SXP::Generator.string form.to_sxp_bin}
30
+ form
31
+ end
32
+ end
33
+
34
+ ##
35
+ # To be valid, subject must be a formula, and object a formula or variable.
36
+ #
37
+ # @param [RDF::Term] subject
38
+ # @param [RDF::Term] object
39
+ # @return [Boolean]
40
+ def valid?(subject, object)
41
+ subject.formula? && (object.formula? || object.is_a?(RDF::Query::Variable))
42
+ end
43
+
44
+ ##
45
+ # Return subject operand.
46
+ #
47
+ # @return [RDF::Term]
48
+ def input_operand
49
+ operands.first
50
+ end
51
+
52
+ ##
53
+ # Yields statements, and de-asserts `inferred` from the subject.
54
+ #
55
+ # @yield [statement]
56
+ # each matching statement
57
+ # @yieldparam [RDF::Statement] solution
58
+ # @yieldreturn [void] ignored
59
+ def each(solutions:, &block)
60
+ super do |stmt|
61
+ block.call(RDF::Statement.from(stmt.to_quad))
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,36 @@
1
+ module RDF::N3::Algebra::Log
2
+ ##
3
+ # A function to merge formulae: logical AND.
4
+ #
5
+ # The subject is a list of formulae. The object, which can be generated, is a formula containing a copy of each of the formulae in the list on the left. A cwm built-in function.
6
+ class Conjunction < RDF::N3::Algebra::ListOperator
7
+ NAME = :logConjunction
8
+ URI = RDF::N3::Log.conjunction
9
+
10
+ ##
11
+ # Evaluates this operator by creating a new formula containing the triples from each of the formulae in the list.
12
+ #
13
+ # @param [RDF::N3::List] list
14
+ # @return [RDF::N3::Algebra::Formula]
15
+ # @see RDF::N3::ListOperator#evaluate
16
+ def resolve(list)
17
+ form = RDF::N3::Algebra::Formula.new(graph_name: RDF::Node.intern(list.hash))
18
+ log_debug(NAME, "list hash") {form.graph_name}
19
+
20
+ list.each do |f|
21
+ form.operands.push(*f.operands)
22
+ end
23
+ form = form.dup
24
+ log_info(NAME, "result") {SXP::Generator.string form.to_sxp_bin}
25
+ form
26
+ end
27
+
28
+ ##
29
+ # Return subject operand.
30
+ #
31
+ # @return [RDF::Term]
32
+ def input_operand
33
+ operands.first
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ module RDF::N3::Algebra::Log
2
+ ##
3
+ # This connects a document and a string that represents it.
4
+ #
5
+ # (Cwm knows how to go get a document in order to evaluate this.)
6
+ #
7
+ # Note that the content-type of the information is not given and so must be known or guessed.
8
+ class Content < RDF::N3::Algebra::ResourceOperator
9
+ NAME = :logContent
10
+ URI = RDF::N3::Log.content
11
+
12
+ ##
13
+ # Reads the subject into the object.
14
+ #
15
+ # Returns nil if resource does not validate, given its position
16
+ #
17
+ # @param [RDF::N3::List] resource
18
+ # @return [RDF::Term]
19
+ def resolve(resource, position: :subject)
20
+ case position
21
+ when :subject
22
+ return nil unless resource.literal? || resource.uri?
23
+ content = begin
24
+ as_literal(RDF::Util::File.open_file(resource) {|f| f.read})
25
+ rescue IOError
26
+ nil
27
+ end
28
+ when :object
29
+ return nil unless resource.literal? || resource.variable?
30
+ resource
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ module RDF::N3::Algebra::Log
2
+ ##
3
+ # True if the subject and object are the same RDF node (symbol or literal). Do not confuse with owl:sameAs. A cwm built-in logical operator, RDF graph level.
4
+ class EqualTo < RDF::N3::Algebra::ResourceOperator
5
+ NAME = :logEqualTo
6
+ URI = RDF::N3::Log.equalTo
7
+
8
+ ##
9
+ # Resolves inputs as terms.
10
+ #
11
+ # @param [RDF::Term] resource
12
+ # @param [:subject, :object] position
13
+ # @return [RDF::Literal]
14
+ # @see RDF::N3::ResourceOperator#evaluate
15
+ def resolve(resource, position:)
16
+ resource if resource.term?
17
+ end
18
+
19
+ # Both subject and object are inputs.
20
+ def input_operand
21
+ RDF::N3::List.new(values: operands)
22
+ end
23
+
24
+ ##
25
+ # @param [RDF::Literal] left
26
+ # a literal
27
+ # @param [RDF::Literal] right
28
+ # a literal
29
+ # @return [RDF::Literal::Boolean]
30
+ def apply(left, right)
31
+ RDF::Literal(left.sameTerm?(right))
32
+ end
33
+ end
34
+ end