gd_bam 0.0.15 → 0.1.0

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