gd_bam 0.1.30 → 0.1.31

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module Bam
2
- VERSION = '0.1.30'
2
+ VERSION = '0.1.31'
3
3
  end
@@ -0,0 +1,35 @@
1
+ module GoodData
2
+ module Bam
3
+ module Taps
4
+
5
+ def self.get_incremental(taps)
6
+ taps.find_all {|t| t[:direct] == false || t[:direct].nil? }
7
+ end
8
+
9
+ def self.get_salesforce(taps)
10
+ taps.find_all {|t| t[:source_type] == :salesforce}
11
+ end
12
+
13
+ def self.get_file(taps)
14
+ taps.find_all {|t| [:web, :file].include?(t[:source_type]) }
15
+ end
16
+
17
+ <<<<<<< HEAD
18
+ def self.get_deleted_records_info(taps, client)
19
+ deleted = client.modules.map {|i| {:name => i[:name], :flag => i[:replicateable]}}.reduce({}) {|memo, x| memo.merge({x[:name] => x[:flag]})}
20
+ taps.map do |t|
21
+ if t[:source_type] == :salesforce
22
+ t.merge({:has_deleted_records => deleted[t[:object]]})
23
+ else
24
+ t.merge({:has_deleted_records => false})
25
+ end
26
+ end
27
+ =======
28
+ def self.get_box(taps)
29
+ taps.find_all {|t| [:box].include?(t[:source_type]) }
30
+ >>>>>>> Box init
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,229 @@
1
+ module GoodData
2
+ module CloudConnect
3
+ module Helpers
4
+
5
+ def self.property(builder, data)
6
+ builder.Property({
7
+ :id => data[:id],
8
+ :name => data[:name] || data[:id],
9
+ :value => data[:value]
10
+ })
11
+ end
12
+
13
+ def self.property_file(builder, data)
14
+ builder.Property({
15
+ :id => data[:id],
16
+ :fileURL => data[:fileURL]
17
+ })
18
+ end
19
+
20
+ <<<<<<< HEAD
21
+ def self.create_deleted_records_meta(builder)
22
+ builder.Metadata({:id => "deleted_records_metadata"}) do |builder|
23
+ csv_metadata(builder, {
24
+ :name => "deleted_records_metadata",
25
+ :fields => [
26
+ {:type => "string", :name => "Id"},
27
+ {:type => "string", :name => "Timestamp"}
28
+ =======
29
+ def self.create_http_request_meta(builder)
30
+ builder.Metadata({:id => "http_metadata"}) do |builder|
31
+ csv_metadata(builder, {
32
+ :name => "http_metadata",
33
+ :fields => [
34
+ {:type => "string", :name => "response"},
35
+ {:type => "string", :name => "all"}
36
+ >>>>>>> Box init
37
+ ]
38
+ })
39
+ end
40
+ end
41
+
42
+ def self.create_trash_meta(builder)
43
+ builder.Metadata({:id => "trash_metadata"}) do |builder|
44
+ csv_metadata(builder, {
45
+ :name => "trash_metadata",
46
+ :fields => [{:type => "string", :name => "all"}]
47
+ })
48
+ end
49
+ end
50
+
51
+ def self.save_metadata(filename, data)
52
+ dirname = File.dirname(filename)
53
+ FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
54
+
55
+ File.open(filename, "w") do |file|
56
+ builder = Builder::XmlMarkup.new(:target => file, :indent=>2)
57
+ builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
58
+ csv_metadata(builder, data)
59
+ end
60
+ end
61
+
62
+ def self.create_moving_graph(file, options={})
63
+ source = options[:source]
64
+ target = options[:target]
65
+ operation = options[:operation]
66
+ force = options[:force] || false
67
+
68
+ File.open(file, "w") do |file|
69
+ builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
70
+ builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
71
+ builder.Graph({
72
+ :name => "File Copy"
73
+ }) do
74
+ builder.Global do
75
+ builder.Metadata({:id => "list_metadata"}) do |builder|
76
+ Helpers::csv_metadata(builder, {
77
+ :name => "list_metadata",
78
+ :fields => [{:name=>"filePath", :type=>"string"}]
79
+ })
80
+ end
81
+ Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
82
+ end
83
+ builder.Phase(:number => 0) do
84
+
85
+ transformation_source = "function integer transform() {\n" + ([["filePath", "filePath"]].map {|t| "$out.0.#{t.last} = $in.0.#{t.first};"}.join("\n")) + "\nreturn OK;\n}"
86
+ Core::build_node2(builder, Nodes.file_list2(:baseURL => target, :id => "file_list", :output_mapping => transformation_source))
87
+
88
+ Core::build_node2(builder, Nodes.file_delete2(:baseURL => "${filePath}", :id => "file_delete"))
89
+ Core::build_node2(builder, Nodes.edge2({:toNode => "file_delete:0", :fromNode => "file_list:0", :metadata => "list_metadata"}))
90
+ end
91
+ builder.Phase(:number => 1) do
92
+ Core::build_node2(builder, Nodes.file_copy2({:sourcePath => source, :targetPath => target, :operation => operation, :id => "file_copy"}))
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def self.csv_metadata(builder, description)
99
+ sf_description = description.merge({
100
+ :fieldDelimiter => ",",
101
+ :recordDelimiter => "\\n",
102
+ :type => "delimited",
103
+ })
104
+ metadata(builder, sf_description)
105
+ end
106
+
107
+ # prepares a sink for sinking into GD. This means dealing with stuff like scientific notation which is handled bu uploading as a decimal and not string
108
+ def self.sink_out_gd_metadata(metadata, sink)
109
+ metadata_fields = metadata[:fields]
110
+ sink_facts = GoodData::Bam::Sink.get_fact_fields(sink).map {|f| f[:meta]}
111
+ x = metadata_fields.map {|f| sink_facts.include?(f[:name]) ? f.merge({:type => "decimal"}) : f}
112
+ GoodData::Bam::Metadata.create(metadata.merge({:fields => x}))
113
+ end
114
+
115
+ def self.metadata(builder, description)
116
+ builder.Record({
117
+ :fieldDelimiter => description[:fieldDelimiter],
118
+ :name => description[:name],
119
+ :recordDelimiter => description[:recordDelimiter],
120
+ :type => description[:type]
121
+ }) do |record|
122
+ description[:fields].each do |field|
123
+ builder.Field :name => field[:name], :type => field[:type] || "string", :nullable => "true"
124
+ end
125
+ end
126
+ end
127
+
128
+ def self.create_lookup_meta(builder)
129
+ builder.Metadata({:id => "lookup_metadata"}) do |builder|
130
+ csv_metadata(builder, {
131
+ :name => "lookup_metadata",
132
+ :fields => [{:type => "string", :name => "key"}, {:type => "string", :name => "value"}]
133
+ })
134
+ end
135
+ end
136
+
137
+ def self.create_file_list_meta(builder)
138
+ builder.Metadata({:id => "file_list"}) do |builder|
139
+ csv_metadata(builder, {
140
+ :name => "file_list",
141
+ :fields => [
142
+ {:name => "filePath", :type => "string"},
143
+ {:name => "fileName", :type => "string"}
144
+ ]
145
+ })
146
+ end
147
+ end
148
+
149
+ def self.create_read_error_meta(builder)
150
+ builder.Metadata({:id => "reader_error_metadata"}) do |builder|
151
+ csv_metadata(builder, {
152
+ :name => "reader_error_metadata",
153
+ :fields => [
154
+ {:name => "line_number", :type => "integer"},
155
+ {:name => "field_number", :type => "integer"},
156
+ {:name => "record", :type => "string"},
157
+ {:name => "message", :type => "string"},
158
+ {:name => "file", :type => "string"}
159
+ ]
160
+ })
161
+ end
162
+ end
163
+
164
+ def self.create_run_graph_failure_metadata(builder)
165
+ builder.Metadata({:id => "run_graph_failure_metadata"}) do |builder|
166
+ csv_metadata(builder, {
167
+ :name => "run_graph_failure_metadata",
168
+ :fields => [
169
+ {:type => "string", :name => "graph"},
170
+ {:type => "string", :name => "result"},
171
+ {:type => "string", :name => "description"},
172
+ {:type => "string", :name => "message"},
173
+ {:type => "decimal", :name => "duration"}
174
+ ]
175
+ })
176
+ end
177
+ end
178
+
179
+ def self.create_run_graph(file, options={})
180
+ subgraphs = options[:subgraphs]
181
+ flow = options[:flow]
182
+ File.open(file, "w") do |file|
183
+ builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
184
+ builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
185
+ builder.Graph({
186
+ :name => "Run graph"
187
+ }) do
188
+ builder.Global do
189
+ property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
190
+ property_file(builder, {:id => "params_params", :fileURL => "params.prm"})
191
+ create_trash_meta(builder)
192
+ create_lookup_meta(builder)
193
+
194
+ end
195
+ phase = 0
196
+ subgraphs.each do |subgraph|
197
+ name = GoodData::Bam::Step.step_name(GoodData::Bam::Graph.create(:path => subgraph))
198
+ # Pathname(subgraph).basename.to_s.chomp(Pathname(subgraph).extname)
199
+ builder.Phase(:number => phase+1) do
200
+ id1 = GoodData::CloudConnect::Nodes.get_id
201
+ id2 = GoodData::CloudConnect::Nodes.get_id
202
+ ctl = "function integer generate() {$out.0.all = \"FLOW=#{flow}\";return OK;}"
203
+ Core::build_node2(builder, Nodes.data_generator2({:name => id1, :id => id1, :generate => ctl}))
204
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{id2}:0", :fromNode => "#{id1}:0", :metadata => "trash_metadata"}))
205
+ Core::build_node2(builder, Nodes.writer2({:name => "PARAMS CSV Writer", :id => "#{id2}", :fileURL => "params.prm", :outputFieldNames => "false", :quotedStrings => "false"}))
206
+ end
207
+ builder.Phase(:number => phase+2) do
208
+
209
+ id1 = GoodData::CloudConnect::Nodes.get_id
210
+ id2 = GoodData::CloudConnect::Nodes.get_id
211
+ ctl = "function integer generate() {$out.0.all = \"NAME=#{name}\";return OK;}"
212
+ Core::build_node2(builder, Nodes.data_generator2({:name => id1, :id => id1, :generate => ctl}))
213
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{id2}:0", :fromNode => "#{id1}:0", :metadata => "trash_metadata"}))
214
+ Core::build_node2(builder, Nodes.writer2({:name => "PARAMS CSV Writer", :id => "#{id2}", :fileURL => "params.prm", :outputFieldNames => "false", :append => "true", :quotedStrings => "false"}))
215
+ end
216
+
217
+ builder.Phase(:number => phase+3) do
218
+ Core::build_node2(builder, Nodes.run_graph2({:guiName => name, :name => name, :id => flow, :graphName => subgraph}))
219
+ end
220
+ phase += 4
221
+ end
222
+ end
223
+ end
224
+ end
225
+
226
+
227
+ end
228
+ end
229
+ end
@@ -427,9 +427,8 @@ HEREDOC
427
427
  Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
428
428
  end
429
429
 
430
- phase = 1
430
+ taps_memo = {}
431
431
 
432
- taps_with_history = []
433
432
  taps.each do |tap|
434
433
  module_name = tap[:object]
435
434
  dataset = tap[:id]
@@ -450,134 +449,154 @@ HEREDOC
450
449
  objects_to_get = Helpers.objects_for_history(client, tap)
451
450
 
452
451
  (tap[:fields] - [id_field, timestamp_field]).each_with_index do |field, i|
453
- builder.Phase(:number => phase += 1) do
454
-
455
- f = field[:name]
456
- selects = if (f == "CreatedDate") then
457
- [{
458
- :object => sf_object,
459
- :query => "SELECT Id, CreatedDate FROM #{sf_object}",
460
- :mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
461
- {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Value\"}},
462
- {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
463
- {\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
464
- ]}}",
465
- :mandatory => ["Id", "CreatedDate"]
466
- }]
467
- # binding.pry
468
- # temp
469
- else
470
- objects_to_get.reduce([]) do |memo, o|
471
- fields = client.fields(o)
472
- # how the history is stored does not rely on table naming convention. It is a couple of conventionsmangled together.This piece of code is trying to recognize which it is and produce the right downloader
473
- generic_field_history = ["NewValue", "OldValue", "ParentId"].all? {|fl| fields.include?(fl)}
474
- specific_field_history = ["NewValue", "OldValue", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
475
- specific_history = ["CreatedDate", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
476
-
477
- select, mapping, mandatory = if generic_field_history && !field[:multi_currency]
478
- # This kicks in when you have Field History type of table. There are several versions in SF. This one deals with the one that references ID of the record as Pernt Id. This is not true for opportunity, account.
479
- [
480
- "SELECT NewValue, CreatedDate, ParentId FROM #{o} WHERE Field = '#{f}'",
481
- "{\"xmlFieldsMapping\":{\"xmlFields\":[
482
- {\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
483
- {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
484
- {\"xmlFieldMapping\":{\"name\":\"ParentId\",\"label\":\"ParentId\",\"xmlPath\":\"ParentId\",\"metadataField\":\"Id\"}}
485
- ]}}",
486
- ["ParentId", "NewValue", "CreatedDate"]
487
- ]
488
- elsif (specific_field_history && !field[:multi_currency])
489
- # This is like the previous with the difference that it specifically names the id of the record. Like OpportunityId, AccountId, etc.
452
+ f = field[:name]
453
+
454
+ selects = if (f == "CreatedDate") then
455
+ [{
456
+ :object => sf_object,
457
+ :query => "SELECT Id, CreatedDate FROM #{sf_object}",
458
+ :mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
459
+ {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Value\"}},
460
+ {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
461
+ {\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
462
+ ]}}",
463
+ :mandatory => ["Id", "CreatedDate"]
464
+ }]
465
+ else
466
+ objects_to_get.reduce([]) do |memo, o|
467
+ fields = client.fields(o)
468
+ # how the history is stored does not rely on table naming convention. It is a couple of conventionsmangled together.This piece of code is trying to recognize which it is and produce the right downloader
469
+ generic_field_history = ["NewValue", "OldValue", "ParentId"].all? {|fl| fields.include?(fl)}
470
+ specific_field_history = ["NewValue", "OldValue", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
471
+ specific_history = ["CreatedDate", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
472
+
473
+ select, mapping, mandatory = if generic_field_history && !field[:multi_currency]
474
+ # This kicks in when you have Field History type of table. There are several versions in SF. This one deals with the one that references ID of the record as Pernt Id. This is not true for opportunity, account.
475
+ [
476
+ "SELECT NewValue, CreatedDate, ParentId FROM #{o} WHERE Field = '#{f}'",
477
+ "{\"xmlFieldsMapping\":{\"xmlFields\":[
478
+ {\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
479
+ {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
480
+ {\"xmlFieldMapping\":{\"name\":\"ParentId\",\"label\":\"ParentId\",\"xmlPath\":\"ParentId\",\"metadataField\":\"Id\"}}
481
+ ]}}",
482
+ ["ParentId", "NewValue", "CreatedDate"]
483
+ ]
484
+ elsif (specific_field_history && !field[:multi_currency])
485
+ # This is like the previous with the difference that it specifically names the id of the record. Like OpportunityId, AccountId, etc.
486
+ [
487
+ "SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f}'",
488
+ "{\"xmlFieldsMapping\":{\"xmlFields\":[
489
+ {\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
490
+ {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
491
+ {\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
492
+ ]}}",
493
+ ["#{sf_object}Id", "NewValue", "CreatedDate"]
494
+ ]
495
+ elsif specific_history
496
+ # Specific history is the row like history. The only instance I know of is OpportunityHistory.
497
+ if fields.include?(f)
490
498
  [
491
- "SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f}'",
499
+ (field[:multi_currency] ? "SELECT convertCurrency(#{f}), CreatedDate, #{sf_object}Id FROM #{o}" : "SELECT #{f}, CreatedDate, #{sf_object}Id FROM #{o}"),
492
500
  "{\"xmlFieldsMapping\":{\"xmlFields\":[
493
- {\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
501
+ {\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
494
502
  {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
495
503
  {\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
496
504
  ]}}",
497
- ["#{sf_object}Id", "NewValue", "CreatedDate"]
505
+ ["#{sf_object}Id", f, "CreatedDate"]
498
506
  ]
499
- elsif specific_history
500
- # Specific history is the row like history. The only instance I know of is OpportunityHistory.
501
- if fields.include?(f)
502
- [
503
- (field[:multi_currency] ? "SELECT convertCurrency(#{f}), CreatedDate, #{sf_object}Id FROM #{o}" : "SELECT #{f}, CreatedDate, #{sf_object}Id FROM #{o}"),
504
- "{\"xmlFieldsMapping\":{\"xmlFields\":[
505
- {\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
506
- {\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
507
- {\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
508
- ]}}",
509
- ["#{sf_object}Id", f, "CreatedDate"]
510
- ]
511
- else
512
- [nil, nil, nil]
513
- end
514
- else
515
- puts "Warning: Unrecognized fields configuration for historization in SF for #{o}"
516
- end
517
- if select.nil?
518
- memo
519
507
  else
520
- memo.concat([{
521
- :object => o,
522
- :query => select,
523
- :mapping => mapping,
524
- :mandatory => mandatory
525
- }])
508
+ [nil, nil, nil]
526
509
  end
510
+ else
511
+ puts "Warning: Unrecognized fields configuration for historization in SF for #{o}"
527
512
  end
528
- end
529
- unless selects.empty?
530
- # binding.pry if f== "CreatedDate"
531
- taps_with_history.concat([tap])
532
- selects = selects.concat([{
533
- :object => sf_object,
534
- :query => (field[:multi_currency] ? "SELECT Id, convertCurrency(#{f}), SystemModstamp FROM #{sf_object}" : "SELECT Id, #{f}, SystemModstamp FROM #{sf_object}"),
535
- :mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
536
- {\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
537
- {\"xmlFieldMapping\":{\"name\":\"SystemModstamp\",\"label\":\"SystemModstamp\",\"xmlPath\":\"SystemModstamp\",\"metadataField\":\"Timestamp\"}},
538
- {\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
539
- ]}}",
540
- :mandatory => ["Id", f, "SystemModstamp"]
541
- }])
542
- selects.each_with_index do |obj, i|
543
- # binding.pry if f== "CreatedDate"
544
- o = obj[:object]
545
- mapping = obj[:mapping]
546
- select = obj[:query]
547
- mandatory = obj[:mandatory]
548
- # puts "#{f}_#{o}_reader:0 -> #{f}_#{sf_object}_gather:#{i}"
549
-
550
- Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{o} SF Reader #{i}", :id => "#{f}_#{o}_#{i}_reader", :soql => select, :sfdcConnection => "SFDC", :fieldsMapping => mapping, :mandatoryFields => mandatory.join(';')}))
551
- Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_gather:#{i}", :fromNode => "#{f}_#{o}_#{i}_reader:0", :metadata => "data_metadata"}))
513
+ if select.nil?
514
+ memo
515
+ else
516
+ memo.concat([{
517
+ :object => o,
518
+ :query => select,
519
+ :mapping => mapping,
520
+ :mandatory => mandatory
521
+ }])
552
522
  end
553
- Core::build_node2(builder, Nodes.gather2({:name => "#{f} Gather", :id => "#{f}_#{sf_object}_gather"}))
554
- Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{f}_#{sf_object}_sort", :id => "#{f}_#{sf_object}_sort"}))
555
- Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_sort:0", :fromNode => "#{f}_#{sf_object}_gather:0", :metadata => "data_metadata"}))
523
+ end
524
+ end
525
+ unless selects.empty?
526
+ # binding.pry if f== "CreatedDate"
527
+ # taps_with_history.concat([tap])
528
+ selects = selects.concat([{
529
+ :object => sf_object,
530
+ :query => (field[:multi_currency] ? "SELECT Id, convertCurrency(#{f}), SystemModstamp FROM #{sf_object}" : "SELECT Id, #{f}, SystemModstamp FROM #{sf_object}"),
531
+ :mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
532
+ {\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
533
+ {\"xmlFieldMapping\":{\"name\":\"SystemModstamp\",\"label\":\"SystemModstamp\",\"xmlPath\":\"SystemModstamp\",\"metadataField\":\"Timestamp\"}},
534
+ {\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
535
+ ]}}",
536
+ :mandatory => ["Id", f, "SystemModstamp"]
537
+ }])
538
+
539
+ taps_memo["#{tap[:id]}:#{f}"] = {
540
+ :tap => tap,
541
+ :field => f,
542
+ :selects => selects
543
+ }
544
+ end
545
+ end
546
+ end
556
547
 
557
- Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{f}_#{sf_object}_copy"}))
558
- Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_copy:0", :fromNode => "#{f}_#{sf_object}_sort:0", :metadata => "data_metadata"}))
548
+ phase = 1
559
549
 
560
- if s3_backup
561
- Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{f}_#{sf_object} s3 Writer", :id => "#{f}_#{sf_object}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{sf_object}/#{f}_#{sf_object}_\`date2long(today())\`", :outputFieldNames => true}))
562
- Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_s3:0", :fromNode => "#{f}_#{sf_object}_copy:1", :metadata => "data_metadata"}))
563
- end
550
+ binding.pry
551
+ taps_memo.values.each_slice(6).to_a.each do |slice|
552
+ builder.Phase(:number => phase +=1) do
553
+ slice.each do |field|
554
+ # taps_memo.each do |key, field|
555
+ f = field[:field]
556
+ sf_object = field[:tap][:object]
557
+ selects = field[:selects]
558
+ selects.each_with_index do |obj, i|
559
+ o = obj[:object]
560
+ mapping = obj[:mapping]
561
+ select = obj[:query]
562
+ mandatory = obj[:mandatory]
563
+ Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{o} SF Reader #{i}", :id => "#{f}_#{o}_#{i}_reader", :soql => select, :sfdcConnection => "SFDC", :fieldsMapping => mapping, :mandatoryFields => mandatory.join(';')}))
564
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_gather:#{i}", :fromNode => "#{f}_#{o}_#{i}_reader:0", :metadata => "data_metadata"}))
565
+ end
566
+ Core::build_node2(builder, Nodes.gather2({:name => "#{f} Gather", :id => "#{f}_#{sf_object}_gather"}))
567
+ Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{f}_#{sf_object}_sort", :id => "#{f}_#{sf_object}_sort"}))
568
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_sort:0", :fromNode => "#{f}_#{sf_object}_gather:0", :metadata => "data_metadata"}))
564
569
 
565
- transform = "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = str2date($in.0.Timestamp,\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\nreturn OK;\n}"
570
+ Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{f}_#{sf_object}_copy"}))
571
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_copy:0", :fromNode => "#{f}_#{sf_object}_sort:0", :metadata => "data_metadata"}))
566
572
 
567
- Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "#{f}_#{sf_object}_reformat", :transformation => transform}))
568
- Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_reformat:0", :fromNode => "#{f}_#{sf_object}_copy:0", :metadata => "data_metadata"}))
573
+ if s3_backup
574
+ Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{f}_#{sf_object} s3 Writer", :id => "#{f}_#{sf_object}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{sf_object}/#{f}_#{sf_object}_\`date2long(today())\`", :outputFieldNames => true}))
575
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_s3:0", :fromNode => "#{f}_#{sf_object}_copy:1", :metadata => "data_metadata"}))
576
+ end
569
577
 
570
- Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{f}_#{sf_object}_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json({:type => :tap, :id => tap[:id], :fields => [{:name => "Id"}, {:name => "Timestamp"}, {:name => f, :meta => "Value"}]}).to_json}))
578
+ transform = "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = str2date($in.0.Timestamp,\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\nreturn OK;\n}"
579
+
580
+ Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "#{f}_#{sf_object}_reformat", :transformation => transform}))
581
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_reformat:0", :fromNode => "#{f}_#{sf_object}_copy:0", :metadata => "data_metadata"}))
571
582
 
572
- # Core::build_node2(builder, Nodes.trash2({:name => "#{f}_#{sf_object}_es", :id => "#{f}_#{sf_object}_es", :debugPrint => true}))
573
- Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_es:0", :fromNode => "#{f}_#{sf_object}_reformat:0", :metadata => "es_metadata"}))
574
- end
575
583
  end
576
584
  end
577
585
  end
578
586
 
579
- taps_with_history.uniq_by {|x| x[:id]}.each do |tap|
587
+ taps_memo.each do |key, field|
588
+ builder.Phase(:number => phase +=1) do
589
+ tap = field[:tap]
590
+ file = field[:tap][:id]
591
+ sf_object = field[:tap][:object]
592
+ f = field[:field]
593
+ Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{f}_#{sf_object}_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json({:type => :tap, :id => tap[:id], :fields => [{:name => "Id"}, {:name => "Timestamp"}, {:name => f, :meta => "Value"}]}).to_json}))
594
+ Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_es:0", :fromNode => "#{f}_#{sf_object}_reformat:0", :metadata => "es_metadata"}))
595
+ end
596
+ end
580
597
 
598
+ taps_memo.values.uniq_by {|x| x[:tap][:id]}.each do |field_tap|
599
+ tap = field_tap[:tap]
581
600
  # Download the Deleted records for these taps. since we will not have a chance to download them later
582
601
 
583
602
  if tap[:has_deleted_records]
@@ -652,7 +671,7 @@ HEREDOC
652
671
  :graph_to_run => "graphs/#{id}_download.grf"
653
672
  })
654
673
  create_incremental_file_downloading_graph(home + "#{tap[:id]}_download.grf", [tap], params)
655
-
674
+
656
675
  end
657
676
  end
658
677
 
@@ -681,6 +700,7 @@ HEREDOC
681
700
  Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
682
701
  Helpers::create_lookup_meta(builder)
683
702
  taps.each do |tap|
703
+
684
704
  module_name = tap[:object]
685
705
  file = tap[:id] || module_name
686
706
 
@@ -710,7 +730,6 @@ HEREDOC
710
730
  dataset = file || module_name
711
731
  source_file = tap[:source]
712
732
 
713
-
714
733
  has_timestamp = GoodData::Bam::Tap.has_output_field?(tap, "Timestamp")
715
734
  timestamp_field = GoodData::Bam::Tap.find_output_field(tap, "Timestamp")
716
735
  id_field = GoodData::Bam::Tap.find_output_field(tap, "Id")
@@ -725,17 +744,13 @@ HEREDOC
725
744
  end
726
745
  stuff = mapping + add.join(",") + "]}}"
727
746
 
728
- mandatory_fields = fields.reject {|f| f[:is_mandatory] == false }.map {|f| f[:name] + ";"}.join
729
-
730
- Core::build_node2(builder, Nodes.reader2({:name => "#{file} File Reader", :id => "#{file}_reader", :fileURL => "${FILE}"}))
747
+ Core::build_node2(builder, Nodes.reader2(Utils.merge_only_values({:name => "#{file} File Reader", :id => "#{file}_reader", :fileURL => "${FILE}"}, tap, [:charset])))
731
748
  es_transformation_source = if has_timestamp
732
- "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = str2date($in.0.#{timestamp_field[:name]},\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");;\nreturn OK;\n}"
749
+ "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = str2date($in.0.#{timestamp_field[:name]},\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\nreturn OK;\n}"
733
750
  else
734
751
  "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = long2date(${GRAPH_STARTED_TIMESTAMP});\nreturn OK;\n}"
735
752
  end
736
753
 
737
- # build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_reformat", :transformation => transformation_source}))
738
-
739
754
  Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{file}_copy"}))
740
755
  Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_copy:0", :fromNode => "#{file}_reader:0", :metadata => "#{file}_source_metadata"}))
741
756
  Core::build_node2(builder, Nodes.writer2({:enabled => "disabled", :name => "#{file} CSV Writer", :id => "#{file}_csv", :fileURL => "data/#{dataset.downcase}.csv", :outputFieldNames => "true"}))
@@ -191,7 +191,7 @@ HEREDOC
191
191
  end
192
192
 
193
193
  builder.Phase(:number => 0) do
194
- Core::build_node2(builder, Nodes.reader2({:name => "reader", :id => "reader", :fileURL => tap[:source] }))
194
+ Core::build_node2(builder, Nodes.reader2(Utils.merge_only_values({:name => "reader", :id => "reader", :fileURL => tap[:source]}, tap, [:charset])))
195
195
 
196
196
  Core::build_node2(builder, Nodes.copy2({:name => "copy", :id => "copy"}))
197
197
  Core::build_node2(builder, Nodes.edge2({:toNode => "copy:0", :fromNode => "reader:0", :metadata => "file_metadata"}))
@@ -61,6 +61,15 @@ module GoodData
61
61
  keys.all? {|key| !params[:additional_params][key].blank?}
62
62
  end
63
63
 
64
- end
65
- end
64
+ def self.merge_only_values(merge_onto, data, keys=[])
65
+ filtered_data = data.inject({}) {|memo, k| memo[k.first] = k[1] unless k[0].blank?; memo}
66
+ if keys.empty?
67
+ merge_onto.merge(filtered_data)
68
+ else
69
+ merge_onto.merge(filtered_data.select {|key, val| keys.include?(key)})
70
+ end
71
+ end
72
+
73
+ end
74
+ end
66
75
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gd_bam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.30
4
+ version: 0.1.31
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-12 00:00:00.000000000 Z
12
+ date: 2013-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -320,9 +320,11 @@ files:
320
320
  - lib/base/step.rb
321
321
  - lib/base/tap.rb
322
322
  - lib/base/taps.rb
323
+ - lib/base/taps.rb.orig
323
324
  - lib/cloud_connect/dsl/cc.rb
324
325
  - lib/cloud_connect/dsl/es_helpers.rb
325
326
  - lib/cloud_connect/dsl/helpers.rb
327
+ - lib/cloud_connect/dsl/helpers.rb.orig
326
328
  - lib/cloud_connect/dsl/nodes.rb
327
329
  - lib/cloud_connect/dsl/sf_helpers.rb
328
330
  - lib/cloud_connect/dsl/structure_helpers.rb