transformator 0.1.4 → 1.0.0.pre1
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.
- checksums.yaml +4 -4
- data/Gemfile +7 -2
- data/Rakefile +0 -43
- data/bin/transformator +4 -0
- data/lib/transformator.rb +13 -29
- data/lib/transformator/cli.rb +42 -0
- data/lib/transformator/dispatcher.rb +43 -0
- data/lib/transformator/filesystem_pattern_evaluator.rb +14 -0
- data/lib/transformator/gzip_reader.rb +0 -0
- data/lib/transformator/gzip_writer.rb +0 -0
- data/lib/transformator/null_processor.rb +9 -0
- data/lib/transformator/oga_xml_dumper.rb +10 -0
- data/lib/transformator/oga_xml_parser.rb +10 -0
- data/lib/transformator/ox_xml_dumper.rb +10 -0
- data/lib/transformator/ox_xml_parser.rb +10 -0
- data/lib/transformator/parallel_processor.rb +39 -0
- data/lib/transformator/processor.rb +4 -0
- data/lib/transformator/tar_reader.rb +51 -0
- data/lib/transformator/tar_reader/patched_rubygems_tar_reader.rb +41 -0
- data/lib/transformator/tar_writer.rb +0 -0
- data/lib/transformator/version.rb +1 -1
- data/spec/spec_helper.rb +0 -1
- data/spec/transformator_spec.rb +0 -8
- data/transformator.gemspec +7 -6
- data/ubpb.yml.erb +25 -0
- metadata +49 -67
- data/assets/primo_search_response.xml +0 -2878
- data/assets/primo_search_response_1.xml +0 -2467
- data/examples/primo_search_response_transformation.rb +0 -123
- data/examples/search_request_transformation.rb +0 -89
- data/lib/transformator/dsl.rb +0 -93
- data/lib/transformator/format_converter.rb +0 -27
- data/lib/transformator/format_converter/document_from_hash.rb +0 -13
- data/lib/transformator/format_converter/document_from_object.rb +0 -20
- data/lib/transformator/format_converter/document_from_xml.rb +0 -28
- data/lib/transformator/format_converter/hash_from_document.rb +0 -61
- data/lib/transformator/format_converter/xml_from_document.rb +0 -7
- data/lib/transformator/transformation.rb +0 -91
- data/spec/examples/primo_search_response_transformation_spec.rb +0 -19
- data/spec/examples/search_request_transformation_spec.rb +0 -48
- data/spec/transformator/dsl_spec.rb +0 -187
- data/spec/transformator/format_converter/hash_from_document_spec.rb +0 -42
- data/spec/transformator/transformation_spec.rb +0 -112
@@ -1,91 +0,0 @@
|
|
1
|
-
require "ox"
|
2
|
-
require "transformator/dsl"
|
3
|
-
|
4
|
-
class Transformator::Transformation
|
5
|
-
def initialize(options = {}, &block)
|
6
|
-
# make it possible to initialize a transformation with external data
|
7
|
-
options.each_pair do |key, value|
|
8
|
-
instance_variable_set "@#{key}".to_sym, value
|
9
|
-
end
|
10
|
-
|
11
|
-
@rules = []
|
12
|
-
self.instance_eval(&block) if block
|
13
|
-
end
|
14
|
-
|
15
|
-
#
|
16
|
-
public
|
17
|
-
#
|
18
|
-
def apply(options = {})
|
19
|
-
source = Transformator.document_from_object(options[:source] ||= options[:to])
|
20
|
-
target = Transformator.document_from_object(options[:target])
|
21
|
-
|
22
|
-
@rules.each do |rule|
|
23
|
-
block = rule[:callable]
|
24
|
-
path = rule[:path]
|
25
|
-
type = rule[:type]
|
26
|
-
|
27
|
-
# allow user to set source/target freely
|
28
|
-
_source =
|
29
|
-
if (source_callable = rule[:source]).respond_to?(:call)
|
30
|
-
source_callable.call
|
31
|
-
else
|
32
|
-
source
|
33
|
-
end
|
34
|
-
|
35
|
-
_target =
|
36
|
-
if (target_callable = rule[:target]).respond_to?(:call)
|
37
|
-
target_callable.call
|
38
|
-
else
|
39
|
-
target
|
40
|
-
end
|
41
|
-
|
42
|
-
if type == :process
|
43
|
-
if path.is_a?(Array)
|
44
|
-
block.call(
|
45
|
-
path.map do |_path| { _path => find_all(_source, _path) } end,
|
46
|
-
_target
|
47
|
-
)
|
48
|
-
elsif path.is_a?(String)
|
49
|
-
find_all(_source, path).each do |element_to_process|
|
50
|
-
block.call(element_to_process, _target)
|
51
|
-
end
|
52
|
-
elsif path.is_a?(Symbol)
|
53
|
-
if path == :document
|
54
|
-
block.call(_source, _target)
|
55
|
-
elsif path == :none
|
56
|
-
block.call
|
57
|
-
elsif path == :source
|
58
|
-
block.call(source, _target)
|
59
|
-
elsif path == :target
|
60
|
-
block.call(target, _target)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
case options[:output_format] || @output_format || Transformator.determine_format(options[:source])
|
67
|
-
when :hash then Transformator.hash_from_document(target)
|
68
|
-
when :ox_document then target
|
69
|
-
when :xml then Ox.dump(target, with_xml: true)
|
70
|
-
else raise "Unknown output format!"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
#
|
75
|
-
private
|
76
|
-
#
|
77
|
-
include Transformator::Dsl
|
78
|
-
|
79
|
-
def before_apply(options = {}, &block)
|
80
|
-
@rules.unshift({ callable: block, path: :none, type: :process}.merge(options))
|
81
|
-
end
|
82
|
-
|
83
|
-
def output_format(format)
|
84
|
-
@output_format = format.to_sym
|
85
|
-
end
|
86
|
-
|
87
|
-
def process(path, options = {}, &block)
|
88
|
-
@rules.push({ callable: block, path: path, type: :process}.merge(options))
|
89
|
-
self
|
90
|
-
end
|
91
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require_relative "../../examples/primo_search_response_transformation"
|
2
|
-
|
3
|
-
describe "Examples" do
|
4
|
-
let(:primo_search_response) do
|
5
|
-
File.read(
|
6
|
-
File.expand_path(
|
7
|
-
File.join(
|
8
|
-
File.dirname(__FILE__), "../../assets/primo_search_response_1.xml"
|
9
|
-
)
|
10
|
-
)
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "transforms primo search response" do
|
15
|
-
Transformator::Examples::PrimoSearchResponseTransformation.apply(to: primo_search_response, output_format: :hash).tap do |w|
|
16
|
-
# binding.pry
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
require_relative "../../examples/search_request_transformation"
|
2
|
-
|
3
|
-
describe "Examples" do
|
4
|
-
let(:search_request_hash) do
|
5
|
-
{
|
6
|
-
from: 0,
|
7
|
-
size: 20,
|
8
|
-
query: {
|
9
|
-
bool: {
|
10
|
-
must: [
|
11
|
-
{
|
12
|
-
query_string: {
|
13
|
-
query: "linux",
|
14
|
-
default_operator: "AND",
|
15
|
-
fields: [
|
16
|
-
"title^2",
|
17
|
-
"_all"
|
18
|
-
]
|
19
|
-
}
|
20
|
-
},
|
21
|
-
{
|
22
|
-
query_string: {
|
23
|
-
query: "kofler",
|
24
|
-
default_operator: "AND",
|
25
|
-
fields: [
|
26
|
-
"creator"
|
27
|
-
]
|
28
|
-
}
|
29
|
-
},
|
30
|
-
{
|
31
|
-
range: {
|
32
|
-
lsr09: {
|
33
|
-
gte: 20140101
|
34
|
-
}
|
35
|
-
}
|
36
|
-
}
|
37
|
-
]
|
38
|
-
}
|
39
|
-
},
|
40
|
-
}
|
41
|
-
end
|
42
|
-
|
43
|
-
it "transforms search request to primo soap body" do
|
44
|
-
Transformator::Examples::SearchRequestTransformation.apply(to: search_request_hash, output_format: :xml).tap do |w|
|
45
|
-
# binding.pry
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,187 +0,0 @@
|
|
1
|
-
describe Transformator::Dsl do
|
2
|
-
let(:dsl) do
|
3
|
-
Module.new.extend(described_class)
|
4
|
-
end
|
5
|
-
|
6
|
-
#
|
7
|
-
# array
|
8
|
-
#
|
9
|
-
describe "#array" do
|
10
|
-
it "creates a new element with attribute \"type\" == \"array\"" do
|
11
|
-
expect(dsl.array(:foo)["type"]).to eq("array")
|
12
|
-
end
|
13
|
-
|
14
|
-
context "when called with a block" do
|
15
|
-
describe "passes an array accumulator to the block" do
|
16
|
-
it "allows appending elements to the array so that it's activesupport Hash.from_xml compatble" do
|
17
|
-
array_with_one_element = dsl.array(:foo) do |arr|
|
18
|
-
arr << dsl.element(:bar)
|
19
|
-
end
|
20
|
-
|
21
|
-
expect(dsl.find(array_with_one_element, "foo/bar")).not_to be_nil
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
#
|
28
|
-
# element
|
29
|
-
#
|
30
|
-
describe "#element" do
|
31
|
-
it "creates a new element with the given name" do
|
32
|
-
expect(dsl.element(:foo).value).to eq("foo")
|
33
|
-
end
|
34
|
-
|
35
|
-
context "when called with an \"attributes\" option" do
|
36
|
-
it "sets the attributes of the newly created element accordingly" do
|
37
|
-
attributes = { attr1: 1, attr2: "2", "attr3" => true }
|
38
|
-
expect(dsl.element(:foo, attributes: attributes).attributes).to eq({
|
39
|
-
"attr1" => "1",
|
40
|
-
"attr2" => "2",
|
41
|
-
"attr3" => "true"
|
42
|
-
})
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context "when called with a \"text\" option" do
|
47
|
-
it "adds a text node to the newly created element" do
|
48
|
-
expect(dsl.element(:foo, text: "bar").text).to eq("bar")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "when called with a \"type\" option" do
|
53
|
-
it "adds an attribute named \"type\" with the given value" do
|
54
|
-
expect(dsl.element(:foo, text: 1, type: :integer).attributes).to include({"type" => "integer"})
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
#
|
60
|
-
# elements_from_hash
|
61
|
-
#
|
62
|
-
describe "#elements_from_hash" do
|
63
|
-
let(:hash) do
|
64
|
-
{
|
65
|
-
key1: "value1",
|
66
|
-
key2: [
|
67
|
-
{
|
68
|
-
subkey: "subvalue"
|
69
|
-
}
|
70
|
-
]
|
71
|
-
}
|
72
|
-
end
|
73
|
-
|
74
|
-
it "creates elements from the given hash" do
|
75
|
-
elements = dsl.elements_from_hash(hash)
|
76
|
-
expect(elements[0].value).to eq("key1")
|
77
|
-
expect(dsl.find(elements[1], "key2/subkey").text).to eq("subvalue") # key2 ist found due to the additional array element encoding
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
#
|
82
|
-
# elements_from_xml
|
83
|
-
#
|
84
|
-
describe "#elements_from_xml" do
|
85
|
-
let(:xml) do
|
86
|
-
<<-xml.strip_heredoc
|
87
|
-
<key1>value1</key1>
|
88
|
-
<key2>
|
89
|
-
<subkey>subvalue</subkey>
|
90
|
-
</key2>
|
91
|
-
xml
|
92
|
-
end
|
93
|
-
|
94
|
-
it "creates elements from the given xml string" do
|
95
|
-
elements = dsl.elements_from_xml(xml)
|
96
|
-
expect(elements[0].value).to eq("key1")
|
97
|
-
expect(dsl.find(elements[1], "subkey").text).to eq("subvalue")
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
#
|
102
|
-
# find
|
103
|
-
#
|
104
|
-
describe "#find" do
|
105
|
-
let(:node) do
|
106
|
-
dsl.element(:root) do |root|
|
107
|
-
root << dsl.element(:foo, text: "1")
|
108
|
-
root << dsl.element(:foo, text: "2")
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
describe "is a shortcut for find_all(..)[0]" do
|
113
|
-
context "when there are elements matching the given path" do
|
114
|
-
it "returns the first element found" do
|
115
|
-
expect(dsl.find(node, "foo").text).to eq("1")
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
context "when there are no elements matching the given path" do
|
120
|
-
it "returns nil" do
|
121
|
-
expect(dsl.find(node, "nope")).to be_nil
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
#
|
128
|
-
# find_all
|
129
|
-
#
|
130
|
-
describe "#find_all" do
|
131
|
-
let(:node) do
|
132
|
-
dsl.element(:root) do |root|
|
133
|
-
root << dsl.element(:foo, text: "1")
|
134
|
-
root << dsl.element(:foo, text: "2")
|
135
|
-
root << dsl.element(:bar) do |bar|
|
136
|
-
bar << dsl.element(:muff) do |muff|
|
137
|
-
muff << dsl.element(:key, text: "value")
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
it "understands xpath like path expressions" do
|
144
|
-
expect(dsl.find_all(node, "//key")).not_to be_nil
|
145
|
-
end
|
146
|
-
|
147
|
-
describe "finds all elements by the given path" do
|
148
|
-
context "when there are elements matching the given path" do
|
149
|
-
it "returns all elements found" do
|
150
|
-
expect(dsl.find_all(node, "foo").map(&:text)).to eq(["1", "2"])
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
context "when there are no elements matching the given path" do
|
155
|
-
it "returns an empty array" do
|
156
|
-
expect(dsl.find_all(node, "nope")).to eq([])
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
context "when called with a block" do
|
162
|
-
context "when there are elements matching the given path" do
|
163
|
-
it "calls the block with resulting array" do
|
164
|
-
variable_changed_inside_block = false
|
165
|
-
|
166
|
-
dsl.find_all(node, "foo") do |result|
|
167
|
-
variable_changed_inside_block = true if result.length == 2
|
168
|
-
end
|
169
|
-
|
170
|
-
expect(variable_changed_inside_block).to be(true)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
context "when there are no elements matching the given path" do
|
175
|
-
it "the block is not called" do
|
176
|
-
variable_changed_inside_block = false
|
177
|
-
|
178
|
-
dsl.find_all(node, "nope") do |foo|
|
179
|
-
variable_changed_inside_block = true
|
180
|
-
end
|
181
|
-
|
182
|
-
expect(variable_changed_inside_block).to be(false)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
describe Transformator::FormatConverter::HashFromDocument do
|
2
|
-
let(:transformator) do
|
3
|
-
Module.new.tap do |mod|
|
4
|
-
mod.extend Transformator::FormatConverter::HashFromDocument
|
5
|
-
mod.extend Transformator::FormatConverter::DocumentFromHash
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
let(:hash) do
|
10
|
-
{
|
11
|
-
"key1" => "value1",
|
12
|
-
"key2" => 1,
|
13
|
-
"key3" => 1.5,
|
14
|
-
"key4" => true,
|
15
|
-
"key5" => nil,
|
16
|
-
"key6" => {
|
17
|
-
"key6_1" => "value6_1"
|
18
|
-
},
|
19
|
-
"key7" => [
|
20
|
-
"1",
|
21
|
-
2,
|
22
|
-
true,
|
23
|
-
{
|
24
|
-
"key_arr_obj1" => [
|
25
|
-
"nested_element1",
|
26
|
-
{
|
27
|
-
"nested_key" => "nested_value"
|
28
|
-
}
|
29
|
-
]
|
30
|
-
}
|
31
|
-
]
|
32
|
-
}
|
33
|
-
end
|
34
|
-
|
35
|
-
let(:document) do
|
36
|
-
transformator.document_from_hash(hash)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "converts a document to its corresponding hash" do
|
40
|
-
expect(transformator.hash_from_document(document)).to eq(hash)
|
41
|
-
end
|
42
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
describe Transformator::Transformation do
|
2
|
-
let(:source_xml) do
|
3
|
-
<<-xml.strip_heredoc
|
4
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
5
|
-
<foo>
|
6
|
-
<bar>muff</bar>
|
7
|
-
</foo>
|
8
|
-
xml
|
9
|
-
end
|
10
|
-
|
11
|
-
let(:transformed_xml) do
|
12
|
-
<<-xml.strip_heredoc
|
13
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
14
|
-
<muff>muff</muff>
|
15
|
-
xml
|
16
|
-
end
|
17
|
-
|
18
|
-
describe ".new" do
|
19
|
-
context "when called with an options hash" do
|
20
|
-
let(:transformed_xml) do
|
21
|
-
<<-xml.strip_heredoc
|
22
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
23
|
-
<muff>value1</muff>
|
24
|
-
xml
|
25
|
-
end
|
26
|
-
|
27
|
-
it "provides each key as an instance variable inside the transformation" do
|
28
|
-
transformation = described_class.new(option1: "value1") do
|
29
|
-
process "foo/bar" do |element, target|
|
30
|
-
target << element("muff", text: @option1)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
expect(transformation.apply(to: source_xml)).to eq(transformed_xml)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
it "can be called with a block, containing the mapping described by the dsl" do
|
39
|
-
transformation = described_class.new do
|
40
|
-
process "foo/bar" do |element, target|
|
41
|
-
target << element("muff", nodes: element.nodes)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
expect(transformation.apply(to: source_xml)).to eq(transformed_xml)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe "#before_apply" do
|
50
|
-
let(:transformation) do
|
51
|
-
described_class.new(data: "some_data") do
|
52
|
-
process :target do |target|
|
53
|
-
target << element("data", text: @foo)
|
54
|
-
end
|
55
|
-
|
56
|
-
# usually rules are executed in order as the are defined, but this one comes first
|
57
|
-
before_apply do
|
58
|
-
@foo = @data
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
it "executes the given block before applying the transformation" do
|
64
|
-
transformed_document = transformation.apply(to: nil, output_format: :ox_document)
|
65
|
-
expect(transformed_document.locate("data").first.text).to eq("some_data")
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "#output_format" do
|
70
|
-
let(:transformation) do
|
71
|
-
described_class.new do
|
72
|
-
output_format :xml
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
it "sets the default output format for the transformation" do
|
77
|
-
expect(transformation.apply(to: {})).to start_with("<?xml")
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
describe "#process" do
|
82
|
-
context "when source responds to call" do
|
83
|
-
let(:transformation) do
|
84
|
-
described_class.new do
|
85
|
-
process :none do
|
86
|
-
@foo = element("foo") << element("bar", text: "muff")
|
87
|
-
end
|
88
|
-
|
89
|
-
process "*", source: -> { @foo } do |element, target|
|
90
|
-
target << element
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
it "executes the rule with the callable result as the source" do
|
96
|
-
expect(transformation.apply(to: nil, output_format: :ox_document).locate("bar").first.text).to eq("muff")
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
context "when called with the special path :document" do
|
101
|
-
it "provides the whole input document to the block" do
|
102
|
-
transformation = described_class.new do
|
103
|
-
process :document do |document, target|
|
104
|
-
target << element("muff", nodes: ["muff"]) if document.nodes.empty?
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
expect(transformation.apply(to: nil, output_format: :xml)).to eq(transformed_xml)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|