roadforest 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/examples/file-management.rb +98 -0
  2. data/lib/roadforest/application/dispatcher.rb +54 -0
  3. data/lib/roadforest/application/parameters.rb +39 -0
  4. data/lib/roadforest/application/path-provider.rb +18 -0
  5. data/lib/roadforest/application/route-adapter.rb +24 -0
  6. data/lib/roadforest/application/services-host.rb +10 -0
  7. data/lib/roadforest/application.rb +42 -0
  8. data/lib/roadforest/blob-model.rb +56 -0
  9. data/lib/roadforest/content-handling/engine.rb +113 -0
  10. data/lib/roadforest/content-handling/media-type.rb +222 -0
  11. data/lib/roadforest/content-handling/type-handlers/jsonld.rb +172 -0
  12. data/lib/roadforest/http/adapters/excon.rb +47 -0
  13. data/lib/roadforest/http/graph-response.rb +20 -0
  14. data/lib/roadforest/http/graph-transfer.rb +112 -0
  15. data/lib/roadforest/http/message.rb +91 -0
  16. data/lib/roadforest/model.rb +151 -0
  17. data/lib/roadforest/models.rb +2 -0
  18. data/lib/roadforest/rdf/context-fascade.rb +25 -0
  19. data/lib/roadforest/rdf/document.rb +23 -0
  20. data/lib/roadforest/rdf/focus-list.rb +19 -0
  21. data/lib/roadforest/rdf/focus-wrapping.rb +30 -0
  22. data/lib/roadforest/rdf/graph-copier.rb +16 -0
  23. data/lib/roadforest/rdf/graph-focus.rb +95 -0
  24. data/lib/roadforest/rdf/graph-reading.rb +145 -0
  25. data/lib/roadforest/rdf/graph-store.rb +217 -0
  26. data/lib/roadforest/rdf/investigation.rb +90 -0
  27. data/lib/roadforest/rdf/normalization.rb +150 -0
  28. data/lib/roadforest/rdf/parcel.rb +47 -0
  29. data/lib/roadforest/rdf/post-focus.rb +35 -0
  30. data/lib/roadforest/rdf/resource-pattern.rb +60 -0
  31. data/lib/roadforest/rdf/resource-query.rb +58 -0
  32. data/lib/roadforest/rdf/source-rigor/credence/any.rb +9 -0
  33. data/lib/roadforest/rdf/source-rigor/credence/none-if-role-absent.rb +19 -0
  34. data/lib/roadforest/rdf/source-rigor/credence/role-if-available.rb +19 -0
  35. data/lib/roadforest/rdf/source-rigor/credence-annealer.rb +22 -0
  36. data/lib/roadforest/rdf/source-rigor/credence.rb +29 -0
  37. data/lib/roadforest/rdf/source-rigor/http-investigator.rb +20 -0
  38. data/lib/roadforest/rdf/source-rigor/investigator.rb +17 -0
  39. data/lib/roadforest/rdf/source-rigor/null-investigator.rb +10 -0
  40. data/lib/roadforest/rdf/source-rigor.rb +44 -0
  41. data/lib/roadforest/rdf/update-focus.rb +73 -0
  42. data/lib/roadforest/rdf/vocabulary.rb +11 -0
  43. data/lib/roadforest/rdf.rb +6 -0
  44. data/lib/roadforest/remote-host.rb +96 -0
  45. data/lib/roadforest/resource/handlers.rb +43 -0
  46. data/lib/roadforest/resource/http/form-parsing.rb +81 -0
  47. data/lib/roadforest/resource/rdf/leaf-item.rb +21 -0
  48. data/lib/roadforest/resource/rdf/list.rb +19 -0
  49. data/lib/roadforest/resource/rdf/parent-item.rb +26 -0
  50. data/lib/roadforest/resource/rdf/read-only.rb +100 -0
  51. data/lib/roadforest/resource/rdf.rb +4 -0
  52. data/lib/roadforest/resource/role/has-children.rb +22 -0
  53. data/lib/roadforest/resource/role/writable.rb +43 -0
  54. data/lib/roadforest/server.rb +3 -0
  55. data/lib/roadforest/test-support/dispatcher-facade.rb +77 -0
  56. data/lib/roadforest/test-support/http-client.rb +151 -0
  57. data/lib/roadforest/test-support/matchers.rb +67 -0
  58. data/lib/roadforest/test-support/remote-host.rb +23 -0
  59. data/lib/roadforest/test-support/trace-formatter.rb +140 -0
  60. data/lib/roadforest/test-support.rb +2 -0
  61. data/lib/roadforest/utility/class-registry.rb +49 -0
  62. data/lib/roadforest.rb +2 -0
  63. data/spec/client.rb +152 -0
  64. data/spec/credence-annealer.rb +44 -0
  65. data/spec/graph-copier.rb +87 -0
  66. data/spec/graph-store.rb +142 -0
  67. data/spec/media-types.rb +14 -0
  68. data/spec/rdf-parcel.rb +158 -0
  69. data/spec/update-focus.rb +117 -0
  70. data/spec_support/gem_test_suite.rb +0 -0
  71. metadata +241 -0
@@ -0,0 +1,47 @@
1
+ require 'roadforest/rdf'
2
+ require 'roadforest/rdf/normalization'
3
+
4
+ module RoadForest::RDF
5
+ class Parcel
6
+ include Normalization
7
+
8
+ attr_accessor :graph
9
+
10
+ def resources
11
+ resource_hash = {}
12
+ graph.each_subject do |subject|
13
+ next unless RDF::URI === subject
14
+ resource_hash[normalize_context(subject)] = true
15
+ end
16
+ resource_hash.keys
17
+ end
18
+
19
+ def subjects_for_resource(resource)
20
+ resource = normalize_context(resource)
21
+ graph.each_subject.find_all do |subject|
22
+ normalize_context(subject) == resource
23
+ end
24
+ end
25
+
26
+ def graph_for(resource)
27
+ new_graph = RDF::Graph.new
28
+ subjects = {}
29
+ subjects_for_resource(resource).each do |subject|
30
+ subjects[subject] ||= :open
31
+ end
32
+
33
+ until (open_subjects = subjects.keys.find_all{|subject| subjects[subject] == :open }).empty?
34
+ open_subjects.each do |subject|
35
+ subjects[subject] = :closed
36
+ graph.query(:subject => subject) do |statement|
37
+ if RDF::Node === statement.object
38
+ subjects[statement.object] ||= :open
39
+ end
40
+ new_graph << statement
41
+ end
42
+ end
43
+ end
44
+ new_graph
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ require 'roadforest/rdf/graph-focus'
2
+
3
+ module RoadForest::RDF
4
+ class PostFocus < GraphFocus
5
+ def initialize(subject = nil, graph = nil , rigor = nil)
6
+ super(subject, graph, rigor)
7
+ @graphs = {}
8
+ end
9
+ attr_accessor :graphs
10
+
11
+ def dup
12
+ other = super
13
+ other.graphs = graphs
14
+ other
15
+ end
16
+
17
+ def graph_transfer
18
+ source_rigor.graph_transfer
19
+ end
20
+
21
+ def post_to
22
+ graph = ::RDF::Graph.new
23
+ focus = GraphFocus.new(subject, graph, source_rigor) #XXX non-client version
24
+ graphs[subject] = graph
25
+ yield focus if block_given?
26
+ return focus
27
+ end
28
+
29
+ def send_graphs
30
+ @graphs.each_pair do |url, graph|
31
+ graph_transfer.post(url, graph)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,60 @@
1
+ require 'rdf/query/pattern'
2
+ require 'roadforest/rdf'
3
+ require 'roadforest/rdf/investigation'
4
+
5
+ module RoadForest::RDF
6
+ class ResourcePattern < ::RDF::Query::Pattern
7
+ def self.from(pattern, options)
8
+ pattern = case pattern
9
+ when self
10
+ pattern
11
+ when ::RDF::Query::Pattern
12
+ options ||= {}
13
+ self.new(pattern.subject, pattern.predicate, pattern.object, options.merge(:context => pattern.context))
14
+ when Array, ::RDF::Statement
15
+ options ||= {}
16
+ self.new(pattern[0], pattern[1], pattern[2], options.merge(:context => pattern[3]))
17
+ when Hash
18
+ options ||= {}
19
+ self.new(options.merge(pattern))
20
+ else
21
+ raise ArgumentError, "expected RoadForest::RDF::ResourcePattern, RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}"
22
+ end
23
+
24
+ unless options.nil?
25
+ pattern.context_roles = options[:context_roles]
26
+ pattern.source_rigor = options[:source_rigor]
27
+ end
28
+
29
+ yield pattern if block_given?
30
+
31
+ pattern
32
+ end
33
+
34
+ attr_accessor :context_roles, :source_rigor
35
+
36
+ def execute(queryable, bindings = nil, query_context_roles = nil, &block)
37
+ unless queryable.is_a? RoadForest::RDF::GraphStore
38
+ return super(queryable, bindings || {}, &block)
39
+ end
40
+
41
+ investigation = Investigation.new
42
+ investigation.queryable = queryable
43
+ investigation.context_roles = (query_context_roles || {}).merge(context_roles)
44
+ investigation.source_rigor = source_rigor
45
+
46
+ results = investigation.result do |results|
47
+ super(queryable, bindings || {}) do |statement|
48
+ results << statement
49
+ end
50
+ end
51
+
52
+ results.each(&block) if block_given?
53
+ results
54
+ end
55
+
56
+ def context
57
+ @context ||= ::RDF::Query::Variable.new(:context)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,58 @@
1
+ require 'roadforest/rdf'
2
+ require 'rdf/query'
3
+
4
+ module RoadForest::RDF
5
+ class ResourceQuery < ::RDF::Query
6
+ def initialize(patterns = [], options = {}, &block)
7
+ @subject_context = options[:subject_context]
8
+ @source_rigor = options[:source_rigor]
9
+ super
10
+ patterns = @patterns.dup
11
+ @patterns.clear
12
+ patterns.each do |pattern|
13
+ pattern(pattern)
14
+ end
15
+ end
16
+
17
+ attr_accessor :subject_context, :source_rigor
18
+ attr_accessor :patterns, :variables, :solutions, :options
19
+
20
+ def <<(pattern)
21
+ pattern(pattern)
22
+ end
23
+
24
+ def pattern(pattern, options = nil)
25
+ options = {
26
+ :context_roles => {:subject => subject_context},
27
+ :source_rigor => source_rigor
28
+ }.merge(options || {})
29
+
30
+ @patterns << ResourcePattern.from(pattern, options)
31
+ self
32
+ end
33
+
34
+ def self.from(other, subject_context = nil, source_rigor = nil)
35
+ query = self.new
36
+
37
+ if subject_context.nil? and other.respond_to?(:subject_context)
38
+ query.subject_context = other.subject_context
39
+ else
40
+ query.subject_context = subject_context
41
+ end
42
+
43
+ if source_rigor.nil? and other.respond_to?(:source_rigor)
44
+ query.source_rigor = other.source_rigor
45
+ else
46
+ query.source_rigor = source_rigor
47
+ end
48
+
49
+ other.patterns.each do |pattern|
50
+ query.pattern(pattern)
51
+ end
52
+ query.variables = other.variables
53
+ query.solutions = other.solutions
54
+ query.options = other.options
55
+ return query
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ class RoadForest::RDF::SourceRigor
2
+ module Credence
3
+ class Any
4
+ def credible(contexts, results)
5
+ contexts
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ class RoadForest::RDF::SourceRigor
2
+ module Credence
3
+ #Unless we have results for the subject context, nothing is valid
4
+ class NoneIfRoleAbsent
5
+ def initialize(role)
6
+ @role = role
7
+ end
8
+ attr_reader :role
9
+
10
+ def credible(contexts, results)
11
+ if contexts.include?(results.context_roles[role])
12
+ contexts
13
+ else
14
+ []
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ class RoadForest::RDF::SourceRigor
2
+ module Credence
3
+ #If there are any results for the subject context, they're good
4
+ class RoleIfAvailable
5
+ def initialize(role)
6
+ @role = role
7
+ end
8
+ attr_reader :role
9
+
10
+ def credible(contexts, results)
11
+ if contexts.include?(results.context_roles[role])
12
+ [results.context_roles[role]]
13
+ else
14
+ contexts
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ require 'roadforest/rdf'
2
+
3
+ class RoadForest::RDF::SourceRigor
4
+ class CredenceAnnealer
5
+ def initialize(graph)
6
+ @graph = graph
7
+ @attempts = 5
8
+ end
9
+
10
+ attr_accessor :attempts
11
+
12
+ def resolve(&block)
13
+ attempts = @attempts
14
+
15
+ begin
16
+ raise "Annealing failed after #@attempts attempts" if (attempts -= 1) < 0
17
+ @graph.next_impulse
18
+ block.call
19
+ end until @graph.quiet_impulse?
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+ class RoadForest::RDF::SourceRigor
2
+ module Credence
3
+ require 'roadforest/rdf/source-rigor/credence/role-if-available'
4
+ require 'roadforest/rdf/source-rigor/credence/any'
5
+ require 'roadforest/rdf/source-rigor/credence/none-if-role-absent'
6
+
7
+ def self.policies
8
+ @policies ||= {
9
+ :any => Any.new,
10
+ :may_subject => RoleIfAvailable.new(:subject),
11
+ :must_subject => NoneIfRoleAbsent.new(:subject),
12
+ :may_local => RoleIfAvailable.new(:local),
13
+ :must_local => NoneIfRoleAbsent.new(:local)
14
+ }
15
+ end
16
+
17
+ def self.policy(name)
18
+ if block_given?
19
+ policies[name] ||= yield
20
+ else
21
+ begin
22
+ policies.fetch(name)
23
+ rescue KeyError
24
+ raise "No Credence policy for #{name.inspect} (available named policies are #{policies.keys.inspect})"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ require 'roadforest/rdf/source-rigor/investigator'
2
+ class RoadForest::RDF::SourceRigor
3
+ class HTTPInvestigator < Investigator
4
+ register :http
5
+
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
16
+ end
17
+ rescue NotCredible
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ require 'roadforest/utility/class-registry'
2
+
3
+ class RoadForest::RDF::SourceRigor
4
+ class NotCredible < StandardError; end
5
+ class NoCredibleResults < StandardError; end
6
+
7
+ class Investigator
8
+ extend ::RoadForest::Utility::ClassRegistry::Registrar
9
+ def self.registry_purpose; "investigator"; end
10
+
11
+ def pursue(investigation)
12
+ raise NoCredibleResults
13
+ end
14
+ end
15
+ end
16
+ require 'roadforest/rdf/source-rigor/null-investigator'
17
+ require 'roadforest/rdf/source-rigor/http-investigator'
@@ -0,0 +1,10 @@
1
+ require 'roadforest/rdf/source-rigor/investigator'
2
+ class RoadForest::RDF::SourceRigor
3
+ class NullInvestigator < Investigator
4
+ register :null
5
+
6
+ def pursue(investigation)
7
+ investigation.results = []
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ require 'roadforest'
2
+
3
+ module RoadForest::RDF
4
+ class SourceRigor
5
+ require 'roadforest/rdf/source-rigor/investigator'
6
+ require 'roadforest/rdf/source-rigor/credence'
7
+
8
+ class << self
9
+ def simple
10
+ rigor = self.new
11
+ rigor.policy_list(:must_local, :may_local)
12
+ rigor.investigator_list(:null)
13
+ rigor
14
+ end
15
+
16
+ def http
17
+ rigor = self.new
18
+ rigor.policy_list(:may_subject, :any) #XXX
19
+ rigor.investigator_list(:http, :null)
20
+ rigor
21
+ end
22
+ end
23
+
24
+ def initialize
25
+ @investigators = []
26
+ @investigation_limit = 3
27
+ @credence_policies = []
28
+ end
29
+
30
+ attr_accessor :graph_transfer, :investigators, :investigation_limit, :credence_policies
31
+
32
+ def policy_list(*names)
33
+ self.credence_policies = names.map do |name|
34
+ Credence.policy(name)
35
+ end
36
+ end
37
+
38
+ def investigator_list(*names)
39
+ self.investigators = names.map do |name|
40
+ Investigator[name].new
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,73 @@
1
+ require 'roadforest/rdf/graph-focus'
2
+ require 'roadforest/rdf/parcel'
3
+
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
24
+ end
25
+
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
65
+ end
66
+
67
+ def wrap_node(value)
68
+ focus = super
69
+ focus.target_graph = self.target_graph
70
+ focus
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ require 'roadforest/rdf'
2
+
3
+ module RoadForest::RDF
4
+ module Vocabulary
5
+ class RF < ::RDF::Vocabulary("http://lrdesign.com/rdf/roadforest#")
6
+ property :Impulse
7
+ property :impulse
8
+ property :begunAt
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ require 'rdf'
2
+
3
+ module RoadForest
4
+ module RDF
5
+ end
6
+ end
@@ -0,0 +1,96 @@
1
+ require 'roadforest/rdf/source-rigor'
2
+ require 'roadforest/rdf/source-rigor/credence-annealer'
3
+ require 'roadforest/http/graph-transfer'
4
+ require 'roadforest/http/adapters/excon'
5
+ require 'roadforest/rdf/graph-store'
6
+
7
+ module RoadForest
8
+ class RemoteHost
9
+ include RDF::Normalization
10
+
11
+ def initialize(well_known_url)
12
+ @url = normalize_resource(well_known_url)
13
+ @graph = build_graph_store
14
+ end
15
+
16
+ def build_graph_store
17
+ RDF::GraphStore.new
18
+ end
19
+
20
+ attr_writer :http_client
21
+ def http_client
22
+ @http_client ||= HTTP::ExconAdapter.new(@url)
23
+ end
24
+
25
+ def graph_transfer
26
+ @graph_transfer ||= HTTP::GraphTransfer.new.tap do |transfer|
27
+ transfer.http_client = http_client
28
+ end
29
+ end
30
+
31
+ def source_rigor
32
+ @source_rigor ||=
33
+ begin
34
+ rigor = RDF::SourceRigor.http
35
+ rigor.graph_transfer = graph_transfer
36
+ rigor
37
+ end
38
+ end
39
+
40
+ def render_graph(graph)
41
+ Resource::ContentType::JSONLD.from_graph(graph)
42
+ end
43
+
44
+ def anneal(focus)
45
+ annealer = RDF::SourceRigor::CredenceAnnealer.new(@graph)
46
+ annealer.resolve do
47
+ yield focus
48
+ end
49
+ end
50
+
51
+ def putting(&block)
52
+ require 'roadforest/rdf/update-focus'
53
+ target_graph = ::RDF::Repository.new
54
+ updater = RDF::UpdateFocus.new(@url, @graph, source_rigor)
55
+ updater.target_graph = target_graph
56
+
57
+ anneal(updater, &block)
58
+
59
+ target_graph.each_context do |context|
60
+ graph = ::RDF::Graph.new(context, :data => target_graph)
61
+ graph_transfer.put(context, graph)
62
+ end
63
+ end
64
+
65
+ def posting(&block)
66
+ require 'roadforest/rdf/post-focus'
67
+ poster = RDF::PostFocus.new(@url, @graph, source_rigor)
68
+
69
+ anneal(poster, &block)
70
+
71
+ poster.send_graphs
72
+ end
73
+
74
+ def getting(&block)
75
+ reader = RDF::GraphReading.new(@url, @graph, source_rigor)
76
+
77
+ anneal(reader, &block)
78
+ end
79
+
80
+ def put_file(destination, type, io)
81
+ if destination.respond_to?(:to_context)
82
+ destination = destination.to_context
83
+ elsif destination.respond_to?(:to_s)
84
+ destination = destination.to_s
85
+ end
86
+ request = HTTP::Request.new("PUT", destination)
87
+ request.body = io
88
+ request.headers["Content-Type"] = type
89
+ response = http_client.do_request request
90
+ end
91
+
92
+ #TODO:
93
+ #def deleting
94
+ #def patching
95
+ end
96
+ end
@@ -0,0 +1,43 @@
1
+ require 'roadforest/application/route-adapter'
2
+
3
+ module RoadForest
4
+ module Resource
5
+ module Handlers
6
+ def self.registry
7
+ @registry ||= {}
8
+ end
9
+
10
+ def self.register(handler_type, klass)
11
+ registry[handler_type] = klass
12
+
13
+ method_name = "#{handler_type}_model"
14
+ define_method(method_name) do |model_class|
15
+ if block_given?
16
+ bundle_model(klass, model_class){|model| yield(model)}
17
+ else
18
+ bundle_model(klass, model_class)
19
+ end
20
+ end
21
+ end
22
+
23
+ def bundle(resource_class, &block)
24
+ Application::RouteAdapter.new(resource_class, &block)
25
+ end
26
+
27
+ def bundle_typed_resource(resource_type, model_class, route_name)
28
+ resource_class = Resource::Handlers.registry.fetch(resource_type)
29
+ bundle(resource_class) do |resource, request, response|
30
+ resource.model = model_class.new(route_name, resource.params, services)
31
+ end
32
+ end
33
+
34
+ def bundle_traced_resource(resource_type, model_class, route_name)
35
+ resource_class = Resource::Handlers.registry.fetch(resource_type)
36
+ bundle(resource_class) do |resource, request, response|
37
+ resource.model = model_class.new(route_name, resource.params, services)
38
+ resource.trace = true
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end