diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f335f9d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,1250 @@ +[*] +charset = utf-8 +end_of_line = crlf +indent_size = 4 +indent_style = space +insert_final_newline = false +max_line_length = 120 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = true +ij_smart_tabs = false +ij_visual_guides = none +ij_wrap_on_typing = false + +[*.css] +ij_css_align_closing_brace_with_properties = false +ij_css_blank_lines_around_nested_selector = 1 +ij_css_blank_lines_between_blocks = 1 +ij_css_block_comment_add_space = false +ij_css_brace_placement = end_of_line +ij_css_enforce_quotes_on_format = false +ij_css_hex_color_long_format = false +ij_css_hex_color_lower_case = false +ij_css_hex_color_short_format = false +ij_css_hex_color_upper_case = false +ij_css_keep_blank_lines_in_code = 2 +ij_css_keep_indents_on_empty_lines = false +ij_css_keep_single_line_blocks = false +ij_css_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_css_space_after_colon = true +ij_css_space_before_opening_brace = true +ij_css_use_double_quotes = true +ij_css_value_alignment = do_not_align + +[*.feature] +indent_size = 2 +ij_gherkin_keep_indents_on_empty_lines = false + +[*.java] +ij_java_align_consecutive_assignments = false +ij_java_align_consecutive_variable_declarations = false +ij_java_align_group_field_declarations = false +ij_java_align_multiline_annotation_parameters = false +ij_java_align_multiline_array_initializer_expression = false +ij_java_align_multiline_assignment = false +ij_java_align_multiline_binary_operation = false +ij_java_align_multiline_chained_methods = false +ij_java_align_multiline_deconstruction_list_components = true +ij_java_align_multiline_extends_list = false +ij_java_align_multiline_for = true +ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_parameters = true +ij_java_align_multiline_parameters_in_calls = false +ij_java_align_multiline_parenthesized_expression = false +ij_java_align_multiline_records = true +ij_java_align_multiline_resources = true +ij_java_align_multiline_ternary_operation = false +ij_java_align_multiline_text_blocks = false +ij_java_align_multiline_throws_list = false +ij_java_align_subsequent_simple_methods = false +ij_java_align_throws_keyword = false +ij_java_align_types_in_multi_catch = true +ij_java_annotation_parameter_wrap = off +ij_java_array_initializer_new_line_after_left_brace = false +ij_java_array_initializer_right_brace_on_new_line = false +ij_java_array_initializer_wrap = off +ij_java_assert_statement_colon_on_next_line = false +ij_java_assert_statement_wrap = off +ij_java_assignment_wrap = off +ij_java_binary_operation_sign_on_next_line = false +ij_java_binary_operation_wrap = off +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 0 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_field = 0 +ij_java_blank_lines_around_field_in_interface = 0 +ij_java_blank_lines_around_initializer = 1 +ij_java_blank_lines_around_method = 1 +ij_java_blank_lines_around_method_in_interface = 1 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_before_imports = 1 +ij_java_blank_lines_before_method_body = 0 +ij_java_blank_lines_before_package = 0 +ij_java_block_brace_style = end_of_line +ij_java_block_comment_add_space = false +ij_java_block_comment_at_first_column = true +ij_java_builder_methods = none +ij_java_call_parameters_new_line_after_left_paren = false +ij_java_call_parameters_right_paren_on_new_line = false +ij_java_call_parameters_wrap = off +ij_java_case_statement_on_separate_line = true +ij_java_catch_on_new_line = false +ij_java_class_annotation_wrap = split_into_lines +ij_java_class_brace_style = end_of_line +ij_java_class_count_to_use_import_on_demand = 5 +ij_java_class_names_in_javadoc = 1 +ij_java_deconstruction_list_wrap = normal +ij_java_do_not_indent_top_level_class_members = false +ij_java_do_not_wrap_after_single_annotation = false +ij_java_do_not_wrap_after_single_annotation_in_parameter = false +ij_java_do_while_brace_force = never +ij_java_doc_add_blank_line_after_description = true +ij_java_doc_add_blank_line_after_param_comments = false +ij_java_doc_add_blank_line_after_return = false +ij_java_doc_add_p_tag_on_empty_lines = true +ij_java_doc_align_exception_comments = true +ij_java_doc_align_param_comments = true +ij_java_doc_do_not_wrap_if_one_line = false +ij_java_doc_enable_formatting = true +ij_java_doc_enable_leading_asterisks = true +ij_java_doc_indent_on_continuation = false +ij_java_doc_keep_empty_lines = true +ij_java_doc_keep_empty_parameter_tag = true +ij_java_doc_keep_empty_return_tag = true +ij_java_doc_keep_empty_throws_tag = true +ij_java_doc_keep_invalid_tags = true +ij_java_doc_param_description_on_new_line = false +ij_java_doc_preserve_line_breaks = false +ij_java_doc_use_throws_not_exception_tag = true +ij_java_else_on_new_line = false +ij_java_entity_dd_suffix = EJB +ij_java_entity_eb_suffix = Bean +ij_java_entity_hi_suffix = Home +ij_java_entity_lhi_prefix = Local +ij_java_entity_lhi_suffix = Home +ij_java_entity_li_prefix = Local +ij_java_entity_pk_class = java.lang.String +ij_java_entity_vo_suffix = VO +ij_java_enum_constants_wrap = off +ij_java_extends_keyword_wrap = off +ij_java_extends_list_wrap = off +ij_java_field_annotation_wrap = split_into_lines +ij_java_finally_on_new_line = false +ij_java_for_brace_force = never +ij_java_for_statement_new_line_after_left_paren = false +ij_java_for_statement_right_paren_on_new_line = false +ij_java_for_statement_wrap = off +ij_java_generate_final_locals = false +ij_java_generate_final_parameters = false +ij_java_if_brace_force = never +ij_java_imports_layout = *, |, javax.**, java.**, |, $* +ij_java_indent_case_from_switch = true +ij_java_insert_inner_class_imports = false +ij_java_insert_override_annotation = true +ij_java_keep_blank_lines_before_right_brace = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_in_code = 2 +ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_builder_methods_indents = false +ij_java_keep_control_statement_in_one_line = true +ij_java_keep_first_column_comment = true +ij_java_keep_indents_on_empty_lines = false +ij_java_keep_line_breaks = true +ij_java_keep_multiple_expressions_in_one_line = false +ij_java_keep_simple_blocks_in_one_line = false +ij_java_keep_simple_classes_in_one_line = false +ij_java_keep_simple_lambdas_in_one_line = false +ij_java_keep_simple_methods_in_one_line = false +ij_java_label_indent_absolute = false +ij_java_label_indent_size = 0 +ij_java_lambda_brace_style = end_of_line +ij_java_layout_static_imports_separately = true +ij_java_line_comment_add_space = false +ij_java_line_comment_add_space_on_reformat = false +ij_java_line_comment_at_first_column = true +ij_java_message_dd_suffix = EJB +ij_java_message_eb_suffix = Bean +ij_java_method_annotation_wrap = split_into_lines +ij_java_method_brace_style = end_of_line +ij_java_method_call_chain_wrap = off +ij_java_method_parameters_new_line_after_left_paren = false +ij_java_method_parameters_right_paren_on_new_line = false +ij_java_method_parameters_wrap = off +ij_java_modifier_list_wrap = false +ij_java_multi_catch_types_wrap = normal +ij_java_names_count_to_use_import_on_demand = 3 +ij_java_new_line_after_lparen_in_annotation = false +ij_java_new_line_after_lparen_in_deconstruction_pattern = true +ij_java_new_line_after_lparen_in_record_header = false +ij_java_packages_to_use_import_on_demand = java.awt.*, javax.swing.* +ij_java_parameter_annotation_wrap = off +ij_java_parentheses_expression_new_line_after_left_paren = false +ij_java_parentheses_expression_right_paren_on_new_line = false +ij_java_place_assignment_sign_on_next_line = false +ij_java_prefer_longer_names = true +ij_java_prefer_parameters_wrap = false +ij_java_record_components_wrap = normal +ij_java_repeat_synchronized = true +ij_java_replace_instanceof_and_cast = false +ij_java_replace_null_check = true +ij_java_replace_sum_lambda_with_method_ref = true +ij_java_resource_list_new_line_after_left_paren = false +ij_java_resource_list_right_paren_on_new_line = false +ij_java_resource_list_wrap = off +ij_java_rparen_on_new_line_in_annotation = false +ij_java_rparen_on_new_line_in_deconstruction_pattern = true +ij_java_rparen_on_new_line_in_record_header = false +ij_java_session_dd_suffix = EJB +ij_java_session_eb_suffix = Bean +ij_java_session_hi_suffix = Home +ij_java_session_lhi_prefix = Local +ij_java_session_lhi_suffix = Home +ij_java_session_li_prefix = Local +ij_java_session_si_suffix = Service +ij_java_space_after_closing_angle_bracket_in_type_argument = false +ij_java_space_after_colon = true +ij_java_space_after_comma = true +ij_java_space_after_comma_in_type_arguments = true +ij_java_space_after_for_semicolon = true +ij_java_space_after_quest = true +ij_java_space_after_type_cast = true +ij_java_space_before_annotation_array_initializer_left_brace = false +ij_java_space_before_annotation_parameter_list = false +ij_java_space_before_array_initializer_left_brace = false +ij_java_space_before_catch_keyword = true +ij_java_space_before_catch_left_brace = true +ij_java_space_before_catch_parentheses = true +ij_java_space_before_class_left_brace = true +ij_java_space_before_colon = true +ij_java_space_before_colon_in_foreach = true +ij_java_space_before_comma = false +ij_java_space_before_deconstruction_list = false +ij_java_space_before_do_left_brace = true +ij_java_space_before_else_keyword = true +ij_java_space_before_else_left_brace = true +ij_java_space_before_finally_keyword = true +ij_java_space_before_finally_left_brace = true +ij_java_space_before_for_left_brace = true +ij_java_space_before_for_parentheses = true +ij_java_space_before_for_semicolon = false +ij_java_space_before_if_left_brace = true +ij_java_space_before_if_parentheses = true +ij_java_space_before_method_call_parentheses = false +ij_java_space_before_method_left_brace = true +ij_java_space_before_method_parentheses = false +ij_java_space_before_opening_angle_bracket_in_type_parameter = false +ij_java_space_before_quest = true +ij_java_space_before_switch_left_brace = true +ij_java_space_before_switch_parentheses = true +ij_java_space_before_synchronized_left_brace = true +ij_java_space_before_synchronized_parentheses = true +ij_java_space_before_try_left_brace = true +ij_java_space_before_try_parentheses = true +ij_java_space_before_type_parameter_list = false +ij_java_space_before_while_keyword = true +ij_java_space_before_while_left_brace = true +ij_java_space_before_while_parentheses = true +ij_java_space_inside_one_line_enum_braces = false +ij_java_space_within_empty_array_initializer_braces = false +ij_java_space_within_empty_method_call_parentheses = false +ij_java_space_within_empty_method_parentheses = false +ij_java_spaces_around_additive_operators = true +ij_java_spaces_around_annotation_eq = true +ij_java_spaces_around_assignment_operators = true +ij_java_spaces_around_bitwise_operators = true +ij_java_spaces_around_equality_operators = true +ij_java_spaces_around_lambda_arrow = true +ij_java_spaces_around_logical_operators = true +ij_java_spaces_around_method_ref_dbl_colon = false +ij_java_spaces_around_multiplicative_operators = true +ij_java_spaces_around_relational_operators = true +ij_java_spaces_around_shift_operators = true +ij_java_spaces_around_type_bounds_in_type_parameters = true +ij_java_spaces_around_unary_operator = false +ij_java_spaces_within_angle_brackets = false +ij_java_spaces_within_annotation_parentheses = false +ij_java_spaces_within_array_initializer_braces = false +ij_java_spaces_within_braces = false +ij_java_spaces_within_brackets = false +ij_java_spaces_within_cast_parentheses = false +ij_java_spaces_within_catch_parentheses = false +ij_java_spaces_within_deconstruction_list = false +ij_java_spaces_within_for_parentheses = false +ij_java_spaces_within_if_parentheses = false +ij_java_spaces_within_method_call_parentheses = false +ij_java_spaces_within_method_parentheses = false +ij_java_spaces_within_parentheses = false +ij_java_spaces_within_record_header = false +ij_java_spaces_within_switch_parentheses = false +ij_java_spaces_within_synchronized_parentheses = false +ij_java_spaces_within_try_parentheses = false +ij_java_spaces_within_while_parentheses = false +ij_java_special_else_if_treatment = true +ij_java_subclass_name_suffix = Impl +ij_java_ternary_operation_signs_on_next_line = false +ij_java_ternary_operation_wrap = off +ij_java_test_name_suffix = Test +ij_java_throws_keyword_wrap = off +ij_java_throws_list_wrap = off +ij_java_use_external_annotations = false +ij_java_use_fq_class_names = false +ij_java_use_relative_indents = false +ij_java_use_single_class_imports = true +ij_java_variable_annotation_wrap = off +ij_java_visibility = public +ij_java_while_brace_force = never +ij_java_while_on_new_line = false +ij_java_wrap_comments = false +ij_java_wrap_first_method_in_call_chain = false +ij_java_wrap_long_lines = false + +[*.less] +indent_size = 2 +ij_less_align_closing_brace_with_properties = false +ij_less_blank_lines_around_nested_selector = 1 +ij_less_blank_lines_between_blocks = 1 +ij_less_block_comment_add_space = false +ij_less_brace_placement = 0 +ij_less_enforce_quotes_on_format = false +ij_less_hex_color_long_format = false +ij_less_hex_color_lower_case = false +ij_less_hex_color_short_format = false +ij_less_hex_color_upper_case = false +ij_less_keep_blank_lines_in_code = 2 +ij_less_keep_indents_on_empty_lines = false +ij_less_keep_single_line_blocks = false +ij_less_line_comment_add_space = false +ij_less_line_comment_at_first_column = false +ij_less_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_less_space_after_colon = true +ij_less_space_before_opening_brace = true +ij_less_use_double_quotes = true +ij_less_value_alignment = 0 + +[*.nbtt] +indent_style = tab +max_line_length = 150 +ij_continuation_indent_size = 4 +ij_nbtt_keep_indents_on_empty_lines = false +ij_nbtt_space_after_colon = true +ij_nbtt_space_after_comma = true +ij_nbtt_space_before_colon = true +ij_nbtt_space_before_comma = false +ij_nbtt_spaces_within_brackets = false +ij_nbtt_spaces_within_parentheses = false + +[*.proto] +indent_size = 2 +tab_width = 2 +ij_continuation_indent_size = 4 +ij_protobuf_keep_blank_lines_in_code = 2 +ij_protobuf_keep_indents_on_empty_lines = false +ij_protobuf_keep_line_breaks = true +ij_protobuf_space_after_comma = true +ij_protobuf_space_before_comma = false +ij_protobuf_spaces_around_assignment_operators = true +ij_protobuf_spaces_within_braces = false +ij_protobuf_spaces_within_brackets = false + +[*.sass] +indent_size = 2 +ij_sass_align_closing_brace_with_properties = false +ij_sass_blank_lines_around_nested_selector = 1 +ij_sass_blank_lines_between_blocks = 1 +ij_sass_brace_placement = 0 +ij_sass_enforce_quotes_on_format = false +ij_sass_hex_color_long_format = false +ij_sass_hex_color_lower_case = false +ij_sass_hex_color_short_format = false +ij_sass_hex_color_upper_case = false +ij_sass_keep_blank_lines_in_code = 2 +ij_sass_keep_indents_on_empty_lines = false +ij_sass_keep_single_line_blocks = false +ij_sass_line_comment_add_space = false +ij_sass_line_comment_at_first_column = false +ij_sass_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_sass_space_after_colon = true +ij_sass_space_before_opening_brace = true +ij_sass_use_double_quotes = true +ij_sass_value_alignment = 0 + +[*.scss] +indent_size = 2 +ij_scss_align_closing_brace_with_properties = false +ij_scss_blank_lines_around_nested_selector = 1 +ij_scss_blank_lines_between_blocks = 1 +ij_scss_block_comment_add_space = false +ij_scss_brace_placement = 0 +ij_scss_enforce_quotes_on_format = false +ij_scss_hex_color_long_format = false +ij_scss_hex_color_lower_case = false +ij_scss_hex_color_short_format = false +ij_scss_hex_color_upper_case = false +ij_scss_keep_blank_lines_in_code = 2 +ij_scss_keep_indents_on_empty_lines = false +ij_scss_keep_single_line_blocks = false +ij_scss_line_comment_add_space = false +ij_scss_line_comment_at_first_column = false +ij_scss_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow +ij_scss_space_after_colon = true +ij_scss_space_before_opening_brace = true +ij_scss_use_double_quotes = true +ij_scss_value_alignment = 0 + +[*.vue] +indent_size = 2 +tab_width = 2 +ij_continuation_indent_size = 4 +ij_vue_indent_children_of_top_level = template +ij_vue_interpolation_new_line_after_start_delimiter = true +ij_vue_interpolation_new_line_before_end_delimiter = true +ij_vue_interpolation_wrap = off +ij_vue_keep_indents_on_empty_lines = false +ij_vue_spaces_within_interpolation_expressions = true + +[.editorconfig] +ij_editorconfig_align_group_field_declarations = false +ij_editorconfig_space_after_colon = false +ij_editorconfig_space_after_comma = true +ij_editorconfig_space_before_colon = false +ij_editorconfig_space_before_comma = false +ij_editorconfig_spaces_around_assignment_operators = true + +[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.pom,*.rng,*.tld,*.wadl,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] +ij_xml_align_attributes = true +ij_xml_align_text = false +ij_xml_attribute_wrap = normal +ij_xml_block_comment_add_space = false +ij_xml_block_comment_at_first_column = true +ij_xml_keep_blank_lines = 2 +ij_xml_keep_indents_on_empty_lines = false +ij_xml_keep_line_breaks = true +ij_xml_keep_line_breaks_in_text = true +ij_xml_keep_whitespaces = false +ij_xml_keep_whitespaces_around_cdata = preserve +ij_xml_keep_whitespaces_inside_cdata = false +ij_xml_line_comment_at_first_column = true +ij_xml_space_after_tag_name = false +ij_xml_space_around_equals_in_attribute = false +ij_xml_space_inside_empty_tag = false +ij_xml_text_wrap = normal +ij_xml_use_custom_settings = false + +[{*.ats,*.cts,*.mts,*.ts}] +ij_continuation_indent_size = 4 +ij_typescript_align_imports = false +ij_typescript_align_multiline_array_initializer_expression = false +ij_typescript_align_multiline_binary_operation = false +ij_typescript_align_multiline_chained_methods = false +ij_typescript_align_multiline_extends_list = false +ij_typescript_align_multiline_for = true +ij_typescript_align_multiline_parameters = true +ij_typescript_align_multiline_parameters_in_calls = false +ij_typescript_align_multiline_ternary_operation = false +ij_typescript_align_object_properties = 0 +ij_typescript_align_union_types = false +ij_typescript_align_var_statements = 0 +ij_typescript_array_initializer_new_line_after_left_brace = false +ij_typescript_array_initializer_right_brace_on_new_line = false +ij_typescript_array_initializer_wrap = off +ij_typescript_assignment_wrap = off +ij_typescript_binary_operation_sign_on_next_line = false +ij_typescript_binary_operation_wrap = off +ij_typescript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/** +ij_typescript_blank_lines_after_imports = 1 +ij_typescript_blank_lines_around_class = 1 +ij_typescript_blank_lines_around_field = 0 +ij_typescript_blank_lines_around_field_in_interface = 0 +ij_typescript_blank_lines_around_function = 1 +ij_typescript_blank_lines_around_method = 1 +ij_typescript_blank_lines_around_method_in_interface = 1 +ij_typescript_block_brace_style = end_of_line +ij_typescript_block_comment_add_space = false +ij_typescript_block_comment_at_first_column = true +ij_typescript_call_parameters_new_line_after_left_paren = false +ij_typescript_call_parameters_right_paren_on_new_line = false +ij_typescript_call_parameters_wrap = off +ij_typescript_catch_on_new_line = false +ij_typescript_chained_call_dot_on_new_line = true +ij_typescript_class_brace_style = end_of_line +ij_typescript_comma_on_new_line = false +ij_typescript_do_while_brace_force = never +ij_typescript_else_on_new_line = false +ij_typescript_enforce_trailing_comma = keep +ij_typescript_enum_constants_wrap = on_every_item +ij_typescript_extends_keyword_wrap = off +ij_typescript_extends_list_wrap = off +ij_typescript_field_prefix = _ +ij_typescript_file_name_style = relaxed +ij_typescript_finally_on_new_line = false +ij_typescript_for_brace_force = never +ij_typescript_for_statement_new_line_after_left_paren = false +ij_typescript_for_statement_right_paren_on_new_line = false +ij_typescript_for_statement_wrap = off +ij_typescript_force_quote_style = false +ij_typescript_force_semicolon_style = false +ij_typescript_function_expression_brace_style = end_of_line +ij_typescript_if_brace_force = never +ij_typescript_import_merge_members = global +ij_typescript_import_prefer_absolute_path = global +ij_typescript_import_sort_members = true +ij_typescript_import_sort_module_name = false +ij_typescript_import_use_node_resolution = true +ij_typescript_imports_wrap = on_every_item +ij_typescript_indent_case_from_switch = true +ij_typescript_indent_chained_calls = true +ij_typescript_indent_package_children = 0 +ij_typescript_jsdoc_include_types = false +ij_typescript_jsx_attribute_value = braces +ij_typescript_keep_blank_lines_in_code = 2 +ij_typescript_keep_first_column_comment = true +ij_typescript_keep_indents_on_empty_lines = false +ij_typescript_keep_line_breaks = true +ij_typescript_keep_simple_blocks_in_one_line = false +ij_typescript_keep_simple_methods_in_one_line = false +ij_typescript_line_comment_add_space = true +ij_typescript_line_comment_at_first_column = false +ij_typescript_method_brace_style = end_of_line +ij_typescript_method_call_chain_wrap = off +ij_typescript_method_parameters_new_line_after_left_paren = false +ij_typescript_method_parameters_right_paren_on_new_line = false +ij_typescript_method_parameters_wrap = off +ij_typescript_object_literal_wrap = on_every_item +ij_typescript_object_types_wrap = on_every_item +ij_typescript_parentheses_expression_new_line_after_left_paren = false +ij_typescript_parentheses_expression_right_paren_on_new_line = false +ij_typescript_place_assignment_sign_on_next_line = false +ij_typescript_prefer_as_type_cast = false +ij_typescript_prefer_explicit_types_function_expression_returns = false +ij_typescript_prefer_explicit_types_function_returns = false +ij_typescript_prefer_explicit_types_vars_fields = false +ij_typescript_prefer_parameters_wrap = false +ij_typescript_reformat_c_style_comments = false +ij_typescript_space_after_colon = true +ij_typescript_space_after_comma = true +ij_typescript_space_after_dots_in_rest_parameter = false +ij_typescript_space_after_generator_mult = true +ij_typescript_space_after_property_colon = true +ij_typescript_space_after_quest = true +ij_typescript_space_after_type_colon = true +ij_typescript_space_after_unary_not = false +ij_typescript_space_before_async_arrow_lparen = true +ij_typescript_space_before_catch_keyword = true +ij_typescript_space_before_catch_left_brace = true +ij_typescript_space_before_catch_parentheses = true +ij_typescript_space_before_class_lbrace = true +ij_typescript_space_before_class_left_brace = true +ij_typescript_space_before_colon = true +ij_typescript_space_before_comma = false +ij_typescript_space_before_do_left_brace = true +ij_typescript_space_before_else_keyword = true +ij_typescript_space_before_else_left_brace = true +ij_typescript_space_before_finally_keyword = true +ij_typescript_space_before_finally_left_brace = true +ij_typescript_space_before_for_left_brace = true +ij_typescript_space_before_for_parentheses = true +ij_typescript_space_before_for_semicolon = false +ij_typescript_space_before_function_left_parenth = true +ij_typescript_space_before_generator_mult = false +ij_typescript_space_before_if_left_brace = true +ij_typescript_space_before_if_parentheses = true +ij_typescript_space_before_method_call_parentheses = false +ij_typescript_space_before_method_left_brace = true +ij_typescript_space_before_method_parentheses = false +ij_typescript_space_before_property_colon = false +ij_typescript_space_before_quest = true +ij_typescript_space_before_switch_left_brace = true +ij_typescript_space_before_switch_parentheses = true +ij_typescript_space_before_try_left_brace = true +ij_typescript_space_before_type_colon = false +ij_typescript_space_before_unary_not = false +ij_typescript_space_before_while_keyword = true +ij_typescript_space_before_while_left_brace = true +ij_typescript_space_before_while_parentheses = true +ij_typescript_spaces_around_additive_operators = true +ij_typescript_spaces_around_arrow_function_operator = true +ij_typescript_spaces_around_assignment_operators = true +ij_typescript_spaces_around_bitwise_operators = true +ij_typescript_spaces_around_equality_operators = true +ij_typescript_spaces_around_logical_operators = true +ij_typescript_spaces_around_multiplicative_operators = true +ij_typescript_spaces_around_relational_operators = true +ij_typescript_spaces_around_shift_operators = true +ij_typescript_spaces_around_unary_operator = false +ij_typescript_spaces_within_array_initializer_brackets = false +ij_typescript_spaces_within_brackets = false +ij_typescript_spaces_within_catch_parentheses = false +ij_typescript_spaces_within_for_parentheses = false +ij_typescript_spaces_within_if_parentheses = false +ij_typescript_spaces_within_imports = false +ij_typescript_spaces_within_interpolation_expressions = false +ij_typescript_spaces_within_method_call_parentheses = false +ij_typescript_spaces_within_method_parentheses = false +ij_typescript_spaces_within_object_literal_braces = false +ij_typescript_spaces_within_object_type_braces = true +ij_typescript_spaces_within_parentheses = false +ij_typescript_spaces_within_switch_parentheses = false +ij_typescript_spaces_within_type_assertion = false +ij_typescript_spaces_within_union_types = true +ij_typescript_spaces_within_while_parentheses = false +ij_typescript_special_else_if_treatment = true +ij_typescript_ternary_operation_signs_on_next_line = false +ij_typescript_ternary_operation_wrap = off +ij_typescript_union_types_wrap = on_every_item +ij_typescript_use_chained_calls_group_indents = false +ij_typescript_use_double_quotes = true +ij_typescript_use_explicit_js_extension = auto +ij_typescript_use_path_mapping = always +ij_typescript_use_public_modifier = false +ij_typescript_use_semicolon_after_statement = true +ij_typescript_var_declaration_wrap = normal +ij_typescript_while_brace_force = never +ij_typescript_while_on_new_line = false +ij_typescript_wrap_comments = false + +[{*.bash,*.sh,*.zsh}] +indent_size = 2 +tab_width = 2 +ij_shell_binary_ops_start_line = false +ij_shell_keep_column_alignment_padding = false +ij_shell_minify_program = false +ij_shell_redirect_followed_by_space = false +ij_shell_switch_cases_indented = false +ij_shell_use_unix_line_separator = true + +[{*.cjs,*.js}] +ij_continuation_indent_size = 4 +ij_javascript_align_imports = false +ij_javascript_align_multiline_array_initializer_expression = false +ij_javascript_align_multiline_binary_operation = false +ij_javascript_align_multiline_chained_methods = false +ij_javascript_align_multiline_extends_list = false +ij_javascript_align_multiline_for = true +ij_javascript_align_multiline_parameters = true +ij_javascript_align_multiline_parameters_in_calls = false +ij_javascript_align_multiline_ternary_operation = false +ij_javascript_align_object_properties = 0 +ij_javascript_align_union_types = false +ij_javascript_align_var_statements = 0 +ij_javascript_array_initializer_new_line_after_left_brace = false +ij_javascript_array_initializer_right_brace_on_new_line = false +ij_javascript_array_initializer_wrap = off +ij_javascript_assignment_wrap = off +ij_javascript_binary_operation_sign_on_next_line = false +ij_javascript_binary_operation_wrap = off +ij_javascript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/** +ij_javascript_blank_lines_after_imports = 1 +ij_javascript_blank_lines_around_class = 1 +ij_javascript_blank_lines_around_field = 0 +ij_javascript_blank_lines_around_function = 1 +ij_javascript_blank_lines_around_method = 1 +ij_javascript_block_brace_style = end_of_line +ij_javascript_block_comment_add_space = false +ij_javascript_block_comment_at_first_column = true +ij_javascript_call_parameters_new_line_after_left_paren = false +ij_javascript_call_parameters_right_paren_on_new_line = false +ij_javascript_call_parameters_wrap = off +ij_javascript_catch_on_new_line = false +ij_javascript_chained_call_dot_on_new_line = true +ij_javascript_class_brace_style = end_of_line +ij_javascript_comma_on_new_line = false +ij_javascript_do_while_brace_force = never +ij_javascript_else_on_new_line = false +ij_javascript_enforce_trailing_comma = keep +ij_javascript_extends_keyword_wrap = off +ij_javascript_extends_list_wrap = off +ij_javascript_field_prefix = _ +ij_javascript_file_name_style = relaxed +ij_javascript_finally_on_new_line = false +ij_javascript_for_brace_force = never +ij_javascript_for_statement_new_line_after_left_paren = false +ij_javascript_for_statement_right_paren_on_new_line = false +ij_javascript_for_statement_wrap = off +ij_javascript_force_quote_style = false +ij_javascript_force_semicolon_style = false +ij_javascript_function_expression_brace_style = end_of_line +ij_javascript_if_brace_force = never +ij_javascript_import_merge_members = global +ij_javascript_import_prefer_absolute_path = global +ij_javascript_import_sort_members = true +ij_javascript_import_sort_module_name = false +ij_javascript_import_use_node_resolution = true +ij_javascript_imports_wrap = on_every_item +ij_javascript_indent_case_from_switch = true +ij_javascript_indent_chained_calls = true +ij_javascript_indent_package_children = 0 +ij_javascript_jsx_attribute_value = braces +ij_javascript_keep_blank_lines_in_code = 2 +ij_javascript_keep_first_column_comment = true +ij_javascript_keep_indents_on_empty_lines = false +ij_javascript_keep_line_breaks = true +ij_javascript_keep_simple_blocks_in_one_line = false +ij_javascript_keep_simple_methods_in_one_line = false +ij_javascript_line_comment_add_space = true +ij_javascript_line_comment_at_first_column = false +ij_javascript_method_brace_style = end_of_line +ij_javascript_method_call_chain_wrap = off +ij_javascript_method_parameters_new_line_after_left_paren = false +ij_javascript_method_parameters_right_paren_on_new_line = false +ij_javascript_method_parameters_wrap = off +ij_javascript_object_literal_wrap = on_every_item +ij_javascript_object_types_wrap = on_every_item +ij_javascript_parentheses_expression_new_line_after_left_paren = false +ij_javascript_parentheses_expression_right_paren_on_new_line = false +ij_javascript_place_assignment_sign_on_next_line = false +ij_javascript_prefer_as_type_cast = false +ij_javascript_prefer_explicit_types_function_expression_returns = false +ij_javascript_prefer_explicit_types_function_returns = false +ij_javascript_prefer_explicit_types_vars_fields = false +ij_javascript_prefer_parameters_wrap = false +ij_javascript_reformat_c_style_comments = false +ij_javascript_space_after_colon = true +ij_javascript_space_after_comma = true +ij_javascript_space_after_dots_in_rest_parameter = false +ij_javascript_space_after_generator_mult = true +ij_javascript_space_after_property_colon = true +ij_javascript_space_after_quest = true +ij_javascript_space_after_type_colon = true +ij_javascript_space_after_unary_not = false +ij_javascript_space_before_async_arrow_lparen = true +ij_javascript_space_before_catch_keyword = true +ij_javascript_space_before_catch_left_brace = true +ij_javascript_space_before_catch_parentheses = true +ij_javascript_space_before_class_lbrace = true +ij_javascript_space_before_class_left_brace = true +ij_javascript_space_before_colon = true +ij_javascript_space_before_comma = false +ij_javascript_space_before_do_left_brace = true +ij_javascript_space_before_else_keyword = true +ij_javascript_space_before_else_left_brace = true +ij_javascript_space_before_finally_keyword = true +ij_javascript_space_before_finally_left_brace = true +ij_javascript_space_before_for_left_brace = true +ij_javascript_space_before_for_parentheses = true +ij_javascript_space_before_for_semicolon = false +ij_javascript_space_before_function_left_parenth = true +ij_javascript_space_before_generator_mult = false +ij_javascript_space_before_if_left_brace = true +ij_javascript_space_before_if_parentheses = true +ij_javascript_space_before_method_call_parentheses = false +ij_javascript_space_before_method_left_brace = true +ij_javascript_space_before_method_parentheses = false +ij_javascript_space_before_property_colon = false +ij_javascript_space_before_quest = true +ij_javascript_space_before_switch_left_brace = true +ij_javascript_space_before_switch_parentheses = true +ij_javascript_space_before_try_left_brace = true +ij_javascript_space_before_type_colon = false +ij_javascript_space_before_unary_not = false +ij_javascript_space_before_while_keyword = true +ij_javascript_space_before_while_left_brace = true +ij_javascript_space_before_while_parentheses = true +ij_javascript_spaces_around_additive_operators = true +ij_javascript_spaces_around_arrow_function_operator = true +ij_javascript_spaces_around_assignment_operators = true +ij_javascript_spaces_around_bitwise_operators = true +ij_javascript_spaces_around_equality_operators = true +ij_javascript_spaces_around_logical_operators = true +ij_javascript_spaces_around_multiplicative_operators = true +ij_javascript_spaces_around_relational_operators = true +ij_javascript_spaces_around_shift_operators = true +ij_javascript_spaces_around_unary_operator = false +ij_javascript_spaces_within_array_initializer_brackets = false +ij_javascript_spaces_within_brackets = false +ij_javascript_spaces_within_catch_parentheses = false +ij_javascript_spaces_within_for_parentheses = false +ij_javascript_spaces_within_if_parentheses = false +ij_javascript_spaces_within_imports = false +ij_javascript_spaces_within_interpolation_expressions = false +ij_javascript_spaces_within_method_call_parentheses = false +ij_javascript_spaces_within_method_parentheses = false +ij_javascript_spaces_within_object_literal_braces = false +ij_javascript_spaces_within_object_type_braces = true +ij_javascript_spaces_within_parentheses = false +ij_javascript_spaces_within_switch_parentheses = false +ij_javascript_spaces_within_type_assertion = false +ij_javascript_spaces_within_union_types = true +ij_javascript_spaces_within_while_parentheses = false +ij_javascript_special_else_if_treatment = true +ij_javascript_ternary_operation_signs_on_next_line = false +ij_javascript_ternary_operation_wrap = off +ij_javascript_union_types_wrap = on_every_item +ij_javascript_use_chained_calls_group_indents = false +ij_javascript_use_double_quotes = true +ij_javascript_use_explicit_js_extension = auto +ij_javascript_use_path_mapping = always +ij_javascript_use_public_modifier = false +ij_javascript_use_semicolon_after_statement = true +ij_javascript_var_declaration_wrap = normal +ij_javascript_while_brace_force = never +ij_javascript_while_on_new_line = false +ij_javascript_wrap_comments = false + +[{*.ft,*.vm,*.vsl}] +ij_vtl_keep_indents_on_empty_lines = false + +[{*.gant,*.groovy,*.gy}] +ij_groovy_align_group_field_declarations = false +ij_groovy_align_multiline_array_initializer_expression = false +ij_groovy_align_multiline_assignment = false +ij_groovy_align_multiline_binary_operation = false +ij_groovy_align_multiline_chained_methods = false +ij_groovy_align_multiline_extends_list = false +ij_groovy_align_multiline_for = true +ij_groovy_align_multiline_list_or_map = true +ij_groovy_align_multiline_method_parentheses = false +ij_groovy_align_multiline_parameters = true +ij_groovy_align_multiline_parameters_in_calls = false +ij_groovy_align_multiline_resources = true +ij_groovy_align_multiline_ternary_operation = false +ij_groovy_align_multiline_throws_list = false +ij_groovy_align_named_args_in_map = true +ij_groovy_align_throws_keyword = false +ij_groovy_array_initializer_new_line_after_left_brace = false +ij_groovy_array_initializer_right_brace_on_new_line = false +ij_groovy_array_initializer_wrap = off +ij_groovy_assert_statement_wrap = off +ij_groovy_assignment_wrap = off +ij_groovy_binary_operation_wrap = off +ij_groovy_blank_lines_after_class_header = 0 +ij_groovy_blank_lines_after_imports = 1 +ij_groovy_blank_lines_after_package = 1 +ij_groovy_blank_lines_around_class = 1 +ij_groovy_blank_lines_around_field = 0 +ij_groovy_blank_lines_around_field_in_interface = 0 +ij_groovy_blank_lines_around_method = 1 +ij_groovy_blank_lines_around_method_in_interface = 1 +ij_groovy_blank_lines_before_imports = 1 +ij_groovy_blank_lines_before_method_body = 0 +ij_groovy_blank_lines_before_package = 0 +ij_groovy_block_brace_style = end_of_line +ij_groovy_block_comment_add_space = false +ij_groovy_block_comment_at_first_column = true +ij_groovy_call_parameters_new_line_after_left_paren = false +ij_groovy_call_parameters_right_paren_on_new_line = false +ij_groovy_call_parameters_wrap = off +ij_groovy_catch_on_new_line = false +ij_groovy_class_annotation_wrap = split_into_lines +ij_groovy_class_brace_style = end_of_line +ij_groovy_class_count_to_use_import_on_demand = 5 +ij_groovy_do_while_brace_force = never +ij_groovy_else_on_new_line = false +ij_groovy_enable_groovydoc_formatting = true +ij_groovy_enum_constants_wrap = off +ij_groovy_extends_keyword_wrap = off +ij_groovy_extends_list_wrap = off +ij_groovy_field_annotation_wrap = split_into_lines +ij_groovy_finally_on_new_line = false +ij_groovy_for_brace_force = never +ij_groovy_for_statement_new_line_after_left_paren = false +ij_groovy_for_statement_right_paren_on_new_line = false +ij_groovy_for_statement_wrap = off +ij_groovy_ginq_general_clause_wrap_policy = 2 +ij_groovy_ginq_having_wrap_policy = 1 +ij_groovy_ginq_indent_having_clause = true +ij_groovy_ginq_indent_on_clause = true +ij_groovy_ginq_on_wrap_policy = 1 +ij_groovy_ginq_space_after_keyword = true +ij_groovy_if_brace_force = never +ij_groovy_import_annotation_wrap = 2 +ij_groovy_imports_layout = *, |, javax.**, java.**, |, $* +ij_groovy_indent_case_from_switch = true +ij_groovy_indent_label_blocks = true +ij_groovy_insert_inner_class_imports = false +ij_groovy_keep_blank_lines_before_right_brace = 2 +ij_groovy_keep_blank_lines_in_code = 2 +ij_groovy_keep_blank_lines_in_declarations = 2 +ij_groovy_keep_control_statement_in_one_line = true +ij_groovy_keep_first_column_comment = true +ij_groovy_keep_indents_on_empty_lines = false +ij_groovy_keep_line_breaks = true +ij_groovy_keep_multiple_expressions_in_one_line = false +ij_groovy_keep_simple_blocks_in_one_line = false +ij_groovy_keep_simple_classes_in_one_line = true +ij_groovy_keep_simple_lambdas_in_one_line = true +ij_groovy_keep_simple_methods_in_one_line = true +ij_groovy_label_indent_absolute = false +ij_groovy_label_indent_size = 0 +ij_groovy_lambda_brace_style = end_of_line +ij_groovy_layout_static_imports_separately = true +ij_groovy_line_comment_add_space = false +ij_groovy_line_comment_add_space_on_reformat = false +ij_groovy_line_comment_at_first_column = true +ij_groovy_method_annotation_wrap = split_into_lines +ij_groovy_method_brace_style = end_of_line +ij_groovy_method_call_chain_wrap = off +ij_groovy_method_parameters_new_line_after_left_paren = false +ij_groovy_method_parameters_right_paren_on_new_line = false +ij_groovy_method_parameters_wrap = off +ij_groovy_modifier_list_wrap = false +ij_groovy_names_count_to_use_import_on_demand = 3 +ij_groovy_packages_to_use_import_on_demand = java.awt.*, javax.swing.* +ij_groovy_parameter_annotation_wrap = off +ij_groovy_parentheses_expression_new_line_after_left_paren = false +ij_groovy_parentheses_expression_right_paren_on_new_line = false +ij_groovy_prefer_parameters_wrap = false +ij_groovy_resource_list_new_line_after_left_paren = false +ij_groovy_resource_list_right_paren_on_new_line = false +ij_groovy_resource_list_wrap = off +ij_groovy_space_after_assert_separator = true +ij_groovy_space_after_colon = true +ij_groovy_space_after_comma = true +ij_groovy_space_after_comma_in_type_arguments = true +ij_groovy_space_after_for_semicolon = true +ij_groovy_space_after_quest = true +ij_groovy_space_after_type_cast = true +ij_groovy_space_before_annotation_parameter_list = false +ij_groovy_space_before_array_initializer_left_brace = false +ij_groovy_space_before_assert_separator = false +ij_groovy_space_before_catch_keyword = true +ij_groovy_space_before_catch_left_brace = true +ij_groovy_space_before_catch_parentheses = true +ij_groovy_space_before_class_left_brace = true +ij_groovy_space_before_closure_left_brace = true +ij_groovy_space_before_colon = true +ij_groovy_space_before_comma = false +ij_groovy_space_before_do_left_brace = true +ij_groovy_space_before_else_keyword = true +ij_groovy_space_before_else_left_brace = true +ij_groovy_space_before_finally_keyword = true +ij_groovy_space_before_finally_left_brace = true +ij_groovy_space_before_for_left_brace = true +ij_groovy_space_before_for_parentheses = true +ij_groovy_space_before_for_semicolon = false +ij_groovy_space_before_if_left_brace = true +ij_groovy_space_before_if_parentheses = true +ij_groovy_space_before_method_call_parentheses = false +ij_groovy_space_before_method_left_brace = true +ij_groovy_space_before_method_parentheses = false +ij_groovy_space_before_quest = true +ij_groovy_space_before_record_parentheses = false +ij_groovy_space_before_switch_left_brace = true +ij_groovy_space_before_switch_parentheses = true +ij_groovy_space_before_synchronized_left_brace = true +ij_groovy_space_before_synchronized_parentheses = true +ij_groovy_space_before_try_left_brace = true +ij_groovy_space_before_try_parentheses = true +ij_groovy_space_before_while_keyword = true +ij_groovy_space_before_while_left_brace = true +ij_groovy_space_before_while_parentheses = true +ij_groovy_space_in_named_argument = true +ij_groovy_space_in_named_argument_before_colon = false +ij_groovy_space_within_empty_array_initializer_braces = false +ij_groovy_space_within_empty_method_call_parentheses = false +ij_groovy_spaces_around_additive_operators = true +ij_groovy_spaces_around_assignment_operators = true +ij_groovy_spaces_around_bitwise_operators = true +ij_groovy_spaces_around_equality_operators = true +ij_groovy_spaces_around_lambda_arrow = true +ij_groovy_spaces_around_logical_operators = true +ij_groovy_spaces_around_multiplicative_operators = true +ij_groovy_spaces_around_regex_operators = true +ij_groovy_spaces_around_relational_operators = true +ij_groovy_spaces_around_shift_operators = true +ij_groovy_spaces_within_annotation_parentheses = false +ij_groovy_spaces_within_array_initializer_braces = false +ij_groovy_spaces_within_braces = true +ij_groovy_spaces_within_brackets = false +ij_groovy_spaces_within_cast_parentheses = false +ij_groovy_spaces_within_catch_parentheses = false +ij_groovy_spaces_within_for_parentheses = false +ij_groovy_spaces_within_gstring_injection_braces = false +ij_groovy_spaces_within_if_parentheses = false +ij_groovy_spaces_within_list_or_map = false +ij_groovy_spaces_within_method_call_parentheses = false +ij_groovy_spaces_within_method_parentheses = false +ij_groovy_spaces_within_parentheses = false +ij_groovy_spaces_within_switch_parentheses = false +ij_groovy_spaces_within_synchronized_parentheses = false +ij_groovy_spaces_within_try_parentheses = false +ij_groovy_spaces_within_tuple_expression = false +ij_groovy_spaces_within_while_parentheses = false +ij_groovy_special_else_if_treatment = true +ij_groovy_ternary_operation_wrap = off +ij_groovy_throws_keyword_wrap = off +ij_groovy_throws_list_wrap = off +ij_groovy_use_flying_geese_braces = false +ij_groovy_use_fq_class_names = false +ij_groovy_use_fq_class_names_in_javadoc = true +ij_groovy_use_relative_indents = false +ij_groovy_use_single_class_imports = true +ij_groovy_variable_annotation_wrap = off +ij_groovy_while_brace_force = never +ij_groovy_while_on_new_line = false +ij_groovy_wrap_chain_calls_after_dot = false +ij_groovy_wrap_long_lines = false + +[{*.gradle.kts,*.kt,*.kts,*.main.kts,*.space.kts}] +ij_kotlin_align_in_columns_case_branch = false +ij_kotlin_align_multiline_binary_operation = false +ij_kotlin_align_multiline_extends_list = false +ij_kotlin_align_multiline_method_parentheses = false +ij_kotlin_align_multiline_parameters = true +ij_kotlin_align_multiline_parameters_in_calls = false +ij_kotlin_allow_trailing_comma = false +ij_kotlin_allow_trailing_comma_on_call_site = false +ij_kotlin_assignment_wrap = off +ij_kotlin_blank_lines_after_class_header = 0 +ij_kotlin_blank_lines_around_block_when_branches = 0 +ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1 +ij_kotlin_block_comment_add_space = false +ij_kotlin_block_comment_at_first_column = true +ij_kotlin_call_parameters_new_line_after_left_paren = false +ij_kotlin_call_parameters_right_paren_on_new_line = false +ij_kotlin_call_parameters_wrap = off +ij_kotlin_catch_on_new_line = false +ij_kotlin_class_annotation_wrap = split_into_lines +ij_kotlin_continuation_indent_for_chained_calls = true +ij_kotlin_continuation_indent_for_expression_bodies = true +ij_kotlin_continuation_indent_in_argument_lists = true +ij_kotlin_continuation_indent_in_elvis = true +ij_kotlin_continuation_indent_in_if_conditions = true +ij_kotlin_continuation_indent_in_parameter_lists = true +ij_kotlin_continuation_indent_in_supertype_lists = true +ij_kotlin_else_on_new_line = false +ij_kotlin_enum_constants_wrap = off +ij_kotlin_extends_list_wrap = off +ij_kotlin_field_annotation_wrap = split_into_lines +ij_kotlin_finally_on_new_line = false +ij_kotlin_if_rparen_on_new_line = false +ij_kotlin_import_nested_classes = false +ij_kotlin_imports_layout = *, java.**, javax.**, kotlin.**, ^ +ij_kotlin_insert_whitespaces_in_simple_one_line_method = true +ij_kotlin_keep_blank_lines_before_right_brace = 2 +ij_kotlin_keep_blank_lines_in_code = 2 +ij_kotlin_keep_blank_lines_in_declarations = 2 +ij_kotlin_keep_first_column_comment = true +ij_kotlin_keep_indents_on_empty_lines = false +ij_kotlin_keep_line_breaks = true +ij_kotlin_lbrace_on_next_line = false +ij_kotlin_line_break_after_multiline_when_entry = true +ij_kotlin_line_comment_add_space = false +ij_kotlin_line_comment_add_space_on_reformat = false +ij_kotlin_line_comment_at_first_column = true +ij_kotlin_method_annotation_wrap = split_into_lines +ij_kotlin_method_call_chain_wrap = off +ij_kotlin_method_parameters_new_line_after_left_paren = false +ij_kotlin_method_parameters_right_paren_on_new_line = false +ij_kotlin_method_parameters_wrap = off +ij_kotlin_name_count_to_use_star_import = 5 +ij_kotlin_name_count_to_use_star_import_for_members = 3 +ij_kotlin_packages_to_use_import_on_demand = java.util.*, kotlinx.android.synthetic.**, io.ktor.** +ij_kotlin_parameter_annotation_wrap = off +ij_kotlin_space_after_comma = true +ij_kotlin_space_after_extend_colon = true +ij_kotlin_space_after_type_colon = true +ij_kotlin_space_before_catch_parentheses = true +ij_kotlin_space_before_comma = false +ij_kotlin_space_before_extend_colon = true +ij_kotlin_space_before_for_parentheses = true +ij_kotlin_space_before_if_parentheses = true +ij_kotlin_space_before_lambda_arrow = true +ij_kotlin_space_before_type_colon = false +ij_kotlin_space_before_when_parentheses = true +ij_kotlin_space_before_while_parentheses = true +ij_kotlin_spaces_around_additive_operators = true +ij_kotlin_spaces_around_assignment_operators = true +ij_kotlin_spaces_around_equality_operators = true +ij_kotlin_spaces_around_function_type_arrow = true +ij_kotlin_spaces_around_logical_operators = true +ij_kotlin_spaces_around_multiplicative_operators = true +ij_kotlin_spaces_around_range = false +ij_kotlin_spaces_around_relational_operators = true +ij_kotlin_spaces_around_unary_operator = false +ij_kotlin_spaces_around_when_arrow = true +ij_kotlin_variable_annotation_wrap = off +ij_kotlin_while_on_new_line = false +ij_kotlin_wrap_elvis_expressions = 1 +ij_kotlin_wrap_expression_body_functions = 0 +ij_kotlin_wrap_first_method_in_call_chain = false + +[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}] +indent_size = 2 +ij_json_array_wrapping = split_into_lines +ij_json_keep_blank_lines_in_code = 0 +ij_json_keep_indents_on_empty_lines = false +ij_json_keep_line_breaks = true +ij_json_keep_trailing_comma = false +ij_json_object_wrapping = split_into_lines +ij_json_property_alignment = do_not_align +ij_json_space_after_colon = true +ij_json_space_after_comma = true +ij_json_space_before_colon = false +ij_json_space_before_comma = false +ij_json_spaces_within_braces = false +ij_json_spaces_within_brackets = false +ij_json_wrap_long_lines = false + +[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}] +ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3 +ij_html_align_attributes = true +ij_html_align_text = false +ij_html_attribute_wrap = normal +ij_html_block_comment_add_space = false +ij_html_block_comment_at_first_column = true +ij_html_do_not_align_children_of_min_lines = 0 +ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p +ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot +ij_html_enforce_quotes = false +ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var +ij_html_keep_blank_lines = 2 +ij_html_keep_indents_on_empty_lines = false +ij_html_keep_line_breaks = true +ij_html_keep_line_breaks_in_text = true +ij_html_keep_whitespaces = false +ij_html_keep_whitespaces_inside = span, pre, textarea +ij_html_line_comment_at_first_column = true +ij_html_new_line_after_last_attribute = never +ij_html_new_line_before_first_attribute = never +ij_html_quote_style = double +ij_html_remove_new_line_before_tags = br +ij_html_space_after_tag_name = false +ij_html_space_around_equality_in_attribute = false +ij_html_space_inside_empty_tag = false +ij_html_text_wrap = normal + +[{*.http,*.rest}] +indent_size = 0 +ij_continuation_indent_size = 4 +ij_http request_call_parameters_wrap = normal + +[{*.jsf,*.jsp,*.jspf,*.tag,*.tagf,*.xjsp}] +ij_jsp_jsp_prefer_comma_separated_import_list = false +ij_jsp_keep_indents_on_empty_lines = false + +[{*.jspx,*.tagx}] +ij_jspx_keep_indents_on_empty_lines = false + +[{*.markdown,*.md}] +ij_markdown_force_one_space_after_blockquote_symbol = true +ij_markdown_force_one_space_after_header_symbol = true +ij_markdown_force_one_space_after_list_bullet = true +ij_markdown_force_one_space_between_words = true +ij_markdown_format_tables = true +ij_markdown_insert_quote_arrows_on_wrap = true +ij_markdown_keep_indents_on_empty_lines = false +ij_markdown_keep_line_breaks_inside_text_blocks = true +ij_markdown_max_lines_around_block_elements = 1 +ij_markdown_max_lines_around_header = 1 +ij_markdown_max_lines_between_paragraphs = 1 +ij_markdown_min_lines_around_block_elements = 1 +ij_markdown_min_lines_around_header = 1 +ij_markdown_min_lines_between_paragraphs = 1 +ij_markdown_wrap_text_if_long = true +ij_markdown_wrap_text_inside_blockquotes = true + +[{*.pb,*.textproto}] +indent_size = 2 +tab_width = 2 +ij_continuation_indent_size = 4 +ij_prototext_keep_blank_lines_in_code = 2 +ij_prototext_keep_indents_on_empty_lines = false +ij_prototext_keep_line_breaks = true +ij_prototext_space_after_colon = true +ij_prototext_space_after_comma = true +ij_prototext_space_before_colon = false +ij_prototext_space_before_comma = false +ij_prototext_spaces_within_braces = true +ij_prototext_spaces_within_brackets = false + +[{*.properties,spring.handlers,spring.schemas}] +ij_properties_align_group_field_declarations = false +ij_properties_keep_blank_lines = false +ij_properties_key_value_delimiter = equals +ij_properties_spaces_around_key_value_delimiter = false + +[{*.py,*.pyw}] +ij_python_align_collections_and_comprehensions = true +ij_python_align_multiline_imports = true +ij_python_align_multiline_parameters = true +ij_python_align_multiline_parameters_in_calls = true +ij_python_blank_line_at_file_end = true +ij_python_blank_lines_after_imports = 1 +ij_python_blank_lines_after_local_imports = 0 +ij_python_blank_lines_around_class = 1 +ij_python_blank_lines_around_method = 1 +ij_python_blank_lines_around_top_level_classes_functions = 2 +ij_python_blank_lines_before_first_method = 0 +ij_python_call_parameters_new_line_after_left_paren = false +ij_python_call_parameters_right_paren_on_new_line = false +ij_python_call_parameters_wrap = normal +ij_python_dict_alignment = 0 +ij_python_dict_new_line_after_left_brace = false +ij_python_dict_new_line_before_right_brace = false +ij_python_dict_wrapping = 1 +ij_python_from_import_new_line_after_left_parenthesis = false +ij_python_from_import_new_line_before_right_parenthesis = false +ij_python_from_import_parentheses_force_if_multiline = false +ij_python_from_import_trailing_comma_if_multiline = false +ij_python_from_import_wrapping = 1 +ij_python_hang_closing_brackets = false +ij_python_keep_blank_lines_in_code = 1 +ij_python_keep_blank_lines_in_declarations = 1 +ij_python_keep_indents_on_empty_lines = false +ij_python_keep_line_breaks = true +ij_python_method_parameters_new_line_after_left_paren = false +ij_python_method_parameters_right_paren_on_new_line = false +ij_python_method_parameters_wrap = normal +ij_python_new_line_after_colon = false +ij_python_new_line_after_colon_multi_clause = true +ij_python_optimize_imports_always_split_from_imports = false +ij_python_optimize_imports_case_insensitive_order = false +ij_python_optimize_imports_join_from_imports_with_same_source = false +ij_python_optimize_imports_sort_by_type_first = true +ij_python_optimize_imports_sort_imports = true +ij_python_optimize_imports_sort_names_in_from_imports = false +ij_python_space_after_comma = true +ij_python_space_after_number_sign = true +ij_python_space_after_py_colon = true +ij_python_space_before_backslash = true +ij_python_space_before_comma = false +ij_python_space_before_for_semicolon = false +ij_python_space_before_lbracket = false +ij_python_space_before_method_call_parentheses = false +ij_python_space_before_method_parentheses = false +ij_python_space_before_number_sign = true +ij_python_space_before_py_colon = false +ij_python_space_within_empty_method_call_parentheses = false +ij_python_space_within_empty_method_parentheses = false +ij_python_spaces_around_additive_operators = true +ij_python_spaces_around_assignment_operators = true +ij_python_spaces_around_bitwise_operators = true +ij_python_spaces_around_eq_in_keyword_argument = false +ij_python_spaces_around_eq_in_named_parameter = false +ij_python_spaces_around_equality_operators = true +ij_python_spaces_around_multiplicative_operators = true +ij_python_spaces_around_power_operator = true +ij_python_spaces_around_relational_operators = true +ij_python_spaces_around_shift_operators = true +ij_python_spaces_within_braces = false +ij_python_spaces_within_brackets = false +ij_python_spaces_within_method_call_parentheses = false +ij_python_spaces_within_method_parentheses = false +ij_python_use_continuation_indent_for_arguments = false +ij_python_use_continuation_indent_for_collection_and_comprehensions = false +ij_python_use_continuation_indent_for_parameters = true +ij_python_wrap_long_lines = false + +[{*.qute.htm,*.qute.html,*.qute.json,*.qute.txt,*.qute.yaml,*.qute.yml}] +ij_qute_keep_indents_on_empty_lines = false + +[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}] +ij_toml_keep_indents_on_empty_lines = false + +[{*.yaml,*.yml}] +indent_size = 2 +ij_yaml_align_values_properties = do_not_align +ij_yaml_autoinsert_sequence_marker = true +ij_yaml_block_mapping_on_new_line = false +ij_yaml_indent_sequence_value = true +ij_yaml_keep_indents_on_empty_lines = false +ij_yaml_keep_line_breaks = true +ij_yaml_sequence_on_new_line = false +ij_yaml_space_before_colon = false +ij_yaml_spaces_within_braces = true +ij_yaml_spaces_within_brackets = true diff --git a/.github/workflows/junit.yml b/.github/workflows/junit.yml index 8bef2b6..0436b0a 100644 --- a/.github/workflows/junit.yml +++ b/.github/workflows/junit.yml @@ -1,6 +1,6 @@ name: JUnit -on: [push] +on: [ push ] jobs: test: diff --git a/README.md b/README.md index 645c670..b27e288 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,4 @@ QueryResult result = connection.insert() This repository contains some basic rules specified in Code of Conduct file.
Code of Conduct
-Database icons created by Freepik - Flaticon +Database icons created by Freepik - Flaticon \ No newline at end of file diff --git a/api/src/main/java/me/zort/sqllib/api/Executive.java b/api/src/main/java/me/zort/sqllib/api/Executive.java index cee7a62..867c374 100644 --- a/api/src/main/java/me/zort/sqllib/api/Executive.java +++ b/api/src/main/java/me/zort/sqllib/api/Executive.java @@ -2,6 +2,6 @@ public interface Executive { - SQLConnection getConnection(); + SQLConnection getConnection(); } diff --git a/api/src/main/java/me/zort/sqllib/api/ISQLConnectionBuilder.java b/api/src/main/java/me/zort/sqllib/api/ISQLConnectionBuilder.java index cb7cc48..9d7d200 100644 --- a/api/src/main/java/me/zort/sqllib/api/ISQLConnectionBuilder.java +++ b/api/src/main/java/me/zort/sqllib/api/ISQLConnectionBuilder.java @@ -1,7 +1,7 @@ package me.zort.sqllib.api; public interface ISQLConnectionBuilder { - - C build(ISQLDatabaseOptions options); - + + C build(ISQLDatabaseOptions options); + } diff --git a/api/src/main/java/me/zort/sqllib/api/ISQLDatabaseOptions.java b/api/src/main/java/me/zort/sqllib/api/ISQLDatabaseOptions.java index f8be621..8f9b91c 100644 --- a/api/src/main/java/me/zort/sqllib/api/ISQLDatabaseOptions.java +++ b/api/src/main/java/me/zort/sqllib/api/ISQLDatabaseOptions.java @@ -5,16 +5,24 @@ public interface ISQLDatabaseOptions { - void setAutoReconnect(boolean autoReconnect); - void setDebug(boolean debug); - void setLogSqlErrors(boolean logSqlErrors); - void setNamingStrategy(NamingStrategy namingStrategy); - void setGson(Gson gson); - - boolean isAutoReconnect(); - boolean isDebug(); - boolean isLogSqlErrors(); - NamingStrategy getNamingStrategy(); - Gson getGson(); + void setAutoReconnect(boolean autoReconnect); + + void setDebug(boolean debug); + + void setLogSqlErrors(boolean logSqlErrors); + + void setNamingStrategy(NamingStrategy namingStrategy); + + void setGson(Gson gson); + + boolean isAutoReconnect(); + + boolean isDebug(); + + boolean isLogSqlErrors(); + + NamingStrategy getNamingStrategy(); + + Gson getGson(); } diff --git a/api/src/main/java/me/zort/sqllib/api/ObjectMapper.java b/api/src/main/java/me/zort/sqllib/api/ObjectMapper.java index 525143b..5cdffc2 100644 --- a/api/src/main/java/me/zort/sqllib/api/ObjectMapper.java +++ b/api/src/main/java/me/zort/sqllib/api/ObjectMapper.java @@ -8,15 +8,16 @@ public interface ObjectMapper { - void registerBackupValueResolver(@NotNull FieldValueResolver resolver); - T assignValues(Row row, Class typeClass); + void registerBackupValueResolver(@NotNull FieldValueResolver resolver); - interface FieldValueResolver { - Object obtainValue(SQLConnection connection, - AnnotatedElement element, - Row row, - String fieldName, - String convertedName, - Type type); - } + T assignValues(Row row, Class typeClass); + + interface FieldValueResolver { + Object obtainValue(SQLConnection connection, + AnnotatedElement element, + Row row, + String fieldName, + String convertedName, + Type type); + } } diff --git a/api/src/main/java/me/zort/sqllib/api/Query.java b/api/src/main/java/me/zort/sqllib/api/Query.java index e4e51b2..63cb646 100644 --- a/api/src/main/java/me/zort/sqllib/api/Query.java +++ b/api/src/main/java/me/zort/sqllib/api/Query.java @@ -4,25 +4,28 @@ /** * This class represents a query. + * * @author ZorTik */ public interface Query { - String buildQuery(); + String buildQuery(); - /** - * Returns the highest parent of this query - * tree. - * @return The parent. - */ - default Query getAncestor() { - return this; - } + /** + * Returns the highest parent of this query + * tree. + * + * @return The parent. + */ + default Query getAncestor() { + return this; + } - default boolean isAncestor() { - return getAncestor() == this; - } + default boolean isAncestor() { + return getAncestor() == this; + } - default void errorSignal(SQLException e) {} + default void errorSignal(SQLException e) { + } } diff --git a/api/src/main/java/me/zort/sqllib/api/SQLConnection.java b/api/src/main/java/me/zort/sqllib/api/SQLConnection.java index 132aa99..f41b995 100644 --- a/api/src/main/java/me/zort/sqllib/api/SQLConnection.java +++ b/api/src/main/java/me/zort/sqllib/api/SQLConnection.java @@ -13,30 +13,30 @@ */ public interface SQLConnection { - /** - * Tries to connect to remote SQL server. - * - * @return True if connection was successful, - * otherwise false. - */ - boolean connect(); - - /** - * Tries to disconnect from remote SQL server. - */ - void disconnect(); - - /** - * Returns current running connection with - * SQL server. - * - * @return The connection. - */ - @Nullable - Connection getConnection(); - - default boolean isConnected() { - return getConnection() != null; - } + /** + * Tries to connect to remote SQL server. + * + * @return True if connection was successful, + * otherwise false. + */ + boolean connect(); + + /** + * Tries to disconnect from remote SQL server. + */ + void disconnect(); + + /** + * Returns current running connection with + * SQL server. + * + * @return The connection. + */ + @Nullable + Connection getConnection(); + + default boolean isConnected() { + return getConnection() != null; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/SQLEndpoint.java b/api/src/main/java/me/zort/sqllib/api/SQLEndpoint.java index 6bc582a..7dcd956 100644 --- a/api/src/main/java/me/zort/sqllib/api/SQLEndpoint.java +++ b/api/src/main/java/me/zort/sqllib/api/SQLEndpoint.java @@ -2,12 +2,14 @@ public interface SQLEndpoint { - String buildJdbc(); - String getUsername(); - String getPassword(); + String buildJdbc(); - default boolean isValid() { - return true; - } + String getUsername(); + + String getPassword(); + + default boolean isValid() { + return true; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/StatementFactory.java b/api/src/main/java/me/zort/sqllib/api/StatementFactory.java index 10812a3..fd3525b 100644 --- a/api/src/main/java/me/zort/sqllib/api/StatementFactory.java +++ b/api/src/main/java/me/zort/sqllib/api/StatementFactory.java @@ -13,13 +13,13 @@ */ public interface StatementFactory { - /** - * Prepares the statement for executing in {@link SQLConnection}. - * - * @param connection The connection to use. - * @return The prepared statement. - * @throws SQLException If an error occurs while preparing. - */ - T prepare(Connection connection) throws SQLException; + /** + * Prepares the statement for executing in {@link SQLConnection}. + * + * @param connection The connection to use. + * @return The prepared statement. + * @throws SQLException If an error occurs while preparing. + */ + T prepare(Connection connection) throws SQLException; } diff --git a/api/src/main/java/me/zort/sqllib/api/cache/CacheManager.java b/api/src/main/java/me/zort/sqllib/api/cache/CacheManager.java index c0bef44..701d4af 100644 --- a/api/src/main/java/me/zort/sqllib/api/cache/CacheManager.java +++ b/api/src/main/java/me/zort/sqllib/api/cache/CacheManager.java @@ -14,39 +14,41 @@ */ public interface CacheManager { - /** - * Sets a query result to the cache. - * If the query is already cached, it should be overwritten. - * - * @param query Query that was executed - * @param result Result - */ - void set(@NotNull Query query, @NotNull QueryResult result); + /** + * Sets a query result to the cache. + * If the query is already cached, it should be overwritten. + * + * @param query Query that was executed + * @param result Result + */ + void set(@NotNull Query query, @NotNull QueryResult result); - /** - * Returns a query result from the cache, or null if - * the query is not cached. - * - * @param query Query that was executed - * @param isExec Whether the query is an exec (no ResultSet) query - * @return The nullable query result - */ - @Nullable QueryResult get(@NotNull Query query, boolean isExec); + /** + * Returns a query result from the cache, or null if + * the query is not cached. + * + * @param query Query that was executed + * @param isExec Whether the query is an exec (no ResultSet) query + * @return The nullable query result + */ + @Nullable QueryResult get(@NotNull Query query, boolean isExec); - /** - * Returns a cache manager that does not cache anything. - * - * @return The cache manager - */ - static CacheManager noCache() { - return new CacheManager() { - @Override - public void set(@NotNull Query query, @NotNull QueryResult result) {} - @Override - public @Nullable QueryResult get(@NotNull Query query, boolean isExec) { - return null; - } - }; - } + /** + * Returns a cache manager that does not cache anything. + * + * @return The cache manager + */ + static CacheManager noCache() { + return new CacheManager() { + @Override + public void set(@NotNull Query query, @NotNull QueryResult result) { + } + + @Override + public @Nullable QueryResult get(@NotNull Query query, boolean isExec) { + return null; + } + }; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/data/QueryResult.java b/api/src/main/java/me/zort/sqllib/api/data/QueryResult.java index 10094fb..e8c8ded 100644 --- a/api/src/main/java/me/zort/sqllib/api/data/QueryResult.java +++ b/api/src/main/java/me/zort/sqllib/api/data/QueryResult.java @@ -9,23 +9,25 @@ */ public interface QueryResult { - boolean isSuccessful(); - @Nullable - String getRejectMessage(); - - QueryResult noChangesResult = successful(); - - static QueryResult successful() { - return new QueryResult() { - @Override - public boolean isSuccessful() { - return true; - } - @Override - public @Nullable String getRejectMessage() { - return null; - } - }; - } + boolean isSuccessful(); + + @Nullable + String getRejectMessage(); + + QueryResult noChangesResult = successful(); + + static QueryResult successful() { + return new QueryResult() { + @Override + public boolean isSuccessful() { + return true; + } + + @Override + public @Nullable String getRejectMessage() { + return null; + } + }; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/data/QueryRowsResult.java b/api/src/main/java/me/zort/sqllib/api/data/QueryRowsResult.java index 932e14a..2df65e7 100644 --- a/api/src/main/java/me/zort/sqllib/api/data/QueryRowsResult.java +++ b/api/src/main/java/me/zort/sqllib/api/data/QueryRowsResult.java @@ -7,32 +7,32 @@ @Getter public class QueryRowsResult extends LinkedList implements QueryResult { - private final boolean successful; - private String rejectMessage = null; - - public QueryRowsResult(boolean successful) { - this(successful, null); - } - - public QueryRowsResult(boolean successful, String rejectMessage) { - this.successful = successful; - rejectMessage(rejectMessage); - } - - public QueryRowsResult rejectMessage(String message) { - if (rejectMessage != null) - throw new RuntimeException("Reject message is already set!"); - - this.rejectMessage = message; - return this; - } - - @Override - public String toString() { - return "QueryRowsResult{" + - "successful=" + successful + - ", rejectMessage='" + rejectMessage + '\'' + - ", data=" + super.toString() + - '}'; - } + private final boolean successful; + private String rejectMessage = null; + + public QueryRowsResult(boolean successful) { + this(successful, null); + } + + public QueryRowsResult(boolean successful, String rejectMessage) { + this.successful = successful; + rejectMessage(rejectMessage); + } + + public QueryRowsResult rejectMessage(String message) { + if (rejectMessage != null) + throw new RuntimeException("Reject message is already set!"); + + this.rejectMessage = message; + return this; + } + + @Override + public String toString() { + return "QueryRowsResult{" + + "successful=" + successful + + ", rejectMessage='" + rejectMessage + '\'' + + ", data=" + super.toString() + + '}'; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/data/Row.java b/api/src/main/java/me/zort/sqllib/api/data/Row.java index 98d6dab..7ed1857 100644 --- a/api/src/main/java/me/zort/sqllib/api/data/Row.java +++ b/api/src/main/java/me/zort/sqllib/api/data/Row.java @@ -4,36 +4,36 @@ public class Row extends HashMap { - public String getString(String key) { - return (String) get(key); - } + public String getString(String key) { + return (String) get(key); + } - public int getInt(String key) { - return (int) get(key); - } + public int getInt(String key) { + return (int) get(key); + } - public long getLong(String key) { - return (long) get(key); - } + public long getLong(String key) { + return (long) get(key); + } - public double getDouble(String key) { - return (double) get(key); - } + public double getDouble(String key) { + return (double) get(key); + } - public float getFloat(String key) { - return (float) get(key); - } + public float getFloat(String key) { + return (float) get(key); + } - public boolean getBoolean(String key) { - return (boolean) get(key); - } + public boolean getBoolean(String key) { + return (boolean) get(key); + } - public byte getByte(String key) { - return (byte) get(key); - } + public byte getByte(String key) { + return (byte) get(key); + } - public short getShort(String key) { - return (short) get(key); - } + public short getShort(String key) { + return (short) get(key); + } } diff --git a/api/src/main/java/me/zort/sqllib/api/mapping/MappingProxyInstance.java b/api/src/main/java/me/zort/sqllib/api/mapping/MappingProxyInstance.java index c121730..cae5d45 100644 --- a/api/src/main/java/me/zort/sqllib/api/mapping/MappingProxyInstance.java +++ b/api/src/main/java/me/zort/sqllib/api/mapping/MappingProxyInstance.java @@ -8,7 +8,8 @@ public interface MappingProxyInstance extends InvocationHandler { - Class getTypeClass(); - List getTableSchemas(NamingStrategy namingStrategy, boolean sqLite); + Class getTypeClass(); + + List getTableSchemas(NamingStrategy namingStrategy, boolean sqLite); } diff --git a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingFactory.java b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingFactory.java index b078f48..99cac50 100644 --- a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingFactory.java +++ b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingFactory.java @@ -10,16 +10,17 @@ */ public interface StatementMappingFactory { - /** - * Creates a new StatementMapping for the given interface class that - * is responsible for handling that specific interface. - * - * @param interfaceClass The interface class - * @param connection The connection to use. - * @return The StatementMapping. - * @param The interface class type. - */ - StatementMappingStrategy strategy(Class interfaceClass, SQLConnection connection); - StatementMappingResultAdapter resultAdapter(); + /** + * Creates a new StatementMapping for the given interface class that + * is responsible for handling that specific interface. + * + * @param interfaceClass The interface class + * @param connection The connection to use. + * @param The interface class type. + * @return The StatementMapping. + */ + StatementMappingStrategy strategy(Class interfaceClass, SQLConnection connection); + + StatementMappingResultAdapter resultAdapter(); } diff --git a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingOptions.java b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingOptions.java index cd41f20..cb5ec45 100644 --- a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingOptions.java +++ b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingOptions.java @@ -8,27 +8,27 @@ public interface StatementMappingOptions { - @Nullable - String getTable(); + @Nullable + String getTable(); - class Builder { - // Default values - private String table = null; + class Builder { + // Default values + private String table = null; - public @NotNull Builder table(final @Nullable String table) { - this.table = table; - return this; - } - - public @NotNull StatementMappingOptions build() { - return new LocalOptionsImplementation(table); - } + public @NotNull Builder table(final @Nullable String table) { + this.table = table; + return this; } - @AllArgsConstructor(access = AccessLevel.PRIVATE) - @Getter - class LocalOptionsImplementation implements StatementMappingOptions { - private String table; + public @NotNull StatementMappingOptions build() { + return new LocalOptionsImplementation(table); } + } + + @AllArgsConstructor(access = AccessLevel.PRIVATE) + @Getter + class LocalOptionsImplementation implements StatementMappingOptions { + private String table; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingRegistry.java b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingRegistry.java index 34a8bf2..40290f4 100644 --- a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingRegistry.java +++ b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingRegistry.java @@ -9,7 +9,8 @@ */ public interface StatementMappingRegistry { - void registerProxy(MappingProxyInstance proxyInstance); - List> getProxyInstances(); + void registerProxy(MappingProxyInstance proxyInstance); + + List> getProxyInstances(); } diff --git a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingResultAdapter.java b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingResultAdapter.java index 3658786..945ad5a 100644 --- a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingResultAdapter.java +++ b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingResultAdapter.java @@ -13,23 +13,23 @@ */ public interface StatementMappingResultAdapter { - /** - * Adapts invoked {@link StatementMappingStrategy} method QueryResult to - * the final result that can be passed to proxy instance. - * - * @param method The invoked proxy method. - * @param result The QueryResult of the invoked method. - * @return The adapted result. - */ - Object adaptResult(Method method, QueryResult result); + /** + * Adapts invoked {@link StatementMappingStrategy} method QueryResult to + * the final result that can be passed to proxy instance. + * + * @param method The invoked proxy method. + * @param result The QueryResult of the invoked method. + * @return The adapted result. + */ + Object adaptResult(Method method, QueryResult result); - /** - * Retrieves type of entity that needs to be mapped in the request - * to be passed in adaptResult as type in QueryResult. - * - * @param method The invoked proxy method. - * @return The type of entity that needs to be mapped. - */ - Class retrieveResultType(Method method); + /** + * Retrieves type of entity that needs to be mapped in the request + * to be passed in adaptResult as type in QueryResult. + * + * @param method The invoked proxy method. + * @return The type of entity that needs to be mapped. + */ + Class retrieveResultType(Method method); } diff --git a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingStrategy.java b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingStrategy.java index 06bae93..6e885d8 100644 --- a/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingStrategy.java +++ b/api/src/main/java/me/zort/sqllib/api/mapping/StatementMappingStrategy.java @@ -14,27 +14,27 @@ */ public interface StatementMappingStrategy { - /** - * Executes query based on invoked method with invoked args from - * proxy instance. MapTo is used as type of entity to be mapped in the - * request. If there is no mapping required, MapTo can be null. - * - * @param options The mapping options. - * @param method The method that was executed in the proxy. - * @param args The arguments passed. - * @param mapTo The type of entity that needs to be mapped. - * @return The QueryResult of the executed query. - */ - QueryResult executeQuery(StatementMappingOptions options, Method method, Object[] args, @Nullable Class mapTo); + /** + * Executes query based on invoked method with invoked args from + * proxy instance. MapTo is used as type of entity to be mapped in the + * request. If there is no mapping required, MapTo can be null. + * + * @param options The mapping options. + * @param method The method that was executed in the proxy. + * @param args The arguments passed. + * @param mapTo The type of entity that needs to be mapped. + * @return The QueryResult of the executed query. + */ + QueryResult executeQuery(StatementMappingOptions options, Method method, Object[] args, @Nullable Class mapTo); - /** - * Checks if the method is eligible for mapping. If this returns false, - * the method is executed in proxy mapping as normal method, eg. does not - * return any mapping results. - * - * @param method The method that was executed in the proxy. - * @return True if the method is eligible for mapping, or false. - */ - boolean isMappingMethod(Method method); + /** + * Checks if the method is eligible for mapping. If this returns false, + * the method is executed in proxy mapping as normal method, eg. does not + * return any mapping results. + * + * @param method The method that was executed in the proxy. + * @return True if the method is eligible for mapping, or false. + */ + boolean isMappingMethod(Method method); } diff --git a/api/src/main/java/me/zort/sqllib/api/model/ColumnDefinition.java b/api/src/main/java/me/zort/sqllib/api/model/ColumnDefinition.java index c8e5e1f..aafdb7a 100644 --- a/api/src/main/java/me/zort/sqllib/api/model/ColumnDefinition.java +++ b/api/src/main/java/me/zort/sqllib/api/model/ColumnDefinition.java @@ -7,12 +7,12 @@ @Getter public class ColumnDefinition { - private final String name; - private final String type; + private final String name; + private final String type; - @Override - public String toString() { - return name + " " + type; - } + @Override + public String toString() { + return name + " " + type; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/model/SchemaSynchronizer.java b/api/src/main/java/me/zort/sqllib/api/model/SchemaSynchronizer.java index 798f41d..9dc7b91 100644 --- a/api/src/main/java/me/zort/sqllib/api/model/SchemaSynchronizer.java +++ b/api/src/main/java/me/zort/sqllib/api/model/SchemaSynchronizer.java @@ -10,15 +10,15 @@ */ public interface SchemaSynchronizer { - /** - * Table synchronization logic in provided source. - * This should update the 'to' schema to be synchronized with the 'from' - * schema. - * - * @param source The source where to apply changes - * @param from The template schema - * @param to The schema to be updated to match 'from' schema - */ - QueryResult synchronize(S source, TableSchema from, TableSchema to); + /** + * Table synchronization logic in provided source. + * This should update the 'to' schema to be synchronized with the 'from' + * schema. + * + * @param source The source where to apply changes + * @param from The template schema + * @param to The schema to be updated to match 'from' schema + */ + QueryResult synchronize(S source, TableSchema from, TableSchema to); } diff --git a/api/src/main/java/me/zort/sqllib/api/model/TableSchema.java b/api/src/main/java/me/zort/sqllib/api/model/TableSchema.java index c378907..263d882 100644 --- a/api/src/main/java/me/zort/sqllib/api/model/TableSchema.java +++ b/api/src/main/java/me/zort/sqllib/api/model/TableSchema.java @@ -2,60 +2,60 @@ public class TableSchema { - private final String table; - private final ColumnDefinition[] definitions; + private final String table; + private final ColumnDefinition[] definitions; - public TableSchema(String table, ColumnDefinition[] definitions) { - this.table = table; - this.definitions = definitions; - } + public TableSchema(String table, ColumnDefinition[] definitions) { + this.table = table; + this.definitions = definitions; + } - public ColumnDefinition getDefinitionDetails(int index) { - return definitions[index]; - } + public ColumnDefinition getDefinitionDetails(int index) { + return definitions[index]; + } - public ColumnDefinition getDefinitionDetails(String name) { - for (ColumnDefinition definition : definitions) { - if (definition.getName().equals(name)) return definition; - } - return null; + public ColumnDefinition getDefinitionDetails(String name) { + for (ColumnDefinition definition : definitions) { + if (definition.getName().equals(name)) return definition; } + return null; + } - public String getDefinitionName(int index) { - return getDefinitionDetails(index).getName(); - } + public String getDefinitionName(int index) { + return getDefinitionDetails(index).getName(); + } - public String getDefinitionType(int index) { - return getDefinitionDetails(index).getType(); - } + public String getDefinitionType(int index) { + return getDefinitionDetails(index).getType(); + } - public String getDefinition(int index) { - ColumnDefinition details = getDefinitionDetails(index); - return details.getName() + " " + details.getType(); - } + public String getDefinition(int index) { + ColumnDefinition details = getDefinitionDetails(index); + return details.getName() + " " + details.getType(); + } - public String[] getDefinitions() { - String[] definitions = new String[this.definitions.length]; - for (int i = 0; i < definitions.length; i++) { - definitions[i] = getDefinition(i); - } - return definitions; + public String[] getDefinitions() { + String[] definitions = new String[this.definitions.length]; + for (int i = 0; i < definitions.length; i++) { + definitions[i] = getDefinition(i); } + return definitions; + } - public String[] getDefinitionNames() { - String[] definitions = new String[this.definitions.length]; - for (int i = 0; i < definitions.length; i++) { - definitions[i] = getDefinitionName(i); - } - return definitions; + public String[] getDefinitionNames() { + String[] definitions = new String[this.definitions.length]; + for (int i = 0; i < definitions.length; i++) { + definitions[i] = getDefinitionName(i); } + return definitions; + } - public String getTable() { - return table; - } + public String getTable() { + return table; + } - public int size() { - return definitions.length; - } + public int size() { + return definitions.length; + } } diff --git a/api/src/main/java/me/zort/sqllib/api/model/TableSchemaBuilder.java b/api/src/main/java/me/zort/sqllib/api/model/TableSchemaBuilder.java index 15106c4..3a1a5a5 100644 --- a/api/src/main/java/me/zort/sqllib/api/model/TableSchemaBuilder.java +++ b/api/src/main/java/me/zort/sqllib/api/model/TableSchemaBuilder.java @@ -2,6 +2,6 @@ public interface TableSchemaBuilder { - TableSchema buildTableSchema(); + TableSchema buildTableSchema(); } diff --git a/api/src/main/java/me/zort/sqllib/api/options/NamingStrategy.java b/api/src/main/java/me/zort/sqllib/api/options/NamingStrategy.java index c5f91b3..75480a1 100644 --- a/api/src/main/java/me/zort/sqllib/api/options/NamingStrategy.java +++ b/api/src/main/java/me/zort/sqllib/api/options/NamingStrategy.java @@ -7,6 +7,6 @@ */ public interface NamingStrategy { - String fieldNameToColumn(String str); + String fieldNameToColumn(String str); } diff --git a/api/src/main/java/me/zort/sqllib/internal/annotation/Default.java b/api/src/main/java/me/zort/sqllib/internal/annotation/Default.java index c2ba457..14398ac 100644 --- a/api/src/main/java/me/zort/sqllib/internal/annotation/Default.java +++ b/api/src/main/java/me/zort/sqllib/internal/annotation/Default.java @@ -8,5 +8,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Default { - String value(); + String value(); } diff --git a/api/src/main/java/me/zort/sqllib/internal/annotation/JsonField.java b/api/src/main/java/me/zort/sqllib/internal/annotation/JsonField.java index e627a74..48d469c 100644 --- a/api/src/main/java/me/zort/sqllib/internal/annotation/JsonField.java +++ b/api/src/main/java/me/zort/sqllib/internal/annotation/JsonField.java @@ -7,4 +7,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) -public @interface JsonField {} +public @interface JsonField { +} diff --git a/api/src/main/java/me/zort/sqllib/internal/annotation/LinkedOne.java b/api/src/main/java/me/zort/sqllib/internal/annotation/LinkedOne.java index b08e38f..54ba07e 100644 --- a/api/src/main/java/me/zort/sqllib/internal/annotation/LinkedOne.java +++ b/api/src/main/java/me/zort/sqllib/internal/annotation/LinkedOne.java @@ -29,18 +29,20 @@ @Target(ElementType.FIELD) public @interface LinkedOne { - /** - * This represents name of current table column where is - * stored id of the linked object in target table. - * @return The column name. - */ - String localColumn(); + /** + * This represents name of current table column where is + * stored id of the linked object in target table. + * + * @return The column name. + */ + String localColumn(); - /** - * This represents name of the target table where is - * stored the linked object. - * @return The table name. - */ - String targetTable(); + /** + * This represents name of the target table where is + * stored the linked object. + * + * @return The table name. + */ + String targetTable(); } diff --git a/api/src/main/java/me/zort/sqllib/internal/annotation/NullableField.java b/api/src/main/java/me/zort/sqllib/internal/annotation/NullableField.java index ef64822..db9212b 100644 --- a/api/src/main/java/me/zort/sqllib/internal/annotation/NullableField.java +++ b/api/src/main/java/me/zort/sqllib/internal/annotation/NullableField.java @@ -29,6 +29,6 @@ @Target(ElementType.FIELD) public @interface NullableField { - boolean nullable() default true; + boolean nullable() default true; } diff --git a/api/src/main/java/me/zort/sqllib/internal/annotation/PrimaryKey.java b/api/src/main/java/me/zort/sqllib/internal/annotation/PrimaryKey.java index 7bc354c..15cd6b5 100644 --- a/api/src/main/java/me/zort/sqllib/internal/annotation/PrimaryKey.java +++ b/api/src/main/java/me/zort/sqllib/internal/annotation/PrimaryKey.java @@ -8,17 +8,19 @@ /** * This annotation is used to mark a field as a primary key * for some operations. + * * @author ZorTik */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface PrimaryKey { - /** - * Tells SQLLib that this primary key is auto-incremented. - * !!! This ONLY works for {@link Integer} type, ans also not for - * primitive int. !!! - * @return If this field should be auto-incremented. - */ - boolean autoIncrement() default false; + /** + * Tells SQLLib that this primary key is auto-incremented. + * !!! This ONLY works for {@link Integer} type, ans also not for + * primitive int. !!! + * + * @return If this field should be auto-incremented. + */ + boolean autoIncrement() default false; } diff --git a/api/src/main/java/me/zort/sqllib/internal/exception/IllegalStatementOperationException.java b/api/src/main/java/me/zort/sqllib/internal/exception/IllegalStatementOperationException.java index 6231364..0eb71c5 100644 --- a/api/src/main/java/me/zort/sqllib/internal/exception/IllegalStatementOperationException.java +++ b/api/src/main/java/me/zort/sqllib/internal/exception/IllegalStatementOperationException.java @@ -6,16 +6,16 @@ public class IllegalStatementOperationException extends RuntimeException { - @Getter(onMethod_ = {@Nullable}) - private final Query location; + @Getter(onMethod_ = {@Nullable}) + private final Query location; - public IllegalStatementOperationException(String message) { - this(message, null); - } + public IllegalStatementOperationException(String message) { + this(message, null); + } - public IllegalStatementOperationException(String message, Query location) { - super(message); - this.location = location; - } + public IllegalStatementOperationException(String message, Query location) { + super(message); + this.location = location; + } } diff --git a/api/src/main/java/me/zort/sqllib/internal/exception/InvalidConnectionInstanceException.java b/api/src/main/java/me/zort/sqllib/internal/exception/InvalidConnectionInstanceException.java index 414c941..c85f628 100644 --- a/api/src/main/java/me/zort/sqllib/internal/exception/InvalidConnectionInstanceException.java +++ b/api/src/main/java/me/zort/sqllib/internal/exception/InvalidConnectionInstanceException.java @@ -5,11 +5,11 @@ public class InvalidConnectionInstanceException extends RuntimeException { - @Getter - private final SQLConnection invalid; + @Getter + private final SQLConnection invalid; - public InvalidConnectionInstanceException(SQLConnection invalid) { - super(String.format("Invalid connection instance %s!", invalid.getClass().getName())); - this.invalid = invalid; - } + public InvalidConnectionInstanceException(SQLConnection invalid) { + super(String.format("Invalid connection instance %s!", invalid.getClass().getName())); + this.invalid = invalid; + } } diff --git a/api/src/main/java/me/zort/sqllib/internal/exception/NoLinkedConnectionException.java b/api/src/main/java/me/zort/sqllib/internal/exception/NoLinkedConnectionException.java index 1f26aaf..c1f81bf 100644 --- a/api/src/main/java/me/zort/sqllib/internal/exception/NoLinkedConnectionException.java +++ b/api/src/main/java/me/zort/sqllib/internal/exception/NoLinkedConnectionException.java @@ -5,11 +5,11 @@ public class NoLinkedConnectionException extends RuntimeException { - @Getter - private final Query location; + @Getter + private final Query location; - public NoLinkedConnectionException(Query location) { - this.location = location; - } + public NoLinkedConnectionException(Query location) { + this.location = location; + } } diff --git a/api/src/main/java/me/zort/sqllib/internal/exception/SQLDriverNotFoundException.java b/api/src/main/java/me/zort/sqllib/internal/exception/SQLDriverNotFoundException.java index 04eafcd..79d7d0a 100644 --- a/api/src/main/java/me/zort/sqllib/internal/exception/SQLDriverNotFoundException.java +++ b/api/src/main/java/me/zort/sqllib/internal/exception/SQLDriverNotFoundException.java @@ -4,12 +4,12 @@ public class SQLDriverNotFoundException extends RuntimeException { - @Getter - private final String driver; + @Getter + private final String driver; - public SQLDriverNotFoundException(String driver, Throwable cause) { - super(String.format("Driver %s not found!", driver), cause); - this.driver = driver; - } + public SQLDriverNotFoundException(String driver, Throwable cause) { + super(String.format("Driver %s not found!", driver), cause); + this.driver = driver; + } } diff --git a/api/src/main/java/me/zort/sqllib/internal/exception/SQLEndpointNotValidException.java b/api/src/main/java/me/zort/sqllib/internal/exception/SQLEndpointNotValidException.java index 058d543..520143a 100644 --- a/api/src/main/java/me/zort/sqllib/internal/exception/SQLEndpointNotValidException.java +++ b/api/src/main/java/me/zort/sqllib/internal/exception/SQLEndpointNotValidException.java @@ -5,12 +5,12 @@ public class SQLEndpointNotValidException extends RuntimeException { - @Getter - private final SQLEndpoint endpoint; + @Getter + private final SQLEndpoint endpoint; - public SQLEndpointNotValidException(SQLEndpoint endpoint) { - super("Provided SQL endpoint is not valid!"); - this.endpoint = endpoint; - } + public SQLEndpointNotValidException(SQLEndpoint endpoint) { + super("Provided SQL endpoint is not valid!"); + this.endpoint = endpoint; + } } diff --git a/api/src/main/java/me/zort/sqllib/internal/factory/SQLConnectionFactory.java b/api/src/main/java/me/zort/sqllib/internal/factory/SQLConnectionFactory.java index 7832293..ec5f040 100644 --- a/api/src/main/java/me/zort/sqllib/internal/factory/SQLConnectionFactory.java +++ b/api/src/main/java/me/zort/sqllib/internal/factory/SQLConnectionFactory.java @@ -5,6 +5,6 @@ public interface SQLConnectionFactory { - Connection connect() throws SQLException; + Connection connect() throws SQLException; } diff --git a/core/src/main/java/me/zort/sqllib/JVM.java b/core/src/main/java/me/zort/sqllib/JVM.java index 9b7c0fc..7156be4 100644 --- a/core/src/main/java/me/zort/sqllib/JVM.java +++ b/core/src/main/java/me/zort/sqllib/JVM.java @@ -7,53 +7,53 @@ public abstract class JVM { - public abstract Object invokeDefault(Class declaringClass, Object instance, Method method, Object[] args) throws Throwable; - - public static JVM getJVM() { - int ver = jvmVer(); - if (ver < 8) - throw new UnsupportedOperationException("Unsupported JVM version: " + ver); - else if (ver == 8) - return new JVM8(); - else - return new JVM9(); + public abstract Object invokeDefault(Class declaringClass, Object instance, Method method, Object[] args) throws Throwable; + + public static JVM getJVM() { + int ver = jvmVer(); + if (ver < 8) + throw new UnsupportedOperationException("Unsupported JVM version: " + ver); + else if (ver == 8) + return new JVM8(); + else + return new JVM9(); + } + + private static int jvmVer() { + String version = System.getProperty("java.version"); + if (version.startsWith("1.")) { + version = version.substring(2, 3); + } else { + int dot = version.indexOf("."); + if (dot != -1) { + version = version.substring(0, dot); + } } - - private static int jvmVer() { - String version = System.getProperty("java.version"); - if(version.startsWith("1.")) { - version = version.substring(2, 3); - } else { - int dot = version.indexOf("."); - if(dot != -1) { - version = version.substring(0, dot); - } - } - return Integer.parseInt(version); + return Integer.parseInt(version); + } + + + static final class JVM8 extends JVM { + @Override + public Object invokeDefault(Class declaringClass, Object instance, Method method, Object[] args) throws Throwable { + Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class); + constructor.setAccessible(true); + return constructor.newInstance(declaringClass) + .in(declaringClass) + .unreflectSpecial(method, declaringClass) + .bindTo(instance) + .invokeWithArguments(args); } - - - static final class JVM8 extends JVM { - @Override - public Object invokeDefault(Class declaringClass, Object instance, Method method, Object[] args) throws Throwable { - Constructor constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class); - constructor.setAccessible(true); - return constructor.newInstance(declaringClass) - .in(declaringClass) - .unreflectSpecial(method, declaringClass) - .bindTo(instance) - .invokeWithArguments(args); - } - } - - static final class JVM9 extends JVM { - @Override - public Object invokeDefault(Class declaringClass, Object instance, Method method, Object[] args) throws Throwable { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - return lookup.findSpecial(declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), declaringClass) - .bindTo(instance) - .invokeWithArguments(args); - } + } + + static final class JVM9 extends JVM { + @Override + public Object invokeDefault(Class declaringClass, Object instance, Method method, Object[] args) throws Throwable { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + return lookup.findSpecial(declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), declaringClass) + .bindTo(instance) + .invokeWithArguments(args); } + } } diff --git a/core/src/main/java/me/zort/sqllib/SQLConnectionBuilder.java b/core/src/main/java/me/zort/sqllib/SQLConnectionBuilder.java index 23e3a22..bfb5370 100644 --- a/core/src/main/java/me/zort/sqllib/SQLConnectionBuilder.java +++ b/core/src/main/java/me/zort/sqllib/SQLConnectionBuilder.java @@ -22,113 +22,113 @@ @SuppressWarnings("unused") public final class SQLConnectionBuilder implements ISQLConnectionBuilder, Cloneable { - public static @NotNull SQLConnectionBuilder of(String address, int port, String database, String username, String password) { - return of(new DefaultSQLEndpoint(address + ":" + port, database, username, password)); - } - - public static @NotNull SQLConnectionBuilder of(String jdbc, String username, String password) { - return of(new SQLEndpointImpl(jdbc, username, password)); - } - - public static @NotNull SQLConnectionBuilder ofSQLite(String path) { - return of(new SQLEndpointImpl("jdbc:sqlite:" + path, null, null)).withDriver("org.sqlite.JDBC"); - } - - public static @NotNull SQLConnectionBuilder of(SQLEndpoint endpoint) { - if(!endpoint.isValid()) throw new SQLEndpointNotValidException(endpoint); - return new SQLConnectionBuilder(endpoint); - } - - private SQLEndpoint endpoint; - private String jdbc; - private String driver = null; - private CacheManager cacheManager = null; - - public SQLConnectionBuilder() { - this(null); - } - - public SQLConnectionBuilder(@NotNull String address, int port, @NotNull String database, @Nullable String username, @Nullable String password) { - this(new DefaultSQLEndpoint(address + ":" + port, database, username, password)); - } - - public SQLConnectionBuilder(@Nullable SQLEndpoint endpoint) { - this.endpoint = endpoint; - this.jdbc = endpoint != null ? endpoint.buildJdbc() : null; - } - - public @NotNull SQLConnectionBuilder withEndpoint(final SQLEndpoint endpoint) { - this.endpoint = endpoint; - this.jdbc = endpoint.buildJdbc(); - return this; - } - - public @NotNull SQLConnectionBuilder withParam(final @NotNull String key, final @NotNull String value) { - if (endpoint != null) jdbc += (jdbc.contains("?") ? "&" : "?") + (key + "=" + value); - return this; - } - - public @NotNull SQLConnectionBuilder withDriver(final @Nullable String driver) { - this.driver = driver; - return this; - } - - public @NotNull SQLConnectionBuilder withCacheManager(final @Nullable CacheManager cacheManager) { - this.cacheManager = cacheManager; - return this; - } - - public @NotNull SQLDatabaseConnection build() { - return build(null); - } - - public @NotNull SQLDatabaseConnection build(@Nullable ISQLDatabaseOptions options) { - return build(driver, options); - } - - public @NotNull SQLDatabaseConnection build(@Nullable String driver, @Nullable ISQLDatabaseOptions options) { - SQLDatabaseConnection connection = buildConnection(driver, options); - if(cacheManager != null) connection.enableCaching(cacheManager); - return connection; - } - - private @NotNull SQLDatabaseConnection buildConnection(@Nullable String driver, @Nullable ISQLDatabaseOptions options) { - Objects.requireNonNull(endpoint, "Endpoint must be set!"); - Objects.requireNonNull(jdbc); - if (driver == null) driver = SQLDatabaseConnectionImpl.DEFAULT_DRIVER; - SQLConnectionFactory connectionFactory = new LocalConnectionFactory(driver); - return jdbc.contains("jdbc:sqlite") - ? new SQLiteDatabaseConnection(connectionFactory, options) - : new SQLDatabaseConnectionImpl(connectionFactory, options); - } - - public @NotNull SQLConnectionPool createPool(final @NotNull SQLConnectionPool.Options options) { - return new SQLConnectionPool(this, options); - } - + public static @NotNull SQLConnectionBuilder of(String address, int port, String database, String username, String password) { + return of(new DefaultSQLEndpoint(address + ":" + port, database, username, password)); + } + + public static @NotNull SQLConnectionBuilder of(String jdbc, String username, String password) { + return of(new SQLEndpointImpl(jdbc, username, password)); + } + + public static @NotNull SQLConnectionBuilder ofSQLite(String path) { + return of(new SQLEndpointImpl("jdbc:sqlite:" + path, null, null)).withDriver("org.sqlite.JDBC"); + } + + public static @NotNull SQLConnectionBuilder of(SQLEndpoint endpoint) { + if (!endpoint.isValid()) throw new SQLEndpointNotValidException(endpoint); + return new SQLConnectionBuilder(endpoint); + } + + private SQLEndpoint endpoint; + private String jdbc; + private String driver = null; + private CacheManager cacheManager = null; + + public SQLConnectionBuilder() { + this(null); + } + + public SQLConnectionBuilder(@NotNull String address, int port, @NotNull String database, @Nullable String username, @Nullable String password) { + this(new DefaultSQLEndpoint(address + ":" + port, database, username, password)); + } + + public SQLConnectionBuilder(@Nullable SQLEndpoint endpoint) { + this.endpoint = endpoint; + this.jdbc = endpoint != null ? endpoint.buildJdbc() : null; + } + + public @NotNull SQLConnectionBuilder withEndpoint(final SQLEndpoint endpoint) { + this.endpoint = endpoint; + this.jdbc = endpoint.buildJdbc(); + return this; + } + + public @NotNull SQLConnectionBuilder withParam(final @NotNull String key, final @NotNull String value) { + if (endpoint != null) jdbc += (jdbc.contains("?") ? "&" : "?") + (key + "=" + value); + return this; + } + + public @NotNull SQLConnectionBuilder withDriver(final @Nullable String driver) { + this.driver = driver; + return this; + } + + public @NotNull SQLConnectionBuilder withCacheManager(final @Nullable CacheManager cacheManager) { + this.cacheManager = cacheManager; + return this; + } + + public @NotNull SQLDatabaseConnection build() { + return build(null); + } + + public @NotNull SQLDatabaseConnection build(@Nullable ISQLDatabaseOptions options) { + return build(driver, options); + } + + public @NotNull SQLDatabaseConnection build(@Nullable String driver, @Nullable ISQLDatabaseOptions options) { + SQLDatabaseConnection connection = buildConnection(driver, options); + if (cacheManager != null) connection.enableCaching(cacheManager); + return connection; + } + + private @NotNull SQLDatabaseConnection buildConnection(@Nullable String driver, @Nullable ISQLDatabaseOptions options) { + Objects.requireNonNull(endpoint, "Endpoint must be set!"); + Objects.requireNonNull(jdbc); + if (driver == null) driver = SQLDatabaseConnectionImpl.DEFAULT_DRIVER; + SQLConnectionFactory connectionFactory = new LocalConnectionFactory(driver); + return jdbc.contains("jdbc:sqlite") + ? new SQLiteDatabaseConnection(connectionFactory, options) + : new SQLDatabaseConnectionImpl(connectionFactory, options); + } + + public @NotNull SQLConnectionPool createPool(final @NotNull SQLConnectionPool.Options options) { + return new SQLConnectionPool(this, options); + } + + @Override + protected SQLConnectionBuilder clone() throws CloneNotSupportedException { + return (SQLConnectionBuilder) super.clone(); + } + + @RequiredArgsConstructor + class LocalConnectionFactory implements SQLConnectionFactory { + + private final String localDriver; + + @Nullable @Override - protected SQLConnectionBuilder clone() throws CloneNotSupportedException { - return (SQLConnectionBuilder) super.clone(); - } - - @RequiredArgsConstructor - class LocalConnectionFactory implements SQLConnectionFactory { - - private final String localDriver; - - @Nullable - @Override - public Connection connect() throws SQLException { - try { - Class.forName(localDriver); - } catch (ClassNotFoundException e) { - throw new SQLDriverNotFoundException(localDriver, e); - } - String usr = endpoint.getUsername(); - String pwd = endpoint.getPassword(); - return DriverManager.getConnection(jdbc, usr, pwd); - } - - } + public Connection connect() throws SQLException { + try { + Class.forName(localDriver); + } catch (ClassNotFoundException e) { + throw new SQLDriverNotFoundException(localDriver, e); + } + String usr = endpoint.getUsername(); + String pwd = endpoint.getPassword(); + return DriverManager.getConnection(jdbc, usr, pwd); + } + + } } diff --git a/core/src/main/java/me/zort/sqllib/SQLConnectionRegistry.java b/core/src/main/java/me/zort/sqllib/SQLConnectionRegistry.java index 34eb0dd..1a6e576 100644 --- a/core/src/main/java/me/zort/sqllib/SQLConnectionRegistry.java +++ b/core/src/main/java/me/zort/sqllib/SQLConnectionRegistry.java @@ -7,24 +7,24 @@ public final class SQLConnectionRegistry { - private SQLConnectionRegistry() { - } + private SQLConnectionRegistry() { + } - private static final List CONNECTIONS = new CopyOnWriteArrayList<>(); + private static final List CONNECTIONS = new CopyOnWriteArrayList<>(); - static void register(SQLDatabaseConnection connection) { - CONNECTIONS.add(connection); - } + static void register(SQLDatabaseConnection connection) { + CONNECTIONS.add(connection); + } - static Optional find(Connection connection) { - return CONNECTIONS.stream().filter(c -> c.getConnection() == connection).findFirst(); - } + static Optional find(Connection connection) { + return CONNECTIONS.stream().filter(c -> c.getConnection() == connection).findFirst(); + } - public static void debug(Connection connection, String message) { - find(connection) - .filter(c -> c instanceof SQLDatabaseConnectionImpl) - .ifPresent(c -> { - if (c.isDebug()) ((SQLDatabaseConnectionImpl) c).debug(message); - }); - } + public static void debug(Connection connection, String message) { + find(connection) + .filter(c -> c instanceof SQLDatabaseConnectionImpl) + .ifPresent(c -> { + if (c.isDebug()) ((SQLDatabaseConnectionImpl) c).debug(message); + }); + } } diff --git a/core/src/main/java/me/zort/sqllib/SQLDatabaseConnection.java b/core/src/main/java/me/zort/sqllib/SQLDatabaseConnection.java index 9217814..e0924a4 100644 --- a/core/src/main/java/me/zort/sqllib/SQLDatabaseConnection.java +++ b/core/src/main/java/me/zort/sqllib/SQLDatabaseConnection.java @@ -15,6 +15,7 @@ import me.zort.sqllib.api.model.SchemaSynchronizer; import me.zort.sqllib.api.model.TableSchema; import me.zort.sqllib.api.model.TableSchemaBuilder; +import me.zort.sqllib.cache.ExpirableEntriesCacheManager; import me.zort.sqllib.internal.factory.SQLConnectionFactory; import me.zort.sqllib.internal.impl.QueryResultImpl; import me.zort.sqllib.internal.query.*; @@ -37,284 +38,311 @@ @SuppressWarnings("unused") public abstract class SQLDatabaseConnection implements SQLConnection, Closeable { - private final SQLConnectionFactory connectionFactory; - @Getter(onMethod_ = {@Nullable}) - private Connection connection; - @Getter(onMethod_ = {@Nullable}) - private SQLException lastError = null; - - public SQLDatabaseConnection(final @NotNull SQLConnectionFactory connectionFactory) { - this.connectionFactory = connectionFactory; - this.connection = null; - - SQLConnectionRegistry.register(this); - } - - /** - * Sets a mapping to use when using {@link SQLDatabaseConnection#createProxy(Class, StatementMappingOptions)}. - * - * @param mappingFactory Mapping factory to use. - */ - public abstract void setProxyMapping(final @NotNull StatementMappingFactory mappingFactory); - - /** - * Sets the schema synchronizer to use with synchronizeModel methods. - * - * @param synchronizer Schema synchronizer to use - */ - @ApiStatus.Experimental - public abstract void setSchemaSynchronizer(SchemaSynchronizer synchronizer); - - @ApiStatus.Experimental - public abstract StatementMappingRegistry getMappingRegistry(); - - /** - * @deprecated Use {@link SQLDatabaseConnection#createProxy(Class)} instead. - */ - @Deprecated - public abstract T createGate(Class mappingInterface); - - /** - * Constructs a mapping repository based on provided interface. - * The interface should follow rules for creating mapping repositories - * in this library. - *

- * Example: - *

-     *     @Table("users")
-     *     public interface MyRepository {
-     *          @Select("*")
-     *          @Where(@Where.Condition(column = "firstname", value = "{First Name}"))
-     *          @Limit(1)
-     *          Optional<User> getUser(@Placeholder("First Name") String firstName);
-     *
-     *          @Select
-     *          List<User> getUsers();
-     *
-     *          @Delete
-     *          QueryResult deleteUsers();
-     *     }
-     *
-     *     SQLDatabaseConnection connection = ...;
-     *     MyRepository repository = connection.createGate(MyRepository.class);
-     *
-     *     Optional<User> user = repository.getUser("John");
-     * 
- * - * @param mappingInterface Interface to create mapping repository for. - * @return Mapping repository. - * @param Type of mapping repository. - */ - public abstract T createProxy(Class mappingInterface); - public abstract T createProxy(Class mappingInterface, @NotNull StatementMappingOptions options); - public abstract boolean buildEntitySchema(String tableName, Class entityClass); - - /** - * Synchronizes proxy mapping models with database.
- * Warning: This tries to update all tables that are part of mapping - * proxies. Should be used carefully. - * - * @return True if synchronization was successful - */ - @ApiStatus.Experimental - public abstract boolean synchronizeModel(); - - /** - * Synchronizes provided entity schema with the database - * In other words, it tries to update database schema (table) to match - * the provided entity schema. - * - * @param entitySchema Entity schema - * @param table Table name - * @return True if synchronization was successful - */ - @ApiStatus.Experimental - public abstract boolean synchronizeModel(TableSchema entitySchema, String table); - /** - * Synchronizes provided entity class with the database - * In other words, it tries to update database schema (table) to match - * the provided entity schema. This method uses synchronizeModel method - * with schema generated from the provided entity class. - * - * @param entity The entity (model) class - * @param table Table name - * @return True if synchronization was successful - */ - @ApiStatus.Experimental - public abstract boolean synchronizeModel(Class entity, String table); - - /** - * Performs new query and returns the result. This result is never null. - * See: {@link QueryRowsResult#isSuccessful()} - * - * Examples: - *

- * query(Select.of().from("players"), Player.class) - * .stream() - * .map(Player::getNickname) - * .forEach(System.out::println); - *

- * query(() -> "SELECT * FROM players;"); - * - * @param query The query to use while constructing query string. - * @param typeClass Type class of object which will be instantiated and - * populated with column values. - * @param Type of objects in result. - * - * @return Collection of row objects. - */ - public abstract QueryRowsResult query(Query query, Class typeClass); - public abstract QueryRowsResult query(Query query); - public abstract QueryRowsResult query(String query); - - /** - * Executes given query and returns execution result. - * This result does not contain any rows. If you want to - * execute query return result of rows, see method - * {@link SQLDatabaseConnection#query(Query)} - * - * @param query Query to use for building query string. - * @return Blank rows result that only informs - * about success state of the request. - */ - public abstract QueryResult exec(Query query); - public abstract QueryResult exec(String query); - @ApiStatus.Experimental - public abstract Transaction beginTransaction(); - @ApiStatus.Experimental - public abstract void closeTransaction(); - @ApiStatus.Experimental - @Nullable - public abstract Transaction getTransaction(); - /** - * Enabled caching for this connection. - * - * @param cacheManager Cache manager to use. - */ - @ApiStatus.Experimental - public abstract void enableCaching(CacheManager cacheManager); - public abstract boolean isTransactionActive(); - protected abstract DefsVals buildDefsVals(Object obj); - public abstract boolean isLogSqlErrors(); - public abstract boolean isDebug(); - @ApiStatus.Experimental - public abstract TableSchemaBuilder getSchemaBuilder(String table); - @ApiStatus.Experimental - public abstract SchemaSynchronizer getSchemaSynchronizer(); - - public UpsertQuery save(final @NotNull String table, final @NotNull Object obj) { - if(buildDefsVals(obj) == null) throw new IllegalArgumentException("Cannot create save query! (defsVals == null)"); - return save(obj).table(table); - } - - public UpsertQuery save(final @NotNull Object obj) { - DefsVals defsVals = buildDefsVals(obj); - if(defsVals == null) return null; - String[] defs = defsVals.getDefs(); - SQLDatabaseConnectionImpl.UnknownValueWrapper[] vals = defsVals.getVals(); - UpsertQuery upsertQuery = upsert().into(null, defs); - for(SQLDatabaseConnectionImpl.UnknownValueWrapper wrapper : vals) { - upsertQuery.appendVal(wrapper.getObject()); - } - SetStatement setStatement = upsertQuery.onDuplicateKey(); - for(int i = 0; i < defs.length; i++) { - setStatement.and(defs[i], vals[i].getObject()); - } - - return (UpsertQuery) setStatement.getAncestor(); - } - - public QueryResult insert(final @NotNull String table, final @NotNull Object obj) { - DefsVals defsVals = buildDefsVals(obj); - if (defsVals == null) return new QueryResultImpl(false); - - InsertQuery query = insert().into(table, defsVals.getDefs()); - for (SQLDatabaseConnectionImpl.UnknownValueWrapper valueWrapper : defsVals.getVals()) { - query.appendVal(valueWrapper.getObject()); - } - - return query.execute(); - } - - // --***-- Query builders --***-- - - public SelectQuery select(String... cols) { - return new SelectQuery(this, cols); + private final SQLConnectionFactory connectionFactory; + @Getter(onMethod_ = {@Nullable}) + private Connection connection; + @Getter(onMethod_ = {@Nullable}) + private SQLException lastError = null; + + public SQLDatabaseConnection(final @NotNull SQLConnectionFactory connectionFactory) { + this.connectionFactory = connectionFactory; + this.connection = null; + + SQLConnectionRegistry.register(this); + } + + /** + * Sets a mapping to use when using {@link SQLDatabaseConnection#createProxy(Class, StatementMappingOptions)}. + * + * @param mappingFactory Mapping factory to use. + */ + public abstract void setProxyMapping(final @NotNull StatementMappingFactory mappingFactory); + + /** + * Sets the schema synchronizer to use with synchronizeModel methods. + * + * @param synchronizer Schema synchronizer to use + */ + @ApiStatus.Experimental + public abstract void setSchemaSynchronizer(SchemaSynchronizer synchronizer); + + @ApiStatus.Experimental + public abstract StatementMappingRegistry getMappingRegistry(); + + /** + * @deprecated Use {@link SQLDatabaseConnection#createProxy(Class)} instead. + */ + @Deprecated + public abstract T createGate(Class mappingInterface); + + /** + * Constructs a mapping repository based on provided interface. + * The interface should follow rules for creating mapping repositories + * in this library. + *

+ * Example: + *

+   *     @Table("users")
+   *     public interface MyRepository {
+   *          @Select("*")
+   *          @Where(@Where.Condition(column = "firstname", value = "{First Name}"))
+   *          @Limit(1)
+   *          Optional<User> getUser(@Placeholder("First Name") String firstName);
+   *
+   *          @Select
+   *          List<User> getUsers();
+   *
+   *          @Delete
+   *          QueryResult deleteUsers();
+   *     }
+   *
+   *     SQLDatabaseConnection connection = ...;
+   *     MyRepository repository = connection.createGate(MyRepository.class);
+   *
+   *     Optional<User> user = repository.getUser("John");
+   * 
+ * + * @param mappingInterface Interface to create mapping repository for. + * @param Type of mapping repository. + * @return Mapping repository. + */ + public abstract T createProxy(Class mappingInterface); + + public abstract T createProxy(Class mappingInterface, @NotNull StatementMappingOptions options); + + public abstract boolean buildEntitySchema(String tableName, Class entityClass); + + /** + * Synchronizes proxy mapping models with database.
+ * Warning: This tries to update all tables that are part of mapping + * proxies. Should be used carefully. + * + * @return True if synchronization was successful + */ + @ApiStatus.Experimental + public abstract boolean synchronizeModel(); + + /** + * Synchronizes provided entity schema with the database + * In other words, it tries to update database schema (table) to match + * the provided entity schema. + * + * @param entitySchema Entity schema + * @param table Table name + * @return True if synchronization was successful + */ + @ApiStatus.Experimental + public abstract boolean synchronizeModel(TableSchema entitySchema, String table); + + /** + * Synchronizes provided entity class with the database + * In other words, it tries to update database schema (table) to match + * the provided entity schema. This method uses synchronizeModel method + * with schema generated from the provided entity class. + * + * @param entity The entity (model) class + * @param table Table name + * @return True if synchronization was successful + */ + @ApiStatus.Experimental + public abstract boolean synchronizeModel(Class entity, String table); + + /** + * Performs new query and returns the result. This result is never null. + * See: {@link QueryRowsResult#isSuccessful()} + *

+ * Examples: + *

+ * query(Select.of().from("players"), Player.class) + * .stream() + * .map(Player::getNickname) + * .forEach(System.out::println); + *

+ * query(() -> "SELECT * FROM players;"); + * + * @param query The query to use while constructing query string. + * @param typeClass Type class of object which will be instantiated and + * populated with column values. + * @param Type of objects in result. + * @return Collection of row objects. + */ + public abstract QueryRowsResult query(Query query, Class typeClass); + + public abstract QueryRowsResult query(Query query); + + public abstract QueryRowsResult query(String query); + + /** + * Executes given query and returns execution result. + * This result does not contain any rows. If you want to + * execute query return result of rows, see method + * {@link SQLDatabaseConnection#query(Query)} + * + * @param query Query to use for building query string. + * @return Blank rows result that only informs + * about success state of the request. + */ + public abstract QueryResult exec(Query query); + + public abstract QueryResult exec(String query); + + @ApiStatus.Experimental + public abstract Transaction beginTransaction(); + + @ApiStatus.Experimental + public abstract void closeTransaction(); + + @ApiStatus.Experimental + @Nullable + public abstract Transaction getTransaction(); + + /** + * Enabled caching for this connection. + * + * @param cacheManager Cache manager to use. + */ + @ApiStatus.Experimental + public abstract void enableCaching(CacheManager cacheManager); + + public abstract boolean isTransactionActive(); + + protected abstract DefsVals buildDefsVals(Object obj); + + public abstract boolean isLogSqlErrors(); + + public abstract boolean isDebug(); + + @ApiStatus.Experimental + public abstract TableSchemaBuilder getSchemaBuilder(String table); + + @ApiStatus.Experimental + public abstract SchemaSynchronizer getSchemaSynchronizer(); + + /** + * Enables caching for provided milliseconds. + * This uses {@link ExpirableEntriesCacheManager} cache manager. + * + * @param millis The entries expiration in milliseconds + * @return This instance + */ + public SQLDatabaseConnection cacheFor(long millis) { + enableCaching(new ExpirableEntriesCacheManager(millis)); + return this; + } + + public UpsertQuery save(final @NotNull String table, final @NotNull Object obj) { + if (buildDefsVals(obj) == null) throw new IllegalArgumentException("Cannot create save query! (defsVals == null)"); + return save(obj).table(table); + } + + public UpsertQuery save(final @NotNull Object obj) { + DefsVals defsVals = buildDefsVals(obj); + if (defsVals == null) return null; + String[] defs = defsVals.getDefs(); + SQLDatabaseConnectionImpl.UnknownValueWrapper[] vals = defsVals.getVals(); + UpsertQuery upsertQuery = upsert().into(null, defs); + for (SQLDatabaseConnectionImpl.UnknownValueWrapper wrapper : vals) { + upsertQuery.appendVal(wrapper.getObject()); } - - public UpdateQuery update() { - return update(null); + SetStatement setStatement = upsertQuery.onDuplicateKey(); + for (int i = 0; i < defs.length; i++) { + setStatement.and(defs[i], vals[i].getObject()); } - public UpdateQuery update(@Nullable String table) { - return new UpdateQuery(this, table); - } + return (UpsertQuery) setStatement.getAncestor(); + } - public InsertQuery insert() { - return insert(null); - } + public QueryResult insert(final @NotNull String table, final @NotNull Object obj) { + DefsVals defsVals = buildDefsVals(obj); + if (defsVals == null) return new QueryResultImpl(false); - public InsertQuery insert(@Nullable String table) { - return new InsertQuery(this, table); + InsertQuery query = insert().into(table, defsVals.getDefs()); + for (SQLDatabaseConnectionImpl.UnknownValueWrapper valueWrapper : defsVals.getVals()) { + query.appendVal(valueWrapper.getObject()); } - public UpsertQuery upsert() { - return upsert(null); + return query.execute(); + } + + // --***-- Query builders --***-- + + public SelectQuery select(String... cols) { + return new SelectQuery(this, cols); + } + + public UpdateQuery update() { + return update(null); + } + + public UpdateQuery update(@Nullable String table) { + return new UpdateQuery(this, table); + } + + public InsertQuery insert() { + return insert(null); + } + + public InsertQuery insert(@Nullable String table) { + return new InsertQuery(this, table); + } + + public UpsertQuery upsert() { + return upsert(null); + } + + public UpsertQuery upsert(@Nullable String table) { + return new UpsertQuery(this, table); + } + + public DeleteQuery delete() { + return new DeleteQuery(this); + } + + @Override + public final boolean connect() { + if (isConnected()) disconnect(); + try { + connection = connectionFactory.connect(); + lastError = null; + } catch (SQLException e) { + logSqlError(e); + connection = null; + lastError = e; } - - public UpsertQuery upsert(@Nullable String table) { - return new UpsertQuery(this, table); - } - - public DeleteQuery delete() { - return new DeleteQuery(this); - } - - @Override - public final boolean connect() { - if(isConnected()) disconnect(); - try { - connection = connectionFactory.connect(); - lastError = null; - } catch (SQLException e) { - logSqlError(e); - connection = null; - lastError = e; - } - return isConnected(); - } - - @Override - public final void disconnect() { - if (!isConnected()) return; - try { - connection.close(); - lastError = null; - } catch (SQLException e) { - logSqlError(e); - lastError = e; - } - } - - @Override - public void close() { - disconnect(); - } - - protected void logSqlError(Exception e) { - if(isLogSqlErrors()) e.printStackTrace(); - } - - @AllArgsConstructor - @Getter - protected static class DefsVals { - private final String[] defs; - private final SQLDatabaseConnectionImpl.UnknownValueWrapper[] vals; - } - - @AllArgsConstructor - @Data - public static class UnknownValueWrapper { - private Object object; + return isConnected(); + } + + @Override + public final void disconnect() { + if (!isConnected()) return; + try { + connection.close(); + lastError = null; + } catch (SQLException e) { + logSqlError(e); + lastError = e; } + } + + @Override + public void close() { + disconnect(); + } + + protected void logSqlError(Exception e) { + if (isLogSqlErrors()) e.printStackTrace(); + } + + @AllArgsConstructor + @Getter + protected static class DefsVals { + private final String[] defs; + private final SQLDatabaseConnectionImpl.UnknownValueWrapper[] vals; + } + + @AllArgsConstructor + @Data + public static class UnknownValueWrapper { + private Object object; + } } diff --git a/core/src/main/java/me/zort/sqllib/SQLDatabaseConnectionImpl.java b/core/src/main/java/me/zort/sqllib/SQLDatabaseConnectionImpl.java index 0d34017..da35a24 100644 --- a/core/src/main/java/me/zort/sqllib/SQLDatabaseConnectionImpl.java +++ b/core/src/main/java/me/zort/sqllib/SQLDatabaseConnectionImpl.java @@ -62,600 +62,599 @@ @SuppressWarnings("unused") public class SQLDatabaseConnectionImpl extends PooledSQLDatabaseConnection { - @NotNull static SQLDatabaseOptions defaultOptions() { - return new SQLDatabaseOptions(DEFAULT_AUTO_RECONNECT, DEFAULT_DEBUG, DEFAULT_LOG_SQL_ERRORS, DEFAULT_NAMING_STRATEGY, DEFAULT_GSON); - } - - // --***-- Default Constants --***-- - - public static final String DEFAULT_DRIVER = Defaults.DEFAULT_DRIVER; - public static final boolean DEFAULT_AUTO_RECONNECT = Defaults.DEFAULT_AUTO_RECONNECT; - public static final boolean DEFAULT_DEBUG = Defaults.DEFAULT_DEBUG; - public static final boolean DEFAULT_LOG_SQL_ERRORS = Defaults.DEFAULT_LOG_SQL_ERRORS; - public static final NamingStrategy DEFAULT_NAMING_STRATEGY = Defaults.DEFAULT_NAMING_STRATEGY; - public static final Gson DEFAULT_GSON = Defaults.DEFAULT_GSON; - - // --***-- Options & Utilities --***-- - - @Getter - private final ISQLDatabaseOptions options; - private final transient List errorStateHandlers; - private final transient MappingRegistryImpl mappingRegistry; - private transient StatementMappingFactory mappingFactory; - private transient ObjectMapper objectMapper; - private transient CacheManager cacheManager; - @Setter - private transient Logger logger; - @Getter(onMethod_ = {@Nullable, @ApiStatus.Experimental}) - private transient Transaction transaction; - private transient SchemaSynchronizer schemaSynchronizer; - private int errorCount = 0; - - /** - * Constructs new instance of this implementation with default - * options. - * - * @see SQLDatabaseConnectionImpl#SQLDatabaseConnectionImpl(SQLConnectionFactory, ISQLDatabaseOptions) - */ - public SQLDatabaseConnectionImpl(final @NotNull SQLConnectionFactory connectionFactory) { - this(connectionFactory, null); - } - - /** - * Constructs new instance of this implementation. - * - * @param connectionFactory Factory to use while opening connection. - * @param options Client options to use. - */ - public SQLDatabaseConnectionImpl(final @NotNull SQLConnectionFactory connectionFactory, @Nullable ISQLDatabaseOptions options) { - super(connectionFactory); - this.options = options == null ? defaultOptions() : options; - this.objectMapper = new DefaultObjectMapper(this); - this.mappingFactory = new DefaultStatementMappingFactory(); - this.errorStateHandlers = new CopyOnWriteArrayList<>(); - this.transaction = null; - this.logger = Logger.getGlobal(); - this.mappingRegistry = new MappingRegistryImpl(this); - - setSchemaSynchronizer(new SQLSchemaSynchronizer()); - enableCaching(CacheManager.noCache()); - - // Default backup value resolvers. - registerBackupValueResolver(new LinkedOneFieldResolver()); - registerBackupValueResolver(new ConstructorParameterResolver()); - } - - /** - * Registers a backup value resolver to the registry. - * Backup value resolvers are used when no value is found for mapped - * field in {@link ObjectMapper}. - * - * @param resolver Resolver to register. - */ - public void registerBackupValueResolver(final @NotNull ObjectMapper.FieldValueResolver resolver) { - Objects.requireNonNull(resolver, "Resolver cannot be null!"); - - objectMapper.registerBackupValueResolver(resolver); - } - - /** - * Sets the object mapper to use. - * Object mapper maps queries to objects, as specified in {@link SQLDatabaseConnection#query(Query, Class)}. - * - * @param objectMapper Object mapper to use. - */ - public void setObjectMapper(final @NotNull ObjectMapper objectMapper) { - this.objectMapper = Objects.requireNonNull(objectMapper, "Object mapper cannot be null!"); - } - - /** - * Sets a mapping to use when using {@link SQLDatabaseConnection#createProxy(Class, StatementMappingOptions)}. - * - * @param mappingFactory Mapping factory to use. - */ - public void setProxyMapping(final @NotNull StatementMappingFactory mappingFactory) { - this.mappingFactory = Objects.requireNonNull(mappingFactory, "Mapping factory cannot be null!"); - } - - /** - * Adds an error state observer to the list of observers to be - * notified when a fatal error occurs. - * - * @param observer Observer to add. - */ - public void addErrorHandler(final @NotNull ErrorStateObserver observer) { - this.errorStateHandlers.add(observer); - } - - /** - * Enabled caching for this connection. - * - * @param cacheManager Cache manager to use. - */ - @ApiStatus.Experimental - @Override - public void enableCaching(CacheManager cacheManager) { - this.cacheManager = cacheManager; - } - - /** - * Synchronizes proxy mapping models with database.
- * Warning: This tries to update all tables that are part of mapping - * proxies. Should be used carefully. - * - * @return True if there were any changes - */ - @ApiStatus.Experimental - @Override - public boolean synchronizeModel() { - return mappingRegistry.getProxyInstances() - .stream().flatMap(i -> i.getTableSchemas( - getOptions().getNamingStrategy(), - this instanceof SQLiteDatabaseConnection).stream()) - .anyMatch(schema -> synchronizeModel(schema, schema.getTable())); - } - - /** - * Synchronizes provided entity schema with the database - * In other words, it tries to update database schema (table) to match - * the provided entity schema. - * - * @param entitySchema Entity schema - * @param table Table name - * @return True if there were any changes - */ - @ApiStatus.Experimental - @Override - public boolean synchronizeModel(TableSchema entitySchema, String table) { - QueryResult result = getSchemaSynchronizer().synchronize(this, entitySchema, - getSchemaBuilder(table).buildTableSchema()); - return result != QueryResult.noChangesResult && result.isSuccessful(); - } - - /** - * Synchronizes provided entity class with the database - * In other words, it tries to update database schema (table) to match - * the provided entity schema. This method uses synchronizeModel method - * with schema generated from the provided entity class. - * - * @param entity The entity (model) class - * @param table Table name - * @return True if there were any changes - */ - @ApiStatus.Experimental - @Override - public boolean synchronizeModel(Class entity, String table) { - return synchronizeModel(new EntitySchemaBuilder(table, entity, - getOptions().getNamingStrategy(), - this instanceof SQLiteDatabaseConnection).buildTableSchema(), table); - } - - /** - * Sets the schema synchronizer to use with synchronizeModel methods. - * - * @param synchronizer Schema synchronizer to use - */ - @ApiStatus.Experimental - @Override - public void setSchemaSynchronizer(SchemaSynchronizer synchronizer) { - this.schemaSynchronizer = synchronizer; - } - - @ApiStatus.Experimental - @Override - public SchemaSynchronizer getSchemaSynchronizer() { - return schemaSynchronizer; - } - - @ApiStatus.Experimental - @Override - public StatementMappingRegistry getMappingRegistry() { - return mappingRegistry; - } - - /** - * Constructs a mapping proxy based on provided interface. - * The interface should follow rules for creating mapping repositories - * in this library. - * - * @param mappingInterface Interface to create mapping repository for. - * @return Mapping repository. - * @param Type of mapping repository. - * - * @see SQLDatabaseConnection#createProxy(Class, StatementMappingOptions) - */ - public T createProxy(Class mappingInterface) { - return createProxy(mappingInterface, new StatementMappingOptions.Builder().build()); - } - - /** - * Replaced with {@link SQLDatabaseConnection#createProxy(Class)}. - * - * @deprecated Will be removed in future releases. - */ - @Deprecated - @Override - public T createGate(Class mappingInterface) { - return createProxy(mappingInterface); - } - - /** - * Constructs a mapping repository based on provided interface. - * The interface should follow rules for creating mapping repositories - * in this library. - *

- * Example: - *

-     *     @Table("users")
-     *     public interface MyRepository {
-     *          @Select("*")
-     *          @Where(@Where.Condition(column = "firstname", value = "{First Name}"))
-     *          @Limit(1)
-     *          Optional<User> getUser(@Placeholder("First Name") String firstName);
-     *
-     *          @Select
-     *          List<User> getUsers();
-     *
-     *          @Delete
-     *          QueryResult deleteUsers();
-     *     }
-     *
-     *     SQLDatabaseConnection connection = ...;
-     *     MyRepository repository = connection.createGate(MyRepository.class);
-     *
-     *     Optional<User> user = repository.getUser("John");
-     * 
- * - * @param mappingInterface Interface to create mapping repository for. - * @return Mapping repository. - * @param Type of mapping repository. - */ - @SuppressWarnings("unchecked") - public final T createProxy(final @NotNull Class mappingInterface, final @NotNull StatementMappingOptions options) { - Objects.requireNonNull(mappingInterface, "Mapping interface cannot be null!"); - Objects.requireNonNull(options, "Options cannot be null!"); - - AtomicReference> instanceReference = new AtomicReference<>(); - T rawInstance = (T) Proxy.newProxyInstance(mappingInterface.getClassLoader(), - new Class[]{mappingInterface}, (proxy, method, args) -> instanceReference.get().invoke(proxy, method, args)); - instanceReference.set(new ProxyInstanceImpl<>(mappingInterface, - options, - mappingFactory.strategy(mappingInterface, this), - mappingFactory.resultAdapter())); - - MappingProxyInstance proxyInstanceWrapper = instanceReference.get(); - mappingRegistry.registerProxy(proxyInstanceWrapper); - return rawInstance; - } - - @ApiStatus.Experimental - public final boolean buildEntitySchema(final @NotNull String tableName, final @NotNull Class entityClass) { - Objects.requireNonNull(entityClass, "Entity class cannot be null!"); - - EntitySchemaBuilder converter = new EntitySchemaBuilder(tableName, entityClass, options.getNamingStrategy(), this instanceof SQLiteDatabaseConnection); - String query = converter.buildTableQuery(); - - return exec(() -> query).isSuccessful(); - } - - /** - * Performs new query and returns the result. This result is never null. - * This method also maps the result to the specified type using {@link ObjectMapper}. - * See: {@link QueryRowsResult#isSuccessful()} - * - * Examples: - *

- * query(Select.of().from("players"), Player.class) - * .stream() - * .map(Player::getNickname) - * .forEach(System.out::println); - *

- * query(() -> "SELECT * FROM players;"); - * - * @param query The query to use while constructing query string. - * @param typeClass Type class of object which will be instantiated and - * populated with column values. - * @param Type of objects in result. - * - * @return Collection of row objects. - */ - @NotNull - @Override - public QueryRowsResult query(final @NotNull Query query, final @NotNull Class typeClass) { - Objects.requireNonNull(query); - Objects.requireNonNull(typeClass); - - QueryRowsResult resultRows = query(query.getAncestor()); - QueryRowsResult result = new QueryRowsResult<>(resultRows.isSuccessful()); - - for(Row row : resultRows) { - Optional.ofNullable(objectMapper.assignValues(row, typeClass)) - .ifPresent(result::add); + @NotNull + static SQLDatabaseOptions defaultOptions() { + return new SQLDatabaseOptions(DEFAULT_AUTO_RECONNECT, DEFAULT_DEBUG, DEFAULT_LOG_SQL_ERRORS, DEFAULT_NAMING_STRATEGY, DEFAULT_GSON); + } + + // --***-- Default Constants --***-- + + public static final String DEFAULT_DRIVER = Defaults.DEFAULT_DRIVER; + public static final boolean DEFAULT_AUTO_RECONNECT = Defaults.DEFAULT_AUTO_RECONNECT; + public static final boolean DEFAULT_DEBUG = Defaults.DEFAULT_DEBUG; + public static final boolean DEFAULT_LOG_SQL_ERRORS = Defaults.DEFAULT_LOG_SQL_ERRORS; + public static final NamingStrategy DEFAULT_NAMING_STRATEGY = Defaults.DEFAULT_NAMING_STRATEGY; + public static final Gson DEFAULT_GSON = Defaults.DEFAULT_GSON; + + // --***-- Options & Utilities --***-- + + @Getter + private final ISQLDatabaseOptions options; + private final transient List errorStateHandlers; + private final transient StatementMappingRegistry mappingRegistry; + private transient StatementMappingFactory mappingFactory; + private transient ObjectMapper objectMapper; + private transient CacheManager cacheManager; + @Setter + private transient Logger logger; + @Getter(onMethod_ = {@Nullable, @ApiStatus.Experimental}) + private transient Transaction transaction; + private transient SchemaSynchronizer schemaSynchronizer; + private int errorCount = 0; + + /** + * Constructs new instance of this implementation with default + * options. + * + * @see SQLDatabaseConnectionImpl#SQLDatabaseConnectionImpl(SQLConnectionFactory, ISQLDatabaseOptions) + */ + public SQLDatabaseConnectionImpl(final @NotNull SQLConnectionFactory connectionFactory) { + this(connectionFactory, null); + } + + /** + * Constructs new instance of this implementation. + * + * @param connectionFactory Factory to use while opening connection. + * @param options Client options to use. + */ + public SQLDatabaseConnectionImpl(final @NotNull SQLConnectionFactory connectionFactory, @Nullable ISQLDatabaseOptions options) { + super(connectionFactory); + this.options = options == null ? defaultOptions() : options; + this.objectMapper = new DefaultObjectMapper(this); + this.mappingFactory = new DefaultStatementMappingFactory(); + this.errorStateHandlers = new CopyOnWriteArrayList<>(); + this.transaction = null; + this.logger = Logger.getGlobal(); + this.mappingRegistry = new MappingRegistryImpl(this); + + setSchemaSynchronizer(new SQLSchemaSynchronizer()); + enableCaching(CacheManager.noCache()); + + // Default backup value resolvers. + registerBackupValueResolver(new LinkedOneFieldResolver()); + registerBackupValueResolver(new ConstructorParameterResolver()); + } + + /** + * Registers a backup value resolver to the registry. + * Backup value resolvers are used when no value is found for mapped + * field in {@link ObjectMapper}. + * + * @param resolver Resolver to register. + */ + public void registerBackupValueResolver(final @NotNull ObjectMapper.FieldValueResolver resolver) { + Objects.requireNonNull(resolver, "Resolver cannot be null!"); + + objectMapper.registerBackupValueResolver(resolver); + } + + /** + * Sets the object mapper to use. + * Object mapper maps queries to objects, as specified in {@link SQLDatabaseConnection#query(Query, Class)}. + * + * @param objectMapper Object mapper to use. + */ + public void setObjectMapper(final @NotNull ObjectMapper objectMapper) { + this.objectMapper = Objects.requireNonNull(objectMapper, "Object mapper cannot be null!"); + } + + /** + * Sets a mapping to use when using {@link SQLDatabaseConnection#createProxy(Class, StatementMappingOptions)}. + * + * @param mappingFactory Mapping factory to use. + */ + public void setProxyMapping(final @NotNull StatementMappingFactory mappingFactory) { + this.mappingFactory = Objects.requireNonNull(mappingFactory, "Mapping factory cannot be null!"); + } + + /** + * Adds an error state observer to the list of observers to be + * notified when a fatal error occurs. + * + * @param observer Observer to add. + */ + public void addErrorHandler(final @NotNull ErrorStateObserver observer) { + this.errorStateHandlers.add(observer); + } + + /** + * Enabled caching for this connection. + * + * @param cacheManager Cache manager to use. + */ + @ApiStatus.Experimental + @Override + public void enableCaching(CacheManager cacheManager) { + this.cacheManager = cacheManager; + } + + /** + * Synchronizes proxy mapping models with database.
+ * Warning: This tries to update all tables that are part of mapping + * proxies. Should be used carefully. + * + * @return True if there were any changes + */ + @ApiStatus.Experimental + @Override + public boolean synchronizeModel() { + return mappingRegistry.getProxyInstances() + .stream().flatMap(i -> i.getTableSchemas( + getOptions().getNamingStrategy(), + this instanceof SQLiteDatabaseConnection).stream()) + .anyMatch(schema -> synchronizeModel(schema, schema.getTable())); + } + + /** + * Synchronizes provided entity schema with the database + * In other words, it tries to update database schema (table) to match + * the provided entity schema. + * + * @param entitySchema Entity schema + * @param table Table name + * @return True if there were any changes + */ + @ApiStatus.Experimental + @Override + public boolean synchronizeModel(TableSchema entitySchema, String table) { + QueryResult result = getSchemaSynchronizer().synchronize(this, entitySchema, + getSchemaBuilder(table).buildTableSchema()); + return result != QueryResult.noChangesResult && result.isSuccessful(); + } + + /** + * Synchronizes provided entity class with the database + * In other words, it tries to update database schema (table) to match + * the provided entity schema. This method uses synchronizeModel method + * with schema generated from the provided entity class. + * + * @param entity The entity (model) class + * @param table Table name + * @return True if there were any changes + */ + @ApiStatus.Experimental + @Override + public boolean synchronizeModel(Class entity, String table) { + return synchronizeModel(new EntitySchemaBuilder(table, entity, + getOptions().getNamingStrategy(), + this instanceof SQLiteDatabaseConnection).buildTableSchema(), table); + } + + /** + * Sets the schema synchronizer to use with synchronizeModel methods. + * + * @param synchronizer Schema synchronizer to use + */ + @ApiStatus.Experimental + @Override + public void setSchemaSynchronizer(SchemaSynchronizer synchronizer) { + this.schemaSynchronizer = synchronizer; + } + + @ApiStatus.Experimental + @Override + public SchemaSynchronizer getSchemaSynchronizer() { + return schemaSynchronizer; + } + + @ApiStatus.Experimental + @Override + public StatementMappingRegistry getMappingRegistry() { + return mappingRegistry; + } + + /** + * Constructs a mapping proxy based on provided interface. + * The interface should follow rules for creating mapping repositories + * in this library. + * + * @param mappingInterface Interface to create mapping repository for. + * @param Type of mapping repository. + * @return Mapping repository. + * @see SQLDatabaseConnection#createProxy(Class, StatementMappingOptions) + */ + public T createProxy(Class mappingInterface) { + return createProxy(mappingInterface, new StatementMappingOptions.Builder().build()); + } + + /** + * Replaced with {@link SQLDatabaseConnection#createProxy(Class)}. + * + * @deprecated Will be removed in future releases. + */ + @Deprecated + @Override + public T createGate(Class mappingInterface) { + return createProxy(mappingInterface); + } + + /** + * Constructs a mapping repository based on provided interface. + * The interface should follow rules for creating mapping repositories + * in this library. + *

+ * Example: + *

+   *     @Table("users")
+   *     public interface MyRepository {
+   *          @Select("*")
+   *          @Where(@Where.Condition(column = "firstname", value = "{First Name}"))
+   *          @Limit(1)
+   *          Optional<User> getUser(@Placeholder("First Name") String firstName);
+   *
+   *          @Select
+   *          List<User> getUsers();
+   *
+   *          @Delete
+   *          QueryResult deleteUsers();
+   *     }
+   *
+   *     SQLDatabaseConnection connection = ...;
+   *     MyRepository repository = connection.createGate(MyRepository.class);
+   *
+   *     Optional<User> user = repository.getUser("John");
+   * 
+ * + * @param mappingInterface Interface to create mapping repository for. + * @param Type of mapping repository. + * @return Mapping repository. + */ + @SuppressWarnings("unchecked") + public final T createProxy(final @NotNull Class mappingInterface, final @NotNull StatementMappingOptions options) { + Objects.requireNonNull(mappingInterface, "Mapping interface cannot be null!"); + Objects.requireNonNull(options, "Options cannot be null!"); + + AtomicReference> instanceReference = new AtomicReference<>(); + T rawInstance = (T) Proxy.newProxyInstance(mappingInterface.getClassLoader(), + new Class[]{mappingInterface}, (proxy, method, args) -> instanceReference.get().invoke(proxy, method, args)); + instanceReference.set(new ProxyInstanceImpl<>(mappingInterface, + options, + mappingFactory.strategy(mappingInterface, this), + mappingFactory.resultAdapter())); + + MappingProxyInstance proxyInstanceWrapper = instanceReference.get(); + mappingRegistry.registerProxy(proxyInstanceWrapper); + return rawInstance; + } + + @ApiStatus.Experimental + public final boolean buildEntitySchema(final @NotNull String tableName, final @NotNull Class entityClass) { + Objects.requireNonNull(entityClass, "Entity class cannot be null!"); + + EntitySchemaBuilder converter = new EntitySchemaBuilder(tableName, entityClass, options.getNamingStrategy(), this instanceof SQLiteDatabaseConnection); + String query = converter.buildTableQuery(); + + return exec(() -> query).isSuccessful(); + } + + /** + * Performs new query and returns the result. This result is never null. + * This method also maps the result to the specified type using {@link ObjectMapper}. + * See: {@link QueryRowsResult#isSuccessful()} + *

+ * Examples: + *

+ * query(Select.of().from("players"), Player.class) + * .stream() + * .map(Player::getNickname) + * .forEach(System.out::println); + *

+ * query(() -> "SELECT * FROM players;"); + * + * @param query The query to use while constructing query string. + * @param typeClass Type class of object which will be instantiated and + * populated with column values. + * @param Type of objects in result. + * @return Collection of row objects. + */ + @NotNull + @Override + public QueryRowsResult query(final @NotNull Query query, final @NotNull Class typeClass) { + Objects.requireNonNull(query); + Objects.requireNonNull(typeClass); + + QueryRowsResult resultRows = query(query.getAncestor()); + QueryRowsResult result = new QueryRowsResult<>(resultRows.isSuccessful()); + + for (Row row : resultRows) { + Optional.ofNullable(objectMapper.assignValues(row, typeClass)) + .ifPresent(result::add); + } + return result; + } + + /** + * Performs new query and returns the result. This result is never null. + * + * @param query The query to use + */ + @NotNull + @Override + public QueryRowsResult query(final @NotNull Query query) { + return query(query, false); + } + + public QueryRowsResult query(final @NotNull String query) { + return query(() -> query); + } + + @SuppressWarnings("unchecked") + @NotNull + QueryRowsResult query(final @NotNull Query query, boolean isRetry) { + Objects.requireNonNull(query); + if (!handleAutoReconnect()) + return new QueryRowsResult<>(false, "Cannot connect to database!"); + + QueryResult cachedResult = cacheManager.get(query, false); + if (cachedResult instanceof QueryRowsResult) return (QueryRowsResult) cachedResult; + + try (PreparedStatement stmt = buildStatement(query); + ResultSet resultSet = stmt.executeQuery()) { + QueryRowsResult result = new QueryRowsResult<>(true); + while (resultSet.next()) { + ResultSetMetaData meta = resultSet.getMetaData(); + Row row = new Row(); + for (int i = 1; i <= meta.getColumnCount(); i++) { + Object obj = resultSet.getObject(i); + if (obj instanceof String) obj = ((String) obj).replaceAll("''", "'"); + row.put(meta.getColumnName(i), obj); } - return result; - } - - /** - * Performs new query and returns the result. This result is never null. - * - * @param query The query to use - */ - @NotNull - @Override - public QueryRowsResult query(final @NotNull Query query) { - return query(query, false); - } - - public QueryRowsResult query(final @NotNull String query) { - return query(() -> query); - } - - @SuppressWarnings("unchecked") - @NotNull - QueryRowsResult query(final @NotNull Query query, boolean isRetry) { - Objects.requireNonNull(query); - if(!handleAutoReconnect()) - return new QueryRowsResult<>(false, "Cannot connect to database!"); - - QueryResult cachedResult = cacheManager.get(query, false); - if (cachedResult instanceof QueryRowsResult) return (QueryRowsResult) cachedResult; - - try(PreparedStatement stmt = buildStatement(query); - ResultSet resultSet = stmt.executeQuery()) { - QueryRowsResult result = new QueryRowsResult<>(true); - while(resultSet.next()) { - ResultSetMetaData meta = resultSet.getMetaData(); - Row row = new Row(); - for(int i = 1; i <= meta.getColumnCount(); i++) { - Object obj = resultSet.getObject(i); - if(obj instanceof String) obj = ((String) obj).replaceAll("''", "'"); - row.put(meta.getColumnName(i), obj); - } - result.add(row); - } - - cacheManager.set(query, result); - debug(result); - return result; - } catch (SQLException e) { - if (!isRetry && e.getMessage().contains("database connection closed")) { - reconnect(); - return query(query, true); - } - - logSqlError(e); - notifyError(ErrorCode.QUERY_FATAL); - query.errorSignal(e); - return new QueryRowsResult<>(false, e.getMessage()); + result.add(row); + } + + cacheManager.set(query, result); + debug(result); + return result; + } catch (SQLException e) { + if (!isRetry && e.getMessage().contains("database connection closed")) { + reconnect(); + return query(query, true); + } + + logSqlError(e); + notifyError(ErrorCode.QUERY_FATAL); + query.errorSignal(e); + return new QueryRowsResult<>(false, e.getMessage()); + } + } + + /** + * Executes given query and returns execution result. + * This result does not contain any rows. If you want to + * execute query return result of rows, see method + * {@link SQLDatabaseConnection#query(Query)} + * + * @param query Query to use for building query string. + * @return Blank rows result that only informs + * about success state of the request. + */ + public QueryResult exec(final @NotNull Query query) { + return exec(query, false); + } + + public QueryResult exec(final @NotNull String query) { + return exec(() -> query); + } + + @NotNull QueryResult exec(final @NotNull Query query, boolean isRetry) { + if (!handleAutoReconnect()) { + return new QueryResultImpl(false, "Cannot connect to database!"); + } + + QueryResult cachedResult = cacheManager.get(query, true); + if (cachedResult != null) return cachedResult; + + try (PreparedStatement stmt = buildStatement(query)) { + stmt.execute(); + QueryResultImpl result = new QueryResultImpl(true); + cacheManager.set(query, result); + debug(result); + return result; + } catch (SQLException e) { + if (!isRetry && e.getMessage().contains("database connection closed")) { + reconnect(); + return exec(query, true); + } + + logSqlError(e); + notifyError(ErrorCode.QUERY_FATAL); + query.errorSignal(e); + return new QueryResultImpl(false, e.getMessage()); + } + } + + @SuppressWarnings("unchecked") + @Nullable + protected final DefsVals buildDefsVals(Object obj) { + Objects.requireNonNull(obj); + + Class aClass = obj.getClass(); + + Map fields = new HashMap<>(); + for (Field field : aClass.getDeclaredFields()) { + + if (Modifier.isTransient(field.getModifiers())) { + // Transient fields are ignored. + continue; + } + + try { + field.setAccessible(true); + Object o = field.get(obj); + if (field.isAnnotationPresent(JsonField.class)) { + o = options.getGson().toJson(o); + } else if (Validator.validateAutoIncrement(field) && field.get(obj) == null) { + // If field is PrimaryKey and autoIncrement true and is null, + // We will skip this to use auto increment strategy on SQL server. + continue; } - } - - /** - * Executes given query and returns execution result. - * This result does not contain any rows. If you want to - * execute query return result of rows, see method - * {@link SQLDatabaseConnection#query(Query)} - * - * @param query Query to use for building query string. - * @return Blank rows result that only informs - * about success state of the request. - */ - public QueryResult exec(final @NotNull Query query) { - return exec(query, false); - } - - public QueryResult exec(final @NotNull String query) { - return exec(() -> query); - } - - @NotNull QueryResult exec(final @NotNull Query query, boolean isRetry) { - if(!handleAutoReconnect()) { - return new QueryResultImpl(false, "Cannot connect to database!"); - } - - QueryResult cachedResult = cacheManager.get(query, true); - if (cachedResult != null) return cachedResult; - - try(PreparedStatement stmt = buildStatement(query)) { - stmt.execute(); - QueryResultImpl result = new QueryResultImpl(true); - cacheManager.set(query, result); - debug(result); - return result; - } catch (SQLException e) { - if (!isRetry && e.getMessage().contains("database connection closed")) { - reconnect(); - return exec(query, true); - } - - logSqlError(e); - notifyError(ErrorCode.QUERY_FATAL); - query.errorSignal(e); - return new QueryResultImpl(false, e.getMessage()); - } - } - - @SuppressWarnings("unchecked") - @Nullable - protected final DefsVals buildDefsVals(Object obj) { - Objects.requireNonNull(obj); - - Class aClass = obj.getClass(); - - Map fields = new HashMap<>(); - for(Field field : aClass.getDeclaredFields()) { - - if(Modifier.isTransient(field.getModifiers())) { - // Transient fields are ignored. - continue; - } - - try { - field.setAccessible(true); - Object o = field.get(obj); - if(field.isAnnotationPresent(JsonField.class)) { - o = options.getGson().toJson(o); - } else if(Validator.validateAutoIncrement(field) && field.get(obj) == null) { - // If field is PrimaryKey and autoIncrement true and is null, - // We will skip this to use auto increment strategy on SQL server. - continue; - } - fields.put(options.getNamingStrategy().fieldNameToColumn(field.getName()), o); - } catch (IllegalAccessException e) { - e.printStackTrace(); - return null; - } - } - // I make entry array for indexing safety. - Map.Entry[] entryArray = fields.entrySet().toArray(new Map.Entry[0]); - String[] defs = new String[entryArray.length]; - UnknownValueWrapper[] vals = new UnknownValueWrapper[entryArray.length]; - for(int i = 0; i < entryArray.length; i++) { - defs[i] = entryArray[i].getKey(); - vals[i] = new UnknownValueWrapper(entryArray[i].getValue()); - } - return new DefsVals(defs, vals); - } - - @ApiStatus.Experimental - @SneakyThrows(SQLException.class) - public final Transaction beginTransaction() { - Connection rawConnection = getConnection(); - if (transaction != null && transaction.isActive()) { - throw new IllegalStateException("There is already an active transaction!"); - } else if(rawConnection == null) { - throw new IllegalStateException("Connection is not established!"); - } - rawConnection.setAutoCommit(false); - return transaction = new Transaction(this); - } - - @ApiStatus.Experimental - @SneakyThrows - public final void closeTransaction() { - Transaction transaction = getTransaction(); - if (transaction != null && transaction.isActive()) transaction.commit(); - this.transaction = null; - } - - public final void rollback() throws SQLException { - if (transaction == null || !transaction.isActive()) { - throw new IllegalStateException("There is no active transaction!"); - } - transaction.rollback(); - } - - @SuppressWarnings("all") - private boolean handleAutoReconnect() { - if(options.isAutoReconnect() && !isConnected()) { - return reconnect(); - } - return true; - } - - private boolean reconnect() { - debug("Trying to make a new connection with the database!"); - if(!connect()) { - debug("Cannot make new connection!"); - return false; - } - return true; - } - - public void debug(String message) { - if(options.isDebug()) logger.info(message); - } - - private void debug(QueryResult result) { - debug("Query result: " + result); - if (result instanceof QueryRowsResult) { - debug("Rows: " + ((QueryRowsResult) result).size()); - } - } - - @Override - public void close() { - if (errorCount > 0 && getAssignedPool() != null) { - // If there was any error and this connection is part of a pool, - // we won't return object to the pool, but disconnect. - disconnect(); - return; - } - - super.close(); - } + fields.put(options.getNamingStrategy().fieldNameToColumn(field.getName()), o); + } catch (IllegalAccessException e) { + e.printStackTrace(); + return null; + } + } + // I make entry array for indexing safety. + Map.Entry[] entryArray = fields.entrySet().toArray(new Map.Entry[0]); + String[] defs = new String[entryArray.length]; + UnknownValueWrapper[] vals = new UnknownValueWrapper[entryArray.length]; + for (int i = 0; i < entryArray.length; i++) { + defs[i] = entryArray[i].getKey(); + vals[i] = new UnknownValueWrapper(entryArray[i].getValue()); + } + return new DefsVals(defs, vals); + } + + @ApiStatus.Experimental + @SneakyThrows(SQLException.class) + public final Transaction beginTransaction() { + Connection rawConnection = getConnection(); + if (transaction != null && transaction.isActive()) { + throw new IllegalStateException("There is already an active transaction!"); + } else if (rawConnection == null) { + throw new IllegalStateException("Connection is not established!"); + } + rawConnection.setAutoCommit(false); + return transaction = new Transaction(this); + } + + @ApiStatus.Experimental + @SneakyThrows + public final void closeTransaction() { + Transaction transaction = getTransaction(); + if (transaction != null && transaction.isActive()) transaction.commit(); + this.transaction = null; + } + + public final void rollback() throws SQLException { + if (transaction == null || !transaction.isActive()) { + throw new IllegalStateException("There is no active transaction!"); + } + transaction.rollback(); + } + + @SuppressWarnings("all") + private boolean handleAutoReconnect() { + if (options.isAutoReconnect() && !isConnected()) { + return reconnect(); + } + return true; + } + + private boolean reconnect() { + debug("Trying to make a new connection with the database!"); + if (!connect()) { + debug("Cannot make new connection!"); + return false; + } + return true; + } + + public void debug(String message) { + if (options.isDebug()) logger.info(message); + } + + private void debug(QueryResult result) { + debug("Query result: " + result); + if (result instanceof QueryRowsResult) { + debug("Rows: " + ((QueryRowsResult) result).size()); + } + } + + @Override + public void close() { + if (errorCount > 0 && getAssignedPool() != null) { + // If there was any error and this connection is part of a pool, + // we won't return object to the pool, but disconnect. + disconnect(); + return; + } + + super.close(); + } + + @Override + public final boolean isLogSqlErrors() { + return options.isLogSqlErrors(); + } + + @Override + public final boolean isDebug() { + return options.isDebug(); + } + + @Override + public final boolean isTransactionActive() { + return transaction != null && transaction.isActive(); + } + + @Override + public TableSchemaBuilder getSchemaBuilder(String table) { + return new DatabaseSchemaBuilder(q -> { + try { + return buildStatement(() -> q); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }, table); + } + + @SuppressWarnings("all") + private void notifyError(int code) { + errorCount++; + this.errorStateHandlers.forEach(handler -> runCatching(() -> handler.onErrorState(code))); + } + + public final SQLDatabaseOptions cloneOptions() { + SQLDatabaseOptions cloned = new SQLDatabaseOptions(); + cloned.setDebug(options.isDebug()); + cloned.setLogSqlErrors(options.isLogSqlErrors()); + cloned.setNamingStrategy(options.getNamingStrategy()); + cloned.setGson(options.getGson()); + cloned.setAutoReconnect(options.isAutoReconnect()); + return cloned; + } + + @SuppressWarnings("unchecked") + private PreparedStatement buildStatement(Query query) throws SQLException { + StatementFactory factory = new DefaultStatementFactory(query); + if (query instanceof StatementFactory) + factory = (StatementFactory) query; + + return factory.prepare(getConnection()); + } + + @RequiredArgsConstructor + static class DefaultStatementFactory implements StatementFactory { + + private final Query query; @Override - public final boolean isLogSqlErrors() { - return options.isLogSqlErrors(); - } + public PreparedStatement prepare(Connection connection) throws SQLException { + String queryString = query.getAncestor().buildQuery(); - @Override - public final boolean isDebug() { - return options.isDebug(); + SQLConnectionRegistry.debug(connection, "Query: " + queryString); + return connection.prepareStatement(queryString); } + } - @Override - public final boolean isTransactionActive() { - return transaction != null && transaction.isActive(); - } - - @Override - public TableSchemaBuilder getSchemaBuilder(String table) { - return new DatabaseSchemaBuilder(q -> { - try { - return buildStatement(() -> q); - } catch (SQLException e) { - throw new RuntimeException(e); - } - }, table); - } - - @SuppressWarnings("all") - private void notifyError(int code) { - errorCount++; - this.errorStateHandlers.forEach(handler -> runCatching(() -> handler.onErrorState(code))); - } + public interface ErrorStateObserver { + void onErrorState(int code); + } - public final SQLDatabaseOptions cloneOptions() { - SQLDatabaseOptions cloned = new SQLDatabaseOptions(); - cloned.setDebug(options.isDebug()); - cloned.setLogSqlErrors(options.isLogSqlErrors()); - cloned.setNamingStrategy(options.getNamingStrategy()); - cloned.setGson(options.getGson()); - cloned.setAutoReconnect(options.isAutoReconnect()); - return cloned; - } - - @SuppressWarnings("unchecked") - private PreparedStatement buildStatement(Query query) throws SQLException { - StatementFactory factory = new DefaultStatementFactory(query); - if (query instanceof StatementFactory) - factory = (StatementFactory) query; - - return factory.prepare(getConnection()); - } - - @RequiredArgsConstructor - static class DefaultStatementFactory implements StatementFactory { - - private final Query query; - - @Override - public PreparedStatement prepare(Connection connection) throws SQLException { - String queryString = query.getAncestor().buildQuery(); - - SQLConnectionRegistry.debug(connection, "Query: " + queryString); - return connection.prepareStatement(queryString); - } - } - - public interface ErrorStateObserver { - void onErrorState(int code); - } - - public static final class ErrorCode { - public static final int QUERY_FATAL = 0; - } + public static final class ErrorCode { + public static final int QUERY_FATAL = 0; + } } diff --git a/core/src/main/java/me/zort/sqllib/SQLDatabaseOptions.java b/core/src/main/java/me/zort/sqllib/SQLDatabaseOptions.java index cc5ca30..3424b9a 100644 --- a/core/src/main/java/me/zort/sqllib/SQLDatabaseOptions.java +++ b/core/src/main/java/me/zort/sqllib/SQLDatabaseOptions.java @@ -15,25 +15,25 @@ @Data public final class SQLDatabaseOptions implements ISQLDatabaseOptions { - private boolean autoReconnect = true; - private boolean debug = false; - private boolean logSqlErrors = true; - private transient NamingStrategy namingStrategy = SQLDatabaseConnectionImpl.DEFAULT_NAMING_STRATEGY; - private transient Gson gson = Defaults.DEFAULT_GSON; + private boolean autoReconnect = true; + private boolean debug = false; + private boolean logSqlErrors = true; + private transient NamingStrategy namingStrategy = SQLDatabaseConnectionImpl.DEFAULT_NAMING_STRATEGY; + private transient Gson gson = Defaults.DEFAULT_GSON; - /** - * Loads options from a connection. - * - * @param connection The connection to load options from. - */ - @SuppressWarnings("unused") - public void load(final @NotNull SQLDatabaseConnectionImpl connection) { - ISQLDatabaseOptions options = connection.getOptions(); - this.autoReconnect = options.isAutoReconnect(); - this.debug = options.isDebug(); - this.logSqlErrors = options.isLogSqlErrors(); - this.namingStrategy = options.getNamingStrategy(); - this.gson = options.getGson(); - } + /** + * Loads options from a connection. + * + * @param connection The connection to load options from. + */ + @SuppressWarnings("unused") + public void load(final @NotNull SQLDatabaseConnectionImpl connection) { + ISQLDatabaseOptions options = connection.getOptions(); + this.autoReconnect = options.isAutoReconnect(); + this.debug = options.isDebug(); + this.logSqlErrors = options.isLogSqlErrors(); + this.namingStrategy = options.getNamingStrategy(); + this.gson = options.getGson(); + } } diff --git a/core/src/main/java/me/zort/sqllib/SQLiteDatabaseConnection.java b/core/src/main/java/me/zort/sqllib/SQLiteDatabaseConnection.java index ddb9422..422674f 100644 --- a/core/src/main/java/me/zort/sqllib/SQLiteDatabaseConnection.java +++ b/core/src/main/java/me/zort/sqllib/SQLiteDatabaseConnection.java @@ -26,162 +26,166 @@ * @author ZorTik */ public class SQLiteDatabaseConnection extends SQLDatabaseConnectionImpl { - private final SQLiteDatabaseConnection identity = this; - - @SuppressWarnings("unused") - public SQLiteDatabaseConnection(final @NotNull SQLConnectionFactory connectionFactory) { - super(connectionFactory); - setup(); + private final SQLiteDatabaseConnection identity = this; + + @SuppressWarnings("unused") + public SQLiteDatabaseConnection(final @NotNull SQLConnectionFactory connectionFactory) { + super(connectionFactory); + setup(); + } + + public SQLiteDatabaseConnection(final @NotNull SQLConnectionFactory connectionFactory, @Nullable ISQLDatabaseOptions options) { + super(connectionFactory, options); + setup(); + } + + // Adjust behaviour to be compatible with SQLite + private void setup() { + if (getSchemaSynchronizer() instanceof SQLSchemaSynchronizer) { + SQLSchemaSynchronizer schemaSynchronizer = (SQLSchemaSynchronizer) getSchemaSynchronizer(); + schemaSynchronizer.setColumnQueryBuilder(new SQLiteColumnQueryBuilder(this)); + schemaSynchronizer.setColumnTypeAdjuster(new SQLiteColumnTypeAdjuster()); + schemaSynchronizer.setSeparateQueries(true); + } + } + + /** + * Performs an upsert query for defined object + * as stated in {@link SQLDatabaseConnection#save(String, Object)}. + *

+ * Object needs to have {@link me.zort.sqllib.internal.annotation.PrimaryKey} annotation + * set to determine which column is a primary key. + * + * @param table Table to save into. + * @param obj The object to save. + * @return Result of the query. + */ + @NotNull + @Override + public final UpsertQuery save(@NotNull String table, @NotNull Object obj) { + DefsVals defsVals = buildDefsVals(obj); + if (defsVals == null) throw new IllegalArgumentException("Cannot create save query! (defsVals == null)"); + String[] defs = defsVals.getDefs(); + UnknownValueWrapper[] vals = defsVals.getVals(); + + debug("Saving object into table " + table + " with definitions " + Arrays.toString(defs) + " and values " + Arrays.toString(vals)); + + PrimaryKey primaryKey = null; + for (Field field : obj.getClass().getDeclaredFields()) { + if (Modifier.isTransient(field.getModifiers())) { + continue; + } + if (field.isAnnotationPresent(me.zort.sqllib.internal.annotation.PrimaryKey.class)) { + String colName = getOptions().getNamingStrategy().fieldNameToColumn(field.getName()); + //int index = Arrays.binarySearch(defs, colName); + int index = -1; + int i = 0; + for (String def : defs) { + if (def.equals(colName)) { + index = i; + break; + } + i++; + } + if (index >= 0) { + primaryKey = new PrimaryKey(colName, vals[index].getObject() instanceof String + ? (String) vals[index].getObject() : String.valueOf(vals[index].getObject())); + break; + } + } + } + InsertQuery insert = insert().into(table, defs); + for (UnknownValueWrapper val : vals) { + insert.appendVal(val.getObject()); } - public SQLiteDatabaseConnection(final @NotNull SQLConnectionFactory connectionFactory, @Nullable ISQLDatabaseOptions options) { - super(connectionFactory, options); - setup(); + if (primaryKey == null) { + debug("No primary key found for object " + obj.getClass().getName() + ", so we can't build update condition."); + debug("Performing insert query instead: " + insert.buildQuery()); + return new UpsertQueryDecorator(insert); } - private void setup() { - if (getSchemaSynchronizer() instanceof SQLSchemaSynchronizer) { - SQLSchemaSynchronizer schemaSynchronizer = (SQLSchemaSynchronizer) getSchemaSynchronizer(); - schemaSynchronizer.setColumnQueryBuilder(new SQLiteColumnQueryBuilder(this)); - schemaSynchronizer.setColumnTypeAdjuster(new SQLiteColumnTypeAdjuster()); - schemaSynchronizer.setSeparateQueries(true); - } + SetStatement setStmt = update().table(table).set(); + for (int i = 0; i < defs.length; i++) { + setStmt.and(defs[i], vals[i].getObject()); + } + UpdateQuery update = setStmt.also() + .where().isEqual(primaryKey.getColumn(), primaryKey.getValue()) + .also(); + return new UpsertQueryDecorator(upsert(table, primaryKey, insert, update)); + } + + /** + * Builds an upsert query for defined table and primary key. + * This returns either a provided insert or update query depending + * on upsert situation. + * + * @param table Table to upsert into. + * @param primaryKey Primary key to use. + * @param insert Insert query to use. + * @param update Update query to use. + * @return Either insert or update query. + */ + @Nullable + public final QueryNode upsert(final @NotNull String table, + final @NotNull PrimaryKey primaryKey, + final @NotNull InsertQuery insert, + final @NotNull UpdateQuery update) { + + QueryRowsResult selectResult = select("*") + .from(table) + .where().isEqual(primaryKey.getColumn(), primaryKey.getValue()) + .also().limit(1) + .obtainAll(); + if (!selectResult.isSuccessful()) { + // Not successful, we'll skip other queries. + return null; } + return selectResult.isEmpty() ? insert : update; + } - /** - * Performs an upsert query for defined object - * as stated in {@link SQLDatabaseConnection#save(String, Object)}. - *

- * Object needs to have {@link me.zort.sqllib.internal.annotation.PrimaryKey} annotation - * set to determine which column is a primary key. - * - * @param table Table to save into. - * @param obj The object to save. - * @return Result of the query. - */ - @NotNull - @Override - public final UpsertQuery save(@NotNull String table, @NotNull Object obj) { - DefsVals defsVals = buildDefsVals(obj); - if(defsVals == null) throw new IllegalArgumentException("Cannot create save query! (defsVals == null)"); - String[] defs = defsVals.getDefs(); - UnknownValueWrapper[] vals = defsVals.getVals(); - - debug("Saving object into table " + table + " with definitions " + Arrays.toString(defs) + " and values " + Arrays.toString(vals)); - - PrimaryKey primaryKey = null; - for(Field field : obj.getClass().getDeclaredFields()) { - if(Modifier.isTransient(field.getModifiers())) { - continue; - } - if(field.isAnnotationPresent(me.zort.sqllib.internal.annotation.PrimaryKey.class)) { - String colName = getOptions().getNamingStrategy().fieldNameToColumn(field.getName()); - //int index = Arrays.binarySearch(defs, colName); - int index = -1; - int i = 0; - for (String def : defs) { - if(def.equals(colName)) { - index = i; - break; - } - i++; - } - if(index >= 0) { - primaryKey = new PrimaryKey(colName, vals[index].getObject() instanceof String - ? (String)vals[index].getObject() : String.valueOf(vals[index].getObject())); - break; - } - } - } - InsertQuery insert = insert().into(table, defs); - for(UnknownValueWrapper val : vals) { - insert.appendVal(val.getObject()); - } + @NotNull + @Override + public QueryResult exec(@NotNull Query query) { + if (query instanceof UpsertQuery && ((UpsertQuery) query).getAssignedSaveObject() != null) + query = save(((UpsertQuery) query).getTable(), ((UpsertQuery) query).getAssignedSaveObject()); - if(primaryKey == null) { - debug("No primary key found for object " + obj.getClass().getName() + ", so we can't build update condition."); - debug("Performing insert query instead: " + insert.buildQuery()); - return new UpsertQueryDecorator(insert); - } + return super.exec(query); + } - SetStatement setStmt = update().table(table).set(); - for(int i = 0; i < defs.length; i++) { - setStmt.and(defs[i], vals[i].getObject()); - } - UpdateQuery update = setStmt.also() - .where().isEqual(primaryKey.getColumn(), primaryKey.getValue()) - .also(); - return new UpsertQueryDecorator(upsert(table, primaryKey, insert, update)); - } + final class UpsertQueryDecorator extends UpsertQuery { + private final QueryNode query; - /** - * Builds an upsert query for defined table and primary key. - * This returns either a provided insert or update query depending - * on upsert situation. - * - * @param table Table to upsert into. - * @param primaryKey Primary key to use. - * @param insert Insert query to use. - * @param update Update query to use. - * @return Either insert or update query. - */ - @Nullable - public final QueryNode upsert(final @NotNull String table, - final @NotNull PrimaryKey primaryKey, - final @NotNull InsertQuery insert, - final @NotNull UpdateQuery update) { - - QueryRowsResult selectResult = select("*") - .from(table) - .where().isEqual(primaryKey.getColumn(), primaryKey.getValue()) - .also().limit(1) - .obtainAll(); - if(!selectResult.isSuccessful()) { - // Not successful, we'll skip other queries. - return null; - } - return selectResult.isEmpty() ? insert : update; + public UpsertQueryDecorator(QueryNode query) { + super(identity); + this.query = query; } - @NotNull @Override - public QueryResult exec(@NotNull Query query) { - if (query instanceof UpsertQuery && ((UpsertQuery) query).getAssignedSaveObject() != null) - query = save(((UpsertQuery) query).getTable(), ((UpsertQuery) query).getAssignedSaveObject()); - - return super.exec(query); + public QueryDetails buildQueryDetails() { + return query.buildQueryDetails(); } - final class UpsertQueryDecorator extends UpsertQuery { - private final QueryNode query; + @Override + public UpsertQuery into(String table, String... defs) { + notAvailable(); + return null; + } - public UpsertQueryDecorator(QueryNode query) { - super(identity); - this.query = query; - } + @Override + public UpsertQuery table(String table) { + notAvailable(); + return null; + } - @Override - public QueryDetails buildQueryDetails() { - return query.buildQueryDetails(); - } + @Override + public UpsertQuery values(Object... values) { + notAvailable(); + return null; + } - @Override - public UpsertQuery into(String table, String... defs) { - notAvailable(); - return null; - } - @Override - public UpsertQuery table(String table) { - notAvailable(); - return null; - } - @Override - public UpsertQuery values(Object... values) { - notAvailable(); - return null; - } - private void notAvailable() { - throw new UnsupportedOperationException("You can't modify upsert query in SQLite mode!"); - } + private void notAvailable() { + throw new UnsupportedOperationException("You can't modify upsert query in SQLite mode!"); } + } } diff --git a/core/src/main/java/me/zort/sqllib/api/provider/Delete.java b/core/src/main/java/me/zort/sqllib/api/provider/Delete.java index 4a644fb..0a621b5 100644 --- a/core/src/main/java/me/zort/sqllib/api/provider/Delete.java +++ b/core/src/main/java/me/zort/sqllib/api/provider/Delete.java @@ -4,12 +4,12 @@ public final class Delete { - public static DeleteQuery of() { - return new DeleteQuery(null); - } + public static DeleteQuery of() { + return new DeleteQuery(null); + } - public static DeleteQuery of(String table) { - return new DeleteQuery(null, table); - } + public static DeleteQuery of(String table) { + return new DeleteQuery(null, table); + } } diff --git a/core/src/main/java/me/zort/sqllib/api/provider/Select.java b/core/src/main/java/me/zort/sqllib/api/provider/Select.java index 7658c98..c850e61 100644 --- a/core/src/main/java/me/zort/sqllib/api/provider/Select.java +++ b/core/src/main/java/me/zort/sqllib/api/provider/Select.java @@ -4,8 +4,8 @@ public final class Select { - public static SelectQuery of(String... columns) { - return new SelectQuery(null, columns); - } + public static SelectQuery of(String... columns) { + return new SelectQuery(null, columns); + } } diff --git a/core/src/main/java/me/zort/sqllib/cache/ExpirableEntriesCacheManager.java b/core/src/main/java/me/zort/sqllib/cache/ExpirableEntriesCacheManager.java index 17e6765..2234348 100644 --- a/core/src/main/java/me/zort/sqllib/cache/ExpirableEntriesCacheManager.java +++ b/core/src/main/java/me/zort/sqllib/cache/ExpirableEntriesCacheManager.java @@ -12,27 +12,27 @@ public class ExpirableEntriesCacheManager implements CacheManager { - private final Cache cache; + private final Cache cache; - /** - * Creates a new cache manager with provided expiration duration - * in milliseconds. - * - * @param expirationDuration The expiration duration - */ - public ExpirableEntriesCacheManager(long expirationDuration) { - cache = CacheBuilder.newBuilder() - .expireAfterWrite(expirationDuration, TimeUnit.MILLISECONDS) - .build(); - } + /** + * Creates a new cache manager with provided expiration duration + * in milliseconds. + * + * @param expirationDuration The expiration duration + */ + public ExpirableEntriesCacheManager(long expirationDuration) { + cache = CacheBuilder.newBuilder() + .expireAfterWrite(expirationDuration, TimeUnit.MILLISECONDS) + .build(); + } - @Override - public void set(@NotNull Query query, @NotNull QueryResult result) { - cache.put(query, result); - } + @Override + public void set(@NotNull Query query, @NotNull QueryResult result) { + cache.put(query, result); + } - @Override - public @Nullable QueryResult get(@NotNull Query query, boolean isExec) { - return cache.getIfPresent(query); - } + @Override + public @Nullable QueryResult get(@NotNull Query query, boolean isExec) { + return cache.getIfPresent(query); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/Defaults.java b/core/src/main/java/me/zort/sqllib/internal/Defaults.java index 6beafd7..29503ac 100644 --- a/core/src/main/java/me/zort/sqllib/internal/Defaults.java +++ b/core/src/main/java/me/zort/sqllib/internal/Defaults.java @@ -7,14 +7,14 @@ public final class Defaults { - public static final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver"; - public static final boolean DEFAULT_AUTO_RECONNECT = true; - public static final boolean DEFAULT_DEBUG = false; - public static final boolean DEFAULT_LOG_SQL_ERRORS = true; - public static final NamingStrategy DEFAULT_NAMING_STRATEGY = new SymbolSeparatedNamingStrategy('_'); + public static final String DEFAULT_DRIVER = "com.mysql.jdbc.Driver"; + public static final boolean DEFAULT_AUTO_RECONNECT = true; + public static final boolean DEFAULT_DEBUG = false; + public static final boolean DEFAULT_LOG_SQL_ERRORS = true; + public static final NamingStrategy DEFAULT_NAMING_STRATEGY = new SymbolSeparatedNamingStrategy('_'); - public static final Gson DEFAULT_GSON = new GsonBuilder() - .enableComplexMapKeySerialization() - .create(); + public static final Gson DEFAULT_GSON = new GsonBuilder() + .enableComplexMapKeySerialization() + .create(); } diff --git a/core/src/main/java/me/zort/sqllib/internal/fieldResolver/ConstructorParameterResolver.java b/core/src/main/java/me/zort/sqllib/internal/fieldResolver/ConstructorParameterResolver.java index 564fc9a..0e196c4 100644 --- a/core/src/main/java/me/zort/sqllib/internal/fieldResolver/ConstructorParameterResolver.java +++ b/core/src/main/java/me/zort/sqllib/internal/fieldResolver/ConstructorParameterResolver.java @@ -13,41 +13,42 @@ @ApiStatus.AvailableSince("0.5.1") public class ConstructorParameterResolver implements ObjectMapper.FieldValueResolver { - private static final Pattern argumentPattern = Pattern.compile("(arg)(\\d+)"); - - @Override - public Object obtainValue(SQLConnection connection, - AnnotatedElement element, - Row row, - String fieldName, - String convertedName, - Type type) { - if (!(element instanceof Parameter) || !(((Parameter) element).getDeclaringExecutable() instanceof Constructor)) - return null; - - Parameter p = (Parameter) element; - Matcher matcher = argumentPattern.matcher(p.getName()); - - if (matcher.matches()) { - try { - Field[] fields = ((Constructor) p.getDeclaringExecutable()).getDeclaringClass().getDeclaredFields(); - int index = Integer.parseInt(matcher.group(2)); - if (index >= fields.length) - return null; - - int i = -1; - for (Field field : fields) { - if (Validator.validateAssignableField(field)) - i++; - - if (i == index) { - fieldName = field.getName(); - break; - } - } - } catch (NumberFormatException ignored) {} + private static final Pattern argumentPattern = Pattern.compile("(arg)(\\d+)"); + + @Override + public Object obtainValue(SQLConnection connection, + AnnotatedElement element, + Row row, + String fieldName, + String convertedName, + Type type) { + if (!(element instanceof Parameter) || !(((Parameter) element).getDeclaringExecutable() instanceof Constructor)) + return null; + + Parameter p = (Parameter) element; + Matcher matcher = argumentPattern.matcher(p.getName()); + + if (matcher.matches()) { + try { + Field[] fields = ((Constructor) p.getDeclaringExecutable()).getDeclaringClass().getDeclaredFields(); + int index = Integer.parseInt(matcher.group(2)); + if (index >= fields.length) + return null; + + int i = -1; + for (Field field : fields) { + if (Validator.validateAssignableField(field)) + i++; + + if (i == index) { + fieldName = field.getName(); + break; + } } - - return row.get(fieldName); + } catch (NumberFormatException ignored) { + } } + + return row.get(fieldName); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/fieldResolver/LinkedOneFieldResolver.java b/core/src/main/java/me/zort/sqllib/internal/fieldResolver/LinkedOneFieldResolver.java index 4d3d9c8..031367c 100644 --- a/core/src/main/java/me/zort/sqllib/internal/fieldResolver/LinkedOneFieldResolver.java +++ b/core/src/main/java/me/zort/sqllib/internal/fieldResolver/LinkedOneFieldResolver.java @@ -15,62 +15,63 @@ /** * Functionality class for {@link LinkedOne} annotation. - * @see LinkedOne + * * @author ZorTik + * @see LinkedOne */ public class LinkedOneFieldResolver implements ObjectMapper.FieldValueResolver { - @Override - public Object obtainValue(SQLConnection _connection, - AnnotatedElement element, - Row row, - String fieldName, - String convertedName, - Type type) { + @Override + public Object obtainValue(SQLConnection _connection, + AnnotatedElement element, + Row row, + String fieldName, + String convertedName, + Type type) { - if(!(_connection instanceof SQLDatabaseConnectionImpl)) - return null; + if (!(_connection instanceof SQLDatabaseConnectionImpl)) + return null; - SQLDatabaseConnectionImpl connection = (SQLDatabaseConnectionImpl) _connection; + SQLDatabaseConnectionImpl connection = (SQLDatabaseConnectionImpl) _connection; - if(!element.isAnnotationPresent(LinkedOne.class)) { - // This makes mapping function hop to the next resolver. - return null; - } - Class targetClass; - if(element instanceof Field) { - targetClass = ((Field) element).getType(); - } else { - targetClass = ((Parameter) element).getType(); - } - Field targetIdField = null; - for(Field field : targetClass.getDeclaredFields()) { - if(field.isAnnotationPresent(PrimaryKey.class)) { - targetIdField = field; - break; - } - } - if(targetIdField == null) { - // Target type has no primary key annotated! - connection.debug(String.format("No primary key field set for target in @LinkedOne field %s.", fieldName)); - return null; - } + if (!element.isAnnotationPresent(LinkedOne.class)) { + // This makes mapping function hop to the next resolver. + return null; + } + Class targetClass; + if (element instanceof Field) { + targetClass = ((Field) element).getType(); + } else { + targetClass = ((Parameter) element).getType(); + } + Field targetIdField = null; + for (Field field : targetClass.getDeclaredFields()) { + if (field.isAnnotationPresent(PrimaryKey.class)) { + targetIdField = field; + break; + } + } + if (targetIdField == null) { + // Target type has no primary key annotated! + connection.debug(String.format("No primary key field set for target in @LinkedOne field %s.", fieldName)); + return null; + } - LinkedOne linkedOne = element.getAnnotation(LinkedOne.class); - Object idObject = row.get(fieldName); - if(idObject == null && (idObject = row.get(convertedName)) == null) { - // No local column found with that name. - connection.debug(String.format("No local column found for @LinkedOne field %s.", fieldName)); - return null; - } - return connection.query(Select.of("*") - .from(linkedOne.targetTable()) - .where().isEqual( - connection.getOptions().getNamingStrategy().fieldNameToColumn(targetIdField.getName()), - idObject), - targetClass) - .stream() - .findFirst().orElse(null); + LinkedOne linkedOne = element.getAnnotation(LinkedOne.class); + Object idObject = row.get(fieldName); + if (idObject == null && (idObject = row.get(convertedName)) == null) { + // No local column found with that name. + connection.debug(String.format("No local column found for @LinkedOne field %s.", fieldName)); + return null; } + return connection.query(Select.of("*") + .from(linkedOne.targetTable()) + .where().isEqual( + connection.getOptions().getNamingStrategy().fieldNameToColumn(targetIdField.getName()), + idObject), + targetClass) + .stream() + .findFirst().orElse(null); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/impl/DefaultObjectMapper.java b/core/src/main/java/me/zort/sqllib/internal/impl/DefaultObjectMapper.java index 6352845..9721458 100644 --- a/core/src/main/java/me/zort/sqllib/internal/impl/DefaultObjectMapper.java +++ b/core/src/main/java/me/zort/sqllib/internal/impl/DefaultObjectMapper.java @@ -16,115 +16,115 @@ public class DefaultObjectMapper implements ObjectMapper { - // Resolvers used after no value is found for the field - // in mapped object as backup. - @Getter(AccessLevel.PROTECTED) - private final List backupValueResolvers; - private final SQLDatabaseConnectionImpl connectionWrapper; + // Resolvers used after no value is found for the field + // in mapped object as backup. + @Getter(AccessLevel.PROTECTED) + private final List backupValueResolvers; + private final SQLDatabaseConnectionImpl connectionWrapper; - public DefaultObjectMapper(SQLDatabaseConnectionImpl connectionWrapper) { - this.backupValueResolvers = new CopyOnWriteArrayList<>(); - this.connectionWrapper = connectionWrapper; - } + public DefaultObjectMapper(SQLDatabaseConnectionImpl connectionWrapper) { + this.backupValueResolvers = new CopyOnWriteArrayList<>(); + this.connectionWrapper = connectionWrapper; + } - @Override - public void registerBackupValueResolver(@NotNull FieldValueResolver resolver) { - this.backupValueResolvers.add(resolver); - } + @Override + public void registerBackupValueResolver(@NotNull FieldValueResolver resolver) { + this.backupValueResolvers.add(resolver); + } - @Nullable - public T assignValues(Row row, Class typeClass) { - T instance = null; - try { + @Nullable + public T assignValues(Row row, Class typeClass) { + T instance = null; + try { + try { + Constructor c = typeClass.getConstructor(); + c.setAccessible(true); + instance = c.newInstance(); + } catch (NoSuchMethodException e) { + for (Constructor c : typeClass.getConstructors()) { + if (c.getParameterCount() == row.size()) { + Parameter[] params = c.getParameters(); + Object[] vals = new Object[c.getParameterCount()]; + for (int i = 0; i < row.size(); i++) { + Parameter param = params[i]; + vals[i] = buildElementValue(param, row); + } try { - Constructor c = typeClass.getConstructor(); - c.setAccessible(true); - instance = c.newInstance(); - } catch (NoSuchMethodException e) { - for(Constructor c : typeClass.getConstructors()) { - if(c.getParameterCount() == row.size()) { - Parameter[] params = c.getParameters(); - Object[] vals = new Object[c.getParameterCount()]; - for(int i = 0; i < row.size(); i++) { - Parameter param = params[i]; - vals[i] = buildElementValue(param, row); - } - try { - c.setAccessible(true); - instance = (T) c.newInstance(vals); - } catch(Exception ignored) { - } - } - } + c.setAccessible(true); + instance = (T) c.newInstance(vals); + } catch (Exception ignored) { } - for(Field field : typeClass.getDeclaredFields()) { - - if(Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { - continue; - } + } + } + } + for (Field field : typeClass.getDeclaredFields()) { - try { - field.setAccessible(true); - field.set(instance, buildElementValue(field, row)); - } catch(SecurityException ignored) { - debug(String.format("Field %s on class %s cannot be set accessible!", - field.getName(), - typeClass.getName())); - } catch(Exception ignored) { - } - } - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - debug("Cannot instantinate " + typeClass.getName() + " for assigning attributes from row!"); - e.printStackTrace(); - return null; + if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { + continue; } - return instance; - } - @Nullable - private Object buildElementValue(AnnotatedElement element, Row row) { - String name; - Type type; - Class declaringClass; - if(element instanceof Field) { - name = ((Field) element).getName(); - type = ((Field) element).getGenericType(); - declaringClass = ((Field) element).getDeclaringClass(); - } else if(element instanceof Parameter) { - name = ((Parameter) element).getName(); - type = ((Parameter) element).getType(); - declaringClass = ((Parameter) element).getDeclaringExecutable().getDeclaringClass(); - } else { - return null; + try { + field.setAccessible(true); + field.set(instance, buildElementValue(field, row)); + } catch (SecurityException ignored) { + debug(String.format("Field %s on class %s cannot be set accessible!", + field.getName(), + typeClass.getName())); + } catch (Exception ignored) { } - Object obj = row.get(name); - if(obj == null) { - String converted; - if((obj = row.get(converted = connectionWrapper.getOptions().getNamingStrategy().fieldNameToColumn(name))) == null) { + } + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + debug("Cannot instantinate " + typeClass.getName() + " for assigning attributes from row!"); + e.printStackTrace(); + return null; + } + return instance; + } - // Now backup resolvers come. - for(ObjectMapper.FieldValueResolver resolver : backupValueResolvers) { - Object backupValue = resolver.obtainValue(connectionWrapper, element, row, name, converted, type); - if(backupValue != null) { - return backupValue; - } - } + @Nullable + private Object buildElementValue(AnnotatedElement element, Row row) { + String name; + Type type; + Class declaringClass; + if (element instanceof Field) { + name = ((Field) element).getName(); + type = ((Field) element).getGenericType(); + declaringClass = ((Field) element).getDeclaringClass(); + } else if (element instanceof Parameter) { + name = ((Parameter) element).getName(); + type = ((Parameter) element).getType(); + declaringClass = ((Parameter) element).getDeclaringExecutable().getDeclaringClass(); + } else { + return null; + } + Object obj = row.get(name); + if (obj == null) { + String converted; + if ((obj = row.get(converted = connectionWrapper.getOptions().getNamingStrategy().fieldNameToColumn(name))) == null) { - debug(String.format("Cannot find column for class %s target %s (%s)", declaringClass.getName(), name, converted)); - return null; - } + // Now backup resolvers come. + for (ObjectMapper.FieldValueResolver resolver : backupValueResolvers) { + Object backupValue = resolver.obtainValue(connectionWrapper, element, row, name, converted, type); + if (backupValue != null) { + return backupValue; + } } - if(element.isAnnotationPresent(JsonField.class) && obj instanceof String) { - String jsonString = (String) obj; - Gson gson = connectionWrapper.getOptions().getGson(); - return gson.fromJson(jsonString, type); - } else { - return obj; - } - } - private void debug(String message) { - connectionWrapper.debug(message); + debug(String.format("Cannot find column for class %s target %s (%s)", declaringClass.getName(), name, converted)); + return null; + } } + if (element.isAnnotationPresent(JsonField.class) && obj instanceof String) { + String jsonString = (String) obj; + Gson gson = connectionWrapper.getOptions().getGson(); + return gson.fromJson(jsonString, type); + } else { + return obj; + } + } + + private void debug(String message) { + connectionWrapper.debug(message); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/impl/DefaultSQLEndpoint.java b/core/src/main/java/me/zort/sqllib/internal/impl/DefaultSQLEndpoint.java index 126ed5e..2689cfe 100644 --- a/core/src/main/java/me/zort/sqllib/internal/impl/DefaultSQLEndpoint.java +++ b/core/src/main/java/me/zort/sqllib/internal/impl/DefaultSQLEndpoint.java @@ -2,8 +2,8 @@ public class DefaultSQLEndpoint extends SQLEndpointImpl { - public DefaultSQLEndpoint(String url, String database, String username, String password) { - super(String.format("jdbc:mysql://%s/%s", url, database), username, password); - } + public DefaultSQLEndpoint(String url, String database, String username, String password) { + super(String.format("jdbc:mysql://%s/%s", url, database), username, password); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/impl/QueryResultImpl.java b/core/src/main/java/me/zort/sqllib/internal/impl/QueryResultImpl.java index b292f0a..ceec1d5 100644 --- a/core/src/main/java/me/zort/sqllib/internal/impl/QueryResultImpl.java +++ b/core/src/main/java/me/zort/sqllib/internal/impl/QueryResultImpl.java @@ -9,27 +9,27 @@ @Getter public class QueryResultImpl implements QueryResult { - private final boolean successful; - private String rejectMessage = null; + private final boolean successful; + private String rejectMessage = null; - public QueryResultImpl(boolean successful, String rejectMessage) { - this.successful = successful; - rejectMessage(rejectMessage); - } + public QueryResultImpl(boolean successful, String rejectMessage) { + this.successful = successful; + rejectMessage(rejectMessage); + } - public QueryResultImpl rejectMessage(String message) { - if (rejectMessage != null) - throw new RuntimeException("Reject message is already set!"); + public QueryResultImpl rejectMessage(String message) { + if (rejectMessage != null) + throw new RuntimeException("Reject message is already set!"); - this.rejectMessage = message; - return this; - } + this.rejectMessage = message; + return this; + } - @Override - public String toString() { - return "QueryResultImpl{" + - "successful=" + successful + - ", rejectMessage='" + rejectMessage + '\'' + - '}'; - } + @Override + public String toString() { + return "QueryResultImpl{" + + "successful=" + successful + + ", rejectMessage='" + rejectMessage + '\'' + + '}'; + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/impl/SQLEndpointImpl.java b/core/src/main/java/me/zort/sqllib/internal/impl/SQLEndpointImpl.java index d475084..6e0d2a9 100644 --- a/core/src/main/java/me/zort/sqllib/internal/impl/SQLEndpointImpl.java +++ b/core/src/main/java/me/zort/sqllib/internal/impl/SQLEndpointImpl.java @@ -8,13 +8,13 @@ @Getter public class SQLEndpointImpl implements SQLEndpoint { - private final String jdbc; - private final String username; - private final String password; + private final String jdbc; + private final String username; + private final String password; - @Override - public String buildJdbc() { - return jdbc; - } + @Override + public String buildJdbc() { + return jdbc; + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/Conditional.java b/core/src/main/java/me/zort/sqllib/internal/query/Conditional.java index bdd808a..6f0bed9 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/Conditional.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/Conditional.java @@ -7,17 +7,17 @@ public interface Conditional

& Conditional

> { // P = self - default WhereStatement

where() { - return where(QueryPriority.CONDITION.getPrior()); - } + default WhereStatement

where() { + return where(QueryPriority.CONDITION.getPrior()); + } - default WhereStatement

where(int priority) { - if(!(this instanceof QueryNode)) { - throw new IllegalStatementOperationException("This instance is not query part!"); - } - WhereStatement

stmt = new WhereStatement<>((P) this, new ArrayList<>(), priority); - ((QueryNode) this).then(stmt); - return stmt; + default WhereStatement

where(int priority) { + if (!(this instanceof QueryNode)) { + throw new IllegalStatementOperationException("This instance is not query part!"); } + WhereStatement

stmt = new WhereStatement<>((P) this, new ArrayList<>(), priority); + ((QueryNode) this).then(stmt); + return stmt; + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/DeleteQuery.java b/core/src/main/java/me/zort/sqllib/internal/query/DeleteQuery.java index 70650f4..96900e6 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/DeleteQuery.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/DeleteQuery.java @@ -11,47 +11,47 @@ public class DeleteQuery extends QueryNode> implements Executive, Conditional, Limitable { - private String table; - - @Getter - private final SQLDatabaseConnection connection; - - public DeleteQuery() { - this(null); - } - - public DeleteQuery(@Nullable SQLDatabaseConnection connection) { - this(connection, null); - } - - public DeleteQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table) { - super(null, new ArrayList<>(), QueryPriority.GENERAL); - this.table = table; - this.connection = connection; - } - - public DeleteQuery from(String table) { - this.table = table; - return this; - } - - public DeleteQuery limit(int limit) { - then(new LimitStatement<>(this, new ArrayList<>(), limit)); - return this; - } - - @Override - public QueryDetails buildQueryDetails() { - Objects.requireNonNull(table, "Table cannot be null!"); - - return new QueryDetails.Builder("DELETE FROM " + table) - .build() - .append(buildInnerQuery()); - } - - @Override - public DeleteQuery then(String part) { - return (DeleteQuery) super.then(part); - } + private String table; + + @Getter + private final SQLDatabaseConnection connection; + + public DeleteQuery() { + this(null); + } + + public DeleteQuery(@Nullable SQLDatabaseConnection connection) { + this(connection, null); + } + + public DeleteQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table) { + super(null, new ArrayList<>(), QueryPriority.GENERAL); + this.table = table; + this.connection = connection; + } + + public DeleteQuery from(String table) { + this.table = table; + return this; + } + + public DeleteQuery limit(int limit) { + then(new LimitStatement<>(this, new ArrayList<>(), limit)); + return this; + } + + @Override + public QueryDetails buildQueryDetails() { + Objects.requireNonNull(table, "Table cannot be null!"); + + return new QueryDetails.Builder("DELETE FROM " + table) + .build() + .append(buildInnerQuery()); + } + + @Override + public DeleteQuery then(String part) { + return (DeleteQuery) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/InsertQuery.java b/core/src/main/java/me/zort/sqllib/internal/query/InsertQuery.java index 282ad10..c9a3d08 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/InsertQuery.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/InsertQuery.java @@ -13,110 +13,110 @@ public class InsertQuery extends QueryNode> implements Executive, Conditional { - @Getter - private String table; - private String[] defs; - private String[] values; - private int currPhIndex = 0; - - @Getter - private final SQLDatabaseConnection connection; - - public InsertQuery() { - this(null); - } - - public InsertQuery(@Nullable SQLDatabaseConnection connection) { - this(connection, null); - } - - public InsertQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table) { - super(null, new ArrayList<>(), QueryPriority.GENERAL); - this.table = table; - this.connection = connection; - this.defs = new String[0]; - this.values = new String[0]; - } - - public InsertQuery into(String table, String... defs) { - this.defs = defs; - return table(table); + @Getter + private String table; + private String[] defs; + private String[] values; + private int currPhIndex = 0; + + @Getter + private final SQLDatabaseConnection connection; + + public InsertQuery() { + this(null); + } + + public InsertQuery(@Nullable SQLDatabaseConnection connection) { + this(connection, null); + } + + public InsertQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table) { + super(null, new ArrayList<>(), QueryPriority.GENERAL); + this.table = table; + this.connection = connection; + this.defs = new String[0]; + this.values = new String[0]; + } + + public InsertQuery into(String table, String... defs) { + this.defs = defs; + return table(table); + } + + public InsertQuery table(String table) { + this.table = table; + return this; + } + + // Used internally + public InsertQuery appendVal(Object val) { + String[] newValues = new String[values.length + 1]; + System.arraycopy(values, 0, newValues, 0, values.length); + newValues[values.length] = handleVal(val); + this.values = newValues; + return this; + } + + public InsertQuery values(Object... values) { + String[] vals = new String[values.length]; + for (int i = 0; i < values.length; i++) { + Object obj = values[i]; + vals[i] = handleVal(obj); } + this.values = vals; + return this; + } - public InsertQuery table(String table) { - this.table = table; - return this; + private String handleVal(Object obj) { + if (obj instanceof String) { + obj = Encoding.handleTo((String) obj); } - - // Used internally - public InsertQuery appendVal(Object val) { - String[] newValues = new String[values.length + 1]; - System.arraycopy(values, 0, newValues, 0, values.length); - newValues[values.length] = handleVal(val); - this.values = newValues; - return this; - } - - public InsertQuery values(Object... values) { - String[] vals = new String[values.length]; - for(int i = 0; i < values.length; i++) { - Object obj = values[i]; - vals[i] = handleVal(obj); - } - this.values = vals; - return this; - } - - private String handleVal(Object obj) { - if(obj instanceof String) { - obj = Encoding.handleTo((String) obj); - } - return Util.buildQuoted(obj); + return Util.buildQuoted(obj); + } + + @Override + public QueryDetails buildQueryDetails() { + Objects.requireNonNull(table, "Table cannot be null!"); + if (defs.length != values.length) { + throw new IllegalStatementOperationException("Definition count must be same as values count!"); } - @Override - public QueryDetails buildQueryDetails() { - Objects.requireNonNull(table, "Table cannot be null!"); - if(defs.length != values.length) { - throw new IllegalStatementOperationException("Definition count must be same as values count!"); - } + QueryDetails details = new QueryDetails.Builder(String.format("INSERT INTO %s ", table)).build(); - QueryDetails details = new QueryDetails.Builder(String.format("INSERT INTO %s ", table)).build(); + insertArray(details, defs, false); + details.append(" VALUES "); + insertArray(details, values, true); - insertArray(details, defs, false); - details.append(" VALUES "); - insertArray(details, values, true); + details.append(buildInnerQuery()); - details.append(buildInnerQuery()); + return details; + } - return details; - } + private void insertArray(QueryDetails details, String[] array, boolean usePlaceholders) { + details.append("("); + for (String obj : array) { + String placeholder = nextPlaceholder(); + if (!details.getQueryStr().endsWith("(")) + details.append(", "); - private void insertArray(QueryDetails details, String[] array, boolean usePlaceholders) { - details.append("("); - for (String obj : array) { - String placeholder = nextPlaceholder(); - if (!details.getQueryStr().endsWith("(")) - details.append(", "); - - if (usePlaceholders) { - details.append(new QueryDetails.Builder("<" + placeholder + ">") - .placeholder(placeholder, obj) - .build()); - } else { - details.append(obj); - } - } - details.append(")"); + if (usePlaceholders) { + details.append(new QueryDetails.Builder("<" + placeholder + ">") + .placeholder(placeholder, obj) + .build()); + } else { + details.append(obj); + } } + details.append(")"); + } - private String nextPlaceholder() { - return "insert_" + currPhIndex++; - } + private String nextPlaceholder() { + return "insert_" + currPhIndex++; + } - @Override - public InsertQuery then(String part) { - return (InsertQuery) super.then(part); - } + @Override + public InsertQuery then(String part) { + return (InsertQuery) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/Limitable.java b/core/src/main/java/me/zort/sqllib/internal/query/Limitable.java index bfea311..6f0513e 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/Limitable.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/Limitable.java @@ -2,6 +2,6 @@ public interface Limitable

& Limitable

> { // P = self - P limit(int limit); + P limit(int limit); } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/QueryDetails.java b/core/src/main/java/me/zort/sqllib/internal/query/QueryDetails.java index e2c403d..aa8dbbf 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/QueryDetails.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/QueryDetails.java @@ -19,141 +19,142 @@ @Getter public class QueryDetails { - public static QueryDetails empty() { - return new QueryDetails(); + public static QueryDetails empty() { + return new QueryDetails(); + } + + @Setter(AccessLevel.PROTECTED) + private String queryStr; + private final Map values; + + public QueryDetails() { // Equiv to empty() + this("", new HashMap<>()); + } + + public QueryDetails append(QueryDetails other) { + return append("", other); + } + + public QueryDetails append(String prefix, QueryDetails other) { + Objects.requireNonNull(other, "QueryDetails cannot be null!"); + + append(prefix + other.queryStr); + other.values.forEach(values::putIfAbsent); + return this; + } + + public QueryDetails append(String s) { + queryStr += s; + return this; + } + + // Creates prepared statement for execution in SQlDatabaseConnectionImpl class. + protected PreparedStatement prepare(Connection connection) throws SQLException { + Pair requirements = buildStatementDetails(); + + // Shows plain query for prepared statement. + SQLConnectionRegistry.debug(connection, String.format("P-Query: %s", requirements.getFirst())); + SQLConnectionRegistry.debug(connection, String.format("P-Values: %s", Arrays.toString(requirements.getSecond()))); + + PreparedStatement statement = connection.prepareStatement(requirements.getFirst()); + Object[] values = requirements.getSecond(); + for (int i = 0; i < values.length; i++) { + set(statement, i + 1, values[i]); } + return statement; + } - @Setter(AccessLevel.PROTECTED) - private String queryStr; - private final Map values; + protected Pair buildStatementDetails() { + String query = queryStr; + Map valuesUnsorted = new HashMap<>(); - public QueryDetails() { // Equiv to empty() - this("", new HashMap<>()); - } + int i = 0; + String queryCloned = query; + for (String placeholder : this.values.keySet()) { + Object value = this.values.get(placeholder); - public QueryDetails append(QueryDetails other) { - return append("", other); - } + placeholder = String.format("<%s>", placeholder); - public QueryDetails append(String prefix, QueryDetails other) { - Objects.requireNonNull(other, "QueryDetails cannot be null!"); + if (Util.count(queryStr, placeholder) != 1) + throw new RuntimeException("Placeholder " + placeholder + " is not unique in query " + queryStr); - append(prefix + other.queryStr); - other.values.forEach(values::putIfAbsent); - return this; - } + valuesUnsorted.put(queryCloned.indexOf(placeholder), value); + query = query.replaceAll(placeholder, "?"); - public QueryDetails append(String s) { - queryStr += s; - return this; + i++; } - // Creates prepared statement for execution in SQlDatabaseConnectionImpl class. - protected PreparedStatement prepare(Connection connection) throws SQLException { - Pair requirements = buildStatementDetails(); - - // Shows plain query for prepared statement. - SQLConnectionRegistry.debug(connection, String.format("P-Query: %s", requirements.getFirst())); - SQLConnectionRegistry.debug(connection, String.format("P-Values: %s", Arrays.toString(requirements.getSecond()))); - - PreparedStatement statement = connection.prepareStatement(requirements.getFirst()); - Object[] values = requirements.getSecond(); - for (int i = 0; i < values.length; i++) { - set(statement, i + 1, values[i]); - } - return statement; + Object[] values = new Object[valuesUnsorted.size()]; + valuesUnsorted.keySet() + .stream() + .mapToInt(Integer::intValue) + .sorted().forEach(new IntConsumer() { + private int index = 0; + + @Override + public void accept(int value) { + values[index] = valuesUnsorted.get(value); + index++; + } + }); + + return new Pair<>(query, values); + } + + private static void set(PreparedStatement statement, int index, Object value) throws SQLException { + String type = value != null ? value.getClass().getSimpleName().toLowerCase() : "null"; + switch (type) { + case "string": + statement.setString(index, (String) value); + break; + case "integer": + case "int": + statement.setInt(index, (int) value); + break; + case "long": + statement.setLong(index, (long) value); + break; + case "double": + statement.setDouble(index, (double) value); + break; + case "float": + statement.setFloat(index, (float) value); + break; + case "boolean": + statement.setBoolean(index, (boolean) value); + break; + default: + statement.setObject(index, value); } + } - protected Pair buildStatementDetails() { - String query = queryStr; - Map valuesUnsorted = new HashMap<>(); + public int length() { + return queryStr.length(); + } - int i = 0; - String queryCloned = query; - for (String placeholder : this.values.keySet()) { - Object value = this.values.get(placeholder); + public String toString() { + return "QueryDetails{str=" + queryStr + ", values=" + new Gson().toJson(values) + "}"; + } - placeholder = String.format("<%s>", placeholder); + @RequiredArgsConstructor + public static class Builder { - if (Util.count(queryStr, placeholder) != 1) - throw new RuntimeException("Placeholder " + placeholder + " is not unique in query " + queryStr); + private final String query; + private final Map values = new HashMap<>(); - valuesUnsorted.put(queryCloned.indexOf(placeholder), value); - query = query.replaceAll(placeholder, "?"); - - i++; - } - - Object[] values = new Object[valuesUnsorted.size()]; - valuesUnsorted.keySet() - .stream() - .mapToInt(Integer::intValue) - .sorted().forEach(new IntConsumer() { - private int index = 0; - @Override - public void accept(int value) { - values[index] = valuesUnsorted.get(value); - index++; - } - }); - - return new Pair<>(query, values); - } + // Name without brackets + public Builder placeholder(String name, Object value) { + if (!query.contains("<" + name + ">")) + throw new IllegalArgumentException("Placeholder <" + name + "> not found in query!"); - private static void set(PreparedStatement statement, int index, Object value) throws SQLException { - String type = value != null ? value.getClass().getSimpleName().toLowerCase() : "null"; - switch(type) { - case "string": - statement.setString(index, (String) value); - break; - case "integer": - case "int": - statement.setInt(index, (int) value); - break; - case "long": - statement.setLong(index, (long) value); - break; - case "double": - statement.setDouble(index, (double) value); - break; - case "float": - statement.setFloat(index, (float) value); - break; - case "boolean": - statement.setBoolean(index, (boolean) value); - break; - default: - statement.setObject(index, value); - } + values.put(name, value); + return this; } - public int length() { - return queryStr.length(); + public QueryDetails build() { + return new QueryDetails(query, values); } - public String toString() { - return "QueryDetails{str=" + queryStr + ", values=" + new Gson().toJson(values) + "}"; - } - - @RequiredArgsConstructor - public static class Builder { - - private final String query; - private final Map values = new HashMap<>(); - - // Name without brackets - public Builder placeholder(String name, Object value) { - if(!query.contains("<" + name + ">")) - throw new IllegalArgumentException("Placeholder <" + name + "> not found in query!"); - - values.put(name, value); - return this; - } - - public QueryDetails build() { - return new QueryDetails(query, values); - } - - } + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/QueryNode.java b/core/src/main/java/me/zort/sqllib/internal/query/QueryNode.java index 1a5cfda..0aa14fa 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/QueryNode.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/QueryNode.java @@ -28,185 +28,185 @@ @Getter public abstract class QueryNode

> implements Query, StatementFactory { - @Getter(onMethod_ = {@Nullable}) - private final transient P parent; - private final List> children; - private final Map details; - private final int priority; - - public QueryNode(@Nullable P parent, List> initial, QueryPriority priority) { - this(parent, initial, priority.getPrior()); - } - - public QueryNode(@Nullable P parent, List> initial, int priority) { - this.parent = parent; - this.children = initial; - this.priority = priority; - this.details = new ConcurrentHashMap<>(); - } - - /** - * Builds the query string with placeholders containing values - * for passing into PreparedStatement. - *

- * Query example: SELECT * FROM table WHERE id = <id>; - * Values example: [AnyId] - * - * @return QueryDetails object. - */ - public abstract QueryDetails buildQueryDetails(); - - @Override - public PreparedStatement prepare(Connection connection) throws SQLException { - return details.remove(buildQuery()).prepare(connection); - } - - @Override - public String buildQuery() { - QueryDetails queryDetails = buildQueryDetails(); - - if (isAncestor()) - debug(String.format("Query: %s", queryDetails.getQueryStr())); - - String uuid = UUID.randomUUID().toString(); - details.put(uuid, queryDetails); - return uuid; - } - - public QueryDetails buildInnerQuery() { - List> children = new ArrayList<>(this.children); - children.sort(Comparator.comparingInt(QueryNode::getPriority)); - - QueryDetails details = new QueryDetails("", new HashMap<>()); - - if (children.isEmpty()) { - return QueryDetails.empty(); - } - - for (QueryNode inner : children) { - if (details.length() > 0) - details.append(" "); - - QueryDetails innerDetails = inner.getDetails().get(inner.buildQuery()); - details.append(innerDetails); - } - - return details; - } - - @Nullable - protected T invokeToConnection(Function func) - throws NoLinkedConnectionException, InvalidConnectionInstanceException { - QueryNode current = this; - while(current.getParent() != null && !(current instanceof Executive)) { - current = current.getParent(); - } - T result; - if(current instanceof Executive) { - SQLConnection connection = ((Executive) current).getConnection(); - if(!(connection instanceof SQLDatabaseConnection)) { - throw new InvalidConnectionInstanceException(connection); - } - - result = func.apply((SQLDatabaseConnection) connection); - } else { - throw new NoLinkedConnectionException(this); - } - return result; - } - - public QueryNode then(String part) { - int maxPriority = children.stream() - .map(QueryNode::getPriority) - .max(Comparator.naturalOrder()) - .orElse(0); - - then(new QueryNode>(parent, Collections.emptyList(), maxPriority + 1) { - @Override - public QueryDetails buildQueryDetails() { - return new QueryDetails(part, new HashMap<>()); - } - }); - return this; - } - - public > QueryNode then(QueryNode part) { - this.children.add(part); - return part; - } - - public P also() { - return parent; - } - - public QueryResult execute() { - return invokeToConnection(connection -> connection.exec(getAncestor())); - } - - public Optional obtainOne() { - QueryRowsResult resultList = obtainAll(); - - return resultList.isEmpty() - ? Optional.empty() - : Optional.ofNullable(resultList.get(0)); - } - - public Optional obtainOne(Class mapTo) { - QueryRowsResult resultList = obtainAll(mapTo); - - return resultList.isEmpty() - ? Optional.empty() - : Optional.ofNullable(resultList.get(0)); - } - - public QueryRowsResult obtainAll() { - requireResultSetAware(); - return invokeToConnection(connection -> connection.query(getAncestor())); - } - - public QueryRowsResult obtainAll(Class mapTo) { - requireResultSetAware(); - return invokeToConnection(connection -> connection.query(getAncestor(), mapTo)); - } - - private void requireResultSetAware() { - if (!generatesResultSet()) { - throw new IllegalStateException("This query node is not ResultSetAware! (Did you mean execute()?)"); - } - } - - public QueryNode getAncestor() { - QueryNode current = this; - while(current.getParent() != null) { - current = current.getParent(); - } - return current; - } - - public boolean generatesResultSet() { - return this instanceof ResultSetAware; - } - - private void debug(String message) { - if (getAncestor() instanceof Executive - && ((Executive) getAncestor()).getConnection() instanceof SQLDatabaseConnectionImpl) { - ((SQLDatabaseConnectionImpl) ((Executive) getAncestor()).getConnection()).debug(message); - } - } - - public String toString() { - return "QueryNode{details=" + buildQueryDetails().toString() + "}"; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof QueryNode)) return false; - QueryNode other = (QueryNode) obj; - return toString().equals(other.toString()); - } - - @Override - public int hashCode() { - return toString().hashCode(); - } + @Getter(onMethod_ = {@Nullable}) + private final transient P parent; + private final List> children; + private final Map details; + private final int priority; + + public QueryNode(@Nullable P parent, List> initial, QueryPriority priority) { + this(parent, initial, priority.getPrior()); + } + + public QueryNode(@Nullable P parent, List> initial, int priority) { + this.parent = parent; + this.children = initial; + this.priority = priority; + this.details = new ConcurrentHashMap<>(); + } + + /** + * Builds the query string with placeholders containing values + * for passing into PreparedStatement. + *

+ * Query example: SELECT * FROM table WHERE id = <id>; + * Values example: [AnyId] + * + * @return QueryDetails object. + */ + public abstract QueryDetails buildQueryDetails(); + + @Override + public PreparedStatement prepare(Connection connection) throws SQLException { + return details.remove(buildQuery()).prepare(connection); + } + + @Override + public String buildQuery() { + QueryDetails queryDetails = buildQueryDetails(); + + if (isAncestor()) + debug(String.format("Query: %s", queryDetails.getQueryStr())); + + String uuid = UUID.randomUUID().toString(); + details.put(uuid, queryDetails); + return uuid; + } + + public QueryDetails buildInnerQuery() { + List> children = new ArrayList<>(this.children); + children.sort(Comparator.comparingInt(QueryNode::getPriority)); + + QueryDetails details = new QueryDetails("", new HashMap<>()); + + if (children.isEmpty()) { + return QueryDetails.empty(); + } + + for (QueryNode inner : children) { + if (details.length() > 0) + details.append(" "); + + QueryDetails innerDetails = inner.getDetails().get(inner.buildQuery()); + details.append(innerDetails); + } + + return details; + } + + @Nullable + protected T invokeToConnection(Function func) + throws NoLinkedConnectionException, InvalidConnectionInstanceException { + QueryNode current = this; + while (current.getParent() != null && !(current instanceof Executive)) { + current = current.getParent(); + } + T result; + if (current instanceof Executive) { + SQLConnection connection = ((Executive) current).getConnection(); + if (!(connection instanceof SQLDatabaseConnection)) { + throw new InvalidConnectionInstanceException(connection); + } + + result = func.apply((SQLDatabaseConnection) connection); + } else { + throw new NoLinkedConnectionException(this); + } + return result; + } + + public QueryNode then(String part) { + int maxPriority = children.stream() + .map(QueryNode::getPriority) + .max(Comparator.naturalOrder()) + .orElse(0); + + then(new QueryNode>(parent, Collections.emptyList(), maxPriority + 1) { + @Override + public QueryDetails buildQueryDetails() { + return new QueryDetails(part, new HashMap<>()); + } + }); + return this; + } + + public > QueryNode then(QueryNode part) { + this.children.add(part); + return part; + } + + public P also() { + return parent; + } + + public QueryResult execute() { + return invokeToConnection(connection -> connection.exec(getAncestor())); + } + + public Optional obtainOne() { + QueryRowsResult resultList = obtainAll(); + + return resultList.isEmpty() + ? Optional.empty() + : Optional.ofNullable(resultList.get(0)); + } + + public Optional obtainOne(Class mapTo) { + QueryRowsResult resultList = obtainAll(mapTo); + + return resultList.isEmpty() + ? Optional.empty() + : Optional.ofNullable(resultList.get(0)); + } + + public QueryRowsResult obtainAll() { + requireResultSetAware(); + return invokeToConnection(connection -> connection.query(getAncestor())); + } + + public QueryRowsResult obtainAll(Class mapTo) { + requireResultSetAware(); + return invokeToConnection(connection -> connection.query(getAncestor(), mapTo)); + } + + private void requireResultSetAware() { + if (!generatesResultSet()) { + throw new IllegalStateException("This query node is not ResultSetAware! (Did you mean execute()?)"); + } + } + + public QueryNode getAncestor() { + QueryNode current = this; + while (current.getParent() != null) { + current = current.getParent(); + } + return current; + } + + public boolean generatesResultSet() { + return this instanceof ResultSetAware; + } + + private void debug(String message) { + if (getAncestor() instanceof Executive + && ((Executive) getAncestor()).getConnection() instanceof SQLDatabaseConnectionImpl) { + ((SQLDatabaseConnectionImpl) ((Executive) getAncestor()).getConnection()).debug(message); + } + } + + public String toString() { + return "QueryNode{details=" + buildQueryDetails().toString() + "}"; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof QueryNode)) return false; + QueryNode other = (QueryNode) obj; + return toString().equals(other.toString()); + } + + @Override + public int hashCode() { + return toString().hashCode(); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/QueryPriority.java b/core/src/main/java/me/zort/sqllib/internal/query/QueryPriority.java index e985513..a16a502 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/QueryPriority.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/QueryPriority.java @@ -7,23 +7,23 @@ public enum QueryPriority { - GENERAL(0), - CONDITION(1), - OTHER(2), - LAST(3); - - @Getter - private final int prior; - - QueryPriority(int prior) { - this.prior = prior; - } - - public boolean isAncestor() { - return prior == Arrays.stream(QueryPriority.values()) - .min(Comparator.comparingInt(QueryPriority::getPrior)) - .orElse(QueryPriority.GENERAL) - .getPrior(); - } + GENERAL(0), + CONDITION(1), + OTHER(2), + LAST(3); + + @Getter + private final int prior; + + QueryPriority(int prior) { + this.prior = prior; + } + + public boolean isAncestor() { + return prior == Arrays.stream(QueryPriority.values()) + .min(Comparator.comparingInt(QueryPriority::getPrior)) + .orElse(QueryPriority.GENERAL) + .getPrior(); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/ResultSetAware.java b/core/src/main/java/me/zort/sqllib/internal/query/ResultSetAware.java index 844633f..a85ea1c 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/ResultSetAware.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/ResultSetAware.java @@ -18,9 +18,12 @@ */ public interface ResultSetAware extends Query { - Optional obtainOne(); - Optional obtainOne(Class mapTo); - QueryRowsResult obtainAll(); - QueryRowsResult obtainAll(Class mapTo); + Optional obtainOne(); + + Optional obtainOne(Class mapTo); + + QueryRowsResult obtainAll(); + + QueryRowsResult obtainAll(Class mapTo); } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/SelectQuery.java b/core/src/main/java/me/zort/sqllib/internal/query/SelectQuery.java index 0136518..4ec5660 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/SelectQuery.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/SelectQuery.java @@ -13,51 +13,51 @@ public class SelectQuery extends QueryNode> implements Executive, Conditional, Limitable, ResultSetAware { - private final List cols; - private String table; - - @Getter - private final SQLDatabaseConnection connection; - - public SelectQuery() { - this(null); - } - - public SelectQuery(@Nullable SQLDatabaseConnection connection, String... cols) { - this(connection, null, Arrays.asList(cols)); - } - - public SelectQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table, List cols) { - super(null, new ArrayList<>(), QueryPriority.GENERAL); - this.table = table; - this.cols = cols; - this.connection = connection; - } - - public SelectQuery from(String table) { - this.table = table; - return this; - } - - public SelectQuery limit(int limit) { - then(new LimitStatement<>(this, new ArrayList<>(), limit)); - return this; - } - - @Override - public QueryDetails buildQueryDetails() { - Objects.requireNonNull(table, "Table cannot be null!"); - - QueryDetails details = new QueryDetails.Builder(String.format("SELECT %s FROM %s", - this.cols.isEmpty() ? "*" : String.join(", ", this.cols), - table)) - .build(); - - return details.append(buildInnerQuery()); - } - - @Override - public SelectQuery then(String part) { - return (SelectQuery) super.then(part); - } + private final List cols; + private String table; + + @Getter + private final SQLDatabaseConnection connection; + + public SelectQuery() { + this(null); + } + + public SelectQuery(@Nullable SQLDatabaseConnection connection, String... cols) { + this(connection, null, Arrays.asList(cols)); + } + + public SelectQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table, List cols) { + super(null, new ArrayList<>(), QueryPriority.GENERAL); + this.table = table; + this.cols = cols; + this.connection = connection; + } + + public SelectQuery from(String table) { + this.table = table; + return this; + } + + public SelectQuery limit(int limit) { + then(new LimitStatement<>(this, new ArrayList<>(), limit)); + return this; + } + + @Override + public QueryDetails buildQueryDetails() { + Objects.requireNonNull(table, "Table cannot be null!"); + + QueryDetails details = new QueryDetails.Builder(String.format("SELECT %s FROM %s", + this.cols.isEmpty() ? "*" : String.join(", ", this.cols), + table)) + .build(); + + return details.append(buildInnerQuery()); + } + + @Override + public SelectQuery then(String part) { + return (SelectQuery) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/UpdateQuery.java b/core/src/main/java/me/zort/sqllib/internal/query/UpdateQuery.java index 00103f9..0856bc8 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/UpdateQuery.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/UpdateQuery.java @@ -12,57 +12,57 @@ public class UpdateQuery extends QueryNode> implements Executive, Conditional { - private String table; - - @Getter - private final SQLDatabaseConnection connection; - - public UpdateQuery() { - this(null); - } - - public UpdateQuery(@Nullable SQLDatabaseConnection connection) { - this(connection, null); - } - - public UpdateQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table) { - super(null, new ArrayList<>(), QueryPriority.GENERAL.getPrior()); - this.table = table; - this.connection = connection; - } - - public UpdateQuery table(String table) { - this.table = table; - return this; - } - - public SetStatement set(String column, Object value) { - SetStatement stmt = set(); - stmt.and(column, value); - return stmt; - } - - public SetStatement set() { - SetStatement stmt = new SetStatement<>(this); - then(stmt); - return stmt; - } - - @Override - public WhereStatement where() { - return Conditional.super.where(2); - } - - @Override - public QueryDetails buildQueryDetails() { - Objects.requireNonNull(table, "Table cannot be null!"); - - return new QueryDetails.Builder("UPDATE " + table).build().append(buildInnerQuery()); - } - - @Override - public UpdateQuery then(String part) { - return (UpdateQuery) super.then(part); - } + private String table; + + @Getter + private final SQLDatabaseConnection connection; + + public UpdateQuery() { + this(null); + } + + public UpdateQuery(@Nullable SQLDatabaseConnection connection) { + this(connection, null); + } + + public UpdateQuery(@Nullable SQLDatabaseConnection connection, @Nullable String table) { + super(null, new ArrayList<>(), QueryPriority.GENERAL.getPrior()); + this.table = table; + this.connection = connection; + } + + public UpdateQuery table(String table) { + this.table = table; + return this; + } + + public SetStatement set(String column, Object value) { + SetStatement stmt = set(); + stmt.and(column, value); + return stmt; + } + + public SetStatement set() { + SetStatement stmt = new SetStatement<>(this); + then(stmt); + return stmt; + } + + @Override + public WhereStatement where() { + return Conditional.super.where(2); + } + + @Override + public QueryDetails buildQueryDetails() { + Objects.requireNonNull(table, "Table cannot be null!"); + + return new QueryDetails.Builder("UPDATE " + table).build().append(buildInnerQuery()); + } + + @Override + public UpdateQuery then(String part) { + return (UpdateQuery) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/UpsertQuery.java b/core/src/main/java/me/zort/sqllib/internal/query/UpsertQuery.java index cdb5ecd..e096eff 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/UpsertQuery.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/UpsertQuery.java @@ -10,59 +10,59 @@ public class UpsertQuery extends InsertQuery { - @Setter - @Getter - private Object assignedSaveObject = null; // Can be null, only relevant in SQLite mode. + @Setter + @Getter + private Object assignedSaveObject = null; // Can be null, only relevant in SQLite mode. - public UpsertQuery(SQLDatabaseConnection connection) { - super(connection); - } + public UpsertQuery(SQLDatabaseConnection connection) { + super(connection); + } - public UpsertQuery(SQLDatabaseConnection connection, @Nullable String table) { - super(connection, table); - } + public UpsertQuery(SQLDatabaseConnection connection, @Nullable String table) { + super(connection, table); + } - @Override - public UpsertQuery into(String table, String... defs) { - return (UpsertQuery) super.into(table, defs); - } + @Override + public UpsertQuery into(String table, String... defs) { + return (UpsertQuery) super.into(table, defs); + } - @Override - public UpsertQuery table(String table) { - return (UpsertQuery) super.table(table); - } + @Override + public UpsertQuery table(String table) { + return (UpsertQuery) super.table(table); + } - @Override - public UpsertQuery values(Object... values) { - return (UpsertQuery) super.values(values); - } + @Override + public UpsertQuery values(Object... values) { + return (UpsertQuery) super.values(values); + } - public SetStatement onDuplicateKey(String column, Object value) { - SetStatement stmt = onDuplicateKey(); - stmt.and(column, value); - return stmt; - } + public SetStatement onDuplicateKey(String column, Object value) { + SetStatement stmt = onDuplicateKey(); + stmt.and(column, value); + return stmt; + } - public SetStatement onDuplicateKey() { - SetStatement stmt = new SetStatement(this, 3) { - @Override - public QueryDetails buildQueryDetails() { - QueryDetails details = new QueryDetails(" ON DUPLICATE KEY UPDATE", new HashMap<>()); + public SetStatement onDuplicateKey() { + SetStatement stmt = new SetStatement(this, 3) { + @Override + public QueryDetails buildQueryDetails() { + QueryDetails details = new QueryDetails(" ON DUPLICATE KEY UPDATE", new HashMap<>()); - QueryDetails superDetails = super.buildQueryDetails(); - superDetails.setQueryStr(superDetails.getQueryStr().replaceAll("SET ", "")); - details.append(superDetails); + QueryDetails superDetails = super.buildQueryDetails(); + superDetails.setQueryStr(superDetails.getQueryStr().replaceAll("SET ", "")); + details.append(superDetails); - return details; - } - }; - then(stmt); - return stmt; - } + return details; + } + }; + then(stmt); + return stmt; + } - @Override - public UpsertQuery then(String part) { - return (UpsertQuery) super.then(part); - } + @Override + public UpsertQuery then(String part) { + return (UpsertQuery) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/part/LimitStatement.java b/core/src/main/java/me/zort/sqllib/internal/query/part/LimitStatement.java index 08b07c5..70bfe0a 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/part/LimitStatement.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/part/LimitStatement.java @@ -10,21 +10,21 @@ public class LimitStatement

> extends QueryNode

implements ResultSetAware { - private final int limit; + private final int limit; - public LimitStatement(@Nullable P parent, List> initial, int limit) { - super(parent, initial, Integer.MAX_VALUE); - this.limit = limit; - } + public LimitStatement(@Nullable P parent, List> initial, int limit) { + super(parent, initial, Integer.MAX_VALUE); + this.limit = limit; + } - @Override - public QueryDetails buildQueryDetails() { - return new QueryDetails(" LIMIT " + Math.max(limit, 0), new HashMap<>()); - } + @Override + public QueryDetails buildQueryDetails() { + return new QueryDetails(" LIMIT " + Math.max(limit, 0), new HashMap<>()); + } - @SuppressWarnings("unchecked") - @Override - public LimitStatement

then(String part) { - return (LimitStatement

) super.then(part); - } + @SuppressWarnings("unchecked") + @Override + public LimitStatement

then(String part) { + return (LimitStatement

) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/part/SetStatement.java b/core/src/main/java/me/zort/sqllib/internal/query/part/SetStatement.java index d5a2504..20763ee 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/part/SetStatement.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/part/SetStatement.java @@ -13,73 +13,73 @@ public class SetStatement

& Conditional

> extends QueryNode

implements Conditional

{ - private final Pairs update; - private int currPhIndex = 0; + private final Pairs update; + private int currPhIndex = 0; - public SetStatement(@Nullable P parent) { - this(parent, 1); - } + public SetStatement(@Nullable P parent) { + this(parent, 1); + } - public SetStatement(@Nullable P parent, int priority) { - super(parent, Collections.emptyList(), priority); - this.update = new Pairs<>(); - } + public SetStatement(@Nullable P parent, int priority) { + super(parent, Collections.emptyList(), priority); + this.update = new Pairs<>(); + } - public SetStatement

and(String column, Object value) { - return and(new Pair<>(column, value)); - } + public SetStatement

and(String column, Object value) { + return and(new Pair<>(column, value)); + } - public SetStatement

and(Pair pair) { - this.update.add(pair); - return this; - } + public SetStatement

and(Pair pair) { + this.update.add(pair); + return this; + } - public SetStatement

and(Pairs pairs) { - this.update.addAll(pairs); - return this; - } + public SetStatement

and(Pairs pairs) { + this.update.addAll(pairs); + return this; + } - @Override - public WhereStatement

where(int priority) { - if(getParent() == null) { - throw new IllegalStatementOperationException("Statement does not have parent set!"); - } - return getParent().where(priority); + @Override + public WhereStatement

where(int priority) { + if (getParent() == null) { + throw new IllegalStatementOperationException("Statement does not have parent set!"); } + return getParent().where(priority); + } - @Override - public QueryDetails buildQueryDetails() { - if(update.isEmpty()) { - return QueryDetails.empty(); - } - - QueryDetails details = new QueryDetails(" SET ", new HashMap<>()); + @Override + public QueryDetails buildQueryDetails() { + if (update.isEmpty()) { + return QueryDetails.empty(); + } - for (Pair pair : update) { - String name = pair.getFirst(); - Object value = pair.getSecond(); + QueryDetails details = new QueryDetails(" SET ", new HashMap<>()); - String placeholder = nextPlaceholder(); + for (Pair pair : update) { + String name = pair.getFirst(); + Object value = pair.getSecond(); - if (!details.getQueryStr().equals(" SET ")) - details.append(", "); + String placeholder = nextPlaceholder(); - details.append(new QueryDetails.Builder(String.format("%s = <%s>", name, placeholder)) - .placeholder(placeholder, value) - .build()); - } + if (!details.getQueryStr().equals(" SET ")) + details.append(", "); - return details; + details.append(new QueryDetails.Builder(String.format("%s = <%s>", name, placeholder)) + .placeholder(placeholder, value) + .build()); } - private String nextPlaceholder() { - return "set_" + currPhIndex++; - } + return details; + } - @SuppressWarnings("unchecked") - @Override - public SetStatement

then(String part) { - return (SetStatement

) super.then(part); - } + private String nextPlaceholder() { + return "set_" + currPhIndex++; + } + + @SuppressWarnings("unchecked") + @Override + public SetStatement

then(String part) { + return (SetStatement

) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/internal/query/part/WhereStatement.java b/core/src/main/java/me/zort/sqllib/internal/query/part/WhereStatement.java index 0dd6811..4ba0215 100644 --- a/core/src/main/java/me/zort/sqllib/internal/query/part/WhereStatement.java +++ b/core/src/main/java/me/zort/sqllib/internal/query/part/WhereStatement.java @@ -8,117 +8,117 @@ public class WhereStatement

> extends QueryNode

implements ResultSetAware { - private final List conditions = new ArrayList<>(); - private int currPhIndex = 0; - - public WhereStatement(@Nullable P parent, List> initial) { - super(parent, initial, QueryPriority.CONDITION.getPrior()); - } - - public WhereStatement(@Nullable P parent, List> initial, int priority) { - super(parent, initial, priority); - } - - public WhereStatement

isEqual(String column, Object value) { - String placeholder = nextPlaceholder(); - conditions.add(new QueryDetails.Builder(String.format("%s = <%s>", column, placeholder)) - .placeholder(placeholder, value) - .build()); - return this; - } - - public WhereStatement

bt(String column, long value) { - String placeholder = nextPlaceholder(); - conditions.add(new QueryDetails.Builder(String.format("%s > <%s>", column, placeholder)) - .placeholder(placeholder, value) - .build()); - return this; - } - - public WhereStatement

lt(String column, long value) { - String placeholder = nextPlaceholder(); - conditions.add(new QueryDetails.Builder(String.format("%s < <%s>", column, placeholder)) - .placeholder(placeholder, value) - .build()); - return this; + private final List conditions = new ArrayList<>(); + private int currPhIndex = 0; + + public WhereStatement(@Nullable P parent, List> initial) { + super(parent, initial, QueryPriority.CONDITION.getPrior()); + } + + public WhereStatement(@Nullable P parent, List> initial, int priority) { + super(parent, initial, priority); + } + + public WhereStatement

isEqual(String column, Object value) { + String placeholder = nextPlaceholder(); + conditions.add(new QueryDetails.Builder(String.format("%s = <%s>", column, placeholder)) + .placeholder(placeholder, value) + .build()); + return this; + } + + public WhereStatement

bt(String column, long value) { + String placeholder = nextPlaceholder(); + conditions.add(new QueryDetails.Builder(String.format("%s > <%s>", column, placeholder)) + .placeholder(placeholder, value) + .build()); + return this; + } + + public WhereStatement

lt(String column, long value) { + String placeholder = nextPlaceholder(); + conditions.add(new QueryDetails.Builder(String.format("%s < <%s>", column, placeholder)) + .placeholder(placeholder, value) + .build()); + return this; + } + + public WhereStatement

in(String column, Object... objs) { + return in(column, Arrays.asList(objs)); + } + + public WhereStatement

in(String column, List objs) { + if (objs.isEmpty()) return this; + + QueryDetails details = new QueryDetails(column + " IN (", new HashMap<>()); + for (Object obj : objs) { + + if (!details.getQueryStr().endsWith("(")) + details.append(", "); + + String placeholder = nextPlaceholder(); + details.append(new QueryDetails.Builder(String.format("<%s>", placeholder)) + .placeholder(placeholder, obj) + .build()); } - - public WhereStatement

in(String column, Object... objs) { - return in(column, Arrays.asList(objs)); - } - - public WhereStatement

in(String column, List objs) { - if(objs.isEmpty()) return this; - - QueryDetails details = new QueryDetails(column + " IN (", new HashMap<>()); - for (Object obj : objs) { - - if (!details.getQueryStr().endsWith("(")) - details.append(", "); - - String placeholder = nextPlaceholder(); - details.append(new QueryDetails.Builder(String.format("<%s>", placeholder)) - .placeholder(placeholder, obj) - .build()); + details.append(")"); + + conditions.add(details); + + return this; + } + + public WhereStatement

like(String column, String paramPlaceholder) { + String placeholder = nextPlaceholder(); + conditions.add(new QueryDetails.Builder(String.format("%s LIKE <%s>", column, placeholder)) + .placeholder(placeholder, paramPlaceholder) + .build()); + return this; + } + + private String nextPlaceholder() { + return "where_" + currPhIndex++; + } + + @Override + public > QueryNode then(QueryNode part) { + throw new IllegalStatementOperationException("Where statement can't have inner parts!"); + } + + public WhereStatement

and() { + return this; + } + + public WhereStatement

or() { + conditions.add(new QueryDetails(" OR ", new HashMap<>())); + return this; + } + + @Override + public QueryDetails buildQueryDetails() { + QueryDetails details = new QueryDetails(" WHERE ", new HashMap<>()); + + if (conditions.isEmpty()) { + // We don't have any conditions, so where statement should be true. + details.append("TRUE"); + } else { + for (QueryDetails _details : conditions) { + String condition = _details.getQueryStr(); + + if (!details.getQueryStr().equals(" WHERE ") && !condition.equals(" OR ") && !details.getQueryStr().endsWith(" OR ")) { + details.append(" AND "); } - details.append(")"); - conditions.add(details); - - return this; + details.append(_details); + } } - public WhereStatement

like(String column, String paramPlaceholder) { - String placeholder = nextPlaceholder(); - conditions.add(new QueryDetails.Builder(String.format("%s LIKE <%s>", column, placeholder)) - .placeholder(placeholder, paramPlaceholder) - .build()); - return this; - } + return details; + } - private String nextPlaceholder() { - return "where_" + currPhIndex++; - } - - @Override - public > QueryNode then(QueryNode part) { - throw new IllegalStatementOperationException("Where statement can't have inner parts!"); - } - - public WhereStatement

and() { - return this; - } - - public WhereStatement

or() { - conditions.add(new QueryDetails(" OR ", new HashMap<>())); - return this; - } - - @Override - public QueryDetails buildQueryDetails() { - QueryDetails details = new QueryDetails(" WHERE ", new HashMap<>()); - - if(conditions.isEmpty()) { - // We don't have any conditions, so where statement should be true. - details.append("TRUE"); - } else { - for(QueryDetails _details : conditions) { - String condition = _details.getQueryStr(); - - if(!details.getQueryStr().equals(" WHERE ") && !condition.equals(" OR ") && !details.getQueryStr().endsWith(" OR ")) { - details.append(" AND "); - } - - details.append(_details); - } - } - - return details; - } - - @SuppressWarnings("unchecked") - @Override - public WhereStatement

then(String part) { - return (WhereStatement

) super.then(part); - } + @SuppressWarnings("unchecked") + @Override + public WhereStatement

then(String part) { + return (WhereStatement

) super.then(part); + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/DefaultResultAdapter.java b/core/src/main/java/me/zort/sqllib/mapping/DefaultResultAdapter.java index aaca8b6..f3907d0 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/DefaultResultAdapter.java +++ b/core/src/main/java/me/zort/sqllib/mapping/DefaultResultAdapter.java @@ -11,59 +11,59 @@ import java.util.Optional; public class DefaultResultAdapter implements StatementMappingResultAdapter { - @Override - public Object adaptResult(Method method, QueryResult result) { - Class returnType = method.getReturnType(); - if(returnType.equals(QueryResult.class)) { - return result; - } else if (isVoid(returnType) || !(result instanceof QueryRowsResult)) { - return noResult(returnType, result.isSuccessful()); - } - QueryRowsResult rows = (QueryRowsResult) result; - if (List.class.isAssignableFrom(returnType)) return rows; - Object obj = rows.isEmpty() ? null : rows.get(0); - if (Optional.class.isAssignableFrom(returnType)) return Optional.ofNullable(obj); - return obj; + @Override + public Object adaptResult(Method method, QueryResult result) { + Class returnType = method.getReturnType(); + if (returnType.equals(QueryResult.class)) { + return result; + } else if (isVoid(returnType) || !(result instanceof QueryRowsResult)) { + return noResult(returnType, result.isSuccessful()); } + QueryRowsResult rows = (QueryRowsResult) result; + if (List.class.isAssignableFrom(returnType)) return rows; + Object obj = rows.isEmpty() ? null : rows.get(0); + if (Optional.class.isAssignableFrom(returnType)) return Optional.ofNullable(obj); + return obj; + } - @Override - public Class retrieveResultType(Method method) { - Class returnType = method.getReturnType(); - if (returnType.equals(Optional.class) || returnType.equals(List.class)) { - return getGenericArgument(returnType, method.getGenericReturnType(), true); - } else if (isVoid(returnType)) { - return null; - } else { - return returnType; - } + @Override + public Class retrieveResultType(Method method) { + Class returnType = method.getReturnType(); + if (returnType.equals(Optional.class) || returnType.equals(List.class)) { + return getGenericArgument(returnType, method.getGenericReturnType(), true); + } else if (isVoid(returnType)) { + return null; + } else { + return returnType; } + } - private static Object noResult(Class returnType, boolean successful) { - if (Optional.class.isAssignableFrom(returnType)) return Optional.empty(); - if (List.class.isAssignableFrom(returnType)) return new QueryRowsResult(successful); - return null; - } - - // List - private static Class getGenericArgument(Class clazz, Type genericType, boolean throwNotFound) { - Type[] typeParameters = ((ParameterizedType) genericType).getActualTypeArguments(); - if (typeParameters.length < 1) { - if (throwNotFound) { - throw new IllegalArgumentException("The given class does not have a generic argument"); - } else { - return clazz; - } // For simplicity, return itself to be mapped. - } + private static Object noResult(Class returnType, boolean successful) { + if (Optional.class.isAssignableFrom(returnType)) return Optional.empty(); + if (List.class.isAssignableFrom(returnType)) return new QueryRowsResult(successful); + return null; + } - try { - return Class.forName(typeParameters[0].getTypeName()); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - return clazz; - } + // List + private static Class getGenericArgument(Class clazz, Type genericType, boolean throwNotFound) { + Type[] typeParameters = ((ParameterizedType) genericType).getActualTypeArguments(); + if (typeParameters.length < 1) { + if (throwNotFound) { + throw new IllegalArgumentException("The given class does not have a generic argument"); + } else { + return clazz; + } // For simplicity, return itself to be mapped. } - private static boolean isVoid(Class type) { - return type.equals(void.class) || type.equals(Void.class); + try { + return Class.forName(typeParameters[0].getTypeName()); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return clazz; } + } + + private static boolean isVoid(Class type) { + return type.equals(void.class) || type.equals(Void.class); + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMapping.java b/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMapping.java index b78f957..1759958 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMapping.java +++ b/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMapping.java @@ -26,74 +26,74 @@ */ public class DefaultStatementMapping implements StatementMappingStrategy { - private final SQLConnection connection; + private final SQLConnection connection; - public DefaultStatementMapping(SQLConnection connection) { - this.connection = connection; - } + public DefaultStatementMapping(SQLConnection connection) { + this.connection = connection; + } - @SuppressWarnings("unchecked") - @Override - public QueryResult executeQuery(StatementMappingOptions options, Method method, Object[] args, @Nullable Class mapTo) { - ParameterPair[] parameters = new ParameterPair[method.getParameters().length]; - int i = 0; - for (Parameter parameter : method.getParameters()) { - parameters[i] = new ParameterPair(parameter, args[i]); - i++; - } + @SuppressWarnings("unchecked") + @Override + public QueryResult executeQuery(StatementMappingOptions options, Method method, Object[] args, @Nullable Class mapTo) { + ParameterPair[] parameters = new ParameterPair[method.getParameters().length]; + int i = 0; + for (Parameter parameter : method.getParameters()) { + parameters[i] = new ParameterPair(parameter, args[i]); + i++; + } - Annotation queryAnnotation = filterQueryAnnotation(method, args); - QueryAnnotation wrappedAnnotation = QueryAnnotation.wrap(queryAnnotation); + Annotation queryAnnotation = filterQueryAnnotation(method, args); + QueryAnnotation wrappedAnnotation = QueryAnnotation.wrap(queryAnnotation); - if (wrappedAnnotation == null) { - throw new SQLMappingException("No query builder found for method " + method.getName() + "! Is query annotation present?", method, args); - } else if (!(connection instanceof SQLDatabaseConnection)) { - throw new SQLMappingException("Connection is not a SQLDatabaseConnection!", method, args); - } + if (wrappedAnnotation == null) { + throw new SQLMappingException("No query builder found for method " + method.getName() + "! Is query annotation present?", method, args); + } else if (!(connection instanceof SQLDatabaseConnection)) { + throw new SQLMappingException("Connection is not a SQLDatabaseConnection!", method, args); + } - QueryNode node = wrappedAnnotation.getQueryBuilder().build( - new QueryAnnotation.DefaultMappingDetails(connection, options), queryAnnotation, - method, parameters); - if (method.isAnnotationPresent(Append.class)) { - Append append = method.getAnnotation(Append.class); - node.then(new PlaceholderMapper(parameters).assignValues(append.value())); - } + QueryNode node = wrappedAnnotation.getQueryBuilder().build( + new QueryAnnotation.DefaultMappingDetails(connection, options), queryAnnotation, + method, parameters); + if (method.isAnnotationPresent(Append.class)) { + Append append = method.getAnnotation(Append.class); + node.then(new PlaceholderMapper(parameters).assignValues(append.value())); + } - if (mapTo != null && wrappedAnnotation.isProducesResult() && QueryRowsResult.class.isAssignableFrom(mapTo)) { - return ((SQLDatabaseConnection) connection).query(node); - } + if (mapTo != null && wrappedAnnotation.isProducesResult() && QueryRowsResult.class.isAssignableFrom(mapTo)) { + return ((SQLDatabaseConnection) connection).query(node); + } - if (wrappedAnnotation.isProducesResult() && node instanceof ResultSetAware) { - return mapTo != null - ? ((SQLDatabaseConnection) connection).query(node, mapTo) - : ((SQLDatabaseConnection) connection).query(node); - } else { - return ((SQLDatabaseConnection) connection).exec(node); - } + if (wrappedAnnotation.isProducesResult() && node instanceof ResultSetAware) { + return mapTo != null + ? ((SQLDatabaseConnection) connection).query(node, mapTo) + : ((SQLDatabaseConnection) connection).query(node); + } else { + return ((SQLDatabaseConnection) connection).exec(node); } + } - private static Annotation filterQueryAnnotation(Method method, Object[] args) { - Annotation queryAnnotation = null; - for (Annotation annotation : method.getAnnotations()) { - boolean isQueryAnnot = QueryAnnotation.isQueryAnnotation(annotation); - if (isQueryAnnot && queryAnnotation == null) { - queryAnnotation = annotation; - } else if (isQueryAnnot) { - String errMessage = String.format("Multiple query annotations (Select/Insert/...) found on method %s!", method.getName()); - throw new SQLMappingException(errMessage, method, args); - } - } - return queryAnnotation; + private static Annotation filterQueryAnnotation(Method method, Object[] args) { + Annotation queryAnnotation = null; + for (Annotation annotation : method.getAnnotations()) { + boolean isQueryAnnot = QueryAnnotation.isQueryAnnotation(annotation); + if (isQueryAnnot && queryAnnotation == null) { + queryAnnotation = annotation; + } else if (isQueryAnnot) { + String errMessage = String.format("Multiple query annotations (Select/Insert/...) found on method %s!", method.getName()); + throw new SQLMappingException(errMessage, method, args); + } } + return queryAnnotation; + } - @Override - public boolean isMappingMethod(Method method) { - for (Annotation annot : method.getAnnotations()) { - if (QueryAnnotation.isQueryAnnotation(annot)) { - return true; - } - } - return false; + @Override + public boolean isMappingMethod(Method method) { + for (Annotation annot : method.getAnnotations()) { + if (QueryAnnotation.isQueryAnnotation(annot)) { + return true; + } } + return false; + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMappingFactory.java b/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMappingFactory.java index c9571ed..014223b 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMappingFactory.java +++ b/core/src/main/java/me/zort/sqllib/mapping/DefaultStatementMappingFactory.java @@ -8,16 +8,17 @@ import java.lang.reflect.Modifier; public class DefaultStatementMappingFactory implements StatementMappingFactory { - private final DefaultResultAdapter resultAdapter = new DefaultResultAdapter(); - @Override - public StatementMappingStrategy strategy(Class interfaceClass, SQLConnection connection) { - if (!interfaceClass.isInterface() || !Modifier.isAbstract(interfaceClass.getModifiers())) - throw new IllegalArgumentException("The given class is not an interface or is not abstract"); - return new DefaultStatementMapping<>(connection); - } + private final DefaultResultAdapter resultAdapter = new DefaultResultAdapter(); - @Override - public StatementMappingResultAdapter resultAdapter() { - return resultAdapter; - } + @Override + public StatementMappingStrategy strategy(Class interfaceClass, SQLConnection connection) { + if (!interfaceClass.isInterface() || !Modifier.isAbstract(interfaceClass.getModifiers())) + throw new IllegalArgumentException("The given class is not an interface or is not abstract"); + return new DefaultStatementMapping<>(connection); + } + + @Override + public StatementMappingResultAdapter resultAdapter() { + return resultAdapter; + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/MappingRegistryImpl.java b/core/src/main/java/me/zort/sqllib/mapping/MappingRegistryImpl.java index 084e822..53562e8 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/MappingRegistryImpl.java +++ b/core/src/main/java/me/zort/sqllib/mapping/MappingRegistryImpl.java @@ -13,17 +13,17 @@ @RequiredArgsConstructor public class MappingRegistryImpl implements StatementMappingRegistry { - private final Map, MappingProxyInstance> proxyWrappers = new ConcurrentHashMap<>(); - private final SQLDatabaseConnectionImpl connection; + private final Map, MappingProxyInstance> proxyWrappers = new ConcurrentHashMap<>(); + private final SQLDatabaseConnectionImpl connection; - @Override - public void registerProxy(MappingProxyInstance proxyInstance) { - proxyWrappers.put(proxyInstance.getTypeClass(), proxyInstance); - } + @Override + public void registerProxy(MappingProxyInstance proxyInstance) { + proxyWrappers.put(proxyInstance.getTypeClass(), proxyInstance); + } - @Override - public List> getProxyInstances() { - return new ArrayList<>(proxyWrappers.values()); - } + @Override + public List> getProxyInstances() { + return new ArrayList<>(proxyWrappers.values()); + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/PlaceholderMapper.java b/core/src/main/java/me/zort/sqllib/mapping/PlaceholderMapper.java index 5e4d8cb..2247dee 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/PlaceholderMapper.java +++ b/core/src/main/java/me/zort/sqllib/mapping/PlaceholderMapper.java @@ -10,25 +10,25 @@ @RequiredArgsConstructor public class PlaceholderMapper { - private final ParameterPair[] parameters; - private final Pattern pattern = Pattern.compile("\\{[a-zA-Z0-9]+}"); - - public String assignValues(String input) { - Matcher matcher = pattern.matcher(input); - while(matcher.find()) { - String placeholder = matcher.group(); - String placeholderName = placeholder.substring(1, placeholder.length() - 1); - for (ParameterPair pair : parameters) { - if (!pair.getParameter().isAnnotationPresent(Placeholder.class)) - continue; - - if (placeholderName.equals(pair.getParameter().getAnnotation(Placeholder.class).value())) { - input = input.replace(placeholder, String.valueOf(pair.getValue())); - } - } + private final ParameterPair[] parameters; + private final Pattern pattern = Pattern.compile("\\{[a-zA-Z0-9]+}"); + + public String assignValues(String input) { + Matcher matcher = pattern.matcher(input); + while (matcher.find()) { + String placeholder = matcher.group(); + String placeholderName = placeholder.substring(1, placeholder.length() - 1); + for (ParameterPair pair : parameters) { + if (!pair.getParameter().isAnnotationPresent(Placeholder.class)) + continue; + + if (placeholderName.equals(pair.getParameter().getAnnotation(Placeholder.class).value())) { + input = input.replace(placeholder, String.valueOf(pair.getValue())); } - - return input; + } } + return input; + } + } diff --git a/core/src/main/java/me/zort/sqllib/mapping/ProxyInstanceImpl.java b/core/src/main/java/me/zort/sqllib/mapping/ProxyInstanceImpl.java index 7464733..a5a766a 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/ProxyInstanceImpl.java +++ b/core/src/main/java/me/zort/sqllib/mapping/ProxyInstanceImpl.java @@ -18,59 +18,66 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; +/** + * Proxy instance invocation handler and reference. + * This class is responsible for handling method invocations + * inside generated proxies and building schemas. + * + * @param Proxy type class + */ @Getter public class ProxyInstanceImpl implements MappingProxyInstance { - private final Class typeClass; - private final StatementMappingOptions options; - private final StatementMappingStrategy statementMapping; - private final StatementMappingResultAdapter mappingResultAdapter; + private final Class typeClass; + private final StatementMappingOptions options; + private final StatementMappingStrategy statementMapping; + private final StatementMappingResultAdapter mappingResultAdapter; - private final List pendingMethods = new CopyOnWriteArrayList<>(); + private final List pendingMethods = new CopyOnWriteArrayList<>(); - public ProxyInstanceImpl(Class typeClass, - StatementMappingOptions options, - StatementMappingStrategy statementMappingStrategy, - StatementMappingResultAdapter mappingResultAdapter) { - this.typeClass = typeClass; - this.options = options; - this.statementMapping = statementMappingStrategy; - this.mappingResultAdapter = mappingResultAdapter; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - // Allow invokation from interfaces or abstract classes only. - Class declaringClass = method.getDeclaringClass(); - if ((declaringClass.isInterface() || Modifier.isAbstract(declaringClass.getModifiers())) - && statementMapping.isMappingMethod(method)) { - // Prepare and execute query based on invoked method. - QueryResult result = statementMapping.executeQuery(options, method, args, mappingResultAdapter.retrieveResultType(method)); - // Adapt QueryResult to method return type. - return mappingResultAdapter.adaptResult(method, result); - } + public ProxyInstanceImpl(Class typeClass, + StatementMappingOptions options, + StatementMappingStrategy statementMappingStrategy, + StatementMappingResultAdapter mappingResultAdapter) { + this.typeClass = typeClass; + this.options = options; + this.statementMapping = statementMappingStrategy; + this.mappingResultAdapter = mappingResultAdapter; + } - // Default methods are invoked normally. - if (declaringClass.isInterface() && method.isDefault()) { - return JVM.getJVM().invokeDefault(declaringClass, proxy, method, args); - } + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // Allow invokation from interfaces or abstract classes only. + Class declaringClass = method.getDeclaringClass(); + if ((declaringClass.isInterface() || Modifier.isAbstract(declaringClass.getModifiers())) + && statementMapping.isMappingMethod(method)) { + // Prepare and execute query based on invoked method. + QueryResult result = statementMapping.executeQuery(options, method, args, mappingResultAdapter.retrieveResultType(method)); + // Adapt QueryResult to method return type. + return mappingResultAdapter.adaptResult(method, result); + } - throw new UnsupportedOperationException("Method " + method.getName() + " is not supported by this mapping repository!"); + // Default methods are invoked normally. + if (declaringClass.isInterface() && method.isDefault()) { + return JVM.getJVM().invokeDefault(declaringClass, proxy, method, args); } - @Override - public List getTableSchemas(NamingStrategy namingStrategy, boolean sqLite) { - List> builtTypes = new ArrayList<>(); - List schemaList = new ArrayList<>(); - for (Method method : getTypeClass().getDeclaredMethods()) { - Class resultType = mappingResultAdapter.retrieveResultType(method); + throw new UnsupportedOperationException("Method " + method.getName() + " is not supported by this mapping repository!"); + } + + @Override + public List getTableSchemas(NamingStrategy namingStrategy, boolean sqLite) { + List> builtTypes = new ArrayList<>(); + List schemaList = new ArrayList<>(); + for (Method method : getTypeClass().getDeclaredMethods()) { + Class resultType = mappingResultAdapter.retrieveResultType(method); - if (!QueryResult.class.isAssignableFrom(resultType) && statementMapping.isMappingMethod(method) && !builtTypes.contains(resultType)) { - String table = options.getTable() != null ? options.getTable() : Table.Util.getFromContext(method, null); - schemaList.add(new EntitySchemaBuilder(table, resultType, namingStrategy, sqLite).buildTableSchema()); - builtTypes.add(resultType); - } - } - return schemaList; + if (!QueryResult.class.isAssignableFrom(resultType) && statementMapping.isMappingMethod(method) && !builtTypes.contains(resultType)) { + String table = options.getTable() != null ? options.getTable() : Table.Util.getFromContext(method, null); + schemaList.add(new EntitySchemaBuilder(table, resultType, namingStrategy, sqLite).buildTableSchema()); + builtTypes.add(resultType); + } } + return schemaList; + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/QueryAnnotation.java b/core/src/main/java/me/zort/sqllib/mapping/QueryAnnotation.java index 06bf146..09a7e89 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/QueryAnnotation.java +++ b/core/src/main/java/me/zort/sqllib/mapping/QueryAnnotation.java @@ -30,60 +30,60 @@ @Getter public class QueryAnnotation { - private final boolean producesResult; - @SuppressWarnings("rawtypes") - private final QueryBuilder queryBuilder; + private final boolean producesResult; + @SuppressWarnings("rawtypes") + private final QueryBuilder queryBuilder; - private static final Map, QueryAnnotation> QUERY_ANNOT = new ConcurrentHashMap<>(); + private static final Map, QueryAnnotation> QUERY_ANNOT = new ConcurrentHashMap<>(); - static { - QUERY_ANNOT.put(Select.class, new QueryAnnotation(true, new SelectQueryBuilder())); - QUERY_ANNOT.put(Delete.class, new QueryAnnotation(false, new DeleteQueryBuilder())); - QUERY_ANNOT.put(Save.class, new QueryAnnotation(false, new SaveQueryBuilder())); - QUERY_ANNOT.put(Insert.class, new QueryAnnotation(false, new InsertQueryBuilder())); - QUERY_ANNOT.put(Query.class, new QueryAnnotation(true, new NativeQueryBuilder())); - QUERY_ANNOT.put(Exec.class, new QueryAnnotation(false, new NativeQueryBuilder())); - } + static { + QUERY_ANNOT.put(Select.class, new QueryAnnotation(true, new SelectQueryBuilder())); + QUERY_ANNOT.put(Delete.class, new QueryAnnotation(false, new DeleteQueryBuilder())); + QUERY_ANNOT.put(Save.class, new QueryAnnotation(false, new SaveQueryBuilder())); + QUERY_ANNOT.put(Insert.class, new QueryAnnotation(false, new InsertQueryBuilder())); + QUERY_ANNOT.put(Query.class, new QueryAnnotation(true, new NativeQueryBuilder())); + QUERY_ANNOT.put(Exec.class, new QueryAnnotation(false, new NativeQueryBuilder())); + } - public static void register(Class annotation, boolean producesResult, QueryBuilder builder) { - QUERY_ANNOT.put(annotation, new QueryAnnotation(producesResult, builder)); - } + public static void register(Class annotation, boolean producesResult, QueryBuilder builder) { + QUERY_ANNOT.put(annotation, new QueryAnnotation(producesResult, builder)); + } - @Nullable - public static QueryAnnotation wrap(Annotation annotation) { - if (annotation == null) return null; - return isQueryAnnotation(annotation) ? QUERY_ANNOT.get(annotation.annotationType()) : null; - } + @Nullable + public static QueryAnnotation wrap(Annotation annotation) { + if (annotation == null) return null; + return isQueryAnnotation(annotation) ? QUERY_ANNOT.get(annotation.annotationType()) : null; + } - public static boolean isQueryAnnotation(Annotation annotation) { - return isQueryAnnotation(annotation.annotationType()); - } + public static boolean isQueryAnnotation(Annotation annotation) { + return isQueryAnnotation(annotation.annotationType()); + } - public static boolean isQueryAnnotation(Class annotation) { - return QUERY_ANNOT.containsKey(annotation); - } + public static boolean isQueryAnnotation(Class annotation) { + return QUERY_ANNOT.containsKey(annotation); + } - /** - * Interface that is used for building query in mapping proxy based on - * method annotations and parameters, to be executed by {@link DefaultStatementMapping}. - */ - public interface QueryBuilder { + /** + * Interface that is used for building query in mapping proxy based on + * method annotations and parameters, to be executed by {@link DefaultStatementMapping}. + */ + public interface QueryBuilder { - QueryNode build(DefaultMappingDetails details, T queryAnnotation, Method method, ParameterPair[] parameters); - } + QueryNode build(DefaultMappingDetails details, T queryAnnotation, Method method, ParameterPair[] parameters); + } - @AllArgsConstructor - @Getter - public static class DefaultMappingDetails { - private final SQLConnection connection; - private final StatementMappingOptions options; - } + @AllArgsConstructor + @Getter + public static class DefaultMappingDetails { + private final SQLConnection connection; + private final StatementMappingOptions options; + } - public static class Validator { - public static void requireWhereDefinition(Method method) { - if (!method.isAnnotationPresent(Where.class)) - throw new SQLMappingException("Method " + method.getName() + " requires @Where annotation", method, null); - } + public static class Validator { + public static void requireWhereDefinition(Method method) { + if (!method.isAnnotationPresent(Where.class)) + throw new SQLMappingException("Method " + method.getName() + " requires @Where annotation", method, null); } + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Append.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Append.java index d93eab4..72f9fa3 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Append.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Append.java @@ -9,6 +9,6 @@ @Target(ElementType.METHOD) public @interface Append { - String value(); + String value(); } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Exec.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Exec.java index ec3e57d..a2fccde 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Exec.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Exec.java @@ -9,7 +9,8 @@ @Target(ElementType.METHOD) public @interface Exec { // Does not produce result - String value(); - String[] params() default {}; + String value(); + + String[] params() default {}; } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Insert.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Insert.java index 69fc910..0bf9be2 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Insert.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Insert.java @@ -9,7 +9,8 @@ @Target(ElementType.METHOD) public @interface Insert { - String[] cols(); - String[] vals(); + String[] cols(); + + String[] vals(); } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Limit.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Limit.java index 9d9dd43..5d0e63c 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Limit.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Limit.java @@ -11,12 +11,12 @@ @Target(ElementType.METHOD) public @interface Limit { - int value(); + int value(); - class Builder { - public static > T build(T parent, Limit annotation) { - return (T) parent.limit(annotation.value()); - } + class Builder { + public static > T build(T parent, Limit annotation) { + return (T) parent.limit(annotation.value()); } + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Placeholder.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Placeholder.java index 883b53f..9390a3b 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Placeholder.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Placeholder.java @@ -15,7 +15,7 @@ @Target(ElementType.PARAMETER) public @interface Placeholder { - // The placeholder, without brackets - String value(); + // The placeholder, without brackets + String value(); } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Query.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Query.java index 6b00f61..f012810 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Query.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Query.java @@ -9,7 +9,8 @@ @Target(ElementType.METHOD) public @interface Query { // Produces result - String value(); - String[] params() default {}; + String value(); + + String[] params() default {}; } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Select.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Select.java index 9c9b763..73fd9ba 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Select.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Select.java @@ -8,5 +8,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Select { - String value() default "*"; + String value() default "*"; } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Table.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Table.java index a686fd4..e2b3b31 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Table.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Table.java @@ -15,19 +15,19 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface Table { - String value(); + String value(); - class Util { - @Nullable - public static String getFromContext(Method method, @Nullable ParameterPair[] parameters) { - PlaceholderMapper mapper = new PlaceholderMapper(parameters != null ? parameters : new ParameterPair[0]); - if (method.isAnnotationPresent(Table.class)) { - return mapper.assignValues(method.getAnnotation(Table.class).value()); - } else if(method.getDeclaringClass().isAnnotationPresent(Table.class)) { - return mapper.assignValues(method.getDeclaringClass().getAnnotation(Table.class).value()); - } else { - throw new SQLMappingException("Method " + method.getName() + " in class " + method.getDeclaringClass().getSimpleName() + " requires @Table annotation", method, null); - } - } + class Util { + @Nullable + public static String getFromContext(Method method, @Nullable ParameterPair[] parameters) { + PlaceholderMapper mapper = new PlaceholderMapper(parameters != null ? parameters : new ParameterPair[0]); + if (method.isAnnotationPresent(Table.class)) { + return mapper.assignValues(method.getAnnotation(Table.class).value()); + } else if (method.getDeclaringClass().isAnnotationPresent(Table.class)) { + return mapper.assignValues(method.getDeclaringClass().getAnnotation(Table.class).value()); + } else { + throw new SQLMappingException("Method " + method.getName() + " in class " + method.getDeclaringClass().getSimpleName() + " requires @Table annotation", method, null); + } } + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/annotation/Where.java b/core/src/main/java/me/zort/sqllib/mapping/annotation/Where.java index b6a1abb..5bc18ff 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/annotation/Where.java +++ b/core/src/main/java/me/zort/sqllib/mapping/annotation/Where.java @@ -14,45 +14,47 @@ @Target(ElementType.METHOD) public @interface Where { - Condition[] value(); // And + Condition[] value(); // And - @interface Condition { + @interface Condition { - String column(); - String value(); - Type type() default Type.EQUALS; + String column(); - enum Type { - EQUALS, BT, LT - } - } + String value(); - class Builder { - public static WhereStatement build(Conditional parent, Where annotation, PlaceholderMapper mapper) { - WhereStatement where = parent.where(); - for (Condition condition : annotation.value()) { - String value = mapper.assignValues(condition.value()); - - switch (condition.type()) { - case EQUALS: - where.isEqual(condition.column(), value); - break; - case BT: - case LT: - try { - int number = Integer.parseInt(value); - if (condition.type().equals(Condition.Type.BT)) { - where.bt(condition.column(), number); - } else { - where.lt(condition.column(), number); - } - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Value of current @Where.Condition must be a number! (" + value + ")"); - } - break; - } + Type type() default Type.EQUALS; + + enum Type { + EQUALS, BT, LT + } + } + + class Builder { + public static WhereStatement build(Conditional parent, Where annotation, PlaceholderMapper mapper) { + WhereStatement where = parent.where(); + for (Condition condition : annotation.value()) { + String value = mapper.assignValues(condition.value()); + + switch (condition.type()) { + case EQUALS: + where.isEqual(condition.column(), value); + break; + case BT: + case LT: + try { + int number = Integer.parseInt(value); + if (condition.type().equals(Condition.Type.BT)) { + where.bt(condition.column(), number); + } else { + where.lt(condition.column(), number); + } + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Value of current @Where.Condition must be a number! (" + value + ")"); } - return where; + break; } + } + return where; } + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/builder/DeleteQueryBuilder.java b/core/src/main/java/me/zort/sqllib/mapping/builder/DeleteQueryBuilder.java index 22bf748..bbca2e9 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/builder/DeleteQueryBuilder.java +++ b/core/src/main/java/me/zort/sqllib/mapping/builder/DeleteQueryBuilder.java @@ -15,21 +15,21 @@ import java.lang.reflect.Method; public class DeleteQueryBuilder implements QueryAnnotation.QueryBuilder { - @Override - public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Delete queryAnnotation, Method method, ParameterPair[] parameters) { - PlaceholderMapper placeholderMapper = new PlaceholderMapper(parameters); - String table = details.getOptions().getTable(); - if (table == null) table = Table.Util.getFromContext(method, parameters); + @Override + public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Delete queryAnnotation, Method method, ParameterPair[] parameters) { + PlaceholderMapper placeholderMapper = new PlaceholderMapper(parameters); + String table = details.getOptions().getTable(); + if (table == null) table = Table.Util.getFromContext(method, parameters); - QueryNode node = new DeleteQuery(null, table); - if (method.isAnnotationPresent(Where.class)) { - node = Where.Builder.build((Conditional) node, method.getAnnotation(Where.class), placeholderMapper); - node = node.getAncestor(); - } - if (method.isAnnotationPresent(Limit.class)) { - node = (QueryNode) Limit.Builder.build((Limitable) node, method.getAnnotation(Limit.class)); - node = node.getAncestor(); - } - return node; + QueryNode node = new DeleteQuery(null, table); + if (method.isAnnotationPresent(Where.class)) { + node = Where.Builder.build((Conditional) node, method.getAnnotation(Where.class), placeholderMapper); + node = node.getAncestor(); } + if (method.isAnnotationPresent(Limit.class)) { + node = (QueryNode) Limit.Builder.build((Limitable) node, method.getAnnotation(Limit.class)); + node = node.getAncestor(); + } + return node; + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/builder/InsertQueryBuilder.java b/core/src/main/java/me/zort/sqllib/mapping/builder/InsertQueryBuilder.java index a92cfac..5185b90 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/builder/InsertQueryBuilder.java +++ b/core/src/main/java/me/zort/sqllib/mapping/builder/InsertQueryBuilder.java @@ -13,25 +13,25 @@ import java.lang.reflect.Method; public class InsertQueryBuilder implements QueryAnnotation.QueryBuilder { - @Override - public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Insert queryAnnotation, Method method, ParameterPair[] parameters) { - SQLConnection connection = details.getConnection(); - if (!(connection instanceof SQLDatabaseConnection)) - throw new IllegalArgumentException("The connection must be a SQLDatabaseConnection"); + @Override + public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Insert queryAnnotation, Method method, ParameterPair[] parameters) { + SQLConnection connection = details.getConnection(); + if (!(connection instanceof SQLDatabaseConnection)) + throw new IllegalArgumentException("The connection must be a SQLDatabaseConnection"); - String table = details.getOptions().getTable(); - if (table == null) table = Table.Util.getFromContext(method, parameters); - InsertQuery query = ((SQLDatabaseConnection) connection).insert(); - query.into(table, queryAnnotation.cols()); + String table = details.getOptions().getTable(); + if (table == null) table = Table.Util.getFromContext(method, parameters); + InsertQuery query = ((SQLDatabaseConnection) connection).insert(); + query.into(table, queryAnnotation.cols()); - PlaceholderMapper mapper = new PlaceholderMapper(parameters); + PlaceholderMapper mapper = new PlaceholderMapper(parameters); - String[] vals = queryAnnotation.vals(); - for (int i = 0; i < vals.length; i++) { - vals[i] = mapper.assignValues(vals[i]); - } - - query.values((Object[]) vals); - return query; + String[] vals = queryAnnotation.vals(); + for (int i = 0; i < vals.length; i++) { + vals[i] = mapper.assignValues(vals[i]); } + + query.values((Object[]) vals); + return query; + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/builder/NativeQueryBuilder.java b/core/src/main/java/me/zort/sqllib/mapping/builder/NativeQueryBuilder.java index 3ae17e2..5f9eef8 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/builder/NativeQueryBuilder.java +++ b/core/src/main/java/me/zort/sqllib/mapping/builder/NativeQueryBuilder.java @@ -6,6 +6,7 @@ import me.zort.sqllib.internal.query.QueryDetails; import me.zort.sqllib.internal.query.QueryNode; import me.zort.sqllib.internal.query.QueryPriority; +import me.zort.sqllib.internal.query.ResultSetAware; import me.zort.sqllib.mapping.PlaceholderMapper; import me.zort.sqllib.mapping.QueryAnnotation; import me.zort.sqllib.mapping.annotation.Exec; @@ -17,60 +18,77 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; public class NativeQueryBuilder implements QueryAnnotation.QueryBuilder { - @Override - public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Annotation queryAnnotation, Method method, ParameterPair[] parameters) { - SQLConnection connection = details.getConnection(); - PlaceholderMapper mapper = new PlaceholderMapper(parameters); - return new LocalQueryNodeExecutive(connection) { - private int currPhIndex = 0; - @Override - public QueryDetails buildQueryDetails() { - String annotValue; - String[] annotParams; + @Override + public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Annotation queryAnnotation, Method method, ParameterPair[] parameters) { + SQLConnection connection = details.getConnection(); + PlaceholderMapper mapper = new PlaceholderMapper(parameters); + AtomicInteger currPhIndex = new AtomicInteger(0); + Supplier nextPlaceholder = () -> "nq_" + currPhIndex.getAndIncrement(); + return buildNodeImpl(queryAnnotation, connection, () -> { + String annotValue; + String[] annotParams; - if (queryAnnotation instanceof Query) { - annotValue = ((Query) queryAnnotation).value(); - annotParams = ((Query) queryAnnotation).params(); - } else if(queryAnnotation instanceof Exec) { - annotValue = ((Exec) queryAnnotation).value(); - annotParams = ((Exec) queryAnnotation).params(); - } else { - throw new IllegalArgumentException(String.format("NativeQueryBuilder does not support %s annotation!", queryAnnotation.getClass().getName())); - } + if (queryAnnotation instanceof Query) { + annotValue = ((Query) queryAnnotation).value(); + annotParams = ((Query) queryAnnotation).params(); + } else if (queryAnnotation instanceof Exec) { + annotValue = ((Exec) queryAnnotation).value(); + annotParams = ((Exec) queryAnnotation).params(); + } else { + throw new IllegalArgumentException(String.format("NativeQueryBuilder does not support %s annotation!", queryAnnotation.getClass().getName())); + } - annotValue = mapper.assignValues(annotValue); + annotValue = mapper.assignValues(annotValue); - Map params = new HashMap<>(); - for (String param : annotParams) { - param = mapper.assignValues(param); - int index = annotValue.indexOf("?"); - if (index == -1) - break; + Map params = new HashMap<>(); + for (String param : annotParams) { + param = mapper.assignValues(param); + int index = annotValue.indexOf("?"); + if (index == -1) + break; - String placeholder = nextPlaceholder(); - annotValue = annotValue.replaceFirst("\\?", "<" + placeholder + ">"); - params.put(placeholder, param); - } - return new QueryDetails(annotValue, params); - } + String placeholder = nextPlaceholder.get(); + annotValue = annotValue.replaceFirst("\\?", "<" + placeholder + ">"); + params.put(placeholder, param); + } + return new QueryDetails(annotValue, params); + }); + } - private String nextPlaceholder() { - return "nq_" + currPhIndex++; - } - }; - } + private static QueryNode buildNodeImpl(Annotation queryAnnotation, SQLConnection connection, Supplier detailsSupplier) { + if (queryAnnotation instanceof Exec) return new NodeExecutiveImpl(connection) { + @Override + public QueryDetails buildQueryDetails() { + return detailsSupplier.get(); + } + }; + else if (queryAnnotation instanceof Query) return new NodeExecutiveImplRS(connection) { + @Override + public QueryDetails buildQueryDetails() { + return detailsSupplier.get(); + } + }; + throw new IllegalArgumentException(); + } - private static abstract class LocalQueryNodeExecutive extends QueryNode> implements Executive { + private static abstract class NodeExecutiveImpl extends QueryNode> implements Executive { + @Getter + private final SQLConnection connection; - @Getter - private final SQLConnection connection; + public NodeExecutiveImpl(SQLConnection connection) { + super(null, new ArrayList<>(), QueryPriority.GENERAL); + this.connection = connection; + } + } - public LocalQueryNodeExecutive(SQLConnection connection) { - super(null, new ArrayList<>(), QueryPriority.GENERAL); - this.connection = connection; - } + private static abstract class NodeExecutiveImplRS extends NodeExecutiveImpl implements ResultSetAware { + public NodeExecutiveImplRS(SQLConnection connection) { + super(connection); } + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/builder/SaveQueryBuilder.java b/core/src/main/java/me/zort/sqllib/mapping/builder/SaveQueryBuilder.java index e5dc918..138c19a 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/builder/SaveQueryBuilder.java +++ b/core/src/main/java/me/zort/sqllib/mapping/builder/SaveQueryBuilder.java @@ -13,32 +13,32 @@ import java.lang.reflect.Method; public class SaveQueryBuilder implements QueryAnnotation.QueryBuilder { - @Override - public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Save queryAnnotation, Method method, ParameterPair[] parameters) { - SQLConnection connection = details.getConnection(); - if (!(connection instanceof SQLDatabaseConnectionImpl)) - throw new IllegalArgumentException("The connection must be an instance of SQLDatabaseConnectionImpl"); + @Override + public QueryNode build(QueryAnnotation.DefaultMappingDetails details, Save queryAnnotation, Method method, ParameterPair[] parameters) { + SQLConnection connection = details.getConnection(); + if (!(connection instanceof SQLDatabaseConnectionImpl)) + throw new IllegalArgumentException("The connection must be an instance of SQLDatabaseConnectionImpl"); - String table = details.getOptions().getTable(); - if (table == null) table = Table.Util.getFromContext(method, parameters); + String table = details.getOptions().getTable(); + if (table == null) table = Table.Util.getFromContext(method, parameters); - Object saveableObject = getSaveableObject(parameters); + Object saveableObject = getSaveableObject(parameters); - UpsertQuery query = ((SQLDatabaseConnectionImpl) connection).save(saveableObject); - query.table(table); - query.setAssignedSaveObject(saveableObject); + UpsertQuery query = ((SQLDatabaseConnectionImpl) connection).save(saveableObject); + query.table(table); + query.setAssignedSaveObject(saveableObject); - return query; - } - - private static Object getSaveableObject(ParameterPair[] parameters) { - for (ParameterPair parameter : parameters) { - if (parameter.getValue() == null) continue; + return query; + } - Class aClass = parameter.getValue().getClass(); - if (!Primitives.isWrapperType(Primitives.wrap(aClass))) return parameter.getValue(); - } + private static Object getSaveableObject(ParameterPair[] parameters) { + for (ParameterPair parameter : parameters) { + if (parameter.getValue() == null) continue; - throw new IllegalArgumentException("No object to save found in paramaters!"); + Class aClass = parameter.getValue().getClass(); + if (!Primitives.isWrapperType(Primitives.wrap(aClass))) return parameter.getValue(); } + + throw new IllegalArgumentException("No object to save found in paramaters!"); + } } diff --git a/core/src/main/java/me/zort/sqllib/mapping/builder/SelectQueryBuilder.java b/core/src/main/java/me/zort/sqllib/mapping/builder/SelectQueryBuilder.java index da9ef3c..1ee2c0c 100644 --- a/core/src/main/java/me/zort/sqllib/mapping/builder/SelectQueryBuilder.java +++ b/core/src/main/java/me/zort/sqllib/mapping/builder/SelectQueryBuilder.java @@ -17,22 +17,22 @@ import java.util.Arrays; public class SelectQueryBuilder implements QueryAnnotation.QueryBuilder