cure 0.1.1 → 0.1.2

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +16 -6
  5. data/exe/cure +7 -3
  6. data/lib/cure/config.rb +17 -3
  7. data/lib/cure/coordinator.rb +72 -0
  8. data/lib/cure/export/exporter.rb +32 -7
  9. data/lib/cure/extract/builder.rb +27 -0
  10. data/lib/cure/extract/csv_lookup.rb +32 -0
  11. data/lib/cure/extract/extractor.rb +123 -0
  12. data/lib/cure/generator/base_generator.rb +51 -0
  13. data/lib/cure/generator/case_generator.rb +25 -0
  14. data/lib/cure/generator/character_generator.rb +35 -0
  15. data/lib/cure/generator/faker_generator.rb +25 -0
  16. data/lib/cure/generator/guid_generator.rb +16 -0
  17. data/lib/cure/generator/hex_generator.rb +16 -0
  18. data/lib/cure/generator/imports.rb +12 -0
  19. data/lib/cure/generator/number_generator.rb +16 -0
  20. data/lib/cure/generator/placeholder_generator.rb +20 -0
  21. data/lib/cure/generator/redact_generator.rb +16 -0
  22. data/lib/cure/generator/variable_generator.rb +20 -0
  23. data/lib/cure/helpers/file_helpers.rb +40 -0
  24. data/lib/cure/helpers/object_helpers.rb +29 -0
  25. data/lib/cure/log.rb +3 -3
  26. data/lib/cure/main.rb +40 -31
  27. data/lib/cure/strategy/append_strategy.rb +24 -0
  28. data/lib/cure/strategy/base_strategy.rb +123 -0
  29. data/lib/cure/strategy/end_with_strategy.rb +46 -0
  30. data/lib/cure/strategy/full_strategy.rb +24 -0
  31. data/lib/cure/strategy/imports.rb +10 -0
  32. data/lib/cure/strategy/match_strategy.rb +43 -0
  33. data/lib/cure/strategy/regex_strategy.rb +49 -0
  34. data/lib/cure/strategy/split_strategy.rb +53 -0
  35. data/lib/cure/strategy/start_with_strategy.rb +47 -0
  36. data/lib/cure/template/dispatch.rb +30 -0
  37. data/lib/cure/template/extraction.rb +38 -0
  38. data/lib/cure/template/template.rb +28 -0
  39. data/lib/cure/template/transformations.rb +26 -0
  40. data/lib/cure/transformation/candidate.rb +23 -9
  41. data/lib/cure/transformation/transform.rb +33 -41
  42. data/lib/cure/validators.rb +71 -0
  43. data/lib/cure/version.rb +1 -1
  44. data/lib/cure.rb +9 -4
  45. data/templates/aws_cur_template.json +130 -128
  46. data/templates/example_template.json +46 -30
  47. metadata +36 -9
  48. data/lib/cure/csv_helpers.rb +0 -6
  49. data/lib/cure/file_helpers.rb +0 -38
  50. data/lib/cure/generator/base.rb +0 -148
  51. data/lib/cure/object_helpers.rb +0 -27
  52. data/lib/cure/strategy/base.rb +0 -223
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cure
4
+ # This name sucks, it is just an exporter
5
+ class Dispatch
6
+
7
+ # @param [Array<Hash>] named_ranges
8
+ attr_accessor :named_ranges
9
+
10
+ def initialize
11
+ @named_ranges = [default]
12
+ end
13
+
14
+ # @param [Array<String>] hash
15
+ # @return [Cure::Dispatch]
16
+ def self.from_hash(hash)
17
+ this = Cure::Dispatch.new
18
+ this.named_ranges = hash["sections"] if hash.key?("sections")
19
+ this
20
+ end
21
+
22
+ def default
23
+ {
24
+ "named_range" => "default",
25
+ "file_name" => "cure-export",
26
+ "type" => "csv"
27
+ }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cure
4
+ class Extraction
5
+ # @param [Array<Hash>] named_ranges
6
+ attr_accessor :named_ranges
7
+
8
+ # @param [Array<Hash>] named_ranges
9
+ attr_accessor :variables
10
+
11
+ def initialize
12
+ @named_ranges = [{
13
+ "name" => "default",
14
+ "section" => -1
15
+ }]
16
+
17
+ @variables = []
18
+ end
19
+
20
+ # @param [Hash] hash
21
+ # @return [Cure::Extraction]
22
+ def self.from_hash(hash)
23
+ this = Cure::Extraction.new
24
+ this.named_ranges.push(*hash["named_ranges"])
25
+ this.variables.push(*hash["variables"])
26
+ this
27
+ end
28
+
29
+ # We only need to get the named ranges where the candidates have specified
30
+ # interest in them.
31
+ #
32
+ # @param [Array] candidate_nrs
33
+ # @return [Array]
34
+ def required_named_ranges(candidate_nrs)
35
+ @named_ranges.select { |nr| candidate_nrs.include?(nr["name"]) }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cure/template/transformations"
4
+ require "cure/template/extraction"
5
+ require "cure/template/dispatch"
6
+
7
+ module Cure
8
+ class Template
9
+ # @param [Cure::Transformations] transformations
10
+ attr_accessor :transformations
11
+
12
+ # @param [Cure::Extraction] extraction
13
+ attr_accessor :extraction
14
+
15
+ # @param [Cure::Dispatch] dispatch
16
+ attr_accessor :dispatch
17
+
18
+ # @param [Hash] hash
19
+ # @return [Cure::Template]
20
+ def self.from_hash(hash)
21
+ this = Cure::Template.new
22
+ this.transformations = Cure::Transformations.from_hash(hash.fetch("transformations", {}))
23
+ this.extraction = Cure::Extraction.from_hash(hash.fetch("extraction", {}))
24
+ this.dispatch = Cure::Dispatch.from_hash(hash.fetch("dispatch", {}))
25
+ this
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cure
4
+ class Transformations
5
+ # @param [Array<Transformation::Candidate>] candidates
6
+ attr_accessor :candidates
7
+
8
+ # @param [Array<Hash>] placeholders
9
+ # TODO: make class Placeholder
10
+ attr_accessor :placeholders
11
+
12
+ def initialize
13
+ @candidates = []
14
+ @placeholders = {}
15
+ end
16
+
17
+ # @param [Hash] hash
18
+ # @return [Cure::Transformations]
19
+ def self.from_hash(hash)
20
+ this = Cure::Transformations.new
21
+ this.candidates = hash["candidates"].map { |c| Cure::Transformation::Candidate.new.from_json(c) }
22
+ this.placeholders = hash["placeholders"]
23
+ this
24
+ end
25
+ end
26
+ end
@@ -1,17 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "cure/object_helpers"
4
- require "cure/strategy/base"
5
- require "cure/generator/base"
3
+ require "cure/helpers/object_helpers"
4
+ require "cure/strategy/imports"
5
+ require "cure/generator/imports"
6
6
  require "cure/log"
7
7
 
8
8
  module Cure
9
9
  module Transformation
10
10
  # Per row, we will have a candidate for each transformation that needs to be made
11
11
  class Candidate
12
- include ObjectHelpers
12
+ include Helpers::ObjectHelpers
13
13
  include Log
14
14
 
15
+ # Named range that column exists in
16
+ # @return [String]
17
+ attr_accessor :named_range
18
+
15
19
  # Lookup column name for CSV.
16
20
  # @return [String]
17
21
  attr_accessor :column
@@ -20,8 +24,14 @@ module Cure
20
24
  # @return [List<Translation>]
21
25
  attr_reader :translations
22
26
 
27
+ # @return [Translation]
23
28
  attr_reader :no_match_translation
24
29
 
30
+ def initialize
31
+ @translations = []
32
+ @named_range = "default"
33
+ end
34
+
25
35
  # @param [String] source_value
26
36
  # @return [String]
27
37
  # Transforms the existing value
@@ -43,24 +53,26 @@ module Cure
43
53
  value
44
54
  end
45
55
 
56
+ # @param [Hash] opts
46
57
  def translations=(opts)
47
58
  @translations = opts.map { |o| Translation.new.from_hash(o) }
48
59
  end
49
60
 
61
+ # @param [Hash] opts
50
62
  def no_match_translation=(opts)
51
63
  @no_match_translation = Translation.new.from_hash(opts)
52
64
  end
53
65
  end
54
66
 
55
67
  class Translation
56
- include ObjectHelpers
68
+ include Helpers::ObjectHelpers
57
69
 
58
70
  # What sort of replacement is done, full/random/lookup/partial.
59
- # @return [Strategy::Base]
71
+ # @return [Strategy::BaseStrategy]
60
72
  attr_reader :strategy
61
73
 
62
74
  # What sort of data needs to be generated.
63
- # @return [Generator::Base]
75
+ # @return [Generator::BaseGenerator]
64
76
  attr_reader :generator
65
77
 
66
78
  # @param [String] source_value
@@ -72,7 +84,9 @@ module Cure
72
84
  # @param [Hash] opts
73
85
  def strategy=(opts)
74
86
  clazz_name = "Cure::Strategy::#{opts["name"].to_s.capitalize}Strategy"
75
- @strategy = Kernel.const_get(clazz_name).new(opts["options"] || {})
87
+ strategy = Kernel.const_get(clazz_name).new(opts["options"] || {})
88
+
89
+ @strategy = strategy
76
90
  end
77
91
 
78
92
  # @param [Hash] opts
@@ -80,7 +94,7 @@ module Cure
80
94
  clazz_name = "Cure::Generator::#{opts["name"].to_s.capitalize}Generator"
81
95
  @generator = Kernel.const_get(clazz_name).new(opts["options"] || {})
82
96
  end
97
+
83
98
  end
84
99
  end
85
100
  end
86
-
@@ -1,14 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cure/log"
4
- require "cure/file_helpers"
4
+ require "cure/helpers/file_helpers"
5
+ require "cure/config"
6
+ require "cure/extract/extractor"
7
+
5
8
  require "rcsv"
6
9
 
7
10
  module Cure
8
11
  module Transformation
12
+ # Operational file for conducting transforms
9
13
  class Transform
10
14
  include Log
11
- include FileHelpers
15
+ include Helpers::FileHelpers
16
+ include Configuration
12
17
 
13
18
  # @return [Array<Candidate>]
14
19
  attr_accessor :candidates
@@ -18,53 +23,34 @@ module Cure
18
23
  @candidates = candidates
19
24
  end
20
25
 
21
- # @param [String] csv_file_location
22
- # @return [TransformContext]
23
- def extract_from_file(csv_file_location)
24
- file_contents = read_file(csv_file_location)
25
- extract_from_contents(file_contents)
26
- end
27
-
28
- # @param [String] file_contents
29
- # @return [TransformContext]
30
- def extract_from_contents(file_contents)
31
- ctx = TransformContext.new
32
- parse_content(ctx, file_contents, header: :none) do |row|
33
- if ctx.row_count == 1
34
- ctx.extract_column_headers(row)
35
- next
26
+ # @param [ParsedCSV] parsed_content
27
+ # @return [Hash<String,TransformResult>] # make this transformation results?
28
+ def transform_content(parsed_content)
29
+ parsed_content.content.each_with_object({}) do |section, hash|
30
+ ctx = TransformResult.new
31
+ section["rows"].each do |row|
32
+ ctx.row_count += 1
33
+
34
+ if ctx.row_count == 1
35
+ ctx.extract_column_headers(row)
36
+ next
37
+ end
38
+
39
+ row = transform(section["name"], ctx.column_headers, row)
40
+ ctx.add_transformed_row(row)
36
41
  end
37
42
 
38
- row = transform(ctx.column_headers, row)
39
- ctx.add_transformed_row(row)
43
+ hash[section["name"]] = ctx
40
44
  end
41
-
42
- ctx
43
45
  end
44
46
 
45
47
  private
46
48
 
47
- # @param [TransformContext] ctx
48
- # @param [String] file_contents
49
- # @param [Proc] _block
50
- # @param [Hash] opts
51
- # @yield [Array] row
52
- # @yield [TransformContext] ctx
53
- # @return [TransformContext]
54
- def parse_content(ctx, file_contents, opts={}, &_block)
55
- return nil unless block_given?
56
-
57
- Rcsv.parse(file_contents, opts) do |row|
58
- ctx.row_count += 1
59
- yield row
60
- end
61
- end
62
-
63
49
  # @param [Hash] column_headers
64
50
  # @param [Array] row
65
51
  # @return [Array]
66
- def transform(column_headers, row)
67
- @candidates.each do |candidate|
52
+ def transform(named_range, column_headers, row)
53
+ candidates_for_named_range(named_range).each do |candidate|
68
54
  column_idx = column_headers[candidate.column]
69
55
  next unless column_idx
70
56
 
@@ -77,10 +63,16 @@ module Cure
77
63
 
78
64
  row
79
65
  end
66
+
67
+ # @param [String] named_range
68
+ # @return [Array<Cure::Transformation::Candidate>]
69
+ def candidates_for_named_range(named_range)
70
+ @candidates.select { |c| c.named_range == named_range }
71
+ end
80
72
  end
81
73
 
82
- class TransformContext
83
- include FileHelpers
74
+ class TransformResult
75
+ include Helpers::FileHelpers
84
76
 
85
77
  attr_accessor :row_count,
86
78
  :transformed_rows,
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cure
4
+ module Validators
5
+ # Should be an array, we can have multiple validators for the same obj
6
+ @validators = {}
7
+
8
+ class << self
9
+ attr_accessor :validators
10
+
11
+ # @param [String] prop
12
+ # @param [Object] options
13
+ def register_validator(caller, prop, options)
14
+ @validators[caller] = [] unless @validators.has_key? caller
15
+ @validators[caller] << {prop: "@#{prop}".to_sym, options: options}
16
+ end
17
+
18
+ # @return [TrueClass, FalseClass]
19
+ def validate(zelf) # rubocop:disable Metrics/AbcSize
20
+ return true unless @validators.has_key? zelf.class
21
+
22
+ variables = instance_variables_hash(zelf)
23
+ @validators[zelf.class].all? do |k|
24
+ options = k[:options]
25
+ return true if options.empty? # No validator, no need to run.
26
+
27
+ validator_prop = options[:validator]
28
+ proc = case validator_prop
29
+ when Symbol
30
+ common_validators.fetch(validator_prop, proc { |_x| false })
31
+ when Proc
32
+ validator_prop
33
+ else
34
+ proc { |_x| false }
35
+ end
36
+
37
+ property = variables[k[:prop]]
38
+ proc.call(property)
39
+ end
40
+ end
41
+
42
+ # @param [Object] zelf
43
+ # @return [Hash]
44
+ def instance_variables_hash(zelf)
45
+ zelf.instance_variables.each_with_object({}) do |attribute, hash|
46
+ hash[attribute] = zelf.instance_variable_get(attribute)
47
+ end
48
+ end
49
+
50
+ def common_validators
51
+ {
52
+ presence: proc { |current_val| !current_val.nil? }
53
+ }
54
+ end
55
+ end
56
+
57
+ def validates(property, options={})
58
+ Validators.register_validator(self, property, options)
59
+ end
60
+
61
+ module Helpers
62
+ def valid?(suppress_error: false)
63
+ status = Validators.validate(self)
64
+ return true if status
65
+ return false if suppress_error
66
+
67
+ raise "Object is invalid"
68
+ end
69
+ end
70
+ end
71
+ end
data/lib/cure/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cure
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/cure.rb CHANGED
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "cure/log"
4
+ require "cure/main"
4
5
  require "cure/config"
5
6
  require "cure/version"
7
+ require "cure/helpers/file_helpers"
6
8
 
7
- require "cure/file_helpers"
9
+ require "cure/template/template"
8
10
  require "cure/transformation/transform"
9
11
 
10
- require "cure/main"
11
-
12
12
  require "logger"
13
13
 
14
14
  module Cure
@@ -21,6 +21,11 @@ module Cure
21
21
  end
22
22
  end
23
23
 
24
-
24
+ # @param [String] csv_file_location
25
+ # @param [Hash] template
26
+ # @return [File] output_file
27
+ def process(template, csv_file_location, output_dir)
28
+ # Main.init_from_hash(template, csv_file_location, output_dir)
29
+ end
25
30
  end
26
31
  end