activedocument 0.2.2 → 0.3
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.
@@ -65,35 +65,47 @@ module ActiveDocument
|
|
65
65
|
# -------------------
|
66
66
|
class Base < Finder
|
67
67
|
include ClassLevelInheritableAttributes
|
68
|
-
inheritable_attributes_list :
|
69
|
-
@
|
70
|
-
@
|
71
|
-
attr_reader :document, :uri
|
68
|
+
inheritable_attributes_list :my_namespaces, :my_default_namespace, :root
|
69
|
+
@my_namespaces = Hash.new
|
70
|
+
@my_default_namespace = String.new
|
71
|
+
attr_reader :document, :uri, :my_namespaces, :my_default_namespace, :root
|
72
72
|
|
73
73
|
|
74
74
|
# create a new instance with an optional xml string to use for constructing the model
|
75
|
-
def initialize(xml_string =
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
def initialize(xml_string = "", uri = "nil")
|
76
|
+
@document = Nokogiri::XML(xml_string) do |config|
|
77
|
+
config.noblanks
|
78
|
+
end
|
79
|
+
if !xml_string.empty? then
|
80
|
+
@root = @document.root.name
|
80
81
|
end
|
81
|
-
@root = self.class.to_s
|
82
82
|
@uri = uri
|
83
83
|
end
|
84
84
|
|
85
|
+
def to_s
|
86
|
+
@document.to_xml(:save_with => Nokogiri::XML::Node::SaveOptions::NO_DECLARATION)
|
87
|
+
end
|
88
|
+
|
89
|
+
# saves this document to the repository. If _uri_ is provided then that will be the value used for the uri.
|
90
|
+
# If no uri was passed in then the existing value or the uri is used, unless uri is nil in which case an exception
|
91
|
+
# will be thrown
|
92
|
+
def save(uri = nil)
|
93
|
+
doc_uri = (uri || @uri)
|
94
|
+
if doc_uri then
|
95
|
+
@@ml_http.send_xquery(@@xquery_builder.save(self, doc_uri))
|
96
|
+
else
|
97
|
+
raise ArgumentError, "uri must not be nil", caller
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
85
102
|
# Returns the root element for this object
|
86
103
|
def root
|
87
104
|
@root
|
88
105
|
end
|
89
106
|
|
90
|
-
# Sets the root element for this object
|
91
|
-
def root=(value)
|
92
|
-
@root = value
|
93
|
-
end
|
94
|
-
|
95
107
|
# enables the dynamic finders
|
96
|
-
def method_missing(method_id, *arguments, &block)
|
108
|
+
def method_missing(method_id, * arguments, & block)
|
97
109
|
@@log.debug("ActiveDocument::Base at line #{__LINE__}: method called is #{method_id} with arguments #{arguments}")
|
98
110
|
method = method_id.to_s
|
99
111
|
if method =~ /^(\w*)$/ # methods with no '.' in them and not ending in '='
|
@@ -101,77 +113,47 @@ module ActiveDocument
|
|
101
113
|
super
|
102
114
|
end
|
103
115
|
access_element $1
|
116
|
+
elsif method =~ /^(\w*)=$/ && arguments.length == 1 # methods with no '.' in them and ending in '='
|
117
|
+
set_element($1, arguments)
|
104
118
|
end
|
105
119
|
end
|
106
120
|
|
107
|
-
def access_element(element)
|
108
|
-
xpath = ""
|
109
|
-
xpath = "//" unless self.instance_of? PartialResult
|
110
|
-
namespace = self.class.namespace_for_element(element)
|
111
|
-
element = "ns:#{element}" unless namespace.nil? || namespace.empty?
|
112
|
-
xpath << element
|
113
|
-
if namespace.nil?
|
114
|
-
nodes = @document.xpath(xpath)
|
115
|
-
else
|
116
|
-
nodes = @document.xpath(xpath, {'ns' => namespace})
|
117
|
-
end
|
118
|
-
evaluate_nodeset(nodes)
|
119
|
-
|
120
|
-
end
|
121
121
|
|
122
|
+
class << self
|
123
|
+
attr_reader :namespaces, :default_namespace, :root
|
122
124
|
|
123
|
-
|
124
|
-
|
125
|
-
if
|
126
|
-
|
127
|
-
elsif result_nodeset[0].children.length >1 # we are now dealing with complex nodes
|
128
|
-
PartialResult.new(result_nodeset)
|
129
|
-
end
|
130
|
-
elsif result_nodeset.length >1 # multiple matches
|
131
|
-
if result_nodeset.all? {|node| node.children.length == 1} and result_nodeset.all? {|node| node.children[0].type == Nokogiri::XML::Node::TEXT_NODE}
|
132
|
-
# we have multiple simple text nodes
|
133
|
-
result_nodeset.collect {|node| node.text}
|
125
|
+
def namespace_for_element(element)
|
126
|
+
namespace = nil
|
127
|
+
if !@my_namespaces.nil? && @my_namespaces[element]
|
128
|
+
namespace = @my_namespaces[element]
|
134
129
|
else
|
135
|
-
|
136
|
-
PartialResult.new(result_nodeset)
|
130
|
+
namespace = @my_default_namespace unless @my_default_namespace.nil?
|
137
131
|
end
|
138
|
-
|
139
|
-
end
|
140
|
-
|
141
|
-
class PartialResult < self
|
142
|
-
def initialize(nodeset)
|
143
|
-
@document = nodeset
|
144
|
-
@root = nodeset[0].name
|
145
|
-
end
|
146
|
-
|
147
|
-
def to_s
|
148
|
-
@document.to_s
|
132
|
+
namespace
|
149
133
|
end
|
150
134
|
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
class << self
|
155
|
-
attr_reader :namespaces, :default_namespace, :root
|
156
|
-
|
157
135
|
def namespaces(namespace_hash)
|
158
|
-
@
|
136
|
+
@my_namespaces = namespace_hash
|
159
137
|
end
|
160
138
|
|
161
139
|
def add_namespace(element, uri)
|
162
|
-
@
|
140
|
+
@my_namespaces[element.to_s] == uri
|
163
141
|
end
|
164
142
|
|
165
143
|
def remove_namespace(element)
|
166
|
-
@
|
144
|
+
@my_namespaces.delete element
|
167
145
|
end
|
168
146
|
|
169
147
|
def default_namespace(namespace)
|
170
|
-
@
|
148
|
+
@my_default_namespace = namespace # todo should this just be an entry in namespaces?
|
149
|
+
end
|
150
|
+
|
151
|
+
def delete(uri)
|
152
|
+
@@ml_http.send_xquery(@@xquery_builder.delete(uri))
|
171
153
|
end
|
172
154
|
|
173
155
|
# enables the dynamic finders
|
174
|
-
def method_missing(method_id, *arguments, &block)
|
156
|
+
def method_missing(method_id, * arguments, & block)
|
175
157
|
@@log.debug("ActiveDocument::Base at line #{__LINE__}: method called is #{method_id} with arguments #{arguments}")
|
176
158
|
method = method_id.to_s
|
177
159
|
# identify element search methods
|
@@ -198,28 +180,126 @@ module ActiveDocument
|
|
198
180
|
|
199
181
|
end
|
200
182
|
|
201
|
-
# Returns an ActiveXML object representing the requested information
|
183
|
+
# Returns an ActiveXML object representing the requested information. If no document exists at that uri then an
|
184
|
+
# empty domain object is created and returned
|
202
185
|
def load(uri)
|
203
186
|
self.new(@@ml_http.send_xquery(@@xquery_builder.load(uri)), uri)
|
204
187
|
end
|
205
188
|
|
206
189
|
# Finds all documents of this type that contain the word anywhere in their structure
|
207
|
-
def find_by_word(word, root=@root, namespace=@
|
190
|
+
def find_by_word(word, root=@root, namespace=@my_default_namespace)
|
208
191
|
SearchResults.new(@@ml_http.send_xquery(@@xquery_builder.find_by_word(word, root, namespace)))
|
209
192
|
end
|
210
193
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
194
|
+
|
195
|
+
end # end inner class
|
196
|
+
|
197
|
+
|
198
|
+
class PartialResult < self
|
199
|
+
# todo should this contain a reference to its parent?
|
200
|
+
def initialize(nodeset, parent)
|
201
|
+
@document = nodeset
|
202
|
+
@root = nodeset[0].name
|
203
|
+
@my_namespaces = parent.class.my_namespaces
|
204
|
+
@my_default_namespace = parent.class.my_default_namespace
|
205
|
+
end
|
206
|
+
|
207
|
+
# returns the number of Nodes in the underlying _NodeSet_
|
208
|
+
def length
|
209
|
+
@document.length
|
210
|
+
end
|
211
|
+
|
212
|
+
# provides access to the child nodes
|
213
|
+
def children
|
214
|
+
@document.children
|
215
|
+
end
|
216
|
+
|
217
|
+
# provides access to an indexed node
|
218
|
+
def [](index)
|
219
|
+
@document[index]
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
def namespace_for_element(element)
|
226
|
+
namespace = nil
|
227
|
+
ns = @my_namespaces || self.class.my_namespaces
|
228
|
+
default_ns = @my_default_namespace || self.class.my_default_namespace
|
229
|
+
if !ns.nil? && ns[element]
|
230
|
+
namespace = ns[element]
|
231
|
+
else
|
232
|
+
namespace = default_ns unless default_ns.nil?
|
233
|
+
end
|
234
|
+
namespace
|
235
|
+
end
|
236
|
+
|
237
|
+
def xpath_for_element(element)
|
238
|
+
xpath = String.new
|
239
|
+
xpath = "//" unless self.instance_of? PartialResult
|
240
|
+
namespace = namespace_for_element(element)
|
241
|
+
element = "ns:#{element}" unless namespace.nil? || namespace.empty?
|
242
|
+
xpath << element
|
243
|
+
return xpath, namespace
|
244
|
+
end
|
245
|
+
|
246
|
+
def evaluate_nodeset(result_nodeset)
|
247
|
+
if result_nodeset.length == 1 # found one match
|
248
|
+
if result_nodeset[0].children.length == 1 and result_nodeset[0].children[0].type == Nokogiri::XML::Node::TEXT_NODE
|
249
|
+
result_nodeset[0].text
|
250
|
+
#elsif result_nodeset[0].children.length >1 # we are now dealing with complex nodes
|
215
251
|
else
|
216
|
-
|
252
|
+
PartialResult.new(result_nodeset, self)
|
253
|
+
end
|
254
|
+
elsif result_nodeset.length >1 # multiple matches
|
255
|
+
if result_nodeset.all? { |node| node.children.length == 1 } and result_nodeset.all? { |node| node.children[0].type == Nokogiri::XML::Node::TEXT_NODE }
|
256
|
+
# we have multiple simple text nodes
|
257
|
+
result_nodeset.collect { |node| node.text }
|
258
|
+
else
|
259
|
+
# we have multiple complex elements
|
260
|
+
PartialResult.new(result_nodeset, self)
|
217
261
|
end
|
218
|
-
namespace
|
219
262
|
end
|
220
|
-
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def set_element(element, value)
|
266
|
+
# element.chop!
|
267
|
+
xpath, namespace = xpath_for_element(element)
|
268
|
+
if namespace.nil?
|
269
|
+
node = @document.xpath(xpath)
|
270
|
+
else
|
271
|
+
node = @document.xpath(xpath, {'ns' => namespace})
|
272
|
+
end
|
273
|
+
if node[0].child.type == Nokogiri::XML::Node::TEXT_NODE
|
274
|
+
node[0].child.content = value
|
275
|
+
else
|
276
|
+
raise ArgumentError, "You can't modify a complex node", caller
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def access_element(element)
|
281
|
+
xpath, namespace = xpath_for_element(element)
|
282
|
+
if namespace.nil?
|
283
|
+
nodes = @document.xpath(xpath)
|
284
|
+
else
|
285
|
+
nodes = @document.xpath(xpath, {'ns' => namespace})
|
286
|
+
end
|
287
|
+
evaluate_nodeset(nodes)
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
end
|
293
|
+
|
294
|
+
# end class
|
295
|
+
|
296
|
+
class ActiveDocumentException < Exception
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
class PersistenceException < ActiveDocumentException
|
221
301
|
|
222
|
-
end
|
302
|
+
end
|
223
303
|
|
224
304
|
|
225
305
|
end # end module
|
@@ -20,6 +20,21 @@ module ActiveDocument
|
|
20
20
|
"fn:doc('#{uri}')"
|
21
21
|
end
|
22
22
|
|
23
|
+
def delete(uri)
|
24
|
+
"xdmp:document-delete('#{uri}')"
|
25
|
+
end
|
26
|
+
|
27
|
+
def save(document, uri)
|
28
|
+
xquery = <<-GENERATED
|
29
|
+
xdmp:document-insert(
|
30
|
+
"#{uri}",
|
31
|
+
#{document.to_s},
|
32
|
+
xdmp:default-permissions(),
|
33
|
+
xdmp:default-collections())
|
34
|
+
GENERATED
|
35
|
+
|
36
|
+
end
|
37
|
+
|
23
38
|
# This method does a full text search
|
24
39
|
def find_by_word(word, root, namespace)
|
25
40
|
xquery = <<GENERATED
|
metadata
CHANGED
@@ -4,9 +4,8 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
|
9
|
-
version: 0.2.2
|
7
|
+
- 3
|
8
|
+
version: "0.3"
|
10
9
|
platform: ruby
|
11
10
|
authors:
|
12
11
|
- Clark D. Richey, Jr.
|
@@ -14,7 +13,7 @@ autorequire:
|
|
14
13
|
bindir: bin
|
15
14
|
cert_chain: []
|
16
15
|
|
17
|
-
date: 2010-
|
16
|
+
date: 2010-06-01 00:00:00 -04:00
|
18
17
|
default_executable:
|
19
18
|
dependencies:
|
20
19
|
- !ruby/object:Gem::Dependency
|