blufin 0.1.0

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