roadforest 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/examples/file-management.rb +2 -1
  2. data/lib/roadforest/application/dispatcher.rb +12 -2
  3. data/lib/roadforest/application/services-host.rb +1 -1
  4. data/lib/roadforest/application.rb +12 -5
  5. data/lib/roadforest/blob-model.rb +7 -1
  6. data/lib/roadforest/content-handling/engine.rb +4 -1
  7. data/lib/roadforest/content-handling/type-handlers/jsonld.rb +25 -17
  8. data/lib/roadforest/http/adapters/excon.rb +1 -1
  9. data/lib/roadforest/http/graph-response.rb +18 -4
  10. data/lib/roadforest/http/graph-transfer.rb +52 -8
  11. data/lib/roadforest/http/message.rb +10 -1
  12. data/lib/roadforest/model.rb +17 -4
  13. data/lib/roadforest/rdf/context-fascade.rb +80 -5
  14. data/lib/roadforest/rdf/etagging.rb +53 -0
  15. data/lib/roadforest/rdf/focus-list.rb +47 -5
  16. data/lib/roadforest/rdf/graph-copier.rb +4 -5
  17. data/lib/roadforest/rdf/graph-focus.rb +38 -14
  18. data/lib/roadforest/rdf/graph-reading.rb +102 -47
  19. data/lib/roadforest/rdf/graph-store.rb +12 -8
  20. data/lib/roadforest/rdf/investigation.rb +0 -1
  21. data/lib/roadforest/rdf/normalization.rb +37 -4
  22. data/lib/roadforest/rdf/resource-pattern.rb +1 -0
  23. data/lib/roadforest/rdf/source-rigor/credence-annealer.rb +2 -0
  24. data/lib/roadforest/rdf/source-rigor/http-investigator.rb +12 -14
  25. data/lib/roadforest/rdf/update-focus.rb +7 -62
  26. data/lib/roadforest/remote-host.rb +21 -10
  27. data/lib/roadforest/resource/rdf/read-only.rb +4 -0
  28. data/lib/roadforest/server.rb +22 -0
  29. data/lib/roadforest/test-support/dispatcher-facade.rb +1 -1
  30. data/lib/roadforest/test-support/http-client.rb +8 -0
  31. data/spec/client.rb +20 -2
  32. data/spec/credence-annealer.rb +1 -1
  33. data/spec/excon-adapater.rb +30 -0
  34. data/spec/focus-list.rb +34 -0
  35. data/spec/form-parsing.rb +1 -0
  36. data/spec/full-integration.rb +193 -0
  37. data/spec/rdf-normalization.rb +17 -0
  38. data/spec/update-focus.rb +37 -0
  39. metadata +22 -17
  40. data/lib/roadforest/rdf/focus-wrapping.rb +0 -30
@@ -1,19 +1,61 @@
1
- require 'roadforest/rdf/focus-wrapping'
2
- require 'roadforest/rdf/normalization'
1
+ require 'rdf'
2
+
3
+ require 'roadforest/rdf/resource-query'
4
+ require 'roadforest/rdf/resource-pattern'
5
+
3
6
  module RoadForest::RDF
4
7
  class FocusList < ::RDF::List
5
- include Normalization
6
8
 
7
- attr_accessor :root_url, :base_node, :source_rigor
9
+ attr_accessor :root_url, :base_node
10
+
11
+ #XXX Can delete?
12
+ def source_rigor
13
+ graph.rigor
14
+ end
15
+
16
+ alias car first
17
+ alias cdr rest
8
18
 
9
19
  def first
10
- base_node.unwrap_value(super)
20
+ at(0)
11
21
  end
12
22
 
13
23
  def each
24
+ return to_enum unless block_given?
14
25
  super do |value|
15
26
  yield base_node.unwrap_value(value)
16
27
  end
17
28
  end
29
+
30
+ def append(value)
31
+ value = case value
32
+ when nil then RDF.nil
33
+ when RDF::Value then value
34
+ when Array then RDF::List.new(nil, graph, value)
35
+ else value
36
+ end
37
+
38
+ if empty?
39
+ new_subject = subject
40
+ graph.insert([new_subject, RDF.type, RDF.List])
41
+ else
42
+ old_subject, new_subject = last_subject, RDF::Node.new
43
+ graph.delete([old_subject, RDF.rest, RDF.nil])
44
+ graph.insert([old_subject, RDF.rest, new_subject])
45
+ end
46
+
47
+ graph.insert([new_subject, RDF.first, value.is_a?(RDF::List) ? value.subject : value])
48
+ graph.insert([new_subject, RDF.rest, RDF.nil])
49
+
50
+ self
51
+ end
52
+ alias << append
53
+
54
+ def append_node(subject=nil)
55
+ base_node.create_node(subject) do |node|
56
+ append(node.subject)
57
+ yield node if block_given?
58
+ end
59
+ end
18
60
  end
19
61
  end
@@ -3,13 +3,12 @@ require 'roadforest/rdf/graph-focus'
3
3
 
4
4
  module RoadForest
5
5
  module RDF
6
- class GraphCopier < GraphFocus
7
- attr_accessor :source_graph, :subject
8
-
9
- alias target_graph graph
6
+ class GraphCopier < GraphWriting
7
+ attr_accessor :target_graph
10
8
 
11
9
  def initialize
12
- @graph = ::RDF::Graph.new
10
+ super
11
+ @target_graph = ::RDF::Graph.new
13
12
  end
14
13
  end
15
14
  end
@@ -1,6 +1,5 @@
1
1
  require 'rdf'
2
2
  require 'roadforest/rdf/context-fascade'
3
- require 'roadforest/rdf/focus-wrapping'
4
3
  require 'roadforest/rdf/graph-reading'
5
4
 
6
5
  module RoadForest::RDF
@@ -34,7 +33,7 @@ module RoadForest::RDF
34
33
  end
35
34
  end
36
35
 
37
- module GraphWriting
36
+ class GraphWriting < GraphReading
38
37
  def normalize_triple(property, value, extra=nil)
39
38
  if not extra.nil?
40
39
  property = [property, value]
@@ -55,41 +54,66 @@ module RoadForest::RDF
55
54
  def add(property, value, extra=nil)
56
55
  property, value = normalize_triple(property, value, extra)
57
56
 
58
- target_graph.insert([subject, property, value])
57
+ access_manager.insert([subject, property, value])
59
58
  return value
60
59
  end
61
60
 
62
61
  def delete(property, extra=nil)
63
- target_graph.delete([subject, normalize_property(property, extra), :value])
62
+ access_manager.delete(:subject => subject, :predicate => normalize_property(property, extra))
63
+ end
64
+
65
+ def find_or_add(property, url=nil, &block)
66
+ value = first(property)
67
+ if value.nil?
68
+ value = add_node(property, url, &block)
69
+ else
70
+ yield value if block_given?
71
+ end
72
+ value
64
73
  end
65
74
 
66
75
  def set_node(property, url=nil)
67
- node = wrap_node(set(property, normalize_resource(url) || RDF::Node.new))
68
- yield node if block_given?
69
- node
76
+ create_node(url) do |node|
77
+ set(property, node.subject)
78
+ yield node if block_given?
79
+ end
70
80
  end
71
81
  alias node_at set_node
72
82
 
73
83
  def add_node(property, url=nil)
74
- node = wrap_node(add(property, normalize_resource(url) || RDF::Node.new))
84
+ create_node(url) do |node|
85
+ add(property, node.subject)
86
+ yield node if block_given?
87
+ end
88
+ end
89
+
90
+ #Create a subject node without relationship to the rest of the graph
91
+ def create_node(url=nil)
92
+ node = wrap_node(normalize_resource(url))
75
93
  yield node if block_given?
76
94
  node
77
95
  end
78
96
 
79
97
  def add_list(property, extra=nil)
80
- list = ::RDF::List.new(nil, target_graph)
81
- target_graph.insert([subject, normalize_property(property, extra), list.subject])
98
+ list = FocusList.new(nil, access_manager)
99
+ access_manager.insert([subject, normalize_property(property, extra), list.subject])
82
100
  yield list if block_given?
83
101
  return list
84
102
  end
85
103
  end
86
104
 
87
- class GraphFocus < GraphReading
88
- include GraphWriting
89
-
105
+ class GraphFocus < GraphWriting
90
106
  def target_graph
91
- graph
107
+ @access_manager.target_graph
108
+ end
109
+
110
+ def source_graph=(graph)
111
+ @access_manager.source_graph = graph
112
+ @access_manager.target_graph = graph
92
113
  end
114
+ alias target_graph= source_graph=
93
115
 
116
+ alias graph source_graph
117
+ alias graph= source_graph=
94
118
  end
95
119
  end
@@ -1,69 +1,113 @@
1
1
  require 'roadforest/rdf/focus-list'
2
2
  require 'roadforest/rdf/normalization'
3
- require 'roadforest/rdf/focus-wrapping'
4
3
  require 'roadforest/rdf/resource-query'
4
+ require 'rdf/model/node'
5
+ require 'roadforest/rdf'
6
+
5
7
 
6
8
  module RoadForest::RDF
7
9
  class GraphReading
10
+ #XXX Any changes to this class heirarchy or to ContextFascade should start
11
+ #with a refactor like:
12
+ # Reduce this to the single-node API ([] []=)
13
+ # Change the ContextFascade into a family of classes (RO, RW, Update)
8
14
  include Normalization
9
- include FocusWrapping
10
15
 
11
- attr_accessor :graph, :subject, :root_url, :source_rigor
16
+ #attr_accessor :source_graph, :target_graph, :subject, :root_url,
17
+ #:source_rigor
18
+
19
+ attr_accessor :subject, :access_manager
20
+
12
21
  alias rdf subject
13
22
 
14
23
  def initialize(subject = nil, graph = nil, rigor = nil)
15
- @graph = nil
16
- @subject = nil
17
- @root_url = nil
18
- @source_rigor = nil
24
+ @access_manager = ContextFascade.new
25
+ @access_manager.rigor = rigor
26
+ self.target_graph = graph
27
+ self.source_graph = graph
28
+
19
29
  self.subject = subject unless subject.nil?
20
- self.graph = graph unless graph.nil?
21
- self.source_rigor = rigor unless rigor.nil?
22
30
  end
23
31
 
24
- def inspect
25
- "#<#{self.class.name}:0x#{"%x" % object_id} (#{subject.to_s}) #{forward_properties.inspect}>"
32
+ def source_graph
33
+ @access_manager.source_graph
26
34
  end
27
35
 
28
- def dup
29
- other = self.class.new
30
- other.graph = graph
31
- other.subject = subject
32
- other.root_url = root_url
33
- other.source_rigor = source_rigor
34
- other
36
+ def source_graph=(graph)
37
+ @access_manager.source_graph = graph
35
38
  end
36
39
 
37
- def to_context
38
- normalize_context(subject)
40
+ def target_graph
41
+ nil
39
42
  end
40
43
 
41
- def root_url=(*value) #XXX curies?
42
- @root_url = normalize_resource(value)
44
+ def target_graph=(graph)
45
+ @access_manager.target_graph = nil
46
+ end
47
+
48
+ def source_rigor
49
+ @access_manager.rigor
50
+ end
51
+
52
+ def source_rigor=(rigor)
53
+ @access_manager.rigor = rigor
54
+ end
55
+
56
+ def root_url
57
+ @access_manager.resource
43
58
  end
44
59
 
45
60
  def subject=(*value)
46
61
  @subject = normalize_resource(value)
47
62
  case @subject
48
63
  when ::RDF::URI
49
- @root_url ||= @subject
64
+ @access_manager.resource = @subject
50
65
  end
51
66
  end
52
67
 
53
- def build_query
54
- ResourceQuery.new([], {}) do |query|
55
- query.subject_context = @root_url
56
- query.source_rigor = @source_rigor
57
- yield query
68
+ def inspect
69
+ "#<#{self.class.name}:0x#{"%x" % object_id} (#{subject.to_s}) #{forward_properties.inspect}>"
70
+ end
71
+ alias to_s inspect
72
+
73
+ def dup
74
+ other = self.class.new
75
+ other.access_manager = access_manager.dup
76
+ other.subject = subject
77
+ other
78
+ end
79
+
80
+ def wrap_node(value)
81
+ next_step = dup
82
+ if ::RDF::Node === value
83
+ next_step.root_url = self.root_url
84
+ else
85
+ next_step.root_url = normalize_context(value)
58
86
  end
87
+ next_step.subject = value
88
+ next_step
59
89
  end
60
90
 
61
- def forward_properties
62
- query_properties( build_query{|q| q.pattern([ normalize_resource(subject), :property, :value ])} )
91
+ def unwrap_value(value)
92
+ return nil if value.nil?
93
+ if value.respond_to? :object
94
+ value.object
95
+ else
96
+ wrap_node(value)
97
+ end
63
98
  end
64
99
 
65
- def reverse_properties
66
- query_properties( build_query{|q| q.pattern([ :value, :property, normalize_resource(subject)])} )
100
+ def to_context
101
+ normalize_context(subject)
102
+ end
103
+
104
+ def root_url=(*value) #XXX curies?
105
+ @root_url = normalize_resource(value)
106
+ end
107
+
108
+ #XXX This probably wants to be handled completely in the MediaType handler
109
+ def relevant_prefixes
110
+ relevant_prefixes_for_graph(source_graph)
67
111
  end
68
112
 
69
113
  def get(prefix, property = nil)
@@ -94,15 +138,32 @@ module RoadForest::RDF
94
138
  end
95
139
 
96
140
  def as_list
97
- graph = ContextFascade.new(@graph, @root_url, @source_rigor)
98
- list = FocusList.new(@subject, graph)
141
+ list = FocusList.new(subject, access_manager)
99
142
  list.base_node = self
100
- list.source_rigor = source_rigor
101
143
  list
102
144
  end
103
145
 
146
+ def forward_properties
147
+ query_properties( build_query{|q| q.pattern([ normalize_resource(subject), :property, :value ])} )
148
+ end
149
+
150
+ def reverse_properties
151
+ query_properties( build_query{|q| q.pattern([ :value, :property, normalize_resource(subject)])} )
152
+ end
153
+
104
154
  protected
105
155
 
156
+ def single_or_enum(values)
157
+ case values.length
158
+ when 0
159
+ return nil
160
+ when 1
161
+ return values.first
162
+ else
163
+ return values.enum_for(:each)
164
+ end
165
+ end
166
+
106
167
  def reverse_query_value(prefix, property=nil)
107
168
  query_value(build_query{|q|
108
169
  q.pattern([ :value, normalize_property(prefix, property), normalize_resource(subject)])
@@ -115,25 +176,19 @@ module RoadForest::RDF
115
176
  })
116
177
  end
117
178
 
179
+ def build_query(&block)
180
+ access_manager.build_query(&block)
181
+ end
182
+
118
183
  def query_value(query)
119
- solutions = query.execute(graph)
184
+ solutions = query.execute(access_manager)
120
185
  solutions.map do |solution|
121
186
  unwrap_value(solution.value)
122
187
  end
123
188
  end
124
- def single_or_enum(values)
125
- case values.length
126
- when 0
127
- return nil
128
- when 1
129
- return values.first
130
- else
131
- return values.enum_for(:each)
132
- end
133
- end
134
189
 
135
190
  def query_properties(query)
136
- Hash[query.execute(graph).map do |solution|
191
+ Hash[query.execute(access_manager).map do |solution|
137
192
  prop = solution.property
138
193
  if qname = prop.qname
139
194
  prop = qname
@@ -25,26 +25,27 @@ module RoadForest::RDF
25
25
  @repository = repo || RDF::Repository.new
26
26
  @local_context_node = RDF::Node.new(:local)
27
27
  @debug_io = nil
28
- next_impulse
28
+ force_impulse
29
29
  yield self if block_given?
30
30
  end
31
31
 
32
- def next_impulse
33
- return if !@current_impulse.nil? and raw_quiet_impulse?
34
- #mark ended?
35
- #chain impulses?
32
+ def force_impulse
36
33
  @current_impulse = RDF::Node.new
37
34
  repository.insert(normalize_statement(@current_impulse, [:rdf, 'type'], [:rf, 'Impulse'], nil))
38
35
  repository.insert(normalize_statement(@current_impulse, [:rf, 'begunAt'], Time.now, nil))
39
36
  end
40
37
 
41
- def quiet_impulse?
42
- raw_quiet_impulse?
38
+ def next_impulse
39
+ return if quiet_impulse?
40
+ force_impulse
41
+ #mark ended?
42
+ #chain impulses?
43
43
  end
44
44
 
45
- def raw_quiet_impulse?
45
+ def quiet_impulse?
46
46
  repository.query([nil, nil, @current_impulse, false]).to_a.empty?
47
47
  end
48
+ alias raw_quiet_impulse? quiet_impulse?
48
49
 
49
50
  #repo cleanup - expired graphs
50
51
 
@@ -130,6 +131,8 @@ module RoadForest::RDF
130
131
  end
131
132
 
132
133
  def insert_statement(statement)
134
+ #puts "\n#{__FILE__}:#{__LINE__} => #{[self.object_id,
135
+ #statement].inspect}"
133
136
  repository.insert(statement)
134
137
 
135
138
  repository.delete([statement.context, expand_curie([:rf, "impulse"]), nil])
@@ -158,6 +161,7 @@ module RoadForest::RDF
158
161
  end
159
162
 
160
163
  @repository.query(query) do |statement|
164
+ next if statement.context.nil?
161
165
  yield statement
162
166
  end
163
167
  end
@@ -28,7 +28,6 @@ module RoadForest::RDF
28
28
  source_rigor.graph_transfer.make_request(method, url, graph)
29
29
  end
30
30
 
31
-
32
31
  def insert_graph(context, graph)
33
32
  queryable.insert_graph(context, graph)
34
33
  end
@@ -9,7 +9,9 @@ module RoadForest::RDF
9
9
  subject = normalize_resource(subject) || RDF::Node.new
10
10
  predicate = normalize_uri(predicate)
11
11
  object = normalize_term(object) || RDF::Node.new
12
- context = normalize_resource(context)
12
+ unless context.nil?
13
+ context = normalize_resource(context)
14
+ end
13
15
 
14
16
  RDF::Statement.new(subject, predicate, object, :context => context)
15
17
  end
@@ -23,6 +25,7 @@ module RoadForest::RDF
23
25
  from = expand_curie(from)
24
26
  case from
25
27
  when nil
28
+ from = RDF::Node.new
26
29
  when RDF::Resource
27
30
  when /^_:/
28
31
  from = RDF::Resource.new(from)
@@ -72,16 +75,47 @@ module RoadForest::RDF
72
75
  RDF::Literal.new(object)
73
76
  end
74
77
 
78
+ def relevant_prefixes_for_graph(graph)
79
+ Hash[ vocabularies_in_graph(graph).map do |prefix|
80
+ vocab = Vocabs[prefix]
81
+ [prefix, vocab.to_uri]
82
+ end]
83
+ end
84
+
85
+ def vocabularies_in_graph(graph)
86
+ patterns = Vocabs.map do |prefix, vocab|
87
+ [%r{^#{vocab.to_uri}}, prefix]
88
+ end
89
+
90
+ vocabs = {}
91
+
92
+ graph.each_statement do |statement|
93
+ statement.to_a.each do |field|
94
+ next unless RDF::URI === field
95
+ field = field.to_s
96
+ patterns.each do |pattern, vocab|
97
+ if pattern =~ field
98
+ vocabs[vocab] = true
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ vocabs.keys
105
+ end
106
+
75
107
  def expand_curie_pair(prefix, property)
76
108
  vocab = Vocabs.fetch(prefix) do
77
109
  vocab = RDF::Vocabulary.find do |vocab|
110
+ unless vocab.__prefix__.is_a? RDF::URI
111
+ Vocabs[vocab.__prefix__.to_s] = vocab
112
+ end
78
113
  vocab.__prefix__.to_s == prefix
79
114
  end
80
115
  #p k => vocab #ok
81
116
  if vocab.nil?
82
117
  raise "Don't know a vocabulary for prefix #{prefix.inspect} in CURIE #{prefix}:#{property}"
83
118
  end
84
- Vocabs[prefix] = vocab
85
119
  vocab
86
120
  end
87
121
  vocab[property]
@@ -126,7 +160,6 @@ module RoadForest::RDF
126
160
  end
127
161
 
128
162
  def interned_uri(value)
129
-
130
163
  RDF::URI.intern(uri(value))
131
164
  end
132
165
 
@@ -140,8 +173,8 @@ module RoadForest::RDF
140
173
  if !value.query.nil? and value.query.empty?
141
174
  value.query = nil
142
175
  end
143
- value.validate!
144
176
  value.canonicalize!
177
+ value.validate!
145
178
 
146
179
  value
147
180
  end
@@ -1,5 +1,6 @@
1
1
  require 'rdf/query/pattern'
2
2
  require 'roadforest/rdf'
3
+ require 'roadforest/rdf/graph-store'
3
4
  require 'roadforest/rdf/investigation'
4
5
 
5
6
  module RoadForest::RDF
@@ -12,6 +12,8 @@ class RoadForest::RDF::SourceRigor
12
12
  def resolve(&block)
13
13
  attempts = @attempts
14
14
 
15
+ @graph.force_impulse
16
+
15
17
  begin
16
18
  raise "Annealing failed after #@attempts attempts" if (attempts -= 1) < 0
17
19
  @graph.next_impulse
@@ -1,20 +1,18 @@
1
1
  require 'roadforest/rdf/source-rigor/investigator'
2
- class RoadForest::RDF::SourceRigor
3
- class HTTPInvestigator < Investigator
4
- register :http
2
+ module RoadForest
3
+ class RDF::SourceRigor
4
+ class HTTPInvestigator < Investigator
5
+ register :http
5
6
 
6
- def pursue(investigation)
7
- response = investigation.make_request("GET", investigation.context_roles[:subject])
8
- case response.status
9
- when (200..299)
10
- investigation.insert_graph(response.url, response.graph)
11
- when (300..399)
12
- #client should follow redirects
13
- when (400..499)
14
- when (500..599)
15
- raise NotCredible #hrm
7
+ def pursue(investigation)
8
+ response = investigation.make_request("GET", investigation.context_roles[:subject])
9
+ case response
10
+ when HTTP::GraphResponse
11
+ investigation.insert_graph(response.url, response.graph)
12
+ when HTTP::UnparseableResponse
13
+ #Do nothing
14
+ end
16
15
  end
17
- rescue NotCredible
18
16
  end
19
17
  end
20
18
  end
@@ -2,72 +2,17 @@ require 'roadforest/rdf/graph-focus'
2
2
  require 'roadforest/rdf/parcel'
3
3
 
4
4
  module RoadForest::RDF
5
- class UpdateFocus < GraphFocus
6
- attr_accessor :target_graph
7
-
8
- alias source_graph= graph=
9
- alias source_graph graph
10
-
11
- def dup
12
- other = super
13
- other.target_graph = target_graph
14
- other
15
- end
16
-
17
- def parceller
18
- @parceller ||=
19
- begin
20
- parceller = Parcel.new
21
- parceller.graph = source_graph
22
- parceller
23
- end
5
+ class UpdateFocus < GraphWriting
6
+ def target_graph
7
+ @access_manager.target_graph
24
8
  end
25
9
 
26
- def copy_context
27
- unless target_graph.has_context?(root_url)
28
- parceller.graph_for(root_url).each_statement do |statement|
29
- statement.context = root_url
30
- target_graph << statement
31
- end
32
- end
33
- end
34
-
35
- def add(property, value, extra=nil)
36
- copy_context
37
- property, value = normalize_triple(property, value, extra)
38
- target_graph.insert([subject, property, value, root_url])
39
- end
40
-
41
- def set(property, value, extra=nil)
42
- copy_context
43
- super
44
- end
45
-
46
- def delete(property, extra=nil)
47
- copy_context
48
- property, value = normalize_triple(property, value, extra)
49
- target_graph.query([subject, property]) do |statement|
50
- target_graph.delete(statement)
51
- end
52
- end
53
-
54
- def query_value(query)
55
- source_result = super
56
- target_result = query.execute(target_graph).map do |solution|
57
- unwrap_value(solution.value)
58
- end
59
-
60
- if target_result.empty?
61
- source_result
62
- else
63
- target_result
64
- end
10
+ def target_graph=(graph)
11
+ @access_manager.target_graph = graph
65
12
  end
66
13
 
67
- def wrap_node(value)
68
- focus = super
69
- focus.target_graph = self.target_graph
70
- focus
14
+ def relevant_prefixes
15
+ super.merge(relevant_prefixes_for_graph(target_graph))
71
16
  end
72
17
  end
73
18
  end