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,29 @@
|
|
|
1
|
+
module Blufin
|
|
2
|
+
|
|
3
|
+
# This class scans ALL Java classes and does general validation.
|
|
4
|
+
# Anything that doesn't fit into a sub-class will go in here.
|
|
5
|
+
class ScannerJavaSource
|
|
6
|
+
|
|
7
|
+
# @return void
|
|
8
|
+
def initialize(site, error_handler)
|
|
9
|
+
|
|
10
|
+
@site = Blufin::SiteResolver::validate_site(site)
|
|
11
|
+
@site_name = Blufin::SiteResolver::get_site_name(@site)
|
|
12
|
+
@site_path = Blufin::SiteResolver::get_site_location(@site)
|
|
13
|
+
@site_domain = Blufin::SiteResolver::get_site_domain(@site)
|
|
14
|
+
|
|
15
|
+
@error_handler = error_handler
|
|
16
|
+
|
|
17
|
+
# @all_files = Blufin::ScannerCommon::get_non_ignored_files(@site_path, ['java'], @error_handler, Blufin::Site::PATH_APP_INFRASTRUCTURE)
|
|
18
|
+
# @all_files.each do |file|
|
|
19
|
+
#
|
|
20
|
+
# class_info = Blufin::ScannerJava::scan(file, @site)
|
|
21
|
+
# puts class_info.inspect
|
|
22
|
+
#
|
|
23
|
+
# end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
module Blufin
|
|
2
|
+
|
|
3
|
+
# This class scans ALL Java classes and generates blank tests for every class which doesn't have a test.
|
|
4
|
+
# Also throws errors if 'rogue' tests exist and/or tests are named/placed incorrectly.
|
|
5
|
+
class ScannerJavaTests < Blufin::YmlWriterBase
|
|
6
|
+
|
|
7
|
+
TEMPLATE = <<TEMPLATE
|
|
8
|
+
package #{PLACEHOLDER_PACKAGE};
|
|
9
|
+
|
|
10
|
+
import org.junit.Before;
|
|
11
|
+
import org.junit.Test;
|
|
12
|
+
import org.junit.runner.RunWith;
|
|
13
|
+
import org.mockito.runners.MockitoJUnitRunner;
|
|
14
|
+
|
|
15
|
+
import static org.hamcrest.CoreMatchers.is;
|
|
16
|
+
import static org.hamcrest.MatcherAssert.assertThat;
|
|
17
|
+
|
|
18
|
+
@RunWith(MockitoJUnitRunner.class)
|
|
19
|
+
public class #{PLACEHOLDER_CLASS} {
|
|
20
|
+
|
|
21
|
+
@Before
|
|
22
|
+
public void setUp() {}
|
|
23
|
+
|
|
24
|
+
@Test
|
|
25
|
+
public void testSomething() {
|
|
26
|
+
|
|
27
|
+
assertThat(true, is(true));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
TEMPLATE
|
|
31
|
+
|
|
32
|
+
# @return void
|
|
33
|
+
def initialize(site, error_handler)
|
|
34
|
+
|
|
35
|
+
@site = Blufin::SiteResolver::validate_site(site)
|
|
36
|
+
@site_name = Blufin::SiteResolver::get_site_name(@site)
|
|
37
|
+
@site_name_camel_cased = Blufin::SiteResolver::get_site_name_camel_cased(@site)
|
|
38
|
+
@site_path = Blufin::SiteResolver::get_site_location(@site)
|
|
39
|
+
@site_domain = Blufin::SiteResolver::get_site_domain(@site)
|
|
40
|
+
|
|
41
|
+
@error_handler = error_handler
|
|
42
|
+
|
|
43
|
+
@infrastructure_classes = {}
|
|
44
|
+
@infrastructure_tests = {}
|
|
45
|
+
|
|
46
|
+
scan_blufin
|
|
47
|
+
scan_app_infrastructure
|
|
48
|
+
|
|
49
|
+
tests_create_and_validate
|
|
50
|
+
tests_rogue_check
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
# Scans the /blufin parent java library files.
|
|
57
|
+
# @return void
|
|
58
|
+
def scan_blufin
|
|
59
|
+
|
|
60
|
+
all_files = Blufin::ScannerCommon::get_non_ignored_files(Blufin::Config::get_path('Paths', 'BlufinJava'), ['java'], @error_handler)
|
|
61
|
+
all_files.each do |file|
|
|
62
|
+
|
|
63
|
+
# TODO - SCAN BLUFIN-JAVA FILES
|
|
64
|
+
|
|
65
|
+
# output_classes = []
|
|
66
|
+
# output_tests = []
|
|
67
|
+
# @infrastructure_classes.each do |key, data|
|
|
68
|
+
# flags = []
|
|
69
|
+
# flags << (data[Blufin::ScannerJava::TEST_REQUIRED] ? 'Test Required' : nil)
|
|
70
|
+
# output_classes << "\x1B[38;5;154m#{key} \x1B[38;5;240m\xe2\x80\x94 #{flags.join('|')}"
|
|
71
|
+
# end
|
|
72
|
+
# @infrastructure_tests.each do |key, data|
|
|
73
|
+
# output_tests << "\x1B[38;5;196m#{key}\x1B[0m"
|
|
74
|
+
# end
|
|
75
|
+
# Blufin::Terminal::info('Classes', output_classes)
|
|
76
|
+
# Blufin::Terminal::info('Tests', output_tests)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Scans the /app-infrastructure directory.
|
|
82
|
+
# @return void
|
|
83
|
+
def scan_app_infrastructure
|
|
84
|
+
base_path = "#{@site_name.gsub('-', '/')}\\/(#{Blufin::SiteServices::REGEX_SERVICES})"
|
|
85
|
+
all_files = Blufin::ScannerCommon::get_non_ignored_files(@site_path, ['java'], @error_handler, Blufin::Site::PATH_APP_INFRASTRUCTURE)
|
|
86
|
+
all_files.each do |file|
|
|
87
|
+
next if file =~ /#{base_path}\/#{@site_name_camel_cased}(#{Blufin::SiteServices::REGEX_SERVICES_CAPITALIZED}).java\z/
|
|
88
|
+
next if file =~ /#{base_path}\/#{@site_name_camel_cased}(#{Blufin::SiteServices::REGEX_SERVICES_CAPITALIZED})Config.java\z/
|
|
89
|
+
next if file =~ /#{base_path}\/health\//
|
|
90
|
+
next if file =~ /#{base_path}\/tasks\//
|
|
91
|
+
class_info = Blufin::ScannerJava::scan(file, @site, @error_handler)
|
|
92
|
+
next unless class_info[Blufin::ScannerJava::TYPE] == Blufin::ScannerJava::TYPE_CLASS
|
|
93
|
+
file_path_split = Blufin::YmlCommon::split_to_path_file(file, @site_path)
|
|
94
|
+
if class_info[Blufin::ScannerJava::TEST]
|
|
95
|
+
@infrastructure_tests[file_path_split[1].gsub('.java', '')] = class_info
|
|
96
|
+
else
|
|
97
|
+
@infrastructure_classes[file_path_split[1].gsub('.java', '')] = class_info
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Checks that Tests are correct.
|
|
103
|
+
# Also creates Tests for classes which need them.
|
|
104
|
+
# @return void
|
|
105
|
+
def tests_create_and_validate
|
|
106
|
+
|
|
107
|
+
@infrastructure_classes.each do |clazz, clazz_info|
|
|
108
|
+
|
|
109
|
+
# TODO - TESTS SHOULD NOT HAVE @AutoGenerated + @TestNotSomething annotations... 21-02-2017
|
|
110
|
+
|
|
111
|
+
if clazz_info[Blufin::ScannerJava::TEST_REQUIRED]
|
|
112
|
+
test_name = "#{clazz}Test"
|
|
113
|
+
file = "#{@site_path}/#{clazz_info[Blufin::ScannerJava::PATH]}/#{test_name}.java"
|
|
114
|
+
file = Blufin::ScannerCommon::swap_classpath_for_testpath(@site, file)
|
|
115
|
+
contents = TEMPLATE
|
|
116
|
+
contents = contents.gsub(PLACEHOLDER_PACKAGE, get_package_from_file(@site, file))
|
|
117
|
+
contents = contents.gsub(PLACEHOLDER_CLASS, test_name)
|
|
118
|
+
contents_ignore = [
|
|
119
|
+
'import org.junit.Before;',
|
|
120
|
+
'import static org.hamcrest.MatcherAssert.assertThat;',
|
|
121
|
+
'import static org.hamcrest.core.Is.is;',
|
|
122
|
+
'import static org.hamcrest.CoreMatchers.is;',
|
|
123
|
+
'import static org.hamcrest.MatcherAssert.assertThat;',
|
|
124
|
+
' @Before',
|
|
125
|
+
' public void setUp() {}',
|
|
126
|
+
' public void testSomething() {',
|
|
127
|
+
' assertThat(true, is(true));'
|
|
128
|
+
]
|
|
129
|
+
Blufin::YmlCommon::validate_file_and_contents(@site, file, Blufin::YmlCommon::convert_string_to_line_array(contents), contents_ignore, @error_handler)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Check for Rogue Tests?
|
|
137
|
+
# @return void
|
|
138
|
+
def tests_rogue_check
|
|
139
|
+
|
|
140
|
+
@infrastructure_tests.each do |clazz, test_info|
|
|
141
|
+
|
|
142
|
+
file = "#{test_info[Blufin::ScannerJava::PATH]}/#{clazz}"
|
|
143
|
+
class_info = @infrastructure_classes[clazz.gsub(/Test\z/, '')]
|
|
144
|
+
|
|
145
|
+
if class_info.nil?
|
|
146
|
+
@error_handler.add_error(Blufin::YmlErrorHandler::TEST_NOT_EXPECTED, file, nil, nil, clazz) unless test_info[Blufin::ScannerJava::TEST_NOT_RELATED_TO_CLASS]
|
|
147
|
+
else
|
|
148
|
+
@error_handler.add_error(Blufin::YmlErrorHandler::TEST_NOT_EXPECTED, file, nil, nil, clazz) unless class_info[Blufin::ScannerJava::TEST_REQUIRED]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Blufin
|
|
2
|
+
|
|
3
|
+
class SqlError
|
|
4
|
+
|
|
5
|
+
attr_accessor :type, :file, :line, :multi_line_content
|
|
6
|
+
|
|
7
|
+
def initialize(type, file, line, multi_line_content)
|
|
8
|
+
|
|
9
|
+
raise RuntimeError, "multi_line_content must be either nil or Array, you passed: #{multi_line_content.class}" unless multi_line_content.nil? || multi_line_content.is_a?(Array)
|
|
10
|
+
|
|
11
|
+
@type = type
|
|
12
|
+
@file = file
|
|
13
|
+
@line = line
|
|
14
|
+
|
|
15
|
+
@multi_line_content = multi_line_content
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
module Blufin
|
|
2
|
+
|
|
3
|
+
class SqlErrorHandler
|
|
4
|
+
|
|
5
|
+
ERROR_SQL_REGEX_MISMATCH = 100
|
|
6
|
+
ERROR_SQL_SCHEMA_MISMATCH = 101
|
|
7
|
+
ERROR_SQL_STATEMENT_NOT_EXPECTED = 102
|
|
8
|
+
|
|
9
|
+
# Returns a Hash of valid error types with titles/descriptions.
|
|
10
|
+
# Moved to top of file for easier programming.
|
|
11
|
+
# @return Hash
|
|
12
|
+
def error_type_meta
|
|
13
|
+
{
|
|
14
|
+
ERROR_SQL_REGEX_MISMATCH => ['SQL DATA - REGEX MISMATCH', "Line does not match expected pattern \xe2\x80\x94 please check your formatting."],
|
|
15
|
+
ERROR_SQL_SCHEMA_MISMATCH => ['SQL DATA - SCHEMA MISMATCH', "Field(s) within a SQL INSERT statement don't match the actual schema."],
|
|
16
|
+
ERROR_SQL_STATEMENT_NOT_EXPECTED => ['SQL DATA - STATEMENT NOT EXPECTED', 'Statement matches REGEX but was not expected in this part of the file.']
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Initializes the Error Handler.
|
|
21
|
+
# @return void
|
|
22
|
+
def initialize(site)
|
|
23
|
+
|
|
24
|
+
@site = Blufin::SiteResolver::validate_site(site)
|
|
25
|
+
@site_sql_path = Blufin::SiteResolver::path_to_sql(@site)
|
|
26
|
+
|
|
27
|
+
@errors = []
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Adds an error to the @error Array.
|
|
32
|
+
# @return void
|
|
33
|
+
def add_error(type, file, line, multi_line_content = nil)
|
|
34
|
+
raise RuntimeError, "Expected multi_line_content to be Array, instead got: #{multi_line_content.class}" unless multi_line_content.nil? || multi_line_content.is_a?(Array)
|
|
35
|
+
@errors << Blufin::SqlError.new(validate_error_type(type), validate_file(file), validate_line(line), multi_line_content)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Displays errors (if any) and halts the script if so.
|
|
39
|
+
# @return Boolean
|
|
40
|
+
def display_errors_if_any(exit = false)
|
|
41
|
+
|
|
42
|
+
return false unless @errors.any?
|
|
43
|
+
|
|
44
|
+
puts
|
|
45
|
+
|
|
46
|
+
errors_types = []
|
|
47
|
+
errors_sorted_by_type = {}
|
|
48
|
+
errors_meta = error_type_meta
|
|
49
|
+
errors_output = []
|
|
50
|
+
|
|
51
|
+
column_path = []
|
|
52
|
+
column_file = []
|
|
53
|
+
column_line = []
|
|
54
|
+
|
|
55
|
+
@errors.each do |error|
|
|
56
|
+
path = ''
|
|
57
|
+
file = ''
|
|
58
|
+
if errors_sorted_by_type[error.type].nil?
|
|
59
|
+
errors_types << error.type
|
|
60
|
+
errors_sorted_by_type[error.type] = []
|
|
61
|
+
end
|
|
62
|
+
errors_sorted_by_type[error.type] << error
|
|
63
|
+
file_parts = error.file.dup.strip.gsub(@site_sql_path, '').gsub(/\A\//, '').split('/')
|
|
64
|
+
file_parts.each_with_index do |part, idx|
|
|
65
|
+
if idx < file_parts.length - 1
|
|
66
|
+
path << "#{part}/"
|
|
67
|
+
else
|
|
68
|
+
file << part
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
column_path << path
|
|
72
|
+
column_file << file
|
|
73
|
+
column_line << error.line
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
column_path_max = column_path.max_by(&:length).length
|
|
77
|
+
column_file_max = column_file.max_by(&:length).length
|
|
78
|
+
column_line_max = column_line.max_by(&:length).length
|
|
79
|
+
|
|
80
|
+
multi_line_padding = (column_path_max + column_file_max + column_line_max + 6).times.collect { ' ' }.join('')
|
|
81
|
+
|
|
82
|
+
errors_types.sort!
|
|
83
|
+
errors_types.each do |error_type|
|
|
84
|
+
errors_output << "#{''.ljust(column_path_max - 5, ' ')}\x1B[38;5;231m\x1B[48;5;238m ERROR \x1B[48;5;196m #{errors_meta[error_type][0]} \x1B[0m\x1B[38;5;240m \xe2\x86\x92 \x1B[0m\x1B[38;5;221m#{errors_meta[error_type][1]}\x1B[0m"
|
|
85
|
+
errors_output << ''
|
|
86
|
+
errors_sorted_by_type[error_type].each do |error|
|
|
87
|
+
path_and_file = split_to_path_file(error.file)
|
|
88
|
+
content = Blufin::Files::read_file(error.file, error.line.dup.to_i, error.line.dup.to_i)
|
|
89
|
+
errors_output << " \x1B[38;5;240m#{path_and_file[0].rjust(column_path_max, ' ')}\x1B[38;5;196m#{path_and_file[1].ljust(column_file_max, ' ')}\x1B[0m:\x1B[38;5;76m#{error.line.ljust(column_line_max, ' ')}\x1B[0m \x1B[38;5;246m\xe2\x80\x94 \x1B[0m\x1B[48;5;240m#{content[0].gsub("\n", '')}\x1B[0m"
|
|
90
|
+
if error.multi_line_content.is_a?(Array)
|
|
91
|
+
error.multi_line_content.each do |line|
|
|
92
|
+
errors_output << "#{multi_line_padding}#{line}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
errors_output << ''
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
errors_output.each { |line| puts line }
|
|
100
|
+
|
|
101
|
+
exit 1 if exit
|
|
102
|
+
|
|
103
|
+
true
|
|
104
|
+
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
# Validate the file.
|
|
110
|
+
# @return String
|
|
111
|
+
def validate_file(file)
|
|
112
|
+
raise RuntimeError, "File does not exist: #{Blufin::Terminal::format_flag(file)}" unless Blufin::Files::file_exists(file)
|
|
113
|
+
file
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Validate the line number.
|
|
117
|
+
# @return String
|
|
118
|
+
def validate_line(line)
|
|
119
|
+
line = line.to_s.strip
|
|
120
|
+
raise RuntimeError, "Expected integer, instead got: #{line}" unless line =~ /^\d+$/
|
|
121
|
+
line
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Validate the error type.
|
|
125
|
+
# @return String
|
|
126
|
+
def validate_error_type(type)
|
|
127
|
+
raise RuntimeError, "Invalid error type: #{type} \xe2\x80\x94 perhaps you forgot to add it to the valid type array in Blufin::SqlErrorHandler ?" unless error_type_meta.keys.include?(type)
|
|
128
|
+
type
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Removes the majority of the pathname to file.
|
|
132
|
+
# @return String
|
|
133
|
+
def split_to_path_file(path_and_file)
|
|
134
|
+
path = ''
|
|
135
|
+
file = ''
|
|
136
|
+
file_parts = path_and_file.strip.gsub(@site_sql_path, '').gsub(/\A\//, '').split('/')
|
|
137
|
+
file_parts.each_with_index do |part, idx|
|
|
138
|
+
if idx < file_parts.length - 1
|
|
139
|
+
path << "#{part}/"
|
|
140
|
+
else
|
|
141
|
+
file << part
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
[path, file]
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Blufin
|
|
2
|
+
|
|
3
|
+
class YmlError
|
|
4
|
+
|
|
5
|
+
attr_accessor :type, :file, :section, :field, :message
|
|
6
|
+
|
|
7
|
+
def initialize(type, file, section, field, message)
|
|
8
|
+
|
|
9
|
+
message = [message] if message.is_a?(String)
|
|
10
|
+
|
|
11
|
+
@type = type
|
|
12
|
+
@file = file
|
|
13
|
+
@section = section
|
|
14
|
+
@field = field
|
|
15
|
+
@message = message
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
require 'columnist'
|
|
2
|
+
|
|
3
|
+
module Blufin
|
|
4
|
+
|
|
5
|
+
class YmlErrorHandler
|
|
6
|
+
|
|
7
|
+
extend Columnist
|
|
8
|
+
|
|
9
|
+
FILE_EMPTY = 1000
|
|
10
|
+
FILE_INVALID = 1005
|
|
11
|
+
FILE_NOT_FOUND = 1010
|
|
12
|
+
TEST_NOT_FOUND = 1011
|
|
13
|
+
FILE_NOT_FOUND_GITIGNORE = 1011
|
|
14
|
+
FILE_NOT_EXPECTED = 1020
|
|
15
|
+
TEST_NOT_EXPECTED = 1021
|
|
16
|
+
FILE_CONTENT_MISMATCH = 1030
|
|
17
|
+
DIRECTORY_NOT_FOUND = 1050
|
|
18
|
+
DIRECTORY_NOT_EXPECTED = 1060
|
|
19
|
+
SECTION_ORDER = 1100
|
|
20
|
+
SECTION_TITLE_REGEX = 1110
|
|
21
|
+
SECTION_VALUE_REGEX = 1111
|
|
22
|
+
SECTION_ALPHABETICAL = 1120
|
|
23
|
+
ARRAY_KEY_ROGUE = 1130
|
|
24
|
+
ARRAY_VALUE_REGEX = 1131
|
|
25
|
+
ARRAY_VALUE_BLANK = 1132
|
|
26
|
+
ARRAY_STRING_EXPECTED = 1133
|
|
27
|
+
ARRAY_HASHES_EXPECTED = 1134
|
|
28
|
+
ANNOTATIONS_ONE_OR_ANOTHER = 1150
|
|
29
|
+
ANNOTATIONS_NOT_EXPECTED = 1151
|
|
30
|
+
FIELD_MISSING_EMPTY = 1200
|
|
31
|
+
FIELD_BOOLEAN = 1210
|
|
32
|
+
FIELD_FILE = 1220
|
|
33
|
+
FIELD_TEXT_CAPITALIZED = 1230
|
|
34
|
+
FIELD_TEXT_REGEX = 1240
|
|
35
|
+
FIELD_TEXT_NOT_DEFINED = 1250
|
|
36
|
+
FIELD_ROGUE = 1260
|
|
37
|
+
FIELD_UNNECESSARY = 1270
|
|
38
|
+
FIELD_MISSING = 1279
|
|
39
|
+
FIELD_ORDER = 1280
|
|
40
|
+
FIELD_INVALID_VALUE = 1285
|
|
41
|
+
FIELD_INVALID_TYPE = 1286
|
|
42
|
+
FIELD_REQUIRES_SUB_FIELDS = 1287
|
|
43
|
+
FIELD_CANNOT_BE_BLANK = 1288
|
|
44
|
+
FIELD_NAME_TRANSIENT_CONFLICT = 1289
|
|
45
|
+
STYLE_MULTIPLE_BLANK_LINES = 1300
|
|
46
|
+
STYLE_TRAILING_BLANK_LINES = 1310
|
|
47
|
+
STYLE_UNRECOGNIZED_LINE = 1320
|
|
48
|
+
API_ENDPOINTS_MISSING = 2000
|
|
49
|
+
API_ENDPOINTS_NOT_ALLOWED = 2001
|
|
50
|
+
API_METHOD_INVALID_FOR_REQUIRED_OBJECT = 2003
|
|
51
|
+
CONFIG = 2100 # RESERVED
|
|
52
|
+
CRON = 2200 # RESERVED
|
|
53
|
+
EVENT = 2300 # RESERVED
|
|
54
|
+
SCHEMA = 2400 # RESERVED
|
|
55
|
+
WORKER_MESSAGE_TYPE_NOT_FOUND = 2500
|
|
56
|
+
DATA_NOT_ALPHABETICAL = 3000
|
|
57
|
+
MAVEN_MODULE_UNRECOGNIZED = 3100
|
|
58
|
+
MAVEN_MODULE_NOT_DEFINED = 3105
|
|
59
|
+
MAVEN_MODULE_NOT_REGISTERED = 3106
|
|
60
|
+
MAVEN_MODULE_DUPLICATE = 3110
|
|
61
|
+
MAVEN_MODULE_ORDER = 3115
|
|
62
|
+
MAVEN_MODULE_UNDEFINED_PARENT = 3116
|
|
63
|
+
MAVEN_MODULE_UNUSED_PARENT = 3117
|
|
64
|
+
|
|
65
|
+
# EVERYTHING IN THE 5000 (OR ABOVE) RANGE PRODUCES ERRORS WITHOUT SECTION/FIELD OUTPUT (AS THEY ARE GENERALLY FILE RELATED).
|
|
66
|
+
EMBEDDED_OBJECT_NOT_FOUND = 5000
|
|
67
|
+
EMBEDDED_OBJECT_NO_ANNOTATION = 5005
|
|
68
|
+
EMBEDDED_OBJECT_NO_TABLE = 5006
|
|
69
|
+
EMBEDDED_OBJECT_INVALID_SCHEMA = 5001
|
|
70
|
+
EMBEDDED_OBJECT_INVALID_NAME = 5010
|
|
71
|
+
EMBEDDED_OBJECT_INVALID_REF_REGEX = 5011
|
|
72
|
+
EMBEDDED_OBJECT_INVALID_REF_LENGTH = 5012
|
|
73
|
+
EMBEDDED_OBJECT_INVALID_ABSTRACTION = 5015
|
|
74
|
+
EMBEDDED_OBJECT_INVALID_EXTENSION = 5016
|
|
75
|
+
EMBEDDED_OBJECT_INVALID_LINE = 5018
|
|
76
|
+
EMBEDDED_OBJECT_INVALID_REGEX = 5019
|
|
77
|
+
EMBEDDED_OBJECT_DATA_NOT_FOUND = 5020
|
|
78
|
+
EMBEDDED_FIELD_MISSING = 5030
|
|
79
|
+
EMBEDDED_FIELD_WRONG_TYPE = 5031
|
|
80
|
+
EMBEDDED_ANNOTATION_MISSING = 5032
|
|
81
|
+
EMBEDDED_ANNOTATION_UNNECESSARY = 5033
|
|
82
|
+
EMBEDDED_EXTRA_VALUE_INVALID = 5034
|
|
83
|
+
EMBEDDED_DATA_TYPE_INVALID = 5035
|
|
84
|
+
EMBEDDED_FLAGS_INVALID = 5036
|
|
85
|
+
EMBEDDED_FKEY_INVALID = 5037
|
|
86
|
+
EMBEDDED_MUST_BE_ENCRYPTED = 5038
|
|
87
|
+
EMBEDDED_CONFIG_CANNOT_BE_ENCRYPTED = 5039
|
|
88
|
+
UNEXPECTED_EXCEPTION = 9999
|
|
89
|
+
|
|
90
|
+
COLOR_TITLE = 123
|
|
91
|
+
COLOR_ERROR_MESSAGE = 242
|
|
92
|
+
|
|
93
|
+
MDASH = "\xe2\x80\x94"
|
|
94
|
+
|
|
95
|
+
# Returns a Hash of valid error types with titles/descriptions.
|
|
96
|
+
# Moved to top of file for easier programming.
|
|
97
|
+
# @return Hash
|
|
98
|
+
def self.error_type_meta
|
|
99
|
+
{
|
|
100
|
+
FILE_EMPTY => ['EMPTY FILE', "The YML parser expected #{Blufin::Terminal::format_action('file(s)')} to contain data:"],
|
|
101
|
+
FILE_INVALID => ['INVALID FILE', "The YML parser was unable to parse the following #{Blufin::Terminal::format_action('file(s)')}:", 'Unable to parse: %s'],
|
|
102
|
+
FILE_NOT_FOUND => ['FILE NOT FOUND', "The YML parser expected #{Blufin::Terminal::format_action('file(s)')} to exist:", 'File not found: %s'],
|
|
103
|
+
TEST_NOT_FOUND => ['TEST NOT FOUND', "The YML parser expected #{Blufin::Terminal::format_action('tests(s)')} to exist (most likely due to missing #{Blufin::SiteServices::ANNOTATION_TEST_REQUIRED}):", 'Test not found: %s'],
|
|
104
|
+
FILE_NOT_FOUND_GITIGNORE => ['GITIGNORE NOT FOUND', "The YML parser expected #{Blufin::Terminal::format_action('.gitignore')} to exist:", 'File not found in: %s'],
|
|
105
|
+
FILE_NOT_EXPECTED => ['FILE NOT EXPECTED', "The YML parser did not expect certain #{Blufin::Terminal::format_action('file(s)')} to exist:", 'Rogue file: %s'],
|
|
106
|
+
TEST_NOT_EXPECTED => ['TEST NOT EXPECTED', "The YML parser did not expect certain #{Blufin::Terminal::format_action('test(s)')} to exist (most likely due to missing #{Blufin::SiteServices::ANNOTATION_TEST_NOT_RELATED_TO_CLASS}):", 'Rogue test: %s'],
|
|
107
|
+
FILE_CONTENT_MISMATCH => ['FILE CONTENT MISMATCH', "The YML parser expect file(s) to have certain #{Blufin::Terminal::format_action('content(s)')} but it wasn't found:"],
|
|
108
|
+
DIRECTORY_NOT_FOUND => ['DIRECTORY NOT FOUND', "The YML parser expected #{Blufin::Terminal::format_action('director(ies)')} to exist:", 'Directory not found: %s'],
|
|
109
|
+
DIRECTORY_NOT_EXPECTED => ['DIRECTORY NOT EXPECTED', "The YML parser did not expect certain #{Blufin::Terminal::format_action('director(ies)')} to exist:", 'Rogue directory: %s'],
|
|
110
|
+
SECTION_ORDER => ['SECTION ORDER MISMATCH', "The YML parser expected #{Blufin::Terminal::format_action('section(s)')} within a file to be in a certain order:"],
|
|
111
|
+
SECTION_TITLE_REGEX => ['SECTION TITLE REGEX MISMATCH', "The YML parser expected section title to match #{Blufin::Terminal::format_action('regex')}:", '%s does not match regex: %s'],
|
|
112
|
+
SECTION_VALUE_REGEX => ['SECTION VALUE REGEX MISMATCH', "The YML parser expected section value to match #{Blufin::Terminal::format_action('regex')}:", '%s does not match regex: %s'],
|
|
113
|
+
SECTION_ALPHABETICAL => ['SECTION NOT ALPHABETICAL', "The YML parser expected section keys to be in #{Blufin::Terminal::format_action('alphabetical')} order:", '%s is in the wrong position.'],
|
|
114
|
+
ARRAY_KEY_ROGUE => ['ROGUE KEY', "The YML parser did not recognize certain #{Blufin::Terminal::format_action('array key(s)')} to exist:", 'Rogue key: %s'],
|
|
115
|
+
ARRAY_VALUE_REGEX => ['ARRAY VALUE REGEX MISMATCH', "The YML parser expected section array value to match #{Blufin::Terminal::format_action('regex')}:", '%s does not match regex: %s'],
|
|
116
|
+
ARRAY_VALUE_BLANK => ['ARRAY VALUE BLANK', "#{Blufin::Terminal::format_action('Array value(s)')} cannot be blank:", 'Blank key: %s'],
|
|
117
|
+
ARRAY_STRING_EXPECTED => ['STRING ARRAY EXPECTED', "The YML parser expected an #{Blufin::Terminal::format_action('Array of Strings')}:", 'Got: %s'],
|
|
118
|
+
ARRAY_HASHES_EXPECTED => ['HASH ARRAY EXPECTED', "The YML parser expected an #{Blufin::Terminal::format_action('Array of Hashes')}:", 'Got: %s'],
|
|
119
|
+
ANNOTATIONS_ONE_OR_ANOTHER => ['ANNOTATIONS MISMATCH', "The YML parser expected either one #{Blufin::Terminal::format_action('annotation')} or another:", '%s cannot be used together.'],
|
|
120
|
+
ANNOTATIONS_NOT_EXPECTED => ['ANNOTATIONS NOT EXPECTED', "The YML parser did not expect certain #{Blufin::Terminal::format_action('annotation(s)')} to exist in file(s):", '%s cannot be used in this file.'],
|
|
121
|
+
FIELD_MISSING_EMPTY => ['MISSING/EMPTY FIELD', "The YML parser expected certain #{Blufin::Terminal::format_action('field(s)')} to exist and not be empty:"],
|
|
122
|
+
FIELD_BOOLEAN => ['INVALID VALUE - BOOLEAN', "Boolean fields must be #{Blufin::Terminal::format_action('TRUE')} or #{Blufin::Terminal::format_action('FALSE')}:"],
|
|
123
|
+
FIELD_FILE => ['INVALID VALUE - FILE NOT FOUND', "The YML parser expected certain #{Blufin::Terminal::format_action('file(s)')} to exist:", 'File not found: %s'],
|
|
124
|
+
FIELD_TEXT_CAPITALIZED => ['VALUE NOT CAPITALIZED', "The YML parser expected text in field(s) to be #{Blufin::Terminal::format_action('capitalized')}:"],
|
|
125
|
+
FIELD_TEXT_REGEX => ['VALUE REGEX MISMATCH', "The YML parser expected text in field(s) to match #{Blufin::Terminal::format_action('regex')}:", '%s does not match regex: %s'],
|
|
126
|
+
FIELD_TEXT_NOT_DEFINED => ['VALUE NOT DEFINED', "The YML parser expected text in field(s) to match pre-set #{Blufin::Terminal::format_action('values')}:"],
|
|
127
|
+
FIELD_ROGUE => ['ROGUE PROPERTY', "The YML parser did not recognize certain #{Blufin::Terminal::format_action('properties')} to exist:", 'Rogue property: %s'],
|
|
128
|
+
FIELD_UNNECESSARY => ['UNNECESSARY PROPERTY', "The following #{Blufin::Terminal::format_action('properties')} are unnecessary with the current configuration:", 'Unnecessary field: %s'],
|
|
129
|
+
FIELD_MISSING => ['PROPERTY MISSING', "The YML parser expected #{Blufin::Terminal::format_action('properties')} within a section to exist:"],
|
|
130
|
+
FIELD_ORDER => ['PROPERTY ORDER MISMATCH', "The YML parser expected #{Blufin::Terminal::format_action('properties')} within a section to be in a certain order:"],
|
|
131
|
+
FIELD_INVALID_VALUE => ['PROPERTY INVALID VALUE', "The YML parser expected properties to contain a certain #{Blufin::Terminal::format_action('value(s)')}:", 'Valid value(s): %s'],
|
|
132
|
+
FIELD_INVALID_TYPE => ['PROPERTY INVALID TYPE', "The YML parser expected properties to to be a certain #{Blufin::Terminal::format_action('type')}:"],
|
|
133
|
+
FIELD_REQUIRES_SUB_FIELDS => ['PROPERTY REQUIRES SUB-FIELDS', "The YML parser expected properties to contain #{Blufin::Terminal::format_action('sub-properties')}:"],
|
|
134
|
+
FIELD_CANNOT_BE_BLANK => ['PROPERTY CANNOT BE BLANK', "Optional properties -- if present -- #{Blufin::Terminal::format_action('cannot be empty')}:", 'Empty properties: %s'],
|
|
135
|
+
FIELD_NAME_TRANSIENT_CONFLICT => ['PROPERTY NAME TRANSIENT CONFLICT', "Property name conflicts with an auto-generated #{Blufin::Terminal::format_action('transient property')}:", 'Conflicting property: %s'],
|
|
136
|
+
STYLE_MULTIPLE_BLANK_LINES => ['UNNECESSARY BLANK LINE', "Unnecessary #{Blufin::Terminal::format_action('blank line(s)')} found in YML file(s):", 'Line: %s'],
|
|
137
|
+
STYLE_TRAILING_BLANK_LINES => ['TRAILING BLANK LINE(S)', "#{Blufin::Terminal::format_action('Trailing blank line(s)')} are not allowed in YML files:", 'Line: %s'],
|
|
138
|
+
STYLE_UNRECOGNIZED_LINE => ['UNRECOGNIZED LINE', "Something is wrong with this #{Blufin::Terminal::format_action('line')}. Perhaps check formatting, key-capitalization or whitespace?", 'Line: %s'],
|
|
139
|
+
API_ENDPOINTS_MISSING => ['API END-POINTS MISSING', "The following #{Blufin::Terminal::format_action('table(s)')} require all HTTP method end-points because they are #{Blufin::Terminal::format_action(Blufin::ScannerJavaEmbeddedObjects::EMBEDDED)}:", 'Needs GET, POST, PATCH & DELETE.'],
|
|
140
|
+
API_ENDPOINTS_NOT_ALLOWED => ['API END-POINTS NOT ALLOWED', "The following #{Blufin::Terminal::format_action('table(s)')} do not allow POST/PUT/PATCH/DELETE HTTP method(s)because they are #{Blufin::Terminal::format_action(Blufin::ScannerJavaEmbeddedObjects::EMBEDDED)}:", 'Found: %s'],
|
|
141
|
+
API_METHOD_INVALID_FOR_REQUIRED_OBJECT => ['API METHOD INVALID FOR REQUIRED OBJECT', "#{Blufin::Terminal::format_action(Blufin::YmlSchemaValidator::REQUIRED)} and #{Blufin::Terminal::format_action(Blufin::YmlSchemaValidator::REQUIRED_IF)} objects cannot have a #{Blufin::Terminal::format_action(Blufin::YmlConfigValidator::POST)} and/or #{Blufin::Terminal::format_action(Blufin::YmlConfigValidator::DELETE)} because they may require a parent:", 'Found: %s'],
|
|
142
|
+
WORKER_MESSAGE_TYPE_NOT_FOUND => ['INVALID MESSAGE TYPE', "The following #{Blufin::Terminal::format_action('MessageTypes(s)', false)} are not defined in the worker-service:", 'Unrecognized MessageType: %s'],
|
|
143
|
+
DATA_NOT_ALPHABETICAL => ['DATA NOT ALPHABETICAL', "The YML parser expected the data in a section to be in #{Blufin::Terminal::format_action('alphabetical')} order:", 'Not in correct order: %s'],
|
|
144
|
+
MAVEN_MODULE_UNRECOGNIZED => ['MAVEN MODULE UNRECOGNIZED', "A maven module has been defined but #{Blufin::Terminal::format_action('not found within the file system')}:", 'Unrecognized module: %s'],
|
|
145
|
+
MAVEN_MODULE_NOT_DEFINED => ['MAVEN MODULE NOT DEFINED', "A maven module found within the file system has #{Blufin::Terminal::format_action('no definition')}:", 'Undefined module: %s'],
|
|
146
|
+
MAVEN_MODULE_NOT_REGISTERED => ['MAVEN MODULE NOT REGISTERED', "A maven module reference has #{Blufin::Terminal::format_action('not been registered')}:", 'Unregistered module: %s'],
|
|
147
|
+
MAVEN_MODULE_DUPLICATE => ['DUPLICATE MAVEN MODULE', "A #{Blufin::Terminal::format_action('duplicate')} maven module was found:", 'Duplicate module: %s'],
|
|
148
|
+
MAVEN_MODULE_ORDER => ['MAVEN MODULE ORDER MISMATCH', "The YML parser expected maven modules to be in #{Blufin::Terminal::format_action('alphabetical order')}:", 'Not in order: %s'],
|
|
149
|
+
MAVEN_MODULE_UNDEFINED_PARENT => ['MAVEN MODULE UNDEFINED PARENT', "A maven module parent has #{Blufin::Terminal::format_action('not been defined')}:", 'Undefined parent: %s'],
|
|
150
|
+
MAVEN_MODULE_UNUSED_PARENT => ['MAVEN MODULE UNUSED PARENT', "A maven module parent has #{Blufin::Terminal::format_action('not been used')}:", 'Unused parent: %s'],
|
|
151
|
+
EMBEDDED_OBJECT_NOT_FOUND => ['OBJECT NOT FOUND', "Java Scanner expected exactly ONE object to be #{Blufin::Terminal::format_action('embedded')} with annotation/value but it wasn't:", "Missing: #{Blufin::ScannerJavaEmbeddedObjects::EMBEDDED}(\"%s\")"],
|
|
152
|
+
EMBEDDED_OBJECT_NO_ANNOTATION => ['EMBEDDED ANNOTATION MISSING', "Java Scanner did not find an #{Blufin::Terminal::format_action(Blufin::ScannerJavaEmbeddedObjects::EMBEDDED)} annotation:", "Missing #{Blufin::ScannerJavaEmbeddedObjects::EMBEDDED} annotation:"],
|
|
153
|
+
EMBEDDED_OBJECT_NO_TABLE => ['TABLE NOT FOUND', "A required #{Blufin::Terminal::format_action('embedded object')} doesn't have a schema counter-part table:", 'Missing table: %s'],
|
|
154
|
+
EMBEDDED_OBJECT_INVALID_SCHEMA => ['INVALID OBJECT SCHEMA', "Java Scanner was unable to attribute a #{Blufin::Terminal::format_action('valid schema')} to an embedded object:", 'Unrecognized schema: %s'],
|
|
155
|
+
EMBEDDED_OBJECT_INVALID_NAME => ['INVALID OBJECT NAME', "Java Scanner was unable to resolve a #{Blufin::Terminal::format_action('valid name')} for an embedded object:", "'%s' needs to start with 'Abstract...':"],
|
|
156
|
+
EMBEDDED_OBJECT_INVALID_REF_REGEX => ['INVALID REFERENCE', "The #{Blufin::Terminal::format_action('reference')} used for an embedded object is invalid:", '%s needs to be lowercase & snake-case.'],
|
|
157
|
+
EMBEDDED_OBJECT_INVALID_REF_LENGTH => ['INVALID REFERENCE', "The #{Blufin::Terminal::format_action('reference')} used for an embedded object is invalid:", "%s needs to be less than #{Blufin::YmlSchemaValidator::MAX_TABLE_CHARACTERS} characters:"],
|
|
158
|
+
EMBEDDED_OBJECT_INVALID_ABSTRACTION => ['INVALID OBJECT ABSTRACTION', "Java Scanner expected embedded object(s) NOT to be #{Blufin::Terminal::format_action('abstract', false)}:", '%s cannot be abstract.'],
|
|
159
|
+
EMBEDDED_OBJECT_INVALID_EXTENSION => ['INVALID OBJECT INTERFACE', "Java Scanner expected embedded object to extend #{Blufin::Terminal::format_action('PersistentDtoEmbedded', false)}:", '%s needs to implement PersistentDtoEmbedded.'],
|
|
160
|
+
EMBEDDED_OBJECT_INVALID_LINE => ['INVALID LINE', "Embedded Object(s). Something is wrong with the following #{Blufin::Terminal::format_action('line(s)')}:", '%s'],
|
|
161
|
+
EMBEDDED_OBJECT_INVALID_REGEX => ['INVALID REGEX', "Embedded Object(s). Object name needs to match #{Blufin::Terminal::format_action('regex')}:", '%s does not match regex: %s'],
|
|
162
|
+
EMBEDDED_OBJECT_DATA_NOT_FOUND => ['NO DATA WITHIN OBJECT', "Java Scanner was unable to resolve #{Blufin::Terminal::format_action('fields')} for an embedded object:", 'No fields in: %s'],
|
|
163
|
+
EMBEDDED_FIELD_MISSING => ['MISSING FIELD', "Embedded object(s) is/are missing expected #{Blufin::Terminal::format_action('fields')}:", 'Missing: %s'],
|
|
164
|
+
EMBEDDED_FIELD_WRONG_TYPE => ['WRONG FIELD TYPE', "Embedded object(s) field(s) are of incorrect #{Blufin::Terminal::format_action('type')}:"],
|
|
165
|
+
EMBEDDED_ANNOTATION_MISSING => ['MISSING ANNOTATION', "Embedded object(s) are missing expected #{Blufin::Terminal::format_action('annotations')}:", 'Missing: %s'],
|
|
166
|
+
EMBEDDED_ANNOTATION_UNNECESSARY => ['UNNECESSARY ANNOTATION', "The following embedded object(s) #{Blufin::Terminal::format_action('annotation value(s)')} are not required:", '%s'],
|
|
167
|
+
EMBEDDED_EXTRA_VALUE_INVALID => ['INVALID EXTRA VALUE', "Embedded object(s) field #{Blufin::Terminal::format_action('extra value')} is invalid:", 'Expected: %s Got: %s'],
|
|
168
|
+
EMBEDDED_DATA_TYPE_INVALID => ['INVALID DATA TYPE', "Embedded object(s) field #{Blufin::Terminal::format_action('data-type')} is invalid:", 'Expected: %s Got: %s'],
|
|
169
|
+
EMBEDDED_FLAGS_INVALID => ['INVALID FLAGS', "Embedded object(s) field has invalid #{Blufin::Terminal::format_action('flags')}:"],
|
|
170
|
+
EMBEDDED_FKEY_INVALID => ['INVALID/MISSING FKEY', "Embedded object(s) field has an invalid/missing #{Blufin::Terminal::format_action('fkey')} property:"],
|
|
171
|
+
EMBEDDED_MUST_BE_ENCRYPTED => ['FIELD MUST BE ENCRYPTED', "Embedded object(s) field must be #{Blufin::Terminal::format_action('encrypted')}:"],
|
|
172
|
+
EMBEDDED_CONFIG_CANNOT_BE_ENCRYPTED => ['FIELD CANNOT BE ENCRYPTED', "Embedded object(s) within the config schema cannot be #{Blufin::Terminal::format_action('encrypted')}:"],
|
|
173
|
+
UNEXPECTED_EXCEPTION => ['UNEXPECTED EXCEPTION', "The YML parser encountered an #{Blufin::Terminal::format_action('unexpected exception')}", '%s']
|
|
174
|
+
}
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Initializes the Error Handler.
|
|
178
|
+
# @return void
|
|
179
|
+
def initialize(site)
|
|
180
|
+
|
|
181
|
+
@site = Blufin::SiteResolver::validate_site(site)
|
|
182
|
+
@site_path = Blufin::SiteResolver::get_site_location(@site)
|
|
183
|
+
@errors = []
|
|
184
|
+
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Adds an YmlError object to the @error Array.
|
|
188
|
+
# @return void
|
|
189
|
+
def add_error(type, file, section, field, message = nil)
|
|
190
|
+
@errors << Blufin::YmlError.new(validate_error_type(type), file, section, field, message)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Adds an SchemaError object to the @error Array.
|
|
194
|
+
# @return void
|
|
195
|
+
def add_error_schema(error_object)
|
|
196
|
+
@errors << error_object
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Displays errors (if any) and halts the script if so.
|
|
200
|
+
# @return Boolean
|
|
201
|
+
def display_errors_if_any(exit = false)
|
|
202
|
+
self.class.output_errors(@errors, @site_path, exit)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Returns a count of how many errors are currently stored.
|
|
206
|
+
# @return Integer
|
|
207
|
+
def get_error_count
|
|
208
|
+
@errors.size
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
private
|
|
212
|
+
|
|
213
|
+
# Validate the error type.
|
|
214
|
+
# @return String
|
|
215
|
+
def validate_error_type(type)
|
|
216
|
+
raise RuntimeError, "Invalid error type: #{type} \xe2\x80\x94 perhaps you forgot to add it to the valid type array in Blufin::YmlErrorHandler ?" unless self.class.error_type_meta.keys.include?(type)
|
|
217
|
+
type
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Must be static because of Columnist.
|
|
221
|
+
# @return void
|
|
222
|
+
def self.output_errors(errors, site_path, exit = false)
|
|
223
|
+
|
|
224
|
+
return false unless errors.any?
|
|
225
|
+
|
|
226
|
+
puts
|
|
227
|
+
|
|
228
|
+
errors_schema = []
|
|
229
|
+
errors_groups = {}
|
|
230
|
+
errors_groups_non_yml = {}
|
|
231
|
+
|
|
232
|
+
errors.each do |error|
|
|
233
|
+
if error.class.to_s == 'Blufin::YmlError'
|
|
234
|
+
if error.type >= 5000
|
|
235
|
+
errors_groups_non_yml[error.type] = [] if errors_groups_non_yml[error.type].nil?
|
|
236
|
+
errors_groups_non_yml[error.type] << error
|
|
237
|
+
else
|
|
238
|
+
errors_groups[error.type] = [] if errors_groups[error.type].nil?
|
|
239
|
+
errors_groups[error.type] << error
|
|
240
|
+
end
|
|
241
|
+
elsif error.class.to_s == 'Blufin::SchemaError'
|
|
242
|
+
errors_schema << error
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
wc1 = 4
|
|
247
|
+
wc2 = 32
|
|
248
|
+
wc3 = 16
|
|
249
|
+
wc4 = 38
|
|
250
|
+
wc5 = Blufin::Terminal::get_terminal_width - (wc1 + wc2 + wc3 + wc4 + 6)
|
|
251
|
+
|
|
252
|
+
# Renders NORMAL errors.
|
|
253
|
+
errors_groups.each do |error_type, error_group|
|
|
254
|
+
Blufin::Terminal::custom(error_type_meta[error_type][0], 88, error_type_meta[error_type][1])
|
|
255
|
+
table(:border => false) do
|
|
256
|
+
row do
|
|
257
|
+
column('', :align => 'left', :width => wc1)
|
|
258
|
+
column('File', :align => 'left', :width => wc2, :color => COLOR_TITLE)
|
|
259
|
+
column('Section', :align => 'left', :width => wc3, :color => COLOR_TITLE)
|
|
260
|
+
column('Field(s)', :align => 'left', :width => wc4, :color => COLOR_TITLE)
|
|
261
|
+
column('Error', :align => 'left', :width => wc5, :color => COLOR_TITLE)
|
|
262
|
+
end
|
|
263
|
+
error_group.each do |error|
|
|
264
|
+
file = error.file.nil? ? MDASH : error.file
|
|
265
|
+
unless file == MDASH
|
|
266
|
+
paf = Blufin::YmlCommon::split_to_path_file(file, site_path)
|
|
267
|
+
file = "#{paf[0]}/#{paf[1]}"
|
|
268
|
+
file = paf[1] if file.length > wc2 - 4
|
|
269
|
+
end
|
|
270
|
+
section = error.section.nil? ? MDASH : error.section
|
|
271
|
+
begin
|
|
272
|
+
field = error.field.nil? ? MDASH : error.field.gsub('|', '.')
|
|
273
|
+
rescue
|
|
274
|
+
# In case field is not a String.
|
|
275
|
+
field = "BUG - Expected String but got: #{error.field.class}"
|
|
276
|
+
end
|
|
277
|
+
message = get_error_message(error)
|
|
278
|
+
row do
|
|
279
|
+
column('', :align => 'left', :width => 4)
|
|
280
|
+
column("#{file}", :color => COLOR_ERROR_MESSAGE)
|
|
281
|
+
column(section, :color => COLOR_ERROR_MESSAGE)
|
|
282
|
+
column(field, :color => COLOR_ERROR_MESSAGE)
|
|
283
|
+
column(message.length > 0 ? message[0] : '', :color => COLOR_ERROR_MESSAGE)
|
|
284
|
+
end
|
|
285
|
+
if message.length > 1
|
|
286
|
+
message.each_with_index do |message, idx|
|
|
287
|
+
next if idx == 0
|
|
288
|
+
row do
|
|
289
|
+
column('')
|
|
290
|
+
column('')
|
|
291
|
+
column('')
|
|
292
|
+
column('')
|
|
293
|
+
column(message, :color => COLOR_ERROR_MESSAGE)
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
puts
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
wc1 = 4
|
|
303
|
+
wc2 = 88
|
|
304
|
+
wc3 = Blufin::Terminal::get_terminal_width - (wc1 + wc2 + 6)
|
|
305
|
+
|
|
306
|
+
# Renders NORMAL (non-YML) errors.
|
|
307
|
+
errors_groups_non_yml.each do |error_type, error_group|
|
|
308
|
+
Blufin::Terminal::custom(error_type_meta[error_type][0], 88, error_type_meta[error_type][1])
|
|
309
|
+
table(:border => false) do
|
|
310
|
+
row do
|
|
311
|
+
column('', :align => 'left', :width => wc1)
|
|
312
|
+
column('File', :align => 'left', :width => wc2, :color => COLOR_TITLE)
|
|
313
|
+
column('Error', :align => 'left', :width => wc3, :color => COLOR_TITLE)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
error_group.each do |error|
|
|
317
|
+
file = error.file.nil? ? MDASH : error.file
|
|
318
|
+
unless file == MDASH
|
|
319
|
+
file.gsub!(Blufin::Config::get_path('Paths', 'BlufinJava'), '')
|
|
320
|
+
file.gsub!(/\A\//, '')
|
|
321
|
+
end
|
|
322
|
+
message = get_error_message(error)
|
|
323
|
+
row do
|
|
324
|
+
column('', :align => 'left', :width => 4)
|
|
325
|
+
column("#{file}", :color => COLOR_ERROR_MESSAGE)
|
|
326
|
+
column(message.length > 0 ? message[0] : '', :color => COLOR_ERROR_MESSAGE)
|
|
327
|
+
end
|
|
328
|
+
if message.length > 1
|
|
329
|
+
message.each_with_index do |message, idx|
|
|
330
|
+
next if idx == 0
|
|
331
|
+
row do
|
|
332
|
+
column('')
|
|
333
|
+
column('')
|
|
334
|
+
column(message, :color => COLOR_ERROR_MESSAGE)
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
puts
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
wc1 = 4
|
|
344
|
+
wc2 = 32
|
|
345
|
+
wc3 = 16
|
|
346
|
+
wc4 = 38
|
|
347
|
+
wc6 = 32
|
|
348
|
+
wc5 = Blufin::Terminal::get_terminal_width - (wc1 + wc2 + wc3 + wc4 + 6 + wc6)
|
|
349
|
+
|
|
350
|
+
# Renders SCHEMA (legacy) errors.
|
|
351
|
+
if errors_schema.length > 0
|
|
352
|
+
Blufin::Terminal::custom('SCHEMA ERROR(S)', 88, 'There are problems with your schema definition(s):')
|
|
353
|
+
table(:border => false) do
|
|
354
|
+
row do
|
|
355
|
+
column('', :align => 'left', :width => wc1)
|
|
356
|
+
column('File', :align => 'left', :width => wc2, :color => COLOR_TITLE)
|
|
357
|
+
column('Section', :align => 'left', :width => wc3, :color => COLOR_TITLE)
|
|
358
|
+
column('Field(s)', :align => 'left', :width => wc4, :color => COLOR_TITLE)
|
|
359
|
+
column('Error', :align => 'left', :width => wc5, :color => COLOR_TITLE)
|
|
360
|
+
column('Detail', :align => 'left', :width => wc6, :color => COLOR_TITLE)
|
|
361
|
+
end
|
|
362
|
+
errors_schema.each do |error|
|
|
363
|
+
if error.file.nil? || error.file == MDASH || error.file == '' || error.file == '—'
|
|
364
|
+
file_output = MDASH
|
|
365
|
+
else
|
|
366
|
+
file = Blufin::YmlCommon::split_to_path_file(error.file, site_path)
|
|
367
|
+
file_output = file[1]
|
|
368
|
+
end
|
|
369
|
+
section = error.section
|
|
370
|
+
field = error.schema_address[2].nil? ? MDASH : error.schema_address[2]
|
|
371
|
+
row do
|
|
372
|
+
column('', :align => 'left', :width => 4)
|
|
373
|
+
column(file_output, :color => COLOR_ERROR_MESSAGE)
|
|
374
|
+
column(section, :color => COLOR_ERROR_MESSAGE)
|
|
375
|
+
column(field, :color => COLOR_ERROR_MESSAGE)
|
|
376
|
+
column(error.error_message, :color => COLOR_ERROR_MESSAGE)
|
|
377
|
+
column(error.error_detail, :color => COLOR_ERROR_MESSAGE)
|
|
378
|
+
end
|
|
379
|
+
multi_content = error.multi_line_content
|
|
380
|
+
if !multi_content.nil? && multi_content.length > 0
|
|
381
|
+
# row { column(''); column(''); column(''); column(''); column(''); column('') }
|
|
382
|
+
multi_content.each do |line|
|
|
383
|
+
row do
|
|
384
|
+
column('')
|
|
385
|
+
column('')
|
|
386
|
+
column('')
|
|
387
|
+
column('')
|
|
388
|
+
column("\x1B[38;5;154m#{line}", :color => COLOR_ERROR_MESSAGE)
|
|
389
|
+
column('')
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
row { column(''); column(''); column(''); column(''); column(''); column('') }
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
end
|
|
396
|
+
end
|
|
397
|
+
puts
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
puts
|
|
401
|
+
|
|
402
|
+
exit 1 if exit
|
|
403
|
+
|
|
404
|
+
true
|
|
405
|
+
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Gets the error message (or a default message if one is defined).
|
|
409
|
+
# @return Array
|
|
410
|
+
def self.get_error_message(error)
|
|
411
|
+
message = error.message
|
|
412
|
+
begin
|
|
413
|
+
raise nil if error_type_meta[error.type][2].nil?
|
|
414
|
+
error_values = nil
|
|
415
|
+
error_values = [error.message] unless error.message.is_a?(Array)
|
|
416
|
+
error_values = error.message if error.message.is_a?(Array)
|
|
417
|
+
error_values = error_values.map { |value| "\x1B[38;5;196m#{value}\x1B[38;5;#{COLOR_ERROR_MESSAGE}m" } unless error_values.nil?
|
|
418
|
+
message = [error_type_meta[error.type][2] % error_values]
|
|
419
|
+
rescue
|
|
420
|
+
end
|
|
421
|
+
message = [MDASH] if message.nil?
|
|
422
|
+
message
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
# Used for creating a consistent way of displaying Expected/Actual output in errors.
|
|
426
|
+
# @return Array
|
|
427
|
+
def self.error_expected_actual(expected, actual)
|
|
428
|
+
[
|
|
429
|
+
"Expected: \x1B[38;5;118m#{expected}\x1B[38;5;#{COLOR_ERROR_MESSAGE}m",
|
|
430
|
+
" Actual: \x1B[38;5;196m#{actual}",
|
|
431
|
+
nil
|
|
432
|
+
]
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
end
|