blufin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bf +5 -0
  3. data/bin/blufin +5 -0
  4. data/lib/blufin.rb +245 -0
  5. data/lib/core/code_scanners/common/scanner_common.rb +83 -0
  6. data/lib/core/code_scanners/common/scanner_java.rb +106 -0
  7. data/lib/core/code_scanners/scanner_java_embedded_objects.rb +386 -0
  8. data/lib/core/code_scanners/scanner_java_enums.rb +125 -0
  9. data/lib/core/code_scanners/scanner_java_source.rb +29 -0
  10. data/lib/core/code_scanners/scanner_java_tests.rb +157 -0
  11. data/lib/core/error_handling/schema_error.rb +9 -0
  12. data/lib/core/error_handling/sql_error.rb +21 -0
  13. data/lib/core/error_handling/sql_error_handler.rb +149 -0
  14. data/lib/core/error_handling/yml_error.rb +21 -0
  15. data/lib/core/error_handling/yml_error_handler.rb +437 -0
  16. data/lib/core/mysql.rb +347 -0
  17. data/lib/core/opt.rb +21 -0
  18. data/lib/core/site/site.rb +26 -0
  19. data/lib/core/site/site_auth.rb +88 -0
  20. data/lib/core/site/site_embedded.rb +27 -0
  21. data/lib/core/site/site_ports.rb +9 -0
  22. data/lib/core/site/site_resolver.rb +276 -0
  23. data/lib/core/site/site_services.rb +162 -0
  24. data/lib/core/site/site_ui.rb +16 -0
  25. data/lib/core/yml/config/yml_config_validator.rb +219 -0
  26. data/lib/core/yml/maven/yml_maven_validator.rb +1132 -0
  27. data/lib/core/yml/resource/yml_resource_validator.rb +154 -0
  28. data/lib/core/yml/schema/yml_schema_flags.rb +9 -0
  29. data/lib/core/yml/schema/yml_schema_validator.rb +1850 -0
  30. data/lib/core/yml/yml_cache_handler.rb +115 -0
  31. data/lib/core/yml/yml_common.rb +487 -0
  32. data/lib/core/yml/yml_meta_writer_base.rb +300 -0
  33. data/lib/core/yml/yml_outputter.rb +307 -0
  34. data/lib/core/yml/yml_validator_base.rb +630 -0
  35. data/lib/core/yml_writers/yml_configuration_writer.rb +40 -0
  36. data/lib/core/yml_writers/yml_java_api_resource_writer.rb +348 -0
  37. data/lib/core/yml_writers/yml_java_cron_type_writer.rb +113 -0
  38. data/lib/core/yml_writers/yml_java_css_dependency_writer.rb +59 -0
  39. data/lib/core/yml_writers/yml_java_dao_writer.rb +364 -0
  40. data/lib/core/yml_writers/yml_java_dto_writer.rb +251 -0
  41. data/lib/core/yml_writers/yml_java_embedded_object_writer.rb +968 -0
  42. data/lib/core/yml_writers/yml_java_enum_writer.rb +161 -0
  43. data/lib/core/yml_writers/yml_java_js_dependency_writer.rb +59 -0
  44. data/lib/core/yml_writers/yml_java_message_type_writer.rb +106 -0
  45. data/lib/core/yml_writers/yml_java_meta_writer.rb +173 -0
  46. data/lib/core/yml_writers/yml_java_model_writer.rb +510 -0
  47. data/lib/core/yml_writers/yml_java_pom_writer.rb +1050 -0
  48. data/lib/core/yml_writers/yml_java_resource_data_writer.rb +251 -0
  49. data/lib/core/yml_writers/yml_java_sdk_writer.rb +732 -0
  50. data/lib/core/yml_writers/yml_java_validator_writer.rb +280 -0
  51. data/lib/core/yml_writers/yml_java_worker_writer.rb +81 -0
  52. data/lib/core/yml_writers/yml_sql_structure_writer.rb +307 -0
  53. data/lib/core/yml_writers/yml_sql_template_writer.rb +243 -0
  54. data/lib/core/yml_writers/yml_vue_service_writer.rb +170 -0
  55. data/lib/core/yml_writers/yml_writer_base.rb +114 -0
  56. data/lib/routes/api_list.rb +35 -0
  57. data/lib/routes/api_meta.rb +59 -0
  58. data/lib/routes/build.rb +46 -0
  59. data/lib/routes/create/create_api.rb +35 -0
  60. data/lib/routes/create/create_ui.rb +84 -0
  61. data/lib/routes/export.rb +56 -0
  62. data/lib/routes/generate/generate_api.rb +225 -0
  63. data/lib/routes/generate/generate_img_favicon.rb +56 -0
  64. data/lib/routes/generate/generate_img_landing.rb +94 -0
  65. data/lib/routes/generate/generate_lambda.rb +43 -0
  66. data/lib/routes/lint.rb +35 -0
  67. data/lib/routes/mysql_reset.rb +43 -0
  68. data/lib/routes/release_blufin.rb +351 -0
  69. data/lib/routes/run.rb +35 -0
  70. data/lib/version.rb +1 -0
  71. data/opt/README.MD +2 -0
  72. data/opt/config/schema.yml +73 -0
  73. data/opt/config/template.yml +25 -0
  74. data/opt/sql/data/config/data-client.sql +7 -0
  75. data/opt/sql/data/config/data-db-configuration-property.sql +47 -0
  76. data/opt/sql/data/config/data-db-configuration.sql +9 -0
  77. data/opt/sql/data/config/data-db.sql +175 -0
  78. data/opt/sql/data/config/data-profile-api.sql +47 -0
  79. data/opt/sql/data/config/data-profile-cron.sql +0 -0
  80. data/opt/sql/data/config/data-profile-worker.sql +0 -0
  81. data/opt/sql/data/config/data-profile.sql +87 -0
  82. data/opt/sql/data/config/data-project.sql +95 -0
  83. data/opt/sql/structure/blufin-master-structure-fks.sql +65 -0
  84. data/opt/sql/structure/blufin-master-structure.sql +97 -0
  85. data/opt/sql/structure/blufin-mock-structure-fks.sql +38 -0
  86. data/opt/sql/structure/blufin-mock-structure.sql +98 -0
  87. data/opt/sql/templates/config/template-client.sql +7 -0
  88. data/opt/sql/templates/config/template-db-configuration-property.sql +11 -0
  89. data/opt/sql/templates/config/template-db-configuration.sql +9 -0
  90. data/opt/sql/templates/config/template-db.sql +21 -0
  91. data/opt/sql/templates/config/template-profile-api.sql +11 -0
  92. data/opt/sql/templates/config/template-profile-cron.sql +7 -0
  93. data/opt/sql/templates/config/template-profile-worker.sql +7 -0
  94. data/opt/sql/templates/config/template-profile.sql +21 -0
  95. data/opt/sql/templates/config/template-project.sql +23 -0
  96. data/opt/yml/api/schema/config/client.yml +14 -0
  97. data/opt/yml/api/schema/config/db.yml +45 -0
  98. data/opt/yml/api/schema/config/db_configuration.yml +22 -0
  99. data/opt/yml/api/schema/config/db_configuration_property.yml +22 -0
  100. data/opt/yml/api/schema/config/profile.yml +53 -0
  101. data/opt/yml/api/schema/config/profile_api.yml +22 -0
  102. data/opt/yml/api/schema/config/profile_cron.yml +14 -0
  103. data/opt/yml/api/schema/config/profile_worker.yml +14 -0
  104. data/opt/yml/api/schema/config/project.yml +48 -0
  105. data/opt/yml/api/schema/mock/mock.yml +99 -0
  106. data/opt/yml/api/schema/mock/mock_nested_if_enum.yml +16 -0
  107. data/opt/yml/api/schema/mock/mock_nested_if_enum_system.yml +16 -0
  108. data/opt/yml/api/schema/mock/mock_nested_linked.yml +43 -0
  109. data/opt/yml/api/schema/mock/mock_nested_multiple.yml +61 -0
  110. data/opt/yml/api/schema/mock/mock_nested_single.yml +67 -0
  111. data/opt/yml/api/schema/mock/mock_nested_single_super_deep.yml +32 -0
  112. data/opt/yml/api/schema/mock/mock_nested_single_super_super_deep.yml +17 -0
  113. metadata +240 -0
@@ -0,0 +1,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,9 @@
1
+ module Blufin
2
+
3
+ class SchemaError
4
+
5
+ attr_accessor :schema_address, :file, :error_detail, :error_message, :multi_line_content, :section
6
+
7
+ end
8
+
9
+ 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