transformator 0.1.4 → 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|