rdf 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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