roadforest 0.1 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/examples/file-management.rb +12 -13
  3. data/lib/roadforest-client.rb +3 -0
  4. data/lib/roadforest-common.rb +2 -0
  5. data/lib/roadforest-server.rb +7 -0
  6. data/lib/roadforest-testing.rb +1 -0
  7. data/lib/roadforest/application.rb +9 -7
  8. data/lib/roadforest/application/dispatcher.rb +39 -63
  9. data/lib/roadforest/application/parameters.rb +1 -1
  10. data/lib/roadforest/application/path-provider.rb +2 -2
  11. data/lib/roadforest/application/route-adapter.rb +130 -18
  12. data/lib/roadforest/application/services-host.rb +0 -4
  13. data/lib/roadforest/augment/affordance.rb +78 -0
  14. data/lib/roadforest/augment/augmentation.rb +97 -0
  15. data/lib/roadforest/augment/augmenter.rb +54 -0
  16. data/lib/roadforest/augmentations.rb +1 -0
  17. data/lib/roadforest/content-handling.rb +1 -0
  18. data/lib/roadforest/content-handling/common-engines.rb +67 -0
  19. data/lib/roadforest/content-handling/engine.rb +2 -14
  20. data/lib/roadforest/content-handling/handler-wrap.rb +29 -31
  21. data/lib/roadforest/content-handling/media-type.rb +6 -0
  22. data/lib/roadforest/{rdf.rb → graph.rb} +1 -1
  23. data/lib/roadforest/{rdf → graph}/access-manager.rb +12 -74
  24. data/lib/roadforest/{rdf → graph}/document.rb +1 -1
  25. data/lib/roadforest/{rdf → graph}/etagging.rb +2 -2
  26. data/lib/roadforest/{rdf → graph}/focus-list.rb +1 -9
  27. data/lib/roadforest/{rdf → graph}/graph-copier.rb +2 -2
  28. data/lib/roadforest/{rdf → graph}/graph-focus.rb +5 -7
  29. data/lib/roadforest/{rdf → graph}/normalization.rb +1 -1
  30. data/lib/roadforest/{rdf → graph}/post-focus.rb +2 -3
  31. data/lib/roadforest/graph/vocabulary.rb +96 -0
  32. data/lib/roadforest/http/graph-transfer.rb +2 -2
  33. data/lib/roadforest/interface/application.rb +145 -0
  34. data/lib/roadforest/interface/blob.rb +38 -0
  35. data/lib/roadforest/interface/rdf.rb +77 -0
  36. data/lib/roadforest/interfaces.rb +2 -0
  37. data/lib/roadforest/remote-host.rb +17 -17
  38. data/lib/roadforest/resource.rb +4 -0
  39. data/lib/roadforest/resource/{rdf/leaf-item.rb → leaf-item.rb} +1 -1
  40. data/lib/roadforest/resource/{rdf/list.rb → list.rb} +1 -1
  41. data/lib/roadforest/resource/{rdf/parent-item.rb → parent-item.rb} +1 -1
  42. data/lib/roadforest/resource/{rdf/read-only.rb → read-only.rb} +18 -18
  43. data/lib/roadforest/resource/role/has-children.rb +1 -1
  44. data/lib/roadforest/resource/role/writable.rb +2 -2
  45. data/lib/roadforest/server.rb +1 -1
  46. data/lib/roadforest/source-rigor.rb +9 -0
  47. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence-annealer.rb +2 -2
  48. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence.rb +5 -5
  49. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence/any.rb +1 -1
  50. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence/none-if-role-absent.rb +1 -1
  51. data/lib/roadforest/{rdf/source-rigor → source-rigor}/credence/role-if-available.rb +1 -1
  52. data/lib/roadforest/source-rigor/engine.rb +45 -0
  53. data/lib/roadforest/{rdf → source-rigor}/graph-store.rb +9 -9
  54. data/lib/roadforest/{rdf/source-rigor → source-rigor}/http-investigator.rb +2 -2
  55. data/lib/roadforest/{rdf → source-rigor}/investigation.rb +2 -2
  56. data/lib/roadforest/{rdf/source-rigor → source-rigor}/investigator.rb +3 -3
  57. data/lib/roadforest/{rdf/source-rigor → source-rigor}/null-investigator.rb +3 -2
  58. data/lib/roadforest/{rdf → source-rigor}/parcel.rb +5 -5
  59. data/lib/roadforest/{rdf → source-rigor}/resource-pattern.rb +6 -6
  60. data/lib/roadforest/{rdf → source-rigor}/resource-query.rb +2 -2
  61. data/lib/roadforest/source-rigor/rigorous-access.rb +101 -0
  62. data/lib/roadforest/templates/affordance-doc.haml +23 -0
  63. data/lib/roadforest/templates/affordance-property-values.haml +13 -0
  64. data/lib/roadforest/templates/affordance-subject.haml +9 -0
  65. data/lib/roadforest/templates/affordance-uri-object.haml +2 -0
  66. data/lib/roadforest/templates/base/{property_value.haml → property-value.haml} +0 -0
  67. data/lib/roadforest/templates/base/{property_values.haml → property-values.haml} +0 -0
  68. data/lib/roadforest/templates/distiller/{property_value.haml → property-value.haml} +0 -0
  69. data/lib/roadforest/templates/distiller/{property_values.haml → property-values.haml} +0 -0
  70. data/lib/roadforest/templates/min/{property_values.haml → property-values.haml} +0 -0
  71. data/lib/roadforest/templates/rdfpost-curie.haml +6 -0
  72. data/lib/roadforest/test-support/dispatcher-facade.rb +2 -0
  73. data/lib/roadforest/test-support/matchers.rb +169 -5
  74. data/lib/roadforest/test-support/remote-host.rb +2 -2
  75. data/lib/roadforest/type-handlers/handler.rb +74 -0
  76. data/lib/roadforest/type-handlers/jsonld.rb +34 -0
  77. data/lib/roadforest/type-handlers/rdf-handler.rb +36 -0
  78. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer.rb +2 -2
  79. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/document-environment.rb +9 -8
  80. data/lib/roadforest/type-handlers/rdfa-writer/environment-decorator.rb +312 -0
  81. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/object-environment.rb +3 -3
  82. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/property-environment.rb +5 -11
  83. data/lib/roadforest/type-handlers/rdfa-writer/render-engine.rb +427 -0
  84. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/render-environment.rb +33 -26
  85. data/lib/roadforest/{content-handling/type-handlers → type-handlers}/rdfa-writer/subject-environment.rb +7 -23
  86. data/lib/roadforest/type-handlers/rdfa.rb +73 -0
  87. data/lib/roadforest/type-handlers/rdfpost.rb +301 -0
  88. data/lib/roadforest/utility/class-registry.rb +23 -5
  89. data/spec/.ctrlp-root +0 -0
  90. data/spec/affordance-augmenter.rb +75 -0
  91. data/spec/affordances-flow.rb +438 -0
  92. data/spec/authorization.rb +34 -0
  93. data/spec/client.rb +13 -12
  94. data/spec/credence-annealer.rb +5 -5
  95. data/spec/focus-list.rb +8 -8
  96. data/spec/full-integration.rb +3 -3
  97. data/spec/graph-copier.rb +4 -4
  98. data/spec/graph-store.rb +19 -31
  99. data/spec/keychain.rb +82 -0
  100. data/spec/rdf-normalization.rb +2 -2
  101. data/spec/rdf-parcel.rb +3 -3
  102. data/spec/rdfa-handler.rb +514 -0
  103. data/spec/rdfpost.rb +96 -0
  104. data/spec/source-rigor.rb +57 -0
  105. data/spec/update-focus.rb +11 -10
  106. metadata +91 -66
  107. data/lib/roadforest/blob-model.rb +0 -53
  108. data/lib/roadforest/content-handling/type-handler.rb +0 -76
  109. data/lib/roadforest/content-handling/type-handlers/jsonld.rb +0 -36
  110. data/lib/roadforest/content-handling/type-handlers/rdf-handler.rb +0 -38
  111. data/lib/roadforest/content-handling/type-handlers/rdfa-writer/render-engine.rb +0 -574
  112. data/lib/roadforest/content-handling/type-handlers/rdfa.rb +0 -175
  113. data/lib/roadforest/content-handling/type-handlers/rdfpost.rb +0 -297
  114. data/lib/roadforest/model.rb +0 -209
  115. data/lib/roadforest/models.rb +0 -2
  116. data/lib/roadforest/rdf/source-rigor.rb +0 -44
  117. data/lib/roadforest/rdf/vocabulary.rb +0 -11
  118. data/lib/roadforest/resource/http/form-parsing.rb +0 -81
  119. data/lib/roadforest/resource/rdf.rb +0 -4
  120. data/spec/form-parsing.rb +0 -1
@@ -1,14 +1,14 @@
1
1
  require 'rdf'
2
2
  require 'roadforest/debug'
3
- require 'roadforest/rdf/vocabulary'
4
- require 'roadforest/rdf/normalization'
3
+ require 'roadforest/graph/vocabulary'
4
+ require 'roadforest/graph/normalization'
5
5
 
6
- require 'roadforest/rdf/resource-query'
7
- require 'roadforest/rdf/resource-pattern'
6
+ require 'roadforest/source-rigor/resource-query'
7
+ require 'roadforest/source-rigor/resource-pattern'
8
8
 
9
- module RoadForest::RDF
10
- class GraphStore
11
- include Normalization
9
+ module RoadForest
10
+ class SourceRigor::GraphStore
11
+ include Graph::Normalization
12
12
 
13
13
  #The interface supported by ::RDF::Graph
14
14
  include ::RDF::Countable
@@ -183,7 +183,7 @@ module RoadForest::RDF
183
183
  def query_execute(query, &block)
184
184
  #XXX Weird edge case of GM getting queried with a vanilla RDF::Query...
185
185
  #needs tests, thought
186
- query = ResourceQuery.from(query)
186
+ query = RoadForest::SourceRigor::ResourceQuery.from(query)
187
187
  query.execute(self).filter do |solution|
188
188
  solution.respond_to?(:context) and not solution.context.nil?
189
189
  end.each(&block)
@@ -191,7 +191,7 @@ module RoadForest::RDF
191
191
 
192
192
  def query_pattern(pattern, &block)
193
193
  case pattern
194
- when ResourcePattern
194
+ when RoadForest::SourceRigor::ResourcePattern
195
195
  pattern.execute(@repository, {}, :context_roles => {:local => local_context_node}) do |statement|
196
196
  next if statement.context.nil?
197
197
  yield statement if block_given?
@@ -1,6 +1,6 @@
1
- require 'roadforest/rdf/source-rigor/investigator'
1
+ require 'roadforest/source-rigor/investigator'
2
2
  module RoadForest
3
- class RDF::SourceRigor
3
+ module SourceRigor
4
4
  class HTTPInvestigator < Investigator
5
5
  register :http
6
6
 
@@ -1,6 +1,6 @@
1
- require 'roadforest/rdf'
1
+ require 'roadforest/graph'
2
2
 
3
- module RoadForest::RDF
3
+ module RoadForest::SourceRigor
4
4
  class Investigation
5
5
  attr_accessor :context_roles, :queryable, :results, :source_rigor
6
6
 
@@ -1,6 +1,6 @@
1
1
  require 'roadforest/utility/class-registry'
2
2
 
3
- class RoadForest::RDF::SourceRigor
3
+ module RoadForest::SourceRigor
4
4
  class NotCredible < StandardError; end
5
5
  class NoCredibleResults < StandardError; end
6
6
 
@@ -13,5 +13,5 @@ class RoadForest::RDF::SourceRigor
13
13
  end
14
14
  end
15
15
  end
16
- require 'roadforest/rdf/source-rigor/null-investigator'
17
- require 'roadforest/rdf/source-rigor/http-investigator'
16
+ require 'roadforest/source-rigor/null-investigator'
17
+ require 'roadforest/source-rigor/http-investigator'
@@ -1,5 +1,6 @@
1
- require 'roadforest/rdf/source-rigor/investigator'
2
- class RoadForest::RDF::SourceRigor
1
+ require 'roadforest/source-rigor/investigator'
2
+
3
+ module RoadForest::SourceRigor
3
4
  class NullInvestigator < Investigator
4
5
  register :null
5
6
 
@@ -1,9 +1,9 @@
1
- require 'roadforest/rdf'
2
- require 'roadforest/rdf/normalization'
1
+ require 'roadforest/graph'
2
+ require 'roadforest/graph/normalization'
3
3
 
4
- module RoadForest::RDF
5
- class Parcel
6
- include Normalization
4
+ module RoadForest
5
+ class SourceRigor::Parcel
6
+ include Graph::Normalization
7
7
 
8
8
  attr_accessor :graph
9
9
 
@@ -1,9 +1,9 @@
1
1
  require 'rdf/query/pattern'
2
- require 'roadforest/rdf'
3
- require 'roadforest/rdf/graph-store'
4
- require 'roadforest/rdf/investigation'
2
+ require 'roadforest/graph'
3
+ require 'roadforest/source-rigor/graph-store'
4
+ require 'roadforest/source-rigor/investigation'
5
5
 
6
- module RoadForest::RDF
6
+ module RoadForest::SourceRigor
7
7
  class ResourcePattern < ::RDF::Query::Pattern
8
8
  def self.from(pattern, options)
9
9
  pattern = case pattern
@@ -19,7 +19,7 @@ module RoadForest::RDF
19
19
  options ||= {}
20
20
  self.new(options.merge(pattern))
21
21
  else
22
- raise ArgumentError, "expected RoadForest::RDF::ResourcePattern, RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}"
22
+ raise ArgumentError, "expected RoadForest::SourceRigor::ResourcePattern, RDF::Query::Pattern, RDF::Statement, Hash, or Array, but got #{pattern.inspect}"
23
23
  end
24
24
 
25
25
  unless options.nil?
@@ -35,7 +35,7 @@ module RoadForest::RDF
35
35
  attr_accessor :context_roles, :source_rigor
36
36
 
37
37
  def execute(queryable, bindings = nil, query_context_roles = nil, &block)
38
- unless queryable.is_a? RoadForest::RDF::GraphStore
38
+ unless queryable.is_a? RoadForest::SourceRigor::GraphStore
39
39
  return super(queryable, bindings || {}, &block)
40
40
  end
41
41
 
@@ -1,7 +1,7 @@
1
- require 'roadforest/rdf'
1
+ require 'roadforest/graph'
2
2
  require 'rdf/query'
3
3
 
4
- module RoadForest::RDF
4
+ module RoadForest::SourceRigor
5
5
  class ResourceQuery < ::RDF::Query
6
6
  def initialize(patterns = [], options = {}, &block)
7
7
  @subject_context = options[:subject_context]
@@ -0,0 +1,101 @@
1
+ require 'roadforest/graph/access-manager'
2
+ require 'roadforest/source-rigor/resource-query'
3
+ require 'roadforest/source-rigor/resource-pattern'
4
+ require 'roadforest/source-rigor/parcel'
5
+
6
+ module RoadForest
7
+ module SourceRigor
8
+ module Rigorous
9
+ attr_accessor :rigor
10
+
11
+ def dup
12
+ other = self.class.allocate
13
+ other.resource = self.resource
14
+ other.rigor = self.rigor
15
+ other.source_graph = self.source_graph
16
+
17
+ return other
18
+ end
19
+
20
+ def build_query
21
+ ResourceQuery.new([], {}) do |query|
22
+ query.subject_context = resource
23
+ query.source_rigor = rigor
24
+ yield query
25
+ end
26
+ end
27
+
28
+ def query_execute(query, &block)
29
+ query = ResourceQuery.from(query, resource, rigor)
30
+ execute_search(query, &block)
31
+ end
32
+
33
+ def query_pattern(pattern, &block)
34
+ pattern = ResourcePattern.from(pattern, {:context_roles => {:subject => resource}, :source_rigor => rigor})
35
+ execute_search(pattern, &block)
36
+ end
37
+ end
38
+
39
+ class RetrieveManager < Graph::ReadOnlyManager
40
+ include Rigorous
41
+ end
42
+
43
+ class PostManager < Graph::WriteManager
44
+ include Rigorous
45
+ end
46
+
47
+ class UpdateManager < Graph::SplitManager
48
+ include Rigorous
49
+
50
+ def initialize
51
+ @copied_contexts = {}
52
+ end
53
+
54
+ attr_accessor :copied_contexts
55
+
56
+ def dup
57
+ other = super
58
+ other.copied_contexts = self.copied_contexts
59
+ other.target_graph = self.target_graph
60
+ return other
61
+ end
62
+
63
+ def execute_search(search, &block)
64
+ enum = search.execute(destination_graph)
65
+ if enum.any?{ true }
66
+ enum.each(&block)
67
+ return enum
68
+ end
69
+ search.execute(origin_graph, &block)
70
+ end
71
+
72
+ def insert(statement)
73
+ copy_context
74
+ super
75
+ end
76
+
77
+ def delete(statement)
78
+ copy_context
79
+ super
80
+ end
81
+
82
+ def parceller
83
+ @parceller ||=
84
+ begin
85
+ parceller = Parcel.new
86
+ parceller.graph = source_graph
87
+ parceller
88
+ end
89
+ end
90
+
91
+ def copy_context
92
+ return if copied_contexts[resource]
93
+ parceller.graph_for(resource).each_statement do |statement|
94
+ statement.context = resource
95
+ destination_graph << statement
96
+ end
97
+ copied_contexts[resource] = true
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,23 @@
1
+ !!! XML
2
+ !!! 5
3
+ %html{:xmlns => "http://www.w3.org/1999/xhtml", :lang => lang, :prefix => prefix}
4
+ - if base || title
5
+ %head
6
+ - if base
7
+ %base{:href => base}
8
+ - if title
9
+ %title= title
10
+ %body
11
+ - subjects.each do |subject|
12
+ - if subject.respond_to? :affordance?
13
+ %form{subject.attrs}
14
+ %input{type: "hidden", name: "rdf"}
15
+ - prefixes.each do |name, target|
16
+ - unless name.nil? or name.empty?
17
+ %input{type: "hidden", name: "n", value: name}
18
+ %input{type: "hidden", name: "v", value: target}
19
+
20
+ != yield(subject)
21
+ - else
22
+ %div{subject.attrs}
23
+ != yield(subject)
@@ -0,0 +1,13 @@
1
+ %div.property
2
+ = rdfpost_curie("p", predicate)
3
+ - objects.each do |object|
4
+ - if object.is_subject?
5
+ = rdfpost_curie("o", object.subject)
6
+ - elsif object.attrs.empty?
7
+ = yield(object)
8
+ - else
9
+ %label{object.label_attrs}
10
+ %span= get_predicate_name(predicate)
11
+ %input{object.input_attrs(yield(object))}
12
+ - if(object.type_uri)
13
+ %input{type: "hidden", name: "lt", value: object.type_uri}
@@ -0,0 +1,9 @@
1
+ - if typeof
2
+ %span.type!= typeof
3
+
4
+ = rdfpost_curie("s", subject)
5
+
6
+ - predicates.each do |predicate|
7
+ != yield(predicate)
8
+ - predicate_nodes.each do |subject|
9
+ %div{subject.attrs}= yield subject
@@ -0,0 +1,2 @@
1
+ = rdfpost_curie("o", object)
2
+ %a{:property => get_curie(predicate), :href => object.to_s, :inlist => inlist}= object.to_s
@@ -0,0 +1,6 @@
1
+ - if reduced?
2
+ - unless prefix.empty?
3
+ %input{type: "hidden", name: "#{kind}n", value: prefix}
4
+ %input{type: "hidden", name: "#{kind}v", value: suffix}
5
+ - else
6
+ %input{type: "hidden", name: "#{kind}u", value: uri}
@@ -3,6 +3,8 @@ require 'webmachine/headers'
3
3
  require 'webmachine/request'
4
4
  require 'webmachine/response'
5
5
  require 'webmachine/decision/flow'
6
+ require 'webmachine/decision/fsm'
7
+
6
8
  module RoadForest
7
9
  module TestSupport
8
10
  class DispatcherFacade < BasicObject
@@ -1,7 +1,165 @@
1
+ require 'rdf/isomorphic'
2
+ require 'rspec/matchers'
3
+ require 'nokogiri'
4
+
5
+ class RDF::Repository
6
+ include RDF::Isomorphic
7
+ end
8
+
1
9
  module RoadForest
2
10
  module Testing
11
+ module HelperMethods
12
+ def statements_from_graph(graph)
13
+ StatementsFromGraph.new(graph)
14
+ end
15
+
16
+ def normalize(graph)
17
+ case graph
18
+ when RDF::Queryable then graph
19
+ when IO, StringIO
20
+ RDF::Graph.new.load(graph, :base_uri => @info.about)
21
+ else
22
+ # Figure out which parser to use
23
+ g = RDF::Graph.new
24
+ reader_class = detect_format(graph)
25
+ reader_class.new(graph, :base_uri => @info.about).each {|s| g << s}
26
+ g
27
+ end
28
+ end
29
+ end
30
+
31
+ class BeEquivalentGraph
32
+ include HelperMethods
33
+ Info = Struct.new(:about, :num, :trace, :compare, :inputDocument, :outputDocument, :expectedResults, :format, :title)
34
+
35
+ def initialize(expected, info)
36
+ @expected = normalize(expected)
37
+
38
+ @info =
39
+ if info.respond_to?(:about)
40
+ info
41
+ elsif info.is_a?(Hash)
42
+ identifier = expected.is_a?(RDF::Graph) ? expected.context : info[:about]
43
+ trace = info[:trace]
44
+ trace = trace.join("\n") if trace.is_a?(Array)
45
+ i = Info.new(identifier, "0000", trace, info[:compare])
46
+ i.format = info[:format]
47
+ i
48
+ else
49
+ Info.new(expected.is_a?(RDF::Graph) ? expected.context : info, "0000", info.to_s)
50
+ end
51
+
52
+ @info.format ||= :ttl
53
+ end
54
+ attr_reader :expected, :info
55
+
56
+ def matches?(actual)
57
+ @actual = normalize(actual)
58
+ @actual.isomorphic_with?(@expected)# rescue false
59
+ end
60
+
61
+ def dump_graph(graph)
62
+ graph.dump(@info.format, :standard_prefixes => true)
63
+ rescue
64
+ begin
65
+ graph.dump(:nquads, :standard_prefixes => true)
66
+ rescue
67
+ graph.inspect
68
+ end
69
+ end
70
+
71
+ def description
72
+ "be equivalent to an expected graph" #graphs tend to be too long to use
73
+ end
74
+
75
+ def failure_message_for_should(actual)
76
+ info = @info.respond_to?(:about) ? @info.about : @info.inspect
77
+ if @expected.is_a?(RDF::Graph) && @actual.size != @expected.size
78
+ "Graph entry count differs:\nexpected: #{@expected.size}\nactual: #{@actual.size}"
79
+ elsif @expected.is_a?(Array) && @actual.size != @expected.length
80
+ "Graph entry count differs:\nexpected: #{@expected.length}\nactual: #{@actual.size}"
81
+ else
82
+ "Graph differs"
83
+ end +
84
+ "\n#{info + "\n" unless info.to_s.empty?}" +
85
+ (@info.inputDocument ? "Input file: #{@info.inputDocument}\n" : "") +
86
+ (@info.outputDocument ? "Output file: #{@info.outputDocument}\n" : "") +
87
+ "\nExpected:\n#{dump_graph(@expected)}" +
88
+ "\nResults:\n#{dump_graph(@actual)}" +
89
+ (@info.trace ? "\nDebug:\n#{@info.trace}" : "")
90
+ end
91
+ end
92
+
93
+ class HaveXpath
94
+ def initialize(xpath, value, trace)
95
+ @xpath, @value, @trace = xpath, value, trace
96
+ end
97
+ attr_reader :xpath, :value, :trace
98
+
99
+ def matches?(actual)
100
+ @doc = Nokogiri::HTML.parse(actual)
101
+ @namespaces = @doc.namespaces.merge("xhtml" => "http://www.w3.org/1999/xhtml", "xml" => "http://www.w3.org/XML/1998/namespace")
102
+ found = @doc.root.at_xpath(xpath, @namespaces)
103
+ case value
104
+ when false
105
+ found.nil?
106
+ when true
107
+ !found.nil?
108
+ when Array
109
+ found.to_s.split(" ").include?(*value)
110
+ when Regexp
111
+ found.to_s =~ value
112
+ else
113
+ found.to_s == value
114
+ end
115
+ end
116
+
117
+ def failure_message_for_should(actual)
118
+ trace ||= debug
119
+ msg =
120
+ case value
121
+ when true
122
+ "expected that #{xpath.inspect} would be present\nwas:\n #{found.inspect}\n"
123
+ when false
124
+ "expected that #{xpath.inspect} would be absent\nwas:\n #{found.inspect}\n"
125
+ else
126
+ "expected that #{xpath.inspect} would be\n #{value.inspect}\nwas:\n #{found.inspect}\n"
127
+ end
128
+ msg += "in:\n" + actual.to_s
129
+ msg += "\nDebug:#{trace.join("\n")}" if trace
130
+ msg
131
+ end
132
+
133
+ def failure_message_for_should_not(actual)
134
+ trace ||= debug
135
+ msg = "expected that #{xpath.inspect} would not be #{value.inspect} in:\n" + actual.to_s
136
+ msg += "\nDebug:#{trace.join("\n")}" if trace
137
+ msg
138
+ end
139
+ end
140
+
141
+ class Produces
142
+ def initialize(expected, info)
143
+ @expected, @info = expected, info
144
+ end
145
+ attr_reader :expected, :info
146
+
147
+ def matches?(actual)
148
+ actual == expected
149
+ end
150
+
151
+ def failure_message_for_should(actual)
152
+ "Expected: #{expected.inspect}\n" +
153
+ "Actual : #{actual.inspect}\n" +
154
+ "Processing results:\n#{info.join("\n")}"
155
+ end
156
+ end
157
+
3
158
  class MatchesQuery
4
159
  def initialize(pattern = nil, &block)
160
+ if pattern.nil? and block.nil?
161
+ raise "Matches query (e.g. should match_query) created with no patterns: probably used a do block..."
162
+ end
5
163
  pattern ||= []
6
164
  if Hash === pattern
7
165
  pattern = [pattern]
@@ -74,17 +232,23 @@ module RoadForest
74
232
  alias that_match_pattern that_match_query
75
233
  end
76
234
 
77
- module HelperMethods
78
- def statements_from_graph(graph)
79
- StatementsFromGraph.new(graph)
235
+ module MatcherMethods
236
+ def produce(expected, info)
237
+ Produces.new(expected, info)
238
+ end
239
+
240
+ def have_xpath(xpath, value = true, trace = nil)
241
+ HaveXpath.new(xpath, value, trace || debug)
80
242
  end
81
- end
82
243
 
83
- module MatcherMethods
84
244
  def match_query(pattern = nil, &block)
85
245
  MatchesQuery.new(pattern, &block)
86
246
  end
87
247
 
248
+ def be_equivalent_graph(graph, info = nil)
249
+ BeEquivalentGraph.new(graph, info)
250
+ end
251
+
88
252
  def be_equivalent_to(list)
89
253
  ListEquivalence.new(list)
90
254
  end