gd_bam 0.0.15 → 0.1.0

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.
Files changed (81) hide show
  1. data/README.md +313 -5
  2. data/bin/bam +126 -48
  3. data/lib/bam/version.rb +1 -1
  4. data/lib/bam.rb +51 -0
  5. data/lib/base/errors.rb +15 -0
  6. data/lib/base/flow.rb +37 -0
  7. data/lib/base/graph.rb +23 -0
  8. data/lib/base/metadata.rb +107 -0
  9. data/lib/base/project.rb +95 -0
  10. data/lib/base/repo.rb +35 -0
  11. data/lib/base/sink.rb +44 -0
  12. data/lib/base/step.rb +47 -0
  13. data/lib/base/tap.rb +167 -0
  14. data/lib/base/taps.rb +19 -0
  15. data/lib/cloud_connect/dsl/cc.rb +42 -0
  16. data/lib/cloud_connect/dsl/es_helpers.rb +49 -0
  17. data/lib/cloud_connect/dsl/helpers.rb +199 -0
  18. data/lib/{nodes → cloud_connect/dsl}/nodes.rb +106 -16
  19. data/lib/cloud_connect/dsl/sf_helpers.rb +39 -0
  20. data/lib/cloud_connect/dsl/structure_helpers.rb +94 -0
  21. data/lib/commands/commands.rb +110 -0
  22. data/lib/commands/deployment.rb +217 -0
  23. data/lib/commands/docs_commands.rb +41 -0
  24. data/lib/commands/gd_commands.rb +95 -0
  25. data/lib/commands/scaffold_commands.rb +103 -0
  26. data/lib/commands/sf_commands.rb +37 -0
  27. data/lib/commands/validators.rb +19 -0
  28. data/lib/compatibility.rb +19 -0
  29. data/lib/compiler/compiler.rb +76 -0
  30. data/lib/compiler/etl_visitor.rb +165 -0
  31. data/lib/dsl/dsl.rb +125 -0
  32. data/lib/generators/downloaders.rb +449 -0
  33. data/lib/generators/etl.rb +261 -0
  34. data/lib/generators/validators.rb +445 -0
  35. data/lib/graphs/docentize.grf +1 -1
  36. data/lib/graphs/dummy.grf +1 -1
  37. data/lib/graphs/goodsales_v2/docentize.grf +47 -0
  38. data/lib/graphs/goodsales_v2/dummy.grf +46 -0
  39. data/lib/graphs/goodsales_v2/load_history.grf +579 -0
  40. data/lib/graphs/goodsales_v2/process_account.grf +47 -0
  41. data/lib/graphs/goodsales_v2/process_activity.grf +222 -0
  42. data/lib/graphs/goodsales_v2/process_activity_dim.grf +88 -0
  43. data/lib/graphs/goodsales_v2/process_activity_owner.grf +48 -0
  44. data/lib/graphs/goodsales_v2/process_forecast.grf +20 -0
  45. data/lib/graphs/goodsales_v2/process_opp_records.grf +84 -0
  46. data/lib/graphs/goodsales_v2/process_opportunity.grf +46 -0
  47. data/lib/graphs/goodsales_v2/process_opportunity_line_item.grf +171 -0
  48. data/lib/graphs/goodsales_v2/process_opportunity_snapshot.grf +94 -0
  49. data/lib/graphs/goodsales_v2/process_owner.grf +48 -0
  50. data/lib/graphs/goodsales_v2/process_stage.grf +51 -0
  51. data/lib/graphs/goodsales_v2/process_stage_history.grf +184 -0
  52. data/lib/graphs/goodsales_v2/process_velocity_duration.grf +140 -0
  53. data/lib/graphs/process_account.grf +1 -1
  54. data/lib/graphs/process_activity.grf +1 -1
  55. data/lib/graphs/process_activity_dim.grf +1 -1
  56. data/lib/graphs/process_activity_owner.grf +1 -1
  57. data/lib/graphs/process_forecast.grf +1 -1
  58. data/lib/graphs/process_opp_records.grf +1 -1
  59. data/lib/graphs/process_opportunity.grf +1 -1
  60. data/lib/graphs/process_opportunity_line_item.grf +1 -1
  61. data/lib/graphs/process_opportunity_snapshot.grf +1 -1
  62. data/lib/graphs/process_owner.grf +1 -1
  63. data/lib/graphs/process_stage.grf +1 -1
  64. data/lib/graphs/process_stage_history.grf +1 -1
  65. data/lib/graphs/process_velocity_duration.grf +1 -1
  66. data/lib/nodes/clover_gen.rb +59 -946
  67. data/lib/nodes/dependency.rb +95 -96
  68. data/lib/runtime.rb +7 -648
  69. data/lib/utils/utils.rb +66 -0
  70. data/templates/flow.rb.erb +7 -6
  71. data/templates/join_template.grf.erb +1 -1
  72. data/templates/reformat_template.grf.erb +1 -1
  73. data/templates/sink.json.erb +28 -0
  74. data/templates/tap.json.erb +3 -5
  75. data/templates/workspace.prm.erb +4 -0
  76. metadata +50 -8
  77. data/lib/contract_checkers/contract_checkers.rb +0 -53
  78. data/lib/dsl/project_dsl.rb +0 -259
  79. data/lib/repo/1_config.json +0 -8
  80. data/templates/dataset.json.erb +0 -13
  81. data/templates/source.json.erb +0 -22
data/lib/bam/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Bam
2
- VERSION = '0.0.15'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/bam.rb CHANGED
@@ -3,6 +3,57 @@ require 'pry'
3
3
  require 'zip/zip'
4
4
  require 'fileutils'
5
5
  $:.unshift(File.dirname(__FILE__))
6
+ require 'utils/utils'
7
+ require 'compatibility'
8
+
9
+ require 'cloud_connect/dsl/helpers'
10
+ require 'cloud_connect/dsl/sf_helpers'
11
+ require 'cloud_connect/dsl/es_helpers'
12
+ require 'cloud_connect/dsl/structure_helpers'
13
+ require 'cloud_connect/dsl/cc'
14
+ require 'cloud_connect/dsl/nodes'
15
+
16
+ require 'base/errors'
17
+ require 'base/tap'
18
+ require 'base/taps'
19
+ require 'base/sink'
20
+ require 'base/flow'
21
+ require 'base/metadata'
22
+ require 'base/project'
23
+ require 'base/graph'
24
+ require 'base/step'
25
+ require 'base/repo'
26
+
27
+ require 'dsl/dsl'
28
+ require 'compiler/compiler'
29
+ require 'compiler/etl_visitor'
30
+
31
+ require 'commands/commands'
32
+ require 'commands/scaffold_commands'
33
+ require 'commands/sf_commands'
34
+ require 'commands/deployment'
35
+ require 'commands/gd_commands'
36
+ require 'commands/docs_commands'
37
+ require 'commands/validators'
38
+
39
+ require 'generators/downloaders'
40
+ require 'generators/validators'
41
+ require 'generators/etl'
42
+
6
43
  require 'runtime'
44
+
45
+
7
46
  # Add requires for other files you add to your project here, so
8
47
  # you just need to require this one file in your bin file
48
+
49
+ module GoodData
50
+ module Bam
51
+
52
+ GENERATOR_ROOT = Pathname(__FILE__).expand_path.dirname
53
+ BAM_ROOT = GENERATOR_ROOT.parent
54
+
55
+ BAM_DEFINED_GRAPHS_ROOT = GENERATOR_ROOT + "graphs"
56
+ REPO_ROOT = GENERATOR_ROOT + "repo"
57
+ TEMPLATE_ROOT = BAM_ROOT + "templates"
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ module GoodData
2
+ module Bam
3
+ class RemoveMetadataFieldError < RuntimeError
4
+
5
+ attr_reader :options, :metadata, :field
6
+
7
+ def initialize(message, options={})
8
+ super(message)
9
+ @options = options
10
+ @metadata = options[:metadata]
11
+ @field = options[:field]
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/base/flow.rb ADDED
@@ -0,0 +1,37 @@
1
+ module GoodData
2
+ module Bam
3
+ module Flow
4
+
5
+ def self.create(flow)
6
+ {:steps => []}.merge(flow).merge({:type => :flow})
7
+ end
8
+
9
+ attr_accessor :steps, :name
10
+
11
+ def self.define(name="", &script)
12
+ # puts "Reading flow #{name}"
13
+ x = self.new
14
+ x.flow_name(name)
15
+ x.instance_eval(&script)
16
+ x
17
+ end
18
+
19
+ def self.add_step(flow, step)
20
+ new_steps = flow[:steps].concat([step])
21
+ Flow.create(flow.merge({:steps => new_steps}))
22
+ end
23
+
24
+ def self.remove_last_step(flow)
25
+ new_steps = flow[:steps][0..-2]
26
+ Flow.create(flow.merge({:steps => new_steps}))
27
+ end
28
+
29
+ # DSL is mutating part of the API. DO not use it except in DSL part of BAM that means in the flows
30
+
31
+ end
32
+
33
+ def self.flow(name="", &bl)
34
+ Flow.define(name, &bl)
35
+ end
36
+ end
37
+ end
data/lib/base/graph.rb ADDED
@@ -0,0 +1,23 @@
1
+ module GoodData
2
+ module Bam
3
+ module Graph
4
+
5
+ def self.create(graph)
6
+ fail "Graph should have graph to execute. You defined \"#{graph}\"" if graph[:path].blank?
7
+ {
8
+ :inputs => [],
9
+ :outputs => []
10
+ }.merge(graph).merge({
11
+ :path => Pathname(graph[:path]),
12
+ :name => Pathname(graph[:path]).basename.to_s,
13
+ :type => :graph
14
+ })
15
+ end
16
+
17
+ def self.get_path(graph)
18
+ Pathname(graph[:repository][:base]) + graph[:path]
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,107 @@
1
+ module GoodData
2
+ module Bam
3
+ module Metadata
4
+
5
+ attr_accessor :attributes
6
+
7
+ def self.create(metadata)
8
+ metadata
9
+ end
10
+
11
+ def self.clone(metadata)
12
+ Metadata.create(attributes)
13
+ end
14
+
15
+ def self.find_field(metadata, name)
16
+ metadata[:fields].detect {|f| f[:name] == name}
17
+ end
18
+
19
+ def self.has_field?(metadata, name)
20
+ !Metadata.find_field(metadata, name).nil?
21
+ end
22
+
23
+ def self.add_field(metadata, field)
24
+ fail "You have to specify name at the metadata change. You specified \"#{field}\"" unless field.respond_to?(:has_key?) && field.has_key?(:name)
25
+ position = field[:position] || 0
26
+ what = {
27
+ :name => field[:name],
28
+ :type => field[:type]
29
+ }
30
+ fields = metadata[:fields].clone
31
+ fields.insert(position - 1, what) unless Metadata.has_field?(metadata, field[:name])
32
+ Metadata.create(metadata.merge({:fields => fields}))
33
+ end
34
+
35
+ def self.remove_field(metadata, field_name)
36
+ fields = metadata[:fields]
37
+ fail RemoveMetadataFieldError.new("When trying to remove field \"#{field_name}\" from metadata \"#{metadata[:name]}\" the field was not found", :field => field_name, :metadata => metadata) unless fields.detect {|f| f[:name] == field_name}
38
+ fields = fields.find_all {|f| f[:name] != field_name}
39
+ Metadata.create(metadata.merge({:fields => fields}))
40
+ end
41
+
42
+ def self.get_metadata(what)
43
+ {
44
+ :input_metadata => Metadata.get_source_metadata(what),
45
+ :output_metadata => Metadata.get_target_metadata(what)
46
+ }
47
+ end
48
+
49
+ def self.get_target_metadata(what, options={})
50
+ name = options[:name] || what[:id]
51
+ case what[:type]
52
+ when :sink
53
+ Metadata.create({
54
+ :name => name,
55
+ :id => name,
56
+ :fields => GoodData::CloverGenerator::clover_metadata_for_fields(what[:fields].map {|f| {:name => f[:meta]}})
57
+ })
58
+ when :tap, :graph
59
+ Metadata.create({
60
+ :name => name,
61
+ :id => name,
62
+ :fields => GoodData::CloverGenerator::clover_metadata_for_module(what)
63
+ })
64
+ end
65
+ end
66
+
67
+ def self.get_source_metadata(what, options={})
68
+ name = options[:name] || what[:id]
69
+ case what[:type]
70
+ when :sink
71
+ Metadata.create({
72
+ :name => name,
73
+ :id => name,
74
+ :fields => GoodData::CloverGenerator::clover_metadata_for_fields(what[:fields].map {|f| {:name => f[:meta]}})
75
+ })
76
+ when :tap, :graph
77
+ Metadata.create({
78
+ :name => name,
79
+ :id => name,
80
+ :fields => GoodData::CloverGenerator::sf_metadata_for_module(what)
81
+ })
82
+ end
83
+ end
84
+
85
+ def self.add_timestamp_as_date(metadata)
86
+ if GoodData::Bam::Metadata.has_field?(metadata, "Timestamp")
87
+ metadata = GoodData::Bam::Metadata.remove_field(metadata, "Timestamp")
88
+ end
89
+ GoodData::Bam::Metadata.add_field(metadata, {:name => "Timestamp", :type => "date"})
90
+ end
91
+
92
+ def self.remove_timestamp(metadata)
93
+ if GoodData::Bam::Metadata.has_field?(metadata, "Timestamp")
94
+ GoodData::Bam::Metadata.remove_field(metadata, "Timestamp")
95
+ else
96
+ metadata
97
+ end
98
+ end
99
+
100
+ # def change
101
+ # yield(self)
102
+ # self
103
+ # end
104
+
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,95 @@
1
+ module GoodData
2
+ module Bam
3
+ module Project
4
+
5
+ def self.create(project)
6
+ {
7
+ :flows => [],
8
+ :flows_definitions => [],
9
+ :taps => [],
10
+ :sinks => []
11
+ }.merge(project).merge({:type => :project})
12
+ end
13
+
14
+ def self.find_by(project, what, by_what, name)
15
+ project[what].detect {|item| item[by_what] == name}
16
+ end
17
+
18
+ def self.find_tap_by_id(project, name)
19
+ Project.find_by(project, :taps, :id, name)
20
+ end
21
+
22
+ def self.find_tap_by_name(project, name)
23
+ Project.find_by(project, :taps, :name, name)
24
+ end
25
+
26
+ def self.find_sink_by_id(project, name)
27
+ Project.find_by(project, :sinks, :id, name)
28
+ end
29
+
30
+ def self.find_sink_by_name(project, name)
31
+ Project.find_by(project, :sinks, :name, name)
32
+ end
33
+
34
+ def self.find_graph_by_path(project, path)
35
+ found = project[:graph_repos].reduce([]) do |acc, repo|
36
+ if Bam::Repository.find(repo, path)
37
+ acc.concat([Bam::Repository.find(repo, path)])
38
+ else
39
+ acc
40
+ end
41
+ end
42
+ found.first
43
+ end
44
+
45
+ def self.load_taps(project, path="./taps/")
46
+ p = Pathname(path)
47
+ taps = Pathname.glob(p + "*.json").map do |p|
48
+ Tap.create(JSON.parse(File.read(p), :symbolize_names => true))
49
+ end
50
+ Project.create(project.merge({:taps => taps.map {|tap| Tap.create(tap)}}))
51
+ end
52
+
53
+ def self.set_graph_repos(project, repos=[])
54
+
55
+ # paths = paths.map {|p| Pathname(p)}
56
+ # graphs = paths.reduce([]) do |acc, path|
57
+ # Pathname.glob(path + "*.grf").map do |graph_path|
58
+ # acc.concat([Graph.create({
59
+ # :path => graph_path
60
+ # })])
61
+ # end
62
+ # acc
63
+ # end
64
+ Project.create(project.merge({:graph_repos => repos}))
65
+ end
66
+
67
+ def self.load_sinks(project, path="./sinks/")
68
+ p = Pathname(path)
69
+ sinks = Pathname.glob(p + "*.json").map do |p|
70
+ Sink.create(JSON.parse(File.read(p), :symbolize_names => true))
71
+ end
72
+ Project.create(project.merge({:sinks => sinks}))
73
+ end
74
+
75
+ def self.load_flows_definitions(project, path="./flows/")
76
+ p = Pathname(path)
77
+ flows = Pathname.glob(p + "*.rb").map do |p|
78
+ GoodData::Bam::DSL.class_eval(File.read p).to_hash
79
+ end
80
+ Project.create(project.merge({:flows_definitions => flows}))
81
+ end
82
+
83
+ def self.build_project(options={})
84
+ project = Project.create({})
85
+ paths = options[:graph_repos] || []
86
+ p = Project.load_taps(project)
87
+ p = Project.load_sinks(p)
88
+ p = Project.set_graph_repos(p, paths)
89
+ p = Project.load_flows_definitions(p)
90
+ p = Compiler.compile_dsl(p)
91
+ end
92
+
93
+ end
94
+ end
95
+ end
data/lib/base/repo.rb ADDED
@@ -0,0 +1,35 @@
1
+ module GoodData
2
+ module Bam
3
+ module Repository
4
+
5
+ def self.create(repository)
6
+ fail "repository has to have \"type\" defined. You specified \"#{repository}\"" unless repository.has_key?(:type)
7
+ case repository[:type]
8
+ when :file
9
+ repository.merge({
10
+ :base => Pathname(repository[:base])})
11
+ when :hash
12
+ fail "Repo has to have content defined" if repository[:content].nil? || !repository[:content].is_a?(Hash)
13
+ repository
14
+ end
15
+ end
16
+
17
+ def self.find(repository, path)
18
+ case repository[:type]
19
+ when :file
20
+ path = repository[:base] + Pathname(path)
21
+ if (path).exist?
22
+ Graph.create({
23
+ :path => Pathname(path).expand_path,
24
+ :repository => repository
25
+ })
26
+ end
27
+ when :hash
28
+ Graph.create(repository[:content][path])
29
+ else
30
+ fail "not implemented"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
data/lib/base/sink.rb ADDED
@@ -0,0 +1,44 @@
1
+ module GoodData
2
+ module Bam
3
+ module Sink
4
+
5
+ def self.create(sink)
6
+ fail "Sink should have id. You defined \"#{sink}\"" if sink[:id].blank?
7
+ fail "Sink should have target. You defined \"#{sink}\"" if sink[:target].blank?
8
+ sink = {:fields => []}.merge(sink).merge({:type => :sink})
9
+ add_target_type(sink)
10
+ end
11
+
12
+ def self.find_field(sink, name)
13
+ sink[:fields].detect {|f| f[:name] == name}
14
+ end
15
+
16
+ def self.has_field?(sink, name)
17
+ !find_field(sink, name).nil?
18
+ end
19
+
20
+ def self.add_target_type(sink)
21
+ target = sink[:target].to_s
22
+ path = Pathname(target)
23
+ uri = URI(target)
24
+
25
+ if target == "gooddata"
26
+ sink.merge({
27
+ :target => :gooddata,
28
+ :target_type => :gooddata
29
+ })
30
+ elsif uri.absolute? && (uri.scheme == "http" || uri.scheme == "https")
31
+ sink.merge({
32
+ :target => uri,
33
+ :target_type => :web
34
+ })
35
+ elsif target =~ /^\./ || target =~ /^\//
36
+ sink.merge({
37
+ :target => path,
38
+ :target_type => :file
39
+ })
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
data/lib/base/step.rb ADDED
@@ -0,0 +1,47 @@
1
+ module GoodData
2
+ module Bam
3
+ module Step
4
+
5
+ def self.get_graph_path(step)
6
+ case step[:type]
7
+ when :tap
8
+ "graphs/#{step[:flow_id]}_#{step[:id]}_#{step[:source_type]}_tap.grf"
9
+ when :sink
10
+ "graphs/#{step[:flow_id]}_#{step[:id]}_sink.grf"
11
+ when :graph
12
+ Graph.get_path(step)
13
+ else
14
+ raise "Not implemented"
15
+ end
16
+ end
17
+
18
+ def self.has_output_step?(steps)
19
+ steps.any? {|s| s.has_key?(:out)}
20
+ end
21
+
22
+ def self.find_output_step(steps)
23
+ if has_output_step?(steps)
24
+ steps.detect {|s| s.has_key?(:out)}
25
+ elsif steps.count == 1
26
+ steps.first
27
+ else
28
+ fail "No out is defined and there are more than 1 fields in flow \"#{steps}\""
29
+ end
30
+ end
31
+
32
+ def self.step_name(step)
33
+ case step[:type]
34
+ when :tap
35
+ "#{step[:id]}_#{step[:type]}"
36
+ when :sink
37
+ "#{step[:id]}_#{step[:type]}"
38
+ when :graph
39
+ "#{step[:path].basename.to_s.chomp(step[:path].extname)}_#{step[:type]}"
40
+ else
41
+ raise "Not implemented"
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
data/lib/base/tap.rb ADDED
@@ -0,0 +1,167 @@
1
+ module GoodData
2
+ module Bam
3
+
4
+ module Tap
5
+
6
+ def self.create(tap)
7
+ tap = ({:fields => [], :direct => false}.merge(tap).merge(:type => :tap))
8
+ tap = Tap.add_source_type(tap)
9
+ fail "Tap has to have id defined" if tap[:id].nil?
10
+
11
+ tap
12
+ end
13
+
14
+ def self.add_field(tap, field)
15
+ fail "You have to specify name. You specified \"#{field}\"" unless field.respond_to?(:has_key?) && field.has_key?(:name)
16
+ fail "There already is a field named #{field[:name]}" if has_field?(tap, field[:name])
17
+ position = field[:position] || 0
18
+ fields = tap[:fields].clone
19
+ fields.insert(position - 1, field)
20
+ Tap.create(tap.merge({:fields => fields}))
21
+ end
22
+
23
+ def self.remove_field(tap, name)
24
+ fields = tap[:fields].find_all {|f| f[:name] != name}
25
+ Tap.create(tap.merge({:fields => fields}))
26
+ end
27
+
28
+ def self.add_source_type(tap)
29
+ source = tap[:source].to_s
30
+ path = Pathname(source)
31
+ uri = URI(source)
32
+
33
+ if uri.absolute? && (uri.scheme == "http" || uri.scheme == "https")
34
+ tap.merge({
35
+ :source => uri,
36
+ :source_type => :web
37
+ })
38
+ elsif source =~ /^\./ || source =~ /^\//
39
+ tap.merge({
40
+ :source => path,
41
+ :source_type => :file
42
+ })
43
+ elsif source == :dummy
44
+ tap.merge({
45
+ :source_type => :dummy
46
+ })
47
+ else
48
+ tap.merge({
49
+ :source_type => :salesforce
50
+ })
51
+ end
52
+ end
53
+
54
+ def self.has_field?(tap, name)
55
+ !Tap.find_field(tap, name).nil?
56
+ end
57
+
58
+ def self.find_field(tap, name)
59
+ tap[:fields].detect {|f| f[:name] == name}
60
+ end
61
+
62
+ def self.find_output_field(tap, name)
63
+ acts_as_field = tap[:fields].detect {|f| f[:acts_as] && f[:acts_as].include?(name)}
64
+ source_field = Tap.find_field(tap, name)
65
+ if acts_as_field.blank?
66
+ source_field if source_field && (!source_field.has_key?(:acts_as) || !source_field[:acts_as].include(name))
67
+ else
68
+ acts_as_field
69
+ end
70
+ end
71
+
72
+ def self.has_output_field?(tap, name)
73
+ !find_output_field(tap, name).nil?
74
+ end
75
+
76
+ def self.remove_timestamp_field(tap)
77
+ remove_field(tap, "Timestamp")
78
+ end
79
+
80
+ def self.add_timestamp_field(tap)
81
+ if has_field?(tap, "Timestamp")
82
+ tap
83
+ else
84
+ add_field(tap, {:name => "Timestamp"})
85
+ end
86
+ end
87
+
88
+ def self.pull_timestamp_from_output_to_input(tap)
89
+ if has_field?(tap, "Timestamp")
90
+ tap
91
+ elsif has_output_field?(tap, "Timestamp")
92
+ field = find_output_field(tap, "Timestamp")
93
+ fields = tap[:fields].clone
94
+ index = fields.index(field)
95
+
96
+ field = field.clone
97
+ field[:name] = "Timestamp"
98
+ fields.delete_at(index)
99
+ fields.insert(index, field)
100
+ Tap.create(tap.merge(:fields => fields))
101
+ else
102
+ tap
103
+ end
104
+ end
105
+
106
+ def self.pull_id_from_output_to_input(tap)
107
+ if has_field?(tap, "Id")
108
+ tap
109
+ elsif has_output_field?(tap, "Id")
110
+ field = find_output_field(tap, "Id")
111
+ fields = tap[:fields].clone
112
+ index = fields.index(field)
113
+
114
+ field = field.clone
115
+ field[:name] = "Id"
116
+ fields.delete_at(index)
117
+ fields.insert(index, field)
118
+
119
+ Tap.create(tap.merge(:fields => fields))
120
+ else
121
+ tap
122
+ end
123
+ end
124
+
125
+ def self.source_target_mappging(tap)
126
+ tap[:fields].reduce([]) do |acc, f|
127
+ transformation = f[:acts_as] ? f[:acts_as].map {|i| [f[:name], i]} : [[f[:name], f[:name]]]
128
+ acc.concat(transformation)
129
+ end
130
+ end
131
+
132
+ def self.collect_validations(tap)
133
+ tap[:fields].find_all {|f| f.has_key?(:validates_as)}
134
+ end
135
+
136
+ def self.remove_acts_as(tap)
137
+ Tap.create(tap.merge({
138
+ :fields => tap[:fields].map {|f| f = f.clone; f.delete_if {|key, value| key == :acts_as }}
139
+ }))
140
+ end
141
+
142
+ def self.prepare_for_sf_downloader(tap)
143
+ id_field = Tap.find_output_field(tap, "Id")
144
+ time_field = Tap.find_output_field(tap, "Timestamp")
145
+ tap = Tap.remove_acts_as(tap)
146
+ fields = tap[:fields].map {|f| f[:name] == id_field[:name] ? f.merge(:acts_as => ["Id"]) : f}
147
+ if time_field
148
+ fields = fields.map {|f| f[:name] == time_field[:name] ? f.merge(:acts_as => ["Timestamp"]) : f}
149
+ end
150
+ Tap.create(tap.merge({
151
+ :fields => fields
152
+ }))
153
+ end
154
+
155
+ def self.prepare_for_es_downloader(tap)
156
+ tap = Tap.pull_id_from_output_to_input(tap)
157
+ tap = Tap.remove_timestamp_field(Tap.pull_timestamp_from_output_to_input(tap))
158
+ tap[:snapshots] == true ? Tap.add_field(tap, {:name => "Snapshot"}) : tap
159
+ end
160
+
161
+ def self.prepare_for_s3_backup(tap)
162
+ Tap.remove_acts_as(tap)
163
+ end
164
+
165
+ end
166
+ end
167
+ end
data/lib/base/taps.rb ADDED
@@ -0,0 +1,19 @@
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
+ end
18
+ end
19
+ end