blufin 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 (113) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bf +5 -0
  3. data/bin/blufin +5 -0
  4. data/lib/blufin.rb +245 -0
  5. data/lib/core/code_scanners/common/scanner_common.rb +83 -0
  6. data/lib/core/code_scanners/common/scanner_java.rb +106 -0
  7. data/lib/core/code_scanners/scanner_java_embedded_objects.rb +386 -0
  8. data/lib/core/code_scanners/scanner_java_enums.rb +125 -0
  9. data/lib/core/code_scanners/scanner_java_source.rb +29 -0
  10. data/lib/core/code_scanners/scanner_java_tests.rb +157 -0
  11. data/lib/core/error_handling/schema_error.rb +9 -0
  12. data/lib/core/error_handling/sql_error.rb +21 -0
  13. data/lib/core/error_handling/sql_error_handler.rb +149 -0
  14. data/lib/core/error_handling/yml_error.rb +21 -0
  15. data/lib/core/error_handling/yml_error_handler.rb +437 -0
  16. data/lib/core/mysql.rb +347 -0
  17. data/lib/core/opt.rb +21 -0
  18. data/lib/core/site/site.rb +26 -0
  19. data/lib/core/site/site_auth.rb +88 -0
  20. data/lib/core/site/site_embedded.rb +27 -0
  21. data/lib/core/site/site_ports.rb +9 -0
  22. data/lib/core/site/site_resolver.rb +276 -0
  23. data/lib/core/site/site_services.rb +162 -0
  24. data/lib/core/site/site_ui.rb +16 -0
  25. data/lib/core/yml/config/yml_config_validator.rb +219 -0
  26. data/lib/core/yml/maven/yml_maven_validator.rb +1132 -0
  27. data/lib/core/yml/resource/yml_resource_validator.rb +154 -0
  28. data/lib/core/yml/schema/yml_schema_flags.rb +9 -0
  29. data/lib/core/yml/schema/yml_schema_validator.rb +1850 -0
  30. data/lib/core/yml/yml_cache_handler.rb +115 -0
  31. data/lib/core/yml/yml_common.rb +487 -0
  32. data/lib/core/yml/yml_meta_writer_base.rb +300 -0
  33. data/lib/core/yml/yml_outputter.rb +307 -0
  34. data/lib/core/yml/yml_validator_base.rb +630 -0
  35. data/lib/core/yml_writers/yml_configuration_writer.rb +40 -0
  36. data/lib/core/yml_writers/yml_java_api_resource_writer.rb +348 -0
  37. data/lib/core/yml_writers/yml_java_cron_type_writer.rb +113 -0
  38. data/lib/core/yml_writers/yml_java_css_dependency_writer.rb +59 -0
  39. data/lib/core/yml_writers/yml_java_dao_writer.rb +364 -0
  40. data/lib/core/yml_writers/yml_java_dto_writer.rb +251 -0
  41. data/lib/core/yml_writers/yml_java_embedded_object_writer.rb +968 -0
  42. data/lib/core/yml_writers/yml_java_enum_writer.rb +161 -0
  43. data/lib/core/yml_writers/yml_java_js_dependency_writer.rb +59 -0
  44. data/lib/core/yml_writers/yml_java_message_type_writer.rb +106 -0
  45. data/lib/core/yml_writers/yml_java_meta_writer.rb +173 -0
  46. data/lib/core/yml_writers/yml_java_model_writer.rb +510 -0
  47. data/lib/core/yml_writers/yml_java_pom_writer.rb +1050 -0
  48. data/lib/core/yml_writers/yml_java_resource_data_writer.rb +251 -0
  49. data/lib/core/yml_writers/yml_java_sdk_writer.rb +732 -0
  50. data/lib/core/yml_writers/yml_java_validator_writer.rb +280 -0
  51. data/lib/core/yml_writers/yml_java_worker_writer.rb +81 -0
  52. data/lib/core/yml_writers/yml_sql_structure_writer.rb +307 -0
  53. data/lib/core/yml_writers/yml_sql_template_writer.rb +243 -0
  54. data/lib/core/yml_writers/yml_vue_service_writer.rb +170 -0
  55. data/lib/core/yml_writers/yml_writer_base.rb +114 -0
  56. data/lib/routes/api_list.rb +35 -0
  57. data/lib/routes/api_meta.rb +59 -0
  58. data/lib/routes/build.rb +46 -0
  59. data/lib/routes/create/create_api.rb +35 -0
  60. data/lib/routes/create/create_ui.rb +84 -0
  61. data/lib/routes/export.rb +56 -0
  62. data/lib/routes/generate/generate_api.rb +225 -0
  63. data/lib/routes/generate/generate_img_favicon.rb +56 -0
  64. data/lib/routes/generate/generate_img_landing.rb +94 -0
  65. data/lib/routes/generate/generate_lambda.rb +43 -0
  66. data/lib/routes/lint.rb +35 -0
  67. data/lib/routes/mysql_reset.rb +43 -0
  68. data/lib/routes/release_blufin.rb +351 -0
  69. data/lib/routes/run.rb +35 -0
  70. data/lib/version.rb +1 -0
  71. data/opt/README.MD +2 -0
  72. data/opt/config/schema.yml +73 -0
  73. data/opt/config/template.yml +25 -0
  74. data/opt/sql/data/config/data-client.sql +7 -0
  75. data/opt/sql/data/config/data-db-configuration-property.sql +47 -0
  76. data/opt/sql/data/config/data-db-configuration.sql +9 -0
  77. data/opt/sql/data/config/data-db.sql +175 -0
  78. data/opt/sql/data/config/data-profile-api.sql +47 -0
  79. data/opt/sql/data/config/data-profile-cron.sql +0 -0
  80. data/opt/sql/data/config/data-profile-worker.sql +0 -0
  81. data/opt/sql/data/config/data-profile.sql +87 -0
  82. data/opt/sql/data/config/data-project.sql +95 -0
  83. data/opt/sql/structure/blufin-master-structure-fks.sql +65 -0
  84. data/opt/sql/structure/blufin-master-structure.sql +97 -0
  85. data/opt/sql/structure/blufin-mock-structure-fks.sql +38 -0
  86. data/opt/sql/structure/blufin-mock-structure.sql +98 -0
  87. data/opt/sql/templates/config/template-client.sql +7 -0
  88. data/opt/sql/templates/config/template-db-configuration-property.sql +11 -0
  89. data/opt/sql/templates/config/template-db-configuration.sql +9 -0
  90. data/opt/sql/templates/config/template-db.sql +21 -0
  91. data/opt/sql/templates/config/template-profile-api.sql +11 -0
  92. data/opt/sql/templates/config/template-profile-cron.sql +7 -0
  93. data/opt/sql/templates/config/template-profile-worker.sql +7 -0
  94. data/opt/sql/templates/config/template-profile.sql +21 -0
  95. data/opt/sql/templates/config/template-project.sql +23 -0
  96. data/opt/yml/api/schema/config/client.yml +14 -0
  97. data/opt/yml/api/schema/config/db.yml +45 -0
  98. data/opt/yml/api/schema/config/db_configuration.yml +22 -0
  99. data/opt/yml/api/schema/config/db_configuration_property.yml +22 -0
  100. data/opt/yml/api/schema/config/profile.yml +53 -0
  101. data/opt/yml/api/schema/config/profile_api.yml +22 -0
  102. data/opt/yml/api/schema/config/profile_cron.yml +14 -0
  103. data/opt/yml/api/schema/config/profile_worker.yml +14 -0
  104. data/opt/yml/api/schema/config/project.yml +48 -0
  105. data/opt/yml/api/schema/mock/mock.yml +99 -0
  106. data/opt/yml/api/schema/mock/mock_nested_if_enum.yml +16 -0
  107. data/opt/yml/api/schema/mock/mock_nested_if_enum_system.yml +16 -0
  108. data/opt/yml/api/schema/mock/mock_nested_linked.yml +43 -0
  109. data/opt/yml/api/schema/mock/mock_nested_multiple.yml +61 -0
  110. data/opt/yml/api/schema/mock/mock_nested_single.yml +67 -0
  111. data/opt/yml/api/schema/mock/mock_nested_single_super_deep.yml +32 -0
  112. data/opt/yml/api/schema/mock/mock_nested_single_super_super_deep.yml +17 -0
  113. metadata +240 -0
@@ -0,0 +1,115 @@
1
+ require 'date'
2
+
3
+ module Blufin
4
+
5
+ class YmlCacheHandler
6
+
7
+ FORMAT_EXTENSION = '.txt'
8
+ FORMAT_DATE = '%Y-%d-%m-%H-%M-%S'
9
+
10
+ CONFIG = 'config'
11
+ SCHEMA_CONFIG = 'schema-config'
12
+ SCHEMA_DATA = 'schema-data'
13
+ SCHEMA_DESCRIPTIONS = 'schema-descriptions'
14
+ SCHEMA_FKS = 'schema-fks'
15
+ SCHEMA_FKS_DEPENDENCIES = 'schema-fks-dependencies'
16
+ SCHEMA_FKS_PLACEHOLDERS = 'schema-fks-placeholders'
17
+ SCHEMA_FKS_LINKS = 'schema-fks-links'
18
+ SCHEMA_RESOURCES = 'schema-resources'
19
+
20
+ VALID_KEYS = [
21
+ CONFIG,
22
+ SCHEMA_CONFIG,
23
+ SCHEMA_DATA,
24
+ SCHEMA_DESCRIPTIONS,
25
+ SCHEMA_FKS,
26
+ SCHEMA_FKS_DEPENDENCIES,
27
+ SCHEMA_FKS_PLACEHOLDERS,
28
+ SCHEMA_FKS_LINKS,
29
+ SCHEMA_RESOURCES
30
+ ]
31
+
32
+ KEY_DATE = 'date'
33
+ KEY_DATA = 'data'
34
+
35
+ # Stores a Yaml HASH.
36
+ # @return void
37
+ def self.store(site, key, data)
38
+
39
+ Blufin::SiteResolver::validate_site(site)
40
+
41
+ validate_key(key)
42
+ delete_pre_existing_cache_files(site, key)
43
+
44
+ Blufin::Files::write_file_string("#{get_cache_directory(site)}/#{key}-#{get_timestamp}#{FORMAT_EXTENSION}", data.inspect)
45
+
46
+ end
47
+
48
+ # Retrieves a Yaml HASH.
49
+ # @return Hash
50
+ def self.get(site, key, with_date = false)
51
+
52
+ files = get_files_for_key(site, key)
53
+
54
+ # Throw crude error if cache file doesn't exist.
55
+ # TODO - This currently throws RunTimeError but should ideally run 'blufin s g' or something to rebuild the cache automatically...
56
+ raise RuntimeError, "Cache file for key '#{key}' doesn't exist. Please run: #{Blufin::Terminal::format_command("blufin s g #{site}")}" unless files.any?
57
+
58
+ # Get the last file -- although there should never be more than 1.
59
+ file = files[files.length - 1]
60
+
61
+ date = File.basename(file).gsub("#{key}-", '').gsub(FORMAT_EXTENSION, '')
62
+ date = DateTime.strptime(date, FORMAT_DATE)
63
+ date = date.strftime("%A \xe2\x80\x94 %B %d [%H:%M:%S]")
64
+
65
+ hash = {}
66
+
67
+ eval("hash = #{Blufin::Files::read_file(file)[0]}")
68
+
69
+ return with_date ? { KEY_DATE => date.to_s, KEY_DATA => hash } : hash
70
+
71
+ end
72
+
73
+ private
74
+
75
+ # Makes sure the 'key' is a constant within this class.
76
+ # @return void
77
+ def self.validate_key(key)
78
+ raise RuntimeError, "Invalid YmlCacheHandler key: #{key}" unless VALID_KEYS.include?(key)
79
+ end
80
+
81
+ # Removes any pre-existing cache files from the /tmp dir.
82
+ # @return void
83
+ def self.delete_pre_existing_cache_files(site, key)
84
+ get_files_for_key(site, key).each do |file|
85
+ Blufin::Files::delete_file(file)
86
+ end
87
+ end
88
+
89
+ # Gets an Array of files for specific key.
90
+ # @return Array
91
+ def self.get_files_for_key(site, key)
92
+ files_return = []
93
+ Blufin::Files::get_files_in_dir(get_cache_directory(site)).each do |file|
94
+ files_return << file if File.basename(file) =~ /\A#{key}-[0-9-]+#{FORMAT_EXTENSION}\z/
95
+ end
96
+ files_return
97
+ end
98
+
99
+ # Get the cache directory.
100
+ # @return String
101
+ def self.get_cache_directory(site)
102
+ cache_directory = "/tmp/cache-#{Blufin::SiteResolver::get_site_name(site)}/"
103
+ Blufin::Files::create_directory(cache_directory) unless Blufin::Files::path_exists(cache_directory)
104
+ cache_directory
105
+ end
106
+
107
+ # Get a timestamp of the current time.
108
+ # @return String
109
+ def self.get_timestamp
110
+ Time.now.strftime(FORMAT_DATE)
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,487 @@
1
+ module Blufin
2
+
3
+ class YmlCommon
4
+
5
+ @@enum_scanner = nil
6
+
7
+ # Return TRUE if file is .yml -- FALSE if not.
8
+ # @return boolean
9
+ def self.is_yml_file(file_path)
10
+ File.extname(file_path).downcase == '.yml'
11
+ end
12
+
13
+ # Returns nil on success, otherwise an array of invalid keys.
14
+ # @return nil|Array
15
+ def self.validate_keys(key_set, valid_keys_as_array)
16
+ invalid_keys = []
17
+ key_set.each do |key|
18
+ invalid_keys << key unless valid_keys_as_array.include?(key)
19
+ end
20
+ return invalid_keys if invalid_keys.any?
21
+ end
22
+
23
+ # Returns TYPE_ENUM, TYPE_ENUM_CUSTOM or TYPE_ENUM_SYSTEM from ENUM('a','b') string.
24
+ # @return String
25
+ def self.enum_type_extractor(enum_string)
26
+ if enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM
27
+ Blufin::YmlSchemaValidator::TYPE_ENUM
28
+ elsif enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM_CUSTOM
29
+ Blufin::YmlSchemaValidator::TYPE_ENUM_CUSTOM
30
+ elsif enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM_SYSTEM
31
+ Blufin::YmlSchemaValidator::TYPE_ENUM_SYSTEM
32
+ else
33
+ raise RuntimeError, "'enum_string' doesn't match regex --> #{enum_string}"
34
+ end
35
+ end
36
+
37
+ # Returns Array ['a','b'] from ENUM('a','b')
38
+ # @return Array
39
+ def self.enum_value_extractor(enum_string, site)
40
+ if enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM
41
+ enum_string = enum_string.gsub(/\A#{Blufin::YmlSchemaValidator::TYPE_ENUM}\(/, '').gsub(/\)\z/, '')
42
+ enum_array = enum_string.split(',')
43
+ enum_array = enum_array.map { |value|
44
+ value.gsub!(/\A'/, '').gsub!(/'\z/, '') if value.is_a?(String) && value != ''
45
+ }
46
+ return enum_array
47
+ elsif enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM_CUSTOM
48
+ enum_array = []
49
+ enum_string = enum_string.gsub(/\A#{Blufin::YmlSchemaValidator::TYPE_ENUM_CUSTOM}\(/, '').gsub(/\)\z/, '').gsub(/\A'/, '').gsub(/'\z/, '')
50
+ enum_custom_all = get_enum_scanner(site).get_custom_enums
51
+ enum_array = enum_custom_all[enum_string] if enum_custom_all.has_key?(enum_string)
52
+ return enum_array
53
+ elsif enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM_SYSTEM
54
+ enum_array = []
55
+ enum_string = enum_string.gsub(/\A#{Blufin::YmlSchemaValidator::TYPE_ENUM_SYSTEM}\(/, '').gsub(/\)\z/, '').gsub(/\A'/, '').gsub(/'\z/, '')
56
+ enum_system_all = get_enum_scanner(site).get_system_enums
57
+ enum_array = enum_system_all[enum_string] if enum_system_all.has_key?(enum_string)
58
+ return enum_array
59
+ else
60
+ raise RuntimeError, "'enum_string' doesn't match regex --> #{enum_string}"
61
+ end
62
+ end
63
+
64
+ # Returns Array 'Measure' from ENUM_CUSTOM('Measure')
65
+ # @return Array
66
+ def self.enum_name_extractor(enum_string)
67
+ if enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM_CUSTOM
68
+ return enum_string.gsub(/\A#{Blufin::YmlSchemaValidator::TYPE_ENUM_CUSTOM}\(/, '').gsub(/\)\z/, '').gsub("'", '')
69
+ elsif enum_string =~ Blufin::YmlSchemaValidator::REGEX_ENUM_SYSTEM
70
+ return enum_string.gsub(/\A#{Blufin::YmlSchemaValidator::TYPE_ENUM_SYSTEM}\(/, '').gsub(/\)\z/, '').gsub("'", '')
71
+ else
72
+ raise RuntimeError, "'#{enum_string}' doesn't match regex for ENUM, ENUM_CUSTOM or ENUM_SYSTEM."
73
+ end
74
+ end
75
+
76
+ # Abstract method for extracting flags used in Schema definition.
77
+ # @return Blufin::YmlSchemaFlags
78
+ def self.extract_flags(flags)
79
+ raise RuntimeError, "Expected String, instead got:#{flags.class}" unless flags.is_a?(String)
80
+ errors = []
81
+ sort_order = 1
82
+ definition_order = {}
83
+ flags_object = Blufin::YmlSchemaFlags.new
84
+ flags_object.flags_raw = flags
85
+ flags.split(' ').each do |flag|
86
+ flag_invalid = false
87
+ case flag
88
+ when Blufin::YmlSchemaValidator::FLAG_PRIMARY_KEY
89
+ flags_object.primary_key = true
90
+ flags_object.primary_key_sort_order = sort_order
91
+ when Blufin::YmlSchemaValidator::FLAG_INDEX
92
+ flags_object.index = true
93
+ flags_object.index_sort_order = sort_order
94
+ when Blufin::YmlSchemaValidator::FLAG_NULLABLE
95
+ flags_object.nullable = true
96
+ flags_object.nullable_sort_order = sort_order
97
+ when Blufin::YmlSchemaValidator::FLAG_UNIQUE
98
+ flags_object.unique = true
99
+ flags_object.unique_sort_order = sort_order
100
+ else
101
+ if flag =~ /\A#{Blufin::YmlSchemaValidator::FLAG_AUTO_INCREMENT}\z/
102
+ flags_object.auto_increment = true
103
+ flags_object.auto_increment_amount = nil
104
+ flags_object.auto_increment_sort_order = sort_order
105
+ elsif flag =~ /\A#{Blufin::YmlSchemaValidator::FLAG_AUTO_INCREMENT}\(\d{1,10}\)\z/
106
+ auto_increment_amount = flag.match(/\(\d{1,10}\)/)
107
+ auto_increment_amount = auto_increment_amount[0].gsub('(', '').gsub(')', '')
108
+ flags_object.auto_increment = true
109
+ flags_object.auto_increment_amount = auto_increment_amount
110
+ flags_object.auto_increment_sort_order = sort_order
111
+ else
112
+ errors << ["Invalid 'flag' value.", flag]
113
+ flag_invalid = true
114
+ end
115
+ end
116
+ unless flag_invalid
117
+ definition_order[flag] = sort_order
118
+ sort_order = sort_order + 1
119
+ end
120
+ end
121
+ flags_object.definition_order = definition_order
122
+ [flags_object, errors]
123
+ end
124
+
125
+ # Takes something like app.field[] and returns -> field.
126
+ # @return String
127
+ def self.extract_field_name(field)
128
+ field.gsub(/\A(#{Blufin::YmlSchemaValidator::VALID_SCHEMAS_REGEX})\./, '').gsub(/(\[\]|\[link\])\z/, '')
129
+ end
130
+
131
+ # Extracts 13, 2 from DECIMAL(13,2)
132
+ # @return List
133
+ def self.decimal_extract_values(type)
134
+ decimal_amount = Blufin::Strings::extract_using_regex(type, /\(\d{1,2},\d{1,2}\)\z/, %w{( )})
135
+ decimal_amount = decimal_amount.split(',')
136
+ [decimal_amount[0].to_i, decimal_amount[1].to_i]
137
+ end
138
+
139
+ # Extracts 45 from VARCHAR(45)
140
+ # @return List
141
+ def self.varchar_extract_max_length(type)
142
+ Blufin::Strings::extract_using_regex(type, /\(\d{1,3}\)\z/, %w{( )})
143
+ end
144
+
145
+ # Removes formatting (such as asterisks '*') from description strings.
146
+ # @return String
147
+ def self.description_without_formatting(description)
148
+ description.gsub(/\s\*/, ' ').gsub(/\*\s/, ' ')
149
+ end
150
+
151
+ # Determines what a 'LINK' table should be named,
152
+ # @return String
153
+ def self.get_link_table_name(source_table, column_name)
154
+ column = column_name.dup.gsub("[#{Blufin::YmlSchemaValidator::LINK}]", '')
155
+ raise RuntimeError, "Expected clean column name without brackets, instead got:#{column}" unless column[-1, 1] =~ /[a-z]/i
156
+ target_table = column.split('.')[1]
157
+ "#{source_table}_to_#{target_table}_link"
158
+ end
159
+
160
+ # Return TRUE if value is nil, false or empty string.
161
+ # @return boolean
162
+ def self.is_empty(value)
163
+ value.nil? || value == false || value == ''
164
+ end
165
+
166
+ # Converts /Users/Albert/Repos/repos-blufin/[site-name]/yml/worker/amazon.yml -> amazon.yml
167
+ # @return String
168
+ def self.convert_filename_to_name(file)
169
+ file_split = file.split('/')
170
+ file_split[file_split.length - 1].gsub(/\.yml\z/, '')
171
+ end
172
+
173
+ # Converts Regex to string, IE: =(?-mix:\A[A-Z_]+\z) -> \A[A-Z_]+\z
174
+ def self.convert_regex_to_string(regex)
175
+ raise RuntimeError, "Expected Regex, instead got:#{regex.class}" unless regex.nil? || regex.is_a?(Regexp)
176
+ regex_string = regex.to_s
177
+ regex_string.gsub(/\A\(\?-mix:/, '').gsub(/\)\z/, '')
178
+ end
179
+
180
+ # Extracts "reference" from "/{reference}.jpg"
181
+ # @return String
182
+ def self.extract_jersey_path_reference(value)
183
+ value.gsub(/\A(.)*\{/, '').gsub(/\}(.)*\z/, '')
184
+ end
185
+
186
+ # Darkens the path and highlights the filename.
187
+ # @return String
188
+ def self.colorize_path_and_file(file, site_path)
189
+ file_split = split_to_path_file(file, site_path)
190
+ "\x1B[38;5;240m#{file_split[0].gsub(/\/\z/, '')} → \x1B[38;5;140m#{file_split[1]}"
191
+ end
192
+
193
+ # Shortens filenames by removing @site_path.
194
+ # @return String
195
+ def self.remove_site_path(path_and_file, site_path)
196
+ raise RuntimeError, "Expected String, instead got:#{path_and_file.class}" unless path_and_file.is_a?(String)
197
+ raise RuntimeError, "Expected String, instead got:#{site_path.class}" unless site_path.is_a?(String)
198
+ sp = site_path.dup
199
+ sp[0] = ''
200
+ path_and_file = path_and_file.gsub(/\A\//, '')
201
+ path_and_file.gsub("#{sp}/", '')
202
+ end
203
+
204
+ # Splits the path & filename.
205
+ # @return Array
206
+ def self.split_to_path_file(path_and_file, site_path)
207
+ raise RuntimeError, "Expected String, instead got:#{path_and_file.class}" unless path_and_file.is_a?(String)
208
+ raise RuntimeError, "Expected String, instead got:#{site_path.class}" unless site_path.is_a?(String)
209
+ sp = site_path.dup
210
+ sp[0] = ''
211
+ path = ''
212
+ file = ''
213
+ file_parts = path_and_file.strip.gsub(/\A\//, '').split('/')
214
+ file_parts.each_with_index do |part, idx|
215
+ if idx < file_parts.length - 1
216
+ path << "#{part}/"
217
+ else
218
+ file << part
219
+ end
220
+ end
221
+ [path.gsub("#{sp}/", '').gsub(/\/\z/, ''), file]
222
+ end
223
+
224
+ # Checks that a directory structure (YML directory) matches a certain criteria.
225
+ # Returns FALSE if fails, TRUE if success
226
+ # @return boolean
227
+ def self.validate_directory_structure(site_path, path, files_expected, files_optional, error_handler)
228
+ raise RuntimeError, "Expected String, instead got:#{path.class}" unless path.is_a?(String)
229
+ raise RuntimeError, "Expected Array, instead got:#{files_expected.class}" unless files_expected.is_a?(Array)
230
+ raise RuntimeError, "Expected Array, instead got:#{files_optional.class}" unless files_optional.is_a?(Array)
231
+ raise RuntimeError, "Expected YmlErrorHandler, instead got:#{error_handler.class}" unless error_handler.is_a?(Blufin::YmlErrorHandler)
232
+ path = "#{site_path}/#{path}"
233
+ current_errors = error_handler.get_error_count
234
+ files_expected = files_expected.map { |value| "#{path}/#{value}" }
235
+ files_optional = files_optional.map { |value| "#{path}/#{value}" }
236
+ files_present = []
237
+ Blufin::Files::get_files_in_dir(path).each do |file|
238
+ error_handler.add_error(Blufin::YmlErrorHandler::FILE_NOT_EXPECTED, file, nil, nil, remove_site_path(file, site_path)) unless files_expected.include?(file) || files_optional.include?(file)
239
+ files_present << file
240
+ end
241
+ files_expected.each do |file|
242
+ error_handler.add_error(Blufin::YmlErrorHandler::FILE_NOT_FOUND, file, nil, nil, remove_site_path(file, site_path)) unless files_present.include?(file)
243
+ end
244
+ current_errors == error_handler.get_error_count
245
+ end
246
+
247
+ # Checks that a file exists (and if not, creates it) and validates that it matches a basic template.
248
+ # @return void
249
+ def self.validate_file_and_contents(site, file, contents = [], contents_ignore = [], error_handler = nil, add_to_git = true)
250
+ raise RuntimeError, "Expected String, instead got:#{file.class}" unless file.is_a?(String)
251
+ raise RuntimeError, "Expected Array, instead got:#{contents.class}" unless contents.is_a?(Array)
252
+ raise RuntimeError, "Expected Array, instead got:#{contents_ignore.class}" unless contents_ignore.is_a?(Array)
253
+ raise RuntimeError, "Expected YmlErrorHandler (or nil), instead got:#{error_handler.class}" unless error_handler.is_a?(Blufin::YmlErrorHandler) || error_handler.nil?
254
+ site = Blufin::SiteResolver::validate_site(site)
255
+ site_path = Blufin::SiteResolver::get_site_location(site)
256
+ site_name = Blufin::SiteResolver::get_site_name(site)
257
+ if Blufin::Files::file_exists(file)
258
+ lines_expected = []
259
+ contents.each do |line|
260
+ unless contents_ignore.include?(line)
261
+ unless line =~ /\Aimport\s/
262
+ lines_expected << line unless line.strip == ''
263
+ end
264
+ end
265
+ end
266
+ contents = Blufin::Files::read_file(file)
267
+ contents.each do |line|
268
+ line = line.gsub("\n", '')
269
+ lines_expected.delete(line) if lines_expected.include?(line)
270
+ end
271
+ if lines_expected.length > 0 && !error_handler.nil?
272
+ lines_expected.map! { |line| "\x1B[38;5;154m#{line}" }
273
+ file = Blufin::YmlCommon::remove_site_path(file, site_path)
274
+ file = file.gsub(/(#{Blufin::Site::REGEX_APP_DIRS})\/#{site_name}-(#{Blufin::SiteServices::REGEX_JAVA})\/src\/main\/java\//, '')
275
+ error_output = ["File: \x1B[38;5;196m#{file}\x1B[0m", 'Line(s) expected but not found:']
276
+ error_output = error_output + lines_expected + [nil]
277
+ error_handler.add_error(Blufin::YmlErrorHandler::FILE_CONTENT_MISMATCH, nil, nil, nil, error_output)
278
+ end
279
+ else
280
+ if file =~ /\.java$/
281
+ Blufin::Files::write_file_java(file, contents, Blufin::Files::JAVA_AUTO_GENERATED_ONCE)
282
+ else
283
+ Blufin::Files::write_file(file, contents)
284
+ end
285
+ Blufin::Terminal::command("git add #{file}", site_path, false, false) if add_to_git
286
+ Blufin::Terminal::output(colorize_path_and_file(file, site_path), Blufin::Terminal::MSG_GENERATED)
287
+ end
288
+
289
+ end
290
+
291
+ # Converts an Array of lines to a string (for easier gsub replacement).
292
+ # @return String
293
+ def self.convert_line_array_to_string(array_of_lines)
294
+ raise RuntimeError, "Expected Array of lines, instead got: #{array_of_lines.class}" unless array_of_lines.is_a?(Array)
295
+ string = ''
296
+ array_of_lines.each_with_index do |line, idx|
297
+ newline_or_not = (idx == (array_of_lines.length - 1)) ? '' : "\n"
298
+ string += "#{line}#{newline_or_not}"
299
+ end
300
+ string
301
+ end
302
+
303
+ # Converts a string to an Array of lines to a string.
304
+ # @return String
305
+ def self.convert_string_to_line_array(string)
306
+ raise RuntimeError, "Expected String, instead got: #{string.class}" unless string.is_a?(String)
307
+ array_of_lines = []
308
+ string.split("\n").each { |line| array_of_lines << line.gsub("\n", '') }
309
+ array_of_lines
310
+ end
311
+
312
+ # Content Hash is and Hash of Arrays where the inner Array consists of:
313
+ #
314
+ # Key = Snake Cased String (such as: amazon, ebay, magento, etc).
315
+ # Value[0] = Contents -> for Blufin::YmlCommon::validate_file_and_contents()
316
+ # Value[1] = Contents to Ignore -> for Blufin::YmlCommon::validate_file_and_contents()
317
+ #
318
+ # Path parameter is where the root of where the directories will be, so if message handlers (for example) live at the following location:
319
+ # ../app-infrastructure/{site-name}-worker/src/main/java/io/{site-name}/worker/messages/amazon/AmazonMessageHandler.java
320
+ #
321
+ # Then path would be:
322
+ # ../app-infrastructure/{site-name}-worker/src/main/java/io/{site-name}/worker/messages
323
+ #
324
+ # @return void
325
+ def self.create_boilerplate_files(content_hash, path, site, error_handler, default_nested_paths = %w(data logic))
326
+
327
+ raise RuntimeError, "Expected Hash, instead got: #{content_hash.class}" unless content_hash.is_a?(Hash)
328
+ raise RuntimeError, "Expected String, instead got: #{path.class}" unless path.is_a?(String)
329
+ raise RuntimeError, "Expected YmlErrorHandler (or nil), instead got:#{error_handler.class}" unless error_handler.is_a?(Blufin::YmlErrorHandler) || error_handler.nil?
330
+ raise RuntimeError, "Expected Array, instead got: #{default_nested_paths.class}" unless default_nested_paths.is_a?(Array)
331
+
332
+ site = Blufin::SiteResolver::validate_site(site)
333
+ site_path = Blufin::SiteResolver::get_site_location(site)
334
+
335
+ path = path.gsub(/\/\z/, '')
336
+ path_last = path.split('/')
337
+ path_last = path_last[path_last.length - 1]
338
+
339
+ expected_paths = []
340
+
341
+ content_hash.each do |key, ca|
342
+
343
+ key_camel_cased_lower = Blufin::Strings::snake_case_to_camel_case_lower(key)
344
+
345
+ contents = ca[0]
346
+ contents_ignore = ca[1]
347
+ path_inner = "#{path}/#{key_camel_cased_lower}"
348
+ file = "#{path_inner}/#{ca[2]}"
349
+
350
+ raise RuntimeError, "Expected String, instead got: #{contents.class}" unless contents.is_a?(String)
351
+ raise RuntimeError, "Expected Array, instead got: #{contents_ignore.class}" unless contents_ignore.is_a?(Array)
352
+
353
+ expected_paths << path_inner
354
+
355
+ Blufin::YmlCommon::validate_file_and_contents(site, file, Blufin::YmlCommon::convert_string_to_line_array(contents), contents_ignore, error_handler)
356
+
357
+ # Check for Rogue files (inner).
358
+ existing_files = []
359
+ Blufin::Files::get_files_in_dir(path_inner).each do |existing_file|
360
+ begin
361
+ existing_file_parts = existing_file.split("#{path_last}/#{key_camel_cased_lower}/")
362
+ existing_file_parts = existing_file_parts[1].split('/')
363
+ next unless existing_file_parts.length == 1
364
+ existing_files << existing_file
365
+ rescue
366
+ next
367
+ end
368
+ end
369
+ existing_files.each do |existing_file|
370
+ unless existing_file == file
371
+ error_handler.add_error(Blufin::YmlErrorHandler::FILE_NOT_EXPECTED, nil, nil, nil, Blufin::YmlCommon::remove_site_path(existing_file, site_path))
372
+ end
373
+ end
374
+
375
+ # Check for Rogue directories (inner) -- and create default_nested paths (if not exist).
376
+ existing_directories = Blufin::Files::get_dirs_in_dir(path_inner)
377
+ existing_directories.each do |existing_directory|
378
+ default_nested_paths_found = false
379
+ default_nested_paths.each { |default_nested_path| default_nested_paths_found = true if existing_directory == "#{path_inner}/#{default_nested_path}" }
380
+ error_handler.add_error(Blufin::YmlErrorHandler::DIRECTORY_NOT_EXPECTED, nil, nil, nil, Blufin::YmlCommon::remove_site_path(existing_directory, site_path)) unless default_nested_paths_found
381
+ end
382
+
383
+ # Create "default_nested_path" if no exists.
384
+ default_nested_paths.each { |default_nested_path| Blufin::Files::create_directory("#{path_inner}/#{default_nested_path}") unless Blufin::Files::path_exists("#{path_inner}/#{default_nested_path}") }
385
+ end
386
+
387
+ # Check for Rogue directories.
388
+ existing_directories = Blufin::Files::get_dirs_in_dir(path)
389
+ existing_directories.each do |existing_directory|
390
+ unless expected_paths.include?(existing_directory)
391
+ error_handler.add_error(Blufin::YmlErrorHandler::DIRECTORY_NOT_EXPECTED, nil, nil, nil, Blufin::YmlCommon::remove_site_path(existing_directory, site_path))
392
+ end
393
+ end
394
+
395
+ # Check for Missing directories (in theory this will never be reached as it's created above).
396
+ expected_paths.each do |expected_path|
397
+ unless existing_directories.include?(expected_path)
398
+ error_handler.add_error(Blufin::YmlErrorHandler::DIRECTORY_NOT_FOUND, nil, nil, nil, Blufin::YmlCommon::remove_site_path(expected_path, site_path))
399
+ end
400
+ end
401
+
402
+ end
403
+
404
+ # Returns TRUE if resource has specified HTTP method, FALSE otherwise.
405
+ # @return Boolean
406
+ def self.has_http_method(http_method_name, resource_data, internal_or_oauth)
407
+ raise RuntimeError, "Expected 'http_method_name' to be [#{Blufin::YmlConfigValidator::VALID_METHODS}], instead got: #{http_method_name}" unless Blufin::YmlConfigValidator::VALID_METHODS.include?(http_method_name)
408
+ raise RuntimeError, "Expected 'internal' or 'oauth', instead got: #{internal_or_oauth}" unless [Blufin::YmlSchemaValidator::CONFIG_INTERNAL, Blufin::YmlSchemaValidator::CONFIG_OAUTH].include?(internal_or_oauth)
409
+ raise RuntimeError, "Expected Hash, instead got: #{resource_data.class}" unless resource_data.is_a?(Hash)
410
+ methods_key = (internal_or_oauth == Blufin::YmlSchemaValidator::CONFIG_INTERNAL) ? :methods_internal : :methods_oauth
411
+ if resource_data.has_key?(methods_key)
412
+ resource_data[methods_key].keys.each do |http_method|
413
+ return true if http_method_name.downcase == http_method.downcase
414
+ end
415
+ end
416
+ false
417
+ end
418
+
419
+ # Returns TRUE if resource has at least one HTTP method, FALSE otherwise.
420
+ # @return Boolean
421
+ def self.has_at_least_one_http_method(resource_data, internal_or_oauth)
422
+ raise RuntimeError, "Expected 'internal' or 'oauth', instead got: #{internal_or_oauth}" unless [Blufin::YmlSchemaValidator::CONFIG_INTERNAL, Blufin::YmlSchemaValidator::CONFIG_OAUTH].include?(internal_or_oauth)
423
+ raise RuntimeError, "Expected Hash, instead got: #{resource_data.class}" unless resource_data.is_a?(Hash)
424
+ methods_key = (internal_or_oauth == Blufin::YmlSchemaValidator::CONFIG_INTERNAL) ? :methods_internal : :methods_oauth
425
+ if resource_data.has_key?(methods_key)
426
+ resource_data[methods_key].keys.each do |http_method|
427
+ if [
428
+ Blufin::YmlConfigValidator::GET,
429
+ Blufin::YmlConfigValidator::POST,
430
+ Blufin::YmlConfigValidator::PATCH,
431
+ Blufin::YmlConfigValidator::DELETE
432
+ ].include?(http_method)
433
+ return true
434
+ else
435
+ raise RuntimeError, "Un-handled HTTP method: #{http_method}"
436
+ end
437
+ end
438
+ end
439
+ false
440
+ end
441
+
442
+ # Extracts the <groupID>, <artifactId> & <version> from -> [{"group-id"=>"com.zaxxer"}, {"artifact-id"=>"HikariCP"}, {"version"=>"3.2.0-BLUFIN"}]
443
+ # @return Hash
444
+ def self.extract_group_artifact_version_from_array(array)
445
+ raise RuntimeError, "Expected Array, instead got: #{array.class}" unless array.is_a?(Array)
446
+ obj = {}
447
+ array.each do |fragment|
448
+ raise RuntimeError, "Expected Hash, instead got: #{fragment.class}" unless fragment.is_a?(Hash)
449
+ obj[Blufin::YmlMavenValidator::DEPENDENCIES_GROUP_ID] = fragment[Blufin::YmlMavenValidator::DEPENDENCIES_GROUP_ID] if fragment.has_key?(Blufin::YmlMavenValidator::DEPENDENCIES_GROUP_ID)
450
+ obj[Blufin::YmlMavenValidator::DEPENDENCIES_ARTIFACT_ID] = fragment[Blufin::YmlMavenValidator::DEPENDENCIES_ARTIFACT_ID] if fragment.has_key?(Blufin::YmlMavenValidator::DEPENDENCIES_ARTIFACT_ID)
451
+ obj[Blufin::YmlMavenValidator::DEPENDENCIES_VERSION] = fragment[Blufin::YmlMavenValidator::DEPENDENCIES_VERSION] if fragment.has_key?(Blufin::YmlMavenValidator::DEPENDENCIES_VERSION)
452
+ end
453
+ obj
454
+ end
455
+
456
+ # Extracts OBJECT, OBJECT_LIST or nil from @schema_data Hash.
457
+ # @return String
458
+ def self.extract_child_type_from_schema_data(schema_data, schema, table)
459
+ ct = extract_child_type_from_schema_data_for_java(schema_data, schema, table)
460
+ ct.nil? ? nil : ct.split('.')[1]
461
+ end
462
+
463
+ # Extracts DataType.OBJECT, DataType.OBJECT_LIST or nil from @schema_data Hash.
464
+ # @return String
465
+ def self.extract_child_type_from_schema_data_for_java(schema_data, schema, table)
466
+ schema_data[schema][table].each do |column_name, column_data|
467
+ if column_data.has_key?(Blufin::YmlSchemaValidator::CHILD_TYPE)
468
+ return column_data[Blufin::YmlSchemaValidator::CHILD_TYPE]
469
+ end
470
+ end
471
+ nil
472
+ end
473
+
474
+ private
475
+
476
+ # Returns a cached instance of the ENUM scanner.
477
+ # @return Object
478
+ def self.get_enum_scanner(site)
479
+ if @@enum_scanner.nil?
480
+ @@enum_scanner = Blufin::ScannerJavaEnums.new(site)
481
+ end
482
+ @@enum_scanner
483
+ end
484
+
485
+ end
486
+
487
+ end