saxon-rb 0.4.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +62 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +3 -0
  5. data/.ruby-version +1 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +43 -0
  10. data/Rakefile +20 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/net/sf/saxon/Saxon-HE/9.9.1-5/Saxon-HE-9.9.1-5.jar +0 -0
  14. data/lib/saxon.rb +6 -0
  15. data/lib/saxon/axis_iterator.rb +31 -0
  16. data/lib/saxon/configuration.rb +116 -0
  17. data/lib/saxon/document_builder.rb +28 -0
  18. data/lib/saxon/item_type.rb +290 -0
  19. data/lib/saxon/item_type/lexical_string_conversion.rb +383 -0
  20. data/lib/saxon/item_type/value_to_ruby.rb +78 -0
  21. data/lib/saxon/jaxp.rb +8 -0
  22. data/lib/saxon/loader.rb +93 -0
  23. data/lib/saxon/occurrence_indicator.rb +33 -0
  24. data/lib/saxon/parse_options.rb +127 -0
  25. data/lib/saxon/processor.rb +102 -0
  26. data/lib/saxon/qname.rb +153 -0
  27. data/lib/saxon/s9api.rb +34 -0
  28. data/lib/saxon/serializer.rb +143 -0
  29. data/lib/saxon/source.rb +187 -0
  30. data/lib/saxon/version.rb +3 -0
  31. data/lib/saxon/xdm.rb +35 -0
  32. data/lib/saxon/xdm/array.rb +77 -0
  33. data/lib/saxon/xdm/atomic_value.rb +173 -0
  34. data/lib/saxon/xdm/empty_sequence.rb +37 -0
  35. data/lib/saxon/xdm/external_object.rb +21 -0
  36. data/lib/saxon/xdm/function_item.rb +21 -0
  37. data/lib/saxon/xdm/item.rb +32 -0
  38. data/lib/saxon/xdm/map.rb +77 -0
  39. data/lib/saxon/xdm/node.rb +71 -0
  40. data/lib/saxon/xdm/sequence_like.rb +30 -0
  41. data/lib/saxon/xdm/value.rb +145 -0
  42. data/lib/saxon/xpath.rb +8 -0
  43. data/lib/saxon/xpath/compiler.rb +69 -0
  44. data/lib/saxon/xpath/executable.rb +58 -0
  45. data/lib/saxon/xpath/static_context.rb +161 -0
  46. data/lib/saxon/xpath/variable_declaration.rb +68 -0
  47. data/lib/saxon/xslt.rb +8 -0
  48. data/lib/saxon/xslt/compiler.rb +70 -0
  49. data/lib/saxon/xslt/evaluation_context.rb +165 -0
  50. data/lib/saxon/xslt/executable.rb +156 -0
  51. data/lib/saxon_jars.rb +10 -0
  52. data/saxon-rb.gemspec +39 -0
  53. data/saxon.gemspec +30 -0
  54. metadata +240 -0
@@ -0,0 +1,3 @@
1
+ module Saxon
2
+ VERSION = "0.4.0"
3
+ end
data/lib/saxon/xdm.rb ADDED
@@ -0,0 +1,35 @@
1
+ require_relative 'xdm/node'
2
+ require_relative 'xdm/atomic_value'
3
+ require_relative 'xdm/array'
4
+ require_relative 'xdm/map'
5
+ require_relative 'xdm/function_item'
6
+ require_relative 'xdm/external_object'
7
+ require_relative 'xdm/value'
8
+ require_relative 'xdm/empty_sequence'
9
+ require_relative 'xdm/item'
10
+
11
+ module Saxon
12
+ module XDM
13
+ class << self
14
+ def AtomicValue(*args)
15
+ XDM::AtomicValue.create(*args)
16
+ end
17
+
18
+ def Value(*args)
19
+ XDM::Value.create(*args)
20
+ end
21
+
22
+ def EmptySequence()
23
+ XDM::EmptySequence.create
24
+ end
25
+
26
+ def Array(*args)
27
+ XDM::Array.create(*args)
28
+ end
29
+
30
+ def Map(*args)
31
+ XDM::Map.create(*args)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,77 @@
1
+ require_relative '../s9api'
2
+ require_relative 'sequence_like'
3
+
4
+ module Saxon
5
+ module XDM
6
+ # Represents an XDM Array
7
+ class Array
8
+ def self.create(array)
9
+ case array
10
+ when S9API::XdmArray
11
+ new(array)
12
+ else
13
+ new(S9API::XdmArray.new(array.map { |item|
14
+ XDM.Value(item).to_java
15
+ }))
16
+ end
17
+ end
18
+
19
+ include SequenceLike
20
+ include ItemSequenceLike
21
+ include Enumerable
22
+
23
+ attr_reader :s9_xdm_array
24
+ private :s9_xdm_array
25
+
26
+ # @api private
27
+ def initialize(s9_xdm_array)
28
+ @s9_xdm_array = s9_xdm_array
29
+ end
30
+
31
+ def each(&block)
32
+ cached_array.each(&block)
33
+ end
34
+
35
+ def [](i)
36
+ cached_array[i]
37
+ end
38
+
39
+ def length
40
+ s9_xdm_array.arrayLength
41
+ end
42
+
43
+ alias_method :size, :length
44
+
45
+ # compares two {XDM::AtomicValue}s using the underlying Saxon and XDM
46
+ # comparision rules
47
+ #
48
+ # @param other [Saxon::XDM::AtomicValue]
49
+ # @return [Boolean]
50
+ def ==(other)
51
+ return false unless other.is_a?(XDM::Array)
52
+ return false if length != other.length
53
+ cached_array == other.to_a
54
+ end
55
+
56
+ def to_a
57
+ cached_array
58
+ end
59
+
60
+ alias_method :eql?, :==
61
+
62
+ def hash
63
+ @hash ||= cached_array.hash
64
+ end
65
+
66
+ def to_java
67
+ s9_xdm_array
68
+ end
69
+
70
+ private
71
+
72
+ def cached_array
73
+ @cached_array ||= s9_xdm_array.asList.map { |s9_xdm_value| XDM.Value(s9_xdm_value) }.freeze
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,173 @@
1
+ require_relative 'sequence_like'
2
+ require_relative '../s9api'
3
+ require_relative '../qname'
4
+ require_relative '../item_type'
5
+
6
+ module Saxon
7
+ module XDM
8
+ # An XPath Data Model Node object, representing an XML document, or an element
9
+ # or one of the other node chunks in the XDM.
10
+ class AtomicValue
11
+ include XDM::SequenceLike
12
+ include XDM::ItemSequenceLike
13
+
14
+ # Error thrown when an attempt to create QName-holding XDM::AtomicValue is
15
+ # made using anything other than a {Saxon::QName} or s9api.QName instance.
16
+ #
17
+ # QNames are dependent on the namespace URI, which isn't present in the
18
+ # lexical string you normally see (e.g. <tt>prefix:name</tt>). Prefixes are
19
+ # only bound to a URI in the context of a particular document, so creating
20
+ # them imlpicitly through the XDM::AtomicValue creation process doesn't really
21
+ # work. They need to be created explicitly and then handed in to be wrapped.
22
+ class CannotCreateQNameFromString < StandardError
23
+ def to_s
24
+ "QName XDM::AtomicValues must be created using an instance of Saxon::QName, not a string like 'prefix:name': Prefix URI binding is undefined at this point"
25
+ end
26
+ end
27
+
28
+ # xs:NOTATION is another QName-holding XDM type. Unlike xs:QName, there
29
+ # isn't a way to create these outside of parsing an XML document within
30
+ # Saxon, so attempting to do so raises this error.
31
+ class NotationCannotBeDirectlyCreated < StandardError
32
+ def to_s
33
+ "xs:NOTATION XDM::AtomicValues cannot be directly created outside of XML parsing."
34
+ end
35
+ end
36
+
37
+ XS_QNAME = ItemType.get_type('xs:QName')
38
+ XS_NOTATION = ItemType.get_type('xs:NOTATION')
39
+
40
+ class << self
41
+ # Convert a single Ruby value into an XDM::AtomicValue
42
+ #
43
+ # If no explicit {ItemType} is passed, the correct type is guessed based
44
+ # on the class of the value. (e.g. <tt>xs:date</tt> for {Date}.)
45
+ #
46
+ # Values are converted based on Ruby idioms and operations, so an explicit
47
+ # {ItemType} of <tt>xs:boolean</tt> will use truthyness to evaluate the
48
+ # value. This means that the Ruby string <tt>'false'</tt> will produce an
49
+ # <tt>xs:boolean</tt> whose value is <tt>true</tt>, because all strings
50
+ # are truthy. If you need to pass lexical strings unchanged, use
51
+ # {XDM::AtomicValue.from_lexical_string}.
52
+ #
53
+ # @param value [Object] the value to convert
54
+ #
55
+ # @param item_type [Saxon::ItemType, String] the value's type, as either
56
+ # an {ItemType} or a name (<tt>xs:date</tt>)
57
+ #
58
+ # @return [Saxon::XDM::AtomicValue]
59
+ def create(value, item_type = nil)
60
+ case value
61
+ when Saxon::S9API::XdmAtomicValue
62
+ new(value)
63
+ when XDM::AtomicValue
64
+ value
65
+ else
66
+ return create_implying_item_type(value) if item_type.nil?
67
+
68
+ item_type = ItemType.get_type(item_type)
69
+
70
+ return new(Saxon::S9API::XdmAtomicValue.new(value.to_java)) if item_type == XS_QNAME && value_is_qname?(value)
71
+ raise NotationCannotBeDirectlyCreated if item_type == XS_NOTATION
72
+
73
+ value_lexical_string = item_type.lexical_string(value)
74
+ new(new_s9_xdm_atomic_value(value_lexical_string, item_type))
75
+ end
76
+ end
77
+
78
+ # convert a lexical string representation of an XDM Atomic Value into an
79
+ # XDM::AtomicValue.
80
+ #
81
+ # Note that this skips all conversion and checking of the string before
82
+ # handing it off to Saxon.
83
+ #
84
+ # @param value [String] the lexical string representation of the value
85
+ # @param item_type [Saxon::ItemType, String] the value's type, as either
86
+ # an {ItemType} or a name (<tt>xs:date</tt>)
87
+ # @return [Saxon::XDM::AtomicValue]
88
+ def from_lexical_string(value, item_type)
89
+ item_type = ItemType.get_type(item_type)
90
+ raise CannotCreateQNameFromString if item_type == XS_QNAME
91
+ new(new_s9_xdm_atomic_value(value.to_s, item_type))
92
+ end
93
+
94
+ private
95
+
96
+ def new_s9_xdm_atomic_value(value, item_type)
97
+ Saxon::S9API::XdmAtomicValue.new(value.to_java, item_type.to_java)
98
+ end
99
+
100
+ def create_implying_item_type(value)
101
+ return new(Saxon::S9API::XdmAtomicValue.new(value.to_java)) if value_is_qname?(value)
102
+
103
+ item_type = ItemType.get_type(value.class)
104
+
105
+ new(new_s9_xdm_atomic_value(item_type.lexical_string(value), item_type))
106
+ end
107
+
108
+ def value_is_qname?(value)
109
+ QName === value || S9API::QName === value
110
+ end
111
+ end
112
+
113
+ attr_reader :s9_xdm_atomic_value
114
+ private :s9_xdm_atomic_value
115
+
116
+ # @api private
117
+ def initialize(s9_xdm_atomic_value)
118
+ @s9_xdm_atomic_value = s9_xdm_atomic_value
119
+ end
120
+
121
+ # Return a {QName} representing the type of the value
122
+ #
123
+ # @return [Saxon::QName] the {QName} of the value's type
124
+ def type_name
125
+ @type_name ||= Saxon::QName.new(s9_xdm_atomic_value.getTypeName)
126
+ end
127
+
128
+ # @return [Saxon::S9API::XdmAtomicValue] The underlying Saxon Java XDM
129
+ # atomic value object.
130
+ def to_java
131
+ s9_xdm_atomic_value
132
+ end
133
+
134
+ # Return the value as a String. Like calling XPath's <tt>string()</tt>
135
+ # function.
136
+ #
137
+ # @return [String] The string representation of the value
138
+ def to_s
139
+ s9_xdm_atomic_value.toString
140
+ end
141
+
142
+ # @return [Saxon::ItemType] The ItemType of the value
143
+ def item_type
144
+ @item_type ||= Saxon::ItemType.get_type(Saxon::QName.resolve(s9_xdm_atomic_value.getTypeName))
145
+ end
146
+
147
+ # Return the value as an instance of the Ruby class that best represents the
148
+ # type of the value. Types with no sensible equivalent are returned as their
149
+ # lexical string form
150
+ #
151
+ # @return [Object] A Ruby object representation of the value
152
+ def to_ruby
153
+ @ruby_value ||= item_type.ruby_value(self).freeze
154
+ end
155
+
156
+ # compares two {XDM::AtomicValue}s using the underlying Saxon and XDM
157
+ # comparision rules
158
+ #
159
+ # @param other [Saxon::XDM::AtomicValue]
160
+ # @return [Boolean]
161
+ def ==(other)
162
+ return false unless other.is_a?(XDM::AtomicValue)
163
+ s9_xdm_atomic_value.equals(other.to_java)
164
+ end
165
+
166
+ alias_method :eql?, :==
167
+
168
+ def hash
169
+ @hash ||= s9_xdm_atomic_value.hashCode
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,37 @@
1
+ require_relative '../s9api'
2
+ require_relative 'sequence_like'
3
+
4
+ module Saxon
5
+ module XDM
6
+ # Represents the empty sequence in XDM
7
+ class EmptySequence
8
+ def self.create
9
+ @instance ||= new
10
+ end
11
+
12
+ include SequenceLike
13
+
14
+ def sequence_enum
15
+ [].to_enum
16
+ end
17
+
18
+ def sequence_size
19
+ 0
20
+ end
21
+
22
+ def ==(other)
23
+ other.class == self.class
24
+ end
25
+
26
+ alias_method :eql?, :==
27
+
28
+ def hash
29
+ [].hash
30
+ end
31
+
32
+ def to_java
33
+ @s9_xdm_empty_sequence ||= Saxon::S9API::XdmEmptySequence.getInstance
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../s9api'
2
+ require_relative 'sequence_like'
3
+
4
+ module Saxon
5
+ module XDM
6
+ # Represents a Saxon XDM ExternalObject
7
+ class ExternalObject
8
+ include SequenceLike
9
+ include ItemSequenceLike
10
+
11
+ # @api private
12
+ def initialize(s9_xdm_external_object)
13
+ @s9_xdm_external_object = s9_xdm_external_object
14
+ end
15
+
16
+ def to_java
17
+ @s9_xdm_external_object
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require_relative '../s9api'
2
+ require_relative 'sequence_like'
3
+
4
+ module Saxon
5
+ module XDM
6
+ # Represents an XDM Function Item
7
+ class FunctionItem
8
+ include SequenceLike
9
+ include ItemSequenceLike
10
+
11
+ # @api private
12
+ def initialize(s9_xdm_function_item)
13
+ @s9_xdm_function_item = s9_xdm_function_item
14
+ end
15
+
16
+ def to_java
17
+ @s9_xdm_function_item
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,32 @@
1
+ module Saxon
2
+ module XDM
3
+ def self.Item(item)
4
+ case item
5
+ when Value, AtomicValue, Node, Array, Map, ExternalObject
6
+ item
7
+ when Saxon::S9API::XdmNode
8
+ Node.new(item)
9
+ when Saxon::S9API::XdmAtomicValue
10
+ AtomicValue.new(item)
11
+ when Saxon::S9API::XdmExternalObject
12
+ ExternalObject.new(item)
13
+ when Saxon::S9API::XdmArray
14
+ Array.new(item)
15
+ when Saxon::S9API::XdmMap
16
+ Map.new(item)
17
+ when Saxon::S9API::XdmValue
18
+ Value.new(item)
19
+ when ::Array
20
+ Array.create(item)
21
+ when ::Hash
22
+ Map.create(item)
23
+ else
24
+ if item.respond_to?(:each)
25
+ Array.create(item)
26
+ else
27
+ AtomicValue.create(item)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,77 @@
1
+ require_relative '../s9api'
2
+ require_relative 'sequence_like'
3
+
4
+ module Saxon
5
+ module XDM
6
+ # Represents an XDM Map
7
+ class Map
8
+ def self.create(hash)
9
+ case hash
10
+ when Saxon::S9API::XdmMap
11
+ new(hash)
12
+ else
13
+ new(S9API::XdmMap.new(Hash[
14
+ hash.map { |key, value|
15
+ [XDM.AtomicValue(key).to_java, XDM.Value(value).to_java]
16
+ }
17
+ ]))
18
+ end
19
+ end
20
+
21
+ include SequenceLike
22
+ include ItemSequenceLike
23
+ include Enumerable
24
+
25
+ attr_reader :s9_xdm_map
26
+ private :s9_xdm_map
27
+
28
+ # @api private
29
+ def initialize(s9_xdm_map)
30
+ @s9_xdm_map = s9_xdm_map
31
+ end
32
+
33
+ def ==(other)
34
+ return false unless other.is_a?(self.class)
35
+ to_h == other.to_h
36
+ end
37
+
38
+ def [](key)
39
+ cached_hash[XDM.AtomicValue(key)]
40
+ end
41
+
42
+ def fetch(key, *args, &block)
43
+ cached_hash.fetch(XDM.AtomicValue(key), *args, &block)
44
+ end
45
+
46
+ def each(&block)
47
+ cached_hash.each(&block)
48
+ end
49
+
50
+ def select(&block)
51
+ self.class.create(each.select(&block).to_h)
52
+ end
53
+
54
+ def reject(&block)
55
+ self.class.create(each.reject(&block).to_h)
56
+ end
57
+
58
+ def merge(other)
59
+ self.class.create(to_h.merge(other.to_h))
60
+ end
61
+
62
+ def to_java
63
+ @s9_xdm_map
64
+ end
65
+
66
+ def to_h
67
+ cached_hash
68
+ end
69
+
70
+ private
71
+
72
+ def cached_hash
73
+ @cached_hash ||= s9_xdm_map.entrySet.map { |entry| [XDM.AtomicValue(entry.getKey), XDM.Value(entry.getValue)] }.to_h.freeze
74
+ end
75
+ end
76
+ end
77
+ end