rdf 0.0.5 → 0.0.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.
@@ -0,0 +1,139 @@
1
+ module RDF class Query
2
+ ##
3
+ # An RDF query solution.
4
+ #
5
+ # @example Iterating over every binding in the solution
6
+ # solution.each_binding { |name, value| puts value.inspect }
7
+ # solution.each_variable { |variable| puts variable.value.inspect }
8
+ #
9
+ # @example Iterating over every value in the solution
10
+ # solution.each_value { |value| puts value.inspect }
11
+ #
12
+ # @example Checking whether a variable is bound or unbound
13
+ # solution.bound?(:title)
14
+ # solution.unbound?(:mbox)
15
+ #
16
+ # @example Retrieving the value of a bound variable
17
+ # solution[:mbox]
18
+ # solution.mbox
19
+ #
20
+ # @example Retrieving all bindings in the solution as a `Hash`
21
+ # solution.to_hash #=> {:mbox => "jrhacker@example.org", ...}
22
+ #
23
+ class Solution
24
+ undef_method *(instance_methods - %w(__id__ __send__ __class__ __eval__ instance_eval inspect class object_id))
25
+
26
+ include Enumerable
27
+
28
+ ##
29
+ # @param [Hash{Symbol => Value}] bindings
30
+ def initialize(bindings = {})
31
+ @bindings = bindings
32
+ end
33
+
34
+ ##
35
+ # Enumerates over every variable binding in this solution.
36
+ #
37
+ # @yield [name, value]
38
+ # @yieldparam [Symbol, Value]
39
+ # @return [Enumerator]
40
+ def each_binding(&block)
41
+ @bindings.each(&block)
42
+ end
43
+
44
+ alias_method :each, :each_binding
45
+
46
+ ##
47
+ # Enumerates over every variable name in this solution.
48
+ #
49
+ # @yield [name]
50
+ # @yieldparam [Symbol]
51
+ # @return [Enumerator]
52
+ def each_name(&block)
53
+ @bindings.each_key(&block)
54
+ end
55
+
56
+ alias_method :each_key, :each_name
57
+
58
+ ##
59
+ # Enumerates over every variable value in this solution.
60
+ #
61
+ # @yield [value]
62
+ # @yieldparam [Value]
63
+ # @return [Enumerator]
64
+ def each_value(&block)
65
+ @bindings.each_value(&block)
66
+ end
67
+
68
+ ##
69
+ # Enumerates over every variable in this solution.
70
+ #
71
+ # @yield [variable]
72
+ # @yieldparam [Variable]
73
+ # @return [Enumerator]
74
+ def each_variable(&block)
75
+ @bindings.each do |name, value|
76
+ block.call(Variable.new(name, value))
77
+ end
78
+ end
79
+
80
+ ##
81
+ # Returns `true` if the variable `name` is bound in this solution.
82
+ #
83
+ # @param [Symbol] name
84
+ # @return [Boolean]
85
+ def bound?(name)
86
+ !unbound?(name)
87
+ end
88
+
89
+ ##
90
+ # Returns `true` if the variable `name` is unbound in this solution.
91
+ #
92
+ # @param [Symbol] name
93
+ # @return [Boolean]
94
+ def unbound?(name)
95
+ @bindings[name.to_sym].nil?
96
+ end
97
+
98
+ ##
99
+ # Returns the value of the variable `name`.
100
+ #
101
+ # @param [Symbol] name
102
+ # @return [Value]
103
+ def [](name)
104
+ @bindings[name.to_sym]
105
+ end
106
+
107
+ ##
108
+ # @return [Array<Array(Symbol, Value)>}
109
+ def to_a
110
+ @bindings.to_a
111
+ end
112
+
113
+ ##
114
+ # @return [Hash{Symbol => Value}}
115
+ def to_hash
116
+ @bindings.dup
117
+ end
118
+
119
+ ##
120
+ # @return [String]
121
+ def inspect
122
+ sprintf("#<%s:%#0x(%s)>", self.class.name, object_id, @bindings.inspect)
123
+ end
124
+
125
+ protected
126
+
127
+ ##
128
+ # @param [Symbol] name
129
+ # @return [Value]
130
+ def method_missing(name, *args, &block)
131
+ if args.empty? && @bindings.has_key?(name.to_sym)
132
+ @bindings[name.to_sym]
133
+ else
134
+ super
135
+ end
136
+ end
137
+
138
+ end
139
+ end end
@@ -0,0 +1,145 @@
1
+ module RDF class Query
2
+ ##
3
+ # An RDF query variable.
4
+ #
5
+ # @example Creating an unbound variable
6
+ # var = RDF::Query::Variable.new(:x)
7
+ # var.unbound? #=> true
8
+ # var.value #=> nil
9
+ #
10
+ # @example Unbound variables match any value
11
+ # var === 42 #=> true
12
+ #
13
+ # @example Creating a bound variable
14
+ # var = RDF::Query::Variable.new(:y, 123)
15
+ # var.bound? #=> true
16
+ # var.value #=> 123
17
+ #
18
+ # @example Bound variables match only their actual value
19
+ # var === 42 #=> false
20
+ # var === 123 #=> true
21
+ #
22
+ # @example Getting the variable name
23
+ # var.named? #=> true
24
+ # var.name #=> :y
25
+ # var.to_sym #=> :y
26
+ #
27
+ # @example Rebinding a variable returns the previous value
28
+ # var.bind!(456) #=> 123
29
+ # var.value #=> 456
30
+ #
31
+ # @example Unbinding a previously bound variable
32
+ # var.unbind!
33
+ # var.unbound? #=> true
34
+ #
35
+ # @example Getting the string representation of a variable
36
+ # var = RDF::Query::Variable.new(:x)
37
+ # var.to_s #=> "?x"
38
+ # var = RDF::Query::Variable.new(:y, 123)
39
+ # var.to_s #=> "?y=123"
40
+ #
41
+ class Variable < Value
42
+ # @return [Symbol] The variable's name.
43
+ attr_accessor :name
44
+
45
+ alias_method :to_sym, :name
46
+
47
+ # @return [Value] The variable's value.
48
+ attr_accessor :value
49
+
50
+ ##
51
+ # @param [Symbol] name
52
+ # @param [Value] value
53
+ def initialize(name, value = nil)
54
+ @name, @value = name.to_sym, value
55
+ end
56
+
57
+ ##
58
+ # Returns `true` if this variable has a name.
59
+ #
60
+ # @return [Boolean]
61
+ def named?
62
+ true
63
+ end
64
+
65
+ ##
66
+ # Returns `true` if this variable is bound.
67
+ #
68
+ # @return [Boolean]
69
+ def bound?
70
+ !unbound?
71
+ end
72
+
73
+ ##
74
+ # Returns `true` if this variable is unbound.
75
+ #
76
+ # @return [Boolean]
77
+ def unbound?
78
+ value.nil?
79
+ end
80
+
81
+ ##
82
+ # Rebinds this variable to the given `value`.
83
+ #
84
+ # @param [Value] value
85
+ # @return [Value] The previous value, if any.
86
+ def bind(value)
87
+ old_value = self.value
88
+ self.value = value
89
+ old_value
90
+ end
91
+
92
+ alias_method :bind!, :bind
93
+
94
+ ##
95
+ # Unbinds this variable, discarding any currently bound value.
96
+ #
97
+ # @return [Value] The previous value, if any.
98
+ def unbind
99
+ old_value = self.value
100
+ self.value = nil
101
+ old_value
102
+ end
103
+
104
+ alias_method :unbind!, :unbind
105
+
106
+ ##
107
+ # Returns this variable as `Hash`.
108
+ #
109
+ # @return [Hash{Symbol => Variable}]
110
+ def variables
111
+ { name => self }
112
+ end
113
+
114
+ alias_method :to_hash, :variables
115
+
116
+ ##
117
+ # Returns this variable's bindings (if any) as a `Hash`.
118
+ #
119
+ # @return [Hash{Symbol => Value}]
120
+ def bindings
121
+ unbound? ? {} : { name => value }
122
+ end
123
+
124
+ ##
125
+ # Compares this variable with the given value.
126
+ #
127
+ # @param [Value] other
128
+ # @return [Boolean]
129
+ def ===(other)
130
+ if unbound?
131
+ true # match anything when unbound
132
+ else
133
+ value === other
134
+ end
135
+ end
136
+
137
+ ##
138
+ # Returns a string representation of this variable.
139
+ #
140
+ # @return [String]
141
+ def to_s
142
+ unbound? ? "?#{name}" : "?#{name}=#{value}"
143
+ end
144
+ end
145
+ end end
data/lib/rdf/reader.rb CHANGED
@@ -4,15 +4,10 @@ module RDF
4
4
  #
5
5
  # @abstract
6
6
  class Reader
7
- autoload :NTriples, 'rdf/reader/ntriples'
7
+ autoload :NTriples, 'rdf/reader/ntriples' # @deprecated
8
8
 
9
9
  include Enumerable
10
10
 
11
- @@subclasses = []
12
- @@file_extensions = {}
13
- @@content_types = {}
14
- @@content_encoding = {}
15
-
16
11
  ##
17
12
  # Enumerates known RDF reader classes.
18
13
  #
@@ -22,24 +17,13 @@ module RDF
22
17
  !block_given? ? @@subclasses : @@subclasses.each { |klass| yield klass }
23
18
  end
24
19
 
25
- ##
26
- # @return [Hash{String => Symbol}]
27
- def self.content_types
28
- @@content_types
29
- end
30
-
31
- ##
32
- # @return [Hash{Symbol => String}]
33
- def self.file_extensions
34
- @@file_extensions
35
- end
36
-
37
20
  ##
38
21
  # @param [Symbol] format
39
22
  # @return [Class]
40
23
  def self.for(format)
41
24
  klass = case format.to_s.downcase.to_sym
42
- when :ntriples then RDF::Reader::NTriples
25
+ when :ntriples then RDF::NTriples::Reader
26
+ else nil # FIXME
43
27
  end
44
28
  end
45
29
 
@@ -127,23 +111,15 @@ module RDF
127
111
 
128
112
  private
129
113
 
114
+ @@subclasses = [] # @private
115
+
130
116
  def self.inherited(child) #:nodoc:
131
117
  @@subclasses << child
132
118
  super
133
119
  end
134
120
 
135
- def self.content_type(type, options = {})
136
- @@content_types[type] ||= []
137
- @@content_types[type] << self
138
-
139
- if options[:extension]
140
- extensions = [options[:extension]].flatten.map { |ext| ext.to_sym }
141
- extensions.each { |ext| @@file_extensions[ext] = type }
142
- end
143
- end
144
-
145
- def self.content_encoding(encoding)
146
- @@content_encoding[self] = encoding.to_sym
121
+ def self.format(klass)
122
+ # TODO
147
123
  end
148
124
 
149
125
  def lineno
@@ -1,86 +1,5 @@
1
- module RDF class Reader
2
- ##
3
- # An N-Triples parser.
4
- #
5
- # @see http://www.w3.org/TR/rdf-testcases/#ntriples
6
- class NTriples < Reader
7
- content_type 'text/plain', :extension => :nt
8
- content_encoding 'ascii'
9
-
10
- protected
11
-
12
- ##
13
- # @return [Array, nil]
14
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar
15
- def read_triple
16
- loop do
17
- readline.strip! # EOFError thrown on end of input
18
-
19
- unless blank? || read_comment
20
- subject = read_uriref || read_bnode || fail_subject
21
- predicate = read_uriref || fail_predicate
22
- object = read_uriref || read_bnode || read_literal || fail_object
23
- return [subject, predicate, object]
24
- end
25
- end
26
- end
27
-
28
- ##
29
- # @return [Boolean]
30
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (comment)
31
- def read_comment
32
- match(/^#\s*(.*)$/)
33
- end
34
-
35
- ##
36
- # @return [URI, nil]
37
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (uriref)
38
- def read_uriref
39
- if uri = match(/^<([^>]+)>/)
40
- RDF::URI.parse(uri)
41
- end
42
- end
43
-
44
- ##
45
- # @return [Node, nil]
46
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (nodeID)
47
- def read_bnode
48
- if node_id = match(/^_:([A-Za-z][A-Za-z0-9]*)/)
49
- @nodes[node_id] ||= Object.new # TODO: RDF::Node.new
50
- end
51
- end
52
-
53
- ##
54
- # @return [String, Literal, nil]
55
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (literal)
56
- def read_literal
57
- if literal = match(/^"((?:\\"|[^"])*)"/)
58
- literal = unescaped(literal)
59
-
60
- if language = match(/^@([a-z]+[\-a-z0-9]*)/)
61
- # TODO: RDF::Literal.new(literal, :language => language)
62
- literal
63
- elsif datatype = match(/^(\^\^)/)
64
- # TODO: RDF::Literal.new(literal, :type => read_uriref || fail_object)
65
- literal
66
- else
67
- literal # plain string literal
68
- end
69
- end
70
- end
71
-
72
- ##
73
- # @param [String] string
74
- # @return [String]
75
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_strings
76
- def unescaped(string)
77
- ["\t", "\n", "\r", "\"", "\\"].each do |escape|
78
- string.gsub!(escape.inspect[1...-1], escape)
79
- end
80
- string.gsub!(/\\u([0-9A-Fa-f]{4,4})/u) { [$1.hex].pack('U*') }
81
- string.gsub!(/\\U([0-9A-Fa-f]{8,8})/u) { [$1.hex].pack('U*') }
82
- string
83
- end
84
-
1
+ module RDF
2
+ class Reader
3
+ NTriples = RDF::NTriples::Reader # @deprecated
85
4
  end
86
- end end
5
+ end
@@ -150,13 +150,15 @@ module RDF
150
150
  ##
151
151
  # Queries the repository for RDF statements matching the given pattern.
152
152
  #
153
- # @param [Statement, Array(Value)] pattern
153
+ # @param [Query, Statement, Array(Value)] pattern
154
154
  # @yield [statement]
155
155
  # @yieldparam [Statement]
156
156
  # @return [Array<Statement>, nil]
157
157
  def query(pattern, &block)
158
158
  raise TypeError.new("repository is not readable") unless readable?
159
159
  case pattern
160
+ when Query
161
+ pattern.execute(self, &block)
160
162
  when Array
161
163
  query(Statement.new(*pattern), &block)
162
164
  when Statement