jruby-existdb 0.4
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.
- data/conf.xml +812 -0
- data/lib/existdb.rb +74 -0
- data/lib/existdb/classwrap.rb +70 -0
- data/lib/existdb/collection.rb +98 -0
- data/lib/existdb/dom/active_record.rb +82 -0
- data/lib/existdb/dom/mapper.rb +285 -0
- data/lib/existdb/embedded.rb +84 -0
- data/lib/existdb/index_factory.rb +120 -0
- data/lib/existdb/meta.rb +41 -0
- data/lib/existdb/resource/base.rb +84 -0
- data/lib/existdb/resource/binary.rb +21 -0
- data/lib/existdb/resource/xml.rb +23 -0
- data/lib/existdb/resource_set.rb +34 -0
- data/lib/existdb/xql_factory.rb +191 -0
- data/lib/existdb/xquery_service.rb +11 -0
- data/lib/jars/antlr-2.7.7.jar +0 -0
- data/lib/jars/commons-collections-3.2.1.jar +0 -0
- data/lib/jars/commons-logging-1.1.1.jar +0 -0
- data/lib/jars/commons-pool-1.5.1.jar +0 -0
- data/lib/jars/endorsed/resolver-1.2.jar +0 -0
- data/lib/jars/endorsed/serializer-2.9.1.jar +0 -0
- data/lib/jars/endorsed/xalan-2.7.1.jar +0 -0
- data/lib/jars/endorsed/xercesImpl-2.9.1.jar +0 -0
- data/lib/jars/endorsed/xml-apis-1.3.04.jar +0 -0
- data/lib/jars/exist-lucene-module.jar +0 -0
- data/lib/jars/exist-modules.jar +0 -0
- data/lib/jars/exist.jar +0 -0
- data/lib/jars/extensions/exist-lucene-module.jar +0 -0
- data/lib/jars/extensions/exist-ngram-module.jar +0 -0
- data/lib/jars/extensions/exist-versioning.jar +0 -0
- data/lib/jars/extensions/lucene-core-2.4.1.jar +0 -0
- data/lib/jars/extensions/lucene-regex-2.4.1.jar +0 -0
- data/lib/jars/jgroups-all-2.2.6.jar +0 -0
- data/lib/jars/jta-1.1.jar +0 -0
- data/lib/jars/log4j-1.2.15.jar +0 -0
- data/lib/jars/lucene-core-2.4.1.jar +0 -0
- data/lib/jars/lucene-regex-2.4.1.jar +0 -0
- data/lib/jars/quartz-1.6.5.jar +0 -0
- data/lib/jars/sunxacml-1.2.jar +0 -0
- data/lib/jars/xmldb.jar +0 -0
- data/lib/jars/xmlrpc-client-3.1.2.jar +0 -0
- data/lib/jars/xmlrpc-common-3.1.2.jar +0 -0
- data/lib/jars/xmlrpc-server-3.1.2.jar +0 -0
- data/log4j.xml +190 -0
- metadata +104 -0
data/lib/existdb.rb
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'java'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'cgi' # For HTML Escaping
|
|
4
|
+
require 'find'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
require 'singleton'
|
|
7
|
+
require 'forwardable'
|
|
8
|
+
require 'date'
|
|
9
|
+
require 'time'
|
|
10
|
+
|
|
11
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
|
12
|
+
|
|
13
|
+
module ExistDB
|
|
14
|
+
class SystemProperties
|
|
15
|
+
class << self
|
|
16
|
+
def home_directory
|
|
17
|
+
defined?(EXIST_HOME) && EXIST_HOME || ENV['EXIST_HOME'] || '/var/spool/existdb'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def log_directory
|
|
21
|
+
defined?(EXIST_LOG) && EXIST_LOG || ENV['EXIST_LOG'] || '/var/log/existdb'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def data_directory
|
|
25
|
+
home_directory + '/data'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def init
|
|
29
|
+
java.lang.System.setProperty('exist.home', home_directory)
|
|
30
|
+
java.lang.System.setProperty('exist.logdir', log_directory)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def autocreate_config_files
|
|
34
|
+
# Copy the config files to the places where eXist will eXpect them.
|
|
35
|
+
# the log4j.xml file should be on your classpath to ensure proper logging
|
|
36
|
+
[ 'conf.xml', 'log4j.xml' ].each do |config_file|
|
|
37
|
+
src = "#{File.dirname(__FILE__)}/../#{config_file}"
|
|
38
|
+
dest = "#{home_directory}/#{config_file}"
|
|
39
|
+
FileUtils.copy(src, dest) if not File.exists?(dest)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def autocreate_data_directory
|
|
44
|
+
FileUtils.mkdir_p data_directory
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
init
|
|
49
|
+
autocreate_data_directory
|
|
50
|
+
autocreate_config_files
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Load eXistDB jars
|
|
55
|
+
Find.find( File.dirname(__FILE__) + '/jars' ) do |path|
|
|
56
|
+
next if File.extname(path) != '.jar'
|
|
57
|
+
require path
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
require 'existdb/classwrap.rb'
|
|
61
|
+
require 'existdb/collection.rb'
|
|
62
|
+
|
|
63
|
+
require 'existdb/resource/base.rb'
|
|
64
|
+
require 'existdb/resource/xml.rb'
|
|
65
|
+
require 'existdb/resource/binary.rb'
|
|
66
|
+
require 'existdb/resource_set.rb'
|
|
67
|
+
|
|
68
|
+
require 'existdb/xquery_service.rb'
|
|
69
|
+
require 'existdb/meta.rb'
|
|
70
|
+
require 'existdb/embedded.rb'
|
|
71
|
+
require 'existdb/xql_factory.rb'
|
|
72
|
+
require 'existdb/index_factory.rb'
|
|
73
|
+
require 'existdb/dom/mapper.rb'
|
|
74
|
+
require 'existdb/dom/active_record.rb'
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module ExistDB
|
|
2
|
+
|
|
3
|
+
class ClassUnwrap
|
|
4
|
+
class << self
|
|
5
|
+
def [](obj)
|
|
6
|
+
if obj.is_a?(Array) then
|
|
7
|
+
return obj.map{ |o| ClassUnwrap[o] }
|
|
8
|
+
else
|
|
9
|
+
obj.instance_variable_get(:@obj) || obj
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class ClassWrap
|
|
16
|
+
class << self
|
|
17
|
+
def [](java_obj)
|
|
18
|
+
return nil if java_obj.nil?
|
|
19
|
+
if java_obj.is_a?(Fixnum) or java_obj.is_a?(String) then
|
|
20
|
+
return java_obj
|
|
21
|
+
end
|
|
22
|
+
klass = map[java_obj.class]
|
|
23
|
+
if klass then
|
|
24
|
+
if klass.is_a?(Proc) then
|
|
25
|
+
return klass.call(java_obj)
|
|
26
|
+
else
|
|
27
|
+
return klass.new(java_obj)
|
|
28
|
+
end
|
|
29
|
+
else
|
|
30
|
+
raise "I don't know how to wrap [#{java_obj.class}]"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def map
|
|
35
|
+
{
|
|
36
|
+
Java::OrgExistXmldb::LocalCollection => Collection,
|
|
37
|
+
Java::OrgExistXmldb::LocalXPathQueryService => XQueryService,
|
|
38
|
+
Java::OrgExistXmldb::LocalResourceSet => ResourceSet,
|
|
39
|
+
Java::OrgExistXmldb::LocalXMLResource => Resource::Xml,
|
|
40
|
+
Java::OrgExistXmldb::LocalBinaryResource => Resource::Binary,
|
|
41
|
+
Java::OrgExistXmldb::FullXmldbURI => Proc.new { |obj| obj.toString },
|
|
42
|
+
Java::JavaUtil::Date => Proc.new { |obj| Time.parse( obj.to_s ) },
|
|
43
|
+
Java::OrgExistXquery::PathExpr => Proc.new { |obj| obj }
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
module ClassWrappingForwardable
|
|
50
|
+
def delegate_to_java(*opts)
|
|
51
|
+
opts.each do |opt|
|
|
52
|
+
if opt.is_a?(Hash) then
|
|
53
|
+
opt.each do |to, from|
|
|
54
|
+
module_eval "
|
|
55
|
+
def #{to}(*opts)
|
|
56
|
+
ClassWrap[ @obj.#{from}( *ClassUnwrap[ opts ] ) ]
|
|
57
|
+
end
|
|
58
|
+
"
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
module_eval "
|
|
62
|
+
def #{opt}(*opts)
|
|
63
|
+
ClassWrap[ @obj.#{opt}( *ClassUnwrap[ opts ] ) ]
|
|
64
|
+
end
|
|
65
|
+
"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
module ExistDB
|
|
2
|
+
class Collection
|
|
3
|
+
|
|
4
|
+
extend ClassWrappingForwardable
|
|
5
|
+
delegate_to_java :name, :path, :uri, :parent => :getParentCollection, :to_s => :name
|
|
6
|
+
|
|
7
|
+
def initialize(java_obj)
|
|
8
|
+
@obj = java_obj
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def collections
|
|
12
|
+
child_collection_names.map{|name|
|
|
13
|
+
collection(name)
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def collection(name)
|
|
18
|
+
Collection.new( @obj.getChildCollection(name) ) if child_collection_names.include?(name)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def resources
|
|
22
|
+
resource_names.map{ |name|
|
|
23
|
+
resource(name)
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def resource(name)
|
|
28
|
+
Resource.new( @obj.getResource(name) ) if resource_names.include?(name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Supports relative paths including slashes
|
|
32
|
+
# e.g. 'foo/bar/baz'
|
|
33
|
+
# Wish I could figure out how to do absolute paths from here...
|
|
34
|
+
def [](path)
|
|
35
|
+
(myconcern, remainder) = path.split('/', 2)
|
|
36
|
+
if myconcern.nil? or myconcern == '' then
|
|
37
|
+
return nil
|
|
38
|
+
elsif myconcern == '..' then
|
|
39
|
+
target = parent
|
|
40
|
+
else
|
|
41
|
+
target = collection(myconcern) || resource(myconcern)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if target.nil? then
|
|
45
|
+
return nil
|
|
46
|
+
elsif remainder then
|
|
47
|
+
return target[remainder]
|
|
48
|
+
else
|
|
49
|
+
return target
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def delete(resource = nil)
|
|
54
|
+
if resource.nil? then
|
|
55
|
+
collection_manager.removeCollection(@obj.uri)
|
|
56
|
+
else
|
|
57
|
+
@obj.removeResource( ClassUnwrap[ resource ] )
|
|
58
|
+
end
|
|
59
|
+
true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def xquery
|
|
63
|
+
ClassWrap[ @obj.getService('XQueryService', '1.0') ]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def create_collection(path)
|
|
67
|
+
if path =~ /^\// then
|
|
68
|
+
ClassWrap[ collection_manager.createCollection( path ) ]
|
|
69
|
+
else
|
|
70
|
+
ClassWrap[ collection_manager.createCollection( self.path + '/' + path ) ]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def store_url(url, name)
|
|
75
|
+
url = url.to_s.gsub(/&(?!amp;)/, '&')
|
|
76
|
+
xquery.query("xmldb:store( '#{self.uri}', '#{name}', doc(#{url.inspect}) )")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def inspect
|
|
80
|
+
"#<#{self.class}:0x#{self.hash.to_s(16)} name=#{self.name.inspect}>"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def child_collection_names
|
|
84
|
+
@obj.getChildCollections.collect
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def resource_names
|
|
88
|
+
@obj.getResources.collect
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def collection_manager
|
|
94
|
+
@obj.getService('CollectionManager','1.0')
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module ExistDB
|
|
2
|
+
module Dom
|
|
3
|
+
|
|
4
|
+
# Inspired by Rails ActiveRecord
|
|
5
|
+
# Because we cannot make assumptions about the structure of XML this must inspect the dom when descending into each node.
|
|
6
|
+
# For large well structured documents a mapper pattern where the structure is defined in the class would be more efficient.
|
|
7
|
+
|
|
8
|
+
class ActiveRecord
|
|
9
|
+
|
|
10
|
+
module NodeArray
|
|
11
|
+
def [](*opts)
|
|
12
|
+
raw = super
|
|
13
|
+
if raw.is_a?(Array) then
|
|
14
|
+
return raw.map{|obj| convert(obj) }
|
|
15
|
+
else
|
|
16
|
+
return convert(raw)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def each
|
|
21
|
+
super do |obj|
|
|
22
|
+
yield convert(obj)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module Convertible
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def convert(obj)
|
|
31
|
+
@cache ||= Hash.new
|
|
32
|
+
if @cache[obj] then
|
|
33
|
+
return @cache[obj]
|
|
34
|
+
else
|
|
35
|
+
if obj.getFirstChild.getNodeName == '' then
|
|
36
|
+
@cache[obj] = obj.getNodeValue
|
|
37
|
+
else
|
|
38
|
+
@cache[obj] = ActiveRecord.new(obj)
|
|
39
|
+
end
|
|
40
|
+
return @cache[obj]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
include org.w3c.dom.Node
|
|
47
|
+
include Convertible
|
|
48
|
+
|
|
49
|
+
def initialize(resource)
|
|
50
|
+
@dom = resource.respond_to?(:dom) ? resource.dom : resource
|
|
51
|
+
@children = Hash.new
|
|
52
|
+
@raw = Hash.new
|
|
53
|
+
@dom.getChildNodes.each do |child|
|
|
54
|
+
name = child.getNodeName.to_s.to_sym
|
|
55
|
+
next if respond_to?(name)
|
|
56
|
+
@raw[name] ||= Array.new
|
|
57
|
+
@raw[name] << child
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
@raw.each_key do |name|
|
|
61
|
+
if @raw[name].size > 1 then
|
|
62
|
+
@raw[name].extend(NodeArray, Convertible)
|
|
63
|
+
self.instance_eval %{
|
|
64
|
+
def #{name}
|
|
65
|
+
@raw[#{name.inspect}]
|
|
66
|
+
end
|
|
67
|
+
}
|
|
68
|
+
else
|
|
69
|
+
@raw[name] = @raw[name].first
|
|
70
|
+
self.instance_eval %{
|
|
71
|
+
def #{name}
|
|
72
|
+
convert( @raw[#{name.inspect}] )
|
|
73
|
+
end
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
|
|
2
|
+
module ExistDB
|
|
3
|
+
module Dom
|
|
4
|
+
|
|
5
|
+
# Inspired by HappyMapper
|
|
6
|
+
|
|
7
|
+
module Mapper
|
|
8
|
+
def self.included(base)
|
|
9
|
+
base.instance_variable_set("@attributes", Hash.new)
|
|
10
|
+
base.instance_variable_set("@elements", Hash.new)
|
|
11
|
+
base.extend ClassMethods
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(resource)
|
|
15
|
+
@dom = resource.respond_to?(:dom) ? resource.dom : resource
|
|
16
|
+
@cache = Hash.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def get_element(tag_name)
|
|
22
|
+
@cache[tag_name] ||= self.class.get_element(tag_name, @dom)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def get_elements(tag_name, klass)
|
|
26
|
+
@cache[tag_name] ||= self.class.get_elements(tag_name, klass, @dom)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def get_attribute(tag_name)
|
|
30
|
+
@cache[tag_name] ||= self.class.get_attribute(tag_name, @dom)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def set_element(tag_name, value)
|
|
34
|
+
@cache.delete(tag_name)
|
|
35
|
+
self.class.set_element(@dom, tag_name, value)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def set_attribute(tag_name, value)
|
|
39
|
+
@cache.delete(tag_name)
|
|
40
|
+
self.class.set_attribute(@dom, tag_name, value)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
module ClassMethods
|
|
44
|
+
|
|
45
|
+
def attribute(name, type = String, options = {})
|
|
46
|
+
a = Attribute.new(name, type, options)
|
|
47
|
+
@attributes ||= Hash.new
|
|
48
|
+
@attributes[a.tag] = a
|
|
49
|
+
self.class_eval %{
|
|
50
|
+
def #{a.method_name}
|
|
51
|
+
get_attribute(#{a.tag.inspect})
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def #{a.method_name}=(value)
|
|
55
|
+
set_attribute(#{a.tag.inspect}, value)
|
|
56
|
+
end
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def attributes
|
|
61
|
+
@attributes.values
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def element(name, type = String, options = {}, &block)
|
|
65
|
+
e = Element.new(name, type, options)
|
|
66
|
+
@elements ||= Hash.new
|
|
67
|
+
@elements[e.tag] = e
|
|
68
|
+
|
|
69
|
+
if (type.respond_to?(:is_dom_mapper?) and type.is_dom_mapper?) or block_given? then # Nested elements
|
|
70
|
+
if block_given? then # Anonymous Mapper Class
|
|
71
|
+
klass = self.class_eval %{
|
|
72
|
+
@@#{e.method_name}_klass = Class.new do
|
|
73
|
+
include ExistDB::Dom::Mapper
|
|
74
|
+
end
|
|
75
|
+
}
|
|
76
|
+
klass.instance_eval &block
|
|
77
|
+
else
|
|
78
|
+
self.class_eval %{
|
|
79
|
+
@@#{e.method_name}_klass = #{type}
|
|
80
|
+
}
|
|
81
|
+
end
|
|
82
|
+
self.class_eval %{
|
|
83
|
+
def #{e.method_name}
|
|
84
|
+
get_elements(#{e.tag.inspect}, @@#{e.method_name}_klass)
|
|
85
|
+
end
|
|
86
|
+
}
|
|
87
|
+
else # No nested elements
|
|
88
|
+
self.class_eval %{
|
|
89
|
+
def #{e.method_name}
|
|
90
|
+
get_element(#{e.tag.inspect})
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def #{e.method_name}=(value)
|
|
94
|
+
set_element(#{e.tag.inspect}, value)
|
|
95
|
+
end
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def elements
|
|
101
|
+
@elements.values
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def get_element(tag_name, dom)
|
|
105
|
+
e = @elements[tag_name]
|
|
106
|
+
child = getFirstChildByTagName(dom, tag_name)
|
|
107
|
+
return e.type_cast( child.getNodeValue ) if child.respond_to?(:getNodeValue)
|
|
108
|
+
return nil
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def get_elements(tag_name, klass, dom)
|
|
112
|
+
children = dom.getElementsByTagName(tag_name)
|
|
113
|
+
size = children.getLength
|
|
114
|
+
if size == 1 then
|
|
115
|
+
klass.new(children.item(0))
|
|
116
|
+
elsif size > 1 then
|
|
117
|
+
0..size.map{ |i| klass.new(children.item(i)) }
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def get_attribute(tag_name, dom)
|
|
122
|
+
a = @attributes[tag_name]
|
|
123
|
+
value = dom.getAttributes.getNamedItem(tag_name).getValue rescue nil
|
|
124
|
+
a.type_cast( value )
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def set_element(dom, tag_name, value)
|
|
128
|
+
parent = dom
|
|
129
|
+
node = getFirstChildByTagName(dom, tag_name)
|
|
130
|
+
|
|
131
|
+
if node.nil? then
|
|
132
|
+
doc = parent.getOwnerDocument
|
|
133
|
+
node = doc.createElement( tag_name.to_s )
|
|
134
|
+
parent.appendChild(node)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
child = node.getChildNodes.select{ |child|
|
|
138
|
+
child.getNodeType == org.w3c.dom.Node.TEXT_NODE }.first
|
|
139
|
+
text = org.exist.dom.TextImpl.new( value.to_s.to_java_string )
|
|
140
|
+
if child then
|
|
141
|
+
ExistDB::Embedded.instance.transaction do |transaction|
|
|
142
|
+
text.setOwnerDocument( node.getOwnerDocument )
|
|
143
|
+
node.updateChild(transaction, child, text)
|
|
144
|
+
end
|
|
145
|
+
else
|
|
146
|
+
node.appendChild(text)
|
|
147
|
+
end
|
|
148
|
+
return value
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def set_attribute(dom, tag_name, value)
|
|
152
|
+
attr = dom.getAttributes.getNamedItem(tag_name)
|
|
153
|
+
new_attr = org.exist.dom.AttrImpl.new(
|
|
154
|
+
org.exist.dom.QName.new( tag_name.to_s.to_java_string ),
|
|
155
|
+
value.to_s.to_java_string )
|
|
156
|
+
ExistDB::Embedded.instance.transaction do |transaction|
|
|
157
|
+
if attr then
|
|
158
|
+
new_attr.setOwnerDocument( dom.getOwnerDocument )
|
|
159
|
+
dom.updateChild(transaction, attr, new_attr)
|
|
160
|
+
else
|
|
161
|
+
dom.appendChild(new_attr)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
return value
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def tag(new_tag_name)
|
|
168
|
+
@tag_name = new_tag_name.to_s unless new_tag_name.nil? || new_tag_name.to_s.empty?
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def tag_name
|
|
172
|
+
@tag_name ||= to_s.split('::').last.downcase
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def parse(resource, options = {})
|
|
176
|
+
|
|
177
|
+
if options[:single] then
|
|
178
|
+
return new(resource)
|
|
179
|
+
else
|
|
180
|
+
xpath = options[:xpath]
|
|
181
|
+
xpath ||= "//#{options[:tag]}" if options[:tag]
|
|
182
|
+
xpath ||= "//#{options[:name]}" if options[:name]
|
|
183
|
+
xpath ||= "//#{tag_name}"
|
|
184
|
+
|
|
185
|
+
resource_set = resource.xquery(xpath)
|
|
186
|
+
return resource_set.map{ |res| new(res) }
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def find(*options)
|
|
192
|
+
xql = XQLFactory::XQLFactory.new(*options)
|
|
193
|
+
|
|
194
|
+
if xql.node_xpath.nil? then
|
|
195
|
+
xql.node_xpath = "//#{tag_name}"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
if xql.doc.is_a?(Resource::Xml) then
|
|
199
|
+
xql.doc.xquery(xql.xquery).map{ |res| new(res) }
|
|
200
|
+
elsif xql.doc.is_a?(ResourceSet) then
|
|
201
|
+
xql.doc.join.xquery(xql.xquery).map{ |res| new(res) }
|
|
202
|
+
elsif xql.doc.is_a?(String) and Embedded.instance.running?
|
|
203
|
+
Embedded.instance.xquery_service.query(xql.xquery).map{ |res| new(res) }
|
|
204
|
+
else
|
|
205
|
+
nil
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def find_by_xquery(resource, query)
|
|
210
|
+
nodes = resource.xquery(query)
|
|
211
|
+
nodes.map{ |node| new(node) }
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def is_dom_mapper?
|
|
215
|
+
true
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
private
|
|
219
|
+
|
|
220
|
+
def getFirstChildByTagName(dom, tag_name)
|
|
221
|
+
dom.getChildNodes.each do |child|
|
|
222
|
+
next if not child.respond_to?(:getTagName) or child.getTagName != tag_name
|
|
223
|
+
return child
|
|
224
|
+
break
|
|
225
|
+
end
|
|
226
|
+
return nil
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
class Boolean; end
|
|
232
|
+
|
|
233
|
+
class Item
|
|
234
|
+
attr_accessor :name, :type, :tag, :options, :method_name
|
|
235
|
+
def initialize(name, type, o={})
|
|
236
|
+
self.name = name.to_s
|
|
237
|
+
self.method_name = self.name.tr('-','_')
|
|
238
|
+
self.type = type
|
|
239
|
+
self.tag = o[:tag] || name.to_s
|
|
240
|
+
self.options = { :single => true }.merge(o.merge(:name => self.name))
|
|
241
|
+
|
|
242
|
+
@xml_type = self.class.to_s.split('::').last.downcase
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def type_cast(value, type = self.type)
|
|
246
|
+
begin
|
|
247
|
+
if type == String then value.to_s
|
|
248
|
+
elsif type == Float then value.to_f
|
|
249
|
+
elsif type == Time then
|
|
250
|
+
Time.parse(value.to_s) rescue Time.at(value.to_i)
|
|
251
|
+
elsif type == Date then Date.parse(value.to_s)
|
|
252
|
+
elsif type == DateTime then DateTime.parse(value.to_s)
|
|
253
|
+
elsif type == Boolean then
|
|
254
|
+
['true','t','1','y','yes'].include?(value.to_s.downcase)
|
|
255
|
+
elsif type == Integer then
|
|
256
|
+
# ganked from datamapper, and happymapper
|
|
257
|
+
value_to_i = value.to_i
|
|
258
|
+
if value_to_i == 0 && value != '0'
|
|
259
|
+
value_to_s = value.to_s
|
|
260
|
+
begin
|
|
261
|
+
Integer(value_to_s =~ /^(\d+)/ ? $1 : value_to_s)
|
|
262
|
+
rescue ArgumentError
|
|
263
|
+
nil
|
|
264
|
+
end
|
|
265
|
+
else
|
|
266
|
+
value_to_i
|
|
267
|
+
end
|
|
268
|
+
else
|
|
269
|
+
value
|
|
270
|
+
end
|
|
271
|
+
rescue
|
|
272
|
+
value
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
class Element < Item; end
|
|
279
|
+
|
|
280
|
+
class Attribute < Item; end
|
|
281
|
+
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
end
|
|
285
|
+
end
|