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.
- checksums.yaml +7 -0
- data/bin/bf +5 -0
- data/bin/blufin +5 -0
- data/lib/blufin.rb +245 -0
- data/lib/core/code_scanners/common/scanner_common.rb +83 -0
- data/lib/core/code_scanners/common/scanner_java.rb +106 -0
- data/lib/core/code_scanners/scanner_java_embedded_objects.rb +386 -0
- data/lib/core/code_scanners/scanner_java_enums.rb +125 -0
- data/lib/core/code_scanners/scanner_java_source.rb +29 -0
- data/lib/core/code_scanners/scanner_java_tests.rb +157 -0
- data/lib/core/error_handling/schema_error.rb +9 -0
- data/lib/core/error_handling/sql_error.rb +21 -0
- data/lib/core/error_handling/sql_error_handler.rb +149 -0
- data/lib/core/error_handling/yml_error.rb +21 -0
- data/lib/core/error_handling/yml_error_handler.rb +437 -0
- data/lib/core/mysql.rb +347 -0
- data/lib/core/opt.rb +21 -0
- data/lib/core/site/site.rb +26 -0
- data/lib/core/site/site_auth.rb +88 -0
- data/lib/core/site/site_embedded.rb +27 -0
- data/lib/core/site/site_ports.rb +9 -0
- data/lib/core/site/site_resolver.rb +276 -0
- data/lib/core/site/site_services.rb +162 -0
- data/lib/core/site/site_ui.rb +16 -0
- data/lib/core/yml/config/yml_config_validator.rb +219 -0
- data/lib/core/yml/maven/yml_maven_validator.rb +1132 -0
- data/lib/core/yml/resource/yml_resource_validator.rb +154 -0
- data/lib/core/yml/schema/yml_schema_flags.rb +9 -0
- data/lib/core/yml/schema/yml_schema_validator.rb +1850 -0
- data/lib/core/yml/yml_cache_handler.rb +115 -0
- data/lib/core/yml/yml_common.rb +487 -0
- data/lib/core/yml/yml_meta_writer_base.rb +300 -0
- data/lib/core/yml/yml_outputter.rb +307 -0
- data/lib/core/yml/yml_validator_base.rb +630 -0
- data/lib/core/yml_writers/yml_configuration_writer.rb +40 -0
- data/lib/core/yml_writers/yml_java_api_resource_writer.rb +348 -0
- data/lib/core/yml_writers/yml_java_cron_type_writer.rb +113 -0
- data/lib/core/yml_writers/yml_java_css_dependency_writer.rb +59 -0
- data/lib/core/yml_writers/yml_java_dao_writer.rb +364 -0
- data/lib/core/yml_writers/yml_java_dto_writer.rb +251 -0
- data/lib/core/yml_writers/yml_java_embedded_object_writer.rb +968 -0
- data/lib/core/yml_writers/yml_java_enum_writer.rb +161 -0
- data/lib/core/yml_writers/yml_java_js_dependency_writer.rb +59 -0
- data/lib/core/yml_writers/yml_java_message_type_writer.rb +106 -0
- data/lib/core/yml_writers/yml_java_meta_writer.rb +173 -0
- data/lib/core/yml_writers/yml_java_model_writer.rb +510 -0
- data/lib/core/yml_writers/yml_java_pom_writer.rb +1050 -0
- data/lib/core/yml_writers/yml_java_resource_data_writer.rb +251 -0
- data/lib/core/yml_writers/yml_java_sdk_writer.rb +732 -0
- data/lib/core/yml_writers/yml_java_validator_writer.rb +280 -0
- data/lib/core/yml_writers/yml_java_worker_writer.rb +81 -0
- data/lib/core/yml_writers/yml_sql_structure_writer.rb +307 -0
- data/lib/core/yml_writers/yml_sql_template_writer.rb +243 -0
- data/lib/core/yml_writers/yml_vue_service_writer.rb +170 -0
- data/lib/core/yml_writers/yml_writer_base.rb +114 -0
- data/lib/routes/api_list.rb +35 -0
- data/lib/routes/api_meta.rb +59 -0
- data/lib/routes/build.rb +46 -0
- data/lib/routes/create/create_api.rb +35 -0
- data/lib/routes/create/create_ui.rb +84 -0
- data/lib/routes/export.rb +56 -0
- data/lib/routes/generate/generate_api.rb +225 -0
- data/lib/routes/generate/generate_img_favicon.rb +56 -0
- data/lib/routes/generate/generate_img_landing.rb +94 -0
- data/lib/routes/generate/generate_lambda.rb +43 -0
- data/lib/routes/lint.rb +35 -0
- data/lib/routes/mysql_reset.rb +43 -0
- data/lib/routes/release_blufin.rb +351 -0
- data/lib/routes/run.rb +35 -0
- data/lib/version.rb +1 -0
- data/opt/README.MD +2 -0
- data/opt/config/schema.yml +73 -0
- data/opt/config/template.yml +25 -0
- data/opt/sql/data/config/data-client.sql +7 -0
- data/opt/sql/data/config/data-db-configuration-property.sql +47 -0
- data/opt/sql/data/config/data-db-configuration.sql +9 -0
- data/opt/sql/data/config/data-db.sql +175 -0
- data/opt/sql/data/config/data-profile-api.sql +47 -0
- data/opt/sql/data/config/data-profile-cron.sql +0 -0
- data/opt/sql/data/config/data-profile-worker.sql +0 -0
- data/opt/sql/data/config/data-profile.sql +87 -0
- data/opt/sql/data/config/data-project.sql +95 -0
- data/opt/sql/structure/blufin-master-structure-fks.sql +65 -0
- data/opt/sql/structure/blufin-master-structure.sql +97 -0
- data/opt/sql/structure/blufin-mock-structure-fks.sql +38 -0
- data/opt/sql/structure/blufin-mock-structure.sql +98 -0
- data/opt/sql/templates/config/template-client.sql +7 -0
- data/opt/sql/templates/config/template-db-configuration-property.sql +11 -0
- data/opt/sql/templates/config/template-db-configuration.sql +9 -0
- data/opt/sql/templates/config/template-db.sql +21 -0
- data/opt/sql/templates/config/template-profile-api.sql +11 -0
- data/opt/sql/templates/config/template-profile-cron.sql +7 -0
- data/opt/sql/templates/config/template-profile-worker.sql +7 -0
- data/opt/sql/templates/config/template-profile.sql +21 -0
- data/opt/sql/templates/config/template-project.sql +23 -0
- data/opt/yml/api/schema/config/client.yml +14 -0
- data/opt/yml/api/schema/config/db.yml +45 -0
- data/opt/yml/api/schema/config/db_configuration.yml +22 -0
- data/opt/yml/api/schema/config/db_configuration_property.yml +22 -0
- data/opt/yml/api/schema/config/profile.yml +53 -0
- data/opt/yml/api/schema/config/profile_api.yml +22 -0
- data/opt/yml/api/schema/config/profile_cron.yml +14 -0
- data/opt/yml/api/schema/config/profile_worker.yml +14 -0
- data/opt/yml/api/schema/config/project.yml +48 -0
- data/opt/yml/api/schema/mock/mock.yml +99 -0
- data/opt/yml/api/schema/mock/mock_nested_if_enum.yml +16 -0
- data/opt/yml/api/schema/mock/mock_nested_if_enum_system.yml +16 -0
- data/opt/yml/api/schema/mock/mock_nested_linked.yml +43 -0
- data/opt/yml/api/schema/mock/mock_nested_multiple.yml +61 -0
- data/opt/yml/api/schema/mock/mock_nested_single.yml +67 -0
- data/opt/yml/api/schema/mock/mock_nested_single_super_deep.yml +32 -0
- data/opt/yml/api/schema/mock/mock_nested_single_super_super_deep.yml +17 -0
- 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
|