roadforest 0.0.1

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.
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,95 @@
1
+ require 'rdf'
2
+ require 'roadforest/rdf/context-fascade'
3
+ require 'roadforest/rdf/focus-wrapping'
4
+ require 'roadforest/rdf/graph-reading'
5
+
6
+ module RoadForest::RDF
7
+ class GraphCollection
8
+ include Enumerable
9
+ end
10
+
11
+ class MultivaluedProperty < GraphCollection
12
+ attr_reader :graph, :subject, :property
13
+ def initialize(graph, subject, property)
14
+ @graph, @subject, @propery = graph, subject, property
15
+ end
16
+
17
+ def values
18
+ query_value(graph, subject, property)
19
+ end
20
+
21
+ def each
22
+ if block_given?
23
+ other
24
+ values.each do |value|
25
+ yield unwrap_value(value)
26
+ end
27
+ else
28
+ values.each
29
+ end
30
+ end
31
+
32
+ def add(value)
33
+ add_statement(subject, property, value)
34
+ end
35
+ end
36
+
37
+ module GraphWriting
38
+ def normalize_triple(property, value, extra=nil)
39
+ if not extra.nil?
40
+ property = [property, value]
41
+ value = extra
42
+ end
43
+ return normalize_property(property), normalize_term(value)
44
+ end
45
+
46
+ def set(property, value, extra=nil)
47
+ property, value = normalize_triple(property, value, extra)
48
+
49
+ delete(property)
50
+ add(property, value)
51
+ return value
52
+ end
53
+ alias_method :[]=, :set
54
+
55
+ def add(property, value, extra=nil)
56
+ property, value = normalize_triple(property, value, extra)
57
+
58
+ target_graph.insert([subject, property, value])
59
+ return value
60
+ end
61
+
62
+ def delete(property, extra=nil)
63
+ target_graph.delete([subject, normalize_property(property, extra), :value])
64
+ end
65
+
66
+ 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
70
+ end
71
+ alias node_at set_node
72
+
73
+ def add_node(property, url=nil)
74
+ node = wrap_node(add(property, normalize_resource(url) || RDF::Node.new))
75
+ yield node if block_given?
76
+ node
77
+ end
78
+
79
+ 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])
82
+ yield list if block_given?
83
+ return list
84
+ end
85
+ end
86
+
87
+ class GraphFocus < GraphReading
88
+ include GraphWriting
89
+
90
+ def target_graph
91
+ graph
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,145 @@
1
+ require 'roadforest/rdf/focus-list'
2
+ require 'roadforest/rdf/normalization'
3
+ require 'roadforest/rdf/focus-wrapping'
4
+ require 'roadforest/rdf/resource-query'
5
+
6
+ module RoadForest::RDF
7
+ class GraphReading
8
+ include Normalization
9
+ include FocusWrapping
10
+
11
+ attr_accessor :graph, :subject, :root_url, :source_rigor
12
+ alias rdf subject
13
+
14
+ def initialize(subject = nil, graph = nil, rigor = nil)
15
+ @graph = nil
16
+ @subject = nil
17
+ @root_url = nil
18
+ @source_rigor = nil
19
+ self.subject = subject unless subject.nil?
20
+ self.graph = graph unless graph.nil?
21
+ self.source_rigor = rigor unless rigor.nil?
22
+ end
23
+
24
+ def inspect
25
+ "#<#{self.class.name}:0x#{"%x" % object_id} (#{subject.to_s}) #{forward_properties.inspect}>"
26
+ end
27
+
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
35
+ end
36
+
37
+ def to_context
38
+ normalize_context(subject)
39
+ end
40
+
41
+ def root_url=(*value) #XXX curies?
42
+ @root_url = normalize_resource(value)
43
+ end
44
+
45
+ def subject=(*value)
46
+ @subject = normalize_resource(value)
47
+ case @subject
48
+ when ::RDF::URI
49
+ @root_url ||= @subject
50
+ end
51
+ end
52
+
53
+ def build_query
54
+ ResourceQuery.new([], {}) do |query|
55
+ query.subject_context = @root_url
56
+ query.source_rigor = @source_rigor
57
+ yield query
58
+ end
59
+ end
60
+
61
+ def forward_properties
62
+ query_properties( build_query{|q| q.pattern([ normalize_resource(subject), :property, :value ])} )
63
+ end
64
+
65
+ def reverse_properties
66
+ query_properties( build_query{|q| q.pattern([ :value, :property, normalize_resource(subject)])} )
67
+ end
68
+
69
+ def get(prefix, property = nil)
70
+ return single_or_enum(forward_query_value( prefix, property))
71
+ end
72
+ alias_method :[], :get
73
+
74
+ def first(prefix, property = nil)
75
+ return forward_query_value( prefix, property ).first
76
+ end
77
+
78
+ def all(prefix, property = nil)
79
+ return forward_query_value( prefix, property )
80
+ end
81
+
82
+ #XXX Maybe rev should return a decorator, so it looks like:
83
+ #focus.rev.get(...) or focus.rev.all(...)
84
+ def rev(prefix, property = nil)
85
+ return single_or_enum(reverse_query_value( prefix, property))
86
+ end
87
+
88
+ def rev_first(prefix, property = nil)
89
+ return reverse_query_value(prefix, property).first
90
+ end
91
+
92
+ def rev_all(prefix, property = nil)
93
+ return reverse_query_value(prefix, property)
94
+ end
95
+
96
+ def as_list
97
+ graph = ContextFascade.new(@graph, @root_url, @source_rigor)
98
+ list = FocusList.new(@subject, graph)
99
+ list.base_node = self
100
+ list.source_rigor = source_rigor
101
+ list
102
+ end
103
+
104
+ protected
105
+
106
+ def reverse_query_value(prefix, property=nil)
107
+ query_value(build_query{|q|
108
+ q.pattern([ :value, normalize_property(prefix, property), normalize_resource(subject)])
109
+ })
110
+ end
111
+
112
+ def forward_query_value(prefix, property=nil)
113
+ query_value(build_query{|q|
114
+ q.pattern([ normalize_resource(subject), normalize_property(prefix, property), :value])
115
+ })
116
+ end
117
+
118
+ def query_value(query)
119
+ solutions = query.execute(graph)
120
+ solutions.map do |solution|
121
+ unwrap_value(solution.value)
122
+ end
123
+ 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
+
135
+ def query_properties(query)
136
+ Hash[query.execute(graph).map do |solution|
137
+ prop = solution.property
138
+ if qname = prop.qname
139
+ prop = qname
140
+ end
141
+ [prop, solution.value]
142
+ end]
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,217 @@
1
+ require 'rdf'
2
+ require 'roadforest/rdf/graph-focus'
3
+ require 'roadforest/rdf/vocabulary'
4
+ require 'roadforest/rdf/normalization'
5
+
6
+ require 'roadforest/rdf/resource-query'
7
+ require 'roadforest/rdf/resource-pattern'
8
+
9
+ module RoadForest::RDF
10
+ class GraphStore
11
+ include Normalization
12
+
13
+ #The interface supported by ::RDF::Graph
14
+ include ::RDF::Countable
15
+ include ::RDF::Durable
16
+ include ::RDF::Enumerable
17
+ include ::RDF::Mutable
18
+ include ::RDF::Queryable
19
+ include ::RDF::Resource
20
+
21
+ attr_reader :repository, :current_impulse, :local_context_node
22
+ attr_accessor :debug_io
23
+
24
+ def initialize(repo = nil)
25
+ @repository = repo || RDF::Repository.new
26
+ @local_context_node = RDF::Node.new(:local)
27
+ @debug_io = nil
28
+ next_impulse
29
+ yield self if block_given?
30
+ end
31
+
32
+ def next_impulse
33
+ return if !@current_impulse.nil? and raw_quiet_impulse?
34
+ #mark ended?
35
+ #chain impulses?
36
+ @current_impulse = RDF::Node.new
37
+ repository.insert(normalize_statement(@current_impulse, [:rdf, 'type'], [:rf, 'Impulse'], nil))
38
+ repository.insert(normalize_statement(@current_impulse, [:rf, 'begunAt'], Time.now, nil))
39
+ end
40
+
41
+ def quiet_impulse?
42
+ raw_quiet_impulse?
43
+ end
44
+
45
+ def raw_quiet_impulse?
46
+ repository.query([nil, nil, @current_impulse, false]).to_a.empty?
47
+ end
48
+
49
+ #repo cleanup - expired graphs
50
+
51
+ def reader_for(content_type, repository)
52
+ RDF::Reader.for(content_type)
53
+ end
54
+
55
+ def debug(message)
56
+ return if @debug_io.nil?
57
+ @debug_io.puts(message)
58
+ end
59
+
60
+ def repository_dump(format = :turtle)
61
+ repository.dump(format)
62
+ end
63
+ alias graph_dump repository_dump
64
+
65
+ def delete_statements(pattern)
66
+ repository.delete(pattern)
67
+ end
68
+
69
+ def named_graph(context)
70
+ ::RDF::Graph.new(context, :data => repository)
71
+ end
72
+
73
+ def named_list(context, values = nil)
74
+ ::RDF::List.new(nil, named_graph(context), values)
75
+ end
76
+
77
+ def create_list(values = nil)
78
+ named_list(local_context_node, values)
79
+ end
80
+
81
+ def insert_document(document)
82
+ #puts; puts "#{__FILE__}:#{__LINE__} => #{(document).inspect}"
83
+ #puts document.body_string
84
+ reader = RDF::Reader.for(:content_type => document.content_type) do
85
+ sample = document.body.read(1000)
86
+ document.body.rewind
87
+ sample
88
+ end.new(document.body, :base_uri => document.root_url) #consider :processor_graph
89
+ insert_reader(document.source, reader)
90
+ end
91
+
92
+ def insert_reader(context, reader)
93
+ #puts; puts "#{__FILE__}:#{__LINE__} => #{(context).inspect}"
94
+ context = normalize_context(context)
95
+ delete_statements(:context => context)
96
+ reader.each_statement do |statement|
97
+ statement.context = context
98
+ record_statement(statement)
99
+ end
100
+ #puts; puts "#{__FILE__}:#{__LINE__} => \n#{(graph_dump(:nquads))}"
101
+ end
102
+
103
+ def insert_graph(context, graph)
104
+ context = normalize_context(context)
105
+ delete_statements(:context => context)
106
+ graph.each_statement do |statement|
107
+ statement.context = context
108
+ record_statement(statement)
109
+ end
110
+ end
111
+
112
+ def add_statement(*args)
113
+ case args.length
114
+ when 1
115
+ subject, predicate, object, context = *args.first
116
+ when 2
117
+ triple, context = *args
118
+ subject, predicate, object = *triple
119
+ when 3
120
+ subject, predicate, object = *args
121
+ context = nil
122
+ when 4
123
+ subject, predicate, object, context = *args
124
+ else
125
+ raise ArgumentError, "insert_statement needs some variation of subject, predicate, object, [context]"
126
+ end
127
+ context ||= local_context_node
128
+
129
+ record_statement(normalize_statement(subject, predicate, object, context))
130
+ end
131
+
132
+ def insert_statement(statement)
133
+ repository.insert(statement)
134
+
135
+ repository.delete([statement.context, expand_curie([:rf, "impulse"]), nil])
136
+ repository.insert(normalize_statement(statement.context, [:rf, "impulse"], current_impulse, nil))
137
+ end
138
+ alias record_statement insert_statement
139
+
140
+ def delete_statement(statement)
141
+ repository.query(statement) do |statement|
142
+ next if statement.context.nil?
143
+ repository.delete(statement)
144
+ end
145
+ end
146
+
147
+ def replace(original, statement)
148
+ unless original == statement
149
+ repository.delete(original)
150
+ repository.insert(statement)
151
+ end
152
+ end
153
+
154
+ def each_statement(context=nil, &block)
155
+ query = {}
156
+ unless context.nil?
157
+ query[:context] = context
158
+ end
159
+
160
+ @repository.query(query) do |statement|
161
+ yield statement
162
+ end
163
+ end
164
+
165
+ def durable?
166
+ @repository.durable?
167
+ end
168
+
169
+ #XXX Credence? Default context?
170
+ def each(&block)
171
+ if @repository.respond_to?(:query)
172
+ @repository.query(:context => false, &block)
173
+ elsif @repository.respond_to?(:each)
174
+ @repository.each(&block)
175
+ else
176
+ @repository.to_a.each(&block)
177
+ end
178
+ end
179
+
180
+ #XXX Needed, maybe, if we need to handle constant patterns
181
+ #def include?(statement)
182
+ #end
183
+
184
+ def context_variable
185
+ @context_variable ||= RDF::Query::Variable.new(:context)
186
+ end
187
+
188
+ def query_execute(query, &block)
189
+ #XXX Weird edge case of GM getting queried with a vanilla RDF::Query...
190
+ #needs tests, thought
191
+ query = ResourceQuery.from(query)
192
+ query.execute(self).filter do |solution|
193
+ solution.respond_to?(:context) and not solution.context.nil?
194
+ end.each(&block)
195
+ end
196
+
197
+ def query_pattern(pattern, &block)
198
+ case pattern
199
+ when ResourcePattern
200
+ pattern.execute(@repository, {}, :context_roles => {:local => local_context_node}) do |statement|
201
+ next if statement.context.nil?
202
+ yield statement if block_given?
203
+ end
204
+ else
205
+ pattern.execute(@repository, {}) do |statement|
206
+ next if statement.context.nil?
207
+ yield statement if block_given?
208
+ end
209
+ end
210
+ end
211
+
212
+ def unnamed_graph
213
+ ::RDF::Graph.new(nil, :data => @repository)
214
+ end
215
+
216
+ end
217
+ end
@@ -0,0 +1,90 @@
1
+ require 'roadforest/rdf'
2
+
3
+ module RoadForest::RDF
4
+ class Investigation
5
+ attr_accessor :context_roles, :queryable, :results, :source_rigor
6
+
7
+ def initialize
8
+ @results = []
9
+ end
10
+
11
+ def http_client
12
+ queryable.http_client
13
+ end
14
+
15
+ def found_results?
16
+ !@results.nil?
17
+ end
18
+
19
+ def investigators
20
+ source_rigor.investigators
21
+ end
22
+
23
+ def credence_policies
24
+ source_rigor.credence_policies
25
+ end
26
+
27
+ def make_request(method, url, graph=nil)
28
+ source_rigor.graph_transfer.make_request(method, url, graph)
29
+ end
30
+
31
+
32
+ def insert_graph(context, graph)
33
+ queryable.insert_graph(context, graph)
34
+ end
35
+
36
+ def result
37
+ investigators.each do |investigator|
38
+ self.results = []
39
+ yield(results)
40
+
41
+ contexts = result_contexts
42
+
43
+ catch :not_credible do
44
+ credence_policies.each do |policy|
45
+ contexts = policy.credible(contexts, self)
46
+ if contexts.empty?
47
+ throw :not_credible
48
+ end
49
+ end
50
+ return results_for_context(contexts.first)
51
+ end
52
+
53
+ self.results = nil
54
+ investigator.pursue(self)
55
+
56
+ if found_results?
57
+ return results
58
+ end
59
+ end
60
+ raise NoCredibleResults
61
+ end
62
+
63
+ def result_contexts
64
+ (results.map(&:context) +
65
+ context_roles.values.find_all do |context|
66
+ not context_metadata(context).empty?
67
+ end).uniq
68
+ end
69
+
70
+ def context_metadata(context)
71
+ query = RDF::Query.new do |query|
72
+ query.pattern [context, :property, :value]
73
+ end
74
+ query.execute(queryable.unnamed_graph).select(:property, :value)
75
+ end
76
+
77
+ def results_for_context(context)
78
+ results.find_all{|item| item.context == context}
79
+ end
80
+
81
+ #XXX Do we need the nil result if context_metadata is empty?
82
+ def empty_for_context(context)
83
+ if context_metadata(context).empty? #We've never checked
84
+ nil
85
+ else
86
+ empty_result
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,150 @@
1
+ require 'rdf'
2
+
3
+ module RoadForest::RDF
4
+ module Normalization
5
+ Vocabs = {}
6
+ Vocabs["rdf"] = RDF
7
+
8
+ def normalize_statement(subject, predicate, object, context)
9
+ subject = normalize_resource(subject) || RDF::Node.new
10
+ predicate = normalize_uri(predicate)
11
+ object = normalize_term(object) || RDF::Node.new
12
+ context = normalize_resource(context)
13
+
14
+ RDF::Statement.new(subject, predicate, object, :context => context)
15
+ end
16
+
17
+ def normalize_tuple(tuple)
18
+ subject, predicate, object, context = *tuple
19
+ [ normalize_resource(subject) || RDF::Node.new, normalize_uri(predicate), normalize_term(object) || RDF::Node.new, normalize_resource(context) ]
20
+ end
21
+
22
+ def normalize_resource(from)
23
+ from = expand_curie(from)
24
+ case from
25
+ when nil
26
+ when RDF::Resource
27
+ when /^_:/
28
+ from = RDF::Resource.new(from)
29
+ when String, RDF::URI, Addressable::URI
30
+ from = interned_uri(from)
31
+ when Symbol
32
+ from = RDF::Node.new(from)
33
+ else
34
+ from = RDF::Resource.new(from)
35
+ end
36
+ return from
37
+ end
38
+
39
+ def normalize_context(from)
40
+ case from
41
+ when Array
42
+ from = expand_curie(from)
43
+ when RDF::URI, Addressable::URI, String
44
+ from = uri(from)
45
+ else
46
+ return nil
47
+ end
48
+ from.fragment = nil
49
+ return RDF::URI.intern(from.to_s)
50
+ end
51
+
52
+ def normalize_uri(from)
53
+ from = expand_curie(from)
54
+ case from
55
+ when nil
56
+ when RDF::URI
57
+ else
58
+ from = interned_uri(from)
59
+ end
60
+ return from
61
+ end
62
+
63
+ def normalize_term(object)
64
+ if Array === object
65
+ RDF::Resource.new(expand_curie(object))
66
+ else
67
+ object
68
+ end
69
+ end
70
+
71
+ def literal(object)
72
+ RDF::Literal.new(object)
73
+ end
74
+
75
+ def expand_curie_pair(prefix, property)
76
+ vocab = Vocabs.fetch(prefix) do
77
+ vocab = RDF::Vocabulary.find do |vocab|
78
+ vocab.__prefix__.to_s == prefix
79
+ end
80
+ #p k => vocab #ok
81
+ if vocab.nil?
82
+ raise "Don't know a vocabulary for prefix #{prefix.inspect} in CURIE #{prefix}:#{property}"
83
+ end
84
+ Vocabs[prefix] = vocab
85
+ vocab
86
+ end
87
+ vocab[property]
88
+ end
89
+
90
+ def expand_curie(from)
91
+ case from
92
+ when Array
93
+ case from.length
94
+ when 2
95
+ prefix, property = *from
96
+ return interned_uri(expand_curie_pair(prefix.to_s, property.to_s))
97
+ when 1
98
+ return expand_curie(from.first)
99
+ else
100
+ return from
101
+ end
102
+ else
103
+ return from
104
+ end
105
+ end
106
+
107
+ def normalize_property(prefix, property = nil)
108
+ if property.nil?
109
+ property = prefix
110
+
111
+ case property
112
+ when Array
113
+ normalize_property(*property)
114
+ when String
115
+ RDF::URI.intern(property)
116
+ else
117
+ property
118
+ end
119
+ else
120
+ expand_curie([prefix, property])
121
+ end
122
+ end
123
+
124
+ def root_url
125
+ nil
126
+ end
127
+
128
+ def interned_uri(value)
129
+
130
+ RDF::URI.intern(uri(value))
131
+ end
132
+
133
+ def uri(value)
134
+ if root_url
135
+ value = root_url.join(value)
136
+ else
137
+ value = RDF::URI.new(value)
138
+ end
139
+
140
+ if !value.query.nil? and value.query.empty?
141
+ value.query = nil
142
+ end
143
+ value.validate!
144
+ value.canonicalize!
145
+
146
+ value
147
+ end
148
+ end
149
+
150
+ end