openlogic-rdf 0.3.6

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 (80) hide show
  1. data/AUTHORS +3 -0
  2. data/CREDITS +9 -0
  3. data/README +361 -0
  4. data/UNLICENSE +24 -0
  5. data/VERSION +1 -0
  6. data/bin/rdf +18 -0
  7. data/etc/doap.nt +62 -0
  8. data/lib/df.rb +1 -0
  9. data/lib/rdf/cli.rb +200 -0
  10. data/lib/rdf/format.rb +383 -0
  11. data/lib/rdf/mixin/countable.rb +39 -0
  12. data/lib/rdf/mixin/durable.rb +31 -0
  13. data/lib/rdf/mixin/enumerable.rb +637 -0
  14. data/lib/rdf/mixin/indexable.rb +26 -0
  15. data/lib/rdf/mixin/inferable.rb +5 -0
  16. data/lib/rdf/mixin/mutable.rb +191 -0
  17. data/lib/rdf/mixin/queryable.rb +265 -0
  18. data/lib/rdf/mixin/readable.rb +15 -0
  19. data/lib/rdf/mixin/type_check.rb +21 -0
  20. data/lib/rdf/mixin/writable.rb +152 -0
  21. data/lib/rdf/model/graph.rb +263 -0
  22. data/lib/rdf/model/list.rb +731 -0
  23. data/lib/rdf/model/literal/boolean.rb +121 -0
  24. data/lib/rdf/model/literal/date.rb +73 -0
  25. data/lib/rdf/model/literal/datetime.rb +72 -0
  26. data/lib/rdf/model/literal/decimal.rb +86 -0
  27. data/lib/rdf/model/literal/double.rb +189 -0
  28. data/lib/rdf/model/literal/integer.rb +126 -0
  29. data/lib/rdf/model/literal/numeric.rb +184 -0
  30. data/lib/rdf/model/literal/time.rb +87 -0
  31. data/lib/rdf/model/literal/token.rb +47 -0
  32. data/lib/rdf/model/literal/xml.rb +39 -0
  33. data/lib/rdf/model/literal.rb +373 -0
  34. data/lib/rdf/model/node.rb +156 -0
  35. data/lib/rdf/model/resource.rb +28 -0
  36. data/lib/rdf/model/statement.rb +296 -0
  37. data/lib/rdf/model/term.rb +77 -0
  38. data/lib/rdf/model/uri.rb +570 -0
  39. data/lib/rdf/model/value.rb +133 -0
  40. data/lib/rdf/nquads.rb +152 -0
  41. data/lib/rdf/ntriples/format.rb +48 -0
  42. data/lib/rdf/ntriples/reader.rb +239 -0
  43. data/lib/rdf/ntriples/writer.rb +219 -0
  44. data/lib/rdf/ntriples.rb +104 -0
  45. data/lib/rdf/query/pattern.rb +329 -0
  46. data/lib/rdf/query/solution.rb +252 -0
  47. data/lib/rdf/query/solutions.rb +237 -0
  48. data/lib/rdf/query/variable.rb +221 -0
  49. data/lib/rdf/query.rb +404 -0
  50. data/lib/rdf/reader.rb +511 -0
  51. data/lib/rdf/repository.rb +389 -0
  52. data/lib/rdf/transaction.rb +161 -0
  53. data/lib/rdf/util/aliasing.rb +63 -0
  54. data/lib/rdf/util/cache.rb +139 -0
  55. data/lib/rdf/util/file.rb +38 -0
  56. data/lib/rdf/util/uuid.rb +36 -0
  57. data/lib/rdf/util.rb +6 -0
  58. data/lib/rdf/version.rb +19 -0
  59. data/lib/rdf/vocab/cc.rb +18 -0
  60. data/lib/rdf/vocab/cert.rb +13 -0
  61. data/lib/rdf/vocab/dc.rb +63 -0
  62. data/lib/rdf/vocab/dc11.rb +23 -0
  63. data/lib/rdf/vocab/doap.rb +45 -0
  64. data/lib/rdf/vocab/exif.rb +168 -0
  65. data/lib/rdf/vocab/foaf.rb +69 -0
  66. data/lib/rdf/vocab/geo.rb +13 -0
  67. data/lib/rdf/vocab/http.rb +26 -0
  68. data/lib/rdf/vocab/owl.rb +59 -0
  69. data/lib/rdf/vocab/rdfs.rb +17 -0
  70. data/lib/rdf/vocab/rsa.rb +12 -0
  71. data/lib/rdf/vocab/rss.rb +14 -0
  72. data/lib/rdf/vocab/sioc.rb +93 -0
  73. data/lib/rdf/vocab/skos.rb +36 -0
  74. data/lib/rdf/vocab/wot.rb +21 -0
  75. data/lib/rdf/vocab/xhtml.rb +9 -0
  76. data/lib/rdf/vocab/xsd.rb +58 -0
  77. data/lib/rdf/vocab.rb +215 -0
  78. data/lib/rdf/writer.rb +475 -0
  79. data/lib/rdf.rb +192 -0
  80. metadata +173 -0
@@ -0,0 +1,237 @@
1
+ module RDF; class Query
2
+ ##
3
+ # An RDF basic graph pattern (BGP) query solution sequence.
4
+ #
5
+ # @example Filtering solutions using a hash
6
+ # solutions.filter(:author => RDF::URI("http://ar.to/#self"))
7
+ # solutions.filter(:author => "Arto Bendiken")
8
+ # solutions.filter(:author => [RDF::URI("http://ar.to/#self"), "Arto Bendiken"])
9
+ # solutions.filter(:updated => RDF::Literal(Date.today))
10
+ #
11
+ # @example Filtering solutions using a block
12
+ # solutions.filter { |solution| solution.author.literal? }
13
+ # solutions.filter { |solution| solution.title =~ /^SPARQL/ }
14
+ # solutions.filter { |solution| solution.price < 30.5 }
15
+ # solutions.filter { |solution| solution.bound?(:date) }
16
+ # solutions.filter { |solution| solution.age.datatype == RDF::XSD.integer }
17
+ # solutions.filter { |solution| solution.name.language == :es }
18
+ #
19
+ # @example Reordering solutions based on a variable or proc
20
+ # solutions.order_by(:updated)
21
+ # solutions.order_by(:updated, :created)
22
+ # solutions.order_by(:updated, lambda {|a, b| b <=> a})
23
+ #
24
+ # @example Selecting/Projecting particular variables only
25
+ # solutions.select(:title)
26
+ # solutions.select(:title, :description)
27
+ # solutions.project(:title)
28
+ #
29
+ # @example Eliminating duplicate solutions
30
+ # solutions.distinct
31
+ #
32
+ # @example Limiting the number of solutions
33
+ # solutions.offset(20).limit(10)
34
+ #
35
+ # @example Counting the number of matching solutions
36
+ # solutions.count
37
+ # solutions.count { |solution| solution.price < 30.5 }
38
+ #
39
+ # @example Iterating over all found solutions
40
+ # solutions.each { |solution| puts solution.inspect }
41
+ #
42
+ # @since 0.3.0
43
+ class Solutions < Array
44
+ alias_method :each_solution, :each
45
+
46
+ ##
47
+ # Returns the number of matching query solutions.
48
+ #
49
+ # @overload count
50
+ # @return [Integer]
51
+ #
52
+ # @overload count { |solution| ... }
53
+ # @yield [solution]
54
+ # @yieldparam [RDF::Query::Solution] solution
55
+ # @yieldreturn [Boolean]
56
+ # @return [Integer]
57
+ #
58
+ # @return [Integer]
59
+ def count(&block)
60
+ super
61
+ end
62
+
63
+ ##
64
+ # Returns hash of bindings from each solution. Each bound variable will have
65
+ # an array of bound values representing those from each solution, where a given
66
+ # solution will have just a single value for each bound variable
67
+ # @return [Hash{Symbol => Array<RDF::Term>}]
68
+ def bindings
69
+ bindings = {}
70
+ each do |solution|
71
+ solution.each do |key, value|
72
+ bindings[key] ||= []
73
+ bindings[key] << value
74
+ end
75
+ end
76
+ bindings
77
+ end
78
+
79
+ ##
80
+ # Filters this solution sequence by the given `criteria`.
81
+ #
82
+ # @param [Hash{Symbol => Object}] criteria
83
+ # @yield [solution]
84
+ # @yieldparam [RDF::Query::Solution] solution
85
+ # @yieldreturn [Boolean]
86
+ # @return [void] `self`
87
+ def filter(criteria = {}, &block)
88
+ if block_given?
89
+ self.reject! do |solution|
90
+ !block.call(solution.is_a?(Solution) ? solution : Solution.new(solution))
91
+ end
92
+ else
93
+ self.reject! do |solution|
94
+ solution = solution.is_a?(Solution) ? solution : Solution.new(solution)
95
+ results = criteria.map do |name, value|
96
+ solution[name] == value
97
+ end
98
+ !results.all?
99
+ end
100
+ end
101
+ self
102
+ end
103
+ alias_method :filter!, :filter
104
+
105
+ ##
106
+ # Reorders this solution sequence by the given `variables`.
107
+ #
108
+ # Variables may be symbols or {Query::Variable} instances.
109
+ # A variable may also be a Procedure/Lambda, compatible with {::Enumerable#sort}.
110
+ # This takes two arguments (solutions) and returns -1, 0, or 1 equivalently to <=>.
111
+ #
112
+ # If called with a block, variables are ignored, and the block is invoked with
113
+ # pairs of solutions. The block is expected to return -1, 0, or 1 equivalently to <=>.
114
+ #
115
+ # @param [Array<Proc, Query::Variable, Symbol, #to_sym>] variables
116
+ # @yield [solution]
117
+ # @yieldparam [RDF::Query::Solution] q
118
+ # @yieldparam [RDF::Query::Solution] b
119
+ # @yieldreturn [Integer] -1, 0, or 1 depending on value of comparator
120
+ # @return [void] `self`
121
+ def order(*variables, &block)
122
+ if variables.empty? && !block_given?
123
+ raise ArgumentError, "wrong number of arguments (0 for 1)"
124
+ else
125
+ self.sort! do |a, b|
126
+ if block_given?
127
+ block.call((a.is_a?(Solution) ? a : Solution.new(a)), (b.is_a?(Solution) ? b : Solution.new(b)))
128
+ else
129
+ # Try each variable until a difference is found.
130
+ variables.inject(nil) do |memo, v|
131
+ memo || begin
132
+ comp = v.is_a?(Proc) ? v.call(a, b) : (v = v.to_sym; a[v] <=> b[v])
133
+ comp == 0 ? false : comp
134
+ end
135
+ end || 0
136
+ end
137
+ end
138
+ end
139
+ self
140
+ end
141
+ alias_method :order_by, :order
142
+
143
+ ##
144
+ # Restricts this solution sequence to the given `variables` only.
145
+ #
146
+ # @param [Array<Symbol, #to_sym>] variables
147
+ # @return [void] `self`
148
+ def project(*variables)
149
+ if variables.empty?
150
+ raise ArgumentError, "wrong number of arguments (0 for 1)"
151
+ else
152
+ variables.map!(&:to_sym)
153
+ self.each do |solution|
154
+ solution.bindings.delete_if { |k, v| !variables.include?(k.to_sym) }
155
+ end
156
+ end
157
+ self
158
+ end
159
+ alias_method :select, :project
160
+
161
+ ##
162
+ # Ensures that the solutions in this solution sequence are unique.
163
+ #
164
+ # @return [void] `self`
165
+ def distinct
166
+ self.uniq!
167
+ self
168
+ end
169
+ alias_method :distinct!, :distinct
170
+ alias_method :reduced, :distinct
171
+ alias_method :reduced!, :distinct
172
+
173
+ ##
174
+ # Limits this solution sequence to bindings starting from the `start`
175
+ # offset in the overall solution sequence.
176
+ #
177
+ # @param [Integer, #to_i] start
178
+ # zero or a positive or negative integer
179
+ # @return [void] `self`
180
+ def offset(start)
181
+ case start = start.to_i
182
+ when 0 then nil
183
+ else self.slice!(0...start)
184
+ end
185
+ self
186
+ end
187
+ alias_method :offset!, :offset
188
+
189
+ ##
190
+ # Limits the number of solutions in this solution sequence to a maximum
191
+ # of `length`.
192
+ #
193
+ # @param [Integer, #to_i] length
194
+ # zero or a positive integer
195
+ # @return [void] `self`
196
+ # @raise [ArgumentError] if `length` is negative
197
+ def limit(length)
198
+ length = length.to_i
199
+ raise ArgumentError, "expected zero or a positive integer, got #{length}" if length < 0
200
+ case length
201
+ when 0 then self.clear
202
+ else self.slice!(length..-1) if length < self.size
203
+ end
204
+ self
205
+ end
206
+ alias_method :limit!, :limit
207
+
208
+ ##
209
+ # Returns an array of the distinct variable names used in this solution
210
+ # sequence.
211
+ #
212
+ # @return [Array<Symbol>]
213
+ def variable_names
214
+ variables = self.inject({}) do |result, solution|
215
+ solution.each_name do |name|
216
+ result[name] ||= true
217
+ end
218
+ result
219
+ end
220
+ variables.keys
221
+ end
222
+
223
+ ##
224
+ # Returns `true` if this solution sequence contains bindings for any of
225
+ # the given `variables`.
226
+ #
227
+ # @param [Array<Symbol, #to_sym>] variables
228
+ # an array of variables to check
229
+ # @return [Boolean] `true` or `false`
230
+ # @see RDF::Query::Solution#has_variables?
231
+ # @see RDF::Query#execute
232
+ def have_variables?(variables)
233
+ self.any? { |solution| solution.has_variables?(variables) }
234
+ end
235
+ alias_method :has_variables?, :have_variables?
236
+ end # Solutions
237
+ end; end # RDF::Query
@@ -0,0 +1,221 @@
1
+ class RDF::Query
2
+ ##
3
+ # An RDF query variable.
4
+ #
5
+ # @example Creating a named unbound variable
6
+ # var = RDF::Query::Variable.new(:x)
7
+ # var.unbound? #=> true
8
+ # var.value #=> nil
9
+ #
10
+ # @example Creating an anonymous unbound variable
11
+ # var = RDF::Query::Variable.new
12
+ # var.name #=> :g2166151240
13
+ #
14
+ # @example Unbound variables match any value
15
+ # var === 42 #=> true
16
+ #
17
+ # @example Creating a bound variable
18
+ # var = RDF::Query::Variable.new(:y, 123)
19
+ # var.bound? #=> true
20
+ # var.value #=> 123
21
+ #
22
+ # @example Bound variables match only their actual value
23
+ # var === 42 #=> false
24
+ # var === 123 #=> true
25
+ #
26
+ # @example Getting the variable name
27
+ # var.named? #=> true
28
+ # var.name #=> :y
29
+ # var.to_sym #=> :y
30
+ #
31
+ # @example Rebinding a variable returns the previous value
32
+ # var.bind!(456) #=> 123
33
+ # var.value #=> 456
34
+ #
35
+ # @example Unbinding a previously bound variable
36
+ # var.unbind!
37
+ # var.unbound? #=> true
38
+ #
39
+ # @example Getting the string representation of a variable
40
+ # var = RDF::Query::Variable.new(:x)
41
+ # var.to_s #=> "?x"
42
+ # var = RDF::Query::Variable.new(:y, 123)
43
+ # var.to_s #=> "?y=123"
44
+ #
45
+ class Variable
46
+ include RDF::Term
47
+
48
+ ##
49
+ # The variable's name.
50
+ #
51
+ # @return [Symbol]
52
+ attr_accessor :name
53
+ alias_method :to_sym, :name
54
+
55
+ ##
56
+ # The variable's value.
57
+ #
58
+ # @return [RDF::Term]
59
+ attr_accessor :value
60
+
61
+ ##
62
+ # @param [Symbol, #to_sym] name
63
+ # the variable name
64
+ # @param [RDF::Term] value
65
+ # an optional variable value
66
+ def initialize(name = nil, value = nil)
67
+ @name = (name || "g#{__id__.to_i.abs}").to_sym
68
+ @value = value
69
+ end
70
+
71
+ ##
72
+ # Returns `true`.
73
+ #
74
+ # @return [Boolean]
75
+ # @see RDF::Term#variable?
76
+ # @since 0.1.7
77
+ def variable?
78
+ true
79
+ end
80
+
81
+ ##
82
+ # Returns `true` if this variable has a name.
83
+ #
84
+ # @return [Boolean]
85
+ def named?
86
+ true
87
+ end
88
+
89
+ ##
90
+ # Returns `true` if this variable is bound.
91
+ #
92
+ # @return [Boolean]
93
+ def bound?
94
+ !unbound?
95
+ end
96
+
97
+ ##
98
+ # Returns `true` if this variable is unbound.
99
+ #
100
+ # @return [Boolean]
101
+ def unbound?
102
+ value.nil?
103
+ end
104
+
105
+ ##
106
+ # Returns `true` if this variable is distinguished.
107
+ #
108
+ # @return [Boolean]
109
+ def distinguished?
110
+ @distinguished.nil? || @distinguished
111
+ end
112
+
113
+ ##
114
+ # Sets if variable is distinguished or non-distinguished.
115
+ # By default, variables are distinguished
116
+ #
117
+ # @return [Boolean]
118
+ def distinguished=(value)
119
+ @distinguished = value
120
+ end
121
+
122
+ ##
123
+ # Rebinds this variable to the given `value`.
124
+ #
125
+ # @param [RDF::Term] value
126
+ # @return [RDF::Term] the previous value, if any.
127
+ def bind(value)
128
+ old_value = self.value
129
+ self.value = value
130
+ old_value
131
+ end
132
+ alias_method :bind!, :bind
133
+
134
+ ##
135
+ # Unbinds this variable, discarding any currently bound value.
136
+ #
137
+ # @return [RDF::Term] the previous value, if any.
138
+ def unbind
139
+ old_value = self.value
140
+ self.value = nil
141
+ old_value
142
+ end
143
+ alias_method :unbind!, :unbind
144
+
145
+ ##
146
+ # Returns this variable as `Hash`.
147
+ #
148
+ # @return [Hash{Symbol => RDF::Query::Variable}]
149
+ def variables
150
+ {name => self}
151
+ end
152
+ alias_method :to_hash, :variables
153
+
154
+ ##
155
+ # Returns this variable's bindings (if any) as a `Hash`.
156
+ #
157
+ # @return [Hash{Symbol => RDF::Term}]
158
+ def bindings
159
+ unbound? ? {} : {name => value}
160
+ end
161
+
162
+ ##
163
+ # Returns a hash code for this variable.
164
+ #
165
+ # @return [Fixnum]
166
+ # @since 0.3.0
167
+ def hash
168
+ @name.hash
169
+ end
170
+
171
+ ##
172
+ # Returns `true` if this variable is equivalent to a given `other`
173
+ # variable. Or, to another Term if bound, or to any other Term
174
+ #
175
+ # @param [Object] other
176
+ # @return [Boolean] `true` or `false`
177
+ # @since 0.3.0
178
+ def eql?(other)
179
+ if unbound?
180
+ other.is_a?(RDF::Term) # match any Term when unbound
181
+ elsif other.is_a?(RDF::Query::Variable)
182
+ @name.eql?(other.name)
183
+ else
184
+ value.eql?(other)
185
+ end
186
+ end
187
+ alias_method :==, :eql?
188
+
189
+ ##
190
+ # Compares this variable with the given value.
191
+ #
192
+ # @param [RDF::Term] other
193
+ # @return [Boolean]
194
+ def ===(other)
195
+ if unbound?
196
+ other.is_a?(RDF::Term) # match any Term when unbound
197
+ else
198
+ value === other
199
+ end
200
+ end
201
+
202
+ ##
203
+ # Returns a string representation of this variable.
204
+ #
205
+ # Distinguished variables are indicated with a single `?`.
206
+ #
207
+ # Non-distinguished variables are indicated with a double `??`
208
+ #
209
+ # @example
210
+ # v = Variable.new("a")
211
+ # v.to_s => '?a'
212
+ # v.distinguished = false
213
+ # v.to_s => '??a'
214
+ #
215
+ # @return [String]
216
+ def to_s
217
+ prefix = distinguished? ? '?' : "??"
218
+ unbound? ? "#{prefix}#{name}" : "#{prefix}#{name}=#{value}"
219
+ end
220
+ end # Variable
221
+ end # RDF::Query